mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-19 20:37:20 +00:00
Compare commits
364 Commits
v14.4.1
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
![]() |
015fa1da89 | ||
![]() |
a11e269ca0 | ||
![]() |
2831bbfd18 | ||
![]() |
92b3f7d37c | ||
![]() |
a2d1915692 | ||
![]() |
082170374c | ||
![]() |
c2628c95f3 | ||
![]() |
2bc5f682b0 | ||
![]() |
cea46bb660 | ||
![]() |
b67231483a | ||
![]() |
e6918d8b9c | ||
![]() |
7ea95ec6b2 | ||
![]() |
8921a42f79 | ||
![]() |
c8181e3290 | ||
![]() |
117e503aaa | ||
![]() |
3baa110f9d | ||
![]() |
a4096ab049 | ||
![]() |
83118b9e05 | ||
![]() |
3a28938b91 | ||
![]() |
68f019cf43 | ||
![]() |
4707cc068f | ||
![]() |
0604fac3bc | ||
![]() |
c12974366b | ||
![]() |
cced48d824 | ||
![]() |
1a8903578f | ||
![]() |
230ce2c539 | ||
![]() |
6b7606c958 | ||
![]() |
cfe1cee4d3 | ||
![]() |
2999eed8b9 | ||
![]() |
3f82228905 | ||
![]() |
7ddf8abf90 | ||
![]() |
215b37bf69 | ||
![]() |
342bb2cb7b | ||
![]() |
2096411be6 | ||
![]() |
929582b1af | ||
![]() |
4ed48feaa2 | ||
![]() |
c121dbcd4a | ||
![]() |
e8baea464f | ||
![]() |
2bf67b96a6 | ||
![]() |
0cb6a8ba24 | ||
![]() |
39494f1287 | ||
![]() |
90c690e67a | ||
![]() |
08f20b9404 | ||
![]() |
dfabe8cc0f | ||
![]() |
b43d360d37 | ||
![]() |
2f7793ddcf | ||
![]() |
3c70b728ac | ||
![]() |
289120ee92 | ||
![]() |
b77b622fbe | ||
![]() |
a47e6f1496 | ||
![]() |
74757ee7da | ||
![]() |
ea2baee3b8 | ||
![]() |
f4bb9d98b6 | ||
![]() |
87b95f798a | ||
![]() |
da4dc56b16 | ||
![]() |
714ad233e0 | ||
![]() |
2da631e442 | ||
![]() |
6f47f23f7a | ||
![]() |
69fca99ac1 | ||
![]() |
a3b564f4f3 | ||
![]() |
52f3306f15 | ||
![]() |
9d6640a42e | ||
![]() |
307e1d9c29 | ||
![]() |
f71ca3e0a2 | ||
![]() |
a3d86eebf0 | ||
![]() |
f331a64ac3 | ||
![]() |
caac9f1257 | ||
![]() |
b47a1bc1e2 | ||
![]() |
9e3ad52356 | ||
![]() |
38ceafe789 | ||
![]() |
ddc1439edf | ||
![]() |
3827bca3cc | ||
![]() |
8183a9ed3b | ||
![]() |
00e2d1d430 | ||
![]() |
863c6d1214 | ||
![]() |
73cace5274 | ||
![]() |
1ada6da6b8 | ||
![]() |
fbb752d8c2 | ||
![]() |
fb6640b91f | ||
![]() |
c0d15de965 | ||
![]() |
3764e88ed2 | ||
![]() |
0ea1f8e632 | ||
![]() |
234c5ea170 | ||
![]() |
ce92723c41 | ||
![]() |
e1f7ee26fa | ||
![]() |
a97d306a16 | ||
![]() |
508992258f | ||
![]() |
1b51aef911 | ||
![]() |
6486ba3b26 | ||
![]() |
9b4eb64caa | ||
![]() |
6d376a079e | ||
![]() |
69c3863b14 | ||
![]() |
ac8236abe1 | ||
![]() |
16e9d105ba | ||
![]() |
f3ae3bec4b | ||
![]() |
cae4551762 | ||
![]() |
007608914c | ||
![]() |
758ba17dde | ||
![]() |
08fae4bcd6 | ||
![]() |
f305113d6d | ||
![]() |
7b8d2fe93d | ||
![]() |
714435be1c | ||
![]() |
e3eb47078f | ||
![]() |
a0c8ac4f80 | ||
![]() |
c926b4b3a6 | ||
![]() |
3f93d2deee | ||
![]() |
06aa356bc3 | ||
![]() |
58632d67db | ||
![]() |
e26a2cdac9 | ||
![]() |
72535db185 | ||
![]() |
f2bf8b96e7 | ||
![]() |
549ca6e32f | ||
![]() |
72520e0743 | ||
![]() |
aed82dc8b2 | ||
![]() |
2e35a2ab93 | ||
![]() |
3c171c1ed8 | ||
![]() |
481f2cd8e1 | ||
![]() |
9a98db9773 | ||
![]() |
e92e411040 | ||
![]() |
aecba92da4 | ||
![]() |
4ee4b5908f | ||
![]() |
3f74bc83e5 | ||
![]() |
fd0501035d | ||
![]() |
670fab7ead | ||
![]() |
375864b23b | ||
![]() |
788ac574ac | ||
![]() |
5aa7d08c91 | ||
![]() |
b4c61325cb | ||
![]() |
d10eafc500 | ||
![]() |
90ebff552d | ||
![]() |
0c26698ba6 | ||
![]() |
1db796c40f | ||
![]() |
b8459eb685 | ||
![]() |
b1f3d6268d | ||
![]() |
7a4d8a5fb1 | ||
![]() |
0ab5548615 | ||
![]() |
1af1057e66 | ||
![]() |
039960153a | ||
![]() |
b4c1cd654f | ||
![]() |
c6b975561f | ||
![]() |
4306823ba6 | ||
![]() |
9b258cadcf | ||
![]() |
871723b6f7 | ||
![]() |
3c66ace01b | ||
![]() |
41af475cdb | ||
![]() |
3c5f22b31f | ||
![]() |
cb333a5a38 | ||
![]() |
c39a7d924a | ||
![]() |
f07af885a9 | ||
![]() |
f1be1b8ba9 | ||
![]() |
cfc11b5e83 | ||
![]() |
a939b4973e | ||
![]() |
d805cef66e | ||
![]() |
64ec55db4e | ||
![]() |
a2af12c969 | ||
![]() |
f383c877c6 | ||
![]() |
cc14f721f9 | ||
![]() |
ccf8902515 | ||
![]() |
f3dc35e9ca | ||
![]() |
0b3be314e7 | ||
![]() |
a9150dc703 | ||
![]() |
c076331fad | ||
![]() |
8621b9adf4 | ||
![]() |
bc7a1f5dbc | ||
![]() |
3ef9fe9f6e | ||
![]() |
1910aba79f | ||
![]() |
dbcfe486af | ||
![]() |
214b392839 | ||
![]() |
b9bc3580f4 | ||
![]() |
b07bd68046 | ||
![]() |
7a97a8fa98 | ||
![]() |
1b2fc5eccc | ||
![]() |
e7f5ecc2d0 | ||
![]() |
ff5b4956c8 | ||
![]() |
5a6b219971 | ||
![]() |
99cbdf687d | ||
![]() |
57e4d18d26 | ||
![]() |
d4a8952c34 | ||
![]() |
28b22de7e4 | ||
![]() |
f65646ba80 | ||
![]() |
f014299adc | ||
![]() |
af4ec3e0d0 | ||
![]() |
f1e5b576ba | ||
![]() |
c4dd9839c9 | ||
![]() |
db96993e50 | ||
![]() |
35a27d4541 | ||
![]() |
f727013373 | ||
![]() |
d54dfa6bc4 | ||
![]() |
a07973e866 | ||
![]() |
23ae0db9a8 | ||
![]() |
89b1df6a81 | ||
![]() |
117c1f68b7 | ||
![]() |
1988cd620d | ||
![]() |
470065e36b | ||
![]() |
d94e680b51 | ||
![]() |
c7d4a2a104 | ||
![]() |
8bf10f0b9a | ||
![]() |
ed52e711a9 | ||
![]() |
6ffb783321 | ||
![]() |
c4d2f010ef | ||
![]() |
1c0327e2c1 | ||
![]() |
63845ad3e8 | ||
![]() |
268a7267ac | ||
![]() |
a9c39fe098 | ||
![]() |
ea584f60c8 | ||
![]() |
2c0172d7d5 | ||
![]() |
94e2a91bbd | ||
![]() |
dcc407889a | ||
![]() |
97cf0a4baa | ||
![]() |
6421d6b1ab | ||
![]() |
b02ac268ad | ||
![]() |
2ac886a7f8 | ||
![]() |
8f641238b6 | ||
![]() |
2c8c5ae6b9 | ||
![]() |
892e29f599 | ||
![]() |
a9996ecc40 | ||
![]() |
9be9bb8af3 | ||
![]() |
518df07ba1 | ||
![]() |
c9cd6aae1d | ||
![]() |
ab9ad562cb | ||
![]() |
0b95779947 | ||
![]() |
0ba224bf9a | ||
![]() |
427db230fc | ||
![]() |
670d7bd8eb | ||
![]() |
cba8723c59 | ||
![]() |
c773a95ff7 | ||
![]() |
35e2d43191 | ||
![]() |
8a0e2d0604 | ||
![]() |
66a1f04414 | ||
![]() |
0c898b8d75 | ||
![]() |
299f983610 | ||
![]() |
aaa49f84ab | ||
![]() |
def7ede895 | ||
![]() |
e8ca96008f | ||
![]() |
943a0b1e6c | ||
![]() |
0bc319acb5 | ||
![]() |
d72ec454c0 | ||
![]() |
0288157fdb | ||
![]() |
7dd6b999ca | ||
![]() |
34b173e953 | ||
![]() |
9d963ce599 | ||
![]() |
f4bc628940 | ||
![]() |
0dcd38186f | ||
![]() |
9bb7b7913a | ||
![]() |
60570dec76 | ||
![]() |
95e93b8f33 | ||
![]() |
9613004bb4 | ||
![]() |
b167955e87 | ||
![]() |
18d99daa72 | ||
![]() |
4d9dd0aa3f | ||
![]() |
53dee5b002 | ||
![]() |
1065db5831 | ||
![]() |
0471f0f3c5 | ||
![]() |
beb967ccd4 | ||
![]() |
a91771e0cf | ||
![]() |
5cbe5fe9e4 | ||
![]() |
b253b344c2 | ||
![]() |
fa4f2123cf | ||
![]() |
9f3f234ac9 | ||
![]() |
4b69d30a5f | ||
![]() |
cd0743c6ed | ||
![]() |
ed1c6e2d9e | ||
![]() |
a7ee6054b5 | ||
![]() |
a49e924b53 | ||
![]() |
ebbef97cde | ||
![]() |
3068a48d90 | ||
![]() |
5ac1fdb8fe | ||
![]() |
866ffc8967 | ||
![]() |
3efdfae845 | ||
![]() |
6d7aab4662 | ||
![]() |
ec8cf6e2f0 | ||
![]() |
d176a1d65b | ||
![]() |
ddcdc85520 | ||
![]() |
fc8485d91b | ||
![]() |
e5e4c336b5 | ||
![]() |
6b3719bd9e | ||
![]() |
d0ef026bb9 | ||
![]() |
03e8497211 | ||
![]() |
cf739e9522 | ||
![]() |
e299035266 | ||
![]() |
83b09f4de1 | ||
![]() |
3365fd0d0b | ||
![]() |
ed21cfd487 | ||
![]() |
f42cb555c3 | ||
![]() |
e57b3e8b05 | ||
![]() |
76fb95b166 | ||
![]() |
d6ce776c98 | ||
![]() |
dce79fd0c3 | ||
![]() |
d3da193e39 | ||
![]() |
b73f50be6b | ||
![]() |
1fc6f5c707 | ||
![]() |
fe2f4d031f | ||
![]() |
b472e821cf | ||
![]() |
17ab5a5e83 | ||
![]() |
2263305bee | ||
![]() |
0d0b9de474 | ||
![]() |
77d98868bf | ||
![]() |
a5610eea09 | ||
![]() |
bd7e47139c | ||
![]() |
c084719b0e | ||
![]() |
124f55ca70 | ||
![]() |
50f0f8a651 | ||
![]() |
64a2fe8aee | ||
![]() |
ed7b58291a | ||
![]() |
aafe528682 | ||
![]() |
d5d757fd3d | ||
![]() |
b5c326d772 | ||
![]() |
884e795dff | ||
![]() |
8fa33ff4da | ||
![]() |
a2752bf500 | ||
![]() |
01154e9497 | ||
![]() |
1a482364bc | ||
![]() |
5f95b33220 | ||
![]() |
dc531de02b | ||
![]() |
a1aef6b39f | ||
![]() |
02225ea7c4 | ||
![]() |
2d2c732e2e | ||
![]() |
9fb8065fac | ||
![]() |
1ad89ccb3e | ||
![]() |
de3a7f3909 | ||
![]() |
17924392fa | ||
![]() |
f4d0606d06 | ||
![]() |
6d5a33772c | ||
![]() |
d1a7d70ca0 | ||
![]() |
7f8f61423a | ||
![]() |
b729886a16 | ||
![]() |
4d3a780eb1 | ||
![]() |
64f0acb0c5 | ||
![]() |
2143082aa4 | ||
![]() |
1d244fcd28 | ||
![]() |
02ae53cec5 | ||
![]() |
94f3744235 | ||
![]() |
8a37df10c6 | ||
![]() |
2024bf88ac | ||
![]() |
fc3ad45836 | ||
![]() |
4fd3d9465c | ||
![]() |
3412761881 | ||
![]() |
3457d66d1e | ||
![]() |
3b48a1c16a | ||
![]() |
27e85809b5 | ||
![]() |
f3fcbea6d1 | ||
![]() |
f59c1675eb | ||
![]() |
6745bc1b48 | ||
![]() |
9f3c7859d7 | ||
![]() |
52d4e84b39 | ||
![]() |
8311bff7ee | ||
![]() |
fde529fac4 | ||
![]() |
af724a6149 | ||
![]() |
0d9ce6de12 | ||
![]() |
df79533611 | ||
![]() |
e4ff66192f | ||
![]() |
9b6dc1f0f1 | ||
![]() |
2d3a049e59 | ||
![]() |
b7da75da30 | ||
![]() |
db29cb7152 | ||
![]() |
97b375fd57 | ||
![]() |
2c3785c1c6 | ||
![]() |
69d3fc1003 | ||
![]() |
90e0595b7f | ||
![]() |
fba6a806ac | ||
![]() |
ef7b2404d4 | ||
![]() |
6468b6edcd | ||
![]() |
c40b707b76 | ||
![]() |
af3bb96a2a |
1
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/Bug_report.md
vendored
@ -32,6 +32,7 @@ _Make sure your have performed every step and checked the applicable boxes befor
|
||||
- [ ] Searched the problem in [discussions](https://github.com/arendst/Tasmota/discussions)
|
||||
- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/FAQ)
|
||||
- [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4)
|
||||
- [ ] Problem is not scripter related, in this case open a discussion and tag gemu2015
|
||||
- [ ] Device used (e.g., Sonoff Basic): _____
|
||||
- [ ] Tasmota binary firmware version number used: _____
|
||||
- [ ] Pre-compiled
|
||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -7,7 +7,7 @@
|
||||
- [ ] Only relevant files were touched
|
||||
- [ ] Only one feature/fix was added per PR and the code change compiles without warnings
|
||||
- [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.8
|
||||
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.0.241206
|
||||
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.3.250411
|
||||
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
|
||||
|
||||
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_
|
||||
|
99
.github/workflows/Tasmota_build_devel.yml
vendored
99
.github/workflows/Tasmota_build_devel.yml
vendored
@ -25,35 +25,31 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
#- name: Install clang compiler
|
||||
#run: |
|
||||
#sudo apt-get install -f clang
|
||||
- name: Make Berry and Tasmota Berry code
|
||||
|
||||
- name: Make Berry and Solidify code
|
||||
run: |
|
||||
cd lib/libesp32/berry
|
||||
make
|
||||
cd ../berry_tasmota
|
||||
../berry/berry -s -g solidify_all.be
|
||||
- name: Matter Berry Code
|
||||
run: |
|
||||
cd lib/libesp32/berry_matter
|
||||
cd ../berry_matter
|
||||
../berry/berry -s -g solidify_all.be
|
||||
- name: Berry Animate Code
|
||||
run: |
|
||||
cd lib/libesp32/berry_animate
|
||||
cd ../berry_animate
|
||||
../berry/berry -s -g solidify_all.be
|
||||
- name: LVGL Berry Code
|
||||
run: |
|
||||
cd lib/libesp32_lvgl/lv_binding_berry
|
||||
cd ../../libesp32_lvgl/lv_binding_berry
|
||||
../../libesp32/berry/berry -s -g solidify_all.be
|
||||
- name: HASPmota Berry Code
|
||||
run: |
|
||||
cd lib/libesp32_lvgl/lv_haspmota
|
||||
cd ../lv_haspmota
|
||||
../../libesp32/berry/berry -s -g solidify_all.be
|
||||
- uses: jason2866/upload-artifact@v2.0.3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: '["berry_tasmota", "berry_matter", "berry_animate", "berry_lvgl", "berry_haspmota", "berry_header"]'
|
||||
path: '["./lib/libesp32/berry_tasmota/src/solidify", "./lib/libesp32/berry_matter/src/solidify", "./lib/libesp32/berry_animate/src/solidify", "./lib/libesp32_lvgl/lv_binding_berry/src/solidify", "./lib/libesp32_lvgl/lv_haspmota/src/solidify", "./lib/libesp32/berry/generate"]'
|
||||
name: berry
|
||||
path: |
|
||||
./lib/libesp32/berry_tasmota/src/solidify
|
||||
./lib/libesp32/berry_matter/src/solidify
|
||||
./lib/libesp32/berry_animate/src/solidify
|
||||
./lib/libesp32_lvgl/lv_binding_berry/src/solidify
|
||||
./lib/libesp32_lvgl/lv_haspmota/src/solidify
|
||||
./lib/libesp32/berry/generate
|
||||
|
||||
push_solidified:
|
||||
needs: be_solidify
|
||||
@ -66,22 +62,19 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: jason2866/download-artifact@v3.0.4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: |
|
||||
berry_tasmota
|
||||
berry_matter
|
||||
berry_animate
|
||||
berry_lvgl
|
||||
berry_haspmota
|
||||
berry_header
|
||||
path: |
|
||||
./lib/libesp32/berry_tasmota/src/solidify
|
||||
./lib/libesp32/berry_matter/src/solidify
|
||||
./lib/libesp32/berry_animate/src/solidify
|
||||
./lib/libesp32_lvgl/lv_binding_berry/src/solidify
|
||||
./lib/libesp32_lvgl/lv_haspmota/src/solidify
|
||||
./lib/libesp32/berry/generate
|
||||
pattern: berry
|
||||
path: berry
|
||||
- name: Move solidified Berry files back
|
||||
run: |
|
||||
ls -R ./berry
|
||||
mv berry/berry/libesp32/berry_tasmota/src/solidify/* ./lib/libesp32/berry_tasmota/src/solidify
|
||||
mv berry/berry/libesp32/berry_matter/src/solidify/* ./lib/libesp32/berry_matter/src/solidify
|
||||
mv berry/berry/libesp32/berry_animate/src/solidify/* ./lib/libesp32/berry_animate/src/solidify
|
||||
mv berry/berry/libesp32_lvgl/lv_binding_berry/src/solidify/* ./lib/libesp32_lvgl/lv_binding_berry/src/solidify
|
||||
mv berry/berry/libesp32_lvgl/lv_haspmota/src/solidify/* ./lib/libesp32_lvgl/lv_haspmota/src/solidify
|
||||
mv berry/berry/libesp32/berry/generate/* ./lib/libesp32/berry/generate
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Solidified Code updated
|
||||
@ -129,9 +122,9 @@ jobs:
|
||||
#run: |
|
||||
#cp ./build_output/firmware/tasmota32solo1-safeboot.bin ./build_output/firmware/tasmota32-safeboot.bin
|
||||
- name: Upload safeboot firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
base-images:
|
||||
@ -172,9 +165,9 @@ jobs:
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
base32-images:
|
||||
@ -214,10 +207,14 @@ jobs:
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./firmware
|
||||
pattern: tasmota32*
|
||||
path: ./temp
|
||||
- name: Move safeboot files
|
||||
run: |
|
||||
mkdir -p ./firmware/firmware
|
||||
find ./temp -type f -exec cp -t ./firmware/firmware {} +
|
||||
- name: Add SHA to footer
|
||||
run: |
|
||||
COMMIT_SHA_LONG=$(git rev-parse --short HEAD || echo "")
|
||||
@ -226,9 +223,9 @@ jobs:
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
language-images:
|
||||
@ -239,7 +236,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
variant: [ tasmota, tasmota32 ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, LT, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@ -254,10 +251,14 @@ jobs:
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./firmware
|
||||
pattern: tasmota32*
|
||||
path: ./temp
|
||||
- name: Move safeboot files
|
||||
run: |
|
||||
mkdir -p ./firmware/firmware
|
||||
find ./temp -type f -exec cp -t ./firmware/firmware {} +
|
||||
- name: Add SHA to footer
|
||||
run: |
|
||||
COMMIT_SHA_LONG=$(git rev-parse --short HEAD || echo "")
|
||||
@ -266,9 +267,9 @@ jobs:
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
|
||||
- name: Upload language firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}-${{ matrix.language }}
|
||||
path: ./build_output
|
||||
|
||||
Start_final_copy:
|
||||
|
470
.github/workflows/Tasmota_build_master.yml
vendored
470
.github/workflows/Tasmota_build_master.yml
vendored
@ -1,236 +1,234 @@
|
||||
name: Build_firmware_master
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Start a workflow
|
||||
push:
|
||||
branches: master
|
||||
paths-ignore:
|
||||
- '.github/**' # Ignore changes towards the .github directory
|
||||
- '**.md' # Do no build if *.md files changes
|
||||
|
||||
# Ensures that only one deploy task per branch/environment will run at a time.
|
||||
concurrency:
|
||||
group: environment-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
safeboot-images:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota32-safeboot
|
||||
- tasmota32solo1-safeboot
|
||||
- tasmota32c2-safeboot
|
||||
- tasmota32c3-safeboot
|
||||
- tasmota32c3ser-safeboot
|
||||
- tasmota32s2-safeboot
|
||||
- tasmota32s2cdc-safeboot
|
||||
- tasmota32s3-safeboot
|
||||
- tasmota32s3ser-safeboot
|
||||
- tasmota32c6-safeboot
|
||||
- tasmota32c6ser-safeboot
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload safeboot firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./build_output
|
||||
|
||||
base-images:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota
|
||||
- tasmota-4M
|
||||
- tasmota-minimal
|
||||
- tasmota-display
|
||||
- tasmota-ir
|
||||
- tasmota-knx
|
||||
- tasmota-lite
|
||||
- tasmota-sensors
|
||||
- tasmota-zbbridge
|
||||
- tasmota-zigbee
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
with:
|
||||
name: firmware
|
||||
path: ./build_output
|
||||
|
||||
base32-images:
|
||||
needs: safeboot-images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota32
|
||||
- tasmota32-zbbrdgpro
|
||||
- tasmota32-webcam
|
||||
- tasmota32-bluetooth
|
||||
- tasmota32-nspanel
|
||||
- tasmota32-display
|
||||
- tasmota32-ir
|
||||
- tasmota32-lvgl
|
||||
- tasmota32c2
|
||||
- tasmota32c3
|
||||
- tasmota32c6
|
||||
- tasmota32s2
|
||||
- tasmota32s2cdc
|
||||
- tasmota32s3
|
||||
- tasmota32solo1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./firmware
|
||||
- name: Display downloaded files
|
||||
run: |
|
||||
ls -R ./firmware/
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
with:
|
||||
name: firmware
|
||||
path: ./build_output
|
||||
|
||||
language-images:
|
||||
needs: safeboot-images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant: [ tasmota, tasmota32 ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./firmware
|
||||
- name: Display downloaded files
|
||||
run: |
|
||||
ls -R ./firmware/
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
|
||||
- name: Upload language firmware artifacts
|
||||
uses: jason2866/upload-artifact@v2.0.3
|
||||
with:
|
||||
name: firmware
|
||||
path: ./build_output
|
||||
|
||||
Release:
|
||||
needs: [base-images, base32-images, language-images]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download Tasmota firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
with:
|
||||
name: firmware
|
||||
path: ./mv_firmware
|
||||
- name: Download safeboot firmwares
|
||||
uses: jason2866/download-artifact@v3.0.4
|
||||
with:
|
||||
name: firmware_safeboot
|
||||
path: ./mv_firmware
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R ./mv_firmware/
|
||||
- name: Zip all map.gz files in one file -> map_all.zip
|
||||
run: 7z a -mx=9 -tzip -xr'!.*' map_all.zip mv_firmware/map
|
||||
- name: Release
|
||||
uses: jason2866/action-gh-release@v1.2
|
||||
#if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
tag_name: ${{ github.run_number }}
|
||||
files: |
|
||||
./mv_firmware/firmware/*
|
||||
map_all.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
Start_final_copy:
|
||||
needs: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dispatch workflow in arendst/Tasmota-firmware
|
||||
run: |
|
||||
curl -X POST https://api.github.com/repos/arendst/Tasmota-firmware/actions/workflows/fetch_deploy.yml/dispatches \
|
||||
-H 'Accept: application/vnd.github.everest-preview+json' \
|
||||
-u ${{ secrets.API_TOKEN_GITHUB }} \
|
||||
--data '{"ref": "gh_actions"}'
|
||||
name: Build_firmware_master
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Start a workflow
|
||||
push:
|
||||
branches: master
|
||||
paths-ignore:
|
||||
- '.github/**' # Ignore changes towards the .github directory
|
||||
- '**.md' # Do no build if *.md files changes
|
||||
|
||||
# Ensures that only one deploy task per branch/environment will run at a time.
|
||||
concurrency:
|
||||
group: environment-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
safeboot-images:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota32-safeboot
|
||||
- tasmota32solo1-safeboot
|
||||
- tasmota32c2-safeboot
|
||||
- tasmota32c3-safeboot
|
||||
- tasmota32c3ser-safeboot
|
||||
- tasmota32s2-safeboot
|
||||
- tasmota32s2cdc-safeboot
|
||||
- tasmota32s3-safeboot
|
||||
- tasmota32s3ser-safeboot
|
||||
- tasmota32c6-safeboot
|
||||
- tasmota32c6ser-safeboot
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload safeboot firmware artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
base-images:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota
|
||||
- tasmota-4M
|
||||
- tasmota-minimal
|
||||
- tasmota-display
|
||||
- tasmota-ir
|
||||
- tasmota-knx
|
||||
- tasmota-lite
|
||||
- tasmota-sensors
|
||||
- tasmota-zbbridge
|
||||
- tasmota-zigbee
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
base32-images:
|
||||
needs: safeboot-images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant:
|
||||
- tasmota32
|
||||
- tasmota32-zbbrdgpro
|
||||
- tasmota32-webcam
|
||||
- tasmota32-bluetooth
|
||||
- tasmota32-nspanel
|
||||
- tasmota32-display
|
||||
- tasmota32-ir
|
||||
- tasmota32-lvgl
|
||||
- tasmota32c2
|
||||
- tasmota32c3
|
||||
- tasmota32c6
|
||||
- tasmota32s2
|
||||
- tasmota32s2cdc
|
||||
- tasmota32s3
|
||||
- tasmota32solo1
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: tasmota32*
|
||||
path: ./temp
|
||||
- name: Move safeboot files
|
||||
run: |
|
||||
mkdir -p ./firmware/firmware
|
||||
find ./temp -type f -exec cp -t ./firmware/firmware {} +
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- name: Upload firmware artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
language-images:
|
||||
needs: safeboot-images
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
continue-on-error: true
|
||||
strategy:
|
||||
matrix:
|
||||
variant: [ tasmota, tasmota32 ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, LT, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pip install wheel
|
||||
pip install -U platformio
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Download safeboot firmwares
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: tasmota32*
|
||||
path: ./temp
|
||||
- name: Move safeboot files
|
||||
run: |
|
||||
mkdir -p ./firmware/firmware
|
||||
find ./temp -type f -exec cp -t ./firmware/firmware {} +
|
||||
- name: Add "release" to footer
|
||||
run: |
|
||||
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
|
||||
- name: Upload language firmware artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.variant }}-${{ matrix.language }}
|
||||
path: ./build_output
|
||||
|
||||
Release:
|
||||
needs: [base-images, base32-images, language-images]
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download all Tasmota artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: tasmota*
|
||||
path: ./temp
|
||||
- name: Move files
|
||||
run: |
|
||||
mkdir -p ./release
|
||||
find ./temp -type f -exec cp -t ./release {} +
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R ./release/
|
||||
- name: Release
|
||||
uses: jason2866/action-gh-release@v1.2
|
||||
#if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
tag_name: ${{ github.run_number }}
|
||||
files: |
|
||||
./release/tasmota*
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
Start_final_copy:
|
||||
needs: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dispatch workflow in arendst/Tasmota-firmware
|
||||
run: |
|
||||
curl -X POST https://api.github.com/repos/arendst/Tasmota-firmware/actions/workflows/fetch_deploy.yml/dispatches \
|
||||
-H 'Accept: application/vnd.github.everest-preview+json' \
|
||||
-u ${{ secrets.API_TOKEN_GITHUB }} \
|
||||
--data '{"ref": "gh_actions"}'
|
||||
|
18
.github/workflows/build_all_the_things.yml
vendored
18
.github/workflows/build_all_the_things.yml
vendored
@ -41,9 +41,9 @@ jobs:
|
||||
#platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- uses: jason2866/upload-artifact@v2.0.3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
os-check-mac:
|
||||
@ -69,9 +69,9 @@ jobs:
|
||||
#platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- uses: jason2866/upload-artifact@v2.0.3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
base-images:
|
||||
@ -128,9 +128,9 @@ jobs:
|
||||
cp ./platformio_override_sample.ini ./platformio_override.ini
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}
|
||||
- uses: jason2866/upload-artifact@v2.0.3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}
|
||||
path: ./build_output
|
||||
|
||||
language-images:
|
||||
@ -140,7 +140,7 @@ jobs:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
variant: [ tasmota ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, LT, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
@ -156,7 +156,7 @@ jobs:
|
||||
#platformio update
|
||||
- name: Run PlatformIO
|
||||
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
|
||||
- uses: jason2866/upload-artifact@v2.0.3
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: firmware
|
||||
name: ${{ matrix.variant }}-${{ matrix.language }}
|
||||
path: ./build_output
|
||||
|
5
.gitignore
vendored
5
.gitignore
vendored
@ -23,6 +23,8 @@ data
|
||||
unpacked_fs
|
||||
unpacked_boards
|
||||
tasmota/user_config_override.h
|
||||
tasmota/include/local_ca_data.h
|
||||
tasmota/include/local_ca_descriptor.h
|
||||
variants
|
||||
variants3
|
||||
build
|
||||
@ -47,6 +49,9 @@ lib/libesp32/berry/berry
|
||||
*.bak
|
||||
*.code-workspace
|
||||
|
||||
## IntelliJ ######
|
||||
.idea
|
||||
|
||||
## Python virtual environments for Platformio ##
|
||||
venv
|
||||
.venv
|
||||
|
13
BUILDS.md
13
BUILDS.md
@ -14,10 +14,13 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
||||
| USE_HOME_ASSISTANT | - | - / - | - | - | - | - |
|
||||
| USE_TASMOTA_DISCOVERY | x | x / x | x | x | x | x |
|
||||
| USE_MQTT_TLS\* | - | - / x | - | - | - | - |
|
||||
| USE_MQTT_CLIENT_CERT | - | - / - | - | - | - | - |
|
||||
| USE_MQTT_AWS_IOT | - | - / - | - | - | - | - |
|
||||
| USE_4K_RSA | - | - / - | - | - | - | - |
|
||||
| USE_TELEGRAM | - | - / - | - | - | - | - |
|
||||
| USE_KNX | - | - / x | x | - | - | - |
|
||||
| USE_TELNET | - | - / - | - | - | - | - |
|
||||
| USE_XYZMODEM | - | - / - | - | - | - | - |
|
||||
| USE_WEBSERVER | x | x / x | x | x | x | x |
|
||||
| USE_WEBSEND_RESPONSE | - | - / - | - | - | - | - |
|
||||
| USE_EMULATION_HUE | x | x / x | - | x | - | - |
|
||||
@ -105,8 +108,9 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
||||
| **Feature or Sensor** | **l** | **t** | **k** | **s** | **i** | **d** | **Remarks** |
|
||||
| USE_I2C | - | x / x | x | x | - | x |
|
||||
| USE_RTC_CHIPS | - | - / x | - | - | - | - |
|
||||
| -USE_DS3231 | - | - / - | - | - | - | - |
|
||||
| -USE_BM8563 | - | - / x | - | - | - | - |
|
||||
| -USE_DS3231 | - | - / - | - | - | - | - |
|
||||
| -USE_PCF85063 | - | - / - | - | - | - | - |
|
||||
| -USE_PCF85363 | - | - / - | - | - | - | - |
|
||||
| -USE_RX8010 | - | - / - | - | - | - | - |
|
||||
| USE_SHT | - | - / x | - | x | - | - |
|
||||
@ -227,12 +231,15 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
||||
| USE_MIEL_HVAC | - | - / - | - | - | - | - |
|
||||
| USE_PROJECTOR_CTRL | - | - / - | - | - | - | - |
|
||||
| USE_AS608 | - | - / - | - | - | - | - |
|
||||
| USE_LD2402 | - | - / - | - | - | - | - |
|
||||
| USE_LD2410 | - | - / - | - | - | - | - |
|
||||
| USE_LD2410S | - | - / - | - | - | - | - |
|
||||
| USE_GM861 | - | - / - | - | - | - | - |
|
||||
| USE_TCP_BRIDGE | - | - / - | - | - | - | - | zbbridge / zbbrdgpro |
|
||||
| USE_HC8 | - | - / - | - | - | - | - |
|
||||
| USE_PIPSOLAR | - | - / - | - | - | - | - |
|
||||
| USE_WOOLIIS | - | - / - | - | - | - | - |
|
||||
| USE_C8_CO2_5K | - | - / - | - | - | - | - |
|
||||
| | | | | | | |
|
||||
| USE_NRF24 | - | - / - | - | - | - | - |
|
||||
| USE_MIBLE | - | - / - | - | - | - | - |
|
||||
@ -244,11 +251,14 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
||||
| USE_IR_RECEIVE | - | x / - | x | x | x | x |
|
||||
| USE_IR_REMOTE_FULL | - | - / - | - | - | x | - | Enable ALL protocols |
|
||||
| | | | | | | |
|
||||
| USE_WIZMOTE | - | - / - | - | - | - | - |
|
||||
| | | | | | | |
|
||||
| USE_SR04 | - | - / - | - | x | - | - |
|
||||
| USE_ME007 | - | - / - | - | - | - | - |
|
||||
| USE_DYP | - | - / - | - | - | - | - |
|
||||
| USE_TM1638 | - | - / x | - | x | - | - |
|
||||
| USE_HX711 | - | - / x | - | x | - | - |
|
||||
| -USE_HX711_M5SCALES | - | - / - | - | - | - | - |
|
||||
| USE_TX2x_WIND_SENSOR | - | - / - | - | - | - | - |
|
||||
| USE_WINDMETER | - | - / - | - | - | - | - |
|
||||
| USE_RC_SWITCH | - | - / x | - | x | - | - |
|
||||
@ -283,6 +293,7 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
|
||||
| USE_SONOFF_SPM | | / x | | | | |
|
||||
| USE_DISPLAY_TM1621_SONOFF | | / x | | | | |
|
||||
| USE_SHELLY_PRO | | / x | | | | |
|
||||
| USE_ESP32_TWAI | | / x | | | | |
|
||||
| USE_DALI | | / x | | | | |
|
||||
| USE_DINGTIAN_RELAY | | / - | | | | |
|
||||
| USE_MATTER_DEVICE | | / x | | | | | See SetOption151 |
|
||||
|
197
CHANGELOG.md
197
CHANGELOG.md
@ -1,8 +1,205 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased] - Development
|
||||
|
||||
## [14.6.0.1]
|
||||
### Added
|
||||
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
|
||||
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
|
||||
|
||||
### Breaking Changed
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
- Berry `bytes().asstring()` now truncates a string if buffer contains NULL (#23311)
|
||||
- Berry string literals containing NULL are truncated (#23312)
|
||||
|
||||
### Removed
|
||||
|
||||
|
||||
|
||||
## [Released]
|
||||
|
||||
## [14.6.0] 20250416
|
||||
- Release Ryan
|
||||
|
||||
## [14.5.0.3] 20250416
|
||||
### Added
|
||||
- Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go
|
||||
- Berry `bytes.add()` now accepts 3-bytes values (#23200)
|
||||
- Berry expose `esp_http_server` for websockets (#23206)
|
||||
- AlpineJS 2.8.2 - optional for now (#23259)
|
||||
- Support for XMODEM over serial and telnet if enabled with `#define USE_XYZMODEM`
|
||||
- PZEM_AC device address in JSON and GUI (#23268)
|
||||
- Filesystem command ``UfsList[2]``
|
||||
- ESP32 show network interface priority in `Status 5` debug logging (#23302)
|
||||
|
||||
### Breaking Changed
|
||||
- HASPmota added `y2_min` and `y2_max` to control the second series of `chart` (#23287)
|
||||
- HASPmota default theme is now Tasmota-style (#23288)
|
||||
|
||||
### Changed
|
||||
- Output of commands `GPIO` and `GPIOs` swapped
|
||||
- Smoothen light gamma curve when using `Fade` (#23230)
|
||||
- ESP32 Platform from 2025.03.30 to 2025.04.30, Framework (Arduino Core) from v3.1.3.250302 to v3.1.3.250411 and IDF from v5.3.2.250228 to 5.3.2.250403 (#23280)
|
||||
- HLK-LD2402 updates for firmware 3.3.5+ (#23281)
|
||||
|
||||
### Fixed
|
||||
- INA226 driver fixes (#23197)
|
||||
- TLS increase timeout and fix crash (#23249)
|
||||
- Berry `readline` when a line is exactly 98 characters (#23276)
|
||||
|
||||
## [14.5.0.2] 20250325
|
||||
### Added
|
||||
- Berry load `.tapp` files in `/.extensions/` then in `/` (#23113)
|
||||
- Support Vango Technologies V924x ultralow power, single-phase, power measurement (#23127)
|
||||
- Support for HLK-LD2402 24GHz smart wave motion sensor (#23133)
|
||||
- Matter prepare for ICD cluster (#23158)
|
||||
- Berry `re.dump()` (#23162)
|
||||
- Support for Telnet server using command `Telnet <0|1|port>[,<IP filter>]` if enabled with `#define USE_TELNET`
|
||||
- HASPmota autostart when `pages.jsonl` exists (#23181)
|
||||
|
||||
### Breaking Changed
|
||||
- Berry remove `Leds.create_matrix` from the standard library waiting for reimplementation (#23114)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2025.02.30 to 2025.03.30, Framework (Arduino Core) from v3.1.1.250203 to v3.1.3.250302 and IDF from v5.3.2.250120 to 5.3.2.250228 (#23088)
|
||||
- ESP32 enable webcam version 2 (#18732)
|
||||
- ESP8266 enable FTP for >= 4MB variants (#23120)
|
||||
- Berry update flasher for Sonoff ZBBridge Pro (#23136)
|
||||
- Berry `re` now accepts `bytes()` as precompiled patterns, added `re.compilebytes()` (#23149)
|
||||
- RCSwitch `RCSWITCH_SEPARATION_LIMIT` from 4100 to 3600
|
||||
|
||||
### Fixed
|
||||
- Berry prevent `import` from hiding a solidified class (#23112)
|
||||
- ESP32-C3 WiFi sleep (#23096)
|
||||
- ESP32 intermittent exception on WiFi AP cannot be reached (#23115)
|
||||
- ESP32 receive incomplete serial data over 128 bytes (#23156)
|
||||
|
||||
## [14.5.0.1] 20250302
|
||||
### Added
|
||||
- Berry experimental driver for AXP2101 for M5Core2v1.1 (#23039)
|
||||
- LVGL experimental mirroring of display on Web UI (#23041)
|
||||
- Allow acl in mqtt when client certificate is in use with `#define USE_MQTT_CLIENT_CERT` (#22998)
|
||||
- Berry `tasmota.when_network_up()` and simplified Matter using it (#23057)
|
||||
- Berry `introspect.solidified()` to know if a Berry object is solidified or in RAM (#23063)
|
||||
- Berry `global.undef()` to undefine a global variable (#23073)
|
||||
|
||||
### Changed
|
||||
- LVGL, prepare for HASPmota theme, change: no-grow when clicked, DPI set to 160 (#23040)
|
||||
- LVGL Mirroring add checkbox to enable/disable the feature (in the iterim for a better solution) (#23047)
|
||||
- Leds Panel add checkbox to enable/disable the feature (in the iterim for a better solution) (#23048)
|
||||
- GPIOViewer from v1.6.1 to v1.6.2 (No functional change)
|
||||
|
||||
### Fixed
|
||||
- Too many zeros in RCSwitch received data regression from v14.4.1.4 (#23050)
|
||||
|
||||
## [14.5.0] 20250219
|
||||
- Release Ruth
|
||||
|
||||
## [14.4.1.4] 20250219
|
||||
### Added
|
||||
- Formatter `%_U` for `ext_snprintf_P()` to print uint64_t variable as decimal equivalent to `%llu`
|
||||
- Support for RC-switch decoding of 64-bit received data
|
||||
- Berry `tasmota.defer()` (#22976)
|
||||
- Support for Lithuanian language translations by zzdovydas (#22971)
|
||||
- `MqttTLS` field in `Status 6` to indicate if the MQTT connection is encrypted (#22995)
|
||||
- Support for WiZ Smart Remote using `#define USE_WIZMOTE` and command `SetOption164 1`
|
||||
- Berry `bytes().appendb64()` (#22767)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2025.01.31 to 2025.02.30, Framework (Arduino Core) from v3.1.1.250109 to v3.1.1.250203 and IDF to 5.3.2 (#22943)
|
||||
- ESP32 Webcam resolution changes since v14.4.0 (#22901)
|
||||
|
||||
### Fixed
|
||||
- Berry parser error in rare case (#22997)
|
||||
- ESP32 TasMesh broker MAC address all zeros (#23005)
|
||||
- Wrong RMT channels for ESP32S3, now depends on `soc_caps.h` (#23021)
|
||||
- HASPmota exception when clicking on a checkbox (#23022)
|
||||
|
||||
## [14.4.1.3] 20250204
|
||||
### Added
|
||||
- Command `FileLog 0..4` to enable logging to filesystem using up to 16 rotating log files of 100kB (`#define FILE_LOG_SIZE 100`)
|
||||
- Command `FileLog 10..14` to enable logging to filesystem using up to 16 log files of 100kB (`#define FILE_LOG_SIZE 100`)
|
||||
- I2S Opus stream and file support for opus/aac (#22795)
|
||||
- I2S command I2sLoop (#22807)
|
||||
- Berry `serial.read()` read only `n` bytes (#22835)
|
||||
- Display template for Waveshare ESP32-C6 LCD 1.47 (#22863)
|
||||
- Berry `tasmota.global.tele_period` and `tasmota.settings.tele_period` (#22865)
|
||||
- ESP32 command `PixelType` to change the WS2812 color order and channel number (#22876)
|
||||
- Berry driver for AXP2102 and M5CoreS3 (#22878)
|
||||
- GPS driver select baudrate using GPIO GPS_RX1 (9600bps), GPS_RX2 (19200bps) or GPS_RX3 (38400bps) (#22869)
|
||||
- LVLG/HASPmota add color names from OpenHASP (#22879)
|
||||
- HASPmota support for `buttonmatrix` events (#22898)
|
||||
- Berry driver for PN532 NFC/Mifare reader (#22899)
|
||||
- Berry `tasmota.add_rule_once` and auto-remove rules with same pattern and id (#22900)
|
||||
- Berry example for HeatFan WiFi Controller
|
||||
- LVGL `lv.set_paint_cb()` to register a callback when screen is refreshed (#22909)
|
||||
- Berry `tasmota.settings` entries for PixelType (#22912)
|
||||
- Support for C8-CO2-5K CO2 sensor (#22905)
|
||||
- `#define FIX_JSON_HEXADECIMAL` to change JSON hexadecimal value "FF5F78" into "0xFF5F78" (#22919)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2024.12.30 to 2025.01.30, Framework (Arduino Core) from v3.1.0.241206 to v3.1.1.250109 and IDF to 5.3.2 (#22792)
|
||||
- Allow negative values for AdcParam/AdcGpio INPUT, TEMP and RANGE parameters (#22809)
|
||||
- GPIOViewer from v1.5.9 to v1.6.0 (No functional change)
|
||||
- ESP32 Platform from 2025.01.30 to 2025.01.31 (#22832)
|
||||
- Berry `gpio.pin_mode` frees PWM on pin
|
||||
- GPIOViewer from v1.6.0 to v1.6.1 (No functional change)
|
||||
- Berry callback now passes 5 arguments instead of 4 (in line with documentation) (#22908)
|
||||
|
||||
### Fixed
|
||||
- Sonoff SPM `PowerOnState` overrules `SSPMPowerOnState` in mixed 4Relay setup with 4Relay version 1.0.0
|
||||
- ESP32-Cx compilation fails on Windows (#22832)
|
||||
- LoraWan decoding of Dragino LDS02 and MerryIoT DW10 (#22880)
|
||||
|
||||
## [14.4.1.2] 20250110
|
||||
### Added
|
||||
- Support for ESP32 Two-Wire Automotive Interface (TWAI) or Controller Area Network (CAN) busses
|
||||
- Support for Senseair S88 CO2 sensor (#22733)
|
||||
- ESP32 TasmotaLED change dynamically the number of pixels (#22754)
|
||||
- ESP32 expand `Pixels` with reverse, height and alternate (#22755)
|
||||
- Berry add light_pixels values to `tasmota.settings` (#22762)
|
||||
- Berry add `bytes().appendhex()` (#22767)
|
||||
- I2S AAC support for web radio (#22787)
|
||||
- Berry WS2812 real-time Leds panel as app (#22788)
|
||||
|
||||
### Changed
|
||||
- GPIOViewer from v1.5.8 to v1.5.9 (No functional change)
|
||||
- `Pixels` has backwards compatible arguments fixing #22755 (#22791)
|
||||
|
||||
### Fixed
|
||||
- Shutter discovery message regression from v14.4.1 (#22730)
|
||||
|
||||
## [14.4.1.1] 20241231
|
||||
### Added
|
||||
- Command ``SetOption163 1`` to disable display of Device name in GUI header
|
||||
- Berry `animate.crenel` primitive (#22673)
|
||||
- Berry scroll to Leds_matrix (#22693)
|
||||
- HASPmota support for `tabview` (#22707)
|
||||
- Berry bit-shift operators to `int64` (#22709)
|
||||
- Berry add unicode encoding to string parsing (#22713)
|
||||
- Berry `tasmota.int(v, min, max)` function (#22723)
|
||||
- Berry driver for M5Stack 8encoder (#22724)
|
||||
- Support for PCF85063 RTC (#22727)
|
||||
|
||||
### Changed
|
||||
- ESP32 disable PSRAM check (and on restart some relay toggles) with `#define DISABLE_PSRAMCHECK true` (#21266)
|
||||
- TLS disable ECDSA for MQTT to ensure we don't break fingerprints after #22649
|
||||
- GPIOViewer from v1.5.6 to v1.5.8
|
||||
- HASPmota use 'roboto.ttf' for automatic sizing of default font (#22697)
|
||||
- HASPmota add 'tag' attribute for free-form JSON (#22698)
|
||||
- Postpone save_data during light animation when fade is Off
|
||||
|
||||
### Fixed
|
||||
- Berry Zigbee fix wrong attributes (#22684)
|
||||
- Berry walrus operator (#22685)
|
||||
- Webcam compilation with `define USE_WEBCAM` but without `define ENABLE_RTSPSERVER` (#22686)
|
||||
- LVGL updated `Antiburn.tapp` (#22699)
|
||||
- Matter Air Quality sensor (#22708)
|
||||
|
||||
## [14.4.1] 20241215
|
||||
- Release Rudolph
|
||||
|
||||
|
@ -85,12 +85,13 @@ In addition to @arendst the following code is mainly owned by:
|
||||
| xdrv_71_magic_switch | @barbudor
|
||||
| xdrv_72_pipsolar | @chefpro
|
||||
| xdrv_73_lora | @arendst
|
||||
| xdrv_74 |
|
||||
| xdrv_74_lorawan | @arendst
|
||||
| xdrv_75_dali | @eeak, @arendst
|
||||
| xdrv_76 |
|
||||
| xdrv_77 |
|
||||
| xdrv_78 |
|
||||
| xdrv_76_serial_i2c | @s-hadinger
|
||||
| xdrv_77_wizmote | @arendst
|
||||
| xdrv_78_telnet | @arendst
|
||||
| xdrv_79_esp32_ble | @staars, @btsimonh
|
||||
| xdrv_80 |
|
||||
| xdrv_81_esp32_webcam | @gemu, @philrich
|
||||
| xdrv_82_esp32_ethernet | @arendst
|
||||
| xdrv_83_esp32_watch | @gemu
|
||||
@ -105,6 +106,7 @@ In addition to @arendst the following code is mainly owned by:
|
||||
| xdrv_93_ |
|
||||
| xdrv_94_ |
|
||||
| |
|
||||
| xdrv_120_xyzmodem | @arendst
|
||||
| xdrv_121_gpioviewer | @arendst
|
||||
| xdrv_122_file_settings_demo | @arendst
|
||||
| xdrv_122_file_json_settings_demo | @arendst
|
||||
@ -230,6 +232,7 @@ In addition to @arendst the following code is mainly owned by:
|
||||
| xsns_113_hc8 | Daniel Maier
|
||||
| xsns_114_amsx915 | Bastian Urschel
|
||||
| xsns_115_wooliis | Luca Melette
|
||||
| xsns_117_c8_co2_5k | @jeroenvermeulen
|
||||
| |
|
||||
| xsns_127_esp32_sensors | @arendst
|
||||
| |
|
||||
|
@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/CHANGELOG
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
|
||||
|
@ -129,5 +129,6 @@ Index | Define | Driver | Device | Address(es) | Bus2 | Descrip
|
||||
89 | USE_HX711_M5SCALES | xsns_34 | M5SCALES | 0x26 | Yes | M5Unit (Mini)Scales(HX711 STM32) U177
|
||||
90 | USE_RX8010 | xdrv_56 | RX8010 | 0x32 | Yes | RX8010 RTC from IOTTIMER
|
||||
91 | USE_MS5837 | xsns_116 | MS5837 | 0x76 | | Pressure and temperature sensor
|
||||
92 | USE_PCF85063 | xdrv_56 | PCF85063 | 0x51 | | PCF85063 Real time clock
|
||||
|
||||
NOTE: Bus2 supported on ESP32 only.
|
||||
|
@ -94,4 +94,4 @@ Module | LCode | Description
|
||||
06 TTGO Watch | x | TTGO Watch
|
||||
07 M5Stack Core2 | x | M5Stack Core2
|
||||
|
||||
Over 2500 additional devices are supported using [templates](TEMPLATES.md).
|
||||
Over 2800 additional devices are supported using [templates](TEMPLATES.md).
|
||||
|
@ -31,7 +31,7 @@ Firmware binaries can be downloaded from http://ota.tasmota.com/tasmota/release/
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml)
|
||||
[](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml)
|
||||
|
108
RELEASENOTES.md
108
RELEASENOTES.md
@ -36,9 +36,9 @@ While fallback or downgrading is common practice it was never supported due to S
|
||||
|
||||
This release will be supported from ESP8266/Arduino library Core version **2.7.8** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
|
||||
|
||||
This release will be supported from ESP32/Arduino library Core version **v3.1.0.241206**.
|
||||
This release will be supported from ESP32/Arduino library Core version **v3.1.3.250411**.
|
||||
|
||||
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.0.241206 have been removed.
|
||||
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.3.250411 have been removed.
|
||||
|
||||
## Support of TLS
|
||||
|
||||
@ -75,12 +75,12 @@ Latest released binaries can be downloaded from
|
||||
- http://ota.tasmota.com/tasmota/release
|
||||
|
||||
Historical binaries can be downloaded from
|
||||
- http://ota.tasmota.com/tasmota/release-14.4.1
|
||||
- http://ota.tasmota.com/tasmota/release-14.6.0
|
||||
|
||||
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
|
||||
|
||||
### ESP32, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-S2 and ESP32-S3 based
|
||||
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.0.241206**.
|
||||
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.3.250411**.
|
||||
|
||||
- **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY**
|
||||
- **tasmota32solo1.bin** = The Tasmota version with most drivers including additional sensors and KNX for single core ESP32 and 4M+ flash.
|
||||
@ -88,7 +88,7 @@ The following binary downloads have been compiled with ESP32/Arduino library cor
|
||||
- **tasmota32s2cdc.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-S2 with serial over embedded USB CDC only and 4M+ flash.
|
||||
- **tasmota32s3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-S3 with USB HWCDC and fallback to serial and 4M+ flash.
|
||||
- **tasmota32c2.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C2 with serial and 4M+ flash.
|
||||
- **tasmota32c3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C2 with USB HWCDC and fallback to serial and 4M+ flash.
|
||||
- **tasmota32c3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C3 with USB HWCDC and fallback to serial and 4M+ flash.
|
||||
- **tasmota32c6.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C6 with USB HWCDC and fallback to serial and 4M+ flash.
|
||||
- **tasmota32-AD.bin** to **tasmota32-VN.bin** = The Tasmota version in different languages for 4M+ flash.
|
||||
- **tasmota32-bluetooth.bin** = The Bluetooth version adds BLE support for 4M+ flash.
|
||||
@ -104,7 +104,7 @@ Latest released binaries can be downloaded from
|
||||
- https://ota.tasmota.com/tasmota32/release
|
||||
|
||||
Historical binaries can be downloaded from
|
||||
- https://ota.tasmota.com/tasmota32/release-14.4.1
|
||||
- https://ota.tasmota.com/tasmota32/release-14.6.0
|
||||
|
||||
The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasmota.com/tasmota32/release/tasmota32.bin``
|
||||
|
||||
@ -114,99 +114,17 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
|
||||
|
||||
[Complete list](BUILDS.md) of available feature and sensors.
|
||||
|
||||
## Changelog v14.4.1 Rudolph
|
||||
## Changelog v14.6.0.1
|
||||
### Added
|
||||
- MCP23XXX_DRV control register IOCON in template [#22622](https://github.com/arendst/Tasmota/issues/22622)
|
||||
- ESP32 support for TLS ECDSA [#22649](https://github.com/arendst/Tasmota/issues/22649)
|
||||
|
||||
### Changed
|
||||
- Display removed PWM control of backlight GPIO regression from v14.1.0
|
||||
- SSL clean up remnants of old fingerprint algorithm [#22645](https://github.com/arendst/Tasmota/issues/22645)
|
||||
- Berry make Leds animate calls reentrant [#22643](https://github.com/arendst/Tasmota/issues/22643)
|
||||
|
||||
### Fixed
|
||||
- Display DisplayMode adds a display device while not configured
|
||||
- GUI display power button regression from v14.3.0.5 [#15788](https://github.com/arendst/Tasmota/issues/15788)
|
||||
- MCP23xxx, PCF8574 and Shift595 power control when a display is configured regression from v14.3.0.7
|
||||
- ESP32 rules operation priority regression from v13.3.0.4 [#22636](https://github.com/arendst/Tasmota/issues/22636)
|
||||
|
||||
## Changelog v14.4.0 Rudolph
|
||||
### Added
|
||||
- Command `WebColor20` to control color of Button when Off
|
||||
- Command `SetOption161 1` to disable display of state text [#22515](https://github.com/arendst/Tasmota/issues/22515)
|
||||
- Command `SetOption162 1` to disable adding export energy to energy today [#22578](https://github.com/arendst/Tasmota/issues/22578)
|
||||
- DALI support for short addresses (gear) and groups
|
||||
- DALI command `DaliGear` to set max found gear to speed up scan response
|
||||
- DALI command `DaliGroup` to add gear to groups
|
||||
- DALI command `DaliTarget` to set light control broadcast, group number or gear number
|
||||
- DALI command `DaliGroupSliders 0..16` to show GUI group sliders with feedback disabling `DaliLight`
|
||||
- DALI inverted signal configuration using GPIO DALI RX_i/TX_i
|
||||
- Support for I2C over Serial [#22444](https://github.com/arendst/Tasmota/issues/22444)
|
||||
- Support KNX for scripts [#22429](https://github.com/arendst/Tasmota/issues/22429)
|
||||
- Support deep sleep (standby) for VL53L0X [#22441](https://github.com/arendst/Tasmota/issues/22441)
|
||||
- Support for Shelly DALI Dimmer Gen3
|
||||
- Support for HLK-LD2410S 24GHz smart wave motion sensor [#22253](https://github.com/arendst/Tasmota/issues/22253)
|
||||
- Support for US AQI and EPA AQI in PMS5003x sensors [#22294](https://github.com/arendst/Tasmota/issues/22294)
|
||||
- Support for MS5837 pressure and temperature sensor [#22376](https://github.com/arendst/Tasmota/issues/22376)
|
||||
- Support for TM1640 based IoTTimer by Stefan Oskamp [#21376](https://github.com/arendst/Tasmota/issues/21376)
|
||||
- Support for Sonoff POWCT Energy Export Active [#22596](https://github.com/arendst/Tasmota/issues/22596)
|
||||
- HLK-LD2410 Engineering mode [#21880](https://github.com/arendst/Tasmota/issues/21880)
|
||||
- Mitsubishi Electric HVAC Operation time for MiElHVAC [#22334](https://github.com/arendst/Tasmota/issues/22334)
|
||||
- Mitsubishi Electric HVAC Outdoor Temperature for MiElHVAC [#22345](https://github.com/arendst/Tasmota/issues/22345)
|
||||
- Mitsubishi Electric HVAC Compressor Frequency for MiElHVAC [#22347](https://github.com/arendst/Tasmota/issues/22347)
|
||||
- Mitsubishi Electric HVAC Auto Clear Remote Temp for MiElHVAC [#22370](https://github.com/arendst/Tasmota/issues/22370)
|
||||
- SolaxX1 Meter mode [#22330](https://github.com/arendst/Tasmota/issues/22330)
|
||||
- Show Active Power Total with any multi-phase energy monitoring [#22579](https://github.com/arendst/Tasmota/issues/22579)
|
||||
- ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 [#22600](https://github.com/arendst/Tasmota/issues/22600)
|
||||
- ESP32 ULP lp_core to Berry ULP module (#22567)[#22567](https://github.com/arendst/Tasmota/issues/22567)
|
||||
- ESP32 new BLE filters by name and minimum RSSI [#22530](https://github.com/arendst/Tasmota/issues/22530)
|
||||
- ESP32 Hybrid compile take custom boards settings in account [#22542](https://github.com/arendst/Tasmota/issues/22542)
|
||||
- ESP32 MI32 legacy add config operations [#22458](https://github.com/arendst/Tasmota/issues/22458)
|
||||
- BLE track devices with RPA [#22300](https://github.com/arendst/Tasmota/issues/22300)
|
||||
- Berry add I2C read16/write16 supporting Little Endian [#22448](https://github.com/arendst/Tasmota/issues/22448)
|
||||
- Berry drivers for PCA9535 (generic and in SenseCAP D1) [#22451](https://github.com/arendst/Tasmota/issues/22451)
|
||||
- HASPmota `haspmota.get_pages()` to get the sorted list of pages [#22358](https://github.com/arendst/Tasmota/issues/22358)
|
||||
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
|
||||
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
|
||||
|
||||
### Breaking Changed
|
||||
- ESP32 ArtNet switches from GRB to RGB encoding [#22556](https://github.com/arendst/Tasmota/issues/22556)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2024.09.30 to 2024.12.30, Framework (Arduino Core) from v3.1.0.240926 to v3.1.0.241206 and IDF to 5.3.2 [#22600](https://github.com/arendst/Tasmota/issues/22600)
|
||||
- ESP32 LVGL library from v9.2.0 to v9.2.2 [#22385](https://github.com/arendst/Tasmota/issues/22385)
|
||||
- ESP32 replaced NeoPixelBus with TasmotaLED [#22556](https://github.com/arendst/Tasmota/issues/22556)
|
||||
- Redesign GUI adding feedback to buttons, shutters and lights
|
||||
- Add GUI submenu headers and refresh configuration button text (#22592)
|
||||
- Use command `WebButton1` to change GUI shutter 1 name
|
||||
- RG-15 sensor name from RG-15 to RG15 [#22612](https://github.com/arendst/Tasmota/issues/22612)
|
||||
- Unit (k)VAr(h) to (k)var(h) [#22435](https://github.com/arendst/Tasmota/issues/22435)
|
||||
- AHT1X/AHT2X/AHT3X ready for virtual I2C [#22427](https://github.com/arendst/Tasmota/issues/22427)
|
||||
- SGP4X ready for virtual I2C [#22427](https://github.com/arendst/Tasmota/issues/22427)
|
||||
- SCD40 reduce logging levels [#22443](https://github.com/arendst/Tasmota/issues/22443)
|
||||
- SCD40 ready for virtual I2C [#22443](https://github.com/arendst/Tasmota/issues/22443)
|
||||
- Refactored `i2c_enabled` as array [#22387](https://github.com/arendst/Tasmota/issues/22387)
|
||||
- DALI renamed commands `DaliCommission` to `DaliScan` and `DaliWeb` to `DaliLight`
|
||||
- DALI set Tasmota light control as default
|
||||
- Shutter optimized behavior to publish shutter data with sensor request [#22353](https://github.com/arendst/Tasmota/issues/22353)
|
||||
- Prevent active BLE operations with unencrypted MI-format beacons [#22453](https://github.com/arendst/Tasmota/issues/22453)
|
||||
- ESP32 max number of supported switches/buttons/relays from 28 to 32
|
||||
- ESP32 max number of interlocks from 14 to 16
|
||||
- HASPmota support for page delete and object updates [#22311](https://github.com/arendst/Tasmota/issues/22311)
|
||||
|
||||
### Fixed
|
||||
- FUNC_COMMAND linked list command buffer corruption by shutter driver
|
||||
- Shift595 output offsets and restart relay toggles
|
||||
- Use HTML escape on File System Edit File load [#22492](https://github.com/arendst/Tasmota/issues/22492)
|
||||
- Prevent crashing when `display.ini` is missing end `#` [#22471](https://github.com/arendst/Tasmota/issues/22471)
|
||||
- KNX Scenes index change regression from v14.2.0.4 [#22405](https://github.com/arendst/Tasmota/issues/22405)
|
||||
- Magic switch applying masking window to any power change [#22535](https://github.com/arendst/Tasmota/issues/22535)
|
||||
- Shutter wrong power ON state [#22548](https://github.com/arendst/Tasmota/issues/22548)
|
||||
- Alexa Hue with multiple devices [#22383](https://github.com/arendst/Tasmota/issues/22383)
|
||||
- Mitsubishi Electric HVAC Standby Stage for MiElHVAC [#22430](https://github.com/arendst/Tasmota/issues/22430)
|
||||
- EQ3 TRV firmware version 1.46 fails if the default true is used in subscribe on the notify characteristic [#22328](https://github.com/arendst/Tasmota/issues/22328)
|
||||
- Ethernet on -DFRAMEWORK_ARDUINO_ITEAD framework regression from v14.3.0 [#22367](https://github.com/arendst/Tasmota/issues/22367)
|
||||
- ESP8266 Device Group exception due to lack of stack space (#22271)[#22271](https://github.com/arendst/Tasmota/issues/22271)
|
||||
- ESP32 Upgrade by file upload response based on file size [#22500](https://github.com/arendst/Tasmota/issues/22500)
|
||||
- ESP32 Arduino Core IPv6 zones used by Matter [#22378](https://github.com/arendst/Tasmota/issues/22378)
|
||||
- ESP32, ESP32-S2 and ESP32-S3 re-enable touch buttons [#22446](https://github.com/arendst/Tasmota/issues/22446)
|
||||
- ESP32-S3 UART output mode for Tx [#22426](https://github.com/arendst/Tasmota/issues/22426)
|
||||
- Matter provisioning with matter.js controller [#22470](https://github.com/arendst/Tasmota/issues/22470)
|
||||
- Berry `bytes().asstring()` now truncates a string if buffer contains NULL [#23311](https://github.com/arendst/Tasmota/issues/23311)
|
||||
- Berry string literals containing NULL are truncated [#23312](https://github.com/arendst/Tasmota/issues/23312)
|
||||
|
||||
### Removed
|
||||
|
37
TEMPLATES.md
37
TEMPLATES.md
@ -5,7 +5,7 @@
|
||||
|
||||
# Templates
|
||||
|
||||
Find below the available templates as of December 2024. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
|
||||
Find below the available templates as of April 2025. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
|
||||
|
||||
## Adapter Board
|
||||
```
|
||||
@ -186,7 +186,6 @@ LE lampUX 15W RGBCCT {"NAME":"LE lampUX 15W","GPIO":[0,0,0,0,416,419,0,0
|
||||
LightZone MeLiTec {"NAME":"LightZone MeLiTec D114 Light ","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
Lohas ZN026CL10 RGBCCT {"NAME":"Lohas LED Lamp","GPIO":[0,0,0,0,417,416,0,0,419,418,420,0,0,0],"FLAG":0,"BASE":18}
|
||||
LOLAsmart Uranus White 70 cm {"NAME":"lola smart","GPIO":[0,0,0,1088,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
LSC 20W 1400lm White Ambiance {"NAME":"LSC RGBCW LED","GPIO":[0,0,0,0,0,0,0,0,4064,0,4032,0,0,0],"FLAG":0,"BASE":18}
|
||||
Luminea 24W CCT {"NAME":"Luminea NX6205-944","GPIO":[0,0,0,0,0,0,0,0,449,0,416,0,0,0],"FLAG":0,"BASE":48}
|
||||
LVL 300mm Round {"NAME":"LVL 300m Round 24W Ceiling LED","GPIO":[0,0,0,0,0,416,0,0,0,449,0,0,0,0],"FLAG":0,"BASE":48}
|
||||
Nedis CCT 800lm {"NAME":"NEDIS WIFILAW10WT","GPIO":[0,0,0,0,0,0,0,0,417,0,416,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -266,6 +265,9 @@ EARU DIN Circuit Breaker 2P 63/80A eWeLink White {"NAME":"RDCBC-2P","GPIO":[32,
|
||||
Hoch Circuit Breaker 1P {"NAME":"HOCH ZJSB9","GPIO":[32,0,0,0,0,0,0,0,224,320,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Ketotek Single Phase Energy Monitor {"NAME":"Ketotek KTEM06","GPIO":[0,2272,0,2304,0,0,0,0,0,0,320,0,32,0],"FLAG":0,"BASE":54}
|
||||
Martin Jerry 30A Circuit Breaker {"NAME":"30A Breaker","GPIO":[0,0,0,0,7584,224,0,0,2720,32,2656,2624,320,0],"FLAG":0,"BASE":18}
|
||||
Nous DIN Smart Switch 16A {"NAME":"Nous D1T","GPIO":[32,1,9312,1,1,320,1,1,9313,8160,3200,544,1,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,1,1,4736,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Nous DIN Smart Switch 20A {"NAME":"Nous D1T","GPIO":[32,1,9312,1,1,320,1,1,9313,8160,3200,544,1,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,1,1,4736,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Nous DIN Smart Switch 25A {"NAME":"Nous D1T","GPIO":[32,1,9312,1,1,320,1,1,9313,8160,3200,544,1,1,1,1,0,1,1,1,0,0,1,1,0,0,0,0,1,1,4736,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
OpenEnergyMonitor WiFi MQTT Thermostat {"NAME":"MQTT-RELAY","GPIO":[32,0,1,0,0,224,0,0,0,0,0,0,320,0],"FLAG":0,"BASE":18}
|
||||
RocketController ASTRA Controller {"NAME":"ASTRA R4A4","GPIO":[1,1,1,1,576,1,1,1,480,1,1,1,3232,3200,1,1,0,640,608,1,0,224,225,1152,0,0,0,0,227,226,160,161,162,0,0,163],"FLAG":0,"BASE":1}
|
||||
Shelly Pro 1 {"NAME":"Shelly Pro 1","GPIO":[0,1,0,1,768,0,0,0,672,704,736,0,0,0,5600,6214,0,0,0,5568,0,0,0,0,0,0,0,0,0,0,0,32,4736,0,160,0],"FLAG":0,"BASE":1,"CMND":"AdcParam1 2,10000,10000,3350"}
|
||||
@ -601,6 +603,7 @@ EBERG ROT 720 Infrared {"NAME":"Tuya MCU","GPIO":[0,2272,0,2304,0,0,0,0,0,
|
||||
Klarstein Bornholm Smart 2000W {"NAME":"Klarstein Bornholm","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
Kogan 1500W Panel {"NAME":"Kogan Panel Heater","GPIO":[0,0,0,0,0,0,0,0,0,2304,0,2272,0,0],"FLAG":0,"BASE":54}
|
||||
LSC Smart Connect 500W IR Panel {"NAME":"LSC Connect Smart IR Panel Heater","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
Mursche 450W Infrared Heater {"NAME":"Mursche Infrared Heater","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
SmartMi Electric Air {"NAME":"ZNNFJ07ZM","GPIO":[0,0,0,0,0,0,0,0,0,0,0,0,0,3200,3232,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
```
|
||||
|
||||
@ -989,6 +992,8 @@ Merkury {"NAME":"Merkury Switch","GPIO":[0,0,0,0,32,0,0,0,0
|
||||
Meross MSS620 16A IP44 {"NAME":"MSS620","GPIO":[0,320,0,320,225,0,0,0,224,576,32,0,0,0],"FLAG":0,"BASE":18}
|
||||
Minoston MP22W {"NAME":"Minoston MP22W","GPIO":[0,0,0,0,320,0,0,0,224,64,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Nedis PO120 IP44 {"NAME":"WIFIPO120FWT","GPIO":[32,0,0,0,2688,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":49}
|
||||
Nous A6T Smart Socket {"NAME":"NOUS A5T","GPIO":[0,3072,544,3104,0,259,0,0,225,226,224,0,35,4704],"FLAG":1,"BASE":18}
|
||||
Nous Dual Smart Socket {"NAME":"NOUS A4T","GPIO":[0,2624,0,576,2656,2720,0,0,224,225,32,0,0,0],"FLAG":0,"BASE":18}
|
||||
Obi Stecker IP44 {"NAME":"OBI-Outdoor-Socket2","GPIO":[0,0,0,0,224,32,0,0,576,288,1,1,1,1],"FLAG":0,"BASE":18}
|
||||
Oittm IP44 15A {"NAME":"Oittm Outdoor","GPIO":[576,0,320,0,2688,2656,0,0,224,2592,0,0,0,0],"FLAG":0,"BASE":57}
|
||||
Oittm Outdoor {"NAME":"Oittm Outdoor","GPIO":[32,0,0,0,0,0,0,0,0,0,320,224,1,0],"FLAG":0,"BASE":18}
|
||||
@ -1073,6 +1078,7 @@ Arlec Twin Socket with Energy Meter {"NAME":"Arlec PC287HA","GPIO":[0,32,0,320,
|
||||
Athom 16A {"NAME":"Athom Power Monitoring Plug","GPIO":[0,0,0,32,2720,2656,0,0,2624,544,224,0,0,1],"FLAG":0,"BASE":18}
|
||||
Athom 16A AU {"NAME":"Athom PG05-AU16A","GPIO":[0,0,0,32,2720,2656,0,0,2624,544,224,0,0,0],"FLAG":0,"BASE":1}
|
||||
Athom 16A AU {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A AU V3 {"NAME":"Athom Plug V3","GPIO":[0,0,0,32,0,224,576,0,0,0,0,0,0,0,0,0,0,0,0,0,3104,0],"FLAG":0,"BASE":1}
|
||||
Athom 16A BR V2 {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A Brazil {"NAME":"Athom PG05-BR16A","GPIO":[0,0,0,32,2720,2656,0,0,2624,544,224,0,0,0],"FLAG":0,"BASE":1}
|
||||
Athom 16A EU V2 {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -1082,8 +1088,10 @@ Athom 16A Italy {"NAME":"Athom PG05-IT16A","GPIO":[0,0,0,32,2720,26
|
||||
Athom 16A Switzerland v2 {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A UK {"NAME":"Athom PG04-UK16A","GPIO":[0,0,0,32,2720,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A UK V2 {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A UK V3 {"NAME":"Athom Plug V3","GPIO":[0,0,0,32,0,224,576,0,0,0,0,0,0,0,0,0,0,0,0,0,3104,0],"FLAG":0,"BASE":1}
|
||||
Athom 16A US {"NAME":"Athom PG03-US16A","GPIO":[0,0,0,32,2720,2656,0,0,2624,288,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A US V2 {"NAME":"Athom Plug V2","GPIO":[0,0,0,3104,0,32,0,0,224,576,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 16A US V3 {"NAME":"Athom Plug V3","GPIO":[0,0,0,32,0,224,576,0,0,0,0,0,0,0,0,0,0,0,0,0,3104,0],"FLAG":0,"BASE":1}
|
||||
Atlantis {"NAME":"Atlantis Smart Plug","GPIO":[32,0,0,0,2720,2656,0,0,2624,544,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
Atomi AT1217 {"NAME":"AT1217","GPIO":[0,0,0,0,320,321,0,0,224,32,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Aubess 16A {"NAME":"Aubess 16A Power Monitoring Plug","GPIO":[0,32,0,0,2720,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -1458,6 +1466,7 @@ Nishica SM-PW701I {"NAME":"SM-PW701I","GPIO":[1,1,1,1,1,1,1,1,224,288
|
||||
Nivian {"NAME":"Nivian Smart Socket","GPIO":[0,0,320,0,0,2688,0,0,2624,32,2656,224,0,0],"FLAG":0,"BASE":18}
|
||||
Nous A1 {"NAME":"NOUS A1","GPIO":[320,0,576,0,2656,2720,0,0,2624,32,0,224,0,0],"FLAG":0,"BASE":45}
|
||||
Nous A1T 16A {"NAME":"NOUS A1T","GPIO":[32,0,0,0,2720,2656,0,0,2624,320,224,0,0,0],"FLAG":0,"BASE":49}
|
||||
Nous A8T 10A {"NAME":"NOUS A8T","GPIO":[1,1,320,1,32,1,1,1,1,224,2624,1,1,1,1,1,0,1,1,1,0,1,2656,2720,0,0,0,0,1,1,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
NX-SM112 {"NAME":"NX-SM112v3","GPIO":[0,0,0,0,2720,2656,0,0,576,32,2592,224,0,0],"FLAG":0,"BASE":45}
|
||||
NX-SM200 {"NAME":"NX-SM200","GPIO":[320,0,0,0,0,2720,0,0,224,32,2656,321,2624,0],"FLAG":0,"BASE":18}
|
||||
NX-SM210 {"NAME":"NX-SM210","GPIO":[0,32,0,0,0,0,0,0,0,320,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -1833,6 +1842,7 @@ ZLD64-EU-W {"NAME":"ZLD64-EU-W","GPIO":[0,320,0,32,225,224,0,0
|
||||
|
||||
## Presence Sensor
|
||||
```
|
||||
Athom Human Presence Sensor {"NAME":"Athom PS01 Sensor","GPIO":[32,0,0,0,640,608,0,0,161,3232,160,3200,576,0],"FLAG":0,"BASE":18}
|
||||
Everything Presence Lite {"NAME":"Everything Presence Lite","GPIO":[0,0,0,0,0,0,0,0,0,0,544,0,3232,3200,160,161,0,640,608,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
Everything Presence One {"NAME":"Everything Presence One","GPIO":[0,0,0,0,0,0,0,0,0,3200,3232,160,0,1,1,1,0,0,1,1,0,608,640,0,0,0,0,0,544,161,0,0,0,0,0,0],"FLAG":0,"BASE":1,"CMND":"SO114 1 | SwitchMode1 1 | SwitchMode2 1"}
|
||||
Tuya mmWave {"NAME":"ZY-M100","GPIO":[1,1,1,1,1,1,0,0,1,1,1,1,1,0],"FLAG":0,"BASE":54,"CMND":"SO97 1 | TuyaMCU 99,1 | TuyaMCU 75,104"}
|
||||
@ -2209,7 +2219,7 @@ Rogoei EBE-QPZ04 6.5W 450lm {"NAME":"EBE-QPZ04","GPIO":[0,0,0,0,4032,0,0,0,0,0,
|
||||
Saudio 7W 700lm {"NAME":"X002BU0DOL","GPIO":[0,0,0,0,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
Sengled {"NAME":"Sengled RGBW","GPIO":[0,0,0,0,0,0,0,0,417,416,419,418,0,0],"FLAG":0,"BASE":18}
|
||||
Shelly Duo RGBW 5W 400lm {"NAME":"Shelly Duo RGBW","GPIO":[0,0,0,0,0,419,0,0,417,416,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
Shelly Duo RGBW 9W 800lm {"NAME":"Shelly Duo RGBW","GPIO":[0,0,0,0,0,419,0,0,417,416,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
Shelly Duo RGBW 9W 800lm {"NAME":"Shelly Duo RGBW","GPIO":[0,0,0,0,0,419,0,0,417,416,418,0,0,4736],"FLAG":0,"BASE":18,"CMND":"AdcParam 2, 32000, 1000, 3950|SetOption37 128|SetOption106 1|SetOption107 0|WebButton1 COLOR|WebButton2 WHITE|SetOption42 85|Fade ON|Speed 2|SetOption91 1|Rule1 ON POWER2#state=1 DO POWER1 OFF ENDON ON POWER1#state=1 DO POWER2 OFF ENDON ON Dimmer1#State DO POWER2 OFF ENDON ON Dimmer2#State DO POWER1 OFF ENDON|Rule1 ON"}
|
||||
Smart 810lm {"NAME":"OOOLED 60W RGB","GPIO":[0,0,0,0,418,419,0,0,416,0,417,0,0,4704],"FLAG":0,"BASE":18}
|
||||
SmartLED 9W 400lm {"NAME":"SmartLED RGBWW","GPIO":[0,0,0,0,416,419,0,0,417,420,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
Smartyfi 600lm {"NAME":"SMARTYFI 9W","GPIO":[0,0,0,0,416,419,0,0,417,0,418,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -2266,10 +2276,11 @@ Anmbest 2 Channel Inching Self-locking Switch Module {"NAME":"Generic","GPIO":[
|
||||
Aptinex IOT RelayNode 4 Channel {"NAME":"APTINEX","GPIO":[0,0,1,0,0,0,0,0,224,225,226,227,0,0],"FLAG":0,"BASE":18}
|
||||
Armtronix Quad {"NAME":"Armtronix Wifi Four Relay Board","GPIO":[1,0,0,0,224,1,0,0,225,226,227,0,1,0],"FLAG":0,"BASE":7}
|
||||
Athom 1Ch Inching/Self-locking {"NAME":"Athom R01","GPIO":[1,1,1,1,1,224,1,1,1,1,1,1,576,0],"FLAG":0,"BASE":18}
|
||||
Athom 8Ch Inching/Self-locking 10A {"NAME":"Athom R08","GPIO":[229,1,1,1,230,231,1,1,226,227,225,228,224,0],"FLAG":0,"BASE":18}
|
||||
Athom 8Ch Inching/Self-locking 10A {"NAME":"Athom 8CH Relay Board","GPIO":[0,0,228,0,229,230,1,1,226,227,225,544,1,1152,231,0,0,0,0,0,0,33,32,224,0,0,0,0,35,34,37,36,39,0,0,38],"FLAG":0,"BASE":1}
|
||||
Claudy 5V {"NAME":"CLAUDY","GPIO":[0,0,225,0,0,0,0,0,0,0,0,224,0,0],"FLAG":0,"BASE":18}
|
||||
Devantech 8x16A {"NAME":"ESP32LR88","GPIO":[0,0,231,0,32,35,0,0,229,230,228,0,33,34,36,37,0,38,39,544,0,225,226,227,0,0,0,0,0,224,3232,3200,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
Dingtian 16 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9729,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Dingtian 2 Channel {"NAME":"Dingtian DT-R002","GPIO":[5536,9408,225,9440,0,0,0,0,0,9952,0,0,224,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,576,0,0,0,160,0,0,161],"FLAG":0,"BASE":1}
|
||||
Dingtian 32 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9731,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Dingtian 4 Channel {"NAME":"Dingtian DT-R004","GPIO":[0,9408,225,9440,0,0,0,0,227,9952,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,162,0,163,160,0,0,161],"FLAG":0,"BASE":1}
|
||||
Dingtian 8 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9728,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
@ -2365,6 +2376,10 @@ Connex Smart Indoor {"NAME":"Connex Siren","GPIO":[0,2272,0,2304,0,0,0,
|
||||
NEO Coolcam Temperature and Humidity 3in1 Alarm {"NAME":"Neo Siren 3in1","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
```
|
||||
|
||||
## Smart Meter
|
||||
```
|
||||
```
|
||||
|
||||
## Smoke Sensor
|
||||
```
|
||||
Nedis Smoke Detector {"NAME":"Nedis WIFIDS10WT","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54}
|
||||
@ -2441,7 +2456,6 @@ Connect SmartHome 3 Gang Wall Switch () {"NAME":"CSH-SWTCH3","GPIO":[0,0,288,0,
|
||||
Csmart US-B2 {"NAME":"Csmart US-B2","GPIO":[0,544,0,33,32,0,0,0,0,225,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
Delock WLAN EASY-USB {"NAME":"Delock 11828","GPIO":[0,0,0,32,0,0,0,0,0,576,224,0,0,0],"FLAG":0,"BASE":53}
|
||||
Deta 1 Gang {"NAME":"Deta 1G Switch","GPIO":[0,0,0,0,544,0,0,0,0,224,0,0,64,0],"FLAG":0,"BASE":18}
|
||||
Deta 2 Gang {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,544,0,0,0,65,224,225,0,64,0],"FLAG":0,"BASE":18}
|
||||
Deta 3 Gang {"NAME":"DETA 3G Switch","GPIO":[544,0,0,66,65,224,0,0,226,0,225,0,64,0],"FLAG":0,"BASE":18}
|
||||
Deta 4 Gang {"NAME":"Deta 4G Switch","GPIO":[576,0,0,34,33,224,0,0,226,35,225,227,32,0],"FLAG":0,"BASE":18}
|
||||
DETA Mechanism {"NAME":"Deta 6014HA","GPIO":[0,0,0,0,0,0,0,0,320,0,32,0,224,0],"FLAG":0,"BASE":18}
|
||||
@ -2636,7 +2650,7 @@ Smatrul 5A RF433MHz 4 Gang Touch {"NAME":"Smatrul RF433MHz 3 Gang Touch Switch
|
||||
Smatrul Infrared Sensor {"NAME":"WHS-2","GPIO":[0,0,0,160,288,0,0,0,0,224,0,0,0,0],"FLAG":0,"BASE":18,"CMND":"SwitchMode1 4 | SO13 1"}
|
||||
Sonoff IW101 {"NAME":"Sonoff IW101","GPIO":[32,3072,0,3104,0,0,0,0,224,544,0,0,0,0],"FLAG":0,"BASE":41}
|
||||
Sonoff SwitchMan M5-1C 1 Gang {"NAME":"Sonoff SwitchMan M5-1C-86","GPIO":[32,0,0,0,288,576,0,0,0,0,0,0,0,0,416,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
Sonoff SwitchMan M5-2C 2 Gang {"NAME":"Sonoff SwitchMan 2C","GPIO":[0,0,0,0,32,576,0,0,0,0,0,33,0,0,416,225,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
Sonoff SwitchMan M5-2C 2 Gang {"NAME":"Sonoff SwitchMan 2C","GPIO":[0,0,0,0,32,576,0,0,0,0,0,33,0,0,416,225,0,0,289,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,288],"FLAG":0,"BASE":1}
|
||||
Sonoff SwitchMan M5-3C 3 Gang {"NAME":"Sonoff M5-3C","GPIO":[33,0,0,0,32,576,0,0,0,0,0,34,0,0,416,225,0,0,226,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":1}
|
||||
Sonoff T1 EU 1 Gang {"NAME":"Sonoff T1 1CH","GPIO":[32,1,1,1,0,0,0,0,224,320,0,0,0,0],"FLAG":0,"BASE":28}
|
||||
Sonoff T1 EU 2 Gang {"NAME":"Sonoff T1 2CH","GPIO":[32,1,1,1,0,225,33,0,224,320,0,0,0,0],"FLAG":0,"BASE":29}
|
||||
@ -2742,9 +2756,9 @@ ZUCZUG 3 Gang {"NAME":"2ph105626a x3","GPIO":[0,288,0,32,34,33,0,
|
||||
AGL Módulo Relé 01 Canal {"NAME":"AGL-Basic","GPIO":[0,1,0,0,224,32,0,0,0,0,320,0,0,0],"FLAG":0,"BASE":18}
|
||||
Albohes 2 Channel {"NAME":"Albohes SH-08","GPIO":[0,3200,33,3232,321,320,0,0,224,544,32,0,225,1],"FLAG":0,"BASE":18}
|
||||
Athom 10A {"NAME":"CB01-TAS-1","GPIO":[0,0,0,32,320,0,0,0,0,224,0,0,0,1],"FLAG":0,"BASE":18}
|
||||
Athom 2Ch Inching/Self-locking {"NAME":"Athom R02","GPIO":[1,1,1,1,225,224,1,1,1,1,1,1,576,0],"FLAG":0,"BASE":18}
|
||||
Athom 2Ch Inching/Self-locking {"NAME":"Athom 2CH Relay Board","GPIO":[0,0,0,0,0,0,1,1,0,0,225,544,1,1152,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,32,0,0,33],"FLAG":0,"BASE":1}
|
||||
Athom 3-Way Mini Relay {"NAME":"RS01-TAS-1","GPIO":[0,0,0,32,576,0,0,0,0,224,160,0,0,0],"FLAG":0,"BASE":18}
|
||||
Athom 4Ch Inching/Self-locking 10A {"NAME":"Athom R04","GPIO":[1,1,1,1,32,576,1,1,226,227,225,1,224,0],"FLAG":0,"BASE":18}
|
||||
Athom 4Ch Inching/Self-locking 10A {"NAME":"Athom 4CH Relay Board","GPIO":[0,0,0,0,0,0,1,1,226,227,225,544,1,1152,0,0,0,0,0,0,0,0,0,224,0,0,0,0,0,0,34,35,32,0,0,33],"FLAG":0,"BASE":1}
|
||||
Athom 4Ch Inching/Self-locking 30A {"NAME":"Athom R04-30A","GPIO":[1,1,1,1,32,576,1,1,226,227,225,1,224,0],"FLAG":0,"BASE":18}
|
||||
ATMS1601 230VAC DIN Timer/Switch {"NAME":"ATMS1601","GPIO":[1,1,1,1,544,320,1,1,224,32,1,1,1,1],"FLAG":0,"BASE":18}
|
||||
Aubess Power Monitor Switch 16A {"NAME":"Aubess with (BL0942)","GPIO":[0,3200,0,7520,0,0,0,0,160,0,224,0,0,0],"FLAG":0,"BASE":18}
|
||||
@ -2782,8 +2796,11 @@ Moes {"NAME":"Moes MS-104B","GPIO":[0,0,32,0,480,0,0,0,1
|
||||
Moes 10A {"NAME":"Moes MS-101","GPIO":[0,0,0,0,0,320,0,0,224,32,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
Moes Mini 3 Gang 1/2 Way {"NAME":"Moes MS-104C","GPIO":[0,0,0,34,32,33,0,0,224,225,226,0,0,0],"FLAG":0,"BASE":18}
|
||||
Nedis 10A {"NAME":"Nedis WIFIPS10WT","GPIO":[0,0,0,0,224,0,0,0,32,321,0,288,0,0],"FLAG":0,"BASE":18}
|
||||
Nous 1 Channel {"NAME":"NOUS B1T","GPIO":[544,0,1,0,32,160,1,1,224,0,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Nous 1 Channel Touch {"NAME":"NOUS L1T","GPIO":[544,0,1,32,0,0,0,0,0,224,288,0,0,0],"FLAG":0,"BASE":1}
|
||||
Nous 1/2 Channel {"NAME":"NOUS L13T Smart Switch Module","GPIO":[1,161,1,160,225,224,1,1,544,1,32,1,1,1],"FLAG":0,"BASE":18}
|
||||
Nous 2 Channel {"NAME":"NOUS B2T","GPIO":[544,3200,1,8160,32,160,1,1,224,0,0,1,1,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Nous 2 Channel / Curtain {"NAME":"NOUS B3T","GPIO":[544,3200,1,8128,32,160,1,1,224,225,0,1,1,1,161,1,0,1,1,1,0,1,1,1,0,0,0,0,1,1,1,0,1,0,0,1],"FLAG":0,"BASE":1}
|
||||
Nous 2 Channel Touch {"NAME":"NOUS L2T","GPIO":[544,289,1,32,225,33,0,0,0,224,288,0,0,0],"FLAG":0,"BASE":1}
|
||||
Nova Digital Basic 1 MS101 {"NAME":"NovaDigBasic1","GPIO":[0,1,0,1,320,0,0,0,224,32,0,0,0,0],"FLAG":0,"BASE":18}
|
||||
ONiOFF Smart Switch {"NAME":"ONOFF SmartSwitch","GPIO":[1,320,1,1,1,32,0,0,224,1,1,0,0,0],"FLAG":0,"BASE":1}
|
||||
@ -2937,6 +2954,10 @@ Xenon {"NAME":"Xenon SM-PM801-K1","GPIO":[0,320,0,32,2720
|
||||
Xenon 2AC 1USB {"NAME":"Xenon SM-PW801-U1","GPIO":[0,0,0,0,288,32,0,0,224,0,225,0,226,0],"FLAG":0,"BASE":18}
|
||||
```
|
||||
|
||||
## Wall Switch
|
||||
```
|
||||
```
|
||||
|
||||
## Water Sensor
|
||||
```
|
||||
Nedis SmartLife Water Detector {"NAME":"Nedis WIFIDW10WT","GPIO":[0,2272,0,2304,0,0,0,0,0,0,0,0,0,0],"FLAG":0,"BASE":54,"CMND":"TuyaMCU 51,21"}
|
||||
|
@ -177,6 +177,22 @@ char * ToBinary(uint32_t value, char *str, int32_t digits) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char * U64toStr(uint64_t value, char *str) {
|
||||
// str must be at least 24 bytes long
|
||||
uint32_t i = 23;
|
||||
str[--i] = 0; // end of string
|
||||
do {
|
||||
uint64_t m = value;
|
||||
value /= 10;
|
||||
char c = m - 10 * value;
|
||||
str[--i] = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while (value);
|
||||
if (i) {
|
||||
memmove(str, str +i, 23 -i);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char * U64toHex(uint64_t value, char *str, uint32_t zeroleads) {
|
||||
// str must be at least 17 bytes long
|
||||
str[16] = 0; // end of string
|
||||
@ -310,6 +326,7 @@ int32_t ext_vsnprintf_P(char * out_buf, size_t buf_len, const char * fmt_P, va_l
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'B': // Pointer to SBuffer
|
||||
{
|
||||
if (cur_val < min_valid_ptr) { new_val_str = ext_invalid_mem; }
|
||||
@ -326,6 +343,7 @@ int32_t ext_vsnprintf_P(char * out_buf, size_t buf_len, const char * fmt_P, va_l
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// '%_b' outputs a uint32_t to binary
|
||||
// '%8_b' outputs a uint8_t to binary
|
||||
case 'b': // Binary, decimals indicates the zero prefill
|
||||
@ -416,6 +434,7 @@ int32_t ext_vsnprintf_P(char * out_buf, size_t buf_len, const char * fmt_P, va_l
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// '%_X' outputs a 64 bits unsigned int to uppercase HEX with 16 digits
|
||||
case 'X': // input is `uint64_t*`, printed as 16 hex digits (no prefix 0x)
|
||||
{
|
||||
@ -429,6 +448,20 @@ int32_t ext_vsnprintf_P(char * out_buf, size_t buf_len, const char * fmt_P, va_l
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// '%_U' outputs a 64 bits unsigned int to decimal
|
||||
case 'U': // input is `uint64_t*`, printed as decimal
|
||||
{
|
||||
if (cur_val < min_valid_ptr) { new_val_str = ext_invalid_mem; }
|
||||
else {
|
||||
U64toStr(*(uint64_t*)cur_val, hex);
|
||||
new_val_str = copyStr(hex);
|
||||
if (new_val_str == nullptr) { goto free_allocs; }
|
||||
allocs[alloc_idx++] = new_val_str;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
*cur_val_ptr = new_val_str;
|
||||
*fmt = 's'; // replace `%_X` with `%0s` to display a string instead
|
||||
|
@ -66,11 +66,14 @@ void test_ext_snprintf_P(void) {
|
||||
Serial.printf("--> out=%s\n", c);
|
||||
ext_snprintf_P(c, sizeof(c), "Float default=%*_f, int(3)=%*_f, int(3)=%*_f, int(3)=%*_f, 6dec=%*_f", 1, &fpi, 4, &f3, -4, &f3, -4, &f31, -8, &fpi);
|
||||
Serial.printf("--> out=%s\n", c);
|
||||
uint64_t u641 = 0x1122334455667788LL;
|
||||
uint64_t u642 = 0x0123456789ABCDEFLL;
|
||||
uint64_t u643 = 0xFEDCBA9876543210LL;
|
||||
|
||||
uint64_t u641 = 0x1122334455667788LL; // 1234605616436508552
|
||||
uint64_t u642 = 0x0123456789ABCDEFLL; // 81985529216486895
|
||||
uint64_t u643 = 0xFEDCBA9876543210LL; // 18364758544493064720
|
||||
ext_snprintf_P(c, sizeof(c), "Int64 0x%_X 0x%_X 0x%_X", &u641, &u642, &u643);
|
||||
Serial.printf("--> out=%s\n", c);
|
||||
ext_snprintf_P(c, sizeof(c), "Int64 decimal %_U %_U %_U", &u641, &u642, &u643);
|
||||
Serial.printf("--> out=%s\n", c);
|
||||
|
||||
// ext_snprintf_P(c, sizeof(c), "Float default=%*_f, int(3)=%*_f, int(3)=%*_f, int(3)=%*_f, 6dec=%*_f", &fpi, &f3, &f3, &f31, &fpi);
|
||||
|
||||
|
@ -168,15 +168,25 @@ void TasmotaSerial::Esp32Begin(void) {
|
||||
if (m_speed <= 9600) {
|
||||
// At 9600, 10 chars are ~10ms
|
||||
uart_set_rx_full_threshold(m_uart, 10);
|
||||
} else {
|
||||
// At 19200, 120 chars are ~60ms
|
||||
// At 76800, 120 chars are ~15ms
|
||||
uart_set_rx_full_threshold(m_uart, 120);
|
||||
}
|
||||
/*
|
||||
} else if (m_speed < 115200) {
|
||||
// At 19200, 120 chars are ~60ms
|
||||
// At 76800, 120 chars are ~15ms
|
||||
uart_set_rx_full_threshold(m_uart, 120);
|
||||
} else {
|
||||
} else if (m_speed == 115200) {
|
||||
// At 115200, 256 chars are ~20ms
|
||||
// Zigbee requires to keep frames together, i.e. 256 bytes max
|
||||
uart_set_rx_full_threshold(m_uart, 256);
|
||||
} else {
|
||||
// At even higher speeds set 75% of the buffer
|
||||
uart_set_rx_full_threshold(m_uart, serial_buffer_size * 3 / 4);
|
||||
}
|
||||
*/
|
||||
// For bitrate below 115200, set the Rx time out to 6 chars instead of the default 10
|
||||
if (m_speed < 115200) {
|
||||
// At 76800 the timeout is ~1ms
|
||||
|
128
lib/default/base64-1.1.1/src/base64.cpp
Normal file
128
lib/default/base64-1.1.1/src/base64.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
/**
|
||||
* Base64 encoding and decoding of strings. Uses '+' for 62, '/' for 63, '=' for padding
|
||||
*/
|
||||
|
||||
#include "base64.hpp"
|
||||
|
||||
unsigned char binary_to_base64(unsigned char v) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if(v < 26) return v + 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if(v < 52) return v + 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if(v < 62) return v - 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(v == 62) return '+';
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(v == 63) return '/';
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
unsigned char base64_to_binary(unsigned char c) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if('A' <= c && c <= 'Z') return c - 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if('a' <= c && c <= 'z') return c - 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if('0' <= c && c <= '9') return c + 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(c == '+') return 62;
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(c == '/') return 63;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
unsigned int encode_base64_length(unsigned int input_length) {
|
||||
return (input_length + 2)/3*4;
|
||||
}
|
||||
|
||||
unsigned int decode_base64_length(unsigned char input[]) {
|
||||
unsigned char *start = input;
|
||||
|
||||
while(base64_to_binary(input[0]) < 64) {
|
||||
++input;
|
||||
}
|
||||
|
||||
unsigned int input_length = input - start;
|
||||
|
||||
unsigned int output_length = input_length/4*3;
|
||||
|
||||
switch(input_length % 4) {
|
||||
default: return output_length;
|
||||
case 2: return output_length + 1;
|
||||
case 3: return output_length + 2;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
|
||||
unsigned int full_sets = input_length/3;
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 0; i < full_sets; ++i) {
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
|
||||
output[3] = binary_to_base64( input[2] & 0x3F);
|
||||
|
||||
input += 3;
|
||||
output += 4;
|
||||
}
|
||||
|
||||
switch(input_length % 3) {
|
||||
case 0:
|
||||
output[0] = '\0';
|
||||
break;
|
||||
case 1:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4);
|
||||
output[2] = '=';
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
case 2:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
return encode_base64_length(input_length);
|
||||
}
|
||||
|
||||
unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
|
||||
unsigned int output_length = decode_base64_length(input);
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 2; i < output_length; i += 3) {
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
|
||||
|
||||
input += 4;
|
||||
output += 3;
|
||||
}
|
||||
|
||||
switch(output_length % 3) {
|
||||
case 1:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
break;
|
||||
case 2:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return output_length;
|
||||
}
|
@ -69,127 +69,4 @@ unsigned int encode_base64(unsigned char input[], unsigned int input_length, uns
|
||||
*/
|
||||
unsigned int decode_base64(unsigned char input[], unsigned char output[]);
|
||||
|
||||
unsigned char binary_to_base64(unsigned char v) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if(v < 26) return v + 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if(v < 52) return v + 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if(v < 62) return v - 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(v == 62) return '+';
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(v == 63) return '/';
|
||||
|
||||
return 64;
|
||||
}
|
||||
|
||||
unsigned char base64_to_binary(unsigned char c) {
|
||||
// Capital letters - 'A' is ascii 65 and base64 0
|
||||
if('A' <= c && c <= 'Z') return c - 'A';
|
||||
|
||||
// Lowercase letters - 'a' is ascii 97 and base64 26
|
||||
if('a' <= c && c <= 'z') return c - 71;
|
||||
|
||||
// Digits - '0' is ascii 48 and base64 52
|
||||
if('0' <= c && c <= '9') return c + 4;
|
||||
|
||||
// '+' is ascii 43 and base64 62
|
||||
if(c == '+') return 62;
|
||||
|
||||
// '/' is ascii 47 and base64 63
|
||||
if(c == '/') return 63;
|
||||
|
||||
return 255;
|
||||
}
|
||||
|
||||
unsigned int encode_base64_length(unsigned int input_length) {
|
||||
return (input_length + 2)/3*4;
|
||||
}
|
||||
|
||||
unsigned int decode_base64_length(unsigned char input[]) {
|
||||
unsigned char *start = input;
|
||||
|
||||
while(base64_to_binary(input[0]) < 64) {
|
||||
++input;
|
||||
}
|
||||
|
||||
unsigned int input_length = input - start;
|
||||
|
||||
unsigned int output_length = input_length/4*3;
|
||||
|
||||
switch(input_length % 4) {
|
||||
default: return output_length;
|
||||
case 2: return output_length + 1;
|
||||
case 3: return output_length + 2;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
|
||||
unsigned int full_sets = input_length/3;
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 0; i < full_sets; ++i) {
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
|
||||
output[3] = binary_to_base64( input[2] & 0x3F);
|
||||
|
||||
input += 3;
|
||||
output += 4;
|
||||
}
|
||||
|
||||
switch(input_length % 3) {
|
||||
case 0:
|
||||
output[0] = '\0';
|
||||
break;
|
||||
case 1:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4);
|
||||
output[2] = '=';
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
case 2:
|
||||
output[0] = binary_to_base64( input[0] >> 2);
|
||||
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
|
||||
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
|
||||
output[3] = '=';
|
||||
output[4] = '\0';
|
||||
break;
|
||||
}
|
||||
|
||||
return encode_base64_length(input_length);
|
||||
}
|
||||
|
||||
unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
|
||||
unsigned int output_length = decode_base64_length(input);
|
||||
|
||||
// While there are still full sets of 24 bits...
|
||||
for(unsigned int i = 2; i < output_length; i += 3) {
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
|
||||
|
||||
input += 4;
|
||||
output += 3;
|
||||
}
|
||||
|
||||
switch(output_length % 3) {
|
||||
case 1:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
break;
|
||||
case 2:
|
||||
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
|
||||
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
|
||||
break;
|
||||
}
|
||||
|
||||
return output_length;
|
||||
}
|
||||
|
||||
#endif // ifndef
|
||||
|
@ -18,7 +18,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma GCC optimize ("O3")
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
#include "AudioGeneratorAAC.h"
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
||||
#define AAC_ENABLE_SBR 1
|
||||
#endif
|
||||
|
||||
#pragma GCC optimize ("O3")
|
||||
#pragma GCC optimize ("Os")
|
||||
|
||||
#include "aacdec.h"
|
||||
#include "statname.h"
|
||||
|
@ -482,7 +482,7 @@ static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
|
||||
int pitch_index;
|
||||
VARDECL( opus_val16, lp_pitch_buf );
|
||||
SAVE_STACK;
|
||||
opus_val16 *lp_pitch_buf = (opus_val16*)malloc((DECODE_BUFFER_SIZE>>1) * sizeof(opus_val16)); //ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
|
||||
ALLOC( lp_pitch_buf, DECODE_BUFFER_SIZE>>1, opus_val16 );
|
||||
pitch_downsample(decode_mem, lp_pitch_buf,
|
||||
DECODE_BUFFER_SIZE, C, arch);
|
||||
pitch_search(lp_pitch_buf+(PLC_PITCH_LAG_MAX>>1), lp_pitch_buf,
|
||||
@ -490,7 +490,6 @@ static int celt_plc_pitch_search(celt_sig *decode_mem[2], int C, int arch)
|
||||
PLC_PITCH_LAG_MAX-PLC_PITCH_LAG_MIN, &pitch_index, arch);
|
||||
pitch_index = PLC_PITCH_LAG_MAX-pitch_index;
|
||||
RESTORE_STACK;
|
||||
free(lp_pitch_buf);
|
||||
return pitch_index;
|
||||
}
|
||||
|
||||
|
@ -207,4 +207,3 @@
|
||||
# define __restrict__
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -171,7 +171,7 @@ extern "C" {
|
||||
#define OPUS_GET_IN_DTX_REQUEST 4049
|
||||
|
||||
/** Defines for the presence of extended APIs. */
|
||||
#define OPUS_HAVE_OPUS_PROJECTION_H
|
||||
// #define OPUS_HAVE_OPUS_PROJECTION_H
|
||||
|
||||
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
|
||||
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
|
||||
|
@ -239,30 +239,21 @@ opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus
|
||||
|
||||
int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
|
||||
{
|
||||
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
|
||||
OpusRepacketizer rp;
|
||||
opus_int32 ret;
|
||||
if (len < 1) {
|
||||
free(rp);
|
||||
if (len < 1)
|
||||
return OPUS_BAD_ARG;
|
||||
}
|
||||
if (len==new_len) {
|
||||
free(rp);
|
||||
if (len==new_len)
|
||||
return OPUS_OK;
|
||||
}
|
||||
else if (len > new_len) {
|
||||
free(rp);
|
||||
else if (len > new_len)
|
||||
return OPUS_BAD_ARG;
|
||||
}
|
||||
opus_repacketizer_init(rp);
|
||||
opus_repacketizer_init(&rp);
|
||||
/* Moving payload to the end of the packet so we can do in-place padding */
|
||||
OPUS_MOVE(data+new_len-len, data, len);
|
||||
ret = opus_repacketizer_cat(rp, data+new_len-len, len);
|
||||
if (ret != OPUS_OK) {
|
||||
free(rp);
|
||||
ret = opus_repacketizer_cat(&rp, data+new_len-len, len);
|
||||
if (ret != OPUS_OK)
|
||||
return ret;
|
||||
}
|
||||
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, new_len, 0, 1);
|
||||
free(rp);
|
||||
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, new_len, 0, 1);
|
||||
if (ret > 0)
|
||||
return OPUS_OK;
|
||||
else
|
||||
@ -271,20 +262,15 @@ int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
|
||||
|
||||
opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
|
||||
{
|
||||
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
|
||||
OpusRepacketizer rp;
|
||||
opus_int32 ret;
|
||||
if (len < 1) {
|
||||
free(rp);
|
||||
if (len < 1)
|
||||
return OPUS_BAD_ARG;
|
||||
}
|
||||
opus_repacketizer_init(rp);
|
||||
ret = opus_repacketizer_cat(rp, data, len);
|
||||
if (ret < 0) {
|
||||
free(rp);
|
||||
opus_repacketizer_init(&rp);
|
||||
ret = opus_repacketizer_cat(&rp, data, len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, len, 0, 0);
|
||||
free(rp);
|
||||
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, data, len, 0, 0);
|
||||
celt_assert(ret > 0 && ret <= len);
|
||||
return ret;
|
||||
}
|
||||
@ -326,14 +312,12 @@ opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, in
|
||||
unsigned char toc;
|
||||
opus_int16 size[48];
|
||||
opus_int32 packet_offset;
|
||||
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
|
||||
OpusRepacketizer rp;
|
||||
unsigned char *dst;
|
||||
opus_int32 dst_len;
|
||||
|
||||
if (len < 1){
|
||||
free(rp);
|
||||
if (len < 1)
|
||||
return OPUS_BAD_ARG;
|
||||
}
|
||||
dst = data;
|
||||
dst_len = 0;
|
||||
/* Unpad all frames */
|
||||
@ -341,34 +325,25 @@ opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, in
|
||||
{
|
||||
opus_int32 ret;
|
||||
int self_delimited = s!=nb_streams-1;
|
||||
if (len<=0) {
|
||||
free(rp);
|
||||
if (len<=0)
|
||||
return OPUS_INVALID_PACKET;
|
||||
}
|
||||
opus_repacketizer_init(rp);
|
||||
opus_repacketizer_init(&rp);
|
||||
ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
|
||||
size, NULL, &packet_offset);
|
||||
if (ret<0) {
|
||||
free(rp);
|
||||
if (ret<0)
|
||||
return ret;
|
||||
}
|
||||
ret = opus_repacketizer_cat_impl(rp, data, packet_offset, self_delimited);
|
||||
if (ret < 0) {
|
||||
free(rp);
|
||||
ret = opus_repacketizer_cat_impl(&rp, data, packet_offset, self_delimited);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, dst, len, self_delimited, 0);
|
||||
if (ret < 0) {
|
||||
free(rp);
|
||||
ret = opus_repacketizer_out_range_impl(&rp, 0, rp.nb_frames, dst, len, self_delimited, 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
dst_len += ret;
|
||||
dst += ret;
|
||||
data += packet_offset;
|
||||
len -= packet_offset;
|
||||
}
|
||||
free(rp);
|
||||
return dst_len;
|
||||
}
|
||||
|
||||
|
@ -80,11 +80,10 @@ void silk_NLSF2A(
|
||||
};
|
||||
const unsigned char *ordering;
|
||||
opus_int k, i, dd;
|
||||
opus_int32 *cos_LSF_QA = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC );
|
||||
opus_int32 *P = (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC / 2 + 1));
|
||||
opus_int32 *Q= (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC / 2 + 1));
|
||||
opus_int32 cos_LSF_QA[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ], Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
|
||||
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
|
||||
opus_int32 *a32_QA1 = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC );
|
||||
opus_int32 a32_QA1[ SILK_MAX_ORDER_LPC ];
|
||||
|
||||
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
|
||||
celt_assert( d==10 || d==16 );
|
||||
@ -138,9 +137,5 @@ void silk_NLSF2A(
|
||||
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
|
||||
}
|
||||
}
|
||||
free(cos_LSF_QA);
|
||||
free(P);
|
||||
free(Q);
|
||||
free(a32_QA1);
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,12 @@ void silk_burg_modified_c(
|
||||
opus_int k, n, s, lz, rshifts, reached_max_gain;
|
||||
opus_int32 C0, num, nrg, rc_Q31, invGain_Q30, Atmp_QA, Atmp1, tmp1, tmp2, x1, x2;
|
||||
const opus_int16 *x_ptr;
|
||||
opus_int32 *C_first_row = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC);
|
||||
opus_int32 *C_last_row = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC);
|
||||
opus_int32 *Af_QA = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC);
|
||||
opus_int32 *CAf = (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC+1));
|
||||
opus_int32 *CAb = (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC+1));
|
||||
opus_int32 *xcorr = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC);
|
||||
opus_int32 C_first_row[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 C_last_row[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 Af_QA[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int32 CAf[ SILK_MAX_ORDER_LPC + 1 ];
|
||||
opus_int32 CAb[ SILK_MAX_ORDER_LPC + 1 ];
|
||||
opus_int32 xcorr[ SILK_MAX_ORDER_LPC ];
|
||||
opus_int64 C0_64;
|
||||
|
||||
celt_assert( subfr_length * nb_subfr <= MAX_FRAME_SIZE );
|
||||
@ -277,10 +277,4 @@ void silk_burg_modified_c(
|
||||
*res_nrg = silk_SMLAWW( nrg, silk_SMMUL( SILK_FIX_CONST( FIND_LPC_COND_FAC, 32 ), C0 ), -tmp1 );/* Q( -rshifts ) */
|
||||
*res_nrg_Q = -rshifts;
|
||||
}
|
||||
free(C_first_row);
|
||||
free(C_last_row);
|
||||
free(Af_QA);
|
||||
free(CAf);
|
||||
free(CAb);
|
||||
free(xcorr);
|
||||
}
|
||||
|
@ -49,8 +49,8 @@ void silk_warped_autocorrelation_FIX_c(
|
||||
{
|
||||
opus_int n, i, lsh;
|
||||
opus_int32 tmp1_QS, tmp2_QS;
|
||||
opus_int32 *state_QS = (opus_int32*)calloc(MAX_SHAPE_LPC_ORDER + 1, sizeof(opus_int32));
|
||||
opus_int64 *corr_QC = (opus_int64*)calloc(MAX_SHAPE_LPC_ORDER + 1, sizeof(opus_int64));
|
||||
opus_int32 state_QS[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
|
||||
opus_int64 corr_QC[ MAX_SHAPE_LPC_ORDER + 1 ] = { 0 };
|
||||
|
||||
/* Order must be even */
|
||||
celt_assert( ( order & 1 ) == 0 );
|
||||
@ -88,7 +88,5 @@ void silk_warped_autocorrelation_FIX_c(
|
||||
}
|
||||
}
|
||||
silk_assert( corr_QC[ 0 ] >= 0 ); /* If breaking, decrease QC*/
|
||||
free(state_QS);
|
||||
free(corr_QC);
|
||||
}
|
||||
#endif /* OVERRIDE_silk_warped_autocorrelation_FIX_c */
|
||||
|
@ -48,8 +48,7 @@ void silk_resampler_down2_3(
|
||||
opus_int32 *buf_ptr;
|
||||
SAVE_STACK;
|
||||
|
||||
// ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 );
|
||||
opus_int32 *buf = (opus_int32*)malloc((RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR) * sizeof(opus_int32));
|
||||
ALLOC( buf, RESAMPLER_MAX_BATCH_SIZE_IN + ORDER_FIR, opus_int32 );
|
||||
|
||||
/* Copy buffered samples to start of buffer */
|
||||
silk_memcpy( buf, S, ORDER_FIR * sizeof( opus_int32 ) );
|
||||
@ -100,6 +99,5 @@ void silk_resampler_down2_3(
|
||||
|
||||
/* Copy last part of filtered signal to the state for the next call */
|
||||
silk_memcpy( S, &buf[ nSamplesIn ], ORDER_FIR * sizeof( opus_int32 ) );
|
||||
free(buf);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
35
lib/lib_audio/ESP8266Audio/src/libwebm/.clang-format
Normal file
35
lib/lib_audio/ESP8266Audio/src/libwebm/.clang-format
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Google
|
||||
AlignTrailingComments: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
|
||||
# A separate 'Other libraries' grouping is added before libwebm's headers for
|
||||
# gtest and gmock includes. This is based on the suggested grouping in the
|
||||
# Google C++ Style Guide:
|
||||
# https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes
|
||||
# The other categories come from `clang-format-14 --dump-config --style=Google`.
|
||||
# See the clang-format documentation for more information on this option:
|
||||
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html#includecategories
|
||||
IncludeCategories:
|
||||
- Regex: '^<ext/.*\.h>'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*\.h>'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^<.*'
|
||||
Priority: 2
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^((<|")(gtest|gmock)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 4
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
6
lib/lib_audio/ESP8266Audio/src/libwebm/.gitattributes
vendored
Normal file
6
lib/lib_audio/ESP8266Audio/src/libwebm/.gitattributes
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.sln eol=crlf
|
||||
*.vcproj eol=crlf
|
||||
*.vsprops eol=crlf
|
||||
*.vcxproj eol=crlf
|
||||
*.mkv -text -diff
|
||||
*.webm -text -diff
|
36
lib/lib_audio/ESP8266Audio/src/libwebm/.gitignore
vendored
Normal file
36
lib/lib_audio/ESP8266Audio/src/libwebm/.gitignore
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
*.MKV
|
||||
*.a
|
||||
*.cmake
|
||||
*.d
|
||||
*.exe
|
||||
*.mkv
|
||||
*.ncb
|
||||
*.o
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.so*
|
||||
*.suo
|
||||
*.swp
|
||||
*.user
|
||||
*~
|
||||
.vscode
|
||||
/*.webm
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
Debug
|
||||
Makefile
|
||||
Release
|
||||
core
|
||||
dumpvtt
|
||||
ipch
|
||||
mkvmuxer_sample
|
||||
mkvmuxer_tests
|
||||
mkvparser_sample
|
||||
mkvparser_tests
|
||||
vp9_header_parser_tests
|
||||
vp9_level_stats_tests
|
||||
vttdemux
|
||||
webm2pes
|
||||
webm2pes_tests
|
||||
webm2ts
|
||||
webm_info
|
6
lib/lib_audio/ESP8266Audio/src/libwebm/.mailmap
Normal file
6
lib/lib_audio/ESP8266Audio/src/libwebm/.mailmap
Normal file
@ -0,0 +1,6 @@
|
||||
Hui Su <huisu@google.com>
|
||||
Matthew Heaney <matthewjheaney@google.com>
|
||||
Neil Birkbeck <birkbeck@google.com>
|
||||
Patrik Carlsson <patrik2.carlsson@sonymobile.com>
|
||||
Roberto Alanis Baez <alanisbaez@google.com>
|
||||
Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org>
|
441
lib/lib_audio/ESP8266Audio/src/libwebm/.pylintrc
Normal file
441
lib/lib_audio/ESP8266Audio/src/libwebm/.pylintrc
Normal file
@ -0,0 +1,441 @@
|
||||
# This Pylint rcfile contains a best-effort configuration to uphold the
|
||||
# best-practices and style described in the Google Python style guide:
|
||||
# https://google.github.io/styleguide/pyguide.html
|
||||
#
|
||||
# Its canonical open-source location is:
|
||||
# https://google.github.io/styleguide/pylintrc
|
||||
|
||||
[MASTER]
|
||||
|
||||
# Files or directories to be skipped. They should be base names, not paths.
|
||||
ignore=third_party
|
||||
|
||||
# Files or directories matching the regex patterns are skipped. The regex
|
||||
# matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=no
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
# Use multiple processes to speed up Pylint.
|
||||
jobs=4
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
|
||||
confidence=
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
#enable=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once).You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
disable=abstract-method,
|
||||
apply-builtin,
|
||||
arguments-differ,
|
||||
attribute-defined-outside-init,
|
||||
backtick,
|
||||
bad-option-value,
|
||||
basestring-builtin,
|
||||
buffer-builtin,
|
||||
c-extension-no-member,
|
||||
consider-using-enumerate,
|
||||
cmp-builtin,
|
||||
cmp-method,
|
||||
coerce-builtin,
|
||||
coerce-method,
|
||||
delslice-method,
|
||||
div-method,
|
||||
duplicate-code,
|
||||
eq-without-hash,
|
||||
execfile-builtin,
|
||||
file-builtin,
|
||||
filter-builtin-not-iterating,
|
||||
fixme,
|
||||
getslice-method,
|
||||
global-statement,
|
||||
hex-method,
|
||||
idiv-method,
|
||||
implicit-str-concat-in-sequence,
|
||||
import-error,
|
||||
import-self,
|
||||
import-star-module-level,
|
||||
inconsistent-return-statements,
|
||||
input-builtin,
|
||||
intern-builtin,
|
||||
invalid-str-codec,
|
||||
locally-disabled,
|
||||
long-builtin,
|
||||
long-suffix,
|
||||
map-builtin-not-iterating,
|
||||
misplaced-comparison-constant,
|
||||
missing-function-docstring,
|
||||
metaclass-assignment,
|
||||
next-method-called,
|
||||
next-method-defined,
|
||||
no-absolute-import,
|
||||
no-else-break,
|
||||
no-else-continue,
|
||||
no-else-raise,
|
||||
no-else-return,
|
||||
no-init, # added
|
||||
no-member,
|
||||
no-name-in-module,
|
||||
no-self-use,
|
||||
nonzero-method,
|
||||
oct-method,
|
||||
old-division,
|
||||
old-ne-operator,
|
||||
old-octal-literal,
|
||||
old-raise-syntax,
|
||||
parameter-unpacking,
|
||||
print-statement,
|
||||
raising-string,
|
||||
range-builtin-not-iterating,
|
||||
raw_input-builtin,
|
||||
rdiv-method,
|
||||
reduce-builtin,
|
||||
relative-import,
|
||||
reload-builtin,
|
||||
round-builtin,
|
||||
setslice-method,
|
||||
signature-differs,
|
||||
standarderror-builtin,
|
||||
suppressed-message,
|
||||
sys-max-int,
|
||||
too-few-public-methods,
|
||||
too-many-ancestors,
|
||||
too-many-arguments,
|
||||
too-many-boolean-expressions,
|
||||
too-many-branches,
|
||||
too-many-instance-attributes,
|
||||
too-many-locals,
|
||||
too-many-nested-blocks,
|
||||
too-many-public-methods,
|
||||
too-many-return-statements,
|
||||
too-many-statements,
|
||||
trailing-newlines,
|
||||
unichr-builtin,
|
||||
unicode-builtin,
|
||||
unnecessary-pass,
|
||||
unpacking-in-except,
|
||||
useless-else-on-loop,
|
||||
useless-object-inheritance,
|
||||
useless-suppression,
|
||||
using-cmp-argument,
|
||||
wrong-import-order,
|
||||
xrange-builtin,
|
||||
zip-builtin-not-iterating,
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, msvs
|
||||
# (visual studio) and html. You can also give a reporter class, eg
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]". This option is deprecated
|
||||
# and it will be removed in Pylint 2.0.
|
||||
files-output=no
|
||||
|
||||
# Tells whether to display a full report or only the messages
|
||||
reports=no
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note). You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details
|
||||
#msg-template=
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=main,_,PRESUBMIT
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name
|
||||
include-naming-hint=no
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
property-classes=abc.abstractproperty,cached_property.cached_property,cached_property.threaded_cached_property,cached_property.cached_property_with_ttl,cached_property.threaded_cached_property_with_ttl
|
||||
|
||||
# Regular expression matching correct function names
|
||||
function-rgx=^(?:(?P<exempt>setUp|tearDown|setUpModule|tearDownModule)|(?P<camel_case>_?[A-Z][a-zA-Z0-9]*)|(?P<snake_case>_?[a-z][a-z0-9_]*))$
|
||||
|
||||
# Regular expression matching correct variable names
|
||||
variable-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct constant names
|
||||
const-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||
|
||||
# Regular expression matching correct attribute names
|
||||
attr-rgx=^_{0,2}[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct argument names
|
||||
argument-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct class attribute names
|
||||
class-attribute-rgx=^(_?[A-Z][A-Z0-9_]*|__[a-z0-9_]+__|_?[a-z][a-z0-9_]*)$
|
||||
|
||||
# Regular expression matching correct inline iteration names
|
||||
inlinevar-rgx=^[a-z][a-z0-9_]*$
|
||||
|
||||
# Regular expression matching correct class names
|
||||
class-rgx=^_?[A-Z][a-zA-Z0-9]*$
|
||||
|
||||
# Regular expression matching correct module names
|
||||
module-rgx=^(_?[a-z][a-z0-9_]*|__init__)$
|
||||
|
||||
# Regular expression matching correct method names
|
||||
method-rgx=(?x)^(?:(?P<exempt>_[a-z0-9_]+__|runTest|setUp|tearDown|setUpTestCase|tearDownTestCase|setupSelf|tearDownClass|setUpClass|(test|assert)_*[A-Z0-9][a-zA-Z0-9_]*|next)|(?P<camel_case>_{0,2}[A-Z][a-zA-Z0-9_]*)|(?P<snake_case>_{0,2}[a-z][a-z0-9_]*))$
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=(__.*__|main|test.*|.*test|.*Test)$
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=10
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager,contextlib2.contextmanager
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis. It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=80
|
||||
|
||||
# TODO(https://github.com/PyCQA/pylint/issues/3352): Direct pylint to exempt
|
||||
# lines made too long by directives to pytype.
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=(?x)(
|
||||
^\s*(\#\ )?<?https?://\S+>?$|
|
||||
^\s*(from\s+\S+\s+)?import\s+.+$)
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=yes
|
||||
|
||||
# List of optional constructs for which whitespace checking is disabled. `dict-
|
||||
# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}.
|
||||
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
|
||||
# `empty-line` allows space-only lines.
|
||||
no-space-check=
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=99999
|
||||
|
||||
# String used as indentation unit. The internal Google style guide mandates 2
|
||||
# spaces. Google's externaly-published style guide says 4, consistent with
|
||||
# PEP 8. Here, we use 2 spaces, for conformity with many open-sourced Google
|
||||
# projects (like TensorFlow).
|
||||
indent-string=' '
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=TODO
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=yes
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expectedly
|
||||
# not used).
|
||||
dummy-variables-rgx=^\*{0,2}(_$|unused_|dummy_)
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,_cb
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six,six.moves,past.builtins,future.builtins,functools
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format
|
||||
logging-modules=logging,absl.logging,tensorflow.io.logging
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Ignore imports when computing similarities.
|
||||
ignore-imports=no
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it working
|
||||
# install python-enchant package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to indicated private dictionary in
|
||||
# --spelling-private-dict-file option instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,
|
||||
TERMIOS,
|
||||
Bastion,
|
||||
rexec,
|
||||
sets
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report RP0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report RP0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant, absl
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls,
|
||||
class_
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=mcs
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "Exception"
|
||||
overgeneral-exceptions=StandardError,
|
||||
Exception,
|
||||
BaseException
|
5
lib/lib_audio/ESP8266Audio/src/libwebm/AUTHORS.TXT
Normal file
5
lib/lib_audio/ESP8266Audio/src/libwebm/AUTHORS.TXT
Normal file
@ -0,0 +1,5 @@
|
||||
# Names should be added to this file like so:
|
||||
# Name or Organization <email address>
|
||||
|
||||
Google Inc.
|
||||
Elijah Cirioli <eli.cirioli@gmail.com>
|
41
lib/lib_audio/ESP8266Audio/src/libwebm/CONTRIBUTING.md
Normal file
41
lib/lib_audio/ESP8266Audio/src/libwebm/CONTRIBUTING.md
Normal file
@ -0,0 +1,41 @@
|
||||
# How to Contribute
|
||||
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
just a few small guidelines you need to follow.
|
||||
|
||||
## Contributor License Agreement
|
||||
|
||||
Contributions to this project must be accompanied by a Contributor License
|
||||
Agreement. You (or your employer) retain the copyright to your contribution;
|
||||
this simply gives us permission to use and redistribute your contributions as
|
||||
part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||
your current agreements on file or to sign a new one.
|
||||
|
||||
You generally only need to submit a CLA once, so if you've already submitted one
|
||||
(even if it was for a different project), you probably don't need to do it
|
||||
again.
|
||||
|
||||
## Code reviews
|
||||
|
||||
All submissions, including submissions by project members, require review. We
|
||||
use a [Gerrit](https://www.gerritcodereview.com) instance hosted at
|
||||
https://chromium-review.googlesource.com for this purpose. See the
|
||||
[WebM Project page](https://www.webmproject.org/code/contribute/submitting-patches/)
|
||||
for additional details.
|
||||
|
||||
## Code Style
|
||||
|
||||
The C++ code style is based on the
|
||||
[Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) and
|
||||
`clang-format --style=Google`. `clang-format -i --style=file` can be used to
|
||||
format individual files, it will use the settings from `.clang-format`.
|
||||
|
||||
CMake files are formatted with
|
||||
[cmake-format](https://cmake-format.readthedocs.io/en/latest/). `cmake-format
|
||||
-i` can be used to format individual files, it will use the settings from
|
||||
`.cmake-format.py`.
|
||||
|
||||
## Community Guidelines
|
||||
|
||||
This project follows
|
||||
[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
|
30
lib/lib_audio/ESP8266Audio/src/libwebm/LICENSE.TXT
Normal file
30
lib/lib_audio/ESP8266Audio/src/libwebm/LICENSE.TXT
Normal file
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2010, Google Inc. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Google nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
23
lib/lib_audio/ESP8266Audio/src/libwebm/PATENTS.TXT
Normal file
23
lib/lib_audio/ESP8266Audio/src/libwebm/PATENTS.TXT
Normal file
@ -0,0 +1,23 @@
|
||||
Additional IP Rights Grant (Patents)
|
||||
------------------------------------
|
||||
|
||||
"These implementations" means the copyrightable works that implement the WebM
|
||||
codecs distributed by Google as part of the WebM Project.
|
||||
|
||||
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
|
||||
royalty-free, irrevocable (except as stated in this section) patent license to
|
||||
make, have made, use, offer to sell, sell, import, transfer, and otherwise
|
||||
run, modify and propagate the contents of these implementations of WebM, where
|
||||
such license applies only to those patent claims, both currently owned by
|
||||
Google and acquired in the future, licensable by Google that are necessarily
|
||||
infringed by these implementations of WebM. This grant does not include claims
|
||||
that would be infringed only as a consequence of further modification of these
|
||||
implementations. If you or your agent or exclusive licensee institute or order
|
||||
or agree to the institution of patent litigation or any other patent
|
||||
enforcement activity against any entity (including a cross-claim or
|
||||
counterclaim in a lawsuit) alleging that any of these implementations of WebM
|
||||
or any code incorporated within any of these implementations of WebM
|
||||
constitute direct or contributory patent infringement, or inducement of
|
||||
patent infringement, then any patent rights granted to you under this License
|
||||
for these implementations of WebM shall terminate as of the date such
|
||||
litigation is filed.
|
202
lib/lib_audio/ESP8266Audio/src/libwebm/PRESUBMIT.py
Normal file
202
lib/lib_audio/ESP8266Audio/src/libwebm/PRESUBMIT.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Copyright (c) 2021, Google Inc. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# * Neither the name of Google nor the names of its contributors may
|
||||
# be used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
"""Top-level presubmit script for libwebm.
|
||||
|
||||
See https://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for
|
||||
details on the presubmit API built into depot_tools.
|
||||
"""
|
||||
import re
|
||||
import subprocess2
|
||||
|
||||
USE_PYTHON3 = True
|
||||
_BASH_INDENTATION = "2"
|
||||
_GIT_COMMIT_SUBJECT_LENGTH = 65
|
||||
_INCLUDE_BASH_FILES_ONLY = [r".*\.sh$"]
|
||||
_INCLUDE_SOURCE_FILES_ONLY = [r".*\.(c|cc|[hc]pp|h)$"]
|
||||
_LIBWEBM_MAX_LINE_LENGTH = 80
|
||||
|
||||
|
||||
def _CheckCommitSubjectLength(input_api, output_api):
|
||||
"""Ensures commit's subject length is no longer than 65 chars."""
|
||||
name = "git-commit subject"
|
||||
cmd = ["git", "log", "-1", "--pretty=%s"]
|
||||
start = input_api.time.time()
|
||||
proc = subprocess2.Popen(
|
||||
cmd,
|
||||
stderr=subprocess2.PIPE,
|
||||
stdout=subprocess2.PIPE,
|
||||
universal_newlines=True)
|
||||
|
||||
stdout, _ = proc.communicate()
|
||||
duration = input_api.time.time() - start
|
||||
|
||||
if not re.match(r"^Revert",
|
||||
stdout) and (len(stdout) - 1) > _GIT_COMMIT_SUBJECT_LENGTH:
|
||||
failure_msg = (
|
||||
"The commit subject: %s is too long (%d chars)\n"
|
||||
"Try to keep this to 50 or less (up to 65 is permitted for "
|
||||
"non-reverts).\n"
|
||||
"https://www.git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-"
|
||||
"Project#_commit_guidelines") % (stdout, len(stdout) - 1)
|
||||
return output_api.PresubmitError("%s\n (%4.2fs) failed\n%s" %
|
||||
(name, duration, failure_msg))
|
||||
|
||||
return output_api.PresubmitResult("%s\n (%4.2fs) success" % (name, duration))
|
||||
|
||||
|
||||
def _GetFilesToSkip(input_api):
|
||||
"""Skips libwebm-specific files."""
|
||||
return list(input_api.DEFAULT_FILES_TO_SKIP) + [
|
||||
r"\.pylintrc$",
|
||||
]
|
||||
|
||||
|
||||
def _CheckChangeLintsClean(input_api, output_api):
|
||||
"""Makes sure that libwebm/ code is cpplint clean."""
|
||||
sources = lambda x: input_api.FilterSourceFile(
|
||||
x, files_to_check=_INCLUDE_SOURCE_FILES_ONLY, files_to_skip=None)
|
||||
return input_api.canned_checks.CheckChangeLintsClean(input_api, output_api,
|
||||
sources)
|
||||
|
||||
|
||||
def _RunShellCheckCmd(input_api, output_api, bash_file):
|
||||
"""shellcheck command wrapper."""
|
||||
cmd = ["shellcheck", "-x", "-oall", "-sbash", bash_file]
|
||||
name = "Check %s file." % bash_file
|
||||
start = input_api.time.time()
|
||||
output, rc = subprocess2.communicate(
|
||||
cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
|
||||
duration = input_api.time.time() - start
|
||||
if rc == 0:
|
||||
return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
|
||||
(name, " ".join(cmd), duration))
|
||||
return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
|
||||
(name, " ".join(cmd), duration, output[1]))
|
||||
|
||||
|
||||
def _RunShfmtCheckCmd(input_api, output_api, bash_file):
|
||||
"""shfmt command wrapper."""
|
||||
cmd = [
|
||||
"shfmt", "-i", _BASH_INDENTATION, "-bn", "-ci", "-sr", "-kp", "-d",
|
||||
bash_file
|
||||
]
|
||||
name = "Check %s file." % bash_file
|
||||
start = input_api.time.time()
|
||||
output, rc = subprocess2.communicate(
|
||||
cmd, stdout=None, stderr=subprocess2.PIPE, universal_newlines=True)
|
||||
duration = input_api.time.time() - start
|
||||
if rc == 0:
|
||||
return output_api.PresubmitResult("%s\n%s (%4.2fs)\n" %
|
||||
(name, " ".join(cmd), duration))
|
||||
return output_api.PresubmitError("%s\n%s (%4.2fs) failed\n%s" %
|
||||
(name, " ".join(cmd), duration, output[1]))
|
||||
|
||||
|
||||
def _RunCmdOnCheckedFiles(input_api, output_api, run_cmd, files_to_check):
|
||||
"""Ensure that libwebm/ files are clean."""
|
||||
file_filter = lambda x: input_api.FilterSourceFile(
|
||||
x, files_to_check=files_to_check, files_to_skip=None)
|
||||
|
||||
affected_files = input_api.change.AffectedFiles(file_filter=file_filter)
|
||||
results = [
|
||||
run_cmd(input_api, output_api, f.AbsoluteLocalPath())
|
||||
for f in affected_files
|
||||
]
|
||||
return results
|
||||
|
||||
|
||||
def _CommonChecks(input_api, output_api):
|
||||
results = []
|
||||
results.extend(
|
||||
input_api.canned_checks.CheckChangeHasNoCrAndHasOnlyOneEol(
|
||||
input_api, output_api))
|
||||
results.extend(
|
||||
input_api.canned_checks.CheckChangeHasNoTabs(input_api, output_api))
|
||||
results.extend(
|
||||
input_api.canned_checks.CheckChangeHasNoStrayWhitespace(
|
||||
input_api, output_api))
|
||||
results.append(_CheckCommitSubjectLength(input_api, output_api))
|
||||
|
||||
source_file_filter = lambda x: input_api.FilterSourceFile(
|
||||
x, files_to_skip=_GetFilesToSkip(input_api))
|
||||
results.extend(
|
||||
input_api.canned_checks.CheckLongLines(
|
||||
input_api,
|
||||
output_api,
|
||||
maxlen=_LIBWEBM_MAX_LINE_LENGTH,
|
||||
source_file_filter=source_file_filter))
|
||||
|
||||
results.extend(
|
||||
input_api.canned_checks.CheckPatchFormatted(
|
||||
input_api,
|
||||
output_api,
|
||||
check_clang_format=True,
|
||||
check_python=True,
|
||||
result_factory=output_api.PresubmitError))
|
||||
results.extend(_CheckChangeLintsClean(input_api, output_api))
|
||||
|
||||
# Run pylint.
|
||||
results.extend(
|
||||
input_api.canned_checks.RunPylint(
|
||||
input_api,
|
||||
output_api,
|
||||
files_to_skip=_GetFilesToSkip(input_api),
|
||||
pylintrc=".pylintrc",
|
||||
version="2.7"))
|
||||
|
||||
# Binaries shellcheck and shfmt are not installed in depot_tools.
|
||||
# Installation is needed
|
||||
try:
|
||||
subprocess2.communicate(["shellcheck", "--version"])
|
||||
results.extend(
|
||||
_RunCmdOnCheckedFiles(input_api, output_api, _RunShellCheckCmd,
|
||||
_INCLUDE_BASH_FILES_ONLY))
|
||||
print("shfmt")
|
||||
subprocess2.communicate(["shfmt", "-version"])
|
||||
results.extend(
|
||||
_RunCmdOnCheckedFiles(input_api, output_api, _RunShfmtCheckCmd,
|
||||
_INCLUDE_BASH_FILES_ONLY))
|
||||
except OSError as os_error:
|
||||
results.append(
|
||||
output_api.PresubmitPromptWarning(
|
||||
"%s\nPlease install missing binaries locally." % os_error.args[0]))
|
||||
return results
|
||||
|
||||
|
||||
def CheckChangeOnUpload(input_api, output_api):
|
||||
results = []
|
||||
results.extend(_CommonChecks(input_api, output_api))
|
||||
return results
|
||||
|
||||
|
||||
def CheckChangeOnCommit(input_api, output_api):
|
||||
results = []
|
||||
results.extend(_CommonChecks(input_api, output_api))
|
||||
return results
|
148
lib/lib_audio/ESP8266Audio/src/libwebm/README.libwebm
Normal file
148
lib/lib_audio/ESP8266Audio/src/libwebm/README.libwebm
Normal file
@ -0,0 +1,148 @@
|
||||
Building Libwebm
|
||||
|
||||
To build libwebm you must first create project files. To do this run cmake
|
||||
and pass it the path to your libwebm repo.
|
||||
|
||||
Makefile.unix can be used as a fallback on systems that cmake does not
|
||||
support.
|
||||
|
||||
|
||||
CMake Basics
|
||||
|
||||
To generate project/make files for the default toolchain on your system simply
|
||||
run cmake with the path to the libwebm repo:
|
||||
|
||||
$ cmake path/to/libwebm
|
||||
|
||||
On Windows the above command will produce Visual Studio project files for the
|
||||
newest Visual Studio detected on the system. On Mac OS X and Linux systems, the
|
||||
above command will produce a makefile.
|
||||
|
||||
To control what types of projects are generated the -G parameter is added to
|
||||
the cmake command line. This argument must be followed by the name of a
|
||||
generator. Running cmake with the --help argument will list the available
|
||||
generators for your system.
|
||||
|
||||
On Mac OS X you would run the following command to generate Xcode projects:
|
||||
|
||||
$ cmake path/to/libwebm -G Xcode
|
||||
|
||||
On a Windows box you would run the following command to generate Visual Studio
|
||||
2013 projects:
|
||||
|
||||
$ cmake path/to/libwebm -G "Visual Studio 12"
|
||||
|
||||
To generate 64-bit Windows Visual Studio 2013 projects:
|
||||
|
||||
$ cmake path/to/libwebm "Visual Studio 12 Win64"
|
||||
|
||||
|
||||
CMake Makefiles: Debugging and Optimization
|
||||
|
||||
Unlike Visual Studio and Xcode projects, the build configuration for make builds
|
||||
is controlled when you run cmake. The following examples demonstrate various
|
||||
build configurations.
|
||||
|
||||
Omitting the build type produces makefiles that use build flags containing
|
||||
neither optimization nor debug flags:
|
||||
$ cmake path/to/libwebm
|
||||
|
||||
A makefile using release (optimized) flags is produced like this:
|
||||
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=release
|
||||
|
||||
A release build with debug info can be produced as well:
|
||||
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=relwithdebinfo
|
||||
|
||||
And your standard debug build will be produced using:
|
||||
$ cmake path/to/libwebm -DCMAKE_BUILD_TYPE=debug
|
||||
|
||||
|
||||
Tests
|
||||
|
||||
To enable libwebm tests add -DENABLE_TESTS=ON CMake generation command line. For
|
||||
example:
|
||||
|
||||
$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON
|
||||
|
||||
Libwebm tests depend on googletest. By default googletest is expected to be a
|
||||
sibling directory of the Libwebm repository. To change that, update your CMake
|
||||
command to be similar to the following:
|
||||
|
||||
$ cmake path/to/libwebm -G Xcode -DENABLE_TESTS=ON \
|
||||
-DGTEST_SRC_DIR=/path/to/googletest
|
||||
|
||||
The tests rely upon the LIBWEBM_TEST_DATA_PATH environment variable to locate
|
||||
test input. The following example demonstrates running the muxer tests from the
|
||||
build directory:
|
||||
|
||||
$ LIBWEBM_TEST_DATA_PATH=path/to/libwebm/testing/testdata ./mkvmuxer_tests
|
||||
|
||||
Note: Libwebm Googletest integration was built with googletest from
|
||||
https://github.com/google/googletest.git at git revision
|
||||
ddb8012eb48bc203aa93dcc2b22c1db516302b29.
|
||||
|
||||
|
||||
CMake Include-what-you-use integration
|
||||
|
||||
Include-what-you-use is an analysis tool that helps ensure libwebm includes the
|
||||
C/C++ header files actually in use. To enable the integration support
|
||||
ENABLE_IWYU must be turned on at cmake run time:
|
||||
|
||||
$ cmake path/to/libwebm -G "Unix Makefiles" -DENABLE_IWYU=ON
|
||||
|
||||
This adds the iwyu target to the build. To run include-what-you-use:
|
||||
|
||||
$ make iwyu
|
||||
|
||||
The following requirements must be met for ENABLE_IWYU to enable the iwyu
|
||||
target:
|
||||
|
||||
1. include-what-you-use and iwyu_tool.py must be in your PATH.
|
||||
2. A python interpreter must be on the system and available to CMake.
|
||||
|
||||
The values of the following variables are used to determine if the requirements
|
||||
have been met. Values to the right of the equals sign are what a successful run
|
||||
might look like:
|
||||
iwyu_path=/path/to/iwyu_tool.py
|
||||
iwyu_tool_path=/path/to/include-what-you-use
|
||||
PYTHONINTERP_FOUND=TRUE
|
||||
|
||||
An empty PYTHONINTERP_FOUND, or iwyu_path/iwyu_tool_path suffixed with NOTFOUND
|
||||
are failures.
|
||||
|
||||
For Include-what-you-use setup instructions, see:
|
||||
https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/InstructionsForUsers.md
|
||||
|
||||
If, when building the iwyu target, compile errors reporting failures loading
|
||||
standard include files occur, one solution can be found here:
|
||||
https://github.com/include-what-you-use/include-what-you-use/issues/100
|
||||
|
||||
|
||||
CMake cross compile
|
||||
To cross compile libwebm for Windows using mingw-w64 run cmake with the
|
||||
following arguments:
|
||||
|
||||
$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \
|
||||
path/to/libwebm
|
||||
|
||||
Note1: As of this writing googletest will not build via mingw-w64 without
|
||||
disabling pthreads.
|
||||
googletest hash: d225acc90bc3a8c420a9bcd1f033033c1ccd7fe0
|
||||
|
||||
To build with tests when using mingw-w64 use the following arguments when
|
||||
running CMake:
|
||||
|
||||
$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \
|
||||
-DENABLE_TESTS=ON -Dgtest_disable_pthreads=ON path/to/libwebm
|
||||
|
||||
Note2: i686-w64-mingw32 is the default compiler. This can be controlled using
|
||||
the MINGW_PREFIX variable:
|
||||
|
||||
$ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/libwebm/build/mingw-w64_toolchain.cmake \
|
||||
-DMINGW_PREFIX=x86_64-w64-mingw32 path/to/libwebm
|
||||
|
||||
Bug reports
|
||||
|
||||
Bug reports can be filed in the libwebm issue tracker:
|
||||
https://issues.webmproject.org/.
|
||||
For security reports, select 'Security report' from the Template dropdown.
|
@ -0,0 +1,4 @@
|
||||
# This file is used by git cl to get repository specific information.
|
||||
GERRIT_HOST: True
|
||||
CODE_REVIEW_SERVER: chromium-review.googlesource.com
|
||||
GERRIT_SQUASH_UPLOADS: False
|
193
lib/lib_audio/ESP8266Audio/src/libwebm/common/webmids.h
Normal file
193
lib/lib_audio/ESP8266Audio/src/libwebm/common/webmids.h
Normal file
@ -0,0 +1,193 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
#ifndef COMMON_WEBMIDS_H_
|
||||
#define COMMON_WEBMIDS_H_
|
||||
|
||||
namespace libwebm {
|
||||
|
||||
enum MkvId {
|
||||
kMkvEBML = 0x1A45DFA3,
|
||||
kMkvEBMLVersion = 0x4286,
|
||||
kMkvEBMLReadVersion = 0x42F7,
|
||||
kMkvEBMLMaxIDLength = 0x42F2,
|
||||
kMkvEBMLMaxSizeLength = 0x42F3,
|
||||
kMkvDocType = 0x4282,
|
||||
kMkvDocTypeVersion = 0x4287,
|
||||
kMkvDocTypeReadVersion = 0x4285,
|
||||
kMkvVoid = 0xEC,
|
||||
kMkvSignatureSlot = 0x1B538667,
|
||||
kMkvSignatureAlgo = 0x7E8A,
|
||||
kMkvSignatureHash = 0x7E9A,
|
||||
kMkvSignaturePublicKey = 0x7EA5,
|
||||
kMkvSignature = 0x7EB5,
|
||||
kMkvSignatureElements = 0x7E5B,
|
||||
kMkvSignatureElementList = 0x7E7B,
|
||||
kMkvSignedElement = 0x6532,
|
||||
// segment
|
||||
kMkvSegment = 0x18538067,
|
||||
// Meta Seek Information
|
||||
kMkvSeekHead = 0x114D9B74,
|
||||
kMkvSeek = 0x4DBB,
|
||||
kMkvSeekID = 0x53AB,
|
||||
kMkvSeekPosition = 0x53AC,
|
||||
// Segment Information
|
||||
kMkvInfo = 0x1549A966,
|
||||
kMkvTimecodeScale = 0x2AD7B1,
|
||||
kMkvDuration = 0x4489,
|
||||
kMkvDateUTC = 0x4461,
|
||||
kMkvTitle = 0x7BA9,
|
||||
kMkvMuxingApp = 0x4D80,
|
||||
kMkvWritingApp = 0x5741,
|
||||
// Cluster
|
||||
kMkvCluster = 0x1F43B675,
|
||||
kMkvTimecode = 0xE7,
|
||||
kMkvPrevSize = 0xAB,
|
||||
kMkvBlockGroup = 0xA0,
|
||||
kMkvBlock = 0xA1,
|
||||
kMkvBlockDuration = 0x9B,
|
||||
kMkvReferenceBlock = 0xFB,
|
||||
kMkvLaceNumber = 0xCC,
|
||||
kMkvSimpleBlock = 0xA3,
|
||||
kMkvBlockAdditions = 0x75A1,
|
||||
kMkvBlockMore = 0xA6,
|
||||
kMkvBlockAddID = 0xEE,
|
||||
kMkvBlockAdditional = 0xA5,
|
||||
kMkvDiscardPadding = 0x75A2,
|
||||
// Track
|
||||
kMkvTracks = 0x1654AE6B,
|
||||
kMkvTrackEntry = 0xAE,
|
||||
kMkvTrackNumber = 0xD7,
|
||||
kMkvTrackUID = 0x73C5,
|
||||
kMkvTrackType = 0x83,
|
||||
kMkvFlagEnabled = 0xB9,
|
||||
kMkvFlagDefault = 0x88,
|
||||
kMkvFlagForced = 0x55AA,
|
||||
kMkvFlagLacing = 0x9C,
|
||||
kMkvDefaultDuration = 0x23E383,
|
||||
kMkvMaxBlockAdditionID = 0x55EE,
|
||||
kMkvName = 0x536E,
|
||||
kMkvLanguage = 0x22B59C,
|
||||
kMkvCodecID = 0x86,
|
||||
kMkvCodecPrivate = 0x63A2,
|
||||
kMkvCodecName = 0x258688,
|
||||
kMkvCodecDelay = 0x56AA,
|
||||
kMkvSeekPreRoll = 0x56BB,
|
||||
// video
|
||||
kMkvVideo = 0xE0,
|
||||
kMkvFlagInterlaced = 0x9A,
|
||||
kMkvStereoMode = 0x53B8,
|
||||
kMkvAlphaMode = 0x53C0,
|
||||
kMkvPixelWidth = 0xB0,
|
||||
kMkvPixelHeight = 0xBA,
|
||||
kMkvPixelCropBottom = 0x54AA,
|
||||
kMkvPixelCropTop = 0x54BB,
|
||||
kMkvPixelCropLeft = 0x54CC,
|
||||
kMkvPixelCropRight = 0x54DD,
|
||||
kMkvDisplayWidth = 0x54B0,
|
||||
kMkvDisplayHeight = 0x54BA,
|
||||
kMkvDisplayUnit = 0x54B2,
|
||||
kMkvAspectRatioType = 0x54B3,
|
||||
kMkvColourSpace = 0x2EB524,
|
||||
kMkvFrameRate = 0x2383E3,
|
||||
// end video
|
||||
// colour
|
||||
kMkvColour = 0x55B0,
|
||||
kMkvMatrixCoefficients = 0x55B1,
|
||||
kMkvBitsPerChannel = 0x55B2,
|
||||
kMkvChromaSubsamplingHorz = 0x55B3,
|
||||
kMkvChromaSubsamplingVert = 0x55B4,
|
||||
kMkvCbSubsamplingHorz = 0x55B5,
|
||||
kMkvCbSubsamplingVert = 0x55B6,
|
||||
kMkvChromaSitingHorz = 0x55B7,
|
||||
kMkvChromaSitingVert = 0x55B8,
|
||||
kMkvRange = 0x55B9,
|
||||
kMkvTransferCharacteristics = 0x55BA,
|
||||
kMkvPrimaries = 0x55BB,
|
||||
kMkvMaxCLL = 0x55BC,
|
||||
kMkvMaxFALL = 0x55BD,
|
||||
// mastering metadata
|
||||
kMkvMasteringMetadata = 0x55D0,
|
||||
kMkvPrimaryRChromaticityX = 0x55D1,
|
||||
kMkvPrimaryRChromaticityY = 0x55D2,
|
||||
kMkvPrimaryGChromaticityX = 0x55D3,
|
||||
kMkvPrimaryGChromaticityY = 0x55D4,
|
||||
kMkvPrimaryBChromaticityX = 0x55D5,
|
||||
kMkvPrimaryBChromaticityY = 0x55D6,
|
||||
kMkvWhitePointChromaticityX = 0x55D7,
|
||||
kMkvWhitePointChromaticityY = 0x55D8,
|
||||
kMkvLuminanceMax = 0x55D9,
|
||||
kMkvLuminanceMin = 0x55DA,
|
||||
// end mastering metadata
|
||||
// end colour
|
||||
// projection
|
||||
kMkvProjection = 0x7670,
|
||||
kMkvProjectionType = 0x7671,
|
||||
kMkvProjectionPrivate = 0x7672,
|
||||
kMkvProjectionPoseYaw = 0x7673,
|
||||
kMkvProjectionPosePitch = 0x7674,
|
||||
kMkvProjectionPoseRoll = 0x7675,
|
||||
// end projection
|
||||
// audio
|
||||
kMkvAudio = 0xE1,
|
||||
kMkvSamplingFrequency = 0xB5,
|
||||
kMkvOutputSamplingFrequency = 0x78B5,
|
||||
kMkvChannels = 0x9F,
|
||||
kMkvBitDepth = 0x6264,
|
||||
// end audio
|
||||
// ContentEncodings
|
||||
kMkvContentEncodings = 0x6D80,
|
||||
kMkvContentEncoding = 0x6240,
|
||||
kMkvContentEncodingOrder = 0x5031,
|
||||
kMkvContentEncodingScope = 0x5032,
|
||||
kMkvContentEncodingType = 0x5033,
|
||||
kMkvContentCompression = 0x5034,
|
||||
kMkvContentCompAlgo = 0x4254,
|
||||
kMkvContentCompSettings = 0x4255,
|
||||
kMkvContentEncryption = 0x5035,
|
||||
kMkvContentEncAlgo = 0x47E1,
|
||||
kMkvContentEncKeyID = 0x47E2,
|
||||
kMkvContentSignature = 0x47E3,
|
||||
kMkvContentSigKeyID = 0x47E4,
|
||||
kMkvContentSigAlgo = 0x47E5,
|
||||
kMkvContentSigHashAlgo = 0x47E6,
|
||||
kMkvContentEncAESSettings = 0x47E7,
|
||||
kMkvAESSettingsCipherMode = 0x47E8,
|
||||
kMkvAESSettingsCipherInitData = 0x47E9,
|
||||
// end ContentEncodings
|
||||
// Cueing Data
|
||||
kMkvCues = 0x1C53BB6B,
|
||||
kMkvCuePoint = 0xBB,
|
||||
kMkvCueTime = 0xB3,
|
||||
kMkvCueTrackPositions = 0xB7,
|
||||
kMkvCueTrack = 0xF7,
|
||||
kMkvCueClusterPosition = 0xF1,
|
||||
kMkvCueBlockNumber = 0x5378,
|
||||
// Chapters
|
||||
kMkvChapters = 0x1043A770,
|
||||
kMkvEditionEntry = 0x45B9,
|
||||
kMkvChapterAtom = 0xB6,
|
||||
kMkvChapterUID = 0x73C4,
|
||||
kMkvChapterStringUID = 0x5654,
|
||||
kMkvChapterTimeStart = 0x91,
|
||||
kMkvChapterTimeEnd = 0x92,
|
||||
kMkvChapterDisplay = 0x80,
|
||||
kMkvChapString = 0x85,
|
||||
kMkvChapLanguage = 0x437C,
|
||||
kMkvChapCountry = 0x437E,
|
||||
// Tags
|
||||
kMkvTags = 0x1254C367,
|
||||
kMkvTag = 0x7373,
|
||||
kMkvSimpleTag = 0x67C8,
|
||||
kMkvTagName = 0x45A3,
|
||||
kMkvTagString = 0x4487
|
||||
};
|
||||
|
||||
} // namespace libwebm
|
||||
|
||||
#endif // COMMON_WEBMIDS_H_
|
4207
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxer.cc
Normal file
4207
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxer.cc
Normal file
File diff suppressed because it is too large
Load Diff
1926
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxer.h
Normal file
1926
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxer.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,28 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
#ifndef MKVMUXER_MKVMUXERTYPES_H_
|
||||
#define MKVMUXER_MKVMUXERTYPES_H_
|
||||
|
||||
namespace mkvmuxer {
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
} // namespace mkvmuxer
|
||||
|
||||
// Copied from Chromium basictypes.h
|
||||
// A macro to disallow the copy constructor and operator= functions
|
||||
// This should be used in the private: declarations for a class
|
||||
#define LIBWEBM_DISALLOW_COPY_AND_ASSIGN(TypeName) \
|
||||
TypeName(const TypeName&); \
|
||||
void operator=(const TypeName&)
|
||||
|
||||
#endif // MKVMUXER_MKVMUXERTYPES_HPP_
|
739
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxerutil.cc
Normal file
739
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxerutil.cc
Normal file
@ -0,0 +1,739 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
#include "mkvmuxerutil.h"
|
||||
#ifdef ESP32
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <new>
|
||||
|
||||
#include "../common/webmids.h"
|
||||
#include "mkvmuxer.h"
|
||||
#include "mkvwriter.h"
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
namespace {
|
||||
|
||||
// Date elements are always 8 octets in size.
|
||||
const int kDateElementSize = 8;
|
||||
|
||||
uint64 WriteBlock(IMkvWriter* writer, const Frame* const frame, int64 timecode,
|
||||
uint64 timecode_scale) {
|
||||
uint64 block_additional_elem_size = 0;
|
||||
uint64 block_addid_elem_size = 0;
|
||||
uint64 block_more_payload_size = 0;
|
||||
uint64 block_more_elem_size = 0;
|
||||
uint64 block_additions_payload_size = 0;
|
||||
uint64 block_additions_elem_size = 0;
|
||||
if (frame->additional()) {
|
||||
block_additional_elem_size =
|
||||
EbmlElementSize(libwebm::kMkvBlockAdditional, frame->additional(),
|
||||
frame->additional_length());
|
||||
block_addid_elem_size = EbmlElementSize(
|
||||
libwebm::kMkvBlockAddID, static_cast<uint64>(frame->add_id()));
|
||||
|
||||
block_more_payload_size =
|
||||
block_addid_elem_size + block_additional_elem_size;
|
||||
block_more_elem_size =
|
||||
EbmlMasterElementSize(libwebm::kMkvBlockMore, block_more_payload_size) +
|
||||
block_more_payload_size;
|
||||
block_additions_payload_size = block_more_elem_size;
|
||||
block_additions_elem_size =
|
||||
EbmlMasterElementSize(libwebm::kMkvBlockAdditions,
|
||||
block_additions_payload_size) +
|
||||
block_additions_payload_size;
|
||||
}
|
||||
|
||||
uint64 discard_padding_elem_size = 0;
|
||||
if (frame->discard_padding() != 0) {
|
||||
discard_padding_elem_size =
|
||||
EbmlElementSize(libwebm::kMkvDiscardPadding,
|
||||
static_cast<int64>(frame->discard_padding()));
|
||||
}
|
||||
|
||||
const uint64 reference_block_timestamp =
|
||||
frame->reference_block_timestamp() / timecode_scale;
|
||||
uint64 reference_block_elem_size = 0;
|
||||
if (!frame->is_key()) {
|
||||
reference_block_elem_size =
|
||||
EbmlElementSize(libwebm::kMkvReferenceBlock, reference_block_timestamp);
|
||||
}
|
||||
|
||||
const uint64 duration = frame->duration() / timecode_scale;
|
||||
uint64 block_duration_elem_size = 0;
|
||||
if (duration > 0)
|
||||
block_duration_elem_size =
|
||||
EbmlElementSize(libwebm::kMkvBlockDuration, duration);
|
||||
|
||||
const uint64 block_payload_size = 4 + frame->length();
|
||||
const uint64 block_elem_size =
|
||||
EbmlMasterElementSize(libwebm::kMkvBlock, block_payload_size) +
|
||||
block_payload_size;
|
||||
|
||||
const uint64 block_group_payload_size =
|
||||
block_elem_size + block_additions_elem_size + block_duration_elem_size +
|
||||
discard_padding_elem_size + reference_block_elem_size;
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockGroup,
|
||||
block_group_payload_size)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlock, block_payload_size))
|
||||
return 0;
|
||||
|
||||
if (WriteUInt(writer, frame->track_number()))
|
||||
return 0;
|
||||
|
||||
if (SerializeInt(writer, timecode, 2))
|
||||
return 0;
|
||||
|
||||
// For a Block, flags is always 0.
|
||||
if (SerializeInt(writer, 0, 1))
|
||||
return 0;
|
||||
|
||||
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
|
||||
return 0;
|
||||
|
||||
if (frame->additional()) {
|
||||
if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockAdditions,
|
||||
block_additions_payload_size)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!WriteEbmlMasterElement(writer, libwebm::kMkvBlockMore,
|
||||
block_more_payload_size))
|
||||
return 0;
|
||||
|
||||
if (!WriteEbmlElement(writer, libwebm::kMkvBlockAddID,
|
||||
static_cast<uint64>(frame->add_id())))
|
||||
return 0;
|
||||
|
||||
if (!WriteEbmlElement(writer, libwebm::kMkvBlockAdditional,
|
||||
frame->additional(), frame->additional_length())) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (frame->discard_padding() != 0 &&
|
||||
!WriteEbmlElement(writer, libwebm::kMkvDiscardPadding,
|
||||
static_cast<int64>(frame->discard_padding()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!frame->is_key() && !WriteEbmlElement(writer, libwebm::kMkvReferenceBlock,
|
||||
reference_block_timestamp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (duration > 0 &&
|
||||
!WriteEbmlElement(writer, libwebm::kMkvBlockDuration, duration)) {
|
||||
return false;
|
||||
}
|
||||
return EbmlMasterElementSize(libwebm::kMkvBlockGroup,
|
||||
block_group_payload_size) +
|
||||
block_group_payload_size;
|
||||
}
|
||||
|
||||
uint64 WriteSimpleBlock(IMkvWriter* writer, const Frame* const frame,
|
||||
int64 timecode) {
|
||||
if (WriteID(writer, libwebm::kMkvSimpleBlock))
|
||||
return 0;
|
||||
|
||||
const int32 size = static_cast<int32>(frame->length()) + 4;
|
||||
if (WriteUInt(writer, size))
|
||||
return 0;
|
||||
|
||||
if (WriteUInt(writer, static_cast<uint64>(frame->track_number())))
|
||||
return 0;
|
||||
|
||||
if (SerializeInt(writer, timecode, 2))
|
||||
return 0;
|
||||
|
||||
uint64 flags = 0;
|
||||
if (frame->is_key())
|
||||
flags |= 0x80;
|
||||
|
||||
if (SerializeInt(writer, flags, 1))
|
||||
return 0;
|
||||
|
||||
if (writer->Write(frame->frame(), static_cast<uint32>(frame->length())))
|
||||
return 0;
|
||||
|
||||
return GetUIntSize(libwebm::kMkvSimpleBlock) + GetCodedUIntSize(size) + 4 +
|
||||
frame->length();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int32 GetCodedUIntSize(uint64 value) {
|
||||
if (value < 0x000000000000007FULL)
|
||||
return 1;
|
||||
else if (value < 0x0000000000003FFFULL)
|
||||
return 2;
|
||||
else if (value < 0x00000000001FFFFFULL)
|
||||
return 3;
|
||||
else if (value < 0x000000000FFFFFFFULL)
|
||||
return 4;
|
||||
else if (value < 0x00000007FFFFFFFFULL)
|
||||
return 5;
|
||||
else if (value < 0x000003FFFFFFFFFFULL)
|
||||
return 6;
|
||||
else if (value < 0x0001FFFFFFFFFFFFULL)
|
||||
return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
int32 GetUIntSize(uint64 value) {
|
||||
if (value < 0x0000000000000100ULL)
|
||||
return 1;
|
||||
else if (value < 0x0000000000010000ULL)
|
||||
return 2;
|
||||
else if (value < 0x0000000001000000ULL)
|
||||
return 3;
|
||||
else if (value < 0x0000000100000000ULL)
|
||||
return 4;
|
||||
else if (value < 0x0000010000000000ULL)
|
||||
return 5;
|
||||
else if (value < 0x0001000000000000ULL)
|
||||
return 6;
|
||||
else if (value < 0x0100000000000000ULL)
|
||||
return 7;
|
||||
return 8;
|
||||
}
|
||||
|
||||
int32 GetIntSize(int64 value) {
|
||||
// Doubling the requested value ensures positive values with their high bit
|
||||
// set are written with 0-padding to avoid flipping the signedness.
|
||||
const uint64 v = (value < 0) ? value ^ -1LL : value;
|
||||
return GetUIntSize(2 * v);
|
||||
}
|
||||
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += GetCodedUIntSize(value);
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, int64 value) {
|
||||
// Size of EBML ID
|
||||
int32 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += GetIntSize(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value) {
|
||||
return EbmlElementSize(type, value, 0);
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size) {
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += (fixed_size > 0) ? fixed_size : GetUIntSize(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, float /* value */) {
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += sizeof(float);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, const char* value) {
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += strlen(value);
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size += GetCodedUIntSize(strlen(value));
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size) {
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += size;
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size += GetCodedUIntSize(size);
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
uint64 EbmlDateElementSize(uint64 type) {
|
||||
// Size of EBML ID
|
||||
uint64 ebml_size = GetUIntSize(type);
|
||||
|
||||
// Datasize
|
||||
ebml_size += kDateElementSize;
|
||||
|
||||
// Size of Datasize
|
||||
ebml_size++;
|
||||
|
||||
return ebml_size;
|
||||
}
|
||||
|
||||
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size) {
|
||||
if (!writer || size < 1 || size > 8)
|
||||
return -1;
|
||||
|
||||
for (int32 i = 1; i <= size; ++i) {
|
||||
const int32 byte_count = size - i;
|
||||
const int32 bit_count = byte_count * 8;
|
||||
|
||||
const int64 bb = value >> bit_count;
|
||||
const uint8 b = static_cast<uint8>(bb);
|
||||
|
||||
const int32 status = writer->Write(&b, 1);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 SerializeFloat(IMkvWriter* writer, float f) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
assert(sizeof(uint32) == sizeof(float));
|
||||
// This union is merely used to avoid a reinterpret_cast from float& to
|
||||
// uint32& which will result in violation of strict aliasing.
|
||||
union U32 {
|
||||
uint32 u32;
|
||||
float f;
|
||||
} value;
|
||||
value.f = f;
|
||||
|
||||
for (int32 i = 1; i <= 4; ++i) {
|
||||
const int32 byte_count = 4 - i;
|
||||
const int32 bit_count = byte_count * 8;
|
||||
|
||||
const uint8 byte = static_cast<uint8>(value.u32 >> bit_count);
|
||||
|
||||
const int32 status = writer->Write(&byte, 1);
|
||||
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 WriteUInt(IMkvWriter* writer, uint64 value) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
int32 size = GetCodedUIntSize(value);
|
||||
|
||||
return WriteUIntSize(writer, value, size);
|
||||
}
|
||||
|
||||
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size) {
|
||||
if (!writer || size < 0 || size > 8)
|
||||
return -1;
|
||||
|
||||
if (size > 0) {
|
||||
const uint64 bit = 1LL << (size * 7);
|
||||
|
||||
if (value > (bit - 2))
|
||||
return -1;
|
||||
|
||||
value |= bit;
|
||||
} else {
|
||||
size = 1;
|
||||
int64 bit;
|
||||
|
||||
for (;;) {
|
||||
bit = 1LL << (size * 7);
|
||||
const uint64 max = bit - 2;
|
||||
|
||||
if (value <= max)
|
||||
break;
|
||||
|
||||
++size;
|
||||
}
|
||||
|
||||
if (size > 8)
|
||||
return false;
|
||||
|
||||
value |= bit;
|
||||
}
|
||||
|
||||
return SerializeInt(writer, value, size);
|
||||
}
|
||||
|
||||
int32 WriteID(IMkvWriter* writer, uint64 type) {
|
||||
if (!writer)
|
||||
return -1;
|
||||
|
||||
writer->ElementStartNotify(type, writer->Position());
|
||||
|
||||
const int32 size = GetUIntSize(type);
|
||||
|
||||
return SerializeInt(writer, type, size);
|
||||
}
|
||||
|
||||
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 type, uint64 size) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value) {
|
||||
return WriteEbmlElement(writer, type, value, 0);
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
|
||||
uint64 fixed_size) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
uint64 size = GetUIntSize(value);
|
||||
if (fixed_size > 0) {
|
||||
if (size > fixed_size)
|
||||
return false;
|
||||
size = fixed_size;
|
||||
}
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
if (SerializeInt(writer, value, static_cast<int32>(size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return 0;
|
||||
|
||||
const uint64 size = GetIntSize(value);
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
if (SerializeInt(writer, value, static_cast<int32>(size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, 4))
|
||||
return false;
|
||||
|
||||
if (SerializeFloat(writer, value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value) {
|
||||
if (!writer || !value)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
const uint64 length = strlen(value);
|
||||
if (WriteUInt(writer, length))
|
||||
return false;
|
||||
|
||||
if (writer->Write(value, static_cast<uint32>(length)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||
uint64 size) {
|
||||
if (!writer || !value || size < 1)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, size))
|
||||
return false;
|
||||
|
||||
if (writer->Write(value, static_cast<uint32>(size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
if (WriteID(writer, type))
|
||||
return false;
|
||||
|
||||
if (WriteUInt(writer, kDateElementSize))
|
||||
return false;
|
||||
|
||||
if (SerializeInt(writer, value, kDateElementSize))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||
Cluster* cluster) {
|
||||
if (!writer || !frame || !frame->IsValid() || !cluster ||
|
||||
!cluster->timecode_scale())
|
||||
return 0;
|
||||
|
||||
// Technically the timecode for a block can be less than the
|
||||
// timecode for the cluster itself (remember that block timecode
|
||||
// is a signed, 16-bit integer). However, as a simplification we
|
||||
// only permit non-negative cluster-relative timecodes for blocks.
|
||||
const int64 relative_timecode = cluster->GetRelativeTimecode(
|
||||
frame->timestamp() / cluster->timecode_scale());
|
||||
if (relative_timecode < 0 || relative_timecode > kMaxBlockTimecode)
|
||||
return 0;
|
||||
|
||||
return frame->CanBeSimpleBlock()
|
||||
? WriteSimpleBlock(writer, frame, relative_timecode)
|
||||
: WriteBlock(writer, frame, relative_timecode,
|
||||
cluster->timecode_scale());
|
||||
}
|
||||
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size) {
|
||||
if (!writer)
|
||||
return false;
|
||||
|
||||
// Subtract one for the void ID and the coded size.
|
||||
uint64 void_entry_size = size - 1 - GetCodedUIntSize(size - 1);
|
||||
uint64 void_size = EbmlMasterElementSize(libwebm::kMkvVoid, void_entry_size) +
|
||||
void_entry_size;
|
||||
|
||||
if (void_size != size)
|
||||
return 0;
|
||||
|
||||
const int64 payload_position = writer->Position();
|
||||
if (payload_position < 0)
|
||||
return 0;
|
||||
|
||||
if (WriteID(writer, libwebm::kMkvVoid))
|
||||
return 0;
|
||||
|
||||
if (WriteUInt(writer, void_entry_size))
|
||||
return 0;
|
||||
|
||||
const uint8 value = 0;
|
||||
for (int32 i = 0; i < static_cast<int32>(void_entry_size); ++i) {
|
||||
if (writer->Write(&value, 1))
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int64 stop_position = writer->Position();
|
||||
if (stop_position < 0 ||
|
||||
stop_position - payload_position != static_cast<int64>(void_size))
|
||||
return 0;
|
||||
|
||||
return void_size;
|
||||
}
|
||||
|
||||
void GetVersion(int32_t* major, int32_t* minor, int32_t* build, int32_t* revision) {
|
||||
*major = 0;
|
||||
*minor = 3;
|
||||
*build = 3;
|
||||
*revision = 0;
|
||||
}
|
||||
|
||||
uint64 MakeUID(unsigned int* seed) {
|
||||
uint64 uid = 0;
|
||||
|
||||
for (int i = 0; i < 7; ++i) { // avoid problems with 8-byte values
|
||||
uid <<= 8;
|
||||
|
||||
// TODO(fgalligan): Move random number generation to platform specific code.
|
||||
#ifdef _WIN32
|
||||
(void)seed;
|
||||
const int32 nn = rand();
|
||||
#elif defined(__ANDROID__)
|
||||
(void)seed;
|
||||
int32 temp_num = 1;
|
||||
int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
read(fd, &temp_num, sizeof(temp_num));
|
||||
close(fd);
|
||||
}
|
||||
const int32 nn = temp_num;
|
||||
#else
|
||||
const int32 nn = rand_r(seed);
|
||||
#endif
|
||||
const int32 n = 0xFF & (nn >> 4); // throw away low-order bits
|
||||
|
||||
uid |= n;
|
||||
}
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
bool IsMatrixCoefficientsValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kGbr:
|
||||
case mkvmuxer::Colour::kBt709:
|
||||
case mkvmuxer::Colour::kUnspecifiedMc:
|
||||
case mkvmuxer::Colour::kReserved:
|
||||
case mkvmuxer::Colour::kFcc:
|
||||
case mkvmuxer::Colour::kBt470bg:
|
||||
case mkvmuxer::Colour::kSmpte170MMc:
|
||||
case mkvmuxer::Colour::kSmpte240MMc:
|
||||
case mkvmuxer::Colour::kYcocg:
|
||||
case mkvmuxer::Colour::kBt2020NonConstantLuminance:
|
||||
case mkvmuxer::Colour::kBt2020ConstantLuminance:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsChromaSitingHorzValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kUnspecifiedCsh:
|
||||
case mkvmuxer::Colour::kLeftCollocated:
|
||||
case mkvmuxer::Colour::kHalfCsh:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsChromaSitingVertValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kUnspecifiedCsv:
|
||||
case mkvmuxer::Colour::kTopCollocated:
|
||||
case mkvmuxer::Colour::kHalfCsv:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsColourRangeValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kUnspecifiedCr:
|
||||
case mkvmuxer::Colour::kBroadcastRange:
|
||||
case mkvmuxer::Colour::kFullRange:
|
||||
case mkvmuxer::Colour::kMcTcDefined:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsTransferCharacteristicsValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kIturBt709Tc:
|
||||
case mkvmuxer::Colour::kUnspecifiedTc:
|
||||
case mkvmuxer::Colour::kReservedTc:
|
||||
case mkvmuxer::Colour::kGamma22Curve:
|
||||
case mkvmuxer::Colour::kGamma28Curve:
|
||||
case mkvmuxer::Colour::kSmpte170MTc:
|
||||
case mkvmuxer::Colour::kSmpte240MTc:
|
||||
case mkvmuxer::Colour::kLinear:
|
||||
case mkvmuxer::Colour::kLog:
|
||||
case mkvmuxer::Colour::kLogSqrt:
|
||||
case mkvmuxer::Colour::kIec6196624:
|
||||
case mkvmuxer::Colour::kIturBt1361ExtendedColourGamut:
|
||||
case mkvmuxer::Colour::kIec6196621:
|
||||
case mkvmuxer::Colour::kIturBt202010bit:
|
||||
case mkvmuxer::Colour::kIturBt202012bit:
|
||||
case mkvmuxer::Colour::kSmpteSt2084:
|
||||
case mkvmuxer::Colour::kSmpteSt4281Tc:
|
||||
case mkvmuxer::Colour::kAribStdB67Hlg:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsPrimariesValueValid(uint64_t value) {
|
||||
switch (value) {
|
||||
case mkvmuxer::Colour::kReservedP0:
|
||||
case mkvmuxer::Colour::kIturBt709P:
|
||||
case mkvmuxer::Colour::kUnspecifiedP:
|
||||
case mkvmuxer::Colour::kReservedP3:
|
||||
case mkvmuxer::Colour::kIturBt470M:
|
||||
case mkvmuxer::Colour::kIturBt470Bg:
|
||||
case mkvmuxer::Colour::kSmpte170MP:
|
||||
case mkvmuxer::Colour::kSmpte240MP:
|
||||
case mkvmuxer::Colour::kFilm:
|
||||
case mkvmuxer::Colour::kIturBt2020:
|
||||
case mkvmuxer::Colour::kSmpteSt4281P:
|
||||
case mkvmuxer::Colour::kJedecP22Phosphors:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mkvmuxer
|
||||
#endif // ESP32
|
117
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxerutil.h
Normal file
117
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvmuxerutil.h
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
#ifndef MKVMUXER_MKVMUXERUTIL_H_
|
||||
#define MKVMUXER_MKVMUXERUTIL_H_
|
||||
#ifdef ESP32
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mkvmuxertypes.h"
|
||||
|
||||
namespace mkvmuxer {
|
||||
class Cluster;
|
||||
class Frame;
|
||||
class IMkvWriter;
|
||||
|
||||
// TODO(tomfinegan): mkvmuxer:: integer types continue to be used here because
|
||||
// changing them causes pain for downstream projects. It would be nice if a
|
||||
// solution that allows removal of the mkvmuxer:: integer types while avoiding
|
||||
// pain for downstream users of libwebm. Considering that mkvmuxerutil.{cc,h}
|
||||
// are really, for the great majority of cases, EBML size calculation and writer
|
||||
// functions, perhaps a more EBML focused utility would be the way to go as a
|
||||
// first step.
|
||||
|
||||
const uint64 kEbmlUnknownValue = 0x01FFFFFFFFFFFFFFULL;
|
||||
const int64 kMaxBlockTimecode = 0x07FFFLL;
|
||||
|
||||
// Writes out |value| in Big Endian order. Returns 0 on success.
|
||||
int32 SerializeInt(IMkvWriter* writer, int64 value, int32 size);
|
||||
|
||||
// Writes out |f| in Big Endian order. Returns 0 on success.
|
||||
int32 SerializeFloat(IMkvWriter* writer, float f);
|
||||
|
||||
// Returns the size in bytes of the element.
|
||||
int32 GetUIntSize(uint64 value);
|
||||
int32 GetIntSize(int64 value);
|
||||
int32 GetCodedUIntSize(uint64 value);
|
||||
uint64 EbmlMasterElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, int64 value);
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value);
|
||||
uint64 EbmlElementSize(uint64 type, float value);
|
||||
uint64 EbmlElementSize(uint64 type, const char* value);
|
||||
uint64 EbmlElementSize(uint64 type, const uint8* value, uint64 size);
|
||||
uint64 EbmlDateElementSize(uint64 type);
|
||||
|
||||
// Returns the size in bytes of the element assuming that the element was
|
||||
// written using |fixed_size| bytes. If |fixed_size| is set to zero, then it
|
||||
// computes the necessary number of bytes based on |value|.
|
||||
uint64 EbmlElementSize(uint64 type, uint64 value, uint64 fixed_size);
|
||||
|
||||
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||
// the coded number is determined by the value of |value|. |value| must not
|
||||
// be in a coded form. Returns 0 on success.
|
||||
int32 WriteUInt(IMkvWriter* writer, uint64 value);
|
||||
|
||||
// Creates an EBML coded number from |value| and writes it out. The size of
|
||||
// the coded number is determined by the value of |size|. |value| must not
|
||||
// be in a coded form. Returns 0 on success.
|
||||
int32 WriteUIntSize(IMkvWriter* writer, uint64 value, int32 size);
|
||||
|
||||
// Output an Mkv master element. Returns true if the element was written.
|
||||
bool WriteEbmlMasterElement(IMkvWriter* writer, uint64 value, uint64 size);
|
||||
|
||||
// Outputs an Mkv ID, calls |IMkvWriter::ElementStartNotify|, and passes the
|
||||
// ID to |SerializeInt|. Returns 0 on success.
|
||||
int32 WriteID(IMkvWriter* writer, uint64 type);
|
||||
|
||||
// Output an Mkv non-master element. Returns true if the element was written.
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, int64 value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, float value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const char* value);
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, const uint8* value,
|
||||
uint64 size);
|
||||
bool WriteEbmlDateElement(IMkvWriter* writer, uint64 type, int64 value);
|
||||
|
||||
// Output an Mkv non-master element using fixed size. The element will be
|
||||
// written out using exactly |fixed_size| bytes. If |fixed_size| is set to zero
|
||||
// then it computes the necessary number of bytes based on |value|. Returns true
|
||||
// if the element was written.
|
||||
bool WriteEbmlElement(IMkvWriter* writer, uint64 type, uint64 value,
|
||||
uint64 fixed_size);
|
||||
|
||||
// Output a Mkv Frame. It decides the correct element to write (Block vs
|
||||
// SimpleBlock) based on the parameters of the Frame.
|
||||
uint64 WriteFrame(IMkvWriter* writer, const Frame* const frame,
|
||||
Cluster* cluster);
|
||||
|
||||
// Output a void element. |size| must be the entire size in bytes that will be
|
||||
// void. The function will calculate the size of the void header and subtract
|
||||
// it from |size|.
|
||||
uint64 WriteVoidElement(IMkvWriter* writer, uint64 size);
|
||||
|
||||
// Returns the version number of the muxer in |major|, |minor|, |build|,
|
||||
// and |revision|.
|
||||
void GetVersion(int32_t* major, int32_t* minor, int32_t* build, int32_t* revision);
|
||||
|
||||
// Returns a random number to be used for UID, using |seed| to seed
|
||||
// the random-number generator (see POSIX rand_r() for semantics).
|
||||
uint64 MakeUID(unsigned int* seed);
|
||||
|
||||
// Colour field validation helpers. All return true when |value| is valid.
|
||||
bool IsMatrixCoefficientsValueValid(uint64_t value);
|
||||
bool IsChromaSitingHorzValueValid(uint64_t value);
|
||||
bool IsChromaSitingVertValueValid(uint64_t value);
|
||||
bool IsColourRangeValueValid(uint64_t value);
|
||||
bool IsTransferCharacteristicsValueValid(uint64_t value);
|
||||
bool IsPrimariesValueValid(uint64_t value);
|
||||
|
||||
} // namespace mkvmuxer
|
||||
|
||||
#endif // ESP32
|
||||
#endif // MKVMUXER_MKVMUXERUTIL_H_
|
101
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvwriter.cc
Normal file
101
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvwriter.cc
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
#include "mkvwriter.h"
|
||||
#ifdef ESP32
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <share.h> // for _SH_DENYWR
|
||||
#endif
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
MkvWriter::MkvWriter() : file_(NULL), writer_owns_file_(true) {}
|
||||
|
||||
MkvWriter::MkvWriter(File* fp) : file_(fp), writer_owns_file_(false), use_write_cb_(false) {}
|
||||
|
||||
MkvWriter::MkvWriter(void* userdata, int(*cb)(void* userdata, const void* buffer, uint32 length)) : write_cb_(cb), cb_userdata_(userdata), writer_owns_file_(false), use_write_cb_(true) {}
|
||||
|
||||
MkvWriter::~MkvWriter() { Close(); }
|
||||
|
||||
int32 MkvWriter::Write(const void* buffer, uint32 length) {
|
||||
if (!file_ && !write_cb_)
|
||||
return -1;
|
||||
|
||||
if (length == 0)
|
||||
return 0;
|
||||
|
||||
if (buffer == NULL)
|
||||
return -1;
|
||||
|
||||
size_t bytes_written = 0;
|
||||
if(!use_write_cb_){
|
||||
bytes_written = file_->write((const uint8_t *)buffer, (size_t)length);
|
||||
} else {
|
||||
bytes_written = write_cb_(cb_userdata_, buffer, length);
|
||||
write_cb_written_ += bytes_written;
|
||||
}
|
||||
|
||||
return (bytes_written == length) ? 0 : -1;
|
||||
}
|
||||
|
||||
bool MkvWriter::Open(const char* filename) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MkvWriter::Close() {
|
||||
if (file_ && writer_owns_file_) {
|
||||
file_->close();
|
||||
}
|
||||
file_ = NULL;
|
||||
}
|
||||
|
||||
int64 MkvWriter::Position() const {
|
||||
if (!file_ || use_write_cb_)
|
||||
return write_cb_written_;
|
||||
|
||||
return file_->position();
|
||||
}
|
||||
|
||||
int32 MkvWriter::Position(int64 position) {
|
||||
if (use_write_cb_ && write_cb_written_ == position)
|
||||
return 0;
|
||||
if (!file_ || use_write_cb_)
|
||||
return -1;
|
||||
|
||||
return file_->seek(position);
|
||||
|
||||
// #ifdef _MSC_VER
|
||||
// return _fseeki64(file_, position, SEEK_SET);
|
||||
// #elif defined(_WIN32)
|
||||
// return fseeko64(file_, static_cast<off_t>(position), SEEK_SET);
|
||||
// #elif !(defined(__ANDROID__) && __ANDROID_API__ < 24 && !defined(__LP64__) && \
|
||||
// defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64)
|
||||
// // POSIX.1 has fseeko and ftello. fseeko and ftello are not available before
|
||||
// // Android API level 24. See
|
||||
// // https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md
|
||||
// // return fseeko(file_, static_cast<off_t>(position), SEEK_SET);
|
||||
// #else
|
||||
// return fseek(file_, static_cast<long>(position), SEEK_SET);
|
||||
// #endif
|
||||
// return -1;
|
||||
}
|
||||
|
||||
bool MkvWriter::Seekable() const {
|
||||
if (!file_ || use_write_cb_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MkvWriter::ElementStartNotify(uint64, int64) {}
|
||||
|
||||
} // namespace mkvmuxer
|
||||
#endif // ESP32
|
60
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvwriter.h
Normal file
60
lib/lib_audio/ESP8266Audio/src/libwebm/mkvmuxer/mkvwriter.h
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license
|
||||
// that can be found in the LICENSE file in the root of the source
|
||||
// tree. An additional intellectual property rights grant can be found
|
||||
// in the file PATENTS. All contributing project authors may
|
||||
// be found in the AUTHORS file in the root of the source tree.
|
||||
|
||||
#ifndef MKVMUXER_MKVWRITER_H_
|
||||
#define MKVMUXER_MKVWRITER_H_
|
||||
|
||||
#ifdef ESP32
|
||||
#include <stdio.h>
|
||||
|
||||
#include <FS.h>
|
||||
#include "mkvmuxer.h"
|
||||
#include "mkvmuxertypes.h"
|
||||
|
||||
namespace mkvmuxer {
|
||||
|
||||
// Default implementation of the IMkvWriter interface on Windows.
|
||||
class MkvWriter : public IMkvWriter {
|
||||
public:
|
||||
MkvWriter();
|
||||
MkvWriter(File* fp);
|
||||
MkvWriter(void* userdata, int(*cb)(void* userdata, const void* buffer, uint32 length));
|
||||
virtual ~MkvWriter();
|
||||
|
||||
// IMkvWriter interface
|
||||
virtual int64 Position() const;
|
||||
virtual int32 Position(int64 position);
|
||||
virtual bool Seekable() const;
|
||||
virtual int32 Write(const void* buffer, uint32 length);
|
||||
virtual void ElementStartNotify(uint64 element_id, int64 position);
|
||||
|
||||
// Creates and opens a file for writing. |filename| is the name of the file
|
||||
// to open. This function will overwrite the contents of |filename|. Returns
|
||||
// true on success.
|
||||
bool Open(const char* filename);
|
||||
|
||||
// Closes an opened file.
|
||||
void Close();
|
||||
|
||||
private:
|
||||
// File handle to output file.
|
||||
File* file_;
|
||||
// Callback function to output stream.
|
||||
int(*write_cb_)(void* userdata, const void* buffer, uint32 length);
|
||||
void* cb_userdata_;
|
||||
bool writer_owns_file_;
|
||||
bool use_write_cb_;
|
||||
uint32_t write_cb_written_ = 0;
|
||||
|
||||
LIBWEBM_DISALLOW_COPY_AND_ASSIGN(MkvWriter);
|
||||
};
|
||||
|
||||
} // namespace mkvmuxer
|
||||
|
||||
#endif // ESP32
|
||||
#endif // MKVMUXER_MKVWRITER_H_
|
8107
lib/lib_audio/ESP8266Audio/src/libwebm/mkvparser/mkvparser.cc
Normal file
8107
lib/lib_audio/ESP8266Audio/src/libwebm/mkvparser/mkvparser.cc
Normal file
File diff suppressed because it is too large
Load Diff
1147
lib/lib_audio/ESP8266Audio/src/libwebm/mkvparser/mkvparser.h
Normal file
1147
lib/lib_audio/ESP8266Audio/src/libwebm/mkvparser/mkvparser.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -90,12 +90,12 @@ int op_test(OpusHead *_head,
|
||||
ogg_sync_init(&oy);
|
||||
data=ogg_sync_buffer(&oy,(long)_initial_bytes);
|
||||
if(data!=NULL){
|
||||
ogg_stream_state *os = (ogg_stream_state*)malloc(sizeof(ogg_stream_state));
|
||||
ogg_stream_state os;
|
||||
ogg_page og;
|
||||
int ret;
|
||||
memcpy(data,_initial_data,_initial_bytes);
|
||||
ogg_sync_wrote(&oy,(long)_initial_bytes);
|
||||
ogg_stream_init(os,-1);
|
||||
ogg_stream_init(&os,-1);
|
||||
err=OP_FALSE;
|
||||
do{
|
||||
ogg_packet op;
|
||||
@ -104,11 +104,11 @@ int op_test(OpusHead *_head,
|
||||
if(ret<0)continue;
|
||||
/*Stop if we run out of data.*/
|
||||
if(!ret)break;
|
||||
ogg_stream_reset_serialno(os,ogg_page_serialno(&og));
|
||||
ogg_stream_pagein(os,&og);
|
||||
ogg_stream_reset_serialno(&os,ogg_page_serialno(&og));
|
||||
ogg_stream_pagein(&os,&og);
|
||||
/*Only process the first packet on this page (if it's a BOS packet,
|
||||
it's required to be the only one).*/
|
||||
if(ogg_stream_packetout(os,&op)==1){
|
||||
if(ogg_stream_packetout(&os,&op)==1){
|
||||
if(op.b_o_s){
|
||||
ret=opus_head_parse(_head,op.packet,op.bytes);
|
||||
/*If this didn't look like Opus, keep going.*/
|
||||
@ -122,8 +122,7 @@ int op_test(OpusHead *_head,
|
||||
}
|
||||
}
|
||||
while(err==OP_FALSE);
|
||||
ogg_stream_clear(os);
|
||||
free(os);
|
||||
ogg_stream_clear(&os);
|
||||
}
|
||||
else err=OP_EFAULT;
|
||||
ogg_sync_clear(&oy);
|
||||
@ -836,7 +835,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
ogg_int64_t cur_page_gp;
|
||||
ogg_uint32_t serialno;
|
||||
opus_int32 total_duration;
|
||||
int *durations = (int*)malloc(255 * sizeof(int));
|
||||
int durations[255];
|
||||
int cur_page_eos;
|
||||
int op_count;
|
||||
int pi;
|
||||
@ -853,31 +852,26 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
Otherwise there are no audio data packets in the whole logical stream.*/
|
||||
if(OP_UNLIKELY(page_offset<0)){
|
||||
/*Fail if there was a read error.*/
|
||||
if(page_offset<OP_FALSE) { free(durations); return (int)page_offset; }
|
||||
if(page_offset<OP_FALSE)return (int)page_offset;
|
||||
/*Fail if the pre-skip is non-zero, since it's asking us to skip more
|
||||
samples than exist.*/
|
||||
if(_link->head.pre_skip>0) {free(durations); return OP_EBADTIMESTAMP;}
|
||||
if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
|
||||
_link->pcm_file_offset=0;
|
||||
/*Set pcm_end and end_offset so we can skip the call to
|
||||
op_find_final_pcm_offset().*/
|
||||
_link->pcm_start=_link->pcm_end=0;
|
||||
_link->end_offset=_link->data_offset;
|
||||
free(durations);
|
||||
return 0;
|
||||
}
|
||||
/*Similarly, if we hit the next link in the chain, we've gone too far.*/
|
||||
if(OP_UNLIKELY(ogg_page_bos(_og))){
|
||||
if(_link->head.pre_skip>0) {
|
||||
free(durations);
|
||||
return OP_EBADTIMESTAMP;
|
||||
}
|
||||
if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
|
||||
/*Set pcm_end and end_offset so we can skip the call to
|
||||
op_find_final_pcm_offset().*/
|
||||
_link->pcm_file_offset=0;
|
||||
_link->pcm_start=_link->pcm_end=0;
|
||||
_link->end_offset=_link->data_offset;
|
||||
/*Tell the caller we've got a buffered page for them.*/
|
||||
free(durations);
|
||||
return 1;
|
||||
}
|
||||
/*Ignore pages from other streams (not strictly necessary, because of the
|
||||
@ -907,10 +901,7 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
cur_page_gp=_of->op[op_count-1].granulepos;
|
||||
/*But getting a packet without a valid granule position on the page is not
|
||||
okay.*/
|
||||
if(cur_page_gp==-1) {
|
||||
free(durations);
|
||||
return OP_EBADTIMESTAMP;
|
||||
}
|
||||
if(cur_page_gp==-1)return OP_EBADTIMESTAMP;
|
||||
cur_page_eos=_of->op[op_count-1].e_o_s;
|
||||
if(OP_LIKELY(!cur_page_eos)){
|
||||
/*The EOS flag wasn't set.
|
||||
@ -919,7 +910,6 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
if(OP_UNLIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){
|
||||
/*The starting granule position MUST not be smaller than the amount of
|
||||
audio on the first page with completed packets.*/
|
||||
free(durations);
|
||||
return OP_EBADTIMESTAMP;
|
||||
}
|
||||
}
|
||||
@ -933,7 +923,6 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
/*However, the end-trimming MUST not ask us to trim more samples than
|
||||
exist after applying the pre-skip.*/
|
||||
if(OP_UNLIKELY(op_granpos_cmp(cur_page_gp,_link->head.pre_skip)<0)){
|
||||
free(durations);
|
||||
return OP_EBADTIMESTAMP;
|
||||
}
|
||||
}
|
||||
@ -968,7 +957,6 @@ static int op_find_initial_pcm_offset(OggOpusFile *_of,
|
||||
_link->pcm_file_offset=0;
|
||||
_of->prev_packet_gp=_link->pcm_start=pcm_start;
|
||||
_of->prev_page_offset=page_offset;
|
||||
free(durations);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1403,34 +1391,32 @@ static int op_open_seekable2_impl(OggOpusFile *_of){
|
||||
/*64 seek records should be enough for anybody.
|
||||
Actually, with a bisection search in a 63-bit range down to OP_CHUNK_SIZE
|
||||
granularity, much more than enough.*/
|
||||
OpusSeekRecord *sr = (OpusSeekRecord*)malloc(64 * sizeof(OpusSeekRecord));
|
||||
OpusSeekRecord sr[64];
|
||||
opus_int64 data_offset;
|
||||
int ret;
|
||||
/*We can seek, so set out learning all about this file.*/
|
||||
(*_of->callbacks.seek)(_of->stream,0,SEEK_END);
|
||||
_of->offset=_of->end=(*_of->callbacks.tell)(_of->stream);
|
||||
if(OP_UNLIKELY(_of->end<0)){free(sr); return OP_EREAD;}
|
||||
if(OP_UNLIKELY(_of->end<0))return OP_EREAD;
|
||||
data_offset=_of->links[0].data_offset;
|
||||
if(OP_UNLIKELY(_of->end<data_offset)){ free(sr); return OP_EBADLINK;}
|
||||
if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
|
||||
/*Get the offset of the last page of the physical bitstream, or, if we're
|
||||
lucky, the last Opus page of the first link, as most Ogg Opus files will
|
||||
contain a single logical bitstream.*/
|
||||
ret=op_get_prev_page_serial(_of,sr,_of->end,
|
||||
_of->links[0].serialno,_of->serialnos,_of->nserialnos);
|
||||
if(OP_UNLIKELY(ret<0)){free(sr); return ret;}
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
/*If there's any trailing junk, forget about it.*/
|
||||
_of->end=sr[0].offset+sr[0].size;
|
||||
if(OP_UNLIKELY(_of->end<data_offset)){free(sr); return OP_EBADLINK;}
|
||||
if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
|
||||
/*Now enumerate the bitstream structure.*/
|
||||
ret = op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr),
|
||||
return op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr),
|
||||
&_of->serialnos,&_of->nserialnos,&_of->cserialnos);
|
||||
free(sr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int op_open_seekable2(OggOpusFile *_of){
|
||||
ogg_sync_state oy_start;
|
||||
ogg_stream_state *os_start = (ogg_stream_state*)malloc(sizeof(ogg_stream_state));
|
||||
ogg_stream_state os_start;
|
||||
ogg_packet *op_start;
|
||||
opus_int64 prev_page_offset;
|
||||
opus_int64 start_offset;
|
||||
@ -1449,9 +1435,9 @@ static int op_open_seekable2(OggOpusFile *_of){
|
||||
start_op_count=_of->op_count;
|
||||
/*This is a bit too large to put on the stack unconditionally.*/
|
||||
op_start=(ogg_packet *)_ogg_malloc(sizeof(*op_start)*start_op_count);
|
||||
if(op_start==NULL){free(os_start); return OP_EFAULT;}
|
||||
if(op_start==NULL)return OP_EFAULT;
|
||||
*&oy_start=_of->oy;
|
||||
*os_start=_of->os;
|
||||
*&os_start=_of->os;
|
||||
prev_page_offset=_of->prev_page_offset;
|
||||
start_offset=_of->offset;
|
||||
memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count);
|
||||
@ -1463,7 +1449,7 @@ static int op_open_seekable2(OggOpusFile *_of){
|
||||
ogg_stream_clear(&_of->os);
|
||||
ogg_sync_clear(&_of->oy);
|
||||
*&_of->oy=*&oy_start;
|
||||
*&_of->os=*os_start;
|
||||
*&_of->os=*&os_start;
|
||||
_of->offset=start_offset;
|
||||
_of->op_count=start_op_count;
|
||||
memcpy(_of->op,op_start,sizeof(*_of->op)*start_op_count);
|
||||
@ -1471,10 +1457,9 @@ static int op_open_seekable2(OggOpusFile *_of){
|
||||
_of->prev_packet_gp=_of->links[0].pcm_start;
|
||||
_of->prev_page_offset=prev_page_offset;
|
||||
_of->cur_discard_count=_of->links[0].head.pre_skip;
|
||||
if(OP_UNLIKELY(ret<0)){free(os_start); return ret;}
|
||||
if(OP_UNLIKELY(ret<0))return ret;
|
||||
/*And restore the position indicator.*/
|
||||
ret=(*_of->callbacks.seek)(_of->stream,op_position(_of),SEEK_SET);
|
||||
free(os_start);
|
||||
return OP_UNLIKELY(ret<0)?OP_EREAD:0;
|
||||
}
|
||||
|
||||
@ -1995,7 +1980,7 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
|
||||
ogg_stream_pagein(&_of->os,&og);
|
||||
if(OP_LIKELY(_of->ready_state>=OP_INITSET)){
|
||||
opus_int32 total_duration;
|
||||
int *durations = (int*)malloc(255 * sizeof(int));
|
||||
int durations[255];
|
||||
int op_count;
|
||||
int report_hole;
|
||||
report_hole=0;
|
||||
@ -2052,7 +2037,7 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
|
||||
Proceed to the next link, rather than risk playing back some
|
||||
samples that shouldn't have been played.*/
|
||||
_of->op_count=0;
|
||||
if(report_hole){ free(durations); return OP_HOLE; }
|
||||
if(report_hole)return OP_HOLE;
|
||||
continue;
|
||||
}
|
||||
/*By default discard 80 ms of data after a seek, unless we seek
|
||||
@ -2160,9 +2145,9 @@ static int op_fetch_and_process_page(OggOpusFile *_of,
|
||||
_of->prev_page_offset=_page_offset;
|
||||
_of->op_count=op_count=pi;
|
||||
}
|
||||
if(report_hole) { free(durations); return OP_HOLE; }
|
||||
if(report_hole)return OP_HOLE;
|
||||
/*If end-trimming didn't trim all the packets, we're done.*/
|
||||
if(op_count>0) { free(durations); return 0; }
|
||||
if(op_count>0)return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3016,7 +3001,7 @@ static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={
|
||||
#endif
|
||||
|
||||
#if defined(OP_FIXED_POINT)
|
||||
#if 0
|
||||
|
||||
/*Matrices for downmixing from the supported channel counts to stereo.
|
||||
The matrices with 5 or more channels are normalized to a total volume of 2.0,
|
||||
since most mixes sound too quiet if normalized to 1.0 (as there is generally
|
||||
@ -3025,6 +3010,7 @@ static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={
|
||||
32-bit number.*/
|
||||
static const opus_int16 OP_STEREO_DOWNMIX_Q14
|
||||
[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={
|
||||
#if OP_NCHANNELS_MAX>2
|
||||
/*3.0*/
|
||||
{
|
||||
{9598,0},{6786,6786},{0,9598}
|
||||
@ -3051,8 +3037,9 @@ static const opus_int16 OP_STEREO_DOWNMIX_Q14
|
||||
{6368,0},{4502,4502},{0,6368},{5515,3183},{3183,5515},{5515,3183},
|
||||
{3183,5515},{4502,4502}
|
||||
}
|
||||
#endif // OP_NCHANNELS_MAX>2
|
||||
};
|
||||
#endif
|
||||
|
||||
int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){
|
||||
return op_read_native(_of,_pcm,_buf_size,_li);
|
||||
}
|
||||
@ -3070,7 +3057,6 @@ static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
|
||||
for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i];
|
||||
}
|
||||
else{
|
||||
#if 0
|
||||
for(i=0;i<_nsamples;i++){
|
||||
opus_int32 l;
|
||||
opus_int32 r;
|
||||
@ -3086,8 +3072,6 @@ static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
|
||||
dst[2*i+0]=(opus_int16)OP_CLAMP(-32768,l+8192>>14,32767);
|
||||
dst[2*i+1]=(opus_int16)OP_CLAMP(-32768,r+8192>>14,32767);
|
||||
}
|
||||
#endif
|
||||
// noop, removed for RAM savings
|
||||
}
|
||||
}
|
||||
return _nsamples;
|
||||
|
@ -729,7 +729,7 @@ struct OpusServerInfo{
|
||||
/**The software used by the origin server (Server).
|
||||
This is <code>NULL</code> if there was no <code>Server</code> header.*/
|
||||
char *server;
|
||||
/**The media type of the entity sent to the recipient (Content-Type).
|
||||
/**The media type of the entity sent to the recepient (Content-Type).
|
||||
This is <code>NULL</code> if there was no <code>Content-Type</code>
|
||||
header.*/
|
||||
char *content_type;
|
||||
|
@ -9,11 +9,7 @@
|
||||
},
|
||||
"version": "2.6.7",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*",
|
||||
"dependencies": [
|
||||
{
|
||||
"name": "SPI"
|
||||
}
|
||||
]
|
||||
"libCompatMode": "strict",
|
||||
"platforms": ["espressif8266"]
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
"url": "https://github.com/arendst/Tasmota/lib/lib_basic/TasmotaLED"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"libCompatMode": "strict",
|
||||
"platforms": [
|
||||
"espressif32"
|
||||
]
|
||||
|
@ -24,13 +24,15 @@
|
||||
#include "TasmotaLED.h"
|
||||
|
||||
// DRAM_ATTR to force in IRAM because we use this in show loop
|
||||
static const DRAM_ATTR uint8_t TASMOTALED_CHANNEL_ORDERS[6][3] = {
|
||||
{1, 0, 2}, // GRB (0)
|
||||
{2, 0, 1}, // GBR (1)
|
||||
static const DRAM_ATTR uint8_t TASMOTALED_CHANNEL_ORDERS[8][3] = {
|
||||
{1, 0, 2}, // Def=GRB (0)
|
||||
{1, 0, 2}, // GRB (1)
|
||||
{0, 1, 2}, // RGB (2)
|
||||
{0, 2, 1}, // RBG (3)
|
||||
{2, 1, 0}, // BRG (4)
|
||||
{1, 2, 0} // BGR (5)
|
||||
{1, 2, 0}, // BGR (5)
|
||||
{2, 0, 1}, // GBR (6)
|
||||
{1, 0, 2} // GRB (7) // fallback if erroneous value
|
||||
};
|
||||
|
||||
static const TasmotaLED_Timing TasmotaLED_Timings[] = {
|
||||
@ -61,8 +63,6 @@ enum LoggingLevels {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_D
|
||||
|
||||
TasmotaLED::TasmotaLED(uint16_t type, uint16_t num_leds) :
|
||||
_type(type),
|
||||
_pixel_order((type >> 4) & 0x07),
|
||||
_w_before(type & 0x08),
|
||||
_timing((type >> 8) & 0xFF),
|
||||
_started(false),
|
||||
_dirty(true),
|
||||
@ -70,19 +70,17 @@ TasmotaLED::TasmotaLED(uint16_t type, uint16_t num_leds) :
|
||||
_pixel_count(num_leds),
|
||||
_buf_work(nullptr),
|
||||
_buf_show(nullptr),
|
||||
_pixel_matrix(&TASMOTALED_CHANNEL_ORDERS[0]),
|
||||
_pusher(nullptr)
|
||||
{
|
||||
_adjustSubType(); // compute values for _pixel_order, _w_before, _pixel_matrix
|
||||
if (_timing > (TasmotaLed_TimingEnd >> 8)) {
|
||||
_timing = 0;
|
||||
}
|
||||
switch (_type & 0x0F) {
|
||||
// case TasmotaLed_1_W:
|
||||
// _pixel_size = 1;
|
||||
// break;
|
||||
case TasmotaLed_4_WRGB:
|
||||
_pixel_size = 4;
|
||||
break;
|
||||
case TasmotaLed_1_Def:
|
||||
case TasmotaLed_3_RGB:
|
||||
default: // fallback
|
||||
_pixel_size = 3;
|
||||
@ -109,6 +107,35 @@ TasmotaLED::~TasmotaLED() {
|
||||
_buf_show = nullptr;
|
||||
}
|
||||
|
||||
// Adjust all internal parameters accouring to sub-type
|
||||
void TasmotaLED::_adjustSubType(void) {
|
||||
_pixel_order = (_type >> 4) & 0x07;
|
||||
_pixel_matrix = &TASMOTALED_CHANNEL_ORDERS[_pixel_order];
|
||||
_w_before = _type & 0x08;
|
||||
}
|
||||
|
||||
void TasmotaLED::SetPixelCount(uint16_t num_leds) {
|
||||
if (num_leds != _pixel_count) {
|
||||
_pixel_count = num_leds;
|
||||
delete _buf_work;
|
||||
_buf_work = new uint8_t[_pixel_count * _pixel_size];
|
||||
memset(_buf_work, 0, _pixel_count * _pixel_size);
|
||||
delete _buf_show;
|
||||
_buf_show = new uint8_t[_pixel_count * _pixel_size];
|
||||
memset(_buf_show, 0, _pixel_count * _pixel_size);
|
||||
if (_pusher) {
|
||||
_pusher->SetPixelCount(_pixel_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TasmotaLED::SetPixelSubType(uint8_t subtype) {
|
||||
// subtype is only the 8 lower bits of _type
|
||||
_type = (_type & 0xFF00) | (subtype & 0xFF);
|
||||
_adjustSubType();
|
||||
}
|
||||
|
||||
|
||||
// Color is passed as 0xWWRRGGBB and copied as WWRRGGBB in _buf_work
|
||||
void TasmotaLED::ClearTo(uint32_t wrgb, int32_t first, int32_t last) {
|
||||
// adjust first and last to be in range of 0 to _pixel_count-1
|
||||
|
@ -22,16 +22,17 @@
|
||||
|
||||
enum TasmotaLEDTypesEncoding : uint16_t {
|
||||
// bits 0..3 encode for number of bytes per pixel
|
||||
TasmotaLed_1_W = 0x0, // 1 byte per pixel (not used yet)
|
||||
TasmotaLed_3_RGB = 0x1, // 3 bytes per pixel
|
||||
TasmotaLed_4_WRGB = 0x2, // 4 bytes per pixel
|
||||
TasmotaLed_1_Def = 0x0, // Default value - identical to TasmotaLed_3_RGB
|
||||
TasmotaLed_3_RGB = 0x1, // 3 bytes per pixel
|
||||
TasmotaLed_4_WRGB = 0x2, // 4 bytes per pixel
|
||||
// bits 4..6 encode for pixel order
|
||||
TasmotaLed_GRB = 0b000 << 4,
|
||||
TasmotaLed_GBR = 0b001 << 4,
|
||||
TasmotaLed_Def = 0b000 << 4, // Default value - identical to TasmotaLed_GRB
|
||||
TasmotaLed_GRB = 0b001 << 4,
|
||||
TasmotaLed_RGB = 0b010 << 4,
|
||||
TasmotaLed_RBG = 0b011 << 4,
|
||||
TasmotaLed_BRG = 0b100 << 4,
|
||||
TasmotaLed_BGR = 0b101 << 4,
|
||||
TasmotaLed_GBR = 0b110 << 4,
|
||||
// bit 7 sets the position for W channel
|
||||
TasmotaLed_xxxW = 0b0 << 7, // W channel after color
|
||||
TasmotaLed_Wxxx = 0b1 << 7, // W channel before color
|
||||
@ -91,6 +92,10 @@ public:
|
||||
TasmotaLED(uint16_t type, uint16_t num_leds);
|
||||
~TasmotaLED();
|
||||
|
||||
void SetPixelCount(uint16_t num_leds);
|
||||
void SetPixelSubType(uint8_t type); // change only Pixel order and pixel size
|
||||
void _adjustSubType(void);
|
||||
|
||||
bool Begin(void);
|
||||
void SetPusher(TasmotaLEDPusher *pusher); // needs to be called before `Begin()`, sets the hardware implementation
|
||||
void Show(void); // pushes the pixels to the LED strip
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
}
|
||||
virtual bool Push(uint8_t *buf) = 0;
|
||||
virtual bool CanShow(void) = 0;
|
||||
virtual bool SetPixelCount(uint16_t pixel_count) = 0;
|
||||
|
||||
static uint32_t ResolveHardware(uint32_t hw); // convert to the appropriate hardware acceleration based on capacities of the SOC
|
||||
static TasmotaLEDPusher * Create(uint32_t hw, int8_t gpio); // create instance for the provided type, or nullptr if failed
|
||||
@ -118,6 +119,7 @@ public:
|
||||
~TasmotaLEDPusherRMT();
|
||||
|
||||
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||
bool SetPixelCount(uint16_t pixel_count) override;
|
||||
|
||||
bool Push(uint8_t *buf) override;
|
||||
bool CanShow(void) override;
|
||||
@ -152,6 +154,7 @@ public:
|
||||
~TasmotaLEDPusherSPI();
|
||||
|
||||
bool Begin(uint16_t pixel_count, uint16_t pixel_size, const TasmotaLED_Timing * led_timing) override;
|
||||
bool SetPixelCount(uint16_t pixel_count) override;
|
||||
|
||||
bool Push(uint8_t *buf) override;
|
||||
bool CanShow(void) override;
|
||||
|
@ -213,6 +213,15 @@ bool TasmotaLEDPusherRMT::Begin(uint16_t pixel_count, uint16_t pixel_size, const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TasmotaLEDPusherRMT::SetPixelCount(uint16_t pixel_count) {
|
||||
if (!_initialized) { return false; }
|
||||
if (pixel_count > 0 && _pixel_count != pixel_count) {
|
||||
_pixel_count = pixel_count;
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TasmotaLEDPusherRMT::CanShow(void) {
|
||||
if (_channel && _initialized) {
|
||||
return (ESP_OK == rmt_tx_wait_all_done(_channel, 0));
|
||||
|
@ -104,7 +104,7 @@ TasmotaLEDPusherSPI::TasmotaLEDPusherSPI(int8_t pin) : _pin(pin) {
|
||||
.sclk_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE,
|
||||
.max_transfer_sz = 0, // _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE,
|
||||
};
|
||||
_err = spi_bus_initialize(spi_host, &spi_bus_cfg, _with_dma ? SPI_DMA_CH_AUTO : SPI_DMA_DISABLED);
|
||||
if (_err == ESP_OK) {
|
||||
@ -176,6 +176,39 @@ err:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TasmotaLEDPusherSPI::SetPixelCount(uint16_t pixel_count) {
|
||||
if (!_initialized) { return false; }
|
||||
if (pixel_count > 0 && _pixel_count != pixel_count) {
|
||||
_pixel_count = pixel_count;
|
||||
|
||||
if (_spi_strip.pixel_buf) {
|
||||
heap_caps_free(_spi_strip.pixel_buf);
|
||||
_spi_strip.pixel_buf = nullptr;
|
||||
}
|
||||
|
||||
_spi_strip.strip_len = _pixel_count;
|
||||
uint32_t mem_caps = MALLOC_CAP_DEFAULT;
|
||||
if (_with_dma) { // TODO
|
||||
// DMA buffer must be placed in internal SRAM
|
||||
mem_caps |= MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
|
||||
}
|
||||
_spi_strip.pixel_buf = (uint8_t *)heap_caps_calloc(1, _pixel_count * _pixel_size * SPI_BYTES_PER_COLOR_BYTE, mem_caps);
|
||||
if (_spi_strip.pixel_buf == nullptr) {
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("LED: Error no mem for spi strip"));
|
||||
if (_spi_strip.spi_device) {
|
||||
spi_bus_remove_device(_spi_strip.spi_device);
|
||||
}
|
||||
if (_spi_strip.spi_host) {
|
||||
spi_bus_free(_spi_strip.spi_host);
|
||||
}
|
||||
_initialized = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TasmotaLEDPusherSPI::CanShow(void) {
|
||||
return _initialized; // TODO
|
||||
}
|
||||
|
@ -1225,12 +1225,19 @@ Renderer *uDisplay::Init(void) {
|
||||
_panel_config->de_gpio_num = de;
|
||||
_panel_config->pclk_gpio_num = pclk;
|
||||
|
||||
// assume that byte swapping of 16-bit color is done only upon request
|
||||
// via display.ini and not by callers of pushColor()
|
||||
// -> swap bytes by swapping GPIO numbers
|
||||
int8_t *par_db8 = lvgl_param.swap_color ? par_dbl : par_dbh;
|
||||
for (uint32_t cnt = 0; cnt < 8; cnt ++) {
|
||||
_panel_config->data_gpio_nums[cnt] = par_dbh[cnt];
|
||||
_panel_config->data_gpio_nums[cnt] = par_db8[cnt];
|
||||
}
|
||||
par_db8 = lvgl_param.swap_color ? par_dbh : par_dbl;
|
||||
for (uint32_t cnt = 0; cnt < 8; cnt ++) {
|
||||
_panel_config->data_gpio_nums[cnt + 8] = par_dbl[cnt];
|
||||
_panel_config->data_gpio_nums[cnt + 8] = par_db8[cnt];
|
||||
}
|
||||
lvgl_param.swap_color = 0;
|
||||
|
||||
_panel_config->disp_gpio_num = GPIO_NUM_NC;
|
||||
|
||||
_panel_config->flags.disp_active_low = 0;
|
||||
@ -1781,9 +1788,6 @@ void uDisplay::drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) {
|
||||
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
if (cur_rot > 0) {
|
||||
while (h--) {
|
||||
drawPixel_RGB(x , y , color);
|
||||
@ -1854,9 +1858,6 @@ void uDisplay::drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) {
|
||||
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
if (cur_rot > 0) {
|
||||
while (w--) {
|
||||
drawPixel_RGB(x , y , color);
|
||||
@ -2228,7 +2229,6 @@ void uDisplay::pushColorsMono(uint16_t *data, uint16_t len, bool rgb16_swap) {
|
||||
static inline void lvgl_color_swap(uint16_t *data, uint16_t len) { for (uint32_t i = 0; i < len; i++) (data[i] = data[i] << 8 | data[i] >> 8); }
|
||||
|
||||
void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
uint16_t color;
|
||||
|
||||
if (lvgl_param.swap_color) {
|
||||
not_swapped = !not_swapped;
|
||||
@ -2238,63 +2238,21 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
|
||||
// Isolating _UDSP_RGB to increase code sharing
|
||||
//
|
||||
// LVGL documentation suggest to call the following:
|
||||
// lv_draw_sw_rgb565_swap() to invert bytes
|
||||
// esp_lcd_panel_draw_bitmap() to paste bytes
|
||||
// but it appears to be faster to include the color swap in the copy loop
|
||||
// because the CPU is much faster than PSRAM (SPI bus), therefore
|
||||
// swapping bytes on the fly costs zero performance
|
||||
//
|
||||
// not_swapped == false : called from LVGL bytes are swapped
|
||||
// not_swapped == true : called from displaytext, no byte swap, currently no dma here
|
||||
// Use ESP-IDF LCD driver to push colors and rely on the following assumptions:
|
||||
// * bytes swapping is already handled in the driver configuration (see uDisplay::Init()),
|
||||
// * pushColors() is only called with not_swapped equals true,
|
||||
// * cache flushing is done by the LCD driver.
|
||||
if (interface == _UDSP_RGB) {
|
||||
#ifdef USE_ESP32_S3
|
||||
if (!not_swapped) {
|
||||
// internal error -> write error message but continue (with possibly wrong colors)
|
||||
AddLog(LOG_LEVEL_ERROR, PSTR("DSP: Unexpected byte-swapping requested in pushColors()"));
|
||||
}
|
||||
|
||||
// check that bytes count matches the size of area, and remove from inner loop
|
||||
if ((seta_yp2 - seta_yp1) * (seta_xp2 - seta_xp2) > len) { return; }
|
||||
|
||||
uint16_t lenc = len;
|
||||
|
||||
if (cur_rot > 0) {
|
||||
for (uint32_t y = seta_yp1; y < seta_yp2; y++) {
|
||||
seta_yp1++;
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
if (!not_swapped) { color = color << 8 | color >> 8; }
|
||||
drawPixel_RGB(x, y, color);
|
||||
lenc--;
|
||||
if (!lenc) return; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint16_t *fb_y = rgb_fb + (int32_t)seta_yp1 * _width;
|
||||
for (uint32_t y = seta_yp1; y < seta_yp2; y++) {
|
||||
uint16_t * fb_xy = fb_y + seta_xp1;
|
||||
// we get the 'not_swapped' test outside of the inner loop
|
||||
if (not_swapped) {
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
*fb_xy = color;
|
||||
fb_xy++;
|
||||
lenc--;
|
||||
if (!lenc) break; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
} else {
|
||||
for (uint32_t x = seta_xp1; x < seta_xp2; x++) {
|
||||
uint16_t color = *data++;
|
||||
color = color << 8 | color >> 8;
|
||||
*fb_xy = color;
|
||||
fb_xy++;
|
||||
lenc--;
|
||||
if (!lenc) break; // failsafe - exist if len (pixel number) is exhausted
|
||||
}
|
||||
}
|
||||
uint16_t * flush_ptr = rgb_fb + (int32_t)seta_yp1 * _width + seta_xp1;
|
||||
Cache_WriteBack_Addr((uint32_t)flush_ptr, (seta_xp2 - seta_xp1) * 2);
|
||||
fb_y += _width;
|
||||
seta_yp1++;
|
||||
if (!lenc) break;
|
||||
}
|
||||
}
|
||||
esp_lcd_panel_draw_bitmap(_panel_handle, seta_xp1, seta_yp1, seta_xp2, seta_yp2, (void *)data);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@ -2329,6 +2287,7 @@ void uDisplay::pushColors(uint16_t *data, uint16_t len, boolean not_swapped) {
|
||||
uint8_t *line = (uint8_t*)malloc(len * 3);
|
||||
uint8_t *lp = line;
|
||||
if (line) {
|
||||
uint16_t color;
|
||||
for (uint32_t cnt = 0; cnt < len; cnt++) {
|
||||
color = *data++;
|
||||
color = (color << 8) | (color >> 8);
|
||||
@ -2463,9 +2422,6 @@ void uDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) {
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
if (interface == _UDSP_RGB) {
|
||||
if (lvgl_param.swap_color) {
|
||||
color = color << 8 | color >> 8;
|
||||
}
|
||||
drawPixel_RGB(x, y, color);
|
||||
return;
|
||||
}
|
||||
@ -2548,6 +2504,15 @@ void uDisplay::setRotation(uint8_t rotation) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32_S3
|
||||
if (interface == _UDSP_RGB) {
|
||||
// utilize the ESP-IDF LCD driver's support for display rotation:
|
||||
// mirror x axis for rotation 1 and 2, mirror y axis for rotation 2 and 3
|
||||
esp_lcd_panel_mirror(_panel_handle, rotation == 1 || rotation == 2, rotation & 2);
|
||||
// swap x/y for rotation 1 and 3
|
||||
esp_lcd_panel_swap_xy(_panel_handle, rotation & 1);
|
||||
}
|
||||
#endif // USE_ESP32_S3
|
||||
}
|
||||
|
||||
void udisp_bpwr(uint8_t on);
|
||||
|
@ -97,7 +97,7 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR };
|
||||
#define UDISP_WHITE 0xFFFF /* 255, 255, 255 */
|
||||
#define UDISP_ORANGE 0xFD20 /* 255, 165, 0 */
|
||||
#define UDISP_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
|
||||
#define UDISP_PINK 0xF81F
|
||||
#define UDISP_PINK 0xFc18 /* 255, 128, 192 */
|
||||
|
||||
#ifdef ESP8266
|
||||
#define PIN_OUT_SET 0x60000304
|
||||
|
21
lib/lib_div/FastCRC/LICENCE.md
Normal file
21
lib/lib_div/FastCRC/LICENCE.md
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Frank
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
56
lib/lib_div/FastCRC/README.md
Normal file
56
lib/lib_div/FastCRC/README.md
Normal file
@ -0,0 +1,56 @@
|
||||
FastCRC
|
||||
=======
|
||||
|
||||
Fast CRC Arduino library
|
||||
Up to 30 times faster than crc16.h (_avr_libc)
|
||||
|
||||
- uses the on-chip hardware for Teensy 3.0 / 3.1 / 3.2 / 3.5 / 3.6
|
||||
- uses fast table-algorithms for other chips
|
||||
|
||||
List of supported CRC calculations:
|
||||
-
|
||||
7 BIT:
|
||||
|
||||
CRC7
|
||||
(poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75)
|
||||
MultiMediaCard interface
|
||||
|
||||
|
||||
8 BIT:
|
||||
|
||||
SMBUS
|
||||
(poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4)
|
||||
|
||||
MAXIM
|
||||
(poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1)
|
||||
|
||||
|
||||
16 BIT:
|
||||
|
||||
KERMIT (Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT)
|
||||
(poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
|
||||
Attention: sometimes you'll find byteswapped presentation of result in other implementations)
|
||||
|
||||
CCITT-FALSE
|
||||
(poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1)
|
||||
|
||||
MCRF4XX
|
||||
(poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91)
|
||||
|
||||
MODBUS
|
||||
(poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37)
|
||||
|
||||
XMODEM (Alias ZMODEM, CRC-16/ACORN)
|
||||
(poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3)
|
||||
|
||||
X25 (Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B)
|
||||
(poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e)
|
||||
|
||||
|
||||
32 BIT:
|
||||
|
||||
CRC32, CRC-32/ADCCP, PKZIP, ETHERNET, 802.3
|
||||
(poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926)
|
||||
|
||||
CKSUM, CRC-32/POSIX
|
||||
(poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680)
|
59
lib/lib_div/FastCRC/keywords.txt
Normal file
59
lib/lib_div/FastCRC/keywords.txt
Normal file
@ -0,0 +1,59 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For FastCRC
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
FastCRC7 KEYWORD1
|
||||
FastCRC8 KEYWORD1
|
||||
FastCRC14 KEYWORD1
|
||||
FastCRC16 KEYWORD1
|
||||
FastCRC32 KEYWORD1
|
||||
CRC7 KEYWORD1
|
||||
CRC8 KEYWORD1
|
||||
CRC14 KEYWORD1
|
||||
CRC16 KEYWORD1
|
||||
CRC32 KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
crc7 KEYWORD2
|
||||
crc7_upd KEYWORD2
|
||||
ccitt KEYWORD2
|
||||
ccitt_upd KEYWORD2
|
||||
kermit KEYWORD2
|
||||
kermit_upd KEYWORD2
|
||||
mcrf4xx KEYWORD2
|
||||
mcrf4xx_upd KEYWORD2
|
||||
modbus KEYWORD2
|
||||
modbus_upd KEYWORD2
|
||||
xmodem KEYWORD2
|
||||
xmodem_upd KEYWORD2
|
||||
x25 KEYWORD2
|
||||
x25_upd KEYWORD2
|
||||
update KEYWORD2
|
||||
update_upd KEYWORD2
|
||||
generic KEYWORD2
|
||||
crc32 KEYWORD2
|
||||
crc32_upd KEYWORD2
|
||||
cksum KEYWORD2
|
||||
cksum_upd KEYWORD2
|
||||
darc KEYWORD2
|
||||
darc_upd KEYWORD2
|
||||
gsm KEYWORD2
|
||||
gsm_upd KEYWORD2
|
||||
eloran KEYWORD2
|
||||
eloran_upd KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
CRC_FLAG_NOREFLECT LITERAL1
|
||||
CRC_FLAG_REFLECT LITERAL1
|
||||
CRC_FLAG_XOR LITERAL1
|
||||
CRC_FLAG_NOREFLECT_8 LITERAL1
|
||||
CRC_FLAG_REFLECT_SWAP LITERAL1
|
26
lib/lib_div/FastCRC/library.json
Normal file
26
lib/lib_div/FastCRC/library.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "FastCRC",
|
||||
"keywords": "CRC7, CRC8, CRC16, CRC32",
|
||||
"description": "Fast CRC routines for Arduino and PC (Teensy 3.x: CRC in hardware)",
|
||||
"exclude": [
|
||||
"examples",
|
||||
"examples_PC"
|
||||
],
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/FrankBoesing/FastCRC"
|
||||
},
|
||||
"authors":
|
||||
[
|
||||
{
|
||||
"name": "Frank Bösing",
|
||||
"email": "f.boesing@gmx.de",
|
||||
"url": "https://github.com/FrankBoesing/FastCRC",
|
||||
"maintainer": true
|
||||
}
|
||||
],
|
||||
"version": "1.44",
|
||||
"frameworks": "arduino",
|
||||
"platforms": "*"
|
||||
}
|
10
lib/lib_div/FastCRC/library.properties
Normal file
10
lib/lib_div/FastCRC/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=FastCRC
|
||||
version=1.44
|
||||
author=Frank Bösing
|
||||
maintainer=Frank Boesing<f.boesing@gmx.de>
|
||||
sentence=Fast CRC routines
|
||||
paragraph=
|
||||
category=Data Processing
|
||||
url=https://github.com/FrankBoesing/FastCRC
|
||||
architectures=*
|
||||
#dot_a_linkage=true
|
189
lib/lib_div/FastCRC/src/FastCRC.h
Normal file
189
lib/lib_div/FastCRC/src/FastCRC.h
Normal file
@ -0,0 +1,189 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 Frank Bösing
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
// Teensy 3.0, Teensy 3.1:
|
||||
// See K20P64M72SF1RM.pdf (Kinetis), Pages 638 - 641 for documentation of CRC Device
|
||||
// See KINETIS_4N30D.pdf for Errata (Errata ID 2776)
|
||||
//
|
||||
// So, ALL HW-calculations are done as 32 bit.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Thanks to:
|
||||
// - Catalogue of parametrised CRC algorithms, CRC RevEng
|
||||
// http://reveng.sourceforge.net/crc-catalogue/
|
||||
//
|
||||
// - Danjel McGougan (CRC-Table-Generator)
|
||||
//
|
||||
|
||||
|
||||
// Set this to 0 for smaller 32BIT-CRC-Tables:
|
||||
#if !defined(CRC_BIGTABLES)
|
||||
#define CRC_BIGTABLES 1
|
||||
#endif
|
||||
|
||||
#if !defined(FastCRC_h)
|
||||
#define FastCRC_h
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
// ================= DEFINES ===================
|
||||
#if defined(KINETISK)
|
||||
#define CRC_SW 0
|
||||
#define CRC_FLAG_NOREFLECT (((1<<31) | (1<<30)) | ((0<<29) | (0<<28))) //refin=false refout=false
|
||||
#define CRC_FLAG_REFLECT (((1<<31) | (0<<30)) | ((1<<29) | (0<<28))) //Reflect in- and outgoing bytes (refin=true refout=true)
|
||||
#define CRC_FLAG_XOR (1<<26) //Perform XOR on result
|
||||
#define CRC_FLAG_NOREFLECT_8 (0) //For 8-Bit CRC
|
||||
#define CRC_FLAG_REFLECT_SWAP (((1<<31) | (0<<30)) | ((0<<29) | (1<<28))) //For 16-Bit CRC (byteswap)
|
||||
#else
|
||||
#define CRC_SW 1
|
||||
#endif
|
||||
|
||||
// ================= 7-BIT CRC ===================
|
||||
class FastCRC7
|
||||
{
|
||||
public:
|
||||
FastCRC7();
|
||||
uint8_t crc7(const uint8_t *data, const size_t datalen); // (MultiMediaCard interface)
|
||||
uint8_t crc7_upd(const uint8_t *data, const size_t datalen); // Call for subsequent calculations with previous seed.
|
||||
#if !CRC_SW
|
||||
uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
|
||||
#endif
|
||||
private:
|
||||
#if CRC_SW
|
||||
uint8_t seed;
|
||||
#else
|
||||
uint8_t update(const uint8_t *data, const size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 8-BIT CRC ===================
|
||||
|
||||
class FastCRC8
|
||||
{
|
||||
public:
|
||||
FastCRC8();
|
||||
uint8_t smbus(const uint8_t *data, const size_t datalen); // Alias CRC-8
|
||||
uint8_t maxim(const uint8_t *data, const size_t datalen); // Equivalent to _crc_ibutton_update() in crc16.h from avr_libc
|
||||
|
||||
uint8_t smbus_upd(const uint8_t *data, size_t datalen); // Call for subsequent calculations with previous seed.
|
||||
uint8_t maxim_upd(const uint8_t *data, size_t datalen); // Call for subsequent calculations with previous seed.
|
||||
#if !CRC_SW
|
||||
uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
|
||||
#endif
|
||||
private:
|
||||
#if CRC_SW
|
||||
uint8_t seed;
|
||||
#else
|
||||
uint8_t update(const uint8_t *data, const size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 14-BIT CRC ===================
|
||||
|
||||
class FastCRC14
|
||||
{
|
||||
public:
|
||||
#if !CRC_SW //NO Software-implemenation so far
|
||||
FastCRC14();
|
||||
uint16_t darc(const uint8_t *data, const size_t datalen);
|
||||
uint16_t gsm(const uint8_t *data, const size_t datalen);
|
||||
uint16_t eloran(const uint8_t *data, const size_t datalen);
|
||||
uint16_t ft4(const uint8_t *data, const size_t datalen);
|
||||
|
||||
uint16_t darc_upd(const uint8_t *data, size_t len);
|
||||
uint16_t gsm_upd(const uint8_t *data, size_t len);
|
||||
uint16_t eloran_upd(const uint8_t *data, size_t len);
|
||||
uint16_t ft4_upd(const uint8_t *data, size_t len);
|
||||
#endif
|
||||
#if !CRC_SW
|
||||
uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
|
||||
#endif
|
||||
private:
|
||||
#if CRC_SW
|
||||
uint16_t seed;
|
||||
#else
|
||||
uint16_t update(const uint8_t *data, const size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 16-BIT CRC ===================
|
||||
|
||||
class FastCRC16
|
||||
{
|
||||
public:
|
||||
FastCRC16();
|
||||
uint16_t ccitt(const uint8_t *data, const size_t datalen); // Alias "false CCITT"
|
||||
uint16_t mcrf4xx(const uint8_t *data,const size_t datalen); // Equivalent to _crc_ccitt_update() in crc16.h from avr_libc
|
||||
uint16_t kermit(const uint8_t *data, const size_t datalen); // Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
|
||||
uint16_t modbus(const uint8_t *data, const size_t datalen); // Equivalent to _crc_16_update() in crc16.h from avr_libc
|
||||
uint16_t xmodem(const uint8_t *data, const size_t datalen); // Alias ZMODEM, CRC-16/ACORN
|
||||
uint16_t x25(const uint8_t *data, const size_t datalen); // Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
|
||||
|
||||
uint16_t ccitt_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t mcrf4xx_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t kermit_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t modbus_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t xmodem_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint16_t x25_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
#if !CRC_SW
|
||||
uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
|
||||
#endif
|
||||
private:
|
||||
#if CRC_SW
|
||||
uint16_t seed;
|
||||
#else
|
||||
uint16_t update(const uint8_t *data, const size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
// ================= 32-BIT CRC ===================
|
||||
|
||||
class FastCRC32
|
||||
{
|
||||
public:
|
||||
FastCRC32();
|
||||
uint32_t crc32(const uint8_t *data, const size_t datalen); // Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
|
||||
uint32_t cksum(const uint8_t *data, const size_t datalen); // Alias CRC-32/POSIX
|
||||
|
||||
uint32_t crc32_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
uint32_t cksum_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
|
||||
#if !CRC_SW
|
||||
uint32_t generic(const uint32_t polyom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
|
||||
#endif
|
||||
private:
|
||||
#if CRC_SW
|
||||
uint32_t seed;
|
||||
#else
|
||||
uint32_t update(const uint8_t *data, const size_t datalen);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
1596
lib/lib_div/FastCRC/src/FastCRC_tables.h
Normal file
1596
lib/lib_div/FastCRC/src/FastCRC_tables.h
Normal file
File diff suppressed because it is too large
Load Diff
567
lib/lib_div/FastCRC/src/FastCRChw.cpp
Normal file
567
lib/lib_div/FastCRC/src/FastCRChw.cpp
Normal file
@ -0,0 +1,567 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 Frank Bösing
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
//
|
||||
// HW-calculations are 32BIT
|
||||
//
|
||||
// Thanks to:
|
||||
// - Catalogue of parametrised CRC algorithms, CRC RevEng
|
||||
// http://reveng.sourceforge.net/crc-catalogue/
|
||||
//
|
||||
// - Danjel McGougan (CRC-Table-Generator)
|
||||
//
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
#if defined(KINETISK)
|
||||
|
||||
#include "mk20dx128.h"
|
||||
#include "FastCRC.h"
|
||||
|
||||
// ===============================================
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
uint32_t CRC; //CRC Data register
|
||||
struct {
|
||||
uint16_t CRC16;
|
||||
uint16_t CRC16_1;
|
||||
};
|
||||
struct {
|
||||
uint8_t CRC8;
|
||||
uint8_t CRC8_1;
|
||||
uint8_t CRC8_2;
|
||||
uint8_t CRC8_3;
|
||||
};
|
||||
};
|
||||
uint32_t GPOLY; //CRC Polynomial register
|
||||
uint32_t CTRL; //CRC Control register
|
||||
} CRC_T;
|
||||
|
||||
static volatile CRC_T * const rCRC = (CRC_T *)0x40032000;
|
||||
|
||||
#define CRC_CTRL_WAS 25 // Write CRC Data Register As Seed(1) / Data(0)
|
||||
#define CRC_CTRL_TCRC 24 // Width of CRC protocol (0=16 BIT, 1=32 BIT)
|
||||
#define CRC_CTRL_TOTR1 29 // TOTR[1]
|
||||
|
||||
// ================= 7-BIT CRC ===================
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC7::FastCRC7(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CRC 7
|
||||
* MultiMediaCard interface
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC7::crc7(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
|
||||
return (generic(0x09, 0, CRC_FLAG_NOREFLECT, data, datalen));
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC7::update(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
const uint8_t *src = data;
|
||||
const uint8_t *target = src + datalen;
|
||||
|
||||
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 BIT
|
||||
}
|
||||
|
||||
while (src <= target-4) {
|
||||
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
|
||||
src += 4;
|
||||
}
|
||||
|
||||
while (src < target) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 Bit
|
||||
}
|
||||
|
||||
//TODO: Check handling of CRC_CTRL_TOTR1 for other CRC7s
|
||||
/*
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->CRC8 >> 1;
|
||||
else
|
||||
*/
|
||||
return rCRC->CRC8_3 >> 1;
|
||||
}
|
||||
|
||||
/** generic function for all 7-Bit CRCs
|
||||
* @param polynom Polynom
|
||||
* @param seed Seed
|
||||
* @param flags Flags
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC7::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<(24 + 1); // Set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<(24 + 1)); // Write seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
|
||||
|
||||
|
||||
// ================= 8-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC8::FastCRC8(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
|
||||
/** SMBUS CRC
|
||||
* aka CRC-8
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
|
||||
return generic(0x07, 0, CRC_FLAG_NOREFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** MAXIM 8-Bit CRC
|
||||
* equivalent to _crc_ibutton_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::maxim(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
|
||||
return generic(0x31, 0, CRC_FLAG_REFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::update(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
const uint8_t *src = data;
|
||||
const uint8_t *target = src + datalen;
|
||||
|
||||
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 BIT
|
||||
}
|
||||
|
||||
while (src <= target-4) {
|
||||
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
|
||||
src += 4;
|
||||
}
|
||||
|
||||
while (src < target) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 Bit
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->CRC8;
|
||||
else
|
||||
return rCRC->CRC8_3;
|
||||
}
|
||||
|
||||
/** generic function for all 8-Bit CRCs
|
||||
* @param polynom Polynom
|
||||
* @param seed Seed
|
||||
* @param flags Flags
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<24; // Set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<24); // Write seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
|
||||
|
||||
|
||||
|
||||
// ================= 14-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC14::FastCRC14(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CRC-14/DARC
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::darc(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d residue=0x0000
|
||||
return generic(0x0805, 0x0000, CRC_FLAG_REFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/GSM
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::gsm(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x202d init=0x0000 refin=false refout=false xorout=0x3fff check=0x30ae residue=0x031e
|
||||
return generic(0x202d, 0x0000, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/ELORAN
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::eloran(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x60b1 init=0x0000 refin=false refout=false xorout=0x0000 check=0x38d1
|
||||
return generic(0x60b1, 0x0, CRC_FLAG_NOREFLECT , data, datalen);
|
||||
}
|
||||
|
||||
/** CRC-14/ft4 : TODO
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
/*
|
||||
uint16_t FastCRC14::ft4(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
|
||||
return generic(, , , data, datalen);
|
||||
}
|
||||
*/
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::update(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
const uint8_t *src = data;
|
||||
const uint8_t *target = src + datalen;
|
||||
|
||||
while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 BIT
|
||||
}
|
||||
|
||||
while (src <= target-4) {
|
||||
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
|
||||
src += 4;
|
||||
}
|
||||
|
||||
while (src < target) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 Bit
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->CRC16;
|
||||
else
|
||||
return rCRC->CRC >> (32 - 14);
|
||||
}
|
||||
|
||||
/** generic function for all 14-Bit CRCs
|
||||
* @param polynom Polynom
|
||||
* @param seed Seed
|
||||
* @param flags Flags
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC14::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom) << (32 - 14); // set polynom
|
||||
rCRC->CRC = ((uint32_t)seed << (32 - 14) ); // this is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint16_t FastCRC14::darc_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC14::gsm_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC14::eloran_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
//uint16_t FastCRC14::ft4(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
|
||||
|
||||
// ================= 16-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC16::FastCRC16(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CCITT
|
||||
* Alias "false CCITT"
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_NOREFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** MCRF4XX
|
||||
* equivalent to _crc_ccitt_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT , data, datalen);
|
||||
}
|
||||
|
||||
/** MODBUS
|
||||
* equivalent to _crc_16_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::modbus(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
|
||||
return generic(0x8005, 0XFFFF, CRC_FLAG_REFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** KERMIT
|
||||
* Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::kermit(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
|
||||
// sometimes byteswapped presentation of result
|
||||
return generic(0x1021, 0x00, CRC_FLAG_REFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** XMODEM
|
||||
* Alias ZMODEM, CRC-16/ACORN
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::xmodem(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
//width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
|
||||
return generic(0x1021, 0, CRC_FLAG_NOREFLECT, data, datalen);
|
||||
}
|
||||
|
||||
/** X25
|
||||
* Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::x25(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
|
||||
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::update(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
const uint8_t *src = data;
|
||||
const uint8_t *target = src + datalen;
|
||||
|
||||
while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 BIT
|
||||
}
|
||||
|
||||
while (src <= target-4) {
|
||||
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
|
||||
src += 4;
|
||||
}
|
||||
|
||||
while (src < target) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 Bit
|
||||
}
|
||||
|
||||
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
|
||||
return rCRC->CRC16;
|
||||
else
|
||||
return rCRC->CRC16_1;
|
||||
}
|
||||
|
||||
/** generic function for all 16-Bit CRCs
|
||||
* @param polynom Polynom
|
||||
* @param seed Seed
|
||||
* @param flags Flags
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = ((uint32_t)polynom)<<16; // set polynom
|
||||
rCRC->CRC = ((uint32_t)seed<<16); // this is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len) {return update(data, len);}
|
||||
|
||||
|
||||
|
||||
// ================= 32-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
* Enables CRC-clock
|
||||
*/
|
||||
FastCRC32::FastCRC32(){
|
||||
SIM_SCGC6 |= SIM_SCGC6_CRC;
|
||||
}
|
||||
|
||||
/** CRC32
|
||||
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
|
||||
return generic(0x04C11DB7L, 0XFFFFFFFFL, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** CKSUM
|
||||
* Alias CRC-32/POSIX
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
|
||||
return generic(0x04C11DB7L, 0, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
|
||||
}
|
||||
|
||||
/** Update
|
||||
* Call for subsequent calculations with previous seed
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
//#pragma GCC diagnostic ignored "-Wpointer-arith"
|
||||
uint32_t FastCRC32::update(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
const uint8_t *src = data;
|
||||
const uint8_t *target = src + datalen;
|
||||
|
||||
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 BIT
|
||||
}
|
||||
|
||||
while (src <= target-4) {
|
||||
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
|
||||
src += 4;
|
||||
}
|
||||
|
||||
while (src < target) {
|
||||
rCRC->CRC8_3 = *src++; //Write 8 Bit
|
||||
}
|
||||
|
||||
return rCRC->CRC;
|
||||
}
|
||||
|
||||
/** generic function for all 32-Bit CRCs
|
||||
* @param polynom Polynom
|
||||
* @param seed Seed
|
||||
* @param flags Flags
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint32_t FastCRC32::generic(const uint32_t polynom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, prepare to write seed(25)
|
||||
rCRC->GPOLY = polynom; // Set polynom
|
||||
rCRC->CRC = seed; // This is the seed
|
||||
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
|
||||
|
||||
return update(data, datalen);
|
||||
}
|
||||
|
||||
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len){return update(data, len);}
|
||||
#endif // #if defined(KINETISK)
|
541
lib/lib_div/FastCRC/src/FastCRCsw.cpp
Normal file
541
lib/lib_div/FastCRC/src/FastCRCsw.cpp
Normal file
@ -0,0 +1,541 @@
|
||||
/* FastCRC library code is placed under the MIT license
|
||||
* Copyright (c) 2014 - 2021 Frank Bösing
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
//
|
||||
// Thanks to:
|
||||
// - Catalogue of parametrised CRC algorithms, CRC RevEng
|
||||
// http://reveng.sourceforge.net/crc-catalogue/
|
||||
//
|
||||
// - Danjel McGougan (CRC-Table-Generator)
|
||||
//
|
||||
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#endif
|
||||
|
||||
#if !defined(KINETISK)
|
||||
|
||||
#if !defined(ARDUINO)
|
||||
#define PROGMEM
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned short *)(_addr); \
|
||||
})
|
||||
#define pgm_read_dword(addr) ({ \
|
||||
typeof(addr) _addr = (addr); \
|
||||
*(const unsigned long *)(_addr); \
|
||||
})
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#include "FastCRC.h"
|
||||
#include "FastCRC_tables.h"
|
||||
|
||||
|
||||
static inline
|
||||
uint32_t REV16( uint32_t value)
|
||||
{
|
||||
return (value >> 8) | ((value & 0xff) << 8);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint32_t REV32( uint32_t value)
|
||||
{
|
||||
value = (value >> 16) | ((value & 0xffff) << 16);
|
||||
return ((value >> 8) & 0xff00ff) | ((value & 0xff00ff) << 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ================= 7-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
FastCRC7::FastCRC7(){}
|
||||
|
||||
/** SMBUS CRC
|
||||
* aka CRC-8
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen)
|
||||
{
|
||||
uint8_t crc = seed;
|
||||
if (datalen) do {
|
||||
crc = pgm_read_byte(&crc_table_crc7[crc ^ *data]);
|
||||
data++;
|
||||
} while (--datalen);
|
||||
seed = crc;
|
||||
return crc >> 1;
|
||||
}
|
||||
|
||||
uint8_t FastCRC7::crc7(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
|
||||
seed = 0x00;
|
||||
return crc7_upd(data, datalen);
|
||||
}
|
||||
|
||||
// ================= 8-BIT CRC ===================
|
||||
|
||||
/** Constructor
|
||||
*/
|
||||
FastCRC8::FastCRC8(){}
|
||||
|
||||
/** SMBUS CRC
|
||||
* aka CRC-8
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen)
|
||||
{
|
||||
uint8_t crc = seed;
|
||||
if (datalen) do {
|
||||
crc = pgm_read_byte(&crc_table_smbus[crc ^ *data]);
|
||||
data++;
|
||||
} while (--datalen);
|
||||
seed = crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
|
||||
seed = 0x00;
|
||||
return smbus_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** MAXIM 8-Bit CRC
|
||||
* equivalent to _crc_ibutton_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen)
|
||||
{
|
||||
uint8_t crc = seed;
|
||||
if (datalen) do {
|
||||
crc = pgm_read_byte(&crc_table_maxim[crc ^ *data]);
|
||||
data++;
|
||||
} while (--datalen);
|
||||
seed = crc;
|
||||
return crc;
|
||||
}
|
||||
uint8_t FastCRC8::maxim(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
|
||||
seed = 0x00;
|
||||
return maxim_upd(data, datalen);
|
||||
}
|
||||
|
||||
// ================= 16-BIT CRC ===================
|
||||
/** Constructor
|
||||
*/
|
||||
FastCRC16::FastCRC16(){}
|
||||
|
||||
#define crc_n4(crc, data, table) crc ^= data; \
|
||||
crc = pgm_read_word(&table[(crc & 0xff) + 0x300]) ^ \
|
||||
pgm_read_word(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
|
||||
pgm_read_word(&table[((data >> 16) & 0xff) + 0x100]) ^ \
|
||||
pgm_read_word(&table[data >> 24]);
|
||||
|
||||
/** CCITT
|
||||
* Alias "false CCITT"
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
crc = REV16(crc);
|
||||
|
||||
return crc;
|
||||
}
|
||||
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
|
||||
seed = 0xffff;
|
||||
return ccitt_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** MCRF4XX
|
||||
* equivalent to _crc_ccitt_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
|
||||
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
|
||||
seed = 0xffff;
|
||||
return mcrf4xx_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** MODBUS
|
||||
* equivalent to _crc_16_update() in crc16.h from avr_libc
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::modbus(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
|
||||
seed = 0xffff;
|
||||
return modbus_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** KERMIT
|
||||
* Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::kermit(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
|
||||
// sometimes byteswapped presentation of result
|
||||
seed = 0x0000;
|
||||
return kermit_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** XMODEM
|
||||
* Alias ZMODEM, CRC-16/ACORN
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
crc = REV16(crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::xmodem(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
//width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
|
||||
seed = 0x0000;
|
||||
return xmodem_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** X25
|
||||
* Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint16_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25);
|
||||
crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25);
|
||||
crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25);
|
||||
crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25);
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
crc = ~crc;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint16_t FastCRC16::x25(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
|
||||
seed = 0xffff;
|
||||
return x25_upd(data, datalen);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ================= 32-BIT CRC ===================
|
||||
/** Constructor
|
||||
*/
|
||||
FastCRC32::FastCRC32(){}
|
||||
|
||||
#define crc_n4d(crc, data, table) crc ^= data; \
|
||||
crc = pgm_read_dword(&table[(crc & 0xff) + 0x300]) ^ \
|
||||
pgm_read_dword(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
|
||||
pgm_read_dword(&table[((crc >> 16) & 0xff) + 0x100]) ^ \
|
||||
pgm_read_dword(&table[(crc >> 24) & 0xff]);
|
||||
|
||||
#define crcsm_n4d(crc, data, table) crc ^= data; \
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]);
|
||||
|
||||
/** CRC32
|
||||
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
#if CRC_BIGTABLES
|
||||
#define CRC_TABLE_CRC32 crc_table_crc32_big
|
||||
#else
|
||||
#define CRC_TABLE_CRC32 crc_table_crc32
|
||||
#endif
|
||||
|
||||
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint32_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
#if CRC_BIGTABLES
|
||||
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
|
||||
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
|
||||
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
|
||||
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
|
||||
#else
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
|
||||
#endif
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
crc = ~crc;
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
|
||||
seed = 0xffffffff;
|
||||
return crc32_upd(data, datalen);
|
||||
}
|
||||
|
||||
/** CKSUM
|
||||
* Alias CRC-32/POSIX
|
||||
* @param data Pointer to Data
|
||||
* @param datalen Length of Data
|
||||
* @return CRC value
|
||||
*/
|
||||
#if CRC_BIGTABLES
|
||||
#define CRC_TABLE_CKSUM crc_table_cksum_big
|
||||
#else
|
||||
#define CRC_TABLE_CKSUM crc_table_cksum
|
||||
#endif
|
||||
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len)
|
||||
{
|
||||
|
||||
uint32_t crc = seed;
|
||||
|
||||
while (((uintptr_t)data & 3) && len) {
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
|
||||
len--;
|
||||
}
|
||||
|
||||
while (len >= 16) {
|
||||
len -= 16;
|
||||
#if CRC_BIGTABLES
|
||||
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
|
||||
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
|
||||
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
|
||||
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
|
||||
#else
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
|
||||
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
|
||||
#endif
|
||||
data += 16;
|
||||
}
|
||||
|
||||
while (len--) {
|
||||
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
|
||||
}
|
||||
|
||||
seed = crc;
|
||||
crc = ~REV32(crc);
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
|
||||
{
|
||||
// width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
|
||||
seed = 0x00;
|
||||
return cksum_upd(data, datalen);
|
||||
}
|
||||
|
||||
#endif // #if !defined(KINETISK)
|
19
lib/lib_div/QuickESPNow/LICENSE.md
Normal file
19
lib/lib_div/QuickESPNow/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright (c) 2022 gmag11@github
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
80
lib/lib_div/QuickESPNow/README.md
Normal file
80
lib/lib_div/QuickESPNow/README.md
Normal file
@ -0,0 +1,80 @@
|
||||
# Quick ESP-NOW
|
||||
|
||||
[](https://registry.platformio.org/libraries/gmag11/QuickEspNow)
|
||||
|
||||
## Introduction
|
||||
|
||||
This fork includes a change to the rx_cb signature for compatibility with the 5.x Espressif IDF.
|
||||
|
||||
This is a library for Arduino framework to be used with Espressif ESP8266 and ESP32 series microcontrollers.
|
||||
|
||||
ESP-NOW is a wireless communication protocol that allows two devices to send data to each other without the need for a wireless network. You can read more about it here [https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html)
|
||||
|
||||
## Benefits
|
||||
|
||||
Usage of ESP-NOW may not be straightforward. There are some restrictions that has to be considered, as limit of number of devices, WiFi channel selection, and other factors.
|
||||
|
||||
This library pretends to hide all that restrictions so that it can be used with just a few lines of code.
|
||||
|
||||
Besides, it removes some limitations:
|
||||
|
||||
- No more 20 devices limit. You can use ESP-NOW with **any number of devices**. Library takes control of peer registration and makes it transparent to you.
|
||||
- Channel selection is not required for WiFi coexistence.
|
||||
- No need to assign a role to each device. Just use it for peer to peer communication.
|
||||
- **RSSI** information of every message, so that receiver can estimate how close the sender is.
|
||||
- Receiver can distiguish between broadcast and unicast messages.
|
||||
- Tested maximum througput, about 600 kbps continuous with default parameters.
|
||||
- Encryption is not supported. Usage of ESP-NOW encryption restrict system to 6 devices. You can implement data encryption in a higher layer.
|
||||
- Asynchronous Sending Mode: The send method now supports a blocking mode, returning a value only after the message send has been confirmed. It returns 0 if the message was sent successfully and a different value if there was an error. This feature ensures reliable message delivery by waiting for confirmation before proceeding withour the user needing to implement a TX callback function.
|
||||
It is importatnt to know that the best performance is achieved when using asynchronous mode, as it allows the library to send messages in the background while the user code continues to run. The synchronous mode is provided for users who require a blocking send method for ease of use.
|
||||
- Default Mode Change: For ease of use, the asynchronous mode is now the default configuration. This mode can be set during the `begin` function call, streamlining the setup process for new projects. This change aims to simplify the initial configuration for developers by automatically opting for the more user-friendly synchronous sending mode. If you require best performance, you can still change the mode to asynchronous by calling `begin` function with the proper parameter.
|
||||
|
||||
## Performance
|
||||
|
||||
I include this table to show the performance of the library. It was tested with ESP32 and ESP8266, sending messages as fastest as possible. The test has been repeated with different message lengths and using synchronous and asynchronous modes.
|
||||
|
||||
| Device | broadcast/unicast | sync/async | 250 bytes | 125 bytes | 75 bytes | 35 bytes | 12 bytes |
|
||||
|--------|-------------------|------------|-----------|-----------|----------|----------|-----------|
|
||||
| ESP32 | broadcast | async | 640 kbps | 450 kbps | 340 kbps | 190 kbps | 75 kbps |
|
||||
| ESP32 | broadcast | sync | 615 kbps | 440 kbps | 320 kbps | 180 kbps | 73 kbps |
|
||||
| ESP8266| broadcast | async | 200 kbps | 100 kbps | 60 kbps | 28 kbps | 9.5 kbps |
|
||||
| ESP8266| broadcast | sync | 200 kbps | 100 kbps | 60 kbps | 28 kbps | 9.5 kbps |
|
||||
| ESP32 | unicast | async | 570 kbps | 400 kbps | 285 kbps | 160 kbps | 60 kbps |
|
||||
| ESP32 | unicast | sync | 550 kbps | 375 kbps | 270 kbps | 150 kbps | 57 kbps |
|
||||
| ESP8266| unicast | async | 200 kbps | 100 kbps | 60 kbps | 28 kbps | 9.5 kbps |
|
||||
| ESP8266| unicast | sync | 200 kbps | 100 kbps | 60 kbps | 28 kbps | 9.5 kbps |
|
||||
|
||||
**Note** : In previous versions of the library, esp8266 was able to send messages at 600 kBps, but it was a mistake. The actual performance is 200 kbps. The table has been updated to reflect the correct values. It was due a to a missing check to avoid sending a message before the previous one was confirmed. This check has been added in version 0.8.1.
|
||||
It seems that this check is not completely mandarory and both ESP8266 and ESP32 are able to send messages correctly even if latest one has not been confirmed. I will investigate what implications this may have and if it is possible to (optionally) remove this check in future versions.
|
||||
|
||||
Please note that these maximum values represent the best-case scenario without any message loss, assuming the microcontroller is not running any other tasks.
|
||||
|
||||
However, it's important to consider that in synchronous mode, where the user code is blocked until the message is sent (which can take from 1 to 20 ms), the actual performance may be significantly lower depending on the rest of the code.
|
||||
|
||||
On the other hand, in asynchronous mode, the `send` function returns in just 22us for both ESP32 and ESP8266, so it is not expected to have a significant impact on the rest of the code.
|
||||
|
||||
Please note that the performance of ESP8266 is lower than ESP32. This may cause problems if an ESP32 is sending messages at a higher rate than the ESP8266 can handle. In such cases, the receiver may lose messages or even crash. If you need to use both devices in the same network, it is recommended to keep the message rate at a safe level for the slowest device.
|
||||
|
||||
## Usage
|
||||
|
||||
To get started with Quick ESP-NOW, simply call the `begin` function and set a receiving callback function if you need to receive data. Then, you can use the `send` function to send data to a specific device or use `ESPNOW_BROADCAST_ADDRESS` to send data to all listening devices on the same channel.
|
||||
|
||||
```C++
|
||||
void dataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
|
||||
Serial.printf("Received message: %.*s\n", len, data);
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin (115200);
|
||||
WiFi.mode (WIFI_MODE_STA);
|
||||
WiFi.disconnect (false);
|
||||
quickEspNow.onDataRcvd (dataReceived);
|
||||
quickEspNow.begin (1); // If you are not connected to WiFi, channel should be specified
|
||||
}
|
||||
|
||||
void loop () {
|
||||
String message = "Hello, world!";
|
||||
quickEspNow.send (DEST_ADDR, (uint8_t*)message.c_str (), message.length ());
|
||||
delay (1000);
|
||||
}
|
||||
```
|
BIN
lib/lib_div/QuickESPNow/Throughput.xlsx
Normal file
BIN
lib/lib_div/QuickESPNow/Throughput.xlsx
Normal file
Binary file not shown.
@ -0,0 +1,78 @@
|
||||
#include <Arduino.h>
|
||||
#if defined ESP32
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#elif defined ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#define WIFI_MODE_STA WIFI_STA
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif //ESP32
|
||||
#include <QuickEspNow.h>
|
||||
|
||||
static const String msg = "Hello ESP-NOW!";
|
||||
|
||||
#define USE_BROADCAST 1 // Set this to 1 to use broadcast communication
|
||||
|
||||
#if USE_BROADCAST != 1
|
||||
// set the MAC address of the receiver for unicast
|
||||
static uint8_t receiver[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 };
|
||||
#define DEST_ADDR receiver
|
||||
#else //USE_BROADCAST != 1
|
||||
#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS
|
||||
#endif //USE_BROADCAST != 1
|
||||
|
||||
bool sent = true;
|
||||
|
||||
const unsigned int SEND_MSG_MSEC = 2000;
|
||||
|
||||
void dataSent (uint8_t* address, uint8_t status) {
|
||||
sent = true;
|
||||
Serial.printf ("Message sent to " MACSTR ", status: %d\n", MAC2STR (address), status);
|
||||
}
|
||||
|
||||
void dataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
|
||||
Serial.print ("Received: ");
|
||||
Serial.printf ("%.*s\n", len, data);
|
||||
Serial.printf ("RSSI: %d dBm\n", rssi);
|
||||
Serial.printf ("From: " MACSTR "\n", MAC2STR (address));
|
||||
Serial.printf ("%s\n", broadcast ? "Broadcast" : "Unicast");
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin (115200);
|
||||
WiFi.mode (WIFI_MODE_STA);
|
||||
#if defined ESP32
|
||||
WiFi.disconnect (false, true);
|
||||
#elif defined ESP8266
|
||||
WiFi.disconnect (false);
|
||||
#endif //ESP32
|
||||
|
||||
Serial.printf ("Connected to %s in channel %d\n", WiFi.SSID ().c_str (), WiFi.channel ());
|
||||
Serial.printf ("IP address: %s\n", WiFi.localIP ().toString ().c_str ());
|
||||
Serial.printf ("MAC address: %s\n", WiFi.macAddress ().c_str ());
|
||||
quickEspNow.begin (1, 0, false);
|
||||
quickEspNow.onDataSent (dataSent);
|
||||
quickEspNow.onDataRcvd (dataReceived);
|
||||
}
|
||||
|
||||
void loop () {
|
||||
static time_t lastSend = 0;
|
||||
static unsigned int counter = 0;
|
||||
|
||||
// Sent flag is needed to wait for the message to be actually sent. Avoids messages dropping, maximizing throughput.
|
||||
// readyToSendData() is used to avoid sending messages too fast, which can lead to messages dropping.
|
||||
if (quickEspNow.readyToSendData() && sent && ((millis () - lastSend) > SEND_MSG_MSEC)) {
|
||||
lastSend = millis ();
|
||||
String message = String (msg) + " " + String (counter++);
|
||||
sent = false;
|
||||
if (!quickEspNow.send (DEST_ADDR, (uint8_t*)message.c_str (), message.length ())) {
|
||||
Serial.printf (">>>>>>>>>> Message sent\n");
|
||||
} else {
|
||||
Serial.printf (">>>>>>>>>> Message not sent\n");
|
||||
sent = true; // In case of error we need to set the flag to true to avoid blocking the loop
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
67
lib/lib_div/QuickESPNow/examples/basicespnow/basicespnow.cpp
Normal file
67
lib/lib_div/QuickESPNow/examples/basicespnow/basicespnow.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <Arduino.h>
|
||||
#if defined ESP32
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#elif defined ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#define WIFI_MODE_STA WIFI_STA
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif //ESP32
|
||||
#include <QuickEspNow.h>
|
||||
|
||||
static const String msg = "Hello ESP-NOW!";
|
||||
|
||||
#define USE_BROADCAST 1 // Set this to 1 to use broadcast communication
|
||||
|
||||
#if USE_BROADCAST != 1
|
||||
// set the MAC address of the receiver for unicast
|
||||
static uint8_t receiver[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 };
|
||||
#define DEST_ADDR receiver
|
||||
#else //USE_BROADCAST != 1
|
||||
#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS
|
||||
#endif //USE_BROADCAST != 1
|
||||
|
||||
// Send message every 2 seconds
|
||||
const unsigned int SEND_MSG_MSEC = 2000;
|
||||
|
||||
void dataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
|
||||
Serial.print ("Received: ");
|
||||
Serial.printf ("%.*s\n", len, data);
|
||||
Serial.printf ("RSSI: %d dBm\n", rssi);
|
||||
Serial.printf ("From: " MACSTR "\n", MAC2STR (address));
|
||||
Serial.printf ("%s\n", broadcast ? "Broadcast" : "Unicast");
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin (115200);
|
||||
WiFi.mode (WIFI_MODE_STA);
|
||||
#if defined ESP32
|
||||
WiFi.disconnect (false, true);
|
||||
#elif defined ESP8266
|
||||
WiFi.disconnect (false);
|
||||
#endif //ESP32
|
||||
Serial.printf ("Connected to %s in channel %d\n", WiFi.SSID ().c_str (), WiFi.channel ());
|
||||
Serial.printf ("IP address: %s\n", WiFi.localIP ().toString ().c_str ());
|
||||
Serial.printf ("MAC address: %s\n", WiFi.macAddress ().c_str ());
|
||||
quickEspNow.onDataRcvd (dataReceived);
|
||||
#ifdef ESP32
|
||||
quickEspNow.setWiFiBandwidth (WIFI_IF_STA, WIFI_BW_HT20); // Only needed for ESP32 in case you need coexistence with ESP8266 in the same network
|
||||
#endif //ESP32
|
||||
quickEspNow.begin (1); // If you use no connected WiFi channel needs to be specified
|
||||
}
|
||||
|
||||
void loop () {
|
||||
static unsigned int counter = 0;
|
||||
|
||||
String message = String (msg) + " " + String (counter++);
|
||||
if (!quickEspNow.send (DEST_ADDR, (uint8_t*)message.c_str (), message.length ())) {
|
||||
Serial.println (">>>>>>>>>> Message sent");
|
||||
} else {
|
||||
Serial.println (">>>>>>>>>> Message not sent");
|
||||
}
|
||||
|
||||
delay (SEND_MSG_MSEC);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,70 @@
|
||||
#include <Arduino.h>
|
||||
#if defined ESP32
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#elif defined ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#define WIFI_MODE_STA WIFI_STA
|
||||
#define WIFI_MODE_AP WIFI_AP
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif //ESP32
|
||||
#include <QuickEspNow.h>
|
||||
|
||||
static const String msg = "Hello esp-now from TTGO";
|
||||
|
||||
#define USE_BROADCAST 1 // Set this to 1 to use broadcast communication
|
||||
|
||||
#if USE_BROADCAST != 1
|
||||
// set the MAC address of the receiver for unicast
|
||||
static uint8_t receiver[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 };
|
||||
#define DEST_ADDR receiver
|
||||
#else //USE_BROADCAST != 1
|
||||
#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS
|
||||
#endif //USE_BROADCAST != 1
|
||||
|
||||
static const uint8_t CHANNEL = 1;
|
||||
|
||||
void dataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
|
||||
Serial.print ("Received: ");
|
||||
Serial.printf ("%.*s\n", len, data);
|
||||
Serial.printf ("RSSI: %d dBm\n", rssi);
|
||||
Serial.printf ("From: " MACSTR "\n", MAC2STR (address));
|
||||
Serial.printf ("%s\n", broadcast ? "Broadcast" : "Unicast");
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin (115200);
|
||||
if (!WiFi.mode (WIFI_MODE_AP)) {
|
||||
Serial.println ("WiFi mode not supported");
|
||||
}
|
||||
if (!WiFi.softAP ("espnowAP", "1234567890", CHANNEL)) {
|
||||
Serial.println ("WiFi access point not started");
|
||||
}
|
||||
|
||||
Serial.printf ("Started AP %s in channel %d\n", WiFi.softAPSSID ().c_str (), WiFi.channel ());
|
||||
Serial.printf ("IP address: %s\n", WiFi.softAPIP ().toString ().c_str ());
|
||||
Serial.printf ("MAC address: %s\n", WiFi.softAPmacAddress ().c_str ());
|
||||
#ifdef ESP32
|
||||
quickEspNow.setWiFiBandwidth (WIFI_IF_AP, WIFI_BW_HT20); // Only needed for ESP32 in case you need coexistence with ESP8266 in the same network
|
||||
#endif //ESP32
|
||||
quickEspNow.onDataRcvd (dataReceived);
|
||||
quickEspNow.begin (CURRENT_WIFI_CHANNEL, WIFI_IF_AP); // Same channel must be used for both AP and ESP-NOW
|
||||
}
|
||||
|
||||
void loop () {
|
||||
static time_t lastSend = 60000;
|
||||
static unsigned int counter = 0;
|
||||
|
||||
if (millis () - lastSend >= 1000) {
|
||||
lastSend = millis ();
|
||||
String message = String (msg) + " " + String (counter++);
|
||||
if (!quickEspNow.send (DEST_ADDR, (uint8_t*)message.c_str (), message.length ())) {
|
||||
Serial.printf (">>>>>>>>>> Message sent\n");
|
||||
} else {
|
||||
Serial.printf (">>>>>>>>>> Message not sent\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
#include <Arduino.h>
|
||||
#if defined ESP32
|
||||
#include <WiFi.h>
|
||||
#include <esp_wifi.h>
|
||||
#elif defined ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#define WIFI_MODE_STA WIFI_STA
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif //ESP32
|
||||
#include <QuickEspNow.h>
|
||||
|
||||
static const String msg = "Hello esp-now!";
|
||||
|
||||
#define USE_BROADCAST 1 // Set this to 1 to use broadcast communication
|
||||
|
||||
#if USE_BROADCAST != 1
|
||||
// set the MAC address of the receiver for unicast
|
||||
static uint8_t receiver[] = { 0x12, 0x34, 0x56, 0x78, 0x90, 0x12 };
|
||||
#define DEST_ADDR receiver
|
||||
#else //USE_BROADCAST != 1
|
||||
#define DEST_ADDR ESPNOW_BROADCAST_ADDRESS
|
||||
#endif //USE_BROADCAST != 1
|
||||
|
||||
void dataReceived (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast) {
|
||||
Serial.print ("Received: ");
|
||||
Serial.printf ("%.*s\n", len, data);
|
||||
Serial.printf ("RSSI: %d dBm\n", rssi);
|
||||
Serial.printf ("From: " MACSTR "\n", MAC2STR(address));
|
||||
Serial.printf ("%s\n", broadcast ? "Broadcast" : "Unicast");
|
||||
}
|
||||
|
||||
void setup () {
|
||||
Serial.begin (115200);
|
||||
WiFi.mode (WIFI_MODE_STA);
|
||||
WiFi.begin ("ssid", "pass");
|
||||
while (WiFi.status () != WL_CONNECTED) {
|
||||
delay (500);
|
||||
Serial.print (".");
|
||||
}
|
||||
Serial.printf ("Connected to %s in channel %d\n", WiFi.SSID ().c_str (), WiFi.channel ());
|
||||
Serial.printf ("IP address: %s\n", WiFi.localIP ().toString ().c_str ());
|
||||
Serial.printf ("MAC address: %s\n", WiFi.macAddress ().c_str ());
|
||||
quickEspNow.onDataRcvd (dataReceived);
|
||||
quickEspNow.begin (); // Use no parameters to start ESP-NOW on same channel as WiFi, in STA mode and synchronous send mode
|
||||
}
|
||||
|
||||
void loop() {
|
||||
static time_t lastSend = 60000;
|
||||
static unsigned int counter = 0;
|
||||
|
||||
if (millis () - lastSend >= 1000) {
|
||||
lastSend = millis ();
|
||||
String message = String (msg) + " " + String (counter++);
|
||||
if (!quickEspNow.send (DEST_ADDR, (uint8_t*)message.c_str (), message.length ())) {
|
||||
Serial.printf (">>>>>>>>>> Message sent\n");
|
||||
} else {
|
||||
Serial.printf (">>>>>>>>>> Message not sent\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
35
lib/lib_div/QuickESPNow/library.json
Normal file
35
lib/lib_div/QuickESPNow/library.json
Normal file
@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "QuickEspNow",
|
||||
"frameworks": "arduino",
|
||||
"version": "0.8.1",
|
||||
"keywords": "esp-now, gateway, node, home",
|
||||
"platforms": ["espressif32", "espressif8266"],
|
||||
"description": "QuickEspNow is a library for ESP8266/ESP32 that allows you to send data over the ESP-NOW protocol.",
|
||||
"url": "https://github.com/gmag11/QuickEspNow.git",
|
||||
"authors":
|
||||
{
|
||||
"name": "Germán Martín",
|
||||
"email": "enigmaiot@gmartin.net"
|
||||
},
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/gmag11/QuickEspNow.git"
|
||||
},
|
||||
"examples": "examples/*/*.ino",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"export":
|
||||
{
|
||||
"exclude":
|
||||
[
|
||||
"docs/*",
|
||||
"include/*",
|
||||
"lib/*"
|
||||
]
|
||||
},
|
||||
"dependencies":
|
||||
{
|
||||
"gmag11/QuickDebug": "0.7.0"
|
||||
}
|
||||
}
|
||||
|
9
lib/lib_div/QuickESPNow/library.properties
Normal file
9
lib/lib_div/QuickESPNow/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=QuickEspNow
|
||||
version=0.8.1
|
||||
author=German Martin
|
||||
maintainer=German Martin
|
||||
sentence=EspNow wrapper for ESP32
|
||||
paragraph=EspNow wrapper for ESP32 which adds simplicity and addtitional features to EspNow
|
||||
category=Communication
|
||||
url=https://github.com/gmag11/QuickEspNow
|
||||
architectures=esp32,esp8266
|
108
lib/lib_div/QuickESPNow/src/Comms_hal.h
Normal file
108
lib/lib_div/QuickESPNow/src/Comms_hal.h
Normal file
@ -0,0 +1,108 @@
|
||||
/**
|
||||
* @file Comms_hal.h
|
||||
* @author German Martin
|
||||
* @brief Generic communication system abstraction layer
|
||||
*
|
||||
* This is the interface that communication definition should implement to be used as layer 1 on EnigmaIoT
|
||||
*/
|
||||
#ifndef _COMMS_HAL_h
|
||||
#define _COMMS_HAL_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
//typedef void (*comms_hal_rcvd_data)(uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast);
|
||||
typedef std::function<void (uint8_t* address, uint8_t* data, uint8_t len, signed int rssi, bool broadcast)> comms_hal_rcvd_data;
|
||||
//typedef void (*comms_hal_sent_data)(uint8_t* address, uint8_t status);
|
||||
typedef std::function<void (uint8_t* address, uint8_t status)> comms_hal_sent_data;
|
||||
|
||||
typedef enum {
|
||||
COMMS_SEND_OK = 0, /**< Data was enqued for sending successfully */
|
||||
COMMS_SEND_PARAM_ERROR = -1, /**< Data was not sent due to parameter call error */
|
||||
COMMS_SEND_PAYLOAD_LENGTH_ERROR = -2, /**< Data was not sent due to payload too long */
|
||||
COMMS_SEND_QUEUE_FULL_ERROR = -3, /**< Data was not sent due to queue full */
|
||||
COMMS_SEND_MSG_ENQUEUE_ERROR = -4, /**< Data was not sent due to message queue push error */
|
||||
COMMS_SEND_CONFIRM_ERROR = -5, /**< Data was not sent due to confirmation error (only for synchronous send) */
|
||||
} comms_send_error_t;
|
||||
|
||||
/**
|
||||
* @brief Interface for communication subsystem abstraction layer definition
|
||||
*/
|
||||
class Comms_halClass {
|
||||
protected:
|
||||
//uint8_t gateway[ESPNOW_ADDR_LEN]; ///< @brief Gateway address
|
||||
uint8_t channel; ///< @brief Comms channel to be used
|
||||
|
||||
comms_hal_rcvd_data dataRcvd = 0; ///< @brief Pointer to a function to be called on every received message
|
||||
comms_hal_sent_data sentResult = 0; ///< @brief Pointer to a function to be called to notify last sending status
|
||||
//peerType_t _ownPeerType; ///< @brief Stores peer type, node or gateway
|
||||
|
||||
/**
|
||||
* @brief Communication subsistem initialization
|
||||
* @param peerType Role that peer plays into the system, node or gateway.
|
||||
*/
|
||||
virtual bool initComms () = 0;
|
||||
|
||||
|
||||
public:
|
||||
Comms_halClass () {}
|
||||
|
||||
/**
|
||||
* @brief Setup communication environment and establish the connection from node to gateway
|
||||
* @param gateway Address of gateway. It may be `NULL` in case this is used in the own gateway
|
||||
* @param channel Establishes a channel for the communication. Its use depends on actual communications subsystem
|
||||
* @param peerType Role that peer plays into the system, node or gateway.
|
||||
* @return Returns `true` if the communication subsystem was successfully initialized, `false` otherwise
|
||||
*/
|
||||
virtual bool begin (uint8_t channel, uint32_t interface = 0, bool synchronousSend = true) = 0;
|
||||
|
||||
/**
|
||||
* @brief Terminates communication and closes all connectrions
|
||||
*/
|
||||
virtual void stop () = 0;
|
||||
|
||||
/**
|
||||
* @brief Sends data to the other peer
|
||||
* @param da Destination address to send the message to
|
||||
* @param data Data buffer that contain the message to be sent
|
||||
* @param len Data length in number of bytes
|
||||
* @return Returns sending status. 0 for success, any other value to indicate an error.
|
||||
*/
|
||||
virtual comms_send_error_t send (const uint8_t* da, const uint8_t* data, size_t len) = 0;
|
||||
|
||||
/**
|
||||
* @brief Attach a callback function to be run on every received message
|
||||
* @param dataRcvd Pointer to the callback function
|
||||
*/
|
||||
virtual void onDataRcvd (comms_hal_rcvd_data dataRcvd) = 0;
|
||||
|
||||
/**
|
||||
* @brief Attach a callback function to be run after sending a message to receive its status
|
||||
* @param dataRcvd Pointer to the callback function
|
||||
*/
|
||||
virtual void onDataSent (comms_hal_sent_data dataRcvd) = 0;
|
||||
|
||||
/**
|
||||
* @brief Get address length that a specific communication subsystem uses
|
||||
* @return Returns number of bytes that is used to represent an address
|
||||
*/
|
||||
virtual uint8_t getAddressLength () = 0;
|
||||
|
||||
/**
|
||||
* @brief Get max message length for a specific communication subsystems
|
||||
* @return Returns number of bytes of longer supported message
|
||||
*/
|
||||
virtual uint8_t getMaxMessageLength () = 0;
|
||||
|
||||
/**
|
||||
* @brief Enables or disables transmission of queued messages. Used to disable communication during wifi scan
|
||||
* @param enable `true` to enable transmission, `false` to disable it
|
||||
*/
|
||||
virtual void enableTransmit (bool enable) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
12
lib/lib_div/QuickESPNow/src/QuickEspNow.h
Normal file
12
lib/lib_div/QuickESPNow/src/QuickEspNow.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _QUICK_ESPNOW_h
|
||||
#define _QUICK_ESPNOW_h
|
||||
|
||||
#if defined ESP32
|
||||
#include "QuickEspNow_esp32.h"
|
||||
#elif defined ESP8266
|
||||
#include "QuickEspNow_esp8266.h"
|
||||
#else
|
||||
#error "Unsupported platform"
|
||||
#endif //ESP32
|
||||
|
||||
#endif //_QUICK_ESPNOW_h
|
531
lib/lib_div/QuickESPNow/src/QuickEspNow_esp32.cpp
Normal file
531
lib/lib_div/QuickESPNow/src/QuickEspNow_esp32.cpp
Normal file
@ -0,0 +1,531 @@
|
||||
#include "QuickEspNow.h"
|
||||
|
||||
#ifdef ESP32
|
||||
|
||||
QuickEspNow quickEspNow;
|
||||
|
||||
constexpr auto PEERLIST_TAG = "PEERLIST";
|
||||
|
||||
|
||||
bool QuickEspNow::begin (uint8_t channel, uint32_t wifi_interface, bool synchronousSend) {
|
||||
|
||||
wifi_second_chan_t ch2 = WIFI_SECOND_CHAN_NONE;
|
||||
this->synchronousSend = synchronousSend;
|
||||
|
||||
DEBUG_DBG (QESPNOW_TAG, "Channel: %d, Interface: %d", channel, wifi_interface);
|
||||
// Set the wifi interface
|
||||
switch (wifi_interface) {
|
||||
case WIFI_IF_STA:
|
||||
wifi_if = WIFI_IF_STA;
|
||||
break;
|
||||
case WIFI_IF_AP:
|
||||
wifi_if = WIFI_IF_AP;
|
||||
break;
|
||||
default:
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Unknown wifi interface");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// check channel
|
||||
if (channel != CURRENT_WIFI_CHANNEL && (channel < MIN_WIFI_CHANNEL || channel > MAX_WIFI_CHANNEL)) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Invalid wifi channel %d", channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
// use current channel
|
||||
if (channel == CURRENT_WIFI_CHANNEL) {
|
||||
uint8_t ch;
|
||||
esp_wifi_get_channel (&ch, &ch2);
|
||||
channel = ch;
|
||||
DEBUG_DBG (QESPNOW_TAG, "Current channel: %d : %d", channel, ch2);
|
||||
followWiFiChannel = true;
|
||||
}
|
||||
setChannel (channel, ch2);
|
||||
|
||||
DEBUG_INFO (QESPNOW_TAG, ARDUHAL_LOG_COLOR (ARDUHAL_LOG_COLOR_RED) "Starting ESP-NOW in in channel %u interface %s", channel, wifi_if == WIFI_IF_STA ? "STA" : "AP");
|
||||
|
||||
this->channel = channel;
|
||||
|
||||
return initComms ();
|
||||
}
|
||||
|
||||
void QuickEspNow::stop () {
|
||||
DEBUG_INFO (QESPNOW_TAG, "-------------> ESP-NOW STOP");
|
||||
if (espnowTxTask) {
|
||||
vTaskDelete (espnowTxTask);
|
||||
espnowTxTask = nullptr;
|
||||
}
|
||||
if (espnowRxTask) {
|
||||
vTaskDelete (espnowRxTask);
|
||||
espnowRxTask = nullptr;
|
||||
}
|
||||
esp_now_unregister_recv_cb ();
|
||||
esp_now_unregister_send_cb ();
|
||||
esp_now_deinit ();
|
||||
followWiFiChannel = false;
|
||||
}
|
||||
|
||||
bool QuickEspNow::readyToSendData () {
|
||||
return uxQueueMessagesWaiting (tx_queue) < queueSize;
|
||||
}
|
||||
|
||||
bool QuickEspNow::setChannel (uint8_t channel, wifi_second_chan_t ch2) {
|
||||
|
||||
if (followWiFiChannel) {
|
||||
DEBUG_WARN(QESPNOW_TAG, "Cannot set channel while following WiFi channel");
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t err_ok;
|
||||
if ((err_ok = esp_wifi_set_promiscuous (true))) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error setting promiscuous mode: %s", esp_err_to_name (err_ok));
|
||||
return false;
|
||||
}
|
||||
if ((err_ok = esp_wifi_set_channel (channel, ch2))) { // This is needed even in STA mode. If not done and using IDF > 4.0, the ESP-NOW will not work.
|
||||
DEBUG_DBG (QESPNOW_TAG, "Error setting wifi channel: %d - %s", err_ok, esp_err_to_name (err_ok));
|
||||
return false;
|
||||
}
|
||||
if ((err_ok = esp_wifi_set_promiscuous (false))) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error setting promiscuous mode off: %s", esp_err_to_name (err_ok));
|
||||
return false;
|
||||
}
|
||||
|
||||
this->channel = channel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
comms_send_error_t QuickEspNow::send (const uint8_t* dstAddress, const uint8_t* payload, size_t payload_len) {
|
||||
comms_tx_queue_item_t message;
|
||||
|
||||
if (!dstAddress || !payload || !payload_len) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Parameters error");
|
||||
return COMMS_SEND_PAYLOAD_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
if (payload_len > ESP_NOW_MAX_DATA_LEN) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Length error. %d", payload_len);
|
||||
return COMMS_SEND_PAYLOAD_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
if (uxQueueMessagesWaiting (tx_queue) >= queueSize) {
|
||||
// comms_tx_queue_item_t tempBuffer;
|
||||
// xQueueReceive (tx_queue, &tempBuffer, 0);
|
||||
#ifdef MEAS_TPUT
|
||||
//txDataDropped += tempBuffer.payload_len;
|
||||
#endif // MEAS_TPUT
|
||||
//DEBUG_DBG (QESPNOW_TAG, "Message dropped");
|
||||
return COMMS_SEND_QUEUE_FULL_ERROR;
|
||||
}
|
||||
memcpy (message.dstAddress, dstAddress, ESP_NOW_ETH_ALEN);
|
||||
message.payload_len = payload_len;
|
||||
memcpy (message.payload, payload, payload_len);
|
||||
|
||||
if (xQueueSend (tx_queue, &message, pdMS_TO_TICKS (10))) {
|
||||
#ifdef MEAS_TPUT
|
||||
txDataSent += message.payload_len;
|
||||
#endif // MEAS_TPUT
|
||||
DEBUG_DBG (QESPNOW_TAG, "--------- %d Comms messages queued. Len: %d", uxQueueMessagesWaiting (tx_queue), payload_len);
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "--------- Ready to send is %s", readyToSend ? "true" : "false");
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "--------- SyncronousSend is %s", synchronousSend ? "true" : "false");
|
||||
if (synchronousSend) {
|
||||
waitingForConfirmation = true;
|
||||
DEBUG_INFO (QESPNOW_TAG, "--------- Waiting for send confirmation");
|
||||
while (waitingForConfirmation) {
|
||||
taskYIELD ();
|
||||
}
|
||||
DEBUG_INFO (QESPNOW_TAG, "--------- Confirmation is %s", sentStatus == ESP_NOW_SEND_SUCCESS ? "true" : "false");
|
||||
return (sentStatus == ESP_NOW_SEND_SUCCESS) ? COMMS_SEND_OK : COMMS_SEND_CONFIRM_ERROR;
|
||||
}
|
||||
return COMMS_SEND_OK;
|
||||
} else {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error queuing Comms message to " MACSTR, MAC2STR (dstAddress));
|
||||
return COMMS_SEND_MSG_ENQUEUE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::onDataRcvd (comms_hal_rcvd_data dataRcvd) {
|
||||
this->dataRcvd = dataRcvd;
|
||||
}
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
void QuickEspNow::calculateDataTP () {
|
||||
time_t measTime = (millis () - lastDataTPMeas);
|
||||
lastDataTPMeas = millis ();
|
||||
|
||||
if (txDataSent > 0) {
|
||||
txDataTP = txDataSent * 1000 / measTime;
|
||||
//DEBUG_WARN("Meas time: %d, Data sent: %d, Data TP: %f", measTime, txDataSent, txDataTP);
|
||||
txDroppedDataRatio = (float)txDataDropped / (float)txDataSent;
|
||||
//DEBUG_WARN("Data dropped: %d, Drop ratio: %f", txDataDropped, txDroppedDataRatio);
|
||||
txDataSent = 0;
|
||||
} else {
|
||||
txDataTP = 0;
|
||||
txDroppedDataRatio = 0;
|
||||
}
|
||||
if (rxDataReceived > 0) {
|
||||
rxDataTP = rxDataReceived * 1000 / measTime;
|
||||
//DEBUG_WARN("Meas time: %d, Data received: %d, Data TP: %f", measTime, rxDataReceived, rxDataTP);
|
||||
rxDataReceived = 0;
|
||||
} else {
|
||||
rxDataTP = 0;
|
||||
}
|
||||
txDataDropped = 0;
|
||||
}
|
||||
|
||||
void QuickEspNow::tp_timer_cb (void* param) {
|
||||
quickEspNow.calculateDataTP ();
|
||||
DEBUG_WARN (QESPNOW_TAG, "TxData TP: %.3f kbps, Drop Ratio: %.2f %%, RxDataTP: %.3f kbps",
|
||||
quickEspNow.txDataTP * 8 / 1000,
|
||||
quickEspNow.txDroppedDataRatio * 100,
|
||||
quickEspNow.rxDataTP * 8 / 1000);
|
||||
}
|
||||
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
void QuickEspNow::onDataSent (comms_hal_sent_data sentResult) {
|
||||
this->sentResult = sentResult;
|
||||
}
|
||||
|
||||
int32_t QuickEspNow::sendEspNowMessage (comms_tx_queue_item_t* message) {
|
||||
int32_t error;
|
||||
|
||||
if (!message) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Message is null");
|
||||
return -1;
|
||||
}
|
||||
if (!(message->payload_len) || (message->payload_len > ESP_NOW_MAX_DATA_LEN)) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Message length error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "ESP-NOW message to " MACSTR, MAC2STR (message->dstAddress));
|
||||
|
||||
|
||||
addPeer (message->dstAddress);
|
||||
DEBUG_DBG (QESPNOW_TAG, "Peer added " MACSTR, MAC2STR (message->dstAddress));
|
||||
readyToSend = false;
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "-------------- Ready to send: false");
|
||||
|
||||
error = esp_now_send (message->dstAddress, message->payload, message->payload_len);
|
||||
DEBUG_DBG (QESPNOW_TAG, "esp now send result = %s", esp_err_to_name (error));
|
||||
if (error != ESP_OK) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error sending message: %s", esp_err_to_name (error));
|
||||
}
|
||||
// if (error == ESP_OK) {
|
||||
// txDataSent += message->payload_len;
|
||||
// }
|
||||
if (error == ESP_ERR_ESPNOW_NO_MEM) {
|
||||
delay (2);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowTxHandle () {
|
||||
if (readyToSend) {
|
||||
//DEBUG_WARN ("Process queue: Elements: %d", tx_queue.size ());
|
||||
comms_tx_queue_item_t message;
|
||||
while (xQueueReceive (tx_queue, &message, pdMS_TO_TICKS (1000))) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message got from queue. %d left", uxQueueMessagesWaiting (tx_queue));
|
||||
while (!readyToSend && !synchronousSend) {
|
||||
delay (0);
|
||||
}
|
||||
if (!sendEspNowMessage (&message)) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Message to " MACSTR " sent. Len: %u", MAC2STR (message.dstAddress), message.payload_len);
|
||||
} else {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error sending message to " MACSTR ". Len: %u", MAC2STR (message.dstAddress), message.payload_len);
|
||||
}
|
||||
//message.payload_len = 0;
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message pop. Queue size %d", uxQueueMessagesWaiting (tx_queue));
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Not ready to send");
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::enableTransmit (bool enable) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Send esp-now task %s", enable ? "enabled" : "disabled");
|
||||
if (enable) {
|
||||
if (espnowTxTask_cb) {
|
||||
vTaskResume (espnowTxTask);
|
||||
vTaskResume (espnowRxTask);
|
||||
}
|
||||
} else {
|
||||
if (espnowTxTask_cb) {
|
||||
vTaskSuspend (espnowTxTask);
|
||||
vTaskSuspend (espnowRxTask);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QuickEspNow::addPeer (const uint8_t* peer_addr) {
|
||||
esp_now_peer_info_t peer;
|
||||
esp_err_t error = ESP_OK;
|
||||
|
||||
if (peer_list.get_peer_number () >= ESP_NOW_MAX_TOTAL_PEER_NUM) {
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Peer list full. Deleting older");
|
||||
if (uint8_t* deleted_mac = peer_list.delete_peer ()) {
|
||||
esp_now_del_peer (deleted_mac);
|
||||
} else {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error deleting peer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (peer_list.peer_exists (peer_addr)) {
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Peer already exists");
|
||||
ESP_ERROR_CHECK (esp_now_get_peer (peer_addr, &peer));
|
||||
|
||||
uint8_t currentChannel = peer.channel;
|
||||
DEBUG_DBG (QESPNOW_TAG, "Peer " MACSTR " is using channel %d", MAC2STR (peer_addr), currentChannel);
|
||||
if (currentChannel != this->channel) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Peer channel has to change from %d to %d", currentChannel, this->channel);
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT (esp_now_get_peer (peer_addr, &peer));
|
||||
peer.channel = this->channel;
|
||||
ESP_ERROR_CHECK_WITHOUT_ABORT (esp_now_mod_peer (&peer));
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Peer channel changed to %d", this->channel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
memcpy (peer.peer_addr, peer_addr, ESP_NOW_ETH_ALEN);
|
||||
uint8_t ch;
|
||||
wifi_second_chan_t secondCh;
|
||||
esp_wifi_get_channel (&ch, &secondCh);
|
||||
peer.channel = ch;
|
||||
peer.ifidx = wifi_if;
|
||||
peer.encrypt = false;
|
||||
error = esp_now_add_peer (&peer);
|
||||
if (!error) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Peer added");
|
||||
peer_list.add_peer (peer_addr);
|
||||
} else {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error adding peer: %s", esp_err_to_name (error));
|
||||
return false;
|
||||
}
|
||||
DEBUG_DBG (QESPNOW_TAG, "Peer " MACSTR " added on channel %u. Result 0x%X %s", MAC2STR (peer_addr), ch, error, esp_err_to_name (error));
|
||||
return error == ESP_OK;
|
||||
}
|
||||
|
||||
bool QuickEspNow::initComms () {
|
||||
if (esp_now_init ()) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Failed to init ESP-NOW");
|
||||
// ESP.restart ();
|
||||
// delay (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_now_register_recv_cb (rx_cb);
|
||||
esp_now_register_send_cb (reinterpret_cast<esp_now_send_cb_t>(tx_cb));
|
||||
|
||||
int txQueueSize = queueSize;
|
||||
if (synchronousSend) {
|
||||
txQueueSize = 1;
|
||||
}
|
||||
|
||||
tx_queue = xQueueCreate (txQueueSize, sizeof (comms_tx_queue_item_t));
|
||||
xTaskCreateUniversal (espnowTxTask_cb, "espnow_loop", 8 * 1024, NULL, 1, &espnowTxTask, CONFIG_ARDUINO_RUNNING_CORE);
|
||||
|
||||
rx_queue = xQueueCreate (queueSize, sizeof (comms_rx_queue_item_t));
|
||||
xTaskCreateUniversal (espnowRxTask_cb, "receive_handle", 4 * 1024, NULL, 1, &espnowRxTask, CONFIG_ARDUINO_RUNNING_CORE);
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
dataTPTimer = xTimerCreate ("espnow_tp_timer", pdMS_TO_TICKS (MEAS_TP_EVERY_MS), pdTRUE, NULL, tp_timer_cb);
|
||||
xTimerStart (dataTPTimer, 0);
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowTxTask_cb (void* param) {
|
||||
for (;;) {
|
||||
quickEspNow.espnowTxHandle ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowRxHandle () {
|
||||
comms_rx_queue_item_t rxMessage;
|
||||
|
||||
if (xQueueReceive (rx_queue, &rxMessage, portMAX_DELAY)) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message got from queue. %d left", uxQueueMessagesWaiting (rx_queue));
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Received message from " MACSTR " Len: %u", MAC2STR (rxMessage.srcAddress), rxMessage.payload_len);
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Message: %.*s", rxMessage.payload_len, rxMessage.payload);
|
||||
|
||||
if (quickEspNow.dataRcvd) {
|
||||
bool broadcast = !memcmp (rxMessage.dstAddress, ESPNOW_BROADCAST_ADDRESS, ESP_NOW_ETH_ALEN);
|
||||
quickEspNow.dataRcvd (rxMessage.srcAddress, rxMessage.payload, rxMessage.payload_len, rxMessage.rssi, broadcast); // rssi should be in dBm but it has added almost 100 dB. Do not know why
|
||||
}
|
||||
} else {
|
||||
DEBUG_DBG (QESPNOW_TAG, "No message in queue");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowRxTask_cb (void* param) {
|
||||
for (;;) {
|
||||
quickEspNow.espnowRxHandle ();
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::rx_cb(const esp_now_recv_info_t* esp_now_info, const uint8_t* data, int len) {
|
||||
espnow_frame_format_t* espnow_data = (espnow_frame_format_t*)(data - sizeof(espnow_frame_format_t));
|
||||
wifi_promiscuous_pkt_t* promiscuous_pkt = (wifi_promiscuous_pkt_t*)(data - sizeof(wifi_pkt_rx_ctrl_t) - sizeof(espnow_frame_format_t));
|
||||
wifi_pkt_rx_ctrl_t* rx_ctrl = &promiscuous_pkt->rx_ctrl;
|
||||
const uint8_t* mac_addr = esp_now_info->src_addr;
|
||||
comms_rx_queue_item_t message;
|
||||
|
||||
DEBUG_DBG(QESPNOW_TAG, "Received message with RSSI %d from " MACSTR " Len: %u", rx_ctrl->rssi, MAC2STR(esp_now_info->src_addr), len);
|
||||
|
||||
memcpy(message.srcAddress, mac_addr, ESP_NOW_ETH_ALEN);
|
||||
memcpy(message.payload, data, len);
|
||||
message.payload_len = len;
|
||||
message.rssi = rx_ctrl->rssi;
|
||||
memcpy(message.dstAddress, espnow_data->destination_address, ESP_NOW_ETH_ALEN);
|
||||
|
||||
if (uxQueueMessagesWaiting(quickEspNow.rx_queue) >= quickEspNow.queueSize) {
|
||||
comms_rx_queue_item_t tempBuffer;
|
||||
xQueueReceive(quickEspNow.rx_queue, &tempBuffer, 0);
|
||||
DEBUG_DBG(QESPNOW_TAG, "Rx Message dropped");
|
||||
}
|
||||
#ifdef MEAS_TPUT
|
||||
quickEspNow.rxDataReceived += len;
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
if (!xQueueSend(quickEspNow.rx_queue, &message, pdMS_TO_TICKS(100))) {
|
||||
DEBUG_WARN(QESPNOW_TAG, "Error sending message to queue");
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::tx_cb (uint8_t* mac_addr, uint8_t status) {
|
||||
quickEspNow.readyToSend = true;
|
||||
quickEspNow.sentStatus = status;
|
||||
quickEspNow.waitingForConfirmation = false;
|
||||
DEBUG_DBG (QESPNOW_TAG, "-------------- Ready to send: true. Status: %d", status);
|
||||
if (quickEspNow.sentResult) {
|
||||
quickEspNow.sentResult (mac_addr, status);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t PeerListClass::get_peer_number () {
|
||||
return peer_list.peer_number;
|
||||
}
|
||||
|
||||
bool PeerListClass::peer_exists (const uint8_t* mac) {
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
if (memcmp (peer_list.peer[i].mac, mac, ESP_NOW_ETH_ALEN) == 0) {
|
||||
if (peer_list.peer[i].active) {
|
||||
peer_list.peer[i].last_msg = millis ();
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " found. Updated last_msg", MAC2STR (mac));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
peer_t* PeerListClass::get_peer (const uint8_t* mac) {
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
if (memcmp (peer_list.peer[i].mac, mac, ESP_NOW_ETH_ALEN) == 0) {
|
||||
if (peer_list.peer[i].active) {
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " found", MAC2STR (mac));
|
||||
return &(peer_list.peer[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool PeerListClass::update_peer_use (const uint8_t* mac) {
|
||||
peer_t* peer = get_peer (mac);
|
||||
if (peer) {
|
||||
peer->last_msg = millis ();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PeerListClass::add_peer (const uint8_t* mac) {
|
||||
if (int i = peer_exists (mac)) {
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " already exists", MAC2STR (mac));
|
||||
return false;
|
||||
}
|
||||
if (peer_list.peer_number >= ESP_NOW_MAX_TOTAL_PEER_NUM) {
|
||||
//DEBUG_VERBOSE (PEERLIST_TAG, "Peer list full. Deleting older");
|
||||
#ifndef UNIT_TEST
|
||||
DEBUG_ERROR (PEERLIST_TAG, "Should never happen");
|
||||
#endif
|
||||
return false;
|
||||
// delete_peer (); // Delete should happen in higher level
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
if (!peer_list.peer[i].active) {
|
||||
memcpy (peer_list.peer[i].mac, mac, ESP_NOW_ETH_ALEN);
|
||||
peer_list.peer[i].active = true;
|
||||
peer_list.peer[i].last_msg = millis ();
|
||||
peer_list.peer_number++;
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " added. Total peers = %d", MAC2STR (mac), peer_list.peer_number);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PeerListClass::delete_peer (const uint8_t* mac) {
|
||||
peer_t* peer = get_peer (mac);
|
||||
if (peer) {
|
||||
peer->active = false;
|
||||
peer_list.peer_number--;
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " deleted. Total peers = %d", MAC2STR (mac), peer_list.peer_number);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete peer with older message
|
||||
uint8_t* PeerListClass::delete_peer () {
|
||||
uint32_t oldest_msg = 0;
|
||||
int oldest_index = -1;
|
||||
uint8_t* mac = NULL;
|
||||
for (int i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
if (peer_list.peer[i].active) {
|
||||
if (peer_list.peer[i].last_msg < oldest_msg || oldest_msg == 0) {
|
||||
oldest_msg = peer_list.peer[i].last_msg;
|
||||
oldest_index = i;
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " is %d ms old. Deleting", MAC2STR (peer_list.peer[i].mac), oldest_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (oldest_index != -1) {
|
||||
peer_list.peer[oldest_index].active = false;
|
||||
peer_list.peer_number--;
|
||||
mac = peer_list.peer[oldest_index].mac;
|
||||
DEBUG_VERBOSE (PEERLIST_TAG, "Peer " MACSTR " deleted. Last message %d ms ago. Total peers = %d", MAC2STR (mac), millis () - peer_list.peer[oldest_index].last_msg, peer_list.peer_number);
|
||||
}
|
||||
return mac;
|
||||
}
|
||||
|
||||
bool QuickEspNow::setWiFiBandwidth (wifi_interface_t iface, wifi_bandwidth_t bw) {
|
||||
esp_err_t err_ok;
|
||||
if ((err_ok = esp_wifi_set_bandwidth (iface, bw))) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error setting wifi bandwidth: %s", esp_err_to_name (err_ok));
|
||||
}
|
||||
return !err_ok;
|
||||
}
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
void PeerListClass::dump_peer_list () {
|
||||
Serial.printf ("Number of peers %d\n", peer_list.peer_number);
|
||||
for (int i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
if (peer_list.peer[i].active) {
|
||||
Serial.printf ("Peer " MACSTR " is %d ms old\n", MAC2STR (peer_list.peer[i].mac), millis () - peer_list.peer[i].last_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // UNIT_TEST
|
||||
#endif // ESP32
|
169
lib/lib_div/QuickESPNow/src/QuickEspNow_esp32.h
Normal file
169
lib/lib_div/QuickESPNow/src/QuickEspNow_esp32.h
Normal file
@ -0,0 +1,169 @@
|
||||
#ifndef _QUICK_ESPNOW_ESP32_h
|
||||
#define _QUICK_ESPNOW_ESP32_h
|
||||
#ifdef ESP32
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Comms_hal.h"
|
||||
|
||||
#include <esp_now.h>
|
||||
#include <esp_wifi.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
// Disable debug dependency if debug level is 0
|
||||
#if CORE_DEBUG_LEVEL > 0
|
||||
#include <QuickDebug.h>
|
||||
constexpr auto QESPNOW_TAG = "QESPNOW";
|
||||
#else // CORE_DEBUG_LEVEL
|
||||
#define DEBUG_ERROR(...)
|
||||
#define DEBUG_INFO(...)
|
||||
#define DEBUG_VERBOSE(...)
|
||||
#define DEBUG_WARN(...)
|
||||
#define DEBUG_DBG(...)
|
||||
#endif
|
||||
|
||||
//#define MEAS_TPUT
|
||||
|
||||
static uint8_t ESPNOW_BROADCAST_ADDRESS[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const uint8_t MIN_WIFI_CHANNEL = 0;
|
||||
static const uint8_t MAX_WIFI_CHANNEL = 14;
|
||||
static const uint8_t CURRENT_WIFI_CHANNEL = 255;
|
||||
static const size_t ESPNOW_MAX_MESSAGE_LENGTH = 250; ///< @brief Maximum message length
|
||||
static const uint8_t ESPNOW_ADDR_LEN = 6; ///< @brief Address length
|
||||
static const uint8_t ESPNOW_QUEUE_SIZE = 3; ///< @brief Queue size
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
static const time_t MEAS_TP_EVERY_MS = 10000; ///< @brief Measurement time period
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
typedef struct {
|
||||
uint16_t frame_head;
|
||||
uint16_t duration;
|
||||
uint8_t destination_address[6];
|
||||
uint8_t source_address[6];
|
||||
uint8_t broadcast_address[6];
|
||||
uint16_t sequence_control;
|
||||
|
||||
uint8_t category_code;
|
||||
uint8_t organization_identifier[3]; // 0x18fe34
|
||||
uint8_t random_values[4];
|
||||
struct {
|
||||
uint8_t element_id; // 0xdd
|
||||
uint8_t lenght; //
|
||||
uint8_t organization_identifier[3]; // 0x18fe34
|
||||
uint8_t type; // 4
|
||||
uint8_t version;
|
||||
uint8_t body[0];
|
||||
} vendor_specific_content;
|
||||
} __attribute__ ((packed)) espnow_frame_format_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t dstAddress[ESPNOW_ADDR_LEN]; /**< Message topic*/
|
||||
uint8_t payload[ESPNOW_MAX_MESSAGE_LENGTH]; /**< Message payload*/
|
||||
size_t payload_len; /**< Payload length*/
|
||||
} comms_tx_queue_item_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t srcAddress[ESPNOW_ADDR_LEN]; /**< Source Address */
|
||||
uint8_t dstAddress[ESPNOW_ADDR_LEN]; /**< Destination Address */
|
||||
uint8_t payload[ESPNOW_MAX_MESSAGE_LENGTH]; /**< Message payload */
|
||||
size_t payload_len; /**< Payload length */
|
||||
int8_t rssi; /**< RSSI */
|
||||
} comms_rx_queue_item_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t mac[ESP_NOW_ETH_ALEN];
|
||||
time_t last_msg;
|
||||
bool active;
|
||||
} peer_t;
|
||||
typedef struct {
|
||||
uint8_t peer_number;
|
||||
peer_t peer[ESP_NOW_MAX_TOTAL_PEER_NUM];
|
||||
} peer_list_t;
|
||||
|
||||
class PeerListClass {
|
||||
protected:
|
||||
peer_list_t peer_list;
|
||||
|
||||
public:
|
||||
bool peer_exists (const uint8_t* mac);
|
||||
peer_t* get_peer (const uint8_t* mac);
|
||||
bool update_peer_use (const uint8_t* mac);
|
||||
bool delete_peer (const uint8_t* mac);
|
||||
uint8_t* delete_peer ();
|
||||
bool add_peer (const uint8_t* mac);
|
||||
uint8_t get_peer_number ();
|
||||
#ifdef UNIT_TEST
|
||||
void dump_peer_list ();
|
||||
#endif
|
||||
};
|
||||
|
||||
class QuickEspNow : public Comms_halClass {
|
||||
public:
|
||||
bool begin (uint8_t channel = CURRENT_WIFI_CHANNEL, uint32_t interface = 0, bool synchronousSend = true) override;
|
||||
void stop () override;
|
||||
comms_send_error_t send (const uint8_t* dstAddress, const uint8_t* payload, size_t payload_len) override;
|
||||
comms_send_error_t sendBcast (const uint8_t* payload, size_t payload_len) {
|
||||
return send (ESPNOW_BROADCAST_ADDRESS, payload, payload_len);
|
||||
}
|
||||
void onDataRcvd (comms_hal_rcvd_data dataRcvd) override;
|
||||
void onDataSent (comms_hal_sent_data sentResult) override;
|
||||
uint8_t getAddressLength () override { return ESPNOW_ADDR_LEN; }
|
||||
uint8_t getMaxMessageLength () override { return ESPNOW_MAX_MESSAGE_LENGTH; }
|
||||
void enableTransmit (bool enable) override;
|
||||
bool setChannel (uint8_t channel, wifi_second_chan_t ch2 = WIFI_SECOND_CHAN_NONE);
|
||||
bool setWiFiBandwidth (wifi_interface_t iface = WIFI_IF_AP, wifi_bandwidth_t bw = WIFI_BW_HT20);
|
||||
bool readyToSendData ();
|
||||
|
||||
protected:
|
||||
wifi_interface_t wifi_if;
|
||||
PeerListClass peer_list;
|
||||
TaskHandle_t espnowTxTask;
|
||||
TaskHandle_t espnowRxTask;
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
unsigned long txDataSent = 0;
|
||||
unsigned long rxDataReceived = 0;
|
||||
unsigned long txDataDropped = 0;
|
||||
time_t lastDataTPMeas = 0;
|
||||
TimerHandle_t dataTPTimer;
|
||||
float txDataTP = 0;
|
||||
float rxDataTP = 0;
|
||||
float txDroppedDataRatio = 0;
|
||||
|
||||
static void tp_timer_cb (void* param);
|
||||
void calculateDataTP ();
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
bool readyToSend = true;
|
||||
bool waitingForConfirmation = false;
|
||||
bool synchronousSend = false;
|
||||
uint8_t sentStatus;
|
||||
int queueSize = ESPNOW_QUEUE_SIZE;
|
||||
|
||||
QueueHandle_t tx_queue;
|
||||
QueueHandle_t rx_queue;
|
||||
//SemaphoreHandle_t espnow_send_mutex;
|
||||
//uint8_t channel;
|
||||
bool followWiFiChannel = false;
|
||||
|
||||
bool initComms ();
|
||||
bool addPeer (const uint8_t* peer_addr);
|
||||
static void espnowTxTask_cb (void* param);
|
||||
int32_t sendEspNowMessage (comms_tx_queue_item_t* message);
|
||||
void espnowTxHandle ();
|
||||
|
||||
static void espnowRxTask_cb (void* param);
|
||||
void espnowRxHandle ();
|
||||
|
||||
static void ICACHE_FLASH_ATTR rx_cb(const esp_now_recv_info_t* esp_now_info, const uint8_t* data, int len);
|
||||
static void ICACHE_FLASH_ATTR tx_cb (uint8_t* mac_addr, uint8_t status);
|
||||
};
|
||||
|
||||
extern QuickEspNow quickEspNow;
|
||||
|
||||
#endif // ESP32
|
||||
#endif // _QUICK_ESPNOW_ESP32_h
|
368
lib/lib_div/QuickESPNow/src/QuickEspNow_esp8266.cpp
Normal file
368
lib/lib_div/QuickESPNow/src/QuickEspNow_esp8266.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
#include "QuickEspNow.h"
|
||||
|
||||
#ifdef ESP8266
|
||||
|
||||
typedef struct {
|
||||
signed rssi : 8;
|
||||
unsigned rate : 4;
|
||||
unsigned is_group : 1;
|
||||
unsigned : 1;
|
||||
unsigned sig_mode : 2;
|
||||
unsigned legacy_length : 12;
|
||||
unsigned damatch0 : 1;
|
||||
unsigned damatch1 : 1;
|
||||
unsigned bssidmatch0 : 1;
|
||||
unsigned bssidmatch1 : 1;
|
||||
unsigned MCS : 7;
|
||||
unsigned CWB : 1;
|
||||
unsigned HT_length : 16;
|
||||
unsigned Smoothing : 1;
|
||||
unsigned Not_Sounding : 1;
|
||||
unsigned : 1;
|
||||
unsigned Aggregation : 1;
|
||||
unsigned STBC : 2;
|
||||
unsigned FEC_CODING : 1;
|
||||
unsigned SGI : 1;
|
||||
unsigned rxend_state : 8;
|
||||
unsigned ampdu_cnt : 8;
|
||||
unsigned channel : 4;
|
||||
unsigned : 12;
|
||||
} wifi_pkt_rx_ctrl_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_pkt_rx_ctrl_t rx_ctrl;
|
||||
uint8_t payload[0]; /* ieee80211 packet buff */
|
||||
} wifi_promiscuous_pkt_t;
|
||||
|
||||
QuickEspNow quickEspNow;
|
||||
|
||||
bool QuickEspNow::begin (uint8_t channel, uint32_t wifi_interface, bool synchronousSend) {
|
||||
|
||||
this->synchronousSend = synchronousSend;
|
||||
|
||||
DEBUG_DBG (QESPNOW_TAG, "Channel: %d, Interface: %d", channel, wifi_interface);
|
||||
// Set the wifi interface
|
||||
switch (wifi_interface) {
|
||||
case WIFI_IF_STA:
|
||||
wifi_if = WIFI_IF_STA;
|
||||
break;
|
||||
case WIFI_IF_AP:
|
||||
wifi_if = WIFI_IF_AP;
|
||||
break;
|
||||
default:
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Unknown wifi interface");
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// check channel
|
||||
if (channel != CURRENT_WIFI_CHANNEL && (channel < MIN_WIFI_CHANNEL || channel > MAX_WIFI_CHANNEL)) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Invalid wifi channel %d", channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
// use current channel
|
||||
if (channel == CURRENT_WIFI_CHANNEL) {
|
||||
uint8_t ch;
|
||||
ch = WiFi.channel ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "Current channel: %d", ch);
|
||||
channel = ch;
|
||||
followWiFiChannel = true;
|
||||
} else {
|
||||
setChannel (channel);
|
||||
}
|
||||
DEBUG_INFO (QESPNOW_TAG, "Starting ESP-NOW in in channel %u interface %s", channel, wifi_if == WIFI_IF_STA ? "STA" : "AP");
|
||||
|
||||
this->channel = channel;
|
||||
|
||||
return initComms ();
|
||||
}
|
||||
|
||||
void QuickEspNow::stop () {
|
||||
DEBUG_INFO (QESPNOW_TAG, "-------------> ESP-NOW STOP");
|
||||
os_timer_disarm (&espnowTxTask);
|
||||
os_timer_disarm (&espnowRxTask);
|
||||
esp_now_unregister_recv_cb ();
|
||||
esp_now_unregister_send_cb ();
|
||||
esp_now_deinit ();
|
||||
followWiFiChannel = false;
|
||||
}
|
||||
|
||||
bool QuickEspNow::readyToSendData () {
|
||||
return tx_queue.size () < queueSize;
|
||||
}
|
||||
|
||||
bool QuickEspNow::setChannel (uint8_t channel) {
|
||||
|
||||
if (followWiFiChannel) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Cannot set channel while following WiFi channel");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wifi_set_channel (channel)) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Error setting wifi channel: %u", channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
this->channel = channel;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
comms_send_error_t QuickEspNow::send (const uint8_t* dstAddress, const uint8_t* payload, size_t payload_len) {
|
||||
comms_tx_queue_item_t message;
|
||||
|
||||
if (!dstAddress || !payload || !payload_len) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Parameters error");
|
||||
return COMMS_SEND_PARAM_ERROR;
|
||||
}
|
||||
|
||||
if (payload_len > ESP_NOW_MAX_DATA_LEN) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Length error. %d", payload_len);
|
||||
return COMMS_SEND_PAYLOAD_LENGTH_ERROR;
|
||||
}
|
||||
|
||||
if (tx_queue.size () >= ESPNOW_QUEUE_SIZE) {
|
||||
#ifdef MEAS_TPUT
|
||||
//comms_tx_queue_item_t* tempBuffer;
|
||||
//tempBuffer = tx_queue.front ();
|
||||
//txDataDropped += tempBuffer->payload_len;
|
||||
#endif // MEAS_TPUT
|
||||
// tx_queue.pop ();
|
||||
// DEBUG_DBG (QESPNOW_TAG, "Message dropped");
|
||||
return COMMS_SEND_QUEUE_FULL_ERROR;
|
||||
}
|
||||
|
||||
memcpy (message.dstAddress, dstAddress, ESP_NOW_ETH_ALEN);
|
||||
message.payload_len = payload_len;
|
||||
memcpy (message.payload, payload, payload_len);
|
||||
|
||||
if (tx_queue.push (&message)) {
|
||||
#ifdef MEAS_TPUT
|
||||
txDataSent += message.payload_len;
|
||||
#endif // MEAS_TPUT
|
||||
DEBUG_DBG (QESPNOW_TAG, "--------- %d Comms messages queued. Len: %d", tx_queue.size (), payload_len);
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "--------- Ready to send is %s", readyToSend ? "true" : "false");
|
||||
if (synchronousSend) {
|
||||
waitingForConfirmation = true;
|
||||
DEBUG_INFO (QESPNOW_TAG, "--------- Waiting for send confirmation");
|
||||
while (waitingForConfirmation) {
|
||||
// esp_yield ();
|
||||
delay(0);
|
||||
}
|
||||
DEBUG_INFO (QESPNOW_TAG, "--------- Confirmation is %s", sentStatus == ESP_NOW_SEND_SUCCESS ? "true" : "false");
|
||||
return (sentStatus == ESP_NOW_SEND_SUCCESS) ? COMMS_SEND_OK : COMMS_SEND_CONFIRM_ERROR;
|
||||
}
|
||||
return COMMS_SEND_OK;
|
||||
} else {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error queuing Comms message to " MACSTR, MAC2STR (dstAddress));
|
||||
return COMMS_SEND_MSG_ENQUEUE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::onDataRcvd (comms_hal_rcvd_data dataRcvd) {
|
||||
this->dataRcvd = dataRcvd;
|
||||
}
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
void QuickEspNow::calculateDataTP () {
|
||||
time_t measTime = (millis () - lastDataTPMeas);
|
||||
lastDataTPMeas = millis ();
|
||||
|
||||
if (txDataSent > 0) {
|
||||
txDataTP = txDataSent * 1000 / measTime;
|
||||
//DEBUG_WARN(QESPNOW_TAG, "Meas time: %d, Data sent: %d, Data TP: %f", measTime, txDataSent, txDataTP);
|
||||
txDroppedDataRatio = (float)txDataDropped / (float)txDataSent;
|
||||
//DEBUG_WARN(QESPNOW_TAG, "Data dropped: %d, Drop ratio: %f", txDataDropped, txDroppedDataRatio);
|
||||
txDataSent = 0;
|
||||
} else {
|
||||
txDataTP = 0;
|
||||
txDroppedDataRatio = 0;
|
||||
}
|
||||
if (rxDataReceived > 0) {
|
||||
rxDataTP = rxDataReceived * 1000 / measTime;
|
||||
//DEBUG_WARN(QESPNOW_TAG, "Meas time: %d, Data received: %d, Data TP: %f", measTime, rxDataReceived, rxDataTP);
|
||||
rxDataReceived = 0;
|
||||
} else {
|
||||
rxDataTP = 0;
|
||||
}
|
||||
txDataDropped = 0;
|
||||
}
|
||||
|
||||
void QuickEspNow::tp_timer_cb (void* param) {
|
||||
quickEspNow.calculateDataTP ();
|
||||
DEBUG_WARN (QESPNOW_TAG, "TxData TP: %.3f kbps, Drop Ratio: %.2f %%, RxDataTP: %.3f kbps",
|
||||
quickEspNow.txDataTP * 8 / 1000,
|
||||
quickEspNow.txDroppedDataRatio * 100,
|
||||
quickEspNow.rxDataTP * 8 / 1000);
|
||||
}
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
void QuickEspNow::onDataSent (comms_hal_sent_data sentResult) {
|
||||
this->sentResult = sentResult;
|
||||
}
|
||||
|
||||
int32_t QuickEspNow::sendEspNowMessage (comms_tx_queue_item_t* message) {
|
||||
int32_t error;
|
||||
|
||||
if (!message) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Message is null");
|
||||
return -1;
|
||||
}
|
||||
if (!(message->payload_len) || (message->payload_len > ESP_NOW_MAX_DATA_LEN)) {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Message length error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "ESP-NOW message to " MACSTR, MAC2STR (message->dstAddress));
|
||||
|
||||
readyToSend = false;
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "-------------- Ready to send: false");
|
||||
|
||||
error = esp_now_send (message->dstAddress, message->payload, message->payload_len);
|
||||
DEBUG_DBG (QESPNOW_TAG, "esp now send result = %d", error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowTxHandle () {
|
||||
if (readyToSend) {
|
||||
//DEBUG_WARN ("Process queue: Elements: %d", tx_queue.size ());
|
||||
comms_tx_queue_item_t* message;
|
||||
while (!tx_queue.empty ()) {
|
||||
if (!readyToSend) return;
|
||||
message = tx_queue.front ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message got from queue. %d left", tx_queue.size ());
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Ready to send is %s", readyToSend ? "true" : "false");
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "synchrnousSend is %s", synchronousSend ? "true" : "false");
|
||||
if (!sendEspNowMessage (message)) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Message to " MACSTR " sent. Len: %u", MAC2STR (message->dstAddress), message->payload_len);
|
||||
} else {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error sending message to " MACSTR ". Len: %u", MAC2STR (message->dstAddress), message->payload_len);
|
||||
}
|
||||
message->payload_len = 0;
|
||||
tx_queue.pop ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message pop. Queue size %d", tx_queue.size ());
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Not ready to send");
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::enableTransmit (bool enable) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Send esp-now task %s", enable ? "enabled" : "disabled");
|
||||
if (enable) {
|
||||
os_timer_arm (&espnowTxTask, TASK_PERIOD, true);
|
||||
os_timer_arm (&espnowRxTask, TASK_PERIOD, true);
|
||||
} else {
|
||||
os_timer_disarm (&espnowTxTask);
|
||||
os_timer_disarm (&espnowRxTask);
|
||||
}
|
||||
}
|
||||
|
||||
bool QuickEspNow::initComms () {
|
||||
if (esp_now_init ()) {
|
||||
DEBUG_ERROR (QESPNOW_TAG, "Failed to init ESP-NOW");
|
||||
// ESP.restart ();
|
||||
// delay (1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wifi_if == WIFI_IF_STA) {
|
||||
esp_now_set_self_role (ESP_NOW_ROLE_SLAVE);
|
||||
} else {
|
||||
esp_now_set_self_role (ESP_NOW_ROLE_CONTROLLER);
|
||||
}
|
||||
|
||||
esp_now_register_recv_cb (reinterpret_cast<esp_now_recv_cb_t>(rx_cb));
|
||||
esp_now_register_send_cb (reinterpret_cast<esp_now_send_cb_t>(tx_cb));
|
||||
|
||||
os_timer_setfn (&espnowTxTask, espnowTxTask_cb, NULL);
|
||||
os_timer_arm (&espnowTxTask, TASK_PERIOD, true);
|
||||
|
||||
os_timer_setfn (&espnowRxTask, espnowRxTask_cb, NULL);
|
||||
os_timer_arm (&espnowRxTask, TASK_PERIOD, true);
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
os_timer_setfn (&dataTPTimer, tp_timer_cb, NULL);
|
||||
os_timer_arm (&dataTPTimer, MEAS_TP_EVERY_MS, true);
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowTxTask_cb (void* param) {
|
||||
quickEspNow.espnowTxHandle ();
|
||||
}
|
||||
|
||||
void QuickEspNow::rx_cb (uint8_t* mac_addr, uint8_t* data, uint8_t len) {
|
||||
espnow_frame_format_t* espnow_data = (espnow_frame_format_t*)(data - sizeof (espnow_frame_format_t));
|
||||
wifi_promiscuous_pkt_t* promiscuous_pkt = (wifi_promiscuous_pkt_t*)(data - sizeof (wifi_pkt_rx_ctrl_t) - sizeof (espnow_frame_format_t));
|
||||
wifi_pkt_rx_ctrl_t* rx_ctrl = &promiscuous_pkt->rx_ctrl;
|
||||
|
||||
comms_rx_queue_item_t message;
|
||||
|
||||
DEBUG_DBG (QESPNOW_TAG, "Received message with RSSI %d from " MACSTR " Len: %u", rx_ctrl->rssi, MAC2STR (mac_addr), len);
|
||||
|
||||
memcpy (message.srcAddress, mac_addr, ESP_NOW_ETH_ALEN);
|
||||
memcpy (message.payload, data, len);
|
||||
message.payload_len = len;
|
||||
message.rssi = rx_ctrl->rssi - 100;
|
||||
memcpy (message.dstAddress, espnow_data->destination_address, ESP_NOW_ETH_ALEN);
|
||||
|
||||
if (quickEspNow.rx_queue.size () >= ESPNOW_QUEUE_SIZE) {
|
||||
quickEspNow.tx_queue.pop ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "Rx Message dropped");
|
||||
}
|
||||
|
||||
#ifdef MEAS_TPUT
|
||||
quickEspNow.rxDataReceived += len;
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
if (quickEspNow.rx_queue.push (&message)) {
|
||||
DEBUG_DBG (QESPNOW_TAG, "Message pushed to queue");
|
||||
} else {
|
||||
DEBUG_WARN (QESPNOW_TAG, "Error queuing message");
|
||||
}
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowRxTask_cb (void* param) {
|
||||
quickEspNow.espnowRxHandle ();
|
||||
}
|
||||
|
||||
void QuickEspNow::espnowRxHandle () {
|
||||
comms_rx_queue_item_t *rxMessage;
|
||||
|
||||
if (!rx_queue.empty ()) {
|
||||
rxMessage = rx_queue.front ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "Comms message got from queue. %d left", rx_queue.size ());
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Received message from " MACSTR " Len: %u", MAC2STR (rxMessage->srcAddress), rxMessage->payload_len);
|
||||
DEBUG_VERBOSE (QESPNOW_TAG, "Message: %.*s", rxMessage->payload_len, rxMessage->payload);
|
||||
|
||||
|
||||
if (quickEspNow.dataRcvd) {
|
||||
bool broadcast = ! memcmp (rxMessage->dstAddress, ESPNOW_BROADCAST_ADDRESS, ESP_NOW_ETH_ALEN);
|
||||
// quickEspNow.dataRcvd (mac_addr, data, len, rx_ctrl->rssi - 98); // rssi should be in dBm but it has added almost 100 dB. Do not know why
|
||||
quickEspNow.dataRcvd (rxMessage->srcAddress, rxMessage->payload, rxMessage->payload_len, rxMessage->rssi, broadcast); // rssi should be in dBm but it has added almost 100 dB. Do not know why
|
||||
}
|
||||
|
||||
rxMessage->payload_len = 0;
|
||||
rx_queue.pop ();
|
||||
DEBUG_DBG (QESPNOW_TAG, "RX Comms message pop. Queue size %d", rx_queue.size ());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void QuickEspNow::tx_cb (uint8_t* mac_addr, uint8_t status) {
|
||||
quickEspNow.readyToSend = true;
|
||||
quickEspNow.sentStatus = status;
|
||||
DEBUG_DBG (QESPNOW_TAG, "-------------- Tx Confirmed %s", status == ESP_NOW_SEND_SUCCESS ? "true" : "false");
|
||||
quickEspNow.waitingForConfirmation = false;
|
||||
DEBUG_DBG (QESPNOW_TAG, "-------------- Ready to send: true");
|
||||
if (quickEspNow.sentResult) {
|
||||
quickEspNow.sentResult (mac_addr, status);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ESP8266
|
145
lib/lib_div/QuickESPNow/src/QuickEspNow_esp8266.h
Normal file
145
lib/lib_div/QuickESPNow/src/QuickEspNow_esp8266.h
Normal file
@ -0,0 +1,145 @@
|
||||
#ifndef _QUICK_ESPNOW_ESP8266_h
|
||||
#define _QUICK_ESPNOW_ESP8266_h
|
||||
#ifdef ESP8266
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Comms_hal.h"
|
||||
|
||||
#include <espnow.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include "RingBuffer.h"
|
||||
// Disable debug dependency if debug level is 0
|
||||
#if DEBUG_LEVEL > 0
|
||||
#include <QuickDebug.h>
|
||||
constexpr auto QESPNOW_TAG = "QESPNOW";
|
||||
#else // DEBUG_LEVEL
|
||||
#define DEBUG_ERROR(...)
|
||||
#define DEBUG_INFO(...)
|
||||
#define DEBUG_VERBOSE(...)
|
||||
#define DEBUG_WARN(...)
|
||||
#define DEBUG_DBG(...)
|
||||
#endif
|
||||
|
||||
//#define MEAS_TPUT
|
||||
|
||||
static const uint8_t ESPNOW_BROADCAST_ADDRESS[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const uint8_t MIN_WIFI_CHANNEL = 0;
|
||||
static const uint8_t MAX_WIFI_CHANNEL = 14;
|
||||
static const uint8_t CURRENT_WIFI_CHANNEL = 255;
|
||||
static const size_t ESPNOW_MAX_MESSAGE_LENGTH = 255; ///< @brief Maximum message length
|
||||
static const uint8_t ESPNOW_ADDR_LEN = 6; ///< @brief Address length
|
||||
static const uint8_t ESPNOW_QUEUE_SIZE = 3; ///< @brief Queue size
|
||||
static const int TASK_PERIOD = 10; ///< @brief Rx and Tx tasks period
|
||||
#ifdef MEAS_TPUT
|
||||
static const time_t MEAS_TP_EVERY_MS = 10000; ///< @brief Measurement time period
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
#define ESP_NOW_ETH_ALEN 6
|
||||
#define ESP_NOW_MAX_DATA_LEN 250
|
||||
#define WIFI_IF_STA STATION_IF
|
||||
#define WIFI_IF_AP SOFTAP_IF
|
||||
|
||||
typedef enum {
|
||||
ESP_NOW_SEND_SUCCESS = 0, /**< Send ESPNOW data successfully */
|
||||
ESP_NOW_SEND_FAIL, /**< Send ESPNOW data fail */
|
||||
} esp_now_send_status_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t frame_head;
|
||||
uint16_t duration;
|
||||
uint8_t destination_address[6];
|
||||
uint8_t source_address[6];
|
||||
uint8_t broadcast_address[6];
|
||||
uint16_t sequence_control;
|
||||
|
||||
uint8_t category_code;
|
||||
uint8_t organization_identifier[3]; // 0x18fe34
|
||||
uint8_t random_values[4];
|
||||
struct {
|
||||
uint8_t element_id; // 0xdd
|
||||
uint8_t lenght; //
|
||||
uint8_t organization_identifier[3]; // 0x18fe34
|
||||
uint8_t type; // 4
|
||||
uint8_t version;
|
||||
uint8_t body[0];
|
||||
} vendor_specific_content;
|
||||
} __attribute__ ((packed)) espnow_frame_format_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t dstAddress[ESPNOW_ADDR_LEN]; /**< Message topic*/
|
||||
uint8_t payload[ESPNOW_MAX_MESSAGE_LENGTH]; /**< Message payload*/
|
||||
size_t payload_len; /**< Payload length*/
|
||||
} comms_tx_queue_item_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t srcAddress[ESPNOW_ADDR_LEN]; /**< Source Address */
|
||||
uint8_t dstAddress[ESPNOW_ADDR_LEN]; /**< Destination Address */
|
||||
uint8_t payload[ESPNOW_MAX_MESSAGE_LENGTH]; /**< Message payload */
|
||||
size_t payload_len; /**< Payload length */
|
||||
int8_t rssi; /**< RSSI */
|
||||
} comms_rx_queue_item_t;
|
||||
|
||||
class QuickEspNow : public Comms_halClass {
|
||||
public:
|
||||
QuickEspNow () :
|
||||
tx_queue (ESPNOW_QUEUE_SIZE), rx_queue (ESPNOW_QUEUE_SIZE) {}
|
||||
bool begin (uint8_t channel = 255, uint32_t interface = 0, bool synchronousSend = true) override;
|
||||
void stop () override;
|
||||
comms_send_error_t send (const uint8_t* dstAddress, const uint8_t* payload, size_t payload_len) override;
|
||||
comms_send_error_t sendBcast (const uint8_t* payload, size_t payload_len) {
|
||||
return send (ESPNOW_BROADCAST_ADDRESS, payload, payload_len);
|
||||
}
|
||||
void onDataRcvd (comms_hal_rcvd_data dataRcvd) override;
|
||||
void onDataSent (comms_hal_sent_data sentResult) override;
|
||||
uint8_t getAddressLength () override { return ESPNOW_ADDR_LEN; }
|
||||
uint8_t getMaxMessageLength () override { return ESPNOW_MAX_MESSAGE_LENGTH; }
|
||||
void enableTransmit (bool enable) override;
|
||||
bool setChannel (uint8_t channel);
|
||||
bool readyToSendData ();
|
||||
|
||||
protected:
|
||||
uint8_t wifi_if;
|
||||
ETSTimer espnowTxTask;
|
||||
ETSTimer espnowRxTask;
|
||||
#ifdef MEAS_TPUT
|
||||
ETSTimer dataTPTimer;
|
||||
unsigned long txDataSent = 0;
|
||||
unsigned long rxDataReceived = 0;
|
||||
unsigned long txDataDropped = 0;
|
||||
time_t lastDataTPMeas = 0;
|
||||
float txDataTP = 0;
|
||||
float rxDataTP = 0;
|
||||
float txDroppedDataRatio = 0;
|
||||
|
||||
static void tp_timer_cb (void* param);
|
||||
void calculateDataTP ();
|
||||
#endif // MEAS_TPUT
|
||||
|
||||
bool readyToSend = true;
|
||||
|
||||
bool waitingForConfirmation = false;
|
||||
bool synchronousSend = false;
|
||||
uint8_t sentStatus;
|
||||
int queueSize = ESPNOW_QUEUE_SIZE;
|
||||
|
||||
RingBuffer<comms_tx_queue_item_t> tx_queue;
|
||||
RingBuffer<comms_rx_queue_item_t> rx_queue;
|
||||
//uint8_t channel;
|
||||
bool followWiFiChannel = false;
|
||||
|
||||
bool initComms ();
|
||||
static void espnowTxTask_cb (void* param);
|
||||
static void espnowRxTask_cb (void* param);
|
||||
int32_t sendEspNowMessage (comms_tx_queue_item_t* message);
|
||||
void espnowTxHandle ();
|
||||
void espnowRxHandle ();
|
||||
|
||||
|
||||
static void ICACHE_FLASH_ATTR rx_cb (uint8_t* mac_addr, uint8_t* data, uint8_t len);
|
||||
static void ICACHE_FLASH_ATTR tx_cb (uint8_t* mac_addr, uint8_t status);
|
||||
};
|
||||
|
||||
extern QuickEspNow quickEspNow;
|
||||
|
||||
#endif // ESP8266
|
||||
#endif // _QUICK_ESPNOW_ESP8266_h
|
144
lib/lib_div/QuickESPNow/src/RingBuffer.h
Normal file
144
lib/lib_div/QuickESPNow/src/RingBuffer.h
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* @file RingBuffer.h
|
||||
* @author German Martin
|
||||
* @brief Library to build a gateway for EnigmaIoT system
|
||||
*/
|
||||
|
||||
#ifndef _RINGBUFFER_h
|
||||
#define _RINGBUFFER_h
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
// Disable debug dependency if debug level is 0
|
||||
#if DEBUG_LEVEL > 0
|
||||
#include <QuickDebug.h>
|
||||
static const char* RINGBUFFER_DEBUG_TAG = "RINGBUFFER";
|
||||
#else // DEBUG_LEVEL
|
||||
#define DEBUG_ERROR(...)
|
||||
#define DEBUG_INFO(...)
|
||||
#define DEBUG_VERBOSE(...)
|
||||
#define DEBUG_WARN(...)
|
||||
#define DEBUG_DBG(...)
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Ring buffer class. Used to implement message buffer
|
||||
*
|
||||
*/
|
||||
template <typename Telement>
|
||||
class RingBuffer {
|
||||
protected:
|
||||
int maxSize; ///< @brief Buffer size
|
||||
int numElements = 0; ///< @brief Number of elements that buffer currently has
|
||||
int readIndex = 0; ///< @brief Pointer to next item to be read
|
||||
int writeIndex = 0; ///< @brief Pointer to next position to write onto
|
||||
Telement* buffer; ///< @brief Actual buffer
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a ring buffer to hold `Telement` objects
|
||||
* @param range Buffer depth
|
||||
*/
|
||||
RingBuffer <Telement> (int range) : maxSize (range) {
|
||||
buffer = new Telement[maxSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EnigmaIOTRingBuffer destructor
|
||||
* @param range Free up buffer memory
|
||||
*/
|
||||
~RingBuffer () {
|
||||
maxSize = 0;
|
||||
delete[] (buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns actual number of elements that buffer holds
|
||||
* @return Returns Actual number of elements that buffer holds
|
||||
*/
|
||||
int size () { return numElements; }
|
||||
|
||||
/**
|
||||
* @brief Checks if buffer is full
|
||||
* @return Returns `true`if buffer is full, `false` otherwise
|
||||
*/
|
||||
bool isFull () { return numElements == maxSize; }
|
||||
|
||||
/**
|
||||
* @brief Checks if buffer is empty
|
||||
* @return Returns `true`if buffer has no elements stored, `false` otherwise
|
||||
*/
|
||||
bool empty () { return (numElements == 0); }
|
||||
|
||||
/**
|
||||
* @brief Adds a new item to buffer, deleting older element if it is full
|
||||
* @param item Element to add to buffer
|
||||
* @return Returns `false` if buffer was full before inserting the new element, `true` otherwise
|
||||
*/
|
||||
bool push (Telement* item) {
|
||||
bool wasFull = isFull ();
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "Add element. Buffer was %s", wasFull ? "full" : "not full");
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "Before -- > ReadIdx: %d. WriteIdx: %d. Size: %d", readIndex, writeIndex, numElements);
|
||||
#ifdef ESP32
|
||||
portMUX_TYPE myMutex = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL (&myMutex);
|
||||
#endif
|
||||
memcpy (&(buffer[writeIndex]), item, sizeof (Telement));
|
||||
//Serial.printf ("Copied: %d bytes\n", sizeof (Telement));
|
||||
writeIndex++;
|
||||
if (writeIndex >= maxSize) {
|
||||
writeIndex %= maxSize;
|
||||
}
|
||||
if (wasFull) { // old value is no longer valid
|
||||
readIndex++;
|
||||
if (readIndex >= maxSize) {
|
||||
readIndex %= maxSize;
|
||||
}
|
||||
} else {
|
||||
numElements++;
|
||||
}
|
||||
#ifdef ESP32
|
||||
portEXIT_CRITICAL (&myMutex);
|
||||
#endif
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "After -- > ReadIdx: %d. WriteIdx: %d. Size: %d", readIndex, writeIndex, numElements);
|
||||
return !wasFull;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deletes older item from buffer, if buffer is not empty
|
||||
* @return Returns `false` if buffer was empty before trying to delete element, `true` otherwise
|
||||
*/
|
||||
bool pop () {
|
||||
bool wasEmpty = empty ();
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "Remove element. Buffer was %s", wasEmpty ? "empty" : "not empty");
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "Before -- > ReadIdx: %d. WriteIdx: %d. Size: %d", readIndex, writeIndex, numElements);
|
||||
if (!wasEmpty) {
|
||||
readIndex++;
|
||||
if (readIndex >= maxSize) {
|
||||
readIndex %= maxSize;
|
||||
}
|
||||
numElements--;
|
||||
}
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "After -- > ReadIdx: %d. WriteIdx: %d. Size: %d", readIndex, writeIndex, numElements);
|
||||
return !wasEmpty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a pointer to older item in buffer, if buffer is not empty
|
||||
* @return Returns pointer to element. If buffer was empty before calling this method it returns `NULL`
|
||||
*/
|
||||
Telement* front () {
|
||||
DEBUG_DBG (RINGBUFFER_DEBUG_TAG, "Read element. ReadIdx: %d. WriteIdx: %d. Size: %d", readIndex, writeIndex, numElements);
|
||||
if (!empty ()) {
|
||||
return &(buffer[readIndex]);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _RINGBUFFER_h
|
11
lib/lib_div/QuickESPNow/test/README
Normal file
11
lib/lib_div/QuickESPNow/test/README
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Unit Testing and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/page/plus/unit-testing.html
|
135
lib/lib_div/QuickESPNow/test/test_peer_list/test_peer_list.cpp
Normal file
135
lib/lib_div/QuickESPNow/test/test_peer_list/test_peer_list.cpp
Normal file
@ -0,0 +1,135 @@
|
||||
#define UNIT_TEST
|
||||
|
||||
#include <QuickEspNow.h>
|
||||
#include <unity.h>
|
||||
|
||||
|
||||
PeerListClass PeerList;
|
||||
|
||||
uint8_t macs[ESP_NOW_MAX_TOTAL_PEER_NUM+1][6] = {
|
||||
{0x00,0x01,0x02,0x03,0x04,0x01},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x02},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x03},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x04},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x05},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x06},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x07},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x08},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x09},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x10},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x11},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x12},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x13},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x14},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x15},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x16},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x17},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x18},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x19},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x20},
|
||||
{0x00,0x01,0x02,0x03,0x04,0x21}
|
||||
};
|
||||
|
||||
|
||||
void setUp (void) {
|
||||
// set stuff up here
|
||||
Serial.begin (115200);
|
||||
}
|
||||
|
||||
void tearDown (void) {
|
||||
// clean stuff up here
|
||||
}
|
||||
|
||||
void test_add_one_peer () {
|
||||
uint8_t mac[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (mac));
|
||||
TEST_ASSERT_TRUE (PeerList.add_peer (mac));
|
||||
TEST_ASSERT_TRUE (PeerList.peer_exists (mac));
|
||||
TEST_ASSERT_EQUAL (1, PeerList.get_peer_number ());
|
||||
TEST_ASSERT_TRUE (PeerList.delete_peer (mac));
|
||||
TEST_ASSERT_EQUAL (0, PeerList.get_peer_number ());
|
||||
}
|
||||
|
||||
void test_add_existing_peer () {
|
||||
// Serial.println ("test_add_existing_peer");
|
||||
uint8_t mac[6] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (mac));
|
||||
TEST_ASSERT_TRUE(PeerList.add_peer(mac));
|
||||
TEST_ASSERT_TRUE (PeerList.peer_exists (mac));
|
||||
TEST_ASSERT_EQUAL (1, PeerList.get_peer_number ());
|
||||
TEST_ASSERT_FALSE (PeerList.add_peer (mac));
|
||||
TEST_ASSERT_EQUAL (1, PeerList.get_peer_number ());
|
||||
TEST_ASSERT_TRUE (PeerList.delete_peer (mac));
|
||||
TEST_ASSERT_EQUAL (0, PeerList.get_peer_number ());
|
||||
}
|
||||
|
||||
void test_add_max_peers () {
|
||||
// Serial.println ("test_add_max_peers");
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (macs[i]));
|
||||
TEST_ASSERT_TRUE(PeerList.add_peer(macs[i]));
|
||||
TEST_ASSERT_TRUE (PeerList.peer_exists (macs[i]));
|
||||
TEST_ASSERT_EQUAL (i + 1, PeerList.get_peer_number ());
|
||||
}
|
||||
// PeerList.dump_peer_list ();
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
TEST_ASSERT_TRUE (PeerList.delete_peer (macs[i]));
|
||||
TEST_ASSERT_EQUAL (ESP_NOW_MAX_TOTAL_PEER_NUM - i - 1, PeerList.get_peer_number ());
|
||||
}
|
||||
// PeerList.dump_peer_list ();
|
||||
}
|
||||
|
||||
void test_add_max_peers_plus_1 () {
|
||||
// Serial.println ("test_add_max_peers_plus_1");
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (macs[i]));
|
||||
TEST_ASSERT_TRUE (PeerList.add_peer (macs[i]));
|
||||
TEST_ASSERT_TRUE (PeerList.peer_exists (macs[i]));
|
||||
TEST_ASSERT_EQUAL (i + 1, PeerList.get_peer_number ());
|
||||
}
|
||||
// PeerList.dump_peer_list ();
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (macs[ESP_NOW_MAX_TOTAL_PEER_NUM]));
|
||||
TEST_ASSERT_FALSE (PeerList.add_peer (macs[ESP_NOW_MAX_TOTAL_PEER_NUM]));
|
||||
// PeerList.dump_peer_list ();
|
||||
TEST_ASSERT_FALSE (PeerList.peer_exists (macs[ESP_NOW_MAX_TOTAL_PEER_NUM]));
|
||||
TEST_ASSERT_EQUAL (ESP_NOW_MAX_TOTAL_PEER_NUM, PeerList.get_peer_number ());
|
||||
|
||||
for (uint8_t i = 0; i < ESP_NOW_MAX_TOTAL_PEER_NUM; i++) {
|
||||
TEST_ASSERT_TRUE (PeerList.delete_peer ());
|
||||
TEST_ASSERT_EQUAL (ESP_NOW_MAX_TOTAL_PEER_NUM - i - 1, PeerList.get_peer_number ());
|
||||
}
|
||||
// PeerList.dump_peer_list ();
|
||||
}
|
||||
|
||||
void process () {
|
||||
UNITY_BEGIN ();
|
||||
RUN_TEST (test_add_one_peer);
|
||||
RUN_TEST (test_add_existing_peer);
|
||||
RUN_TEST (test_add_max_peers);
|
||||
RUN_TEST (test_add_max_peers_plus_1);
|
||||
UNITY_END ();
|
||||
}
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
#include <Arduino.h>
|
||||
void setup () {
|
||||
// NOTE!!! Wait for >2 secs
|
||||
// if board doesn't support software reset via Serial.DTR/RTS
|
||||
delay (2000);
|
||||
|
||||
process ();
|
||||
}
|
||||
|
||||
void loop () {
|
||||
delay (1);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main (int argc, char** argv) {
|
||||
process ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -6,7 +6,7 @@
|
||||
#include "DataParsers.h"
|
||||
#include "DataParser.h"
|
||||
#include "Cosem.h"
|
||||
#include "ntohll.h"
|
||||
#include "ntohll_ams.h"
|
||||
|
||||
#define BUF_SIZE_HAN (1280)
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "ntohll.h"
|
||||
#include "ntohll_ams.h"
|
||||
|
||||
uint64_t ntohll(uint64_t x) {
|
||||
uint64_t ntohll_ams(uint64_t x) {
|
||||
return (((uint64_t)ntohl((uint32_t)x)) << 32) + ntohl(x >> 32);
|
||||
}
|
@ -3,6 +3,6 @@
|
||||
|
||||
#include "lwip/def.h"
|
||||
|
||||
uint64_t ntohll(uint64_t x);
|
||||
uint64_t ntohll_ams(uint64_t x);
|
||||
|
||||
#endif
|
@ -59,13 +59,14 @@
|
||||
// Number of maximum high/Low changes per packet.
|
||||
// We can handle up to 36 bit * 2 H/L changes per bit + 2 for sync
|
||||
// Для keeloq нужно увеличить RCSWITCH_MAX_CHANGES до 23+1+66*2+1=157
|
||||
#define RCSWITCH_MAX_CHANGES 75 // default 75 - longest protocol that requires this buffer size is 38/nexus
|
||||
//#define RCSWITCH_MAX_CHANGES 75 // default 75 - longest protocol that requires this buffer size is 38/nexus
|
||||
#define RCSWITCH_MAX_CHANGES 131 // default 75 - Supports 64 too
|
||||
|
||||
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
|
||||
// according to discussion on issue #14 it might be more suitable to set the separation
|
||||
// limit to the same time as the 'low' part of the sync signal for the current protocol.
|
||||
// should be set to the minimum value of pulselength * the sync signal
|
||||
#define RCSWITCH_SEPARATION_LIMIT 4100
|
||||
#define RCSWITCH_SEPARATION_LIMIT 3600
|
||||
|
||||
class RCSwitch {
|
||||
|
||||
|
@ -44,7 +44,7 @@ uint32_t *stack_thunk_light_save = NULL; /* Saved A1 while in BearSSL */
|
||||
uint32_t stack_thunk_light_refcnt = 0;
|
||||
|
||||
//#define _stackSize (5600/4)
|
||||
#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) || defined(USE_MQTT_AZURE_IOT)
|
||||
#if defined(USE_MQTT_CLIENT_CERT) || defined(USE_MQTT_AWS_IOT_LIGHT) || defined(USE_MQTT_AZURE_IOT)
|
||||
#define _stackSize (5300/4) // using a light version of bearssl we can save 300 bytes
|
||||
#else
|
||||
#define _stackSize (4800/4) // no private key, we can reduce a little, max observed 4300
|
||||
|
@ -195,6 +195,7 @@ void WiFiClientSecure_light::_clear() {
|
||||
_recvapp_buf = nullptr;
|
||||
_recvapp_len = 0;
|
||||
_insecure = false; // set to true when calling setPubKeyFingerprint()
|
||||
_rsa_only = true; // for now we disable ECDSA by default
|
||||
_fingerprint_any = true; // by default accept all fingerprints
|
||||
_fingerprint1 = nullptr;
|
||||
_fingerprint2 = nullptr;
|
||||
@ -302,7 +303,9 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port, int32_t timeout
|
||||
setLastError(ERR_TCP_CONNECT);
|
||||
return 0;
|
||||
}
|
||||
return _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
|
||||
bool success = _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
|
||||
if (!success) { stop(); }
|
||||
return success;
|
||||
}
|
||||
#else // ESP32
|
||||
int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) {
|
||||
@ -312,7 +315,9 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) {
|
||||
setLastError(ERR_TCP_CONNECT);
|
||||
return 0;
|
||||
}
|
||||
return _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
|
||||
bool success = _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
|
||||
if (!success) { stop(); }
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -569,6 +574,7 @@ int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) {
|
||||
|
||||
if (((int32_t)(millis() - (t + this->_loopTimeout)) >= 0)){
|
||||
DEBUG_BSSL("_run_until: Timeout\n");
|
||||
setLastError(ERR_TLS_TIMEOUT);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -813,8 +819,10 @@ extern "C" {
|
||||
|
||||
// The tag string doesn't really matter, but it should differ depending on
|
||||
// key type. For ECDSA it's a fixed string.
|
||||
sha1_update_len(&shactx, "ecdsa-sha2-nistp256", 19); // tag
|
||||
sha1_update_len(&shactx, eckey.q, eckey.qlen); // exponent
|
||||
sha1_update_len(&shactx, "ecdsa", 5); // tag
|
||||
int32_t curve = htonl(eckey.curve);
|
||||
sha1_update_len(&shactx, &curve, 4); // curve id as int32be
|
||||
sha1_update_len(&shactx, eckey.q, eckey.qlen); // public point
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
@ -888,16 +896,27 @@ extern "C" {
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
BR_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
||||
};
|
||||
static const uint16_t suites_RSA_ONLY[] = {
|
||||
BR_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
};
|
||||
#endif
|
||||
|
||||
// Default initializion for our SSL clients
|
||||
static void br_ssl_client_base_init(br_ssl_client_context *cc) {
|
||||
static void br_ssl_client_base_init(br_ssl_client_context *cc, bool _rsa_only) {
|
||||
br_ssl_client_zero(cc);
|
||||
// forbid SSL renegotiation, as we free the Private Key after handshake
|
||||
br_ssl_engine_add_flags(&cc->eng, BR_OPT_NO_RENEGOTIATION);
|
||||
|
||||
br_ssl_engine_set_versions(&cc->eng, BR_TLS12, BR_TLS12);
|
||||
#ifdef ESP8266
|
||||
br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0]));
|
||||
#else
|
||||
if (_rsa_only) {
|
||||
br_ssl_engine_set_suites(&cc->eng, suites_RSA_ONLY, (sizeof suites_RSA_ONLY) / (sizeof suites_RSA_ONLY[0]));
|
||||
} else {
|
||||
br_ssl_engine_set_suites(&cc->eng, suites, (sizeof suites) / (sizeof suites[0]));
|
||||
}
|
||||
#endif
|
||||
br_ssl_client_set_default_rsapub(cc);
|
||||
br_ssl_engine_set_default_rsavrfy(&cc->eng);
|
||||
|
||||
@ -945,7 +964,7 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
|
||||
_ctx_present = true;
|
||||
_eng = &_sc->eng; // Allocation/deallocation taken care of by the _sc shared_ptr
|
||||
|
||||
br_ssl_client_base_init(_sc.get());
|
||||
br_ssl_client_base_init(_sc.get(), _rsa_only);
|
||||
if (_alpn_names && _alpn_num > 0) {
|
||||
br_ssl_engine_set_protocol_names(_eng, _alpn_names, _alpn_num);
|
||||
}
|
||||
@ -980,16 +999,16 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
|
||||
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
|
||||
|
||||
// ============================================================
|
||||
// allocate Private key if needed, only if USE_MQTT_AWS_IOT
|
||||
// allocate Private key if needed, only if USE_MQTT_CLIENT_CERT
|
||||
LOG_HEAP_SIZE("_connectSSL before PrivKey allocation");
|
||||
#ifdef USE_MQTT_AWS_IOT
|
||||
#if defined(USE_MQTT_CLIENT_CERT)
|
||||
// ============================================================
|
||||
// Set the EC Private Key, only USE_MQTT_AWS_IOT
|
||||
// Set the EC Private Key, only USE_MQTT_CLIENT_CERT
|
||||
// limited to P256 curve
|
||||
br_ssl_client_set_single_ec(_sc.get(), _chain_P, 1,
|
||||
_sk_ec_P, _allowed_usages,
|
||||
_cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default());
|
||||
#endif // USE_MQTT_AWS_IOT
|
||||
#endif // USE_MQTT_CLIENT_CERT
|
||||
|
||||
// ============================================================
|
||||
// Start TLS connection, ALL
|
||||
|
@ -85,6 +85,10 @@ class WiFiClientSecure_light : public WiFiClient {
|
||||
_fingerprint2 = f2;
|
||||
_fingerprint_any = f_any;
|
||||
_insecure = true;
|
||||
_rsa_only = true; // if fingerprint, we limit to RSA only
|
||||
}
|
||||
void setRSAOnly(bool rsa_only) {
|
||||
_rsa_only = rsa_only;
|
||||
}
|
||||
const uint8_t * getRecvPubKeyFingerprint(void) {
|
||||
return _recv_fingerprint;
|
||||
@ -133,7 +137,7 @@ class WiFiClientSecure_light : public WiFiClient {
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t _loopTimeout=5000;
|
||||
uint32_t _loopTimeout=10000;
|
||||
void _clear();
|
||||
bool _ctx_present;
|
||||
std::shared_ptr<br_ssl_client_context> _sc;
|
||||
@ -150,6 +154,7 @@ class WiFiClientSecure_light : public WiFiClient {
|
||||
|
||||
bool _fingerprint_any; // accept all fingerprints
|
||||
bool _insecure; // force fingerprint
|
||||
bool _rsa_only; // restrict to RSA only key exchange (no ECDSA - enabled to force RSA fingerprints)
|
||||
const uint8_t *_fingerprint1; // fingerprint1 to be checked against
|
||||
const uint8_t *_fingerprint2; // fingerprint2 to be checked against
|
||||
uint8_t _recv_fingerprint[20]; // fingerprint received
|
||||
@ -187,7 +192,8 @@ class WiFiClientSecure_light : public WiFiClient {
|
||||
#define ERR_CANT_RESOLVE_IP -1001
|
||||
#define ERR_TCP_CONNECT -1002
|
||||
// #define ERR_MISSING_EC_KEY -1003 // deprecated, AWS IoT is not called if the private key is not present
|
||||
#define ERR_MISSING_CA -1004
|
||||
// #define ERR_MISSING_CA -1004 // deprecated
|
||||
#define ERR_TLS_TIMEOUT -1005
|
||||
|
||||
// For reference, BearSSL error codes:
|
||||
// #define BR_ERR_OK 0
|
||||
|
@ -315,6 +315,9 @@ int32_t analogAttach(uint32_t pin, bool output_invert) { // returns ledc chan
|
||||
(ledc_timer_t)timer, // timer_sel
|
||||
0, // duty
|
||||
0, // hpoint
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||
(ledc_sleep_mode_t) 2,
|
||||
#endif
|
||||
{ output_invert ? 1u : 0u },// output_invert
|
||||
};
|
||||
ledc_channel_config(&ledc_channel);
|
||||
@ -323,15 +326,20 @@ int32_t analogAttach(uint32_t pin, bool output_invert) { // returns ledc chan
|
||||
return chan;
|
||||
}
|
||||
|
||||
void analogDetach(uint32_t pin) {
|
||||
if (pin_to_channel[pin] > 0) {
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
ledcDetachPin(pin);
|
||||
#else
|
||||
ledcDetach(pin);
|
||||
#endif
|
||||
pin_to_channel[pin] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void analogDetachAll(void) {
|
||||
for (uint32_t pin = 0; pin < SOC_GPIO_PIN_COUNT; pin++) {
|
||||
if (pin_to_channel[pin] > 0) {
|
||||
#if ESP_IDF_VERSION_MAJOR < 5
|
||||
ledcDetachPin(pin);
|
||||
#else
|
||||
ledcDetach(pin);
|
||||
#endif
|
||||
}
|
||||
analogDetach(pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,11 @@ uint8_t ledcReadResolution(uint8_t chan);
|
||||
// Returns: hardware channel number, or -1 if it failed
|
||||
int32_t analogAttach(uint32_t pin, bool output_invert = false); // returns the ledc channel, or -1 if failed. This is implicitly called by analogWrite if the channel was not already allocated
|
||||
|
||||
//
|
||||
// analogDetach - detach attached GPIO from a hardware PWM
|
||||
//
|
||||
void analogDetach(uint32_t pin);
|
||||
|
||||
//
|
||||
// analogDetachAll - detach all attached GPIOs from a hardware PWM
|
||||
//
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
{
|
||||
BearSSL::WiFiClientSecure_light& wcs = static_cast<BearSSL::WiFiClientSecure_light&>(client);
|
||||
wcs.setPubKeyFingerprint(_fingerprint_any, _fingerprint_any, true); // allow all fingerprints
|
||||
wcs.setRSAOnly(false); // although we use fingerprint, we allow ECDSA
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user