forked from espressif/arduino-esp32
Compare commits
57 Commits
Author | SHA1 | Date | |
---|---|---|---|
b0582e1ec8 | |||
a539257a38 | |||
70656aa129 | |||
fa61b3bffe | |||
452c27a74a | |||
2fd39b1aff | |||
ff18a211e4 | |||
a6e3b29004 | |||
812d131663 | |||
00e69a28bc | |||
229d9b7366 | |||
6dd8be3262 | |||
28ea39cf05 | |||
f49c854ff3 | |||
879388e170 | |||
1085e9a8f0 | |||
bed9c96f41 | |||
5af139bb74 | |||
4f9a90fa0e | |||
310e78e6fd | |||
c827bb4177 | |||
1628f533a1 | |||
3e66aeff84 | |||
66d33f792c | |||
0de0d3f79a | |||
512d0d088f | |||
77810471ce | |||
be081ac026 | |||
4d3f6caa0d | |||
2db811f7f3 | |||
39836f12df | |||
25fd2d0f3b | |||
278fa0d87a | |||
b37f4069e4 | |||
e602145c2b | |||
6f6ee98188 | |||
1289f4be4b | |||
70f000da71 | |||
884e417a49 | |||
bb7dea1566 | |||
bff9f0b6b1 | |||
72803703fd | |||
0596a2ac86 | |||
fe1fdd2790 | |||
af7e489f01 | |||
5cfff190e9 | |||
7a332864ab | |||
8aa6e2e143 | |||
b5f317010c | |||
f644d9d157 | |||
a15b7e9088 | |||
ce340faf94 | |||
b69b04cb2b | |||
0cbba8a71d | |||
9e1f8cc457 | |||
cfe7e01158 | |||
fcd734a13c |
@ -7,6 +7,9 @@ python:
|
||||
os:
|
||||
- linux
|
||||
|
||||
git:
|
||||
depth: false
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "l/4Dt+KQ/mACtGAHDUsPr66fUte840PZoQ4xpPikqWZI0uARu4l+Ym7+sHinnT6fBqrj8AJeBYGz4nFa8NK4LutZn9mSD40w+sxl0wSV4oHV8rzKe3Cd8+sMG3+o33yWoikMNjSvqa73Q0rm+SgrlInNdZbuAyixL+a2alaWSnGPm4F2xwUGj+S33TOy5P/Xp77CYtCV5S8vzyk/eEdNhoF0GYePJVdfuzCOUjXMyT5OWxORkzzQ7Hnn/Ka/RDfV8Si4HgujLQBrK5q6iPnNBFqBSqilYBepSMn4opnOBpIm0SCgePz7XQEFC83buA7GUcnCnfg38bf+dCwHaODf1d1PmqVRYt2QmfinexXtM4afAtL0iBUDtvrfnXHzwW9w82VeZhpbJSVh9DUQvB0IlsZeCz9J9PUBAi3N+SMX+9l+BomYwRUlPuKY+Ef2JKk9q6mxtUkky5R0daAlVxEhpVdQks1rT+T+NMoDMemxQ3SKEiqAHh6EgHecruszffmZ71uLX9MpERpew0qN+UFiafws+jkTjx+3yF9yut0Hf9sMbeAYzzkGzRqJTUEBJ6B29Cql8M0yRXCNN/8wuuTHhG8esstozga4ZQoIVrq7mEAgup376PTcNfr1+imbbWVQ7lJdYIuDe6OS5V3OX6np11vgK/DbhfyzvQv9Z1zAGnM="
|
||||
|
@ -3,6 +3,7 @@ set(CORE_SRCS
|
||||
cores/esp32/cbuf.cpp
|
||||
cores/esp32/esp32-hal-adc.c
|
||||
cores/esp32/esp32-hal-bt.c
|
||||
cores/esp32/esp32-hal-cpu.c
|
||||
cores/esp32/esp32-hal-dac.c
|
||||
cores/esp32/esp32-hal-gpio.c
|
||||
cores/esp32/esp32-hal-i2c.c
|
||||
@ -150,6 +151,8 @@ set(BLE_SRCS
|
||||
libraries/BLE/src/BLEDescriptor.cpp
|
||||
libraries/BLE/src/BLEDescriptorMap.cpp
|
||||
libraries/BLE/src/BLEDevice.cpp
|
||||
libraries/BLE/src/BLEEddystoneTLM.cpp
|
||||
libraries/BLE/src/BLEEddystoneURL.cpp
|
||||
libraries/BLE/src/BLEExceptions.cpp
|
||||
libraries/BLE/src/BLEHIDDevice.cpp
|
||||
libraries/BLE/src/BLERemoteCharacteristic.cpp
|
||||
|
276
boards.txt
276
boards.txt
@ -1,4 +1,5 @@
|
||||
menu.UploadSpeed=Upload Speed
|
||||
menu.CPUFreq=CPU Frequency
|
||||
menu.FlashFreq=Flash Frequency
|
||||
menu.FlashMode=Flash Mode
|
||||
menu.FlashSize=Flash Size
|
||||
@ -10,7 +11,7 @@ menu.PSRAM=PSRAM
|
||||
|
||||
esp32.name=ESP32 Dev Module
|
||||
|
||||
esp32.upload.tool=esptool
|
||||
esp32.upload.tool=esptool_py
|
||||
esp32.upload.maximum_size=1310720
|
||||
esp32.upload.maximum_data_size=327680
|
||||
esp32.upload.wait_for_upload_port=true
|
||||
@ -43,12 +44,32 @@ esp32.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
esp32.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
esp32.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
esp32.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
esp32.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA)
|
||||
esp32.menu.PartitionScheme.huge_app.build.partitions=huge_app
|
||||
esp32.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
|
||||
esp32.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
esp32.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
esp32.menu.PartitionScheme.fatflash=16M Fat
|
||||
esp32.menu.PartitionScheme.fatflash.build.partitions=ffat
|
||||
|
||||
esp32.menu.CPUFreq.240=240MHz (WiFi/BT)
|
||||
esp32.menu.CPUFreq.240.build.f_cpu=240000000L
|
||||
esp32.menu.CPUFreq.160=160MHz (WiFi/BT)
|
||||
esp32.menu.CPUFreq.160.build.f_cpu=160000000L
|
||||
esp32.menu.CPUFreq.80=80MHz (WiFi/BT)
|
||||
esp32.menu.CPUFreq.80.build.f_cpu=80000000L
|
||||
esp32.menu.CPUFreq.40=40MHz (40MHz XTAL)
|
||||
esp32.menu.CPUFreq.40.build.f_cpu=40000000L
|
||||
esp32.menu.CPUFreq.26=26MHz (26MHz XTAL)
|
||||
esp32.menu.CPUFreq.26.build.f_cpu=26000000L
|
||||
esp32.menu.CPUFreq.20=20MHz (40MHz XTAL)
|
||||
esp32.menu.CPUFreq.20.build.f_cpu=20000000L
|
||||
esp32.menu.CPUFreq.13=13MHz (26MHz XTAL)
|
||||
esp32.menu.CPUFreq.13.build.f_cpu=13000000L
|
||||
esp32.menu.CPUFreq.10=10MHz (40MHz XTAL)
|
||||
esp32.menu.CPUFreq.10.build.f_cpu=10000000L
|
||||
|
||||
esp32.menu.FlashMode.qio=QIO
|
||||
esp32.menu.FlashMode.qio.build.flash_mode=dio
|
||||
esp32.menu.FlashMode.qio.build.boot=qio
|
||||
@ -108,7 +129,7 @@ esp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
esp32wrover.name=ESP32 Wrover Module
|
||||
|
||||
esp32wrover.upload.tool=esptool
|
||||
esp32wrover.upload.tool=esptool_py
|
||||
esp32wrover.upload.maximum_size=1310720
|
||||
esp32wrover.upload.maximum_data_size=327680
|
||||
esp32wrover.upload.wait_for_upload_port=true
|
||||
@ -136,6 +157,9 @@ esp32wrover.menu.PartitionScheme.minimal.build.partitions=minimal
|
||||
esp32wrover.menu.PartitionScheme.no_ota=No OTA (Large APP)
|
||||
esp32wrover.menu.PartitionScheme.no_ota.build.partitions=no_ota
|
||||
esp32wrover.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
|
||||
esp32wrover.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA)
|
||||
esp32wrover.menu.PartitionScheme.huge_app.build.partitions=huge_app
|
||||
esp32wrover.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (Large APPS with OTA)
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
|
||||
esp32wrover.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
|
||||
@ -190,7 +214,7 @@ esp32wrover.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
pico32.name=ESP32 Pico Kit
|
||||
|
||||
pico32.upload.tool=esptool
|
||||
pico32.upload.tool=esptool_py
|
||||
pico32.upload.maximum_size=1310720
|
||||
pico32.upload.maximum_data_size=327680
|
||||
pico32.upload.wait_for_upload_port=true
|
||||
@ -241,9 +265,52 @@ pico32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
turta_iot_node.name=Turta IoT Node
|
||||
|
||||
turta_iot_node.upload.tool=esptool_py
|
||||
turta_iot_node.upload.maximum_size=1310720
|
||||
turta_iot_node.upload.maximum_data_size=327680
|
||||
turta_iot_node.upload.wait_for_upload_port=true
|
||||
|
||||
turta_iot_node.serial.disableDTR=true
|
||||
turta_iot_node.serial.disableRTS=true
|
||||
|
||||
turta_iot_node.build.mcu=esp32
|
||||
turta_iot_node.build.core=esp32
|
||||
turta_iot_node.build.variant=pico32
|
||||
turta_iot_node.build.board=ESP32_PICO
|
||||
|
||||
turta_iot_node.build.f_cpu=240000000L
|
||||
turta_iot_node.build.flash_size=4MB
|
||||
turta_iot_node.build.flash_freq=80m
|
||||
turta_iot_node.build.flash_mode=dio
|
||||
turta_iot_node.build.boot=dio
|
||||
turta_iot_node.build.partitions=default
|
||||
turta_iot_node.build.defines=
|
||||
|
||||
turta_iot_node.menu.UploadSpeed.921600=921600
|
||||
turta_iot_node.menu.UploadSpeed.921600.upload.speed=921600
|
||||
turta_iot_node.menu.UploadSpeed.115200=115200
|
||||
turta_iot_node.menu.UploadSpeed.115200.upload.speed=115200
|
||||
|
||||
turta_iot_node.menu.DebugLevel.none=None
|
||||
turta_iot_node.menu.DebugLevel.none.build.code_debug=0
|
||||
turta_iot_node.menu.DebugLevel.error=Error
|
||||
turta_iot_node.menu.DebugLevel.error.build.code_debug=1
|
||||
turta_iot_node.menu.DebugLevel.warn=Warn
|
||||
turta_iot_node.menu.DebugLevel.warn.build.code_debug=2
|
||||
turta_iot_node.menu.DebugLevel.info=Info
|
||||
turta_iot_node.menu.DebugLevel.info.build.code_debug=3
|
||||
turta_iot_node.menu.DebugLevel.debug=Debug
|
||||
turta_iot_node.menu.DebugLevel.debug.build.code_debug=4
|
||||
turta_iot_node.menu.DebugLevel.verbose=Verbose
|
||||
turta_iot_node.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
ttgo-lora32-v1.name=TTGO LoRa32-OLED V1
|
||||
|
||||
ttgo-lora32-v1.upload.tool=esptool
|
||||
ttgo-lora32-v1.upload.tool=esptool_py
|
||||
ttgo-lora32-v1.upload.maximum_size=1310720
|
||||
ttgo-lora32-v1.upload.maximum_data_size=294912
|
||||
ttgo-lora32-v1.upload.wait_for_upload_port=true
|
||||
@ -299,7 +366,7 @@ ttgo-lora32-v1.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
cw02.name=XinaBox CW02
|
||||
|
||||
cw02.upload.tool=esptool
|
||||
cw02.upload.tool=esptool_py
|
||||
cw02.upload.maximum_size=1310720
|
||||
cw02.upload.maximum_data_size=294912
|
||||
cw02.upload.wait_for_upload_port=true
|
||||
@ -375,7 +442,7 @@ cw02.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
esp32thing.name=SparkFun ESP32 Thing
|
||||
|
||||
esp32thing.upload.tool=esptool
|
||||
esp32thing.upload.tool=esptool_py
|
||||
esp32thing.upload.maximum_size=1310720
|
||||
esp32thing.upload.maximum_data_size=327680
|
||||
esp32thing.upload.wait_for_upload_port=true
|
||||
@ -442,7 +509,7 @@ esp32thing.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
nina_w10.name=u-blox NINA-W10 series (ESP32)
|
||||
|
||||
nina_w10.upload.tool=esptool
|
||||
nina_w10.upload.tool=esptool_py
|
||||
nina_w10.upload.maximum_size=1310720
|
||||
nina_w10.upload.maximum_data_size=327680
|
||||
nina_w10.upload.wait_for_upload_port=true
|
||||
@ -481,7 +548,7 @@ nina_w10.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
widora-air.name=Widora AIR
|
||||
|
||||
widora-air.upload.tool=esptool
|
||||
widora-air.upload.tool=esptool_py
|
||||
widora-air.upload.maximum_size=1310720
|
||||
widora-air.upload.maximum_data_size=327680
|
||||
widora-air.upload.wait_for_upload_port=true
|
||||
@ -525,7 +592,7 @@ widora-air.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
esp320.name=Electronic SweetPeas - ESP320
|
||||
|
||||
esp320.upload.tool=esptool
|
||||
esp320.upload.tool=esptool_py
|
||||
esp320.upload.maximum_size=1310720
|
||||
esp320.upload.maximum_data_size=327680
|
||||
esp320.upload.wait_for_upload_port=true
|
||||
@ -569,7 +636,7 @@ esp320.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
nano32.name=Nano32
|
||||
|
||||
nano32.upload.tool=esptool
|
||||
nano32.upload.tool=esptool_py
|
||||
nano32.upload.maximum_size=1310720
|
||||
nano32.upload.maximum_data_size=327680
|
||||
nano32.upload.wait_for_upload_port=true
|
||||
@ -613,7 +680,7 @@ nano32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
d32.name=LOLIN D32
|
||||
|
||||
d32.upload.tool=esptool
|
||||
d32.upload.tool=esptool_py
|
||||
d32.upload.maximum_size=1310720
|
||||
d32.upload.maximum_data_size=327680
|
||||
d32.upload.wait_for_upload_port=true
|
||||
@ -686,7 +753,7 @@ d32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
d32_pro.name=LOLIN D32 PRO
|
||||
|
||||
d32_pro.upload.tool=esptool
|
||||
d32_pro.upload.tool=esptool_py
|
||||
d32_pro.upload.maximum_size=1310720
|
||||
d32_pro.upload.maximum_data_size=327680
|
||||
d32_pro.upload.wait_for_upload_port=true
|
||||
@ -764,7 +831,7 @@ d32_pro.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
lolin32.name=WEMOS LOLIN32
|
||||
|
||||
lolin32.upload.tool=esptool
|
||||
lolin32.upload.tool=esptool_py
|
||||
lolin32.upload.maximum_size=1310720
|
||||
lolin32.upload.maximum_data_size=327680
|
||||
lolin32.upload.wait_for_upload_port=true
|
||||
@ -817,7 +884,7 @@ lolin32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
pocket_32.name=Dongsen Tech Pocket 32
|
||||
|
||||
pocket_32.upload.tool=esptool
|
||||
pocket_32.upload.tool=esptool_py
|
||||
pocket_32.upload.maximum_size=1310720
|
||||
pocket_32.upload.maximum_data_size=327680
|
||||
pocket_32.upload.wait_for_upload_port=true
|
||||
@ -861,7 +928,7 @@ pocket_32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
WeMosBat.name="WeMos" WiFi&Bluetooth Battery
|
||||
|
||||
WeMosBat.upload.tool=esptool
|
||||
WeMosBat.upload.tool=esptool_py
|
||||
WeMosBat.upload.maximum_size=1310720
|
||||
WeMosBat.upload.maximum_data_size=327680
|
||||
WeMosBat.upload.wait_for_upload_port=true
|
||||
@ -918,7 +985,7 @@ WeMosBat.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
espea32.name=ESPea32
|
||||
|
||||
espea32.upload.tool=esptool
|
||||
espea32.upload.tool=esptool_py
|
||||
espea32.upload.maximum_size=1310720
|
||||
espea32.upload.maximum_data_size=327680
|
||||
espea32.upload.wait_for_upload_port=true
|
||||
@ -962,7 +1029,7 @@ espea32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
quantum.name=Noduino Quantum
|
||||
|
||||
quantum.upload.tool=esptool
|
||||
quantum.upload.tool=esptool_py
|
||||
quantum.upload.maximum_size=1310720
|
||||
quantum.upload.maximum_data_size=327680
|
||||
quantum.upload.wait_for_upload_port=true
|
||||
@ -1006,7 +1073,7 @@ quantum.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
node32s.name=Node32s
|
||||
|
||||
node32s.upload.tool=esptool
|
||||
node32s.upload.tool=esptool_py
|
||||
node32s.upload.maximum_size=1310720
|
||||
node32s.upload.maximum_data_size=327680
|
||||
node32s.upload.wait_for_upload_port=true
|
||||
@ -1050,7 +1117,7 @@ node32s.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
hornbill32dev.name=Hornbill ESP32 Dev
|
||||
|
||||
hornbill32dev.upload.tool=esptool
|
||||
hornbill32dev.upload.tool=esptool_py
|
||||
hornbill32dev.upload.maximum_size=1310720
|
||||
hornbill32dev.upload.maximum_data_size=327680
|
||||
hornbill32dev.upload.wait_for_upload_port=true
|
||||
@ -1094,7 +1161,7 @@ hornbill32dev.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
hornbill32minima.name=Hornbill ESP32 Minima
|
||||
|
||||
hornbill32minima.upload.tool=esptool
|
||||
hornbill32minima.upload.tool=esptool_py
|
||||
hornbill32minima.upload.maximum_size=1310720
|
||||
hornbill32minima.upload.maximum_data_size=327680
|
||||
hornbill32minima.upload.wait_for_upload_port=true
|
||||
@ -1137,7 +1204,7 @@ hornbill32minima.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
firebeetle32.name=FireBeetle-ESP32
|
||||
|
||||
firebeetle32.upload.tool=esptool
|
||||
firebeetle32.upload.tool=esptool_py
|
||||
firebeetle32.upload.maximum_size=1310720
|
||||
firebeetle32.upload.maximum_data_size=327680
|
||||
firebeetle32.upload.wait_for_upload_port=true
|
||||
@ -1181,7 +1248,7 @@ firebeetle32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
intorobot-fig.name=IntoRobot Fig
|
||||
|
||||
intorobot-fig.upload.tool=esptool
|
||||
intorobot-fig.upload.tool=esptool_py
|
||||
intorobot-fig.upload.maximum_size=1310720
|
||||
intorobot-fig.upload.maximum_data_size=327680
|
||||
intorobot-fig.upload.wait_for_upload_port=true
|
||||
@ -1225,7 +1292,7 @@ intorobot-fig.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
onehorse32dev.name=Onehorse ESP32 Dev Module
|
||||
|
||||
onehorse32dev.upload.tool=esptool
|
||||
onehorse32dev.upload.tool=esptool_py
|
||||
onehorse32dev.upload.maximum_size=1310720
|
||||
onehorse32dev.upload.maximum_data_size=327680
|
||||
onehorse32dev.upload.wait_for_upload_port=true
|
||||
@ -1269,7 +1336,7 @@ onehorse32dev.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
featheresp32.name=Adafruit ESP32 Feather
|
||||
|
||||
featheresp32.upload.tool=esptool
|
||||
featheresp32.upload.tool=esptool_py
|
||||
featheresp32.upload.maximum_size=1310720
|
||||
featheresp32.upload.maximum_data_size=327680
|
||||
featheresp32.upload.wait_for_upload_port=true
|
||||
@ -1326,7 +1393,7 @@ featheresp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
nodemcu-32s.name=NodeMCU-32S
|
||||
|
||||
nodemcu-32s.upload.tool=esptool
|
||||
nodemcu-32s.upload.tool=esptool_py
|
||||
nodemcu-32s.upload.maximum_size=1310720
|
||||
nodemcu-32s.upload.maximum_data_size=327680
|
||||
nodemcu-32s.upload.wait_for_upload_port=true
|
||||
@ -1370,7 +1437,7 @@ nodemcu-32s.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
mhetesp32devkit.name=MH ET LIVE ESP32DevKIT
|
||||
|
||||
mhetesp32devkit.upload.tool=esptool
|
||||
mhetesp32devkit.upload.tool=esptool_py
|
||||
mhetesp32devkit.upload.maximum_size=1310720
|
||||
mhetesp32devkit.upload.maximum_data_size=327680
|
||||
mhetesp32devkit.upload.wait_for_upload_port=true
|
||||
@ -1436,7 +1503,7 @@ mhetesp32devkit.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
mhetesp32minikit.name=MH ET LIVE ESP32MiniKit
|
||||
|
||||
mhetesp32minikit.upload.tool=esptool
|
||||
mhetesp32minikit.upload.tool=esptool_py
|
||||
mhetesp32minikit.upload.maximum_size=1310720
|
||||
mhetesp32minikit.upload.maximum_data_size=327680
|
||||
mhetesp32minikit.upload.wait_for_upload_port=true
|
||||
@ -1502,7 +1569,7 @@ mhetesp32minikit.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
esp32vn-iot-uno.name=ESP32vn IoT Uno
|
||||
|
||||
esp32vn-iot-uno.upload.tool=esptool
|
||||
esp32vn-iot-uno.upload.tool=esptool_py
|
||||
esp32vn-iot-uno.upload.maximum_size=1310720
|
||||
esp32vn-iot-uno.upload.maximum_data_size=327680
|
||||
esp32vn-iot-uno.upload.wait_for_upload_port=true
|
||||
@ -1546,7 +1613,7 @@ esp32vn-iot-uno.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
esp32doit-devkit-v1.name=DOIT ESP32 DEVKIT V1
|
||||
|
||||
esp32doit-devkit-v1.upload.tool=esptool
|
||||
esp32doit-devkit-v1.upload.tool=esptool_py
|
||||
esp32doit-devkit-v1.upload.maximum_size=1310720
|
||||
esp32doit-devkit-v1.upload.maximum_data_size=327680
|
||||
esp32doit-devkit-v1.upload.wait_for_upload_port=true
|
||||
@ -1601,7 +1668,7 @@ esp32doit-devkit-v1.menu.DebugLevel.debug.build.code_debug=4
|
||||
|
||||
esp32-evb.name=OLIMEX ESP32-EVB
|
||||
|
||||
esp32-evb.upload.tool=esptool
|
||||
esp32-evb.upload.tool=esptool_py
|
||||
esp32-evb.upload.maximum_size=1310720
|
||||
esp32-evb.upload.maximum_data_size=327680
|
||||
esp32-evb.upload.wait_for_upload_port=true
|
||||
@ -1634,7 +1701,7 @@ esp32-evb.menu.UploadSpeed.115200.upload.speed=115200
|
||||
|
||||
esp32-gateway.name=OLIMEX ESP32-GATEWAY
|
||||
|
||||
esp32-gateway.upload.tool=esptool
|
||||
esp32-gateway.upload.tool=esptool_py
|
||||
esp32-gateway.upload.maximum_size=1310720
|
||||
esp32-gateway.upload.maximum_data_size=327680
|
||||
esp32-gateway.upload.wait_for_upload_port=true
|
||||
@ -1667,7 +1734,7 @@ esp32-gateway.menu.UploadSpeed.115200.upload.speed=115200
|
||||
|
||||
esp32-poe.name=OLIMEX ESP32-PoE
|
||||
|
||||
esp32-poe.upload.tool=esptool
|
||||
esp32-poe.upload.tool=esptool_py
|
||||
esp32-poe.upload.maximum_size=1310720
|
||||
esp32-poe.upload.maximum_data_size=327680
|
||||
esp32-poe.upload.wait_for_upload_port=true
|
||||
@ -1700,7 +1767,7 @@ esp32-poe.menu.UploadSpeed.115200.upload.speed=115200
|
||||
|
||||
espino32.name=ThaiEasyElec's ESPino32
|
||||
|
||||
espino32.upload.tool=esptool
|
||||
espino32.upload.tool=esptool_py
|
||||
espino32.upload.maximum_size=1310720
|
||||
espino32.upload.maximum_data_size=327680
|
||||
espino32.upload.wait_for_upload_port=true
|
||||
@ -1744,7 +1811,7 @@ espino32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
m5stack-core-esp32.name=M5Stack-Core-ESP32
|
||||
|
||||
m5stack-core-esp32.upload.tool=esptool
|
||||
m5stack-core-esp32.upload.tool=esptool_py
|
||||
m5stack-core-esp32.upload.maximum_size=1310720
|
||||
m5stack-core-esp32.upload.maximum_data_size=327680
|
||||
m5stack-core-esp32.upload.wait_for_upload_port=true
|
||||
@ -1823,7 +1890,7 @@ m5stack-core-esp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
m5stack-fire.name=M5Stack-FIRE
|
||||
|
||||
m5stack-fire.upload.tool=esptool
|
||||
m5stack-fire.upload.tool=esptool_py
|
||||
m5stack-fire.upload.maximum_size=6553600
|
||||
m5stack-fire.upload.maximum_data_size=4521984
|
||||
m5stack-fire.upload.wait_for_upload_port=true
|
||||
@ -1887,7 +1954,7 @@ m5stack-fire.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
odroid_esp32.name=ODROID ESP32
|
||||
|
||||
odroid_esp32.upload.tool=esptool
|
||||
odroid_esp32.upload.tool=esptool_py
|
||||
odroid_esp32.upload.maximum_size=1310720
|
||||
odroid_esp32.upload.maximum_data_size=327680
|
||||
odroid_esp32.upload.wait_for_upload_port=true
|
||||
@ -1966,7 +2033,7 @@ odroid_esp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
heltec_wifi_kit_32.name=Heltec_WIFI_Kit_32
|
||||
|
||||
heltec_wifi_kit_32.upload.tool=esptool
|
||||
heltec_wifi_kit_32.upload.tool=esptool_py
|
||||
heltec_wifi_kit_32.upload.maximum_size=1310720
|
||||
heltec_wifi_kit_32.upload.maximum_data_size=327680
|
||||
heltec_wifi_kit_32.upload.wait_for_upload_port=true
|
||||
@ -2010,7 +2077,7 @@ heltec_wifi_kit_32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
heltec_wifi_lora_32.name=Heltec_WIFI_LoRa_32
|
||||
|
||||
heltec_wifi_lora_32.upload.tool=esptool
|
||||
heltec_wifi_lora_32.upload.tool=esptool_py
|
||||
heltec_wifi_lora_32.upload.maximum_size=1310720
|
||||
heltec_wifi_lora_32.upload.maximum_data_size=327680
|
||||
heltec_wifi_lora_32.upload.wait_for_upload_port=true
|
||||
@ -2054,7 +2121,7 @@ heltec_wifi_lora_32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
espectro32.name=ESPectro32
|
||||
|
||||
espectro32.upload.tool=esptool
|
||||
espectro32.upload.tool=esptool_py
|
||||
espectro32.upload.maximum_size=1310720
|
||||
espectro32.upload.maximum_data_size=327680
|
||||
espectro32.upload.wait_for_upload_port=true
|
||||
@ -2130,7 +2197,7 @@ espectro32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
##############################################################
|
||||
CoreESP32.name=Microduino-CoreESP32
|
||||
|
||||
CoreESP32.upload.tool=esptool
|
||||
CoreESP32.upload.tool=esptool_py
|
||||
CoreESP32.upload.maximum_size=1310720
|
||||
CoreESP32.upload.maximum_data_size=327680
|
||||
CoreESP32.upload.wait_for_upload_port=true
|
||||
@ -2175,7 +2242,7 @@ CoreESP32.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
alksesp32.name=ALKS ESP32
|
||||
|
||||
alksesp32.upload.tool=esptool
|
||||
alksesp32.upload.tool=esptool_py
|
||||
alksesp32.upload.maximum_size=1310720
|
||||
alksesp32.upload.maximum_data_size=327680
|
||||
alksesp32.upload.wait_for_upload_port=true
|
||||
@ -2264,7 +2331,7 @@ alksesp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
wipy3.name=WiPy 3.0
|
||||
|
||||
wipy3.upload.tool=esptool
|
||||
wipy3.upload.tool=esptool_py
|
||||
wipy3.upload.maximum_size=1310720
|
||||
wipy3.upload.maximum_data_size=294912
|
||||
wipy3.upload.wait_for_upload_port=true
|
||||
@ -2321,7 +2388,7 @@ wipy3.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
bpi-bit.name=BPI-BIT
|
||||
|
||||
bpi-bit.upload.tool=esptool
|
||||
bpi-bit.upload.tool=esptool_py
|
||||
bpi-bit.upload.maximum_size=1310720
|
||||
bpi-bit.upload.maximum_data_size=294912
|
||||
bpi-bit.upload.wait_for_upload_port=true
|
||||
@ -2364,7 +2431,7 @@ bpi-bit.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
wesp32.name=Silicognition wESP32
|
||||
|
||||
wesp32.upload.tool=esptool
|
||||
wesp32.upload.tool=esptool_py
|
||||
wesp32.upload.maximum_size=1310720
|
||||
wesp32.upload.maximum_data_size=327680
|
||||
wesp32.upload.wait_for_upload_port=true
|
||||
@ -2421,7 +2488,7 @@ wesp32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
t-beam.name=T-Beam
|
||||
|
||||
t-beam.upload.tool=esptool
|
||||
t-beam.upload.tool=esptool_py
|
||||
t-beam.upload.maximum_size=1310720
|
||||
t-beam.upload.maximum_data_size=327680
|
||||
t-beam.upload.wait_for_upload_port=true
|
||||
@ -2482,7 +2549,7 @@ t-beam.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
d-duino-32.name=D-duino-32
|
||||
|
||||
d-duino-32.upload.tool=esptool
|
||||
d-duino-32.upload.tool=esptool_py
|
||||
d-duino-32.upload.maximum_size=1310720
|
||||
d-duino-32.upload.maximum_data_size=327680
|
||||
d-duino-32.upload.wait_for_upload_port=true
|
||||
@ -2553,7 +2620,7 @@ d-duino-32.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
lopy.name=LoPy
|
||||
|
||||
lopy.upload.tool=esptool
|
||||
lopy.upload.tool=esptool_py
|
||||
lopy.upload.maximum_size=1310720
|
||||
lopy.upload.maximum_data_size=327680
|
||||
lopy.upload.wait_for_upload_port=true
|
||||
@ -2609,7 +2676,7 @@ lopy.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
lopy4.name=LoPy4
|
||||
|
||||
lopy4.upload.tool=esptool
|
||||
lopy4.upload.tool=esptool_py
|
||||
lopy4.upload.maximum_size=1310720
|
||||
lopy4.upload.maximum_data_size=327680
|
||||
lopy4.upload.wait_for_upload_port=true
|
||||
@ -2665,3 +2732,116 @@ lopy4.menu.DebugLevel.debug=Debug
|
||||
lopy4.menu.DebugLevel.debug.build.code_debug=4
|
||||
lopy4.menu.DebugLevel.verbose=Verbose
|
||||
lopy4.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
##############################################################
|
||||
|
||||
oroca_edubot.name=OROCA EduBot
|
||||
|
||||
oroca_edubot.upload.tool=esptool_py
|
||||
oroca_edubot.upload.maximum_size=1310720
|
||||
oroca_edubot.upload.maximum_data_size=327680
|
||||
oroca_edubot.upload.wait_for_upload_port=true
|
||||
|
||||
oroca_edubot.serial.disableDTR=true
|
||||
oroca_edubot.serial.disableRTS=true
|
||||
|
||||
oroca_edubot.build.mcu=esp32
|
||||
oroca_edubot.build.core=esp32
|
||||
oroca_edubot.build.variant=oroca_edubot
|
||||
oroca_edubot.build.board=OROCA_EDUBOT
|
||||
|
||||
oroca_edubot.build.f_cpu=240000000L
|
||||
oroca_edubot.build.flash_mode=dio
|
||||
oroca_edubot.build.flash_size=4MB
|
||||
oroca_edubot.build.boot=dio
|
||||
oroca_edubot.build.partitions=default
|
||||
oroca_edubot.build.defines=
|
||||
|
||||
oroca_edubot.menu.FlashFreq.80=80MHz
|
||||
oroca_edubot.menu.FlashFreq.80.build.flash_freq=80m
|
||||
oroca_edubot.menu.FlashFreq.40=40MHz
|
||||
oroca_edubot.menu.FlashFreq.40.build.flash_freq=40m
|
||||
|
||||
oroca_edubot.menu.UploadSpeed.921600=921600
|
||||
oroca_edubot.menu.UploadSpeed.921600.upload.speed=921600
|
||||
oroca_edubot.menu.UploadSpeed.115200=115200
|
||||
oroca_edubot.menu.UploadSpeed.115200.upload.speed=115200
|
||||
oroca_edubot.menu.UploadSpeed.256000.windows=256000
|
||||
oroca_edubot.menu.UploadSpeed.256000.upload.speed=256000
|
||||
oroca_edubot.menu.UploadSpeed.230400.windows.upload.speed=256000
|
||||
oroca_edubot.menu.UploadSpeed.230400=230400
|
||||
oroca_edubot.menu.UploadSpeed.230400.upload.speed=230400
|
||||
oroca_edubot.menu.UploadSpeed.460800.linux=460800
|
||||
oroca_edubot.menu.UploadSpeed.460800.macosx=460800
|
||||
oroca_edubot.menu.UploadSpeed.460800.upload.speed=460800
|
||||
oroca_edubot.menu.UploadSpeed.512000.windows=512000
|
||||
oroca_edubot.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
oroca_edubot.menu.DebugLevel.none=None
|
||||
oroca_edubot.menu.DebugLevel.none.build.code_debug=0
|
||||
oroca_edubot.menu.DebugLevel.error=Error
|
||||
oroca_edubot.menu.DebugLevel.error.build.code_debug=1
|
||||
oroca_edubot.menu.DebugLevel.warn=Warn
|
||||
oroca_edubot.menu.DebugLevel.warn.build.code_debug=2
|
||||
oroca_edubot.menu.DebugLevel.info=Info
|
||||
oroca_edubot.menu.DebugLevel.info.build.code_debug=3
|
||||
oroca_edubot.menu.DebugLevel.debug=Debug
|
||||
oroca_edubot.menu.DebugLevel.debug.build.code_debug=4
|
||||
oroca_edubot.menu.DebugLevel.verbose=Verbose
|
||||
oroca_edubot.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
|
||||
|
||||
##############################################################
|
||||
|
||||
fm-devkit.name=ESP32 FM DevKit
|
||||
|
||||
fm-devkit.upload.tool=esptool
|
||||
fm-devkit.upload.maximum_size=1310720
|
||||
fm-devkit.upload.maximum_data_size=327680
|
||||
fm-devkit.upload.wait_for_upload_port=true
|
||||
|
||||
fm-devkit.serial.disableDTR=true
|
||||
fm-devkit.serial.disableRTS=true
|
||||
|
||||
fm-devkit.build.mcu=esp32
|
||||
fm-devkit.build.core=esp32
|
||||
fm-devkit.build.variant=fm-devkit
|
||||
fm-devkit.build.board=fm-devkit
|
||||
|
||||
fm-devkit.build.f_cpu=240000000L
|
||||
fm-devkit.build.flash_size=4MB
|
||||
fm-devkit.build.flash_freq=80m
|
||||
fm-devkit.build.flash_mode=dio
|
||||
fm-devkit.build.boot=dio
|
||||
fm-devkit.build.partitions=default
|
||||
fm-devkit.build.defines=
|
||||
|
||||
fm-devkit.menu.UploadSpeed.921600=921600
|
||||
fm-devkit.menu.UploadSpeed.921600.upload.speed=921600
|
||||
fm-devkit.menu.UploadSpeed.115200=115200
|
||||
fm-devkit.menu.UploadSpeed.115200.upload.speed=115200
|
||||
fm-devkit.menu.UploadSpeed.256000.windows=256000
|
||||
fm-devkit.menu.UploadSpeed.256000.upload.speed=256000
|
||||
fm-devkit.menu.UploadSpeed.230400.windows.upload.speed=256000
|
||||
fm-devkit.menu.UploadSpeed.230400=230400
|
||||
fm-devkit.menu.UploadSpeed.230400.upload.speed=230400
|
||||
fm-devkit.menu.UploadSpeed.460800.linux=460800
|
||||
fm-devkit.menu.UploadSpeed.460800.macosx=460800
|
||||
fm-devkit.menu.UploadSpeed.460800.upload.speed=460800
|
||||
fm-devkit.menu.UploadSpeed.512000.windows=512000
|
||||
fm-devkit.menu.UploadSpeed.512000.upload.speed=512000
|
||||
|
||||
fm-devkit.menu.DebugLevel.none=None
|
||||
fm-devkit.menu.DebugLevel.none.build.code_debug=0
|
||||
fm-devkit.menu.DebugLevel.error=Error
|
||||
fm-devkit.menu.DebugLevel.error.build.code_debug=1
|
||||
fm-devkit.menu.DebugLevel.warn=Warn
|
||||
fm-devkit.menu.DebugLevel.warn.build.code_debug=2
|
||||
fm-devkit.menu.DebugLevel.info=Info
|
||||
fm-devkit.menu.DebugLevel.info.build.code_debug=3
|
||||
fm-devkit.menu.DebugLevel.debug=Debug
|
||||
fm-devkit.menu.DebugLevel.debug.build.code_debug=4
|
||||
fm-devkit.menu.DebugLevel.verbose=Verbose
|
||||
fm-devkit.menu.DebugLevel.verbose.build.code_debug=5
|
||||
|
||||
|
@ -26,10 +26,11 @@
|
||||
#include <soc/soc.h>
|
||||
#include <soc/efuse_reg.h>
|
||||
#include <esp_partition.h>
|
||||
#include <esp_ota_ops.h>
|
||||
extern "C" {
|
||||
#include <esp_image_format.h>
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_image_format.h"
|
||||
}
|
||||
#include <MD5Builder.h>
|
||||
|
||||
/**
|
||||
* User-defined Literals
|
||||
@ -156,7 +157,7 @@ static uint32_t sketchSize(sketchSize_t response) {
|
||||
.size = running->size,
|
||||
};
|
||||
data.start_addr = running_pos.offset;
|
||||
esp_image_load(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||
esp_image_verify(ESP_IMAGE_VERIFY, &running_pos, &data);
|
||||
if (response) {
|
||||
return running_pos.size - data.image_len;
|
||||
} else {
|
||||
@ -168,8 +169,53 @@ uint32_t EspClass::getSketchSize () {
|
||||
return sketchSize(SKETCH_SIZE_TOTAL);
|
||||
}
|
||||
|
||||
String EspClass::getSketchMD5()
|
||||
{
|
||||
static String result;
|
||||
if (result.length()) {
|
||||
return result;
|
||||
}
|
||||
uint32_t lengthLeft = getSketchSize();
|
||||
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
if (!running) {
|
||||
log_e("Partition could not be found");
|
||||
|
||||
return String();
|
||||
}
|
||||
const size_t bufSize = SPI_FLASH_SEC_SIZE;
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[bufSize]);
|
||||
uint32_t offset = 0;
|
||||
if(!buf.get()) {
|
||||
log_e("Not enough memory to allocate buffer");
|
||||
|
||||
return String();
|
||||
}
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
while( lengthLeft > 0) {
|
||||
size_t readBytes = (lengthLeft < bufSize) ? lengthLeft : bufSize;
|
||||
if (!ESP.flashRead(running->address + offset, reinterpret_cast<uint32_t*>(buf.get()), (readBytes + 3) & ~3)) {
|
||||
log_e("Could not read buffer from flash");
|
||||
|
||||
return String();
|
||||
}
|
||||
md5.add(buf.get(), readBytes);
|
||||
lengthLeft -= readBytes;
|
||||
offset += readBytes;
|
||||
}
|
||||
md5.calculate();
|
||||
result = md5.toString();
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t EspClass::getFreeSketchSpace () {
|
||||
return sketchSize(SKETCH_SIZE_FREE);
|
||||
const esp_partition_t* _partition = esp_ota_get_next_update_partition(NULL);
|
||||
if(!_partition){
|
||||
return 0;
|
||||
}
|
||||
|
||||
return _partition->size;
|
||||
}
|
||||
|
||||
uint8_t EspClass::getChipRevision(void)
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
FlashMode_t magicFlashChipMode(uint8_t byte);
|
||||
|
||||
uint32_t getSketchSize();
|
||||
String getSketchMD5();
|
||||
uint32_t getFreeSketchSpace();
|
||||
|
||||
bool flashEraseSector(uint32_t sector);
|
||||
|
@ -73,6 +73,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
|
||||
}
|
||||
}
|
||||
|
||||
void HardwareSerial::updateBaudRate(unsigned long baud)
|
||||
{
|
||||
uartSetBaudRate(_uart, baud);
|
||||
}
|
||||
|
||||
void HardwareSerial::end()
|
||||
{
|
||||
if(uartGetDebug() == _uart_nr) {
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
|
||||
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL);
|
||||
void end();
|
||||
void updateBaudRate(unsigned long baud);
|
||||
int available(void);
|
||||
int availableForWrite(void);
|
||||
int peek(void);
|
||||
|
@ -63,7 +63,7 @@ size_t Print::printf(const char *format, ...)
|
||||
len = vsnprintf(temp, len+1, format, arg);
|
||||
write((uint8_t*)temp, len);
|
||||
va_end(arg);
|
||||
if(len > 64){
|
||||
if(len >= sizeof(loc_buf)){
|
||||
delete[] temp;
|
||||
}
|
||||
return len;
|
||||
|
211
cores/esp32/esp32-hal-cpu.c
Normal file
211
cores/esp32/esp32-hal-cpu.c
Normal file
@ -0,0 +1,211 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/xtensa_timer.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "esp32-hal.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
typedef struct apb_change_cb_s {
|
||||
struct apb_change_cb_s * next;
|
||||
void * arg;
|
||||
apb_change_cb_t cb;
|
||||
} apb_change_t;
|
||||
|
||||
const uint32_t MHZ = 1000000;
|
||||
|
||||
static apb_change_t * apb_change_callbacks = NULL;
|
||||
static xSemaphoreHandle apb_change_lock = NULL;
|
||||
|
||||
static void initApbChangeCallback(){
|
||||
static volatile bool initialized = false;
|
||||
if(!initialized){
|
||||
initialized = true;
|
||||
apb_change_lock = xSemaphoreCreateMutex();
|
||||
if(!apb_change_lock){
|
||||
initialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void triggerApbChangeCallback(apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||
initApbChangeCallback();
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
apb_change_t * r = apb_change_callbacks;
|
||||
while(r != NULL){
|
||||
r->cb(r->arg, ev_type, old_apb, new_apb);
|
||||
r=r->next;
|
||||
}
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
}
|
||||
|
||||
bool addApbChangeCallback(void * arg, apb_change_cb_t cb){
|
||||
initApbChangeCallback();
|
||||
apb_change_t * c = (apb_change_t*)malloc(sizeof(apb_change_t));
|
||||
if(!c){
|
||||
log_e("Callback Object Malloc Failed");
|
||||
return false;
|
||||
}
|
||||
c->next = NULL;
|
||||
c->arg = arg;
|
||||
c->cb = cb;
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
if(apb_change_callbacks == NULL){
|
||||
apb_change_callbacks = c;
|
||||
} else {
|
||||
apb_change_t * r = apb_change_callbacks;
|
||||
if(r->cb != cb || r->arg != arg){
|
||||
while(r->next){
|
||||
r = r->next;
|
||||
if(r->cb == cb && r->arg == arg){
|
||||
free(c);
|
||||
goto unlock_and_exit;
|
||||
}
|
||||
}
|
||||
r->next = c;
|
||||
}
|
||||
}
|
||||
unlock_and_exit:
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool removeApbChangeCallback(void * arg, apb_change_cb_t cb){
|
||||
initApbChangeCallback();
|
||||
xSemaphoreTake(apb_change_lock, portMAX_DELAY);
|
||||
apb_change_t * r = apb_change_callbacks;
|
||||
if(r == NULL){
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return false;
|
||||
}
|
||||
if(r->cb == cb && r->arg == arg){
|
||||
apb_change_callbacks = r->next;
|
||||
free(r);
|
||||
} else {
|
||||
while(r->next && (r->next->cb != cb || r->next->arg != arg)){
|
||||
r = r->next;
|
||||
}
|
||||
if(r->next == NULL || r->next->cb != cb || r->next->arg != arg){
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return false;
|
||||
}
|
||||
apb_change_t * c = r->next;
|
||||
r->next = c->next;
|
||||
free(c);
|
||||
}
|
||||
xSemaphoreGive(apb_change_lock);
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t calculateApb(rtc_cpu_freq_config_t * conf){
|
||||
if(conf->freq_mhz >= 80){
|
||||
return 80 * MHZ;
|
||||
}
|
||||
return (conf->source_freq_mhz * MHZ) / conf->div;
|
||||
}
|
||||
|
||||
void esp_timer_impl_update_apb_freq(uint32_t apb_ticks_per_us); //private in IDF
|
||||
|
||||
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz){
|
||||
rtc_cpu_freq_config_t conf, cconf;
|
||||
uint32_t capb, apb;
|
||||
//Get XTAL Frequency and calculate min CPU MHz
|
||||
rtc_xtal_freq_t xtal = rtc_clk_xtal_freq_get();
|
||||
uint32_t min_cpu_mhz = 10;
|
||||
if(xtal > RTC_XTAL_FREQ_AUTO){
|
||||
if(xtal < RTC_XTAL_FREQ_40M) {
|
||||
min_cpu_mhz = xtal / 2; //13Mhz for 26Mhz XTAL
|
||||
if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2)){
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2);
|
||||
return false;
|
||||
}
|
||||
} else if(cpu_freq_mhz <= xtal && cpu_freq_mhz != xtal && cpu_freq_mhz != (xtal/2) && cpu_freq_mhz != (xtal/4)){
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(cpu_freq_mhz > xtal && cpu_freq_mhz != 240 && cpu_freq_mhz != 160 && cpu_freq_mhz != 80){
|
||||
if(xtal >= RTC_XTAL_FREQ_40M){
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2, xtal/4);
|
||||
} else {
|
||||
log_e("Bad frequency: %u MHz! Options are: 240, 160, 80, %u and %u MHz", cpu_freq_mhz, xtal, xtal/2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//Get current CPU clock configuration
|
||||
rtc_clk_cpu_freq_get_config(&cconf);
|
||||
//return if frequency has not changed
|
||||
if(cconf.freq_mhz == cpu_freq_mhz){
|
||||
return true;
|
||||
}
|
||||
//Get configuration for the new CPU frequency
|
||||
if(!rtc_clk_cpu_freq_mhz_to_config(cpu_freq_mhz, &conf)){
|
||||
log_e("CPU clock could not be set to %u MHz", cpu_freq_mhz);
|
||||
return false;
|
||||
}
|
||||
//Current APB
|
||||
capb = calculateApb(&cconf);
|
||||
//New APB
|
||||
apb = calculateApb(&conf);
|
||||
log_d("%s: %u / %u = %u Mhz, APB: %u Hz", (conf.source == RTC_CPU_FREQ_SRC_PLL)?"PLL":((conf.source == RTC_CPU_FREQ_SRC_APLL)?"APLL":((conf.source == RTC_CPU_FREQ_SRC_XTAL)?"XTAL":"8M")), conf.source_freq_mhz, conf.div, conf.freq_mhz, apb);
|
||||
//Call peripheral functions before the APB change
|
||||
if(apb_change_callbacks){
|
||||
triggerApbChangeCallback(APB_BEFORE_CHANGE, capb, apb);
|
||||
}
|
||||
//Make the frequency change
|
||||
rtc_clk_cpu_freq_set_config_fast(&conf);
|
||||
if(capb != apb){
|
||||
//Update REF_TICK (uncomment if REF_TICK is different than 1MHz)
|
||||
//if(conf.freq_mhz < 80){
|
||||
// ESP_REG(APB_CTRL_XTAL_TICK_CONF_REG) = conf.freq_mhz / (REF_CLK_FREQ / MHZ) - 1;
|
||||
//}
|
||||
//Update APB Freq REG
|
||||
rtc_clk_apb_freq_update(apb);
|
||||
//Update esp_timer divisor
|
||||
esp_timer_impl_update_apb_freq(apb / MHZ);
|
||||
}
|
||||
//Update FreeRTOS Tick Divisor
|
||||
uint32_t fcpu = (conf.freq_mhz >= 80)?(conf.freq_mhz * MHZ):(apb);
|
||||
_xt_tick_divisor = fcpu / XT_TICK_PER_SEC;
|
||||
//Call peripheral functions after the APB change
|
||||
if(apb_change_callbacks){
|
||||
triggerApbChangeCallback(APB_AFTER_CHANGE, capb, apb);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t getCpuFrequencyMhz(){
|
||||
rtc_cpu_freq_config_t conf;
|
||||
rtc_clk_cpu_freq_get_config(&conf);
|
||||
return conf.freq_mhz;
|
||||
}
|
||||
|
||||
uint32_t getXtalFrequencyMhz(){
|
||||
return rtc_clk_xtal_freq_get();
|
||||
}
|
||||
|
||||
uint32_t getApbFrequency(){
|
||||
rtc_cpu_freq_config_t conf;
|
||||
rtc_clk_cpu_freq_get_config(&conf);
|
||||
return calculateApb(&conf);
|
||||
}
|
48
cores/esp32/esp32-hal-cpu.h
Normal file
48
cores/esp32/esp32-hal-cpu.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _ESP32_HAL_CPU_H_
|
||||
#define _ESP32_HAL_CPU_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef enum { APB_BEFORE_CHANGE, APB_AFTER_CHANGE } apb_change_ev_t;
|
||||
|
||||
typedef void (* apb_change_cb_t)(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||
|
||||
bool addApbChangeCallback(void * arg, apb_change_cb_t cb);
|
||||
bool removeApbChangeCallback(void * arg, apb_change_cb_t cb);
|
||||
|
||||
//function takes the following frequencies as valid values:
|
||||
// 240, 160, 80 <<< For all XTAL types
|
||||
// 40, 20, 10 <<< For 40MHz XTAL
|
||||
// 26, 13 <<< For 26MHz XTAL
|
||||
// 24, 12 <<< For 24MHz XTAL
|
||||
bool setCpuFrequencyMhz(uint32_t cpu_freq_mhz);
|
||||
|
||||
uint32_t getCpuFrequencyMhz(); // In MHz
|
||||
uint32_t getXtalFrequencyMhz(); // In MHz
|
||||
uint32_t getApbFrequency(); // In Hz
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP32_HAL_CPU_H_ */
|
@ -287,7 +287,7 @@ extern void __detachInterrupt(uint8_t pin)
|
||||
}
|
||||
__pinInterruptHandlers[pin].fn = NULL;
|
||||
__pinInterruptHandlers[pin].arg = NULL;
|
||||
__pinInterruptHandlers[pin].arg = false;
|
||||
__pinInterruptHandlers[pin].functional = false;
|
||||
|
||||
GPIO.pin[pin].int_ena = 0;
|
||||
GPIO.pin[pin].int_type = 0;
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "esp32-hal-cpu.h" // cpu clock change support 31DEC2018
|
||||
//#define I2C_DEV(i) (volatile i2c_dev_t *)((i)?DR_REG_I2C1_EXT_BASE:DR_REG_I2C_EXT_BASE)
|
||||
//#define I2C_DEV(i) ((i2c_dev_t *)(REG_I2C_BASE(i)))
|
||||
#define I2C_SCL_IDX(p) ((p==0)?I2CEXT0_SCL_OUT_IDX:((p==1)?I2CEXT1_SCL_OUT_IDX:0))
|
||||
@ -206,8 +206,8 @@ static i2c_t _i2c_bus_array[2] = {
|
||||
{(volatile i2c_dev_t *)(DR_REG_I2C1_EXT_BASE_FIXED), 1, -1, -1,I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0}
|
||||
};
|
||||
#else
|
||||
#define I2C_MUTEX_LOCK() do {} while (xSemaphoreTake(i2c->lock, portMAX_DELAY) != pdPASS)
|
||||
#define I2C_MUTEX_UNLOCK() xSemaphoreGive(i2c->lock)
|
||||
#define I2C_MUTEX_LOCK() do {} while (xSemaphoreTakeRecursive(i2c->lock, portMAX_DELAY) != pdPASS)
|
||||
#define I2C_MUTEX_UNLOCK() xSemaphoreGiveRecursive(i2c->lock)
|
||||
|
||||
static i2c_t _i2c_bus_array[2] = {
|
||||
{(volatile i2c_dev_t *)(DR_REG_I2C_EXT_BASE_FIXED), NULL, 0, -1, -1, I2C_NONE,I2C_NONE,I2C_ERROR_OK,NULL,NULL,NULL,0,0,0,0,0,0},
|
||||
@ -248,9 +248,10 @@ static void IRAM_ATTR i2cDumpCmdQueue(i2c_t *i2c)
|
||||
|
||||
/* Stickbreaker ISR mode debug support
|
||||
*/
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||
static void i2cDumpDqData(i2c_t * i2c)
|
||||
{
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||
#if defined (ENABLE_I2C_DEBUG_BUFFER)
|
||||
uint16_t a=0;
|
||||
char buff[140];
|
||||
I2C_DATA_QUEUE_t *tdq;
|
||||
@ -306,9 +307,12 @@ static void i2cDumpDqData(i2c_t * i2c)
|
||||
}
|
||||
a++;
|
||||
}
|
||||
#else
|
||||
log_i("Debug Buffer not Enabled");
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
||||
static void i2cDumpI2c(i2c_t * i2c)
|
||||
{
|
||||
log_e("i2c=%p",i2c);
|
||||
@ -332,11 +336,12 @@ static void i2cDumpI2c(i2c_t * i2c)
|
||||
i2cDumpDqData(i2c);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)
|
||||
static void i2cDumpInts(uint8_t num)
|
||||
{
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO) && (defined ENABLE_I2C_DEBUG_BUFFER)
|
||||
|
||||
#if defined (ENABLE_I2C_DEBUG_BUFFER)
|
||||
uint32_t b;
|
||||
log_i("%u row\tcount\tINTR\tTX\tRX\tTick ",num);
|
||||
for(uint32_t a=1; a<=INTBUFFMAX; a++) {
|
||||
@ -349,9 +354,10 @@ static void i2cDumpInts(uint8_t num)
|
||||
log_i("Debug Buffer not Enabled");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||
static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t ack_rec: 1; /*This register stores the value of ACK bit.*/
|
||||
@ -377,11 +383,11 @@ static void IRAM_ATTR i2cDumpStatus(i2c_t * i2c){
|
||||
sr.val= i2c->dev->status_reg.val;
|
||||
|
||||
log_i("ack(%d) sl_rw(%d) to(%d) arb(%d) busy(%d) sl(%d) trans(%d) rx(%d) tx(%d) sclMain(%d) scl(%d)",sr.ack_rec,sr.slave_rw,sr.time_out,sr.arb_lost,sr.bus_busy,sr.slave_addressed,sr.byte_trans, sr.rx_fifo_cnt, sr.tx_fifo_cnt,sr.scl_main_state_last, sr.scl_state_last);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void i2cDumpFifo(i2c_t * i2c){
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||
static void i2cDumpFifo(i2c_t * i2c){
|
||||
char buf[64];
|
||||
uint16_t k = 0;
|
||||
uint16_t i = fifoPos+1;
|
||||
@ -422,8 +428,8 @@ if(i != fifoPos){// actual data
|
||||
}
|
||||
}while( i!= fifoPos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void IRAM_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char locus[]){
|
||||
#if (ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO)&&(defined ENABLE_I2C_DEBUG_BUFFER)
|
||||
@ -439,6 +445,39 @@ static void IRAM_ATTR i2cTriggerDumps(i2c_t * i2c, uint8_t trigger, const char l
|
||||
}
|
||||
// end of debug support routines
|
||||
|
||||
/* Start of CPU Clock change Support
|
||||
*/
|
||||
|
||||
static void i2cApbChangeCallback(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||
i2c_t* i2c = (i2c_t*) arg; // recover data
|
||||
if(i2c == NULL) { // point to peripheral control block does not exits
|
||||
return false;
|
||||
}
|
||||
uint32_t oldFreq=0;
|
||||
switch(ev_type){
|
||||
case APB_BEFORE_CHANGE :
|
||||
if(new_apb < 3000000) {// too slow
|
||||
log_e("apb speed %d too slow",new_apb);
|
||||
break;
|
||||
}
|
||||
I2C_MUTEX_LOCK(); // lock will spin until current transaction is completed
|
||||
break;
|
||||
case APB_AFTER_CHANGE :
|
||||
oldFreq = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period); //read old apbCycles
|
||||
if(oldFreq>0) { // was configured with value
|
||||
oldFreq = old_apb / oldFreq;
|
||||
i2cSetFrequency(i2c,oldFreq);
|
||||
}
|
||||
I2C_MUTEX_UNLOCK();
|
||||
break;
|
||||
default :
|
||||
log_e("unk ev %u",ev_type);
|
||||
I2C_MUTEX_UNLOCK();
|
||||
}
|
||||
return;
|
||||
}
|
||||
/* End of CPU Clock change Support
|
||||
*/
|
||||
static void IRAM_ATTR i2cSetCmd(i2c_t * i2c, uint8_t index, uint8_t op_code, uint8_t byte_num, bool ack_val, bool ack_exp, bool ack_check)
|
||||
{
|
||||
I2C_COMMAND_t cmd;
|
||||
@ -1142,7 +1181,7 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
||||
if(tdq->ctrl.addrReq ==2) { // 10bit address
|
||||
taddr =((tdq->ctrl.addr >> 7) & 0xFE)
|
||||
|tdq->ctrl.mode;
|
||||
taddr = (taddr <<8) || (tdq->ctrl.addr&0xFF);
|
||||
taddr = (taddr <<8) | (tdq->ctrl.addr&0xFF);
|
||||
} else { // 7bit address
|
||||
taddr = ((tdq->ctrl.addr<<1)&0xFE)
|
||||
|tdq->ctrl.mode;
|
||||
@ -1215,6 +1254,12 @@ i2c_err_t i2cProcQueue(i2c_t * i2c, uint32_t *readCount, uint16_t timeOutMillis)
|
||||
I2C_MUTEX_UNLOCK();
|
||||
return I2C_ERROR_MEMORY;
|
||||
}
|
||||
if( !addApbChangeCallback( i2c, i2cApbChangeCallback)) {
|
||||
log_e("install apb Callback failed");
|
||||
I2C_MUTEX_UNLOCK();
|
||||
return I2C_ERROR_DEV;
|
||||
}
|
||||
|
||||
}
|
||||
//hang until it completes.
|
||||
|
||||
@ -1346,6 +1391,9 @@ static void i2cReleaseISR(i2c_t * i2c)
|
||||
if(i2c->intr_handle) {
|
||||
esp_intr_free(i2c->intr_handle);
|
||||
i2c->intr_handle=NULL;
|
||||
if (!removeApbChangeCallback( i2c, i2cApbChangeCallback)) {
|
||||
log_e("unable to release apbCallback");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1431,8 +1479,7 @@ i2c_err_t i2cDetachSDA(i2c_t * i2c, int8_t sda)
|
||||
* PUBLIC API
|
||||
* */
|
||||
// 24Nov17 only supports Master Mode
|
||||
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) //before this is called, pins should be detached, else glitch
|
||||
{
|
||||
i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) {
|
||||
log_v("num=%d sda=%d scl=%d freq=%d",i2c_num, sda, scl, frequency);
|
||||
if(i2c_num > 1) {
|
||||
return NULL;
|
||||
@ -1440,6 +1487,7 @@ i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) //b
|
||||
|
||||
i2c_t * i2c = &_i2c_bus_array[i2c_num];
|
||||
|
||||
// pins should be detached, else glitch
|
||||
if(i2c->sda >= 0){
|
||||
i2cDetachSDA(i2c, i2c->sda);
|
||||
}
|
||||
@ -1451,7 +1499,7 @@ i2c_t * i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency) //b
|
||||
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(i2c->lock == NULL) {
|
||||
i2c->lock = xSemaphoreCreateMutex();
|
||||
i2c->lock = xSemaphoreCreateRecursiveMutex();
|
||||
if(i2c->lock == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1598,27 +1646,50 @@ i2c_err_t i2cRead(i2c_t * i2c, uint16_t address, uint8_t* buff, uint16_t size, b
|
||||
return last_error;
|
||||
}
|
||||
|
||||
#define MIN_I2C_CLKS 100 // minimum ratio between cpu and i2c Bus clocks
|
||||
#define INTERRUPT_CYCLE_OVERHEAD 16000 // number of cpu clocks necessary to respond to interrupt
|
||||
i2c_err_t i2cSetFrequency(i2c_t * i2c, uint32_t clk_speed)
|
||||
{
|
||||
if(i2c == NULL) {
|
||||
return I2C_ERROR_DEV;
|
||||
}
|
||||
I2C_FIFO_CONF_t f;
|
||||
uint32_t apb = getApbFrequency();
|
||||
uint32_t period = (apb/clk_speed) / 2;
|
||||
|
||||
if((apb/8192 > clk_speed)||(apb/MIN_I2C_CLKS < clk_speed)){ //out of bounds
|
||||
log_d("i2c freq(%d) out of bounds.vs APB Clock(%d), min=%d, max=%d",clk_speed,apb,(apb/8192),(apb/MIN_I2C_CLKS));
|
||||
}
|
||||
if(period < (MIN_I2C_CLKS/2) ){
|
||||
period = (MIN_I2C_CLKS/2);
|
||||
clk_speed = apb/(period*2);
|
||||
log_d("APB Freq too slow, Reducing i2c Freq to %d Hz",clk_speed);
|
||||
} else if ( period> 4095) {
|
||||
period = 4095;
|
||||
clk_speed = apb/(period*2);
|
||||
log_d("APB Freq too fast, Increasing i2c Freq to %d Hz",clk_speed);
|
||||
}
|
||||
log_v("freq=%dHz",clk_speed);
|
||||
|
||||
uint32_t period = (APB_CLK_FREQ/clk_speed) / 2;
|
||||
uint32_t halfPeriod = period/2;
|
||||
uint32_t quarterPeriod = period/4;
|
||||
|
||||
I2C_MUTEX_LOCK();
|
||||
|
||||
// Adjust Fifo thresholds based on frequency
|
||||
I2C_FIFO_CONF_t f;
|
||||
|
||||
f.val = i2c->dev->fifo_conf.val;
|
||||
uint32_t a = (clk_speed / 50000L )+1;
|
||||
if (a > 24) a=24;
|
||||
f.rx_fifo_full_thrhd = 32 - a;
|
||||
f.tx_fifo_empty_thrhd = a;
|
||||
/* Adjust Fifo thresholds based on differential between cpu frequency and bus clock.
|
||||
The fifo_delta is calculated such that at least INTERRUPT_CYCLE_OVERHEAD cpu clocks are
|
||||
available when a Fifo interrupt is triggered. This allows enough room in the Fifo so that
|
||||
interrupt latency does not cause a Fifo overflow/underflow event.
|
||||
*/
|
||||
log_v("cpu Freq=%dMhz, i2c Freq=%dHz",getCpuFrequencyMhz(),clk_speed);
|
||||
uint32_t fifo_delta = (INTERRUPT_CYCLE_OVERHEAD/((getCpuFrequencyMhz()*1000000 / clk_speed)*10))+1;
|
||||
if (fifo_delta > 24) fifo_delta=24;
|
||||
f.rx_fifo_full_thrhd = 32 - fifo_delta;
|
||||
f.tx_fifo_empty_thrhd = fifo_delta;
|
||||
i2c->dev->fifo_conf.val = f.val; // set thresholds
|
||||
log_v("Fifo threshold=%d",a);
|
||||
log_v("Fifo delta=%d",fifo_delta);
|
||||
|
||||
//the clock num during SCL is low level
|
||||
i2c->dev->scl_low_period.period = period;
|
||||
@ -1651,7 +1722,7 @@ uint32_t i2cGetFrequency(i2c_t * i2c)
|
||||
uint32_t result = 0;
|
||||
uint32_t old_count = (i2c->dev->scl_low_period.period+i2c->dev->scl_high_period.period);
|
||||
if(old_count>0) {
|
||||
result = APB_CLK_FREQ / old_count;
|
||||
result = getApbFrequency() / old_count;
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
@ -1674,6 +1745,8 @@ uint32_t i2cGetStatus(i2c_t * i2c){
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
|
||||
/* todo
|
||||
22JUL18
|
||||
need to add multi-thread capability, use dq.queueEvent as the group marker. When multiple threads
|
||||
|
@ -53,6 +53,33 @@ xSemaphoreHandle _ledc_sys_lock;
|
||||
#define LEDC_CHAN(g,c) LEDC.channel_group[(g)].channel[(c)]
|
||||
#define LEDC_TIMER(g,t) LEDC.timer_group[(g)].timer[(t)]
|
||||
|
||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||
if(ev_type == APB_AFTER_CHANGE && old_apb != new_apb){
|
||||
uint32_t iarg = (uint32_t)arg;
|
||||
uint8_t chan = iarg;
|
||||
uint8_t group=(chan/8), timer=((chan/2)%4);
|
||||
old_apb /= 1000000;
|
||||
new_apb /= 1000000;
|
||||
if(LEDC_TIMER(group, timer).conf.tick_sel){
|
||||
LEDC_MUTEX_LOCK();
|
||||
uint32_t old_div = LEDC_TIMER(group, timer).conf.clock_divider;
|
||||
uint32_t div_num = (new_apb * old_div) / old_apb;
|
||||
if(div_num > LEDC_DIV_NUM_HSTIMER0_V){
|
||||
new_apb = REF_CLK_FREQ / 1000000;
|
||||
div_num = (new_apb * old_div) / old_apb;
|
||||
if(div_num > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||
div_num = LEDC_DIV_NUM_HSTIMER0_V;//lowest clock possible
|
||||
}
|
||||
LEDC_TIMER(group, timer).conf.tick_sel = 0;
|
||||
} else if(div_num < 256) {
|
||||
div_num = 256;//highest clock possible
|
||||
}
|
||||
LEDC_TIMER(group, timer).conf.clock_divider = div_num;
|
||||
LEDC_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//uint32_t frequency = (80MHz or 1MHz)/((div_num / 256.0)*(1 << bit_num));
|
||||
static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, bool apb_clk)
|
||||
{
|
||||
@ -78,13 +105,15 @@ static void _ledcSetupTimer(uint8_t chan, uint32_t div_num, uint8_t bit_num, boo
|
||||
LEDC_TIMER(group, timer).conf.rst = 1;//This bit is used to reset timer the counter will be 0 after reset.
|
||||
LEDC_TIMER(group, timer).conf.rst = 0;
|
||||
LEDC_MUTEX_UNLOCK();
|
||||
uint32_t iarg = chan;
|
||||
addApbChangeCallback((void*)iarg, _on_apb_change);
|
||||
}
|
||||
|
||||
//max div_num 0x3FFFF (262143)
|
||||
//max bit_num 0x1F (31)
|
||||
static double _ledcSetupTimerFreq(uint8_t chan, double freq, uint8_t bit_num)
|
||||
{
|
||||
uint64_t clk_freq = APB_CLK_FREQ;
|
||||
uint64_t clk_freq = getApbFrequency();
|
||||
clk_freq <<= 8;//div_num is 8 bit decimal
|
||||
uint32_t div_num = (clk_freq >> bit_num) / freq;
|
||||
bool apb_clk = true;
|
||||
@ -117,7 +146,7 @@ static double _ledcTimerRead(uint8_t chan)
|
||||
LEDC_MUTEX_UNLOCK();
|
||||
uint64_t clk_freq = 1000000;
|
||||
if(apb_clk) {
|
||||
clk_freq *= 80;
|
||||
clk_freq = getApbFrequency();
|
||||
}
|
||||
clk_freq <<= 8;//div_num is 8 bit decimal
|
||||
return (clk_freq >> bit_num) / (double)div_num;
|
||||
|
@ -21,8 +21,15 @@
|
||||
#include "esp_partition.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
#include "esp_bt.h"
|
||||
#endif //CONFIG_BT_ENABLED
|
||||
#include <sys/time.h>
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "rom/rtc.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp32-hal.h"
|
||||
|
||||
//Undocumented!!! Get chip temperature in Farenheit
|
||||
@ -39,9 +46,64 @@ void yield()
|
||||
vPortYield();
|
||||
}
|
||||
|
||||
#if CONFIG_AUTOSTART_ARDUINO
|
||||
|
||||
extern TaskHandle_t loopTaskHandle;
|
||||
extern bool loopTaskWDTEnabled;
|
||||
|
||||
void enableLoopWDT(){
|
||||
if(loopTaskHandle != NULL){
|
||||
if(esp_task_wdt_add(loopTaskHandle) != ESP_OK){
|
||||
log_e("Failed to add loop task to WDT");
|
||||
} else {
|
||||
loopTaskWDTEnabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disableLoopWDT(){
|
||||
if(loopTaskHandle != NULL && loopTaskWDTEnabled){
|
||||
loopTaskWDTEnabled = false;
|
||||
if(esp_task_wdt_delete(loopTaskHandle) != ESP_OK){
|
||||
log_e("Failed to remove loop task from WDT");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void enableCore0WDT(){
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if(idle_0 == NULL || esp_task_wdt_add(idle_0) != ESP_OK){
|
||||
log_e("Failed to add Core 0 IDLE task to WDT");
|
||||
}
|
||||
}
|
||||
|
||||
void disableCore0WDT(){
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if(idle_0 == NULL || esp_task_wdt_delete(idle_0) != ESP_OK){
|
||||
log_e("Failed to remove Core 0 IDLE task from WDT");
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
void enableCore1WDT(){
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if(idle_1 == NULL || esp_task_wdt_add(idle_1) != ESP_OK){
|
||||
log_e("Failed to add Core 1 IDLE task to WDT");
|
||||
}
|
||||
}
|
||||
|
||||
void disableCore1WDT(){
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if(idle_1 == NULL || esp_task_wdt_delete(idle_1) != ESP_OK){
|
||||
log_e("Failed to remove Core 1 IDLE task from WDT");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned long IRAM_ATTR micros()
|
||||
{
|
||||
return (unsigned long) esp_timer_get_time();
|
||||
return (unsigned long) (esp_timer_get_time());
|
||||
}
|
||||
|
||||
unsigned long IRAM_ATTR millis()
|
||||
@ -84,6 +146,11 @@ bool btInUse(){ return false; }
|
||||
|
||||
void initArduino()
|
||||
{
|
||||
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
|
||||
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
|
||||
#ifdef F_CPU
|
||||
setCpuFrequencyMhz(F_CPU/1000000);
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_SUPPORT
|
||||
psramInit();
|
||||
#endif
|
||||
|
@ -31,6 +31,26 @@
|
||||
xSemaphoreHandle _sd_sys_lock;
|
||||
#endif
|
||||
|
||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||
if(old_apb == new_apb){
|
||||
return;
|
||||
}
|
||||
uint32_t iarg = (uint32_t)arg;
|
||||
uint8_t channel = iarg;
|
||||
if(ev_type == APB_BEFORE_CHANGE){
|
||||
SIGMADELTA.cg.clk_en = 0;
|
||||
} else {
|
||||
old_apb /= 1000000;
|
||||
new_apb /= 1000000;
|
||||
SD_MUTEX_LOCK();
|
||||
uint32_t old_prescale = SIGMADELTA.channel[channel].prescale + 1;
|
||||
SIGMADELTA.channel[channel].prescale = ((new_apb * old_prescale) / old_apb) - 1;
|
||||
SIGMADELTA.cg.clk_en = 0;
|
||||
SIGMADELTA.cg.clk_en = 1;
|
||||
SD_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-312500
|
||||
{
|
||||
if(channel > 7) {
|
||||
@ -43,7 +63,8 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31
|
||||
_sd_sys_lock = xSemaphoreCreateMutex();
|
||||
}
|
||||
#endif
|
||||
uint32_t prescale = (10000000/(freq*32)) - 1;
|
||||
uint32_t apb_freq = getApbFrequency();
|
||||
uint32_t prescale = (apb_freq/(freq*256)) - 1;
|
||||
if(prescale > 0xFF) {
|
||||
prescale = 0xFF;
|
||||
}
|
||||
@ -52,7 +73,9 @@ uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq) //chan 0-7 freq 1220-31
|
||||
SIGMADELTA.cg.clk_en = 0;
|
||||
SIGMADELTA.cg.clk_en = 1;
|
||||
SD_MUTEX_UNLOCK();
|
||||
return 10000000/((prescale + 1) * 32);
|
||||
uint32_t iarg = channel;
|
||||
addApbChangeCallback((void*)iarg, _on_apb_change);
|
||||
return apb_freq/((prescale + 1) * 256);
|
||||
}
|
||||
|
||||
void sigmaDeltaWrite(uint8_t channel, uint8_t duty) //chan 0-7 duty 8 bit
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
|
||||
#define SPI_CLK_IDX(p) ((p==0)?SPICLK_OUT_IDX:((p==1)?SPICLK_OUT_IDX:((p==2)?HSPICLK_OUT_IDX:((p==3)?VSPICLK_OUT_IDX:0))))
|
||||
#define SPI_MISO_IDX(p) ((p==0)?SPIQ_OUT_IDX:((p==1)?SPIQ_OUT_IDX:((p==2)?HSPIQ_OUT_IDX:((p==3)?VSPIQ_OUT_IDX:0))))
|
||||
@ -371,6 +372,18 @@ void spiSetBitOrder(spi_t * spi, uint8_t bitOrder)
|
||||
SPI_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb)
|
||||
{
|
||||
spi_t * spi = (spi_t *)arg;
|
||||
if(ev_type == APB_BEFORE_CHANGE){
|
||||
SPI_MUTEX_LOCK();
|
||||
while(spi->dev->cmd.usr);
|
||||
} else {
|
||||
spi->dev->clock.val = spiFrequencyToClockDiv(old_apb / ((spi->dev->clock.clkdiv_pre + 1) * (spi->dev->clock.clkcnt_n + 1)));
|
||||
SPI_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
|
||||
void spiStopBus(spi_t * spi)
|
||||
{
|
||||
if(!spi) {
|
||||
@ -387,6 +400,7 @@ void spiStopBus(spi_t * spi)
|
||||
spi->dev->ctrl2.val = 0;
|
||||
spi->dev->clock.val = 0;
|
||||
SPI_MUTEX_UNLOCK();
|
||||
removeApbChangeCallback(spi, _on_apb_change);
|
||||
}
|
||||
|
||||
spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_t bitOrder)
|
||||
@ -433,6 +447,7 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
|
||||
}
|
||||
SPI_MUTEX_UNLOCK();
|
||||
|
||||
addApbChangeCallback(spi, _on_apb_change);
|
||||
return spi;
|
||||
}
|
||||
|
||||
@ -750,7 +765,7 @@ void spiEndTransaction(spi_t * spi)
|
||||
SPI_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
void spiWriteByteNL(spi_t * spi, uint8_t data)
|
||||
void IRAM_ATTR spiWriteByteNL(spi_t * spi, uint8_t data)
|
||||
{
|
||||
if(!spi) {
|
||||
return;
|
||||
@ -776,7 +791,7 @@ uint8_t spiTransferByteNL(spi_t * spi, uint8_t data)
|
||||
return data;
|
||||
}
|
||||
|
||||
void spiWriteShortNL(spi_t * spi, uint16_t data)
|
||||
void IRAM_ATTR spiWriteShortNL(spi_t * spi, uint16_t data)
|
||||
{
|
||||
if(!spi) {
|
||||
return;
|
||||
@ -811,7 +826,7 @@ uint16_t spiTransferShortNL(spi_t * spi, uint16_t data)
|
||||
return data;
|
||||
}
|
||||
|
||||
void spiWriteLongNL(spi_t * spi, uint32_t data)
|
||||
void IRAM_ATTR spiWriteLongNL(spi_t * spi, uint32_t data)
|
||||
{
|
||||
if(!spi) {
|
||||
return;
|
||||
@ -959,7 +974,7 @@ void spiTransferBitsNL(spi_t * spi, uint32_t data, uint32_t * out, uint8_t bits)
|
||||
}
|
||||
}
|
||||
|
||||
void spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){
|
||||
void IRAM_ATTR spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){
|
||||
size_t longs = len >> 2;
|
||||
if(len & 3){
|
||||
longs++;
|
||||
@ -1007,35 +1022,37 @@ void spiWritePixelsNL(spi_t * spi, const void * data_in, size_t len){
|
||||
* */
|
||||
|
||||
typedef union {
|
||||
uint32_t regValue;
|
||||
uint32_t value;
|
||||
struct {
|
||||
unsigned regL :6;
|
||||
unsigned regH :6;
|
||||
unsigned regN :6;
|
||||
unsigned regPre :13;
|
||||
unsigned regEQU :1;
|
||||
uint32_t clkcnt_l: 6; /*it must be equal to spi_clkcnt_N.*/
|
||||
uint32_t clkcnt_h: 6; /*it must be floor((spi_clkcnt_N+1)/2-1).*/
|
||||
uint32_t clkcnt_n: 6; /*it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_N+1)*/
|
||||
uint32_t clkdiv_pre: 13; /*it is pre-divider of spi_clk.*/
|
||||
uint32_t clk_equ_sysclk: 1; /*1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/
|
||||
};
|
||||
} spiClk_t;
|
||||
|
||||
#define ClkRegToFreq(reg) (CPU_CLK_FREQ / (((reg)->regPre + 1) * ((reg)->regN + 1)))
|
||||
#define ClkRegToFreq(reg) (apb_freq / (((reg)->clkdiv_pre + 1) * ((reg)->clkcnt_n + 1)))
|
||||
|
||||
uint32_t spiClockDivToFrequency(uint32_t clockDiv)
|
||||
{
|
||||
uint32_t apb_freq = getApbFrequency();
|
||||
spiClk_t reg = { clockDiv };
|
||||
return ClkRegToFreq(®);
|
||||
}
|
||||
|
||||
uint32_t spiFrequencyToClockDiv(uint32_t freq)
|
||||
{
|
||||
uint32_t apb_freq = getApbFrequency();
|
||||
|
||||
if(freq >= CPU_CLK_FREQ) {
|
||||
if(freq >= apb_freq) {
|
||||
return SPI_CLK_EQU_SYSCLK;
|
||||
}
|
||||
|
||||
const spiClk_t minFreqReg = { 0x7FFFF000 };
|
||||
uint32_t minFreq = ClkRegToFreq((spiClk_t*) &minFreqReg);
|
||||
if(freq < minFreq) {
|
||||
return minFreqReg.regValue;
|
||||
return minFreqReg.value;
|
||||
}
|
||||
|
||||
uint8_t calN = 1;
|
||||
@ -1048,18 +1065,18 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
|
||||
int32_t calPre;
|
||||
int8_t calPreVari = -2;
|
||||
|
||||
reg.regN = calN;
|
||||
reg.clkcnt_n = calN;
|
||||
|
||||
while(calPreVari++ <= 1) {
|
||||
calPre = (((CPU_CLK_FREQ / (reg.regN + 1)) / freq) - 1) + calPreVari;
|
||||
calPre = (((apb_freq / (reg.clkcnt_n + 1)) / freq) - 1) + calPreVari;
|
||||
if(calPre > 0x1FFF) {
|
||||
reg.regPre = 0x1FFF;
|
||||
reg.clkdiv_pre = 0x1FFF;
|
||||
} else if(calPre <= 0) {
|
||||
reg.regPre = 0;
|
||||
reg.clkdiv_pre = 0;
|
||||
} else {
|
||||
reg.regPre = calPre;
|
||||
reg.clkdiv_pre = calPre;
|
||||
}
|
||||
reg.regL = ((reg.regN + 1) / 2);
|
||||
reg.clkcnt_l = ((reg.clkcnt_n + 1) / 2);
|
||||
calFreq = ClkRegToFreq(®);
|
||||
if(calFreq == (int32_t) freq) {
|
||||
memcpy(&bestReg, ®, sizeof(bestReg));
|
||||
@ -1076,6 +1093,6 @@ uint32_t spiFrequencyToClockDiv(uint32_t freq)
|
||||
}
|
||||
calN++;
|
||||
}
|
||||
return bestReg.regValue;
|
||||
return bestReg.value;
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,9 @@
|
||||
|
||||
static void setTimeZone(long offset, int daylight)
|
||||
{
|
||||
char cst[16] = {0};
|
||||
char cdt[16] = "DST";
|
||||
char tz[32] = {0};
|
||||
char cst[17] = {0};
|
||||
char cdt[17] = "DST";
|
||||
char tz[33] = {0};
|
||||
|
||||
if(offset % 3600){
|
||||
sprintf(cst, "UTC%ld:%02u:%02u", offset / 3600, abs((offset % 3600) / 60), abs(offset % 60));
|
||||
|
@ -84,7 +84,7 @@ void IRAM_ATTR __timerISR(void * arg){
|
||||
i = 4;
|
||||
//call callbacks
|
||||
while(i--){
|
||||
if(__timerInterruptHandlers[i] && status & (1 << i)){
|
||||
if(__timerInterruptHandlers[i] && (status & (1 << i))){
|
||||
__timerInterruptHandlers[i]();
|
||||
}
|
||||
}
|
||||
@ -184,6 +184,18 @@ bool timerAlarmEnabled(hw_timer_t *timer){
|
||||
return timer->dev->config.alarm_en;
|
||||
}
|
||||
|
||||
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
|
||||
hw_timer_t * timer = (hw_timer_t *)arg;
|
||||
if(ev_type == APB_BEFORE_CHANGE){
|
||||
timer->dev->config.enable = 0;
|
||||
} else {
|
||||
old_apb /= 1000000;
|
||||
new_apb /= 1000000;
|
||||
timer->dev->config.divider = (new_apb * timer->dev->config.divider) / old_apb;
|
||||
timer->dev->config.enable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
||||
if(num > 3){
|
||||
return NULL;
|
||||
@ -205,12 +217,14 @@ hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
|
||||
timerAttachInterrupt(timer, NULL, false);
|
||||
timerWrite(timer, 0);
|
||||
timer->dev->config.enable = 1;
|
||||
addApbChangeCallback(timer, _on_apb_change);
|
||||
return timer;
|
||||
}
|
||||
|
||||
void timerEnd(hw_timer_t *timer){
|
||||
timer->dev->config.enable = 0;
|
||||
timerAttachInterrupt(timer, NULL, false);
|
||||
removeApbChangeCallback(timer, _on_apb_change);
|
||||
}
|
||||
|
||||
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
|
||||
@ -271,23 +285,23 @@ void timerDetachInterrupt(hw_timer_t *timer){
|
||||
uint64_t timerReadMicros(hw_timer_t *timer){
|
||||
uint64_t timer_val = timerRead(timer);
|
||||
uint16_t div = timerGetDivider(timer);
|
||||
return timer_val * div / 80;
|
||||
return timer_val * div / (getApbFrequency() / 1000000);
|
||||
}
|
||||
|
||||
double timerReadSeconds(hw_timer_t *timer){
|
||||
uint64_t timer_val = timerRead(timer);
|
||||
uint16_t div = timerGetDivider(timer);
|
||||
return (double)timer_val * div / 80000000;
|
||||
return (double)timer_val * div / getApbFrequency();
|
||||
}
|
||||
|
||||
uint64_t timerAlarmReadMicros(hw_timer_t *timer){
|
||||
uint64_t timer_val = timerAlarmRead(timer);
|
||||
uint16_t div = timerGetDivider(timer);
|
||||
return timer_val * div / 80;
|
||||
return timer_val * div / (getApbFrequency() / 1000000);
|
||||
}
|
||||
|
||||
double timerAlarmReadSeconds(hw_timer_t *timer){
|
||||
uint64_t timer_val = timerAlarmRead(timer);
|
||||
uint16_t div = timerGetDivider(timer);
|
||||
return (double)timer_val * div / 80000000;
|
||||
return (double)timer_val * div / getApbFrequency();
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#define UART_REG_BASE(u) ((u==0)?DR_REG_UART_BASE:( (u==1)?DR_REG_UART1_BASE:( (u==2)?DR_REG_UART2_BASE:0)))
|
||||
@ -66,6 +67,8 @@ static uart_t _uart_bus_array[3] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb);
|
||||
|
||||
static void IRAM_ATTR _uart_isr(void *arg)
|
||||
{
|
||||
uint8_t i, c;
|
||||
@ -215,6 +218,7 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
|
||||
uartAttachTx(uart, txPin, inverted);
|
||||
}
|
||||
|
||||
addApbChangeCallback(uart, uart_on_apb_change);
|
||||
return uart;
|
||||
}
|
||||
|
||||
@ -223,11 +227,10 @@ void uartEnd(uart_t* uart)
|
||||
if(uart == NULL) {
|
||||
return;
|
||||
}
|
||||
removeApbChangeCallback(uart, uart_on_apb_change);
|
||||
|
||||
UART_MUTEX_LOCK();
|
||||
if(uart->queue != NULL) {
|
||||
uint8_t c;
|
||||
while(xQueueReceive(uart->queue, &c, 0));
|
||||
vQueueDelete(uart->queue);
|
||||
uart->queue = NULL;
|
||||
}
|
||||
@ -247,8 +250,6 @@ size_t uartResizeRxBuffer(uart_t * uart, size_t new_size) {
|
||||
|
||||
UART_MUTEX_LOCK();
|
||||
if(uart->queue != NULL) {
|
||||
uint8_t c;
|
||||
while(xQueueReceive(uart->queue, &c, 0));
|
||||
vQueueDelete(uart->queue);
|
||||
uart->queue = xQueueCreate(new_size, sizeof(uint8_t));
|
||||
if(uart->queue == NULL) {
|
||||
@ -318,11 +319,10 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
|
||||
}
|
||||
UART_MUTEX_LOCK();
|
||||
while(len) {
|
||||
while(len && uart->dev->status.txfifo_cnt < 0x7F) {
|
||||
while(uart->dev->status.txfifo_cnt == 0x7F);
|
||||
uart->dev->fifo.rw_byte = *data++;
|
||||
len--;
|
||||
}
|
||||
}
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
@ -352,19 +352,55 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
|
||||
return;
|
||||
}
|
||||
UART_MUTEX_LOCK();
|
||||
uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate);
|
||||
uint32_t clk_div = ((getApbFrequency()<<4)/baud_rate);
|
||||
uart->dev->clk_div.div_int = clk_div>>4 ;
|
||||
uart->dev->clk_div.div_frag = clk_div & 0xf;
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
|
||||
static void uart_on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb)
|
||||
{
|
||||
uart_t* uart = (uart_t*)arg;
|
||||
if(ev_type == APB_BEFORE_CHANGE){
|
||||
UART_MUTEX_LOCK();
|
||||
//disabple interrupt
|
||||
uart->dev->int_ena.val = 0;
|
||||
uart->dev->int_clr.val = 0xffffffff;
|
||||
// read RX fifo
|
||||
uint8_t c;
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
while(uart->dev->status.rxfifo_cnt != 0 || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) {
|
||||
c = uart->dev->fifo.rw_byte;
|
||||
if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) {
|
||||
xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken);
|
||||
}
|
||||
}
|
||||
// wait TX empty
|
||||
while(uart->dev->status.txfifo_cnt || uart->dev->status.st_utx_out);
|
||||
} else {
|
||||
//todo:
|
||||
// set baudrate
|
||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||
uint32_t baud_rate = ((old_apb<<4)/clk_div);
|
||||
clk_div = ((new_apb<<4)/baud_rate);
|
||||
uart->dev->clk_div.div_int = clk_div>>4 ;
|
||||
uart->dev->clk_div.div_frag = clk_div & 0xf;
|
||||
//enable interrupts
|
||||
uart->dev->int_ena.rxfifo_full = 1;
|
||||
uart->dev->int_ena.frm_err = 1;
|
||||
uart->dev->int_ena.rxfifo_tout = 1;
|
||||
uart->dev->int_clr.val = 0xffffffff;
|
||||
UART_MUTEX_UNLOCK();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t uartGetBaudRate(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t clk_div = (uart->dev->clk_div.div_int << 4) | (uart->dev->clk_div.div_frag & 0x0F);
|
||||
return ((UART_CLK_FREQ<<4)/clk_div);
|
||||
return ((getApbFrequency()<<4)/clk_div);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR uart0_write_char(char c)
|
||||
@ -385,17 +421,8 @@ static void IRAM_ATTR uart2_write_char(char c)
|
||||
ESP_REG(DR_REG_UART2_BASE) = c;
|
||||
}
|
||||
|
||||
void uartSetDebug(uart_t* uart)
|
||||
void uart_install_putc()
|
||||
{
|
||||
if(uart == NULL || uart->num > 2) {
|
||||
s_uart_debug_nr = -1;
|
||||
ets_install_putc1(NULL);
|
||||
return;
|
||||
}
|
||||
if(s_uart_debug_nr == uart->num) {
|
||||
return;
|
||||
}
|
||||
s_uart_debug_nr = uart->num;
|
||||
switch(s_uart_debug_nr) {
|
||||
case 0:
|
||||
ets_install_putc1((void (*)(char)) &uart0_write_char);
|
||||
@ -412,6 +439,20 @@ void uartSetDebug(uart_t* uart)
|
||||
}
|
||||
}
|
||||
|
||||
void uartSetDebug(uart_t* uart)
|
||||
{
|
||||
if(uart == NULL || uart->num > 2) {
|
||||
s_uart_debug_nr = -1;
|
||||
//ets_install_putc1(NULL);
|
||||
//return;
|
||||
} else
|
||||
if(s_uart_debug_nr == uart->num) {
|
||||
return;
|
||||
} else
|
||||
s_uart_debug_nr = uart->num;
|
||||
uart_install_putc();
|
||||
}
|
||||
|
||||
int uartGetDebug()
|
||||
{
|
||||
return s_uart_debug_nr;
|
||||
@ -440,7 +481,7 @@ int log_printf(const char *format, ...)
|
||||
vsnprintf(temp, len+1, format, arg);
|
||||
#if !CONFIG_DISABLE_HAL_LOCKS
|
||||
if(_uart_bus_array[s_uart_debug_nr].lock){
|
||||
while (xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY) != pdPASS);
|
||||
xSemaphoreTake(_uart_bus_array[s_uart_debug_nr].lock, portMAX_DELAY);
|
||||
ets_printf("%s", temp);
|
||||
xSemaphoreGive(_uart_bus_array[s_uart_debug_nr].lock);
|
||||
} else {
|
||||
@ -450,7 +491,7 @@ int log_printf(const char *format, ...)
|
||||
ets_printf("%s", temp);
|
||||
#endif
|
||||
va_end(arg);
|
||||
if(len > 64){
|
||||
if(len >= sizeof(loc_buf)){
|
||||
free(temp);
|
||||
}
|
||||
return len;
|
||||
@ -499,7 +540,7 @@ uartDetectBaudrate(uart_t *uart)
|
||||
uart->dev->auto_baud.en = 0;
|
||||
uartStateDetectingBaudrate = false; // Initialize for the next round
|
||||
|
||||
unsigned long baudrate = UART_CLK_FREQ / divisor;
|
||||
unsigned long baudrate = getApbFrequency() / divisor;
|
||||
|
||||
static const unsigned long default_rates[] = {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 74880, 115200, 230400, 256000, 460800, 921600, 1843200, 3686400};
|
||||
|
||||
|
@ -62,6 +62,7 @@ void yield(void);
|
||||
#include "esp32-hal-timer.h"
|
||||
#include "esp32-hal-bt.h"
|
||||
#include "esp32-hal-psram.h"
|
||||
#include "esp32-hal-cpu.h"
|
||||
|
||||
#ifndef BOARD_HAS_PSRAM
|
||||
#ifdef CONFIG_SPIRAM_SUPPORT
|
||||
@ -72,6 +73,21 @@ void yield(void);
|
||||
//returns chip temperature in Celsius
|
||||
float temperatureRead();
|
||||
|
||||
#if CONFIG_AUTOSTART_ARDUINO
|
||||
//enable/disable WDT for Arduino's setup and loop functions
|
||||
void enableLoopWDT();
|
||||
void disableLoopWDT();
|
||||
#endif
|
||||
|
||||
//enable/disable WDT for the IDLE task on Core 0 (SYSTEM)
|
||||
void enableCore0WDT();
|
||||
void disableCore0WDT();
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
//enable/disable WDT for the IDLE task on Core 1 (Arduino)
|
||||
void enableCore1WDT();
|
||||
void disableCore1WDT();
|
||||
#endif
|
||||
|
||||
unsigned long micros();
|
||||
unsigned long millis();
|
||||
void delay(uint32_t);
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
TaskHandle_t loopTaskHandle = NULL;
|
||||
|
||||
#if CONFIG_AUTOSTART_ARDUINO
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
@ -10,18 +13,24 @@
|
||||
#define ARDUINO_RUNNING_CORE 1
|
||||
#endif
|
||||
|
||||
bool loopTaskWDTEnabled;
|
||||
|
||||
void loopTask(void *pvParameters)
|
||||
{
|
||||
setup();
|
||||
for(;;) {
|
||||
if(loopTaskWDTEnabled){
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
loop();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void app_main()
|
||||
{
|
||||
loopTaskWDTEnabled = false;
|
||||
initArduino();
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, NULL, ARDUINO_RUNNING_CORE);
|
||||
xTaskCreatePinnedToCore(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, ARDUINO_RUNNING_CORE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -561,7 +561,6 @@ static esp_err_t joinMulticastGroup(const ip_addr_t *addr, bool join, tcpip_adap
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
netif = (struct netif *)nif;
|
||||
}
|
||||
|
||||
if (addr->type == IPADDR_TYPE_V4) {
|
||||
if(join){
|
||||
@ -584,6 +583,29 @@ static esp_err_t joinMulticastGroup(const ip_addr_t *addr, bool join, tcpip_adap
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (addr->type == IPADDR_TYPE_V4) {
|
||||
if(join){
|
||||
if (igmp_joingroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)&(addr->u_addr.ip4))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
if (igmp_leavegroup((const ip4_addr *)IP4_ADDR_ANY, (const ip4_addr *)&(addr->u_addr.ip4))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(join){
|
||||
if (mld6_joingroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
} else {
|
||||
if (mld6_leavegroup((const ip6_addr *)IP6_ADDR_ANY, &(addr->u_addr.ip6))) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
Submodule libraries/BLE updated: 7951347ed6...b232e7f5f0
@ -0,0 +1,148 @@
|
||||
#include "esp_camera.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
//
|
||||
// WARNING!!! Make sure that you have either selected ESP32 Wrover Module,
|
||||
// or another board which has PSRAM enabled
|
||||
//
|
||||
|
||||
// Select camera model
|
||||
#define CAMERA_MODEL_WROVER_KIT
|
||||
//#define CAMERA_MODEL_M5STACK_PSRAM
|
||||
//#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
const char* ssid = "*********";
|
||||
const char* password = "*********";
|
||||
|
||||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM 32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 0
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 21
|
||||
#define Y4_GPIO_NUM 19
|
||||
#define Y3_GPIO_NUM 18
|
||||
#define Y2_GPIO_NUM 5
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
||||
void startCameraServer();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.setDebugOutput(true);
|
||||
Serial.println();
|
||||
|
||||
camera_config_t config;
|
||||
config.ledc_channel = LEDC_CHANNEL_0;
|
||||
config.ledc_timer = LEDC_TIMER_0;
|
||||
config.pin_d0 = Y2_GPIO_NUM;
|
||||
config.pin_d1 = Y3_GPIO_NUM;
|
||||
config.pin_d2 = Y4_GPIO_NUM;
|
||||
config.pin_d3 = Y5_GPIO_NUM;
|
||||
config.pin_d4 = Y6_GPIO_NUM;
|
||||
config.pin_d5 = Y7_GPIO_NUM;
|
||||
config.pin_d6 = Y8_GPIO_NUM;
|
||||
config.pin_d7 = Y9_GPIO_NUM;
|
||||
config.pin_xclk = XCLK_GPIO_NUM;
|
||||
config.pin_pclk = PCLK_GPIO_NUM;
|
||||
config.pin_vsync = VSYNC_GPIO_NUM;
|
||||
config.pin_href = HREF_GPIO_NUM;
|
||||
config.pin_sscb_sda = SIOD_GPIO_NUM;
|
||||
config.pin_sscb_scl = SIOC_GPIO_NUM;
|
||||
config.pin_pwdn = PWDN_GPIO_NUM;
|
||||
config.pin_reset = RESET_GPIO_NUM;
|
||||
config.xclk_freq_hz = 20000000;
|
||||
config.pixel_format = PIXFORMAT_JPEG;
|
||||
//init with high specs to pre-allocate larger buffers
|
||||
if(psramFound()){
|
||||
config.frame_size = FRAMESIZE_UXGA;
|
||||
config.jpeg_quality = 10;
|
||||
config.fb_count = 2;
|
||||
} else {
|
||||
config.frame_size = FRAMESIZE_SVGA;
|
||||
config.jpeg_quality = 12;
|
||||
config.fb_count = 1;
|
||||
}
|
||||
|
||||
// camera init
|
||||
esp_err_t err = esp_camera_init(&config);
|
||||
if (err != ESP_OK) {
|
||||
Serial.printf("Camera init failed with error 0x%x", err);
|
||||
return;
|
||||
}
|
||||
|
||||
//drop down frame size for higher initial frame rate
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
s->set_framesize(s, FRAMESIZE_QVGA);
|
||||
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
|
||||
startCameraServer();
|
||||
|
||||
Serial.print("Camera Ready! Use 'http://");
|
||||
Serial.print(WiFi.localIP());
|
||||
Serial.println("' to connect");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
delay(10000);
|
||||
}
|
650
libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp
Normal file
650
libraries/ESP32/examples/Camera/CameraWebServer/app_httpd.cpp
Normal file
@ -0,0 +1,650 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_http_server.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_camera.h"
|
||||
#include "img_converters.h"
|
||||
#include "camera_index.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "fb_gfx.h"
|
||||
#include "fd_forward.h"
|
||||
#include "dl_lib.h"
|
||||
#include "fr_forward.h"
|
||||
|
||||
#define ENROLL_CONFIRM_TIMES 5
|
||||
#define FACE_ID_SAVE_NUMBER 7
|
||||
|
||||
#define FACE_COLOR_WHITE 0x00FFFFFF
|
||||
#define FACE_COLOR_BLACK 0x00000000
|
||||
#define FACE_COLOR_RED 0x000000FF
|
||||
#define FACE_COLOR_GREEN 0x0000FF00
|
||||
#define FACE_COLOR_BLUE 0x00FF0000
|
||||
#define FACE_COLOR_YELLOW (FACE_COLOR_RED | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_CYAN (FACE_COLOR_BLUE | FACE_COLOR_GREEN)
|
||||
#define FACE_COLOR_PURPLE (FACE_COLOR_BLUE | FACE_COLOR_RED)
|
||||
|
||||
typedef struct {
|
||||
size_t size; //number of values used for filtering
|
||||
size_t index; //current value index
|
||||
size_t count; //value count
|
||||
int sum;
|
||||
int * values; //array to be filled with values
|
||||
} ra_filter_t;
|
||||
|
||||
typedef struct {
|
||||
httpd_req_t *req;
|
||||
size_t len;
|
||||
} jpg_chunking_t;
|
||||
|
||||
#define PART_BOUNDARY "123456789000000000000987654321"
|
||||
static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
|
||||
static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
|
||||
static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
|
||||
|
||||
static ra_filter_t ra_filter;
|
||||
httpd_handle_t stream_httpd = NULL;
|
||||
httpd_handle_t camera_httpd = NULL;
|
||||
|
||||
static mtmn_config_t mtmn_config = {0};
|
||||
static int8_t detection_enabled = 0;
|
||||
static int8_t recognition_enabled = 0;
|
||||
static int8_t is_enrolling = 0;
|
||||
static face_id_list id_list = {0};
|
||||
|
||||
static ra_filter_t * ra_filter_init(ra_filter_t * filter, size_t sample_size){
|
||||
memset(filter, 0, sizeof(ra_filter_t));
|
||||
|
||||
filter->values = (int *)malloc(sample_size * sizeof(int));
|
||||
if(!filter->values){
|
||||
return NULL;
|
||||
}
|
||||
memset(filter->values, 0, sample_size * sizeof(int));
|
||||
|
||||
filter->size = sample_size;
|
||||
return filter;
|
||||
}
|
||||
|
||||
static int ra_filter_run(ra_filter_t * filter, int value){
|
||||
if(!filter->values){
|
||||
return value;
|
||||
}
|
||||
filter->sum -= filter->values[filter->index];
|
||||
filter->values[filter->index] = value;
|
||||
filter->sum += filter->values[filter->index];
|
||||
filter->index++;
|
||||
filter->index = filter->index % filter->size;
|
||||
if (filter->count < filter->size) {
|
||||
filter->count++;
|
||||
}
|
||||
return filter->sum / filter->count;
|
||||
}
|
||||
|
||||
static void rgb_print(dl_matrix3du_t *image_matrix, uint32_t color, const char * str){
|
||||
fb_data_t fb;
|
||||
fb.width = image_matrix->w;
|
||||
fb.height = image_matrix->h;
|
||||
fb.data = image_matrix->item;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
fb_gfx_print(&fb, (fb.width - (strlen(str) * 14)) / 2, 10, color, str);
|
||||
}
|
||||
|
||||
static int rgb_printf(dl_matrix3du_t *image_matrix, uint32_t color, const char *format, ...){
|
||||
char loc_buf[64];
|
||||
char * temp = loc_buf;
|
||||
int len;
|
||||
va_list arg;
|
||||
va_list copy;
|
||||
va_start(arg, format);
|
||||
va_copy(copy, arg);
|
||||
len = vsnprintf(loc_buf, sizeof(loc_buf), format, arg);
|
||||
va_end(copy);
|
||||
if(len >= sizeof(loc_buf)){
|
||||
temp = (char*)malloc(len+1);
|
||||
if(temp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
vsnprintf(temp, len+1, format, arg);
|
||||
va_end(arg);
|
||||
rgb_print(image_matrix, color, temp);
|
||||
if(len > 64){
|
||||
free(temp);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void draw_face_boxes(dl_matrix3du_t *image_matrix, box_array_t *boxes, int face_id){
|
||||
int x, y, w, h, i;
|
||||
uint32_t color = FACE_COLOR_YELLOW;
|
||||
if(face_id < 0){
|
||||
color = FACE_COLOR_RED;
|
||||
} else if(face_id > 0){
|
||||
color = FACE_COLOR_GREEN;
|
||||
}
|
||||
fb_data_t fb;
|
||||
fb.width = image_matrix->w;
|
||||
fb.height = image_matrix->h;
|
||||
fb.data = image_matrix->item;
|
||||
fb.bytes_per_pixel = 3;
|
||||
fb.format = FB_BGR888;
|
||||
for (i = 0; i < boxes->len; i++){
|
||||
// rectangle box
|
||||
x = (int)boxes->box[i].box_p[0];
|
||||
y = (int)boxes->box[i].box_p[1];
|
||||
w = (int)boxes->box[i].box_p[2] - x + 1;
|
||||
h = (int)boxes->box[i].box_p[3] - y + 1;
|
||||
fb_gfx_drawFastHLine(&fb, x, y, w, color);
|
||||
fb_gfx_drawFastHLine(&fb, x, y+h-1, w, color);
|
||||
fb_gfx_drawFastVLine(&fb, x, y, h, color);
|
||||
fb_gfx_drawFastVLine(&fb, x+w-1, y, h, color);
|
||||
#if 0
|
||||
// landmark
|
||||
int x0, y0, j;
|
||||
for (j = 0; j < 10; j+=2) {
|
||||
x0 = (int)boxes->landmark[i].landmark_p[j];
|
||||
y0 = (int)boxes->landmark[i].landmark_p[j+1];
|
||||
fb_gfx_fillRect(&fb, x0, y0, 3, 3, color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static int run_face_recognition(dl_matrix3du_t *image_matrix, box_array_t *net_boxes){
|
||||
dl_matrix3du_t *aligned_face = NULL;
|
||||
int matched_id = 0;
|
||||
|
||||
aligned_face = dl_matrix3du_alloc(1, FACE_WIDTH, FACE_HEIGHT, 3);
|
||||
if(!aligned_face){
|
||||
Serial.println("Could not allocate face recognition buffer");
|
||||
return matched_id;
|
||||
}
|
||||
if (align_face(net_boxes, image_matrix, aligned_face) == ESP_OK){
|
||||
if (is_enrolling == 1){
|
||||
int8_t left_sample_face = enroll_face(&id_list, aligned_face);
|
||||
|
||||
if(left_sample_face == (ENROLL_CONFIRM_TIMES - 1)){
|
||||
Serial.printf("Enrolling Face ID: %d\n", id_list.tail);
|
||||
}
|
||||
Serial.printf("Enrolling Face ID: %d sample %d\n", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
|
||||
rgb_printf(image_matrix, FACE_COLOR_CYAN, "ID[%u] Sample[%u]", id_list.tail, ENROLL_CONFIRM_TIMES - left_sample_face);
|
||||
if (left_sample_face == 0){
|
||||
is_enrolling = 0;
|
||||
Serial.printf("Enrolled Face ID: %d\n", id_list.tail);
|
||||
}
|
||||
} else {
|
||||
matched_id = recognize_face(&id_list, aligned_face);
|
||||
if (matched_id >= 0) {
|
||||
Serial.printf("Match Face ID: %u\n", matched_id);
|
||||
rgb_printf(image_matrix, FACE_COLOR_GREEN, "Hello Subject %u", matched_id);
|
||||
} else {
|
||||
Serial.println("No Match Found");
|
||||
rgb_print(image_matrix, FACE_COLOR_RED, "Intruder Alert!");
|
||||
matched_id = -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Serial.println("Face Not Aligned");
|
||||
//rgb_print(image_matrix, FACE_COLOR_YELLOW, "Human Detected");
|
||||
}
|
||||
|
||||
dl_matrix3du_free(aligned_face);
|
||||
return matched_id;
|
||||
}
|
||||
|
||||
static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
|
||||
jpg_chunking_t *j = (jpg_chunking_t *)arg;
|
||||
if(!index){
|
||||
j->len = 0;
|
||||
}
|
||||
if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){
|
||||
return 0;
|
||||
}
|
||||
j->len += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
static esp_err_t capture_handler(httpd_req_t *req){
|
||||
camera_fb_t * fb = NULL;
|
||||
esp_err_t res = ESP_OK;
|
||||
int64_t fr_start = esp_timer_get_time();
|
||||
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
Serial.println("Camera capture failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
|
||||
|
||||
size_t out_len, out_width, out_height;
|
||||
uint8_t * out_buf;
|
||||
bool s;
|
||||
bool detected = false;
|
||||
int face_id = 0;
|
||||
if(!detection_enabled || fb->width > 400){
|
||||
size_t fb_len = 0;
|
||||
if(fb->format == PIXFORMAT_JPEG){
|
||||
fb_len = fb->len;
|
||||
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
|
||||
} else {
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
fb_len = jchunk.len;
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
Serial.printf("JPG: %uB %ums\n", (uint32_t)(fb_len), (uint32_t)((fr_end - fr_start)/1000));
|
||||
return res;
|
||||
}
|
||||
|
||||
dl_matrix3du_t *image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||
if (!image_matrix) {
|
||||
esp_camera_fb_return(fb);
|
||||
Serial.println("dl_matrix3du_alloc failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
out_buf = image_matrix->item;
|
||||
out_len = fb->width * fb->height * 3;
|
||||
out_width = fb->width;
|
||||
out_height = fb->height;
|
||||
|
||||
s = fmt2rgb888(fb->buf, fb->len, fb->format, out_buf);
|
||||
esp_camera_fb_return(fb);
|
||||
if(!s){
|
||||
dl_matrix3du_free(image_matrix);
|
||||
Serial.println("to rgb888 failed");
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
box_array_t *net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||
|
||||
if (net_boxes){
|
||||
detected = true;
|
||||
if(recognition_enabled){
|
||||
face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
}
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
free(net_boxes->box);
|
||||
free(net_boxes->landmark);
|
||||
free(net_boxes);
|
||||
}
|
||||
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
s = fmt2jpg_cb(out_buf, out_len, out_width, out_height, PIXFORMAT_RGB888, 90, jpg_encode_stream, &jchunk);
|
||||
dl_matrix3du_free(image_matrix);
|
||||
if(!s){
|
||||
Serial.println("JPEG compression failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
Serial.printf("FACE: %uB %ums %s%d\n", (uint32_t)(jchunk.len), (uint32_t)((fr_end - fr_start)/1000), detected?"DETECTED ":"", face_id);
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t stream_handler(httpd_req_t *req){
|
||||
camera_fb_t * fb = NULL;
|
||||
esp_err_t res = ESP_OK;
|
||||
size_t _jpg_buf_len = 0;
|
||||
uint8_t * _jpg_buf = NULL;
|
||||
char * part_buf[64];
|
||||
dl_matrix3du_t *image_matrix = NULL;
|
||||
bool detected = false;
|
||||
int face_id = 0;
|
||||
int64_t fr_start = 0;
|
||||
int64_t fr_ready = 0;
|
||||
int64_t fr_face = 0;
|
||||
int64_t fr_recognize = 0;
|
||||
int64_t fr_encode = 0;
|
||||
|
||||
static int64_t last_frame = 0;
|
||||
if(!last_frame) {
|
||||
last_frame = esp_timer_get_time();
|
||||
}
|
||||
|
||||
res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
|
||||
if(res != ESP_OK){
|
||||
return res;
|
||||
}
|
||||
|
||||
while(true){
|
||||
detected = false;
|
||||
face_id = 0;
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
Serial.println("Camera capture failed");
|
||||
res = ESP_FAIL;
|
||||
} else {
|
||||
fr_start = esp_timer_get_time();
|
||||
fr_ready = fr_start;
|
||||
fr_face = fr_start;
|
||||
fr_encode = fr_start;
|
||||
fr_recognize = fr_start;
|
||||
if(!detection_enabled || fb->width > 400){
|
||||
if(fb->format != PIXFORMAT_JPEG){
|
||||
bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
if(!jpeg_converted){
|
||||
Serial.println("JPEG compression failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
_jpg_buf_len = fb->len;
|
||||
_jpg_buf = fb->buf;
|
||||
}
|
||||
} else {
|
||||
|
||||
image_matrix = dl_matrix3du_alloc(1, fb->width, fb->height, 3);
|
||||
|
||||
if (!image_matrix) {
|
||||
Serial.println("dl_matrix3du_alloc failed");
|
||||
res = ESP_FAIL;
|
||||
} else {
|
||||
if(!fmt2rgb888(fb->buf, fb->len, fb->format, image_matrix->item)){
|
||||
Serial.println("fmt2rgb888 failed");
|
||||
res = ESP_FAIL;
|
||||
} else {
|
||||
fr_ready = esp_timer_get_time();
|
||||
box_array_t *net_boxes = NULL;
|
||||
if(detection_enabled){
|
||||
net_boxes = face_detect(image_matrix, &mtmn_config);
|
||||
}
|
||||
fr_face = esp_timer_get_time();
|
||||
fr_recognize = fr_face;
|
||||
if (net_boxes || fb->format != PIXFORMAT_JPEG){
|
||||
if(net_boxes){
|
||||
detected = true;
|
||||
if(recognition_enabled){
|
||||
face_id = run_face_recognition(image_matrix, net_boxes);
|
||||
}
|
||||
fr_recognize = esp_timer_get_time();
|
||||
draw_face_boxes(image_matrix, net_boxes, face_id);
|
||||
free(net_boxes->box);
|
||||
free(net_boxes->landmark);
|
||||
free(net_boxes);
|
||||
}
|
||||
if(!fmt2jpg(image_matrix->item, fb->width*fb->height*3, fb->width, fb->height, PIXFORMAT_RGB888, 90, &_jpg_buf, &_jpg_buf_len)){
|
||||
Serial.println("fmt2jpg failed");
|
||||
res = ESP_FAIL;
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
} else {
|
||||
_jpg_buf = fb->buf;
|
||||
_jpg_buf_len = fb->len;
|
||||
}
|
||||
fr_encode = esp_timer_get_time();
|
||||
}
|
||||
dl_matrix3du_free(image_matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(res == ESP_OK){
|
||||
size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
|
||||
res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
|
||||
}
|
||||
if(res == ESP_OK){
|
||||
res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
|
||||
}
|
||||
if(res == ESP_OK){
|
||||
res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
|
||||
}
|
||||
if(fb){
|
||||
esp_camera_fb_return(fb);
|
||||
fb = NULL;
|
||||
_jpg_buf = NULL;
|
||||
} else if(_jpg_buf){
|
||||
free(_jpg_buf);
|
||||
_jpg_buf = NULL;
|
||||
}
|
||||
if(res != ESP_OK){
|
||||
break;
|
||||
}
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
|
||||
int64_t ready_time = (fr_ready - fr_start)/1000;
|
||||
int64_t face_time = (fr_face - fr_ready)/1000;
|
||||
int64_t recognize_time = (fr_recognize - fr_face)/1000;
|
||||
int64_t encode_time = (fr_encode - fr_recognize)/1000;
|
||||
int64_t process_time = (fr_encode - fr_start)/1000;
|
||||
|
||||
int64_t frame_time = fr_end - last_frame;
|
||||
last_frame = fr_end;
|
||||
frame_time /= 1000;
|
||||
uint32_t avg_frame_time = ra_filter_run(&ra_filter, frame_time);
|
||||
Serial.printf("MJPG: %uB %ums (%.1ffps), AVG: %ums (%.1ffps), %u+%u+%u+%u=%u %s%d\n",
|
||||
(uint32_t)(_jpg_buf_len),
|
||||
(uint32_t)frame_time, 1000.0 / (uint32_t)frame_time,
|
||||
avg_frame_time, 1000.0 / avg_frame_time,
|
||||
(uint32_t)ready_time, (uint32_t)face_time, (uint32_t)recognize_time, (uint32_t)encode_time, (uint32_t)process_time,
|
||||
(detected)?"DETECTED ":"", face_id
|
||||
);
|
||||
}
|
||||
|
||||
last_frame = 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
static esp_err_t cmd_handler(httpd_req_t *req){
|
||||
char* buf;
|
||||
size_t buf_len;
|
||||
char variable[32] = {0,};
|
||||
char value[32] = {0,};
|
||||
|
||||
buf_len = httpd_req_get_url_query_len(req) + 1;
|
||||
if (buf_len > 1) {
|
||||
buf = (char*)malloc(buf_len);
|
||||
if(!buf){
|
||||
httpd_resp_send_500(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
|
||||
if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
|
||||
httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
|
||||
} else {
|
||||
free(buf);
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
} else {
|
||||
free(buf);
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
httpd_resp_send_404(req);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int val = atoi(value);
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
int res = 0;
|
||||
|
||||
if(!strcmp(variable, "framesize")) {
|
||||
if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
|
||||
}
|
||||
else if(!strcmp(variable, "quality")) res = s->set_quality(s, val);
|
||||
else if(!strcmp(variable, "contrast")) res = s->set_contrast(s, val);
|
||||
else if(!strcmp(variable, "brightness")) res = s->set_brightness(s, val);
|
||||
else if(!strcmp(variable, "saturation")) res = s->set_saturation(s, val);
|
||||
else if(!strcmp(variable, "gainceiling")) res = s->set_gainceiling(s, (gainceiling_t)val);
|
||||
else if(!strcmp(variable, "colorbar")) res = s->set_colorbar(s, val);
|
||||
else if(!strcmp(variable, "awb")) res = s->set_whitebal(s, val);
|
||||
else if(!strcmp(variable, "agc")) res = s->set_gain_ctrl(s, val);
|
||||
else if(!strcmp(variable, "aec")) res = s->set_exposure_ctrl(s, val);
|
||||
else if(!strcmp(variable, "hmirror")) res = s->set_hmirror(s, val);
|
||||
else if(!strcmp(variable, "vflip")) res = s->set_vflip(s, val);
|
||||
else if(!strcmp(variable, "awb_gain")) res = s->set_awb_gain(s, val);
|
||||
else if(!strcmp(variable, "agc_gain")) res = s->set_agc_gain(s, val);
|
||||
else if(!strcmp(variable, "aec_value")) res = s->set_aec_value(s, val);
|
||||
else if(!strcmp(variable, "aec2")) res = s->set_aec2(s, val);
|
||||
else if(!strcmp(variable, "dcw")) res = s->set_dcw(s, val);
|
||||
else if(!strcmp(variable, "bpc")) res = s->set_bpc(s, val);
|
||||
else if(!strcmp(variable, "wpc")) res = s->set_wpc(s, val);
|
||||
else if(!strcmp(variable, "raw_gma")) res = s->set_raw_gma(s, val);
|
||||
else if(!strcmp(variable, "lenc")) res = s->set_lenc(s, val);
|
||||
else if(!strcmp(variable, "special_effect")) res = s->set_special_effect(s, val);
|
||||
else if(!strcmp(variable, "wb_mode")) res = s->set_wb_mode(s, val);
|
||||
else if(!strcmp(variable, "ae_level")) res = s->set_ae_level(s, val);
|
||||
else if(!strcmp(variable, "face_detect")) {
|
||||
detection_enabled = val;
|
||||
if(!detection_enabled) {
|
||||
recognition_enabled = 0;
|
||||
}
|
||||
}
|
||||
else if(!strcmp(variable, "face_enroll")) is_enrolling = val;
|
||||
else if(!strcmp(variable, "face_recognize")) {
|
||||
recognition_enabled = val;
|
||||
if(recognition_enabled){
|
||||
detection_enabled = val;
|
||||
}
|
||||
}
|
||||
else {
|
||||
res = -1;
|
||||
}
|
||||
|
||||
if(res){
|
||||
return httpd_resp_send_500(req);
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
static esp_err_t status_handler(httpd_req_t *req){
|
||||
static char json_response[1024];
|
||||
|
||||
sensor_t * s = esp_camera_sensor_get();
|
||||
char * p = json_response;
|
||||
*p++ = '{';
|
||||
|
||||
p+=sprintf(p, "\"framesize\":%u,", s->status.framesize);
|
||||
p+=sprintf(p, "\"quality\":%u,", s->status.quality);
|
||||
p+=sprintf(p, "\"brightness\":%d,", s->status.brightness);
|
||||
p+=sprintf(p, "\"contrast\":%d,", s->status.contrast);
|
||||
p+=sprintf(p, "\"saturation\":%d,", s->status.saturation);
|
||||
p+=sprintf(p, "\"special_effect\":%u,", s->status.special_effect);
|
||||
p+=sprintf(p, "\"wb_mode\":%u,", s->status.wb_mode);
|
||||
p+=sprintf(p, "\"awb\":%u,", s->status.awb);
|
||||
p+=sprintf(p, "\"awb_gain\":%u,", s->status.awb_gain);
|
||||
p+=sprintf(p, "\"aec\":%u,", s->status.aec);
|
||||
p+=sprintf(p, "\"aec2\":%u,", s->status.aec2);
|
||||
p+=sprintf(p, "\"ae_level\":%d,", s->status.ae_level);
|
||||
p+=sprintf(p, "\"aec_value\":%u,", s->status.aec_value);
|
||||
p+=sprintf(p, "\"agc\":%u,", s->status.agc);
|
||||
p+=sprintf(p, "\"agc_gain\":%u,", s->status.agc_gain);
|
||||
p+=sprintf(p, "\"gainceiling\":%u,", s->status.gainceiling);
|
||||
p+=sprintf(p, "\"bpc\":%u,", s->status.bpc);
|
||||
p+=sprintf(p, "\"wpc\":%u,", s->status.wpc);
|
||||
p+=sprintf(p, "\"raw_gma\":%u,", s->status.raw_gma);
|
||||
p+=sprintf(p, "\"lenc\":%u,", s->status.lenc);
|
||||
p+=sprintf(p, "\"vflip\":%u,", s->status.vflip);
|
||||
p+=sprintf(p, "\"hmirror\":%u,", s->status.hmirror);
|
||||
p+=sprintf(p, "\"dcw\":%u,", s->status.dcw);
|
||||
p+=sprintf(p, "\"colorbar\":%u,", s->status.colorbar);
|
||||
p+=sprintf(p, "\"face_detect\":%u,", detection_enabled);
|
||||
p+=sprintf(p, "\"face_enroll\":%u,", is_enrolling);
|
||||
p+=sprintf(p, "\"face_recognize\":%u", recognition_enabled);
|
||||
*p++ = '}';
|
||||
*p++ = 0;
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
return httpd_resp_send(req, json_response, strlen(json_response));
|
||||
}
|
||||
|
||||
static esp_err_t index_handler(httpd_req_t *req){
|
||||
httpd_resp_set_type(req, "text/html");
|
||||
httpd_resp_set_hdr(req, "Content-Encoding", "gzip");
|
||||
return httpd_resp_send(req, (const char *)index_html_gz, index_html_gz_len);
|
||||
}
|
||||
|
||||
void startCameraServer(){
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
|
||||
httpd_uri_t index_uri = {
|
||||
.uri = "/",
|
||||
.method = HTTP_GET,
|
||||
.handler = index_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
httpd_uri_t status_uri = {
|
||||
.uri = "/status",
|
||||
.method = HTTP_GET,
|
||||
.handler = status_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
httpd_uri_t cmd_uri = {
|
||||
.uri = "/control",
|
||||
.method = HTTP_GET,
|
||||
.handler = cmd_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
httpd_uri_t capture_uri = {
|
||||
.uri = "/capture",
|
||||
.method = HTTP_GET,
|
||||
.handler = capture_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
httpd_uri_t stream_uri = {
|
||||
.uri = "/stream",
|
||||
.method = HTTP_GET,
|
||||
.handler = stream_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
|
||||
|
||||
ra_filter_init(&ra_filter, 20);
|
||||
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.7;
|
||||
mtmn_config.p_threshold.score = 0.6;
|
||||
mtmn_config.p_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.score = 0.7;
|
||||
mtmn_config.r_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.candidate_number = 4;
|
||||
mtmn_config.o_threshold.score = 0.7;
|
||||
mtmn_config.o_threshold.nms = 0.4;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
|
||||
face_id_init(&id_list, FACE_ID_SAVE_NUMBER, ENROLL_CONFIRM_TIMES);
|
||||
|
||||
Serial.printf("Starting web server on port: '%d'\n", config.server_port);
|
||||
if (httpd_start(&camera_httpd, &config) == ESP_OK) {
|
||||
httpd_register_uri_handler(camera_httpd, &index_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &cmd_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &status_uri);
|
||||
httpd_register_uri_handler(camera_httpd, &capture_uri);
|
||||
}
|
||||
|
||||
config.server_port += 1;
|
||||
config.ctrl_port += 1;
|
||||
Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
|
||||
if (httpd_start(&stream_httpd, &config) == ESP_OK) {
|
||||
httpd_register_uri_handler(stream_httpd, &stream_uri);
|
||||
}
|
||||
}
|
233
libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h
Normal file
233
libraries/ESP32/examples/Camera/CameraWebServer/camera_index.h
Normal file
@ -0,0 +1,233 @@
|
||||
//File: index.html.gz, Size: 3663
|
||||
#define index_html_gz_len 3663
|
||||
const uint8_t index_html_gz[] = {
|
||||
0x1F, 0x8B, 0x08, 0x08, 0x60, 0x15, 0x36, 0x5C, 0x00, 0x03, 0x69, 0x6E, 0x64, 0x65, 0x78, 0x2E,
|
||||
0x68, 0x74, 0x6D, 0x6C, 0x00, 0xDD, 0x5C, 0xEB, 0x72, 0x9B, 0xC8, 0x12, 0xFE, 0x7F, 0x9E, 0x02,
|
||||
0x93, 0xDD, 0x08, 0x6A, 0x91, 0x2C, 0xC9, 0x8A, 0xE3, 0x20, 0x0B, 0x1F, 0x5B, 0x76, 0x92, 0xAD,
|
||||
0xCA, 0x6D, 0xE3, 0x3D, 0xBB, 0x5B, 0xB5, 0xB5, 0x95, 0x8C, 0x60, 0x90, 0x26, 0x46, 0x8C, 0x02,
|
||||
0x83, 0x2E, 0xD1, 0xF2, 0x1C, 0xE7, 0x81, 0xCE, 0x8B, 0x9D, 0x9E, 0x19, 0x40, 0xA0, 0x8B, 0x65,
|
||||
0x49, 0x89, 0x94, 0x5A, 0xBB, 0xCA, 0x1A, 0xA0, 0xBB, 0xA7, 0xBB, 0xBF, 0xBE, 0x0C, 0x88, 0xF1,
|
||||
0xF9, 0x91, 0x43, 0x6D, 0x36, 0x19, 0x60, 0xA5, 0xC7, 0xFA, 0x9E, 0xF5, 0xAF, 0x73, 0xF9, 0xA1,
|
||||
0xC0, 0xCF, 0x79, 0x0F, 0x23, 0x47, 0x0E, 0xC5, 0x61, 0x1F, 0x33, 0xA4, 0xD8, 0x3D, 0x14, 0x84,
|
||||
0x98, 0xB5, 0xD4, 0x88, 0xB9, 0xE5, 0x33, 0x75, 0xFE, 0xB2, 0x8F, 0xFA, 0xB8, 0xA5, 0x0E, 0x09,
|
||||
0x1E, 0x0D, 0x68, 0xC0, 0x54, 0xC5, 0xA6, 0x3E, 0xC3, 0x3E, 0x90, 0x8F, 0x88, 0xC3, 0x7A, 0x2D,
|
||||
0x07, 0x0F, 0x89, 0x8D, 0xCB, 0xE2, 0xC0, 0x20, 0x3E, 0x61, 0x04, 0x79, 0xE5, 0xD0, 0x46, 0x1E,
|
||||
0x6E, 0xD5, 0xF2, 0xB2, 0x18, 0x61, 0x1E, 0xB6, 0x6E, 0x6E, 0xDF, 0x9D, 0xD4, 0x95, 0xB7, 0xBF,
|
||||
0xD5, 0x1B, 0xA7, 0xD5, 0xF3, 0x63, 0x79, 0x6E, 0x46, 0x13, 0xB2, 0x09, 0x3F, 0xEE, 0x50, 0x67,
|
||||
0x32, 0x75, 0x61, 0x9A, 0xB2, 0x8B, 0xFA, 0xC4, 0x9B, 0x98, 0x97, 0x01, 0x08, 0x35, 0x5E, 0x62,
|
||||
0x6F, 0x88, 0x19, 0xB1, 0x91, 0x11, 0x22, 0x3F, 0x2C, 0x87, 0x38, 0x20, 0x6E, 0xB3, 0x83, 0xEC,
|
||||
0xBB, 0x6E, 0x40, 0x23, 0xDF, 0x31, 0x1F, 0xD5, 0xCE, 0xF8, 0x6F, 0xD3, 0xA6, 0x1E, 0x0D, 0xCC,
|
||||
0x47, 0x37, 0xCF, 0xF9, 0x6F, 0x53, 0xC8, 0x09, 0xC9, 0x17, 0x6C, 0xD6, 0x4E, 0x07, 0xE3, 0xB8,
|
||||
0x57, 0x9F, 0xE6, 0xCE, 0x9C, 0xC1, 0x99, 0x10, 0xDB, 0x8C, 0x50, 0xBF, 0xD2, 0x47, 0xC4, 0x9F,
|
||||
0x3A, 0x24, 0x1C, 0x78, 0x68, 0x62, 0xBA, 0x1E, 0x1E, 0xC7, 0x8F, 0xFA, 0xD8, 0x8F, 0x8C, 0xC2,
|
||||
0x75, 0x7E, 0xBE, 0xEC, 0x90, 0x40, 0x9E, 0x33, 0x61, 0xAA, 0xA8, 0xEF, 0x4B, 0xC2, 0x8C, 0xD7,
|
||||
0xA7, 0x3E, 0x6E, 0x0A, 0xC2, 0x51, 0x80, 0x06, 0x70, 0xC8, 0x3F, 0x9A, 0x7D, 0xE2, 0x4B, 0x27,
|
||||
0x99, 0x27, 0x8D, 0xEA, 0x60, 0x5C, 0x50, 0xFC, 0xE4, 0x94, 0xFF, 0x36, 0x07, 0xC8, 0x71, 0x88,
|
||||
0xDF, 0x35, 0xCF, 0xF8, 0x65, 0x1A, 0x38, 0x38, 0x28, 0x07, 0xC8, 0x21, 0x51, 0x68, 0x36, 0xE0,
|
||||
0x4C, 0x1F, 0x05, 0x5D, 0x90, 0xC1, 0xE8, 0xC0, 0x2C, 0xD7, 0xAA, 0xB3, 0x13, 0x01, 0xE9, 0xF6,
|
||||
0x98, 0xC9, 0xCF, 0xC4, 0x8F, 0x12, 0x6C, 0x0A, 0x66, 0xE4, 0x54, 0x11, 0x8A, 0x20, 0x8F, 0x74,
|
||||
0xFD, 0x32, 0x61, 0xB8, 0x1F, 0x9A, 0x21, 0x0B, 0x30, 0xB3, 0x7B, 0xB1, 0x4B, 0xBA, 0x51, 0x80,
|
||||
0xA7, 0xA9, 0x02, 0xD5, 0x44, 0x36, 0x0C, 0xCA, 0x23, 0xDC, 0xB9, 0x23, 0xAC, 0x9C, 0x4C, 0xD6,
|
||||
0xC1, 0x2E, 0x0D, 0x70, 0x46, 0x50, 0xEE, 0x78, 0xD4, 0xBE, 0x2B, 0x87, 0x0C, 0x05, 0x6C, 0x91,
|
||||
0x18, 0xB9, 0x0C, 0x07, 0xF3, 0xB4, 0x18, 0x0C, 0x5E, 0xA0, 0x4C, 0x05, 0x24, 0x87, 0xC4, 0xF7,
|
||||
0x88, 0x8F, 0x57, 0x89, 0x95, 0x12, 0x8A, 0xA4, 0xE2, 0x5C, 0x62, 0x86, 0x42, 0xFA, 0xDD, 0xCC,
|
||||
0x03, 0x62, 0xD2, 0xA6, 0x74, 0x7C, 0xAD, 0x5A, 0xFD, 0xB1, 0xD9, 0xC3, 0xC2, 0x5F, 0x28, 0x62,
|
||||
0xF4, 0x7E, 0x27, 0xF3, 0xD8, 0xF8, 0x77, 0x1F, 0x3B, 0x04, 0x29, 0xDA, 0x0C, 0x3C, 0xE5, 0xAC,
|
||||
0x0A, 0x9E, 0xD6, 0x15, 0xE4, 0x3B, 0x8A, 0x46, 0x03, 0x02, 0xDE, 0x46, 0x22, 0x14, 0x3C, 0x38,
|
||||
0x03, 0x61, 0x3F, 0xC0, 0xFA, 0x74, 0x1D, 0x0C, 0x49, 0x44, 0xAC, 0x06, 0x62, 0x89, 0x05, 0x7D,
|
||||
0x34, 0x2E, 0xE7, 0xAC, 0xE0, 0x87, 0x89, 0x25, 0x90, 0x6A, 0xB6, 0x06, 0x27, 0x87, 0x3D, 0xA5,
|
||||
0xAC, 0xF0, 0xD0, 0xD2, 0x13, 0x73, 0x85, 0x89, 0x39, 0x73, 0xFF, 0x29, 0x28, 0xA7, 0x19, 0xFB,
|
||||
0xA8, 0x13, 0x31, 0x46, 0xFD, 0x70, 0x8D, 0x9B, 0x3F, 0x45, 0x21, 0x23, 0xEE, 0xA4, 0x9C, 0x80,
|
||||
0x62, 0x86, 0x03, 0x04, 0xF5, 0xAA, 0x83, 0xD9, 0x08, 0x63, 0x48, 0x5D, 0x1F, 0x0D, 0x01, 0xEE,
|
||||
0x6E, 0xD7, 0xC3, 0x53, 0x3B, 0x0A, 0x42, 0xA8, 0x1C, 0x03, 0x4A, 0x80, 0x32, 0x68, 0x16, 0x00,
|
||||
0xC8, 0x13, 0x96, 0xED, 0xCE, 0x94, 0x46, 0x8C, 0xAB, 0x04, 0x2A, 0x52, 0x90, 0x47, 0xD8, 0x04,
|
||||
0x46, 0xD2, 0xED, 0xD5, 0xD4, 0xE7, 0xD5, 0x39, 0x1E, 0xD3, 0xEE, 0x61, 0xFB, 0x0E, 0x3B, 0x3F,
|
||||
0x15, 0xCB, 0x85, 0x28, 0x35, 0x15, 0xE2, 0x0F, 0x22, 0x56, 0xE6, 0x05, 0x61, 0xB0, 0xC6, 0x1E,
|
||||
0xE1, 0x89, 0x64, 0x8A, 0x7A, 0x3D, 0x8B, 0x59, 0xF3, 0xC9, 0x60, 0xAC, 0x54, 0x0B, 0x82, 0x2C,
|
||||
0x0F, 0x75, 0xB0, 0x97, 0x89, 0x4B, 0x9C, 0x28, 0xE3, 0x29, 0x09, 0x82, 0x5C, 0xF5, 0xC8, 0x55,
|
||||
0xA8, 0xC6, 0xD3, 0x1F, 0x0B, 0x82, 0x14, 0x31, 0x36, 0x0A, 0xA7, 0x42, 0xEC, 0x01, 0x0C, 0xB2,
|
||||
0x20, 0xC2, 0x99, 0x91, 0x59, 0x8B, 0x2B, 0x01, 0xF2, 0xBB, 0x18, 0x00, 0x1C, 0x1B, 0xE9, 0x30,
|
||||
0x57, 0x52, 0x97, 0x4D, 0x6F, 0x56, 0x15, 0x50, 0x3B, 0x96, 0x40, 0x2E, 0x44, 0x7C, 0x6A, 0x56,
|
||||
0x8E, 0xBA, 0x56, 0xCF, 0x6A, 0x23, 0x38, 0xBA, 0xE0, 0x0A, 0x5E, 0x35, 0xE7, 0x10, 0x4C, 0x3A,
|
||||
0x81, 0xEB, 0x16, 0xFB, 0x84, 0xEB, 0x9E, 0x54, 0x4F, 0x1A, 0x73, 0xD9, 0xCF, 0xE7, 0x29, 0xF6,
|
||||
0x8A, 0x66, 0x86, 0x71, 0xA2, 0xA0, 0xD9, 0xA3, 0x43, 0x1C, 0x4C, 0x8B, 0xA2, 0x1A, 0xCF, 0x1A,
|
||||
0x4E, 0x7A, 0x1D, 0x41, 0x5C, 0x0E, 0x71, 0x91, 0xA0, 0x5E, 0xB3, 0xEB, 0xB5, 0x84, 0xA0, 0x02,
|
||||
0x16, 0xA2, 0x8E, 0x87, 0x9D, 0x34, 0xD4, 0x1C, 0xEC, 0xA2, 0xC8, 0x63, 0x05, 0xED, 0x50, 0x95,
|
||||
0xFF, 0xC6, 0xC2, 0xD7, 0x7F, 0xF2, 0x36, 0xDE, 0x12, 0xBE, 0xFC, 0x6B, 0x9A, 0x26, 0x08, 0x1A,
|
||||
0x0C, 0x30, 0x82, 0x73, 0x36, 0x96, 0xAD, 0x66, 0xB1, 0xB8, 0x89, 0xB0, 0x58, 0xD2, 0x60, 0xE6,
|
||||
0xDC, 0x93, 0xA6, 0xFF, 0xE2, 0x5C, 0xA6, 0x4B, 0xED, 0x28, 0x9C, 0x05, 0xF9, 0x12, 0x0A, 0x33,
|
||||
0x55, 0x27, 0xF4, 0x88, 0x70, 0x63, 0xE4, 0xFB, 0xDC, 0xB6, 0x32, 0x0B, 0x60, 0xE2, 0xE9, 0x12,
|
||||
0xA5, 0x16, 0xF1, 0xC9, 0xAB, 0x98, 0xB4, 0xEB, 0x22, 0x28, 0xD5, 0x0C, 0x6B, 0x25, 0xA4, 0x30,
|
||||
0x8F, 0x92, 0x90, 0x3D, 0x40, 0x1F, 0xD6, 0x8B, 0xFA, 0x9D, 0x69, 0xC2, 0x5E, 0x83, 0xDC, 0x90,
|
||||
0x02, 0x82, 0x6E, 0x07, 0x69, 0x55, 0xA3, 0x6A, 0x9C, 0xC0, 0x1F, 0xBD, 0xE0, 0x30, 0xA9, 0x72,
|
||||
0xBD, 0xBE, 0xD0, 0x7D, 0x9F, 0xCC, 0xF7, 0xEB, 0x24, 0x80, 0xE6, 0xAC, 0x59, 0x85, 0x4F, 0xA1,
|
||||
0x71, 0xD7, 0x2A, 0x3C, 0xE0, 0x57, 0x38, 0x7C, 0x9D, 0x53, 0x17, 0xFD, 0xB5, 0xD4, 0x11, 0x7D,
|
||||
0xFA, 0xA5, 0x2C, 0xF3, 0xEF, 0x60, 0x58, 0xE4, 0x54, 0xD8, 0x37, 0x0E, 0xCB, 0xF5, 0x09, 0xB7,
|
||||
0xF4, 0x45, 0x55, 0x49, 0xED, 0x2E, 0xCB, 0x6A, 0x02, 0x62, 0x7C, 0x68, 0x21, 0x01, 0xB4, 0x92,
|
||||
0xE6, 0xC2, 0x99, 0x55, 0x73, 0xBB, 0xC4, 0xF3, 0xCA, 0x1E, 0x1D, 0xCD, 0x55, 0x8F, 0x82, 0x9F,
|
||||
0xE7, 0xFD, 0x3A, 0xEF, 0xFE, 0x7B, 0x65, 0x47, 0x10, 0x73, 0xDF, 0x40, 0xF6, 0xFE, 0x93, 0x68,
|
||||
0x06, 0xCA, 0x3D, 0x49, 0xB2, 0xCE, 0xA3, 0x0F, 0x60, 0x5D, 0x74, 0x98, 0xAC, 0x91, 0x71, 0x25,
|
||||
0x1C, 0x11, 0x58, 0x89, 0xCD, 0x35, 0xA3, 0x01, 0x0D, 0x89, 0x58, 0xE6, 0x05, 0xD8, 0x43, 0xBC,
|
||||
0xC8, 0x2F, 0xB6, 0xE1, 0xB9, 0xE6, 0x91, 0xBB, 0x94, 0xCA, 0x94, 0x6D, 0xF4, 0x61, 0x4B, 0x87,
|
||||
0x8A, 0xAC, 0x00, 0x49, 0xBC, 0x0A, 0xE7, 0x15, 0x8A, 0x7B, 0xC1, 0xB7, 0xF5, 0x7B, 0x63, 0x38,
|
||||
0x09, 0xDC, 0x6E, 0x80, 0x27, 0xA9, 0x58, 0x23, 0xF9, 0x34, 0xE5, 0x4A, 0x6F, 0x79, 0x8F, 0x16,
|
||||
0x71, 0x2D, 0xAD, 0xAE, 0x34, 0xC2, 0x78, 0x8E, 0x65, 0xD1, 0x23, 0xE9, 0x02, 0x4B, 0x55, 0x17,
|
||||
0xA0, 0xCF, 0x92, 0x4D, 0xB8, 0x26, 0xC9, 0x41, 0x3E, 0xF4, 0xB0, 0xCB, 0xC4, 0xC2, 0x9B, 0x57,
|
||||
0xC7, 0x93, 0x42, 0x84, 0x94, 0x67, 0xDD, 0x5B, 0xE2, 0x99, 0xAD, 0x9F, 0x52, 0xDF, 0x2C, 0xA3,
|
||||
0xE5, 0x31, 0xB5, 0x9C, 0x3C, 0x55, 0x3C, 0x2D, 0xB1, 0xC2, 0x3C, 0x38, 0xD3, 0x97, 0x09, 0x0C,
|
||||
0x46, 0xE0, 0x3F, 0xB4, 0xFA, 0x29, 0x5F, 0x3F, 0xAF, 0xBE, 0x14, 0x27, 0xCB, 0x9E, 0x85, 0x94,
|
||||
0x48, 0x5B, 0x6C, 0x2E, 0x0A, 0x1A, 0x73, 0x98, 0xCD, 0x70, 0x5F, 0x58, 0x79, 0xC0, 0x6A, 0xAB,
|
||||
0x8F, 0xA0, 0x58, 0x72, 0x17, 0xC2, 0x6D, 0x26, 0xD8, 0xB6, 0xE8, 0xDE, 0xD9, 0xF2, 0xAC, 0x76,
|
||||
0xCA, 0x6F, 0xF6, 0x2A, 0xB6, 0x47, 0xC3, 0x1C, 0x0E, 0xA8, 0x03, 0x9A, 0x44, 0x0C, 0x37, 0xE5,
|
||||
0x92, 0xEE, 0x49, 0xE2, 0xD4, 0x27, 0xCB, 0xD3, 0x2E, 0x87, 0x41, 0x1E, 0x9A, 0xA2, 0x66, 0x35,
|
||||
0x7E, 0xAF, 0x93, 0x5F, 0x45, 0x31, 0x3C, 0x86, 0xFE, 0xC6, 0xEF, 0x5B, 0x4C, 0x1B, 0x8B, 0x30,
|
||||
0xCB, 0xA7, 0x41, 0x6D, 0x71, 0x09, 0x16, 0x57, 0x7A, 0xC4, 0x71, 0xB0, 0x5F, 0xB8, 0x39, 0x8E,
|
||||
0x67, 0x77, 0xFC, 0xC7, 0xC9, 0x2D, 0xBF, 0x3C, 0x98, 0x3D, 0x9D, 0x38, 0xE7, 0xCF, 0x00, 0xF2,
|
||||
0x4F, 0x06, 0xE4, 0x92, 0x5F, 0xB1, 0x3D, 0x14, 0x86, 0x2D, 0x95, 0xDF, 0x8B, 0xE7, 0x1E, 0x2E,
|
||||
0x08, 0x12, 0x87, 0x0C, 0x15, 0xE2, 0xB4, 0x54, 0x8F, 0x76, 0xE9, 0xDC, 0x35, 0x71, 0x5D, 0x2C,
|
||||
0x86, 0x15, 0x40, 0xB5, 0xA5, 0x16, 0x96, 0xE5, 0xAA, 0xE0, 0x9A, 0x9D, 0x52, 0xAD, 0xC7, 0x8F,
|
||||
0x9E, 0x3D, 0x7D, 0x7A, 0xDA, 0x7C, 0xEC, 0x77, 0xC2, 0x41, 0xF2, 0xF7, 0x57, 0x71, 0x09, 0x16,
|
||||
0xBD, 0x8C, 0xC1, 0x42, 0x34, 0x3C, 0x3F, 0x16, 0xD2, 0xE6, 0x34, 0x38, 0x06, 0x15, 0x56, 0x28,
|
||||
0x95, 0xE4, 0xC6, 0x32, 0xBD, 0x52, 0x92, 0x10, 0x82, 0xB4, 0x83, 0x82, 0x25, 0x24, 0x82, 0x4C,
|
||||
0xC4, 0xB4, 0x22, 0x4A, 0x9A, 0x2A, 0x22, 0xBB, 0x43, 0xC7, 0xF3, 0xAA, 0x0B, 0x6B, 0x92, 0xB0,
|
||||
0x4F, 0xA8, 0xB0, 0xB3, 0x4A, 0x20, 0xB0, 0x09, 0x76, 0x7E, 0x33, 0xB2, 0x82, 0x26, 0xD3, 0x2F,
|
||||
0x71, 0x7B, 0x6E, 0xFD, 0x2F, 0xA7, 0x76, 0x03, 0xD4, 0xC7, 0x3C, 0xDA, 0x93, 0x93, 0xAB, 0xC5,
|
||||
0xCC, 0x43, 0x90, 0x71, 0xAA, 0xD6, 0x7B, 0x2C, 0x02, 0x17, 0xE0, 0x5D, 0xEA, 0xD6, 0x05, 0x29,
|
||||
0x32, 0x05, 0x8B, 0xF3, 0xAB, 0xA9, 0x8A, 0xC9, 0x8A, 0xBA, 0x8C, 0x44, 0xBC, 0xAC, 0x51, 0x48,
|
||||
0x88, 0xA3, 0x03, 0x11, 0x59, 0x43, 0xE4, 0x45, 0xE0, 0xDA, 0x5A, 0x55, 0xB5, 0xFE, 0xF3, 0xC7,
|
||||
0x8B, 0x4B, 0x0D, 0x92, 0xAC, 0x3A, 0xAE, 0xD5, 0xAB, 0x55, 0xFD, 0xFC, 0x58, 0x92, 0x6C, 0x2C,
|
||||
0xEB, 0x99, 0x6A, 0xDD, 0x0A, 0x51, 0xF5, 0x33, 0x10, 0x55, 0xAD, 0x37, 0xB6, 0x17, 0x75, 0xA6,
|
||||
0x5A, 0x42, 0x12, 0x08, 0x19, 0x3F, 0x3D, 0x3D, 0xDB, 0x5E, 0xD0, 0x53, 0xD0, 0xE9, 0x37, 0x90,
|
||||
0x74, 0x06, 0xD6, 0x9D, 0xEE, 0x62, 0xDC, 0xA9, 0x6A, 0x71, 0x39, 0xA7, 0x8D, 0xEA, 0xB8, 0x71,
|
||||
0xB6, 0x83, 0x9C, 0x27, 0x6A, 0x72, 0x2B, 0xC9, 0x43, 0x36, 0x1D, 0xA9, 0x56, 0xFB, 0xE7, 0xE7,
|
||||
0x5A, 0x03, 0x74, 0xAC, 0x3F, 0x3B, 0xDD, 0x5E, 0x76, 0x43, 0xB5, 0x7E, 0xE1, 0x4A, 0x9E, 0xD4,
|
||||
0x41, 0x50, 0x63, 0x07, 0x25, 0x4F, 0x54, 0xEB, 0xA5, 0x90, 0x04, 0x52, 0xC6, 0xB5, 0xA7, 0x3B,
|
||||
0xA8, 0x04, 0xE1, 0xF5, 0x8B, 0x90, 0x04, 0xF1, 0xC5, 0xC3, 0xEB, 0x81, 0x92, 0xA0, 0x50, 0x0A,
|
||||
0xD7, 0xDC, 0x93, 0xA7, 0x8B, 0xD5, 0xA7, 0x70, 0xF9, 0xBE, 0x34, 0xFE, 0x1C, 0x41, 0x4D, 0x67,
|
||||
0x93, 0x8D, 0x93, 0x38, 0xE1, 0x03, 0x93, 0xE4, 0xE0, 0x61, 0xF9, 0x9B, 0xD3, 0x24, 0x7B, 0x4A,
|
||||
0xA0, 0x5A, 0xB5, 0xEA, 0x1A, 0x0B, 0x04, 0x6F, 0xBE, 0x0A, 0x0A, 0xE6, 0x82, 0x01, 0xAA, 0x02,
|
||||
0xA2, 0x44, 0x0E, 0x2B, 0x7D, 0x34, 0x86, 0x18, 0x3D, 0x51, 0x73, 0x79, 0xBD, 0x55, 0x89, 0x58,
|
||||
0xA2, 0x2D, 0x1A, 0xAB, 0xD6, 0xE9, 0xC9, 0x3A, 0x7F, 0xEF, 0x00, 0x47, 0x47, 0x74, 0x70, 0x1F,
|
||||
0x87, 0xE1, 0xC6, 0x88, 0xCC, 0x58, 0x55, 0xEB, 0x2A, 0x1B, 0xEF, 0x82, 0x4B, 0xB9, 0xBE, 0x03,
|
||||
0x2E, 0x39, 0x75, 0x24, 0x34, 0xE5, 0x7A, 0x02, 0x4D, 0x5D, 0x9D, 0x65, 0xC4, 0xD7, 0x04, 0x66,
|
||||
0x9D, 0xB6, 0xBB, 0xE0, 0xC2, 0x9B, 0x78, 0x80, 0x42, 0xB6, 0x31, 0x2A, 0x29, 0x23, 0x94, 0xB5,
|
||||
0x64, 0x74, 0x30, 0x44, 0x32, 0x55, 0xFE, 0x01, 0x78, 0x84, 0x88, 0x45, 0x81, 0x78, 0xFA, 0xBE,
|
||||
0x31, 0x22, 0x33, 0x56, 0xE8, 0x87, 0xD9, 0xF8, 0x60, 0xA8, 0xE4, 0xD4, 0xF9, 0x27, 0xE0, 0x32,
|
||||
0xC0, 0x36, 0x41, 0xDE, 0x07, 0xEC, 0xBA, 0xD0, 0xB2, 0x36, 0xC7, 0xA6, 0xC0, 0x0E, 0xF8, 0xC8,
|
||||
0x63, 0xE5, 0x46, 0x1C, 0x6F, 0xBC, 0x46, 0x9C, 0x13, 0xF7, 0xB5, 0x16, 0x8A, 0xD5, 0xE5, 0xEB,
|
||||
0x96, 0x37, 0x34, 0xD3, 0x73, 0xCB, 0x15, 0x42, 0x0D, 0x84, 0xE0, 0xAE, 0xB8, 0xE7, 0xDB, 0x5A,
|
||||
0x46, 0x5D, 0xB5, 0x5E, 0x04, 0x68, 0x22, 0xBE, 0x86, 0xDD, 0x65, 0xD1, 0xF3, 0x1E, 0x3B, 0xCA,
|
||||
0xAF, 0x70, 0x23, 0xB7, 0xCB, 0x0A, 0xEC, 0x45, 0x80, 0xB1, 0xBF, 0x9B, 0x94, 0x27, 0xD0, 0xCC,
|
||||
0x60, 0xB0, 0x9B, 0x10, 0x58, 0xB0, 0xDE, 0xE2, 0x01, 0x41, 0xDF, 0xC3, 0x82, 0x0B, 0x8D, 0x3A,
|
||||
0x1B, 0xA7, 0x05, 0xF0, 0xA8, 0xD6, 0xE5, 0xEF, 0x57, 0x1B, 0x17, 0x29, 0xF9, 0xF0, 0xE9, 0x21,
|
||||
0x11, 0x2E, 0xAB, 0x53, 0xA2, 0xA0, 0xBA, 0x70, 0xB3, 0xB9, 0x3C, 0x73, 0x1E, 0x7A, 0xC3, 0xB9,
|
||||
0xC4, 0xAE, 0x54, 0x41, 0xF1, 0x7C, 0x46, 0xCD, 0x99, 0xF9, 0x30, 0x1B, 0xBF, 0x5D, 0x05, 0x03,
|
||||
0x25, 0x3E, 0x74, 0x11, 0xD9, 0xBC, 0xAF, 0xA4, 0x8C, 0x02, 0x29, 0xE5, 0x05, 0x8C, 0xF6, 0x05,
|
||||
0x97, 0x9C, 0xF6, 0x60, 0x98, 0x25, 0x56, 0x1F, 0x1A, 0x38, 0x50, 0xA4, 0x4F, 0x9D, 0xCD, 0x1F,
|
||||
0x47, 0x24, 0x7C, 0xAA, 0x05, 0xA8, 0xBD, 0x86, 0xC1, 0xC6, 0x5D, 0x26, 0x15, 0xF0, 0x8D, 0xDB,
|
||||
0xCB, 0x65, 0xC4, 0xE8, 0x2E, 0x9D, 0xE5, 0x36, 0xF2, 0xFD, 0xC9, 0x2E, 0x6D, 0xA5, 0xED, 0xD1,
|
||||
0xC8, 0xD9, 0x5E, 0x02, 0xF4, 0x94, 0xB7, 0xAE, 0x4B, 0xEC, 0xED, 0xBB, 0x12, 0x74, 0x94, 0x97,
|
||||
0xB4, 0xFF, 0x40, 0xFE, 0x6F, 0x5C, 0xC5, 0xB1, 0xBD, 0x79, 0x81, 0xC0, 0x36, 0xA0, 0x78, 0xD3,
|
||||
0x56, 0x6E, 0x6F, 0xDE, 0xDC, 0xBE, 0x7D, 0xBF, 0x9F, 0xEA, 0x00, 0x73, 0x1E, 0xA8, 0x30, 0x70,
|
||||
0x6B, 0x0F, 0x5D, 0x13, 0x40, 0x89, 0xFA, 0x36, 0x38, 0xD5, 0x25, 0x50, 0xD7, 0xB7, 0xEF, 0xF6,
|
||||
0x85, 0x52, 0xFD, 0x70, 0x30, 0xD5, 0xBF, 0x07, 0x9C, 0x3E, 0x78, 0x78, 0x88, 0xBD, 0x2D, 0xB0,
|
||||
0x92, 0x8C, 0x1C, 0x2F, 0xE5, 0x15, 0x1F, 0x1D, 0xEC, 0x46, 0x2E, 0x53, 0xE5, 0x1F, 0x70, 0x1B,
|
||||
0x07, 0x51, 0xF1, 0x41, 0x28, 0xBD, 0x4D, 0xF2, 0x48, 0x4E, 0xD5, 0xBA, 0x19, 0x0F, 0x68, 0x18,
|
||||
0x05, 0x0F, 0x6C, 0xA8, 0xCB, 0x11, 0xD9, 0xE5, 0xC9, 0xE0, 0x4C, 0x15, 0x89, 0x48, 0xFA, 0x68,
|
||||
0x90, 0x3F, 0xD9, 0xCF, 0x30, 0xA9, 0x57, 0x1B, 0x5F, 0x15, 0x15, 0x2E, 0xFC, 0x5B, 0x02, 0xD3,
|
||||
0xDD, 0xA2, 0xEF, 0x74, 0x79, 0xDF, 0x79, 0xD1, 0xDE, 0x4F, 0x29, 0xEB, 0x1E, 0xAC, 0xE1, 0x74,
|
||||
0x0F, 0xDA, 0x70, 0x14, 0xF9, 0x6D, 0x67, 0x06, 0xD3, 0x96, 0x37, 0x11, 0x09, 0x23, 0xDC, 0x3B,
|
||||
0x6F, 0x73, 0x03, 0x91, 0x7F, 0xA8, 0x3E, 0xDE, 0x25, 0x75, 0x52, 0x35, 0x8A, 0x99, 0x73, 0x32,
|
||||
0xCB, 0x9B, 0x27, 0x5F, 0x35, 0x6B, 0x4E, 0xD6, 0x6A, 0xBB, 0x4B, 0xD2, 0x70, 0x4B, 0x6C, 0x4C,
|
||||
0x3C, 0xFE, 0xD2, 0xE3, 0xA6, 0x80, 0xE4, 0x78, 0x25, 0x26, 0x4A, 0x5B, 0x1E, 0xED, 0x82, 0x4D,
|
||||
0x7D, 0x17, 0x6C, 0xF2, 0x1A, 0x15, 0xE1, 0x39, 0xFD, 0x46, 0x9D, 0xA6, 0x56, 0x3F, 0xFB, 0x96,
|
||||
0xF0, 0x74, 0x06, 0x9B, 0xD7, 0x34, 0xE0, 0x51, 0xAD, 0xAB, 0x77, 0xFB, 0xA9, 0x69, 0x7C, 0xB2,
|
||||
0x07, 0xD6, 0xB4, 0x9D, 0x2A, 0x98, 0x30, 0xEA, 0xD0, 0x4B, 0xB1, 0xD1, 0x16, 0x68, 0x8C, 0xB8,
|
||||
0xE2, 0xBF, 0xEF, 0x09, 0x8D, 0xD1, 0xC3, 0xD1, 0xF8, 0xCA, 0x1D, 0x66, 0xF4, 0x3D, 0xE0, 0x13,
|
||||
0xA0, 0xD1, 0x87, 0x6E, 0x1F, 0x6D, 0x8C, 0x51, 0xC2, 0xA7, 0x5A, 0xEF, 0xD1, 0x48, 0x79, 0xF1,
|
||||
0xFA, 0x72, 0x2F, 0x58, 0xA5, 0x93, 0x1E, 0x06, 0xAF, 0xCC, 0xE4, 0x43, 0x63, 0xE6, 0x61, 0x7F,
|
||||
0xF3, 0xA4, 0xE2, 0x4C, 0xAA, 0xF5, 0x0A, 0xFB, 0xA1, 0xD2, 0xA6, 0x41, 0xB2, 0xED, 0x68, 0x2F,
|
||||
0xA8, 0x89, 0x99, 0x0F, 0x03, 0x99, 0x34, 0xFA, 0xD0, 0x78, 0xF5, 0xFA, 0x24, 0x08, 0x68, 0xB0,
|
||||
0x31, 0x64, 0x09, 0x9F, 0x6A, 0xBD, 0x2C, 0xBF, 0x16, 0xA3, 0xBD, 0xC0, 0x95, 0xCE, 0x7A, 0x18,
|
||||
0xC4, 0x32, 0x9B, 0x0F, 0x0D, 0xDA, 0xD0, 0xF5, 0xC8, 0x60, 0x63, 0xC8, 0x04, 0x97, 0x6A, 0xFD,
|
||||
0x56, 0x7E, 0x0E, 0x9F, 0x7B, 0x81, 0x4B, 0xCE, 0x78, 0x18, 0xB0, 0x12, 0x6B, 0x0F, 0x0D, 0x95,
|
||||
0x63, 0x8F, 0x36, 0x06, 0x0A, 0x78, 0x54, 0xEB, 0xBA, 0xFD, 0xBB, 0xA2, 0x5D, 0xD3, 0x91, 0xCF,
|
||||
0x5F, 0xFC, 0x53, 0x6E, 0xDE, 0xE8, 0x7B, 0x41, 0x8C, 0x4F, 0x7D, 0x18, 0xBC, 0x84, 0xD1, 0x87,
|
||||
0x46, 0x4B, 0xBC, 0x04, 0xDC, 0x41, 0x9B, 0x97, 0xC3, 0x94, 0x91, 0xBF, 0xFB, 0x02, 0x23, 0xE5,
|
||||
0x0A, 0xED, 0xA7, 0x20, 0x66, 0xF3, 0xEE, 0x63, 0xD1, 0x3E, 0x33, 0xF2, 0xD0, 0x38, 0xB9, 0xC8,
|
||||
0xC6, 0x1F, 0x1C, 0xCC, 0xB6, 0x79, 0xF1, 0x22, 0xC7, 0xAB, 0x5A, 0xCF, 0xE1, 0x40, 0xB9, 0x16,
|
||||
0x07, 0xFB, 0x5A, 0x72, 0xE4, 0xE7, 0xDF, 0x07, 0x6A, 0x05, 0x7B, 0xBF, 0x0B, 0xE0, 0x60, 0x81,
|
||||
0x47, 0xBB, 0xFE, 0x56, 0xEF, 0x53, 0x17, 0xD8, 0x13, 0xF8, 0xDE, 0xCB, 0xE3, 0xFD, 0x02, 0x38,
|
||||
0x53, 0x62, 0x6F, 0x18, 0xE6, 0xEC, 0xDE, 0x07, 0x8C, 0xE9, 0x66, 0x04, 0xF1, 0x58, 0x40, 0xEE,
|
||||
0x41, 0x5E, 0x87, 0x94, 0x24, 0x93, 0x8F, 0x6E, 0x30, 0x2B, 0x87, 0x8C, 0x78, 0x9E, 0x6A, 0xBD,
|
||||
0xC0, 0x4C, 0xB9, 0xE5, 0xC3, 0xF3, 0x63, 0x49, 0xF0, 0x70, 0x29, 0xC9, 0x0B, 0xFF, 0x7C, 0xDF,
|
||||
0x38, 0xEA, 0xAB, 0xD6, 0x2D, 0xDF, 0x44, 0x0D, 0xB2, 0xF8, 0xD1, 0xE6, 0xC2, 0x84, 0x13, 0xB1,
|
||||
0x1F, 0x50, 0x50, 0x2A, 0x03, 0x29, 0xD9, 0xAA, 0xAA, 0x2A, 0xE9, 0x28, 0x77, 0xCE, 0xBA, 0x11,
|
||||
0xC4, 0x0A, 0x8F, 0xB2, 0xF5, 0xD3, 0xF1, 0x6F, 0x61, 0xED, 0xD5, 0x5F, 0xD6, 0x9E, 0x1F, 0xFB,
|
||||
0x68, 0x89, 0xBB, 0x57, 0xA0, 0x70, 0x2E, 0x77, 0xB1, 0xAF, 0x10, 0x95, 0x6D, 0xA6, 0x10, 0x9E,
|
||||
0x98, 0xED, 0xA7, 0xC9, 0xCC, 0x9A, 0xDB, 0x67, 0x93, 0x3E, 0xB0, 0x7D, 0x58, 0xD2, 0x8A, 0x1D,
|
||||
0x37, 0x49, 0x3F, 0xE4, 0xC3, 0xCC, 0xFD, 0xFF, 0xFB, 0xEF, 0xBA, 0x98, 0x21, 0xFD, 0x6E, 0x4E,
|
||||
0x31, 0x55, 0x09, 0x03, 0xBB, 0xA5, 0xAE, 0xDA, 0x9A, 0xB1, 0xC2, 0xF2, 0xE3, 0x65, 0xA6, 0xCF,
|
||||
0x11, 0x2F, 0xF1, 0xF5, 0x79, 0x68, 0x07, 0x64, 0xC0, 0xAC, 0x7F, 0x39, 0xD4, 0x8E, 0xFA, 0xD8,
|
||||
0x67, 0x15, 0xE4, 0x38, 0x37, 0x43, 0x18, 0xBC, 0x22, 0x21, 0xC3, 0xE0, 0x05, 0xAD, 0x74, 0xFD,
|
||||
0xF6, 0x75, 0x5B, 0x6E, 0x51, 0x79, 0x45, 0x91, 0x83, 0x9D, 0x92, 0xE1, 0x46, 0xBE, 0x90, 0xA3,
|
||||
0xE9, 0xD3, 0x74, 0xA8, 0x74, 0xB4, 0x2B, 0x7D, 0xEA, 0x41, 0xD0, 0xB6, 0x9B, 0xB2, 0x3C, 0x68,
|
||||
0x57, 0x15, 0x9E, 0xE3, 0xFA, 0xD4, 0x46, 0x21, 0x2E, 0xA5, 0x89, 0x5E, 0x32, 0xDB, 0xAD, 0xAB,
|
||||
0x4A, 0xB2, 0xF6, 0xB9, 0xA8, 0xF1, 0x0D, 0x4F, 0x60, 0xF4, 0x5D, 0x53, 0x10, 0x89, 0x47, 0x8A,
|
||||
0x25, 0x53, 0x8C, 0xE5, 0x97, 0xF3, 0x65, 0xEA, 0x63, 0xC9, 0x22, 0x1E, 0x5C, 0xE6, 0x89, 0x65,
|
||||
0x64, 0xA5, 0xD4, 0x51, 0xA7, 0x4F, 0x18, 0xA7, 0x2C, 0xD5, 0x4A, 0x09, 0x55, 0x52, 0x4A, 0xCC,
|
||||
0x00, 0xB3, 0x28, 0xF0, 0x9B, 0x31, 0x00, 0x1B, 0x32, 0xE5, 0xBA, 0xF5, 0xF1, 0x87, 0xA9, 0x1D,
|
||||
0x1F, 0x8B, 0x97, 0x5D, 0xA9, 0x77, 0x31, 0x44, 0x41, 0xEB, 0x87, 0xE9, 0x55, 0x85, 0x38, 0xF1,
|
||||
0x63, 0x98, 0x03, 0xC6, 0xED, 0xF8, 0x63, 0xD3, 0xE5, 0xFF, 0x71, 0x41, 0xBB, 0xD6, 0x2B, 0xAC,
|
||||
0x87, 0x7D, 0xED, 0xA6, 0x65, 0x4D, 0x39, 0x37, 0xF5, 0x70, 0xC5, 0xA3, 0x5D, 0xED, 0x63, 0x80,
|
||||
0x3F, 0x47, 0x18, 0x84, 0x31, 0xAA, 0xFC, 0x30, 0xBD, 0x8E, 0x15, 0x97, 0xF8, 0x24, 0xEC, 0x61,
|
||||
0xC7, 0x50, 0x42, 0x86, 0x58, 0x14, 0x9A, 0x70, 0xFA, 0xA6, 0x22, 0xC7, 0xF1, 0x47, 0x3D, 0xD6,
|
||||
0x63, 0x98, 0x46, 0xB1, 0x5B, 0x99, 0x97, 0x3D, 0x6A, 0x8B, 0x57, 0x3A, 0x2B, 0x34, 0x20, 0x5D,
|
||||
0xE2, 0x37, 0xA5, 0x6E, 0xB8, 0x75, 0x05, 0x33, 0x81, 0x7B, 0x78, 0x48, 0x71, 0x00, 0x38, 0x1A,
|
||||
0x5A, 0x49, 0xC6, 0x61, 0x49, 0x8F, 0x0D, 0x77, 0x81, 0x20, 0xC0, 0x7D, 0x3A, 0xC4, 0x79, 0x9A,
|
||||
0xEE, 0x72, 0x21, 0x69, 0x7E, 0x96, 0x74, 0xE3, 0x2A, 0xDB, 0x6B, 0xDE, 0x3A, 0xAA, 0xC6, 0x46,
|
||||
0x6F, 0xA5, 0xD0, 0x15, 0x3C, 0xB5, 0xD8, 0x20, 0x2D, 0xED, 0xCA, 0x68, 0x1B, 0xD7, 0x3A, 0x70,
|
||||
0x5E, 0xB7, 0x8E, 0x34, 0x3F, 0xF2, 0xBC, 0xA3, 0xD6, 0xB5, 0xFE, 0xF7, 0xDF, 0xD7, 0x4D, 0x1E,
|
||||
0x04, 0x37, 0xCD, 0x19, 0xE2, 0xAD, 0x56, 0x4B, 0x86, 0xC2, 0x05, 0x38, 0x32, 0xC3, 0xDE, 0x68,
|
||||
0xB7, 0x8E, 0x8E, 0xDA, 0x46, 0x76, 0xDC, 0x6A, 0xEB, 0xA6, 0xB8, 0x2E, 0x80, 0x36, 0x92, 0x4F,
|
||||
0x38, 0x6B, 0x5C, 0x3F, 0x7E, 0x7C, 0x73, 0xD4, 0x6A, 0xB5, 0x2F, 0x78, 0x88, 0x99, 0x47, 0x70,
|
||||
0xA8, 0x95, 0x10, 0xB6, 0xA5, 0x5C, 0xE2, 0x5C, 0xB4, 0x2F, 0xB0, 0x36, 0xD4, 0x4D, 0x97, 0xFF,
|
||||
0x29, 0xA1, 0x6E, 0xFE, 0x82, 0xE6, 0x6A, 0x4C, 0x37, 0xB0, 0x16, 0xEA, 0x20, 0x1C, 0xF3, 0xB1,
|
||||
0x2B, 0xC6, 0xA5, 0xF4, 0xAD, 0xA4, 0x1C, 0xAD, 0xAB, 0x8D, 0x75, 0x13, 0xF3, 0x3F, 0xA5, 0x62,
|
||||
0xE3, 0x48, 0x69, 0x60, 0xDE, 0xF6, 0x45, 0x4F, 0xF3, 0x75, 0xB3, 0x0B, 0x7F, 0x74, 0x3D, 0x6E,
|
||||
0x66, 0x70, 0x42, 0x34, 0x04, 0x93, 0x5B, 0x11, 0xB1, 0x34, 0xB8, 0xF4, 0x3C, 0xAD, 0x24, 0x77,
|
||||
0xE0, 0x95, 0xF4, 0x0A, 0x74, 0xA2, 0x1B, 0xC4, 0xB3, 0x41, 0xF8, 0x98, 0xFA, 0xB6, 0x47, 0xEC,
|
||||
0xBB, 0x96, 0xC6, 0x1D, 0x87, 0x21, 0x45, 0xE4, 0xDE, 0xE0, 0x37, 0xD4, 0xC1, 0x7A, 0x1C, 0x83,
|
||||
0x7A, 0x22, 0xEE, 0x64, 0x84, 0xCA, 0xF0, 0xF9, 0x98, 0xC4, 0x60, 0x96, 0x73, 0x90, 0x66, 0x32,
|
||||
0xA2, 0x95, 0xAB, 0xCA, 0xA7, 0x90, 0x27, 0x61, 0xBC, 0x84, 0xE4, 0x3E, 0xD5, 0x8A, 0x3D, 0x36,
|
||||
0xA7, 0x63, 0x1B, 0x94, 0x22, 0x1A, 0x80, 0xF2, 0x67, 0x1B, 0xEC, 0xFD, 0xCB, 0x38, 0xAA, 0xF1,
|
||||
0xD0, 0xD5, 0x93, 0xE8, 0xFC, 0x34, 0x0B, 0x5F, 0xE8, 0x53, 0x37, 0x1E, 0xE6, 0xC3, 0xAB, 0xC9,
|
||||
0xCF, 0x10, 0x5C, 0xB2, 0x72, 0x41, 0x98, 0xDC, 0xAD, 0xA3, 0x99, 0x95, 0x57, 0xA0, 0xF6, 0x56,
|
||||
0x53, 0x67, 0x9D, 0x10, 0xC8, 0xFA, 0xAB, 0xC9, 0x0A, 0xAD, 0x0E, 0x48, 0xFD, 0xD5, 0xA4, 0xB9,
|
||||
0x46, 0x06, 0x84, 0x74, 0x35, 0x61, 0xBE, 0x7C, 0x03, 0xE5, 0x40, 0x82, 0x35, 0x22, 0xBE, 0x43,
|
||||
0x47, 0x90, 0xD3, 0x74, 0xA0, 0x81, 0x4A, 0x15, 0xE2, 0x83, 0x0D, 0x2F, 0x7F, 0x7D, 0xFD, 0xAA,
|
||||
0x55, 0xCA, 0x37, 0xD8, 0x52, 0x6C, 0x7C, 0x96, 0x0C, 0x9F, 0x2A, 0xBC, 0x8E, 0x73, 0x28, 0x7F,
|
||||
0x2A, 0x99, 0x67, 0xB5, 0x12, 0x07, 0x94, 0x53, 0x7C, 0x84, 0x18, 0xBC, 0x5B, 0x90, 0x40, 0x07,
|
||||
0x99, 0x80, 0xA6, 0x57, 0x0C, 0x13, 0x3E, 0xDF, 0x4C, 0x18, 0x54, 0x2E, 0x34, 0x00, 0xF8, 0xF1,
|
||||
0xC5, 0x07, 0xBB, 0x03, 0xD5, 0xEA, 0x1A, 0x31, 0x5C, 0xF1, 0xE9, 0x08, 0xC2, 0x40, 0x4A, 0x8E,
|
||||
0x0D, 0xBA, 0xC8, 0x8F, 0xC5, 0x85, 0x7E, 0xF1, 0x82, 0x84, 0xF5, 0xAA, 0x38, 0x3D, 0x04, 0x7B,
|
||||
0x4E, 0xB5, 0xE6, 0xD5, 0x05, 0xB0, 0x9B, 0x9F, 0x41, 0xBA, 0xE1, 0x17, 0xB9, 0x3B, 0x90, 0x04,
|
||||
0xB1, 0xB1, 0x55, 0x9C, 0x65, 0xB9, 0xD0, 0xE3, 0x05, 0x5F, 0x88, 0xE3, 0xB9, 0x9D, 0x45, 0x5A,
|
||||
0xB0, 0x1A, 0x1C, 0x9E, 0xDF, 0xBA, 0x11, 0xDE, 0x4B, 0x90, 0xFB, 0x66, 0x15, 0x68, 0xD9, 0x3D,
|
||||
0x41, 0x36, 0xFF, 0xBD, 0x5F, 0x49, 0x6F, 0x06, 0x45, 0xBD, 0xC0, 0xCC, 0x40, 0x37, 0x82, 0xAC,
|
||||
0x63, 0xAD, 0xA8, 0x28, 0x71, 0xA2, 0x79, 0x74, 0x8F, 0x62, 0x98, 0x6B, 0x3E, 0xBC, 0x97, 0x20,
|
||||
0xFF, 0x4E, 0x05, 0xE8, 0x12, 0x2D, 0xE8, 0x12, 0xE9, 0x46, 0x94, 0xE9, 0x92, 0x95, 0xBD, 0x74,
|
||||
0xF6, 0xD1, 0x3D, 0xC2, 0xD3, 0x82, 0xA7, 0x1B, 0xE3, 0xD5, 0x54, 0x85, 0x57, 0x24, 0x41, 0x81,
|
||||
0xD1, 0x82, 0x02, 0x23, 0xDD, 0x18, 0x65, 0x0A, 0x64, 0x25, 0x33, 0x55, 0x60, 0xB2, 0x26, 0xFD,
|
||||
0xE4, 0x0D, 0x15, 0xE8, 0xF0, 0x65, 0x0D, 0xE1, 0xAC, 0xF8, 0xEA, 0xC6, 0xE5, 0x3D, 0xB4, 0xE9,
|
||||
0x1E, 0x4F, 0xD0, 0xF5, 0x72, 0x41, 0xD7, 0x4B, 0xDD, 0x78, 0x72, 0x7E, 0x29, 0x1B, 0x09, 0x14,
|
||||
0x6F, 0xA2, 0x4D, 0x78, 0x45, 0x33, 0x88, 0xF6, 0x85, 0x7F, 0x42, 0xF0, 0x4E, 0xE6, 0x58, 0x92,
|
||||
0xBA, 0x9A, 0x31, 0x5D, 0x68, 0xC8, 0xC3, 0x01, 0xD3, 0x4A, 0xEF, 0x3C, 0x0C, 0xAB, 0x8C, 0xE4,
|
||||
0xAD, 0x4B, 0xA5, 0xFD, 0xF3, 0x73, 0x85, 0x06, 0x8A, 0xF8, 0x0F, 0x03, 0x4A, 0x90, 0xED, 0x50,
|
||||
0x55, 0xE4, 0x26, 0x72, 0x05, 0xF3, 0x7F, 0xCB, 0x01, 0x21, 0xA5, 0xB0, 0x1E, 0x09, 0x15, 0x17,
|
||||
0xF3, 0xFD, 0x1B, 0xF8, 0x88, 0x63, 0x4F, 0x89, 0xA3, 0x24, 0x5A, 0xE8, 0x26, 0x3F, 0xD2, 0x3A,
|
||||
0xDA, 0x44, 0x37, 0x8E, 0x26, 0xA9, 0x47, 0x41, 0x4B, 0xDE, 0x5B, 0x32, 0x15, 0x41, 0xC7, 0x2F,
|
||||
0x07, 0xD1, 0xF1, 0x4B, 0x41, 0xC7, 0x2F, 0x00, 0xD8, 0x2C, 0x03, 0x7A, 0x52, 0x43, 0x30, 0xA3,
|
||||
0xAA, 0x27, 0xBD, 0x10, 0x5A, 0x57, 0x33, 0xBF, 0xCC, 0x4C, 0x16, 0x95, 0xF2, 0x48, 0x6E, 0xD7,
|
||||
0x3E, 0x3F, 0x16, 0xFF, 0x6A, 0xEE, 0xFF, 0x81, 0x09, 0x07, 0x8B, 0x81, 0x4E, 0x00, 0x00
|
||||
};
|
97
libraries/ESP32/examples/FreeRTOS/FreeRTOS.ino
Normal file
97
libraries/ESP32/examples/FreeRTOS/FreeRTOS.ino
Normal file
@ -0,0 +1,97 @@
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
#define ARDUINO_RUNNING_CORE 0
|
||||
#else
|
||||
#define ARDUINO_RUNNING_CORE 1
|
||||
#endif
|
||||
|
||||
#ifndef LED_BUILTIN
|
||||
#define LED_BUILTIN 13
|
||||
#endif
|
||||
|
||||
// define two tasks for Blink & AnalogRead
|
||||
void TaskBlink( void *pvParameters );
|
||||
void TaskAnalogReadA3( void *pvParameters );
|
||||
|
||||
// the setup function runs once when you press reset or power the board
|
||||
void setup() {
|
||||
|
||||
// initialize serial communication at 115200 bits per second:
|
||||
Serial.begin(115200);
|
||||
|
||||
// Now set up two tasks to run independently.
|
||||
xTaskCreatePinnedToCore(
|
||||
TaskBlink
|
||||
, "TaskBlink" // A name just for humans
|
||||
, 1024 // This stack size can be checked & adjusted by reading the Stack Highwater
|
||||
, NULL
|
||||
, 2 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
|
||||
, NULL
|
||||
, ARDUINO_RUNNING_CORE);
|
||||
|
||||
xTaskCreatePinnedToCore(
|
||||
TaskAnalogReadA3
|
||||
, "AnalogReadA3"
|
||||
, 1024 // Stack size
|
||||
, NULL
|
||||
, 1 // Priority
|
||||
, NULL
|
||||
, ARDUINO_RUNNING_CORE);
|
||||
|
||||
// Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Empty. Things are done in Tasks.
|
||||
}
|
||||
|
||||
/*--------------------------------------------------*/
|
||||
/*---------------------- Tasks ---------------------*/
|
||||
/*--------------------------------------------------*/
|
||||
|
||||
void TaskBlink(void *pvParameters) // This is a task.
|
||||
{
|
||||
(void) pvParameters;
|
||||
|
||||
/*
|
||||
Blink
|
||||
Turns on an LED on for one second, then off for one second, repeatedly.
|
||||
|
||||
If you want to know what pin the on-board LED is connected to on your ESP32 model, check
|
||||
the Technical Specs of your board.
|
||||
*/
|
||||
|
||||
// initialize digital LED_BUILTIN on pin 13 as an output.
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
|
||||
for (;;) // A Task shall never return or exit.
|
||||
{
|
||||
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
|
||||
vTaskDelay(100); // one tick delay (15ms) in between reads for stability
|
||||
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
|
||||
vTaskDelay(100); // one tick delay (15ms) in between reads for stability
|
||||
}
|
||||
}
|
||||
|
||||
void TaskAnalogReadA3(void *pvParameters) // This is a task.
|
||||
{
|
||||
(void) pvParameters;
|
||||
|
||||
/*
|
||||
AnalogReadSerial
|
||||
Reads an analog input on pin A3, prints the result to the serial monitor.
|
||||
Graphical representation is available using serial plotter (Tools > Serial Plotter menu)
|
||||
Attach the center pin of a potentiometer to pin A3, and the outside pins to +5V and ground.
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// read the input on analog pin A3:
|
||||
int sensorValueA3 = analogRead(A3);
|
||||
// print out the value you read:
|
||||
Serial.println(sensorValueA3);
|
||||
vTaskDelay(10); // one tick delay (15ms) in between reads for stability
|
||||
}
|
||||
}
|
71
libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
Normal file
71
libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This is an example to read analog data at high frequency using the I2S peripheral
|
||||
* Run a wire between pins 27 & 32
|
||||
* The readings from the device will be 12bit (0-4096)
|
||||
*/
|
||||
#include <driver/i2s.h>
|
||||
|
||||
#define I2S_SAMPLE_RATE 78125
|
||||
#define ADC_INPUT ADC1_CHANNEL_4 //pin 32
|
||||
#define OUTPUT_PIN 27
|
||||
#define OUTPUT_VALUE 3800
|
||||
#define READ_DELAY 10000 //microseconds
|
||||
|
||||
void i2sInit()
|
||||
{
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
|
||||
.sample_rate = I2S_SAMPLE_RATE, // The format of the signal using ADC_BUILT_IN
|
||||
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, // is fixed at 12bit, stereo, MSB
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
|
||||
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 4,
|
||||
.dma_buf_len = 8,
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = false,
|
||||
.fixed_mclk = 0
|
||||
};
|
||||
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
|
||||
i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT);
|
||||
i2s_adc_enable(I2S_NUM_0);
|
||||
}
|
||||
|
||||
void reader(void *pvParameters) {
|
||||
uint32_t read_counter = 0;
|
||||
uint64_t read_sum = 0;
|
||||
while(1){
|
||||
size_t bytes_read = 0;
|
||||
uint16_t buffer = 0;
|
||||
i2s_read(I2S_NUM_0, &buffer, sizeof(buffer), &bytes_read, portMAX_DELAY);
|
||||
buffer = ~buffer; // The data is inverted
|
||||
//Serial.println(buffer % 0x1000);
|
||||
read_sum += buffer % 0x1000; // The 4 high bits are the channel
|
||||
read_counter++;
|
||||
if (bytes_read != sizeof(buffer)) Serial.println("buffer empty!");
|
||||
if (read_counter == I2S_SAMPLE_RATE) {
|
||||
Serial.printf("avg: %d\n", read_sum/I2S_SAMPLE_RATE);
|
||||
read_counter = 0;
|
||||
read_sum = 0;
|
||||
i2s_adc_disable(I2S_NUM_0);
|
||||
delay(READ_DELAY);
|
||||
i2s_adc_enable(I2S_NUM_0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
// Put a signal out on pin
|
||||
uint32_t freq = ledcSetup(0, I2S_SAMPLE_RATE, 10);
|
||||
Serial.printf("Output frequency: %d\n", freq);
|
||||
ledcWrite(0, OUTPUT_VALUE/4);
|
||||
ledcAttachPin(OUTPUT_PIN, 0);
|
||||
// Initialize the I2S peripheral
|
||||
i2sInit();
|
||||
// Create a task that will read the data
|
||||
xTaskCreatePinnedToCore(reader, "ADC_reader", 2048, NULL, 1, NULL, 1);
|
||||
}
|
||||
|
||||
void loop() {}
|
@ -43,6 +43,14 @@ License (MIT license):
|
||||
#include <functional>
|
||||
#include "esp_wifi.h"
|
||||
|
||||
// Add quotes around defined value
|
||||
#ifdef __IN_ECLIPSE__
|
||||
#define STR_EXPAND(tok) #tok
|
||||
#define STR(tok) STR_EXPAND(tok)
|
||||
#else
|
||||
#define STR(tok) tok
|
||||
#endif
|
||||
|
||||
static void _on_sys_event(system_event_t *event){
|
||||
mdns_handle_system_event(NULL, event);
|
||||
}
|
||||
@ -82,7 +90,7 @@ void MDNSResponder::setInstanceName(String name) {
|
||||
|
||||
void MDNSResponder::enableArduino(uint16_t port, bool auth){
|
||||
mdns_txt_item_t arduTxtData[4] = {
|
||||
{(char*)"board" ,(char*)ARDUINO_VARIANT},
|
||||
{(char*)"board" ,(char*)STR(ARDUINO_VARIANT)},
|
||||
{(char*)"tcp_check" ,(char*)"no"},
|
||||
{(char*)"ssh_upload" ,(char*)"no"},
|
||||
{(char*)"auth_upload" ,(char*)"no"}
|
||||
|
@ -966,14 +966,14 @@ bool HTTPClient::connect(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
// set Timeout for WiFiClient and for Stream::readBytesUntil() and Stream::readStringUntil()
|
||||
_client->setTimeout((_tcpTimeout + 500) / 1000);
|
||||
|
||||
if(!_client->connect(_host.c_str(), _port)) {
|
||||
log_d("failed connect to %s:%u", _host.c_str(), _port);
|
||||
return false;
|
||||
}
|
||||
|
||||
// set Timeout for WiFiClient and for Stream::readBytesUntil() and Stream::readStringUntil()
|
||||
_client->setTimeout((_tcpTimeout + 500) / 1000);
|
||||
|
||||
log_d(" connected to %s:%u", _host.c_str(), _port);
|
||||
|
||||
#ifdef HTTPCLIENT_1_1_COMPATIBLE
|
||||
|
@ -56,7 +56,7 @@ void loop() {
|
||||
|
||||
switch (ret) {
|
||||
case HTTP_UPDATE_FAILED:
|
||||
Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
|
||||
Serial.printf("HTTP_UPDATE_FAILED Error (%d): %s\n", httpUpdate.getLastError(), httpUpdate.getLastErrorString().c_str());
|
||||
break;
|
||||
|
||||
case HTTP_UPDATE_NO_UPDATES:
|
||||
|
@ -49,14 +49,20 @@ HTTPUpdate::~HTTPUpdate(void)
|
||||
HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& url, const String& currentVersion)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.begin(client, url);
|
||||
if(!http.begin(client, url))
|
||||
{
|
||||
return HTTP_UPDATE_FAILED;
|
||||
}
|
||||
return handleUpdate(http, currentVersion, false);
|
||||
}
|
||||
|
||||
HTTPUpdateResult HTTPUpdate::updateSpiffs(WiFiClient& client, const String& url, const String& currentVersion)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.begin(client, url);
|
||||
if(!http.begin(client, url))
|
||||
{
|
||||
return HTTP_UPDATE_FAILED;
|
||||
}
|
||||
return handleUpdate(http, currentVersion, true);
|
||||
}
|
||||
|
||||
@ -64,7 +70,10 @@ HTTPUpdateResult HTTPUpdate::update(WiFiClient& client, const String& host, uint
|
||||
const String& currentVersion)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.begin(client, host, port, uri);
|
||||
if(!http.begin(client, host, port, uri))
|
||||
{
|
||||
return HTTP_UPDATE_FAILED;
|
||||
}
|
||||
return handleUpdate(http, currentVersion, false);
|
||||
}
|
||||
|
||||
@ -93,31 +102,33 @@ String HTTPUpdate::getLastErrorString(void)
|
||||
StreamString error;
|
||||
Update.printError(error);
|
||||
error.trim(); // remove line ending
|
||||
return String(F("Update error: ")) + error;
|
||||
return String("Update error: ") + error;
|
||||
}
|
||||
|
||||
// error from http client
|
||||
if(_lastError > -100) {
|
||||
return String(F("HTTP error: ")) + HTTPClient::errorToString(_lastError);
|
||||
return String("HTTP error: ") + HTTPClient::errorToString(_lastError);
|
||||
}
|
||||
|
||||
switch(_lastError) {
|
||||
case HTTP_UE_TOO_LESS_SPACE:
|
||||
return F("Not Enough space");
|
||||
return "Not Enough space";
|
||||
case HTTP_UE_SERVER_NOT_REPORT_SIZE:
|
||||
return F("Server Did Not Report Size");
|
||||
return "Server Did Not Report Size";
|
||||
case HTTP_UE_SERVER_FILE_NOT_FOUND:
|
||||
return F("File Not Found (404)");
|
||||
return "File Not Found (404)";
|
||||
case HTTP_UE_SERVER_FORBIDDEN:
|
||||
return F("Forbidden (403)");
|
||||
return "Forbidden (403)";
|
||||
case HTTP_UE_SERVER_WRONG_HTTP_CODE:
|
||||
return F("Wrong HTTP Code");
|
||||
return "Wrong HTTP Code";
|
||||
case HTTP_UE_SERVER_FAULTY_MD5:
|
||||
return F("Wrong MD5");
|
||||
return "Wrong MD5";
|
||||
case HTTP_UE_BIN_VERIFY_HEADER_FAILED:
|
||||
return F("Verify Bin Header Failed");
|
||||
return "Verify Bin Header Failed";
|
||||
case HTTP_UE_BIN_FOR_WRONG_FLASH:
|
||||
return F("New Binary Does Not Fit Flash Size");
|
||||
return "New Binary Does Not Fit Flash Size";
|
||||
case HTTP_UE_NO_PARTITION:
|
||||
return "Partition Could Not be Found";
|
||||
}
|
||||
|
||||
return String();
|
||||
@ -164,29 +175,32 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
|
||||
// use HTTP/1.0 for update since the update handler not support any transfer Encoding
|
||||
http.useHTTP10(true);
|
||||
http.setTimeout(_httpClientTimeout);
|
||||
http.setUserAgent(F("ESP32-http-Update"));
|
||||
http.addHeader(F("Cache-Control"), F("no-cache"));
|
||||
http.addHeader(F("x-ESP32-STA-MAC"), WiFi.macAddress());
|
||||
http.addHeader(F("x-ESP32-AP-MAC"), WiFi.softAPmacAddress());
|
||||
http.addHeader(F("x-ESP32-free-space"), String(ESP.getFreeSketchSpace()));
|
||||
http.addHeader(F("x-ESP32-sketch-size"), String(ESP.getSketchSize()));
|
||||
// To do http.addHeader(F("x-ESP32-sketch-md5"), String(ESP.getSketchMD5()));
|
||||
// Sketch MD5 is not supported by the core, but SHA256 is, so add a SHA256 instead
|
||||
http.setUserAgent("ESP32-http-Update");
|
||||
http.addHeader("Cache-Control", "no-cache");
|
||||
http.addHeader("x-ESP32-STA-MAC", WiFi.macAddress());
|
||||
http.addHeader("x-ESP32-AP-MAC", WiFi.softAPmacAddress());
|
||||
http.addHeader("x-ESP32-free-space", String(ESP.getFreeSketchSpace()));
|
||||
http.addHeader("x-ESP32-sketch-size", String(ESP.getSketchSize()));
|
||||
String sketchMD5 = ESP.getSketchMD5();
|
||||
if(sketchMD5.length() != 0) {
|
||||
http.addHeader("x-ESP32-sketch-md5", sketchMD5);
|
||||
}
|
||||
// Add also a SHA256
|
||||
String sketchSHA256 = getSketchSHA256();
|
||||
if(sketchSHA256.length() != 0) {
|
||||
http.addHeader(F("x-ESP32-sketch-sha256"), sketchSHA256);
|
||||
http.addHeader("x-ESP32-sketch-sha256", sketchSHA256);
|
||||
}
|
||||
http.addHeader(F("x-ESP32-chip-size"), String(ESP.getFlashChipSize()));
|
||||
http.addHeader(F("x-ESP32-sdk-version"), ESP.getSdkVersion());
|
||||
http.addHeader("x-ESP32-chip-size", String(ESP.getFlashChipSize()));
|
||||
http.addHeader("x-ESP32-sdk-version", ESP.getSdkVersion());
|
||||
|
||||
if(spiffs) {
|
||||
http.addHeader(F("x-ESP32-mode"), F("spiffs"));
|
||||
http.addHeader("x-ESP32-mode", "spiffs");
|
||||
} else {
|
||||
http.addHeader(F("x-ESP32-mode"), F("sketch"));
|
||||
http.addHeader("x-ESP32-mode", "sketch");
|
||||
}
|
||||
|
||||
if(currentVersion && currentVersion[0] != 0x00) {
|
||||
http.addHeader(F("x-ESP32-version"), currentVersion);
|
||||
http.addHeader("x-ESP32-version", currentVersion);
|
||||
}
|
||||
|
||||
const char * headerkeys[] = { "x-MD5" };
|
||||
@ -229,14 +243,25 @@ HTTPUpdateResult HTTPUpdate::handleUpdate(HTTPClient& http, const String& curren
|
||||
if(len > 0) {
|
||||
bool startUpdate = true;
|
||||
if(spiffs) {
|
||||
// To do size_t spiffsSize = ((size_t) &_SPIFFS_end - (size_t) &_SPIFFS_start);
|
||||
// To do if(len > (int) spiffsSize) {
|
||||
// To do log_e("spiffsSize to low (%d) needed: %d\n", spiffsSize, len);
|
||||
// To do startUpdate = false;
|
||||
// To do }
|
||||
const esp_partition_t* _partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_SPIFFS, NULL);
|
||||
if(!_partition){
|
||||
_lastError = HTTP_UE_NO_PARTITION;
|
||||
return HTTP_UPDATE_FAILED;
|
||||
}
|
||||
|
||||
if(len > _partition->size) {
|
||||
log_e("spiffsSize to low (%d) needed: %d\n", _partition->size, len);
|
||||
startUpdate = false;
|
||||
}
|
||||
} else {
|
||||
if(len > (int) ESP.getFreeSketchSpace()) {
|
||||
log_e("FreeSketchSpace to low (%d) needed: %d\n", ESP.getFreeSketchSpace(), len);
|
||||
int sketchFreeSpace = ESP.getFreeSketchSpace();
|
||||
if(!sketchFreeSpace){
|
||||
_lastError = HTTP_UE_NO_PARTITION;
|
||||
return HTTP_UPDATE_FAILED;
|
||||
}
|
||||
|
||||
if(len > sketchFreeSpace) {
|
||||
log_e("FreeSketchSpace to low (%d) needed: %d\n", sketchFreeSpace, len);
|
||||
startUpdate = false;
|
||||
}
|
||||
}
|
||||
@ -366,6 +391,8 @@ bool HTTPUpdate::runUpdate(Stream& in, uint32_t size, String md5, int command)
|
||||
}
|
||||
}
|
||||
|
||||
// To do: the SHA256 could be checked if the server sends it
|
||||
|
||||
if(Update.writeStream(in) != size) {
|
||||
_lastError = Update.getError();
|
||||
Update.printError(error);
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define HTTP_UE_SERVER_FAULTY_MD5 (-105)
|
||||
#define HTTP_UE_BIN_VERIFY_HEADER_FAILED (-106)
|
||||
#define HTTP_UE_BIN_FOR_WRONG_FLASH (-107)
|
||||
#define HTTP_UE_NO_PARTITION (-108)
|
||||
|
||||
enum HTTPUpdateResult {
|
||||
HTTP_UPDATE_FAILED,
|
||||
|
@ -16,7 +16,7 @@ extern "C" {
|
||||
#include "diskio.h"
|
||||
#include "ffconf.h"
|
||||
#include "ff.h"
|
||||
#include "esp_vfs.h"
|
||||
//#include "esp_vfs.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
char CRC7(const char* data, int length);
|
||||
unsigned short CRC16(const char* data, int length);
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/* The ESP32 has four SPi buses, however as of right now only two of
|
||||
* them are available to use, HSPI and VSPI. Simply using the SPI API
|
||||
* as illustrated in Arduino examples will use HSPI, leaving VSPI unused.
|
||||
* as illustrated in Arduino examples will use VSPI, leaving HSPI unused.
|
||||
*
|
||||
* However if we simply intialise two instance of the SPI class for both
|
||||
* of these buses both can be used. However when just using these the Arduino
|
||||
|
@ -214,6 +214,11 @@ void SPIClass::writeBytes(uint8_t * data, uint32_t size)
|
||||
spiEndTransaction(_spi);
|
||||
}
|
||||
|
||||
void SPIClass::transfer(uint8_t * data, uint32_t size)
|
||||
{
|
||||
transferBytes(data, data, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param data void *
|
||||
* @param size uint32_t
|
||||
|
@ -65,10 +65,11 @@ public:
|
||||
|
||||
void beginTransaction(SPISettings settings);
|
||||
void endTransaction(void);
|
||||
|
||||
void transfer(uint8_t * data, uint32_t size);
|
||||
uint8_t transfer(uint8_t data);
|
||||
uint16_t transfer16(uint16_t data);
|
||||
uint32_t transfer32(uint32_t data);
|
||||
|
||||
void transferBytes(uint8_t * data, uint8_t * out, uint32_t size);
|
||||
void transferBits(uint32_t data, uint32_t * out, uint8_t bits);
|
||||
|
||||
|
@ -39,11 +39,16 @@ bool SPIFFSFS::begin(bool formatOnFail, const char * basePath, uint8_t maxOpenFi
|
||||
.base_path = basePath,
|
||||
.partition_label = NULL,
|
||||
.max_files = maxOpenFiles,
|
||||
.format_if_mount_failed = formatOnFail
|
||||
.format_if_mount_failed = false
|
||||
};
|
||||
|
||||
esp_err_t err = esp_vfs_spiffs_register(&conf);
|
||||
if(err){
|
||||
if(err == ESP_FAIL && formatOnFail){
|
||||
if(format()){
|
||||
err = esp_vfs_spiffs_register(&conf);
|
||||
}
|
||||
}
|
||||
if(err != ESP_OK){
|
||||
log_e("Mounting SPIFFS failed! Error: %d", err);
|
||||
return false;
|
||||
}
|
||||
@ -65,7 +70,9 @@ void SPIFFSFS::end()
|
||||
|
||||
bool SPIFFSFS::format()
|
||||
{
|
||||
disableCore0WDT();
|
||||
esp_err_t err = esp_spiffs_format(NULL);
|
||||
enableCore0WDT();
|
||||
if(err){
|
||||
log_e("Formatting SPIFFS failed! Error: %d", err);
|
||||
return false;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|University|Board|Method|Result|
|
||||
|-------------|-------------| -----|------|
|
||||
|Technical University in Košice (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working|
|
||||
|Technical University in Košice (Slovakia)|ESP32 DevKitc v4|PEAP + MsCHAPv2|Working|
|
||||
|Technical University in Košice (Slovakia)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working on 6th attempt in loop|
|
||||
|Slovak Technical University in Bratislava (Slovakia)|ESP32 Devkit v1|PEAP + MsCHAPv2|Working|
|
||||
|University of Antwerp (Belgium)|Lolin32|PEAP + MsCHAPv2|Working|
|
||||
|UPV Universitat Politècnica de València (Spain)|ESP32 Devmodule v4|PEAP + MsCHAPv2|Working|
|
||||
@ -27,7 +27,8 @@
|
||||
|Universidad de Granada (Spain)|Lolin D32 Pro|PEAP + MsCHAPv2|Working|
|
||||
|Universidad de Granada (Spain)|Lolin D32|PEAP + MsCHAPv2|Working|
|
||||
|Universidade Federal de Santa Catarina (Brazil)|xxx|EAP-TTLS + MsCHAPv2|Working|
|
||||
|University of Regensburg (Germany)|Lolin32|PEAP + MsCHAPv2|Working|
|
||||
|University of Central Florida (Orlando, Florida)|ESP32 Built-in OLED – Heltec WiFi Kit 32|PEAP + MsCHAPv2|Working|
|
||||
|Université de Montpellier (France)|NodeMCU-32S|PEAP + MsCHAPv2|Working|
|
||||
|
||||
# Common errors - Switch to Debug mode for Serial monitor prints
|
||||
|Error|Appearance|Solution|
|
||||
|
@ -58,6 +58,11 @@ private:
|
||||
{
|
||||
if(!_buffer){
|
||||
_buffer = (uint8_t *)malloc(_size);
|
||||
if(!_buffer) {
|
||||
log_e("Not enough memory to allocate buffer");
|
||||
_failed = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if(_fill && _pos == _fill){
|
||||
_fill = 0;
|
||||
@ -67,8 +72,10 @@ private:
|
||||
return 0;
|
||||
}
|
||||
int res = recv(_fd, _buffer + _fill, _size - _fill, MSG_DONTWAIT);
|
||||
if(res < 0 && errno != EWOULDBLOCK) {
|
||||
if(res < 0) {
|
||||
if(errno != EWOULDBLOCK) {
|
||||
_failed = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
_fill += res;
|
||||
@ -398,7 +405,8 @@ int WiFiClient::peek()
|
||||
|
||||
int WiFiClient::available()
|
||||
{
|
||||
if(!_connected) {
|
||||
if(!_rxBuffer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int res = _rxBuffer->available();
|
||||
@ -439,6 +447,8 @@ uint8_t WiFiClient::connected()
|
||||
if (_connected) {
|
||||
uint8_t dummy;
|
||||
int res = recv(fd(), &dummy, 0, MSG_DONTWAIT);
|
||||
// avoid unused var warning by gcc
|
||||
(void)res;
|
||||
switch (errno) {
|
||||
case EWOULDBLOCK:
|
||||
case ENOENT: //caused by vfs
|
||||
|
@ -96,7 +96,7 @@ static bool _start_network_event_task(){
|
||||
}
|
||||
}
|
||||
if(!_network_event_task_handle){
|
||||
xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, 2, &_network_event_task_handle, ARDUINO_RUNNING_CORE);
|
||||
xTaskCreatePinnedToCore(_network_event_task, "network_event", 4096, NULL, ESP_TASKD_EVENT_PRIO - 1, &_network_event_task_handle, ARDUINO_RUNNING_CORE);
|
||||
if(!_network_event_task_handle){
|
||||
log_e("Network Event Task Start Failed!");
|
||||
return false;
|
||||
@ -187,7 +187,7 @@ typedef struct WiFiEventCbList {
|
||||
WiFiEventSysCb scb;
|
||||
system_event_id_t event;
|
||||
|
||||
WiFiEventCbList() : id(current_id++) {}
|
||||
WiFiEventCbList() : id(current_id++), cb(NULL), fcb(NULL), scb(NULL), event(SYSTEM_EVENT_WIFI_READY) {}
|
||||
} WiFiEventCbList_t;
|
||||
wifi_event_id_t WiFiEventCbList::current_id = 1;
|
||||
|
||||
@ -371,8 +371,7 @@ esp_err_t WiFiGenericClass::_eventCallback(void *arg, system_event_t *event)
|
||||
(reason >= WIFI_REASON_BEACON_TIMEOUT && reason != WIFI_REASON_AUTH_FAIL)) &&
|
||||
WiFi.getAutoReconnect())
|
||||
{
|
||||
WiFi.enableSTA(false);
|
||||
WiFi.enableSTA(true);
|
||||
WiFi.disconnect(true);
|
||||
WiFi.begin();
|
||||
}
|
||||
} else if(event->event_id == SYSTEM_EVENT_STA_GOT_IP) {
|
||||
|
@ -118,16 +118,12 @@ uint8_t WiFiMulti::run(uint32_t connectTimeout)
|
||||
status = WiFi.status();
|
||||
}
|
||||
|
||||
IPAddress ip;
|
||||
uint8_t * mac;
|
||||
switch(status) {
|
||||
case 3:
|
||||
ip = WiFi.localIP();
|
||||
mac = WiFi.BSSID();
|
||||
log_i("[WIFI] Connecting done.");
|
||||
log_d("[WIFI] SSID: %s", WiFi.SSID().c_str());
|
||||
log_d("[WIFI] IP: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||
log_d("[WIFI] MAC: %02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
log_d("[WIFI] IP: %s", WiFi.localIP().toString().c_str());
|
||||
log_d("[WIFI] MAC: %s", WiFi.BSSIDstr().c_str());
|
||||
log_d("[WIFI] Channel: %d", WiFi.channel());
|
||||
break;
|
||||
case 1:
|
||||
|
@ -683,8 +683,10 @@ void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) {
|
||||
smartconfig_status_t status = (smartconfig_status_t) st;
|
||||
log_d("Status: %s", sc_status_strings[st % 5]);
|
||||
if (status == SC_STATUS_GETTING_SSID_PSWD) {
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||
smartconfig_type_t * type = (smartconfig_type_t *)result;
|
||||
log_d("Type: %s", sc_type_strings[*type % 3]);
|
||||
#endif
|
||||
} else if (status == SC_STATUS_LINK) {
|
||||
wifi_sta_config_t *sta_conf = reinterpret_cast<wifi_sta_config_t *>(result);
|
||||
log_d("SSID: %s", (char *)(sta_conf->ssid));
|
||||
@ -694,8 +696,10 @@ void WiFiSTAClass::_smartConfigCallback(uint32_t st, void* result) {
|
||||
_smartConfigDone = true;
|
||||
} else if (status == SC_STATUS_LINK_OVER) {
|
||||
if(result){
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_DEBUG
|
||||
ip4_addr_t * ip = (ip4_addr_t *)result;
|
||||
log_d("Sender IP: " IPSTR, IP2STR(ip));
|
||||
#endif
|
||||
}
|
||||
WiFi.stopSmartConfig();
|
||||
}
|
||||
|
67
libraries/WiFiClientSecure/README.md
Normal file
67
libraries/WiFiClientSecure/README.md
Normal file
@ -0,0 +1,67 @@
|
||||
WiFiClientSecure
|
||||
================
|
||||
|
||||
The WiFiClientSecure class implements support for secure connections using TLS (SSL).
|
||||
It inherits from WiFiClient and thus implements a superset of that class' interface.
|
||||
There are three ways to establish a secure connection using the WiFiClientSecure class:
|
||||
using a root certificate authority (CA) cert, using a root CA cert plus a client cert and key,
|
||||
and using a pre-shared key (PSK).
|
||||
|
||||
Using a root certificate authority cert
|
||||
---------------------------------------
|
||||
This method authenticates the server and negotiates an encrypted connection.
|
||||
It is the same functionality as implemented in your web browser when you connect to HTTPS sites.
|
||||
|
||||
If you are accessing your own server:
|
||||
- Generate a root certificate for your own certificate authority
|
||||
- Generate a cert & private key using your root certificate ("self-signed cert") for your server
|
||||
If you are accessing a public server:
|
||||
- Obtain the cert of the public CA that signed that server's cert
|
||||
Then:
|
||||
- In WiFiClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
|
||||
CA or of the public CA
|
||||
- When WiFiClientSecure connects to the target server it uses the CA cert to verify the certificate
|
||||
presented by the server, and then negotiates encryption for the connection
|
||||
|
||||
Please see the WiFiClientSecure example.
|
||||
|
||||
Using a root CA cert and client cert/keys
|
||||
-----------------------------------------
|
||||
This method authenticates the server and additionally also authenticates
|
||||
the client to the server, then negotiates an encrypted connection.
|
||||
|
||||
- Follow steps above
|
||||
- Using your root CA generate cert/key for your client
|
||||
- Register the keys with the server you will be accessing so the server can authenticate your client
|
||||
- In WiFiClientSecure use setCACert (or the appropriate connect method) to set the root cert of your
|
||||
CA or of the public CA, this is used to authenticate the server
|
||||
- In WiFiClientSecure use setCertificate, and setPrivateKey (or the appropriate connect method) to
|
||||
set your client's cert & key, this will be used to authenticate your client to the server
|
||||
- When WiFiClientSecure connects to the target server it uses the CA cert to verify the certificate
|
||||
presented by the server, it will use the cert/key to authenticate your client to the server, and
|
||||
it will then negotiate encryption for the connection
|
||||
|
||||
Using Pre-Shared Keys (PSK)
|
||||
---------------------------
|
||||
|
||||
TLS supports authentication and encryption using a pre-shared key (i.e. a key that both client and
|
||||
server know) as an alternative to the public key cryptography commonly used on the web for HTTPS.
|
||||
PSK is starting to be used for MQTT, e.g. in mosquitto, to simplify the set-up and avoid having to
|
||||
go through the whole CA, cert, and private key process.
|
||||
|
||||
A pre-shared key is a binary string of up to 32 bytes and is commonly represented in hex form. In
|
||||
addition to the key, clients can also present an id and typically the server allows a different key
|
||||
to be associated with each client id. In effect this is very similar to username and password pairs,
|
||||
except that unlike a password the key is not directly transmitted to the server, thus a connection to a
|
||||
malicious server does not divulge the password. Plus the server is also authenticated to the client.
|
||||
|
||||
To use PSK:
|
||||
- Generate a random hex string (generating an MD5 or SHA for some file is one way to do this)
|
||||
- Come up with a string id for your client and configure your server to accept the id/key pair
|
||||
- In WiFiClientSecure use setPreSharedKey (or the appropriate connect method) to
|
||||
set the id/key combo
|
||||
- When WiFiClientSecure connects to the target server it uses the id/key combo to authenticate the
|
||||
server (it must prove that it has the key too), authenticate the client and then negotiate
|
||||
encryption for the connection
|
||||
|
||||
Please see the WiFiClientPSK example.
|
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Wifi secure connection example for ESP32 using a pre-shared key (PSK)
|
||||
This is useful with MQTT servers instead of using a self-signed cert, tested with mosquitto.
|
||||
Running on TLS 1.2 using mbedTLS
|
||||
|
||||
To test run a test server using: openssl s_server -accept 8443 -psk 1a2b3c4d -nocert
|
||||
It will show the http request made, but there's no easy way to send a reply back...
|
||||
|
||||
2017 - Evandro Copercini - Apache 2.0 License.
|
||||
2018 - Adapted for PSK by Thorsten von Eicken
|
||||
*/
|
||||
|
||||
#include <WiFiClientSecure.h>
|
||||
|
||||
#if 0
|
||||
const char* ssid = "your-ssid"; // your network SSID (name of wifi network)
|
||||
const char* password = "your-password"; // your network password
|
||||
#else
|
||||
const char* ssid = "test"; // your network SSID (name of wifi network)
|
||||
const char* password = "securetest"; // your network password
|
||||
#endif
|
||||
|
||||
//const char* server = "server.local"; // Server hostname
|
||||
const IPAddress server = IPAddress(192, 168, 0, 14); // Server IP address
|
||||
const int port = 8443; // server's port (8883 for MQTT)
|
||||
|
||||
const char* pskIdent = "Client_identity"; // PSK identity (sometimes called key hint)
|
||||
const char* psKey = "1a2b3c4d"; // PSK Key (must be hex string without 0x)
|
||||
|
||||
WiFiClientSecure client;
|
||||
|
||||
void setup() {
|
||||
//Initialize serial and wait for port to open:
|
||||
Serial.begin(115200);
|
||||
delay(100);
|
||||
|
||||
Serial.print("Attempting to connect to SSID: ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
// attempt to connect to Wifi network:
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
Serial.print(".");
|
||||
// wait 1 second for re-trying
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.print("Connected to ");
|
||||
Serial.println(ssid);
|
||||
|
||||
client.setPreSharedKey(pskIdent, psKey);
|
||||
|
||||
Serial.println("\nStarting connection to server...");
|
||||
if (!client.connect(server, port))
|
||||
Serial.println("Connection failed!");
|
||||
else {
|
||||
Serial.println("Connected to server!");
|
||||
// Make a HTTP request:
|
||||
client.println("GET /a/check HTTP/1.0");
|
||||
client.print("Host: ");
|
||||
client.println(server);
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
|
||||
while (client.connected()) {
|
||||
String line = client.readStringUntil('\n');
|
||||
if (line == "\r") {
|
||||
Serial.println("headers received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// if there are incoming bytes available
|
||||
// from the server, read them and print them:
|
||||
while (client.available()) {
|
||||
char c = client.read();
|
||||
Serial.write(c);
|
||||
}
|
||||
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// do nothing
|
||||
}
|
@ -39,6 +39,8 @@ WiFiClientSecure::WiFiClientSecure()
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
@ -59,6 +61,8 @@ WiFiClientSecure::WiFiClientSecure(int sock)
|
||||
_CA_cert = NULL;
|
||||
_cert = NULL;
|
||||
_private_key = NULL;
|
||||
_pskIdent = NULL;
|
||||
_psKey = NULL;
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
@ -89,11 +93,15 @@ void WiFiClientSecure::stop()
|
||||
|
||||
int WiFiClientSecure::connect(IPAddress ip, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(ip, port, _pskIdent, _psKey);
|
||||
return connect(ip, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(const char *host, uint16_t port)
|
||||
{
|
||||
if (_pskIdent && _psKey)
|
||||
return connect(host, port, _pskIdent, _psKey);
|
||||
return connect(host, port, _CA_cert, _cert, _private_key);
|
||||
}
|
||||
|
||||
@ -104,7 +112,24 @@ int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *_CA_cert,
|
||||
|
||||
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *_CA_cert, const char *_cert, const char *_private_key)
|
||||
{
|
||||
int ret = start_ssl_client(sslclient, host, port, _CA_cert, _cert, _private_key);
|
||||
int ret = start_ssl_client(sslclient, host, port, _CA_cert, _cert, _private_key, NULL, NULL);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
stop();
|
||||
return 0;
|
||||
}
|
||||
_connected = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
return connect(ip.toString().c_str(), port,_pskIdent, _psKey);
|
||||
}
|
||||
|
||||
int WiFiClientSecure::connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey) {
|
||||
log_v("start_ssl_client with PSK");
|
||||
int ret = start_ssl_client(sslclient, host, port, NULL, NULL, NULL, _pskIdent, _psKey);
|
||||
_lastError = ret;
|
||||
if (ret < 0) {
|
||||
log_e("start_ssl_client: %d", ret);
|
||||
@ -131,13 +156,6 @@ size_t WiFiClientSecure::write(uint8_t data)
|
||||
int WiFiClientSecure::read()
|
||||
{
|
||||
uint8_t data = -1;
|
||||
|
||||
if(_peek >= 0){
|
||||
data = _peek;
|
||||
_peek = -1;
|
||||
return data;
|
||||
}
|
||||
|
||||
int res = read(&data, 1);
|
||||
if (res < 0) {
|
||||
return res;
|
||||
@ -161,7 +179,8 @@ size_t WiFiClientSecure::write(const uint8_t *buf, size_t size)
|
||||
int WiFiClientSecure::read(uint8_t *buf, size_t size)
|
||||
{
|
||||
int peeked = 0;
|
||||
if ((!buf && size) || (_peek < 0 && !available())) {
|
||||
int avail = available();
|
||||
if ((!buf && size) || avail <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if(!size){
|
||||
@ -171,7 +190,8 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size)
|
||||
buf[0] = _peek;
|
||||
_peek = -1;
|
||||
size--;
|
||||
if(!size || !available()){
|
||||
avail--;
|
||||
if(!size || !avail){
|
||||
return 1;
|
||||
}
|
||||
buf++;
|
||||
@ -181,23 +201,23 @@ int WiFiClientSecure::read(uint8_t *buf, size_t size)
|
||||
int res = get_ssl_receive(sslclient, buf, size);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
return res;
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res + peeked;
|
||||
}
|
||||
|
||||
int WiFiClientSecure::available()
|
||||
{
|
||||
int peeked = (_peek >= 0);
|
||||
if (!_connected) {
|
||||
return 0;
|
||||
return peeked;
|
||||
}
|
||||
int res = data_to_read(sslclient);
|
||||
if (res < 0) {
|
||||
stop();
|
||||
} else if(_peek >= 0) {
|
||||
res += 1;
|
||||
return peeked?peeked:res;
|
||||
}
|
||||
return res;
|
||||
return res+peeked;
|
||||
}
|
||||
|
||||
uint8_t WiFiClientSecure::connected()
|
||||
@ -223,6 +243,11 @@ void WiFiClientSecure::setPrivateKey (const char *private_key)
|
||||
_private_key = private_key;
|
||||
}
|
||||
|
||||
void WiFiClientSecure::setPreSharedKey(const char *pskIdent, const char *psKey) {
|
||||
_pskIdent = pskIdent;
|
||||
_psKey = psKey;
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::verify(const char* fp, const char* domain_name)
|
||||
{
|
||||
if (!sslclient)
|
||||
@ -232,18 +257,19 @@ bool WiFiClientSecure::verify(const char* fp, const char* domain_name)
|
||||
}
|
||||
|
||||
char *WiFiClientSecure::_streamLoad(Stream& stream, size_t size) {
|
||||
char *dest = (char*)malloc(size);
|
||||
static char *dest = nullptr;
|
||||
if(dest) {
|
||||
free(dest);
|
||||
}
|
||||
dest = (char*)malloc(size);
|
||||
if (!dest) {
|
||||
return nullptr;
|
||||
}
|
||||
if (size != stream.readBytes(dest, size)) {
|
||||
free(dest);
|
||||
return nullptr;
|
||||
dest = nullptr;
|
||||
}
|
||||
char ret[size+1];
|
||||
snprintf(ret, size, "%s", dest);
|
||||
free(dest);
|
||||
return ret;
|
||||
return dest;
|
||||
}
|
||||
|
||||
bool WiFiClientSecure::loadCACert(Stream& stream, size_t size) {
|
||||
|
@ -35,6 +35,8 @@ protected:
|
||||
const char *_CA_cert;
|
||||
const char *_cert;
|
||||
const char *_private_key;
|
||||
const char *_pskIdent; // identity for PSK cipher suites
|
||||
const char *_psKey; // key in hex for PSK cipher suites
|
||||
|
||||
public:
|
||||
WiFiClientSecure *next;
|
||||
@ -45,6 +47,8 @@ public:
|
||||
int connect(const char *host, uint16_t port);
|
||||
int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);
|
||||
int peek();
|
||||
size_t write(uint8_t data);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
@ -55,6 +59,7 @@ public:
|
||||
void stop();
|
||||
uint8_t connected();
|
||||
int lastError(char *buf, const size_t size);
|
||||
void setPreSharedKey(const char *pskIdent, const char *psKey); // psKey in Hex
|
||||
void setCACert(const char *rootCA);
|
||||
void setCertificate(const char *client_ca);
|
||||
void setPrivateKey (const char *private_key);
|
||||
|
@ -45,12 +45,12 @@ void ssl_init(sslclient_context *ssl_client)
|
||||
}
|
||||
|
||||
|
||||
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key)
|
||||
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey)
|
||||
{
|
||||
char buf[512];
|
||||
int ret, flags, timeout;
|
||||
int enable = 1;
|
||||
log_v("Free heap before TLS %u", xPortGetFreeHeapSize());
|
||||
log_v("Free internal heap before TLS %u", ESP.getFreeHeap());
|
||||
|
||||
log_v("Starting socket");
|
||||
ssl_client->socket = -1;
|
||||
@ -116,6 +116,36 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
|
||||
if (ret < 0) {
|
||||
return handle_error(ret);
|
||||
}
|
||||
} else if (pskIdent != NULL && psKey != NULL) {
|
||||
log_v("Setting up PSK");
|
||||
// convert PSK from hex to binary
|
||||
if ((strlen(psKey) & 1) != 0 || strlen(psKey) > 2*MBEDTLS_PSK_MAX_LEN) {
|
||||
log_e("pre-shared key not valid hex or too long");
|
||||
return -1;
|
||||
}
|
||||
unsigned char psk[MBEDTLS_PSK_MAX_LEN];
|
||||
size_t psk_len = strlen(psKey)/2;
|
||||
for (int j=0; j<strlen(psKey); j+= 2) {
|
||||
char c = psKey[j];
|
||||
if (c >= '0' && c <= '9') c -= '0';
|
||||
else if (c >= 'A' && c <= 'F') c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'f') c -= 'a' - 10;
|
||||
else return -1;
|
||||
psk[j/2] = c<<4;
|
||||
c = psKey[j+1];
|
||||
if (c >= '0' && c <= '9') c -= '0';
|
||||
else if (c >= 'A' && c <= 'F') c -= 'A' - 10;
|
||||
else if (c >= 'a' && c <= 'f') c -= 'a' - 10;
|
||||
else return -1;
|
||||
psk[j/2] |= c;
|
||||
}
|
||||
// set mbedtls config
|
||||
ret = mbedtls_ssl_conf_psk(&ssl_client->ssl_conf, psk, psk_len,
|
||||
(const unsigned char *)pskIdent, strlen(pskIdent));
|
||||
if (ret != 0) {
|
||||
log_e("mbedtls_ssl_conf_psk returned %d", ret);
|
||||
return handle_error(ret);
|
||||
}
|
||||
} else {
|
||||
mbedtls_ssl_conf_authmode(&ssl_client->ssl_conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
log_i("WARNING: Use certificates for a more secure communication!");
|
||||
@ -202,7 +232,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
|
||||
mbedtls_pk_free(&ssl_client->client_key);
|
||||
}
|
||||
|
||||
log_v("Free heap after TLS %u", xPortGetFreeHeapSize());
|
||||
log_v("Free internal heap after TLS %u", ESP.getFreeHeap());
|
||||
|
||||
return ssl_client->socket;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ typedef struct sslclient_context {
|
||||
|
||||
|
||||
void ssl_init(sslclient_context *ssl_client);
|
||||
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key, const char *pskIdent, const char *psKey);
|
||||
void stop_ssl_socket(sslclient_context *ssl_client, const char *rootCABuff, const char *cli_cert, const char *cli_key);
|
||||
int data_to_read(sslclient_context *ssl_client);
|
||||
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len);
|
||||
|
@ -154,14 +154,15 @@ void TwoWire::beginTransmission(uint16_t address)
|
||||
uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransaction(), Wire.write()
|
||||
{
|
||||
if(transmitting == 1) {
|
||||
// txlength is howmany bytes in txbuffer have been use
|
||||
last_error = writeTransmission(txAddress, &txBuffer[txQueued], txLength - txQueued, sendStop);
|
||||
if(last_error == I2C_ERROR_CONTINUE){
|
||||
txQueued = txLength;
|
||||
} else if( last_error == I2C_ERROR_OK){
|
||||
rxIndex = 0;
|
||||
rxLength = rxQueued;
|
||||
rxQueued = 0;
|
||||
txQueued = 0; // the SendStop=true will restart all Queueing
|
||||
if(last_error == I2C_ERROR_CONTINUE){
|
||||
// txlength is howmany bytes in txbuffer have been use
|
||||
txQueued = txLength;
|
||||
}
|
||||
} else {
|
||||
last_error = I2C_ERROR_NO_BEGIN;
|
||||
@ -170,7 +171,7 @@ uint8_t TwoWire::endTransmission(bool sendStop) // Assumes Wire.beginTransactio
|
||||
txIndex = 0;
|
||||
txLength = 0;
|
||||
transmitting = 0;
|
||||
return last_error;
|
||||
return (last_error == I2C_ERROR_CONTINUE)?I2C_ERROR_OK:last_error; // Don't return Continue for compatibility.
|
||||
}
|
||||
|
||||
/* @stickBreaker 11/2017 fix for ReSTART timeout, ISR
|
||||
@ -191,12 +192,19 @@ uint8_t TwoWire::requestFrom(uint16_t address, uint8_t size, bool sendStop)
|
||||
|
||||
last_error = readTransmission(address, &rxBuffer[cnt], size, sendStop, &cnt);
|
||||
rxIndex = 0;
|
||||
rxLength = rxQueued;
|
||||
|
||||
rxLength = cnt;
|
||||
|
||||
if( last_error != I2C_ERROR_CONTINUE){ // not a buffered ReSTART operation
|
||||
// so this operation actually moved data, queuing is done.
|
||||
rxQueued = 0;
|
||||
txQueued = 0; // the SendStop=true will restart all Queueing
|
||||
if(last_error != I2C_ERROR_OK){
|
||||
txQueued = 0; // the SendStop=true will restart all Queueing or error condition
|
||||
}
|
||||
|
||||
if(last_error != I2C_ERROR_OK){ // ReSTART on read does not return any data
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "freertos/queue.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define STICKBREAKER V1.0.1
|
||||
#define STICKBREAKER 'V1.1.0'
|
||||
#define I2C_BUFFER_LENGTH 128
|
||||
typedef void(*user_onRequest)(void);
|
||||
typedef void(*user_onReceive)(uint8_t*, int);
|
||||
@ -67,12 +67,13 @@ protected:
|
||||
public:
|
||||
TwoWire(uint8_t bus_num);
|
||||
~TwoWire();
|
||||
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0);
|
||||
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
|
||||
// calling will attemp to recover hung bus
|
||||
|
||||
void setClock(uint32_t frequency); // change bus clock without initing hardware
|
||||
size_t getClock(); // current bus clock rate in hz
|
||||
|
||||
void setTimeOut(uint16_t timeOutMillis);
|
||||
void setTimeOut(uint16_t timeOutMillis); // default timeout of i2c transactions is 50ms
|
||||
uint16_t getTimeOut();
|
||||
|
||||
uint8_t lastError();
|
||||
@ -137,6 +138,8 @@ extern TwoWire Wire1;
|
||||
|
||||
|
||||
/*
|
||||
V1.1.0 08JAN2019 Support CPU Clock frequency changes
|
||||
V1.0.2 30NOV2018 stop returning I2C_ERROR_CONTINUE on ReSTART operations, regain compatibility with Arduino libs
|
||||
V1.0.1 02AUG2018 First Fix after release, Correct ReSTART handling, change Debug control, change begin()
|
||||
to a function, this allow reporting if bus cannot be initialized, Wire.begin() can be used to recover
|
||||
a hung bus busy condition.
|
||||
|
@ -37,8 +37,8 @@
|
||||
},
|
||||
{
|
||||
"packager": "esp32",
|
||||
"name": "esptool",
|
||||
"version": "2.5.0"
|
||||
"name": "esptool_py",
|
||||
"version": "2.6.0"
|
||||
},
|
||||
{
|
||||
"packager": "esp32",
|
||||
@ -84,43 +84,43 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "esptool",
|
||||
"version": "2.5.0",
|
||||
"name": "esptool_py",
|
||||
"version": "2.6.0",
|
||||
"systems": [
|
||||
{
|
||||
"host": "i686-mingw32",
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.5.0-windows.zip",
|
||||
"archiveFileName": "esptool-2.5.0-windows.zip",
|
||||
"checksum": "SHA-256:576b8068b577cae0e6e937566a9d32a08ff7ff82963fb60400eacb6691f2fbfb",
|
||||
"size": "3420959"
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.6.0-windows.zip",
|
||||
"archiveFileName": "esptool-2.6.0-windows.zip",
|
||||
"checksum": "SHA-256:a73f4cf68db240d7f1d250c5c7f2dfcb53c17a37483729f1bf71f8f43d79a799",
|
||||
"size": "3421208"
|
||||
},
|
||||
{
|
||||
"host": "x86_64-apple-darwin",
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.5.0-macos.tar.gz",
|
||||
"archiveFileName": "esptool-2.5.0-macos.tar.gz",
|
||||
"checksum": "SHA-256:2da8ba3b83d99b5d808cab955a077e3e0738ec640b51de932d047cad7fac1157",
|
||||
"size": "3835397"
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.6.0-macos.tar.gz",
|
||||
"archiveFileName": "esptool-2.6.0-macos.tar.gz",
|
||||
"checksum": "SHA-256:0a881b91547c840fab8c72ae3d031069384278b8c2e5241647e8c8292c5e4a4b",
|
||||
"size": "3835660"
|
||||
},
|
||||
{
|
||||
"host": "x86_64-pc-linux-gnu",
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.5.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.5.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:34d63b9a0bf2acb9b6fdac15f91a8756f4e722065de031e8fbce4e4abc369e54",
|
||||
"size": "43468"
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
|
||||
"size": "43535"
|
||||
},
|
||||
{
|
||||
"host": "i686-pc-linux-gnu",
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.5.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.5.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:34d63b9a0bf2acb9b6fdac15f91a8756f4e722065de031e8fbce4e4abc369e54",
|
||||
"size": "43468"
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
|
||||
"size": "43535"
|
||||
},
|
||||
{
|
||||
"host": "arm-linux-gnueabihf",
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.5.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.5.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:34d63b9a0bf2acb9b6fdac15f91a8756f4e722065de031e8fbce4e4abc369e54",
|
||||
"size": "43468"
|
||||
"url": "https://dl.espressif.com/dl/esptool-2.6.0-linux.tar.gz",
|
||||
"archiveFileName": "esptool-2.6.0-linux.tar.gz",
|
||||
"checksum": "SHA-256:6d162f70f395ca31f5008829dd7e833e729f044a9c7355d5be8ce333a054e110",
|
||||
"size": "43535"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
36
platform.txt
36
platform.txt
@ -3,13 +3,13 @@ version=0.0.1
|
||||
|
||||
runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}/tools/xtensa-esp32-elf
|
||||
|
||||
tools.esptool.path={runtime.platform.path}/tools/esptool
|
||||
tools.esptool.cmd=esptool
|
||||
tools.esptool.cmd.linux=esptool.py
|
||||
tools.esptool.cmd.windows=esptool.exe
|
||||
tools.esptool_py.path={runtime.platform.path}/tools/esptool
|
||||
tools.esptool_py.cmd=esptool
|
||||
tools.esptool_py.cmd.linux=esptool.py
|
||||
tools.esptool_py.cmd.windows=esptool.exe
|
||||
|
||||
tools.esptool.network_cmd=python "{runtime.platform.path}/tools/espota.py"
|
||||
tools.esptool.network_cmd.windows="{runtime.platform.path}/tools/espota.exe"
|
||||
tools.esptool_py.network_cmd=python "{runtime.platform.path}/tools/espota.py"
|
||||
tools.esptool_py.network_cmd.windows="{runtime.platform.path}/tools/espota.exe"
|
||||
|
||||
tools.gen_esp32part.cmd=python "{runtime.platform.path}/tools/gen_esp32part.py"
|
||||
tools.gen_esp32part.cmd.windows="{runtime.platform.path}/tools/gen_esp32part.exe"
|
||||
@ -22,7 +22,7 @@ compiler.warning_flags.all=-Wall -Werror=all -Wextra
|
||||
|
||||
compiler.path={runtime.tools.xtensa-esp32-elf-gcc.path}/bin/
|
||||
compiler.sdk.path={runtime.platform.path}/tools/sdk
|
||||
compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_https_server" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/unity" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module"
|
||||
compiler.cpreprocessor.flags=-DESP_PLATFORM -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" -DHAVE_CONFIG_H "-I{compiler.sdk.path}/include/config" "-I{compiler.sdk.path}/include/app_trace" "-I{compiler.sdk.path}/include/app_update" "-I{compiler.sdk.path}/include/asio" "-I{compiler.sdk.path}/include/bootloader_support" "-I{compiler.sdk.path}/include/bt" "-I{compiler.sdk.path}/include/coap" "-I{compiler.sdk.path}/include/console" "-I{compiler.sdk.path}/include/driver" "-I{compiler.sdk.path}/include/esp-tls" "-I{compiler.sdk.path}/include/esp32" "-I{compiler.sdk.path}/include/esp_adc_cal" "-I{compiler.sdk.path}/include/esp_event" "-I{compiler.sdk.path}/include/esp_http_client" "-I{compiler.sdk.path}/include/esp_http_server" "-I{compiler.sdk.path}/include/esp_https_ota" "-I{compiler.sdk.path}/include/esp_https_server" "-I{compiler.sdk.path}/include/esp_ringbuf" "-I{compiler.sdk.path}/include/ethernet" "-I{compiler.sdk.path}/include/expat" "-I{compiler.sdk.path}/include/fatfs" "-I{compiler.sdk.path}/include/freemodbus" "-I{compiler.sdk.path}/include/freertos" "-I{compiler.sdk.path}/include/heap" "-I{compiler.sdk.path}/include/idf_test" "-I{compiler.sdk.path}/include/jsmn" "-I{compiler.sdk.path}/include/json" "-I{compiler.sdk.path}/include/libsodium" "-I{compiler.sdk.path}/include/log" "-I{compiler.sdk.path}/include/lwip" "-I{compiler.sdk.path}/include/mbedtls" "-I{compiler.sdk.path}/include/mdns" "-I{compiler.sdk.path}/include/micro-ecc" "-I{compiler.sdk.path}/include/mqtt" "-I{compiler.sdk.path}/include/newlib" "-I{compiler.sdk.path}/include/nghttp" "-I{compiler.sdk.path}/include/nvs_flash" "-I{compiler.sdk.path}/include/openssl" "-I{compiler.sdk.path}/include/protobuf-c" "-I{compiler.sdk.path}/include/protocomm" "-I{compiler.sdk.path}/include/pthread" "-I{compiler.sdk.path}/include/sdmmc" "-I{compiler.sdk.path}/include/smartconfig_ack" "-I{compiler.sdk.path}/include/soc" "-I{compiler.sdk.path}/include/spi_flash" "-I{compiler.sdk.path}/include/spiffs" "-I{compiler.sdk.path}/include/tcp_transport" "-I{compiler.sdk.path}/include/tcpip_adapter" "-I{compiler.sdk.path}/include/ulp" "-I{compiler.sdk.path}/include/unity" "-I{compiler.sdk.path}/include/vfs" "-I{compiler.sdk.path}/include/wear_levelling" "-I{compiler.sdk.path}/include/wifi_provisioning" "-I{compiler.sdk.path}/include/wpa_supplicant" "-I{compiler.sdk.path}/include/xtensa-debug-module" "-I{compiler.sdk.path}/include/esp32-camera" "-I{compiler.sdk.path}/include/esp-face" "-I{compiler.sdk.path}/include/fb_gfx"
|
||||
|
||||
compiler.c.cmd=xtensa-esp32-elf-gcc
|
||||
compiler.c.flags=-std=gnu99 -Os -g3 -fstack-protector -ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib -Wpointer-arith {compiler.warning_flags} -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-sign-compare -Wno-old-style-declaration -MMD -c
|
||||
@ -35,7 +35,7 @@ compiler.S.flags=-c -g3 -x assembler-with-cpp -MMD -mlongcalls
|
||||
|
||||
compiler.c.elf.cmd=xtensa-esp32-elf-gcc
|
||||
compiler.c.elf.flags=-nostdlib "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" -T esp32_out.ld -T esp32.common.ld -T esp32.rom.ld -T esp32.peripherals.ld -T esp32.rom.spiram_incompatible_fns.ld -u ld_include_panic_highint_hdl -u call_user_start_cpu0 -Wl,--gc-sections -Wl,-static -Wl,--undefined=uxTopUsedPriority -u __cxa_guard_dummy -u __cxx_fatal_exception
|
||||
compiler.c.elf.libs=-lgcc -lopenssl -lbtdm_app -lfatfs -lwps -lcoexist -lwear_levelling -lesp_http_client -lprotobuf-c -lhal -lnewlib -ldriver -lbootloader_support -lpp -lfreemodbus -lmesh -lsmartconfig -ljsmn -lwpa -lethernet -lphy -lapp_trace -lconsole -lulp -lwpa_supplicant -lfreertos -lbt -lmicro-ecc -lcxx -lxtensa-debug-module -ltcp_transport -lmdns -lvfs -lesp_ringbuf -lsoc -lcore -lsdmmc -llibsodium -lcoap -ltcpip_adapter -lprotocomm -lesp_event -lc_nano -lesp-tls -lasio -lrtc -lspi_flash -lwpa2 -lwifi_provisioning -lesp32 -lapp_update -lnghttp -lspiffs -lunity -lesp_https_server -lespnow -lnvs_flash -lesp_adc_cal -llog -lsmartconfig_ack -lexpat -lm -lmqtt -lc -lheap -lmbedtls -llwip -lnet80211 -lesp_http_server -lpthread -ljson -lesp_https_ota -lstdc++
|
||||
compiler.c.elf.libs=-lgcc -lopenssl -lbtdm_app -lfatfs -lwps -lcoexist -lwear_levelling -lesp_http_client -lprotobuf-c -lhal -lnewlib -ldriver -lbootloader_support -lpp -lfreemodbus -lmesh -lsmartconfig -ljsmn -lwpa -lethernet -lphy -lfrmn -lapp_trace -lfr_coefficients -lconsole -lulp -lwpa_supplicant -lfreertos -lbt -lmicro-ecc -lesp32-camera -lcxx -lxtensa-debug-module -ltcp_transport -lmdns -lvfs -lmtmn -lesp_ringbuf -lsoc -lcore -lfb_gfx -lsdmmc -llibsodium -lcoap -ltcpip_adapter -lprotocomm -lesp_event -limage_util -lc_nano -lesp-tls -lasio -lrtc -lspi_flash -lwpa2 -lwifi_provisioning -lesp32 -lface_recognition -lapp_update -lnghttp -lspiffs -lface_detection -lunity -lesp_https_server -lespnow -lnvs_flash -lesp_adc_cal -llog -ldl_lib -lsmartconfig_ack -lexpat -lfd_coefficients -lm -lmqtt -lc -lheap -lmbedtls -llwip -lnet80211 -lesp_http_server -lpthread -ljson -lesp_https_ota -lstdc++
|
||||
|
||||
compiler.as.cmd=xtensa-esp32-elf-as
|
||||
|
||||
@ -71,17 +71,17 @@ recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor
|
||||
recipe.S.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" {compiler.S.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/arduino.ar" "{object_file}"
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||
|
||||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{build.path}/arduino.ar" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} -Wl,--start-group {object_files} "{archive_file_path}" {compiler.c.elf.libs} -Wl,--end-group -Wl,-EL -o "{build.path}/{build.project_name}.elf"
|
||||
|
||||
## Create eeprom
|
||||
recipe.objcopy.eep.pattern={tools.gen_esp32part.cmd} -q "{runtime.platform.path}/tools/partitions/{build.partitions}.csv" "{build.path}/{build.project_name}.partitions.bin"
|
||||
|
||||
## Create hex
|
||||
recipe.objcopy.hex.pattern="{tools.esptool.path}/{tools.esptool.cmd}" --chip esp32 elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.flash_freq}" --flash_size "{build.flash_size}" -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf"
|
||||
recipe.objcopy.hex.pattern.linux=python "{tools.esptool.path}/{tools.esptool.cmd}" --chip esp32 elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.flash_freq}" --flash_size "{build.flash_size}" -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf"
|
||||
recipe.objcopy.hex.pattern="{tools.esptool_py.path}/{tools.esptool_py.cmd}" --chip esp32 elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.flash_freq}" --flash_size "{build.flash_size}" -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf"
|
||||
recipe.objcopy.hex.pattern.linux=python "{tools.esptool_py.path}/{tools.esptool_py.cmd}" --chip esp32 elf2image --flash_mode "{build.flash_mode}" --flash_freq "{build.flash_freq}" --flash_size "{build.flash_size}" -o "{build.path}/{build.project_name}.bin" "{build.path}/{build.project_name}.elf"
|
||||
|
||||
## Save hex
|
||||
recipe.output.tmp_file={build.project_name}.bin
|
||||
@ -94,9 +94,9 @@ recipe.size.regex.data=^(?:\.dram0\.data|\.dram0\.bss|\.noinit)\s+([0-9]+).*
|
||||
|
||||
# ------------------------------
|
||||
|
||||
tools.esptool.upload.protocol=esp32
|
||||
tools.esptool.upload.params.verbose=
|
||||
tools.esptool.upload.params.quiet=
|
||||
tools.esptool.upload.pattern="{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed} --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"
|
||||
tools.esptool.upload.pattern.linux=python "{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed} --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"
|
||||
tools.esptool.upload.network_pattern={network_cmd} -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
|
||||
tools.esptool_py.upload.protocol=esp32
|
||||
tools.esptool_py.upload.params.verbose=
|
||||
tools.esptool_py.upload.params.quiet=
|
||||
tools.esptool_py.upload.pattern="{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed} --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"
|
||||
tools.esptool_py.upload.pattern.linux=python "{path}/{cmd}" --chip esp32 --port "{serial.port}" --baud {upload.speed} --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size detect 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0x1000 "{runtime.platform.path}/tools/sdk/bin/bootloader_{build.boot}_{build.flash_freq}.bin" 0x10000 "{build.path}/{build.project_name}.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin"
|
||||
tools.esptool_py.upload.network_pattern={network_cmd} -i "{serial.port}" -p "{network.port}" "--auth={network.password}" -f "{build.path}/{build.project_name}.bin"
|
||||
|
@ -231,7 +231,7 @@ echo " - updating platform.txt..."
|
||||
cat $srcdir/platform.txt | \
|
||||
sed "s/version=.*/version=$ver$extent/g" | \
|
||||
sed 's/runtime.tools.xtensa-esp32-elf-gcc.path={runtime.platform.path}\/tools\/xtensa-esp32-elf//g' | \
|
||||
sed 's/tools.esptool.path={runtime.platform.path}\/tools\/esptool/tools.esptool.path=\{runtime.tools.esptool.path\}/g' \
|
||||
sed 's/tools.esptool_py.path={runtime.platform.path}\/tools\/esptool/tools.esptool_py.path=\{runtime.tools.esptool_py.path\}/g' \
|
||||
> $outdir/platform.txt
|
||||
|
||||
# Put core version and short hash of git version into core_version.h
|
||||
@ -338,7 +338,7 @@ if [ ! -z "$prev_any_release" ] && [ "$prev_any_release" != "null" ]; then
|
||||
|
||||
# Release notes: GIT log comments (prev_any_release, current_release>
|
||||
echo " - executing: git log --oneline $prev_any_release.."
|
||||
#git log --oneline $prev_any_release.. > $releaseDir/commits.txt
|
||||
git log --oneline $prev_any_release.. > $releaseDir/commits.txt
|
||||
fi
|
||||
|
||||
# for RELEASE run update REL JSON as well
|
||||
@ -353,7 +353,7 @@ if [ $bIsPrerelease -eq 0 ]; then
|
||||
|
||||
# Release notes: GIT log comments (prev_release, current_release>
|
||||
echo " - executing: git log --oneline $prev_release.."
|
||||
#git log --oneline $prev_release.. > $releaseDir/commits.txt
|
||||
git log --oneline $prev_release.. > $releaseDir/commits.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -46,6 +46,7 @@ def compile(tmp_dir, sketch, tools_dir, hardware_dir, ide_path, f, args):
|
||||
# Debug=Serial,DebugLevel=Core____
|
||||
cmd += '-fqbn=espressif:esp32:{board_name}:' \
|
||||
'FlashFreq={flash_freq},' \
|
||||
'PartitionScheme=huge_app,' \
|
||||
'UploadSpeed=921600'.format(**vars(args))
|
||||
cmd += ' '
|
||||
cmd += '-ide-version=10607 '
|
||||
|
@ -205,7 +205,7 @@ def serve(remoteAddr, localAddr, remotePort, localPort, password, filename, comm
|
||||
data = connection.recv(32).decode()
|
||||
logging.info('Result: %s' ,data)
|
||||
|
||||
if data == "OK":
|
||||
if "OK" in data:
|
||||
logging.info('Success')
|
||||
connection.close()
|
||||
f.close()
|
||||
|
Binary file not shown.
@ -29,11 +29,15 @@ import struct
|
||||
import sys
|
||||
import hashlib
|
||||
import binascii
|
||||
import errno
|
||||
|
||||
MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature
|
||||
MD5_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for MD5 sum
|
||||
PARTITION_TABLE_SIZE = 0x1000 # Size of partition table
|
||||
|
||||
MIN_PARTITION_SUBTYPE_APP_OTA = 0x10
|
||||
NUM_PARTITION_SUBTYPE_APP_OTA = 16
|
||||
|
||||
__version__ = '1.2'
|
||||
|
||||
APP_TYPE = 0x00
|
||||
@ -67,16 +71,19 @@ md5sum = True
|
||||
secure = False
|
||||
offset_part_table = 0
|
||||
|
||||
|
||||
def status(msg):
|
||||
""" Print status message to stderr """
|
||||
if not quiet:
|
||||
critical(msg)
|
||||
|
||||
|
||||
def critical(msg):
|
||||
""" Print critical message to stderr """
|
||||
sys.stderr.write(msg)
|
||||
sys.stderr.write('\n')
|
||||
|
||||
|
||||
class PartitionTable(list):
|
||||
def __init__(self):
|
||||
super(PartitionTable, self).__init__(self)
|
||||
@ -145,14 +152,14 @@ class PartitionTable(list):
|
||||
ptype = TYPES[ptype]
|
||||
except KeyError:
|
||||
try:
|
||||
ptypes = int(ptype, 0)
|
||||
ptype = int(ptype, 0)
|
||||
except TypeError:
|
||||
pass
|
||||
try:
|
||||
subtype = SUBTYPES[int(ptype)][subtype]
|
||||
except KeyError:
|
||||
try:
|
||||
ptypes = int(ptype, 0)
|
||||
ptype = int(ptype, 0)
|
||||
except TypeError:
|
||||
pass
|
||||
|
||||
@ -205,7 +212,7 @@ class PartitionTable(list):
|
||||
|
||||
@classmethod
|
||||
def from_binary(cls, b):
|
||||
md5 = hashlib.md5();
|
||||
md5 = hashlib.md5()
|
||||
result = cls()
|
||||
for o in range(0,len(b),32):
|
||||
data = b[o:o + 32]
|
||||
@ -238,6 +245,7 @@ class PartitionTable(list):
|
||||
rows += [x.to_csv(simple_formatting) for x in self]
|
||||
return "\n".join(rows) + "\n"
|
||||
|
||||
|
||||
class PartitionDefinition(object):
|
||||
MAGIC_BYTES = b"\xAA\x50"
|
||||
|
||||
@ -253,8 +261,8 @@ class PartitionDefinition(object):
|
||||
}
|
||||
|
||||
# add subtypes for the 16 OTA slot values ("ota_XX, etc.")
|
||||
for ota_slot in range(16):
|
||||
SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = 0x10 + ota_slot
|
||||
for ota_slot in range(NUM_PARTITION_SUBTYPE_APP_OTA):
|
||||
SUBTYPES[TYPES["app"]]["ota_%d" % ota_slot] = MIN_PARTITION_SUBTYPE_APP_OTA + ota_slot
|
||||
|
||||
def __init__(self):
|
||||
self.name = ""
|
||||
@ -349,12 +357,14 @@ class PartitionDefinition(object):
|
||||
raise ValidationError(self, "Size field is not set")
|
||||
|
||||
if self.name in TYPES and TYPES.get(self.name, "") != self.type:
|
||||
critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's type (0x%x). Mistake in partition table?" % (self.name, self.type))
|
||||
critical("WARNING: Partition has name '%s' which is a partition type, but does not match this partition's "
|
||||
"type (0x%x). Mistake in partition table?" % (self.name, self.type))
|
||||
all_subtype_names = []
|
||||
for names in (t.keys() for t in SUBTYPES.values()):
|
||||
all_subtype_names += names
|
||||
if self.name in all_subtype_names and SUBTYPES.get(self.type, {}).get(self.name, "") != self.subtype:
|
||||
critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype))
|
||||
critical("WARNING: Partition has name '%s' which is a partition subtype, but this partition has "
|
||||
"non-matching type 0x%x and subtype 0x%x. Mistake in partition table?" % (self.name, self.type, self.subtype))
|
||||
|
||||
STRUCT_FORMAT = b"<2sBBLL16sL"
|
||||
|
||||
@ -400,7 +410,7 @@ class PartitionDefinition(object):
|
||||
|
||||
def lookup_keyword(t, keywords):
|
||||
for k,v in keywords.items():
|
||||
if simple_formatting == False and t == v:
|
||||
if simple_formatting is False and t == v:
|
||||
return k
|
||||
return "%d" % t
|
||||
|
||||
@ -433,6 +443,7 @@ def parse_int(v, keywords={}):
|
||||
except KeyError:
|
||||
raise InputError("Value '%s' is not valid. Known keywords: %s" % (v, ", ".join(keywords)))
|
||||
|
||||
|
||||
def main():
|
||||
global quiet
|
||||
global md5sum
|
||||
@ -444,7 +455,8 @@ def main():
|
||||
nargs='?', choices=['1MB', '2MB', '4MB', '8MB', '16MB'])
|
||||
parser.add_argument('--disable-md5sum', help='Disable md5 checksum for the partition table', default=False, action='store_true')
|
||||
parser.add_argument('--no-verify', help="Don't verify partition table fields", action='store_true')
|
||||
parser.add_argument('--verify', '-v', help="Verify partition table fields (deprecated, this behaviour is enabled by default and this flag does nothing.", action='store_true')
|
||||
parser.add_argument('--verify', '-v', help="Verify partition table fields (deprecated, this behaviour is "
|
||||
"enabled by default and this flag does nothing.", action='store_true')
|
||||
parser.add_argument('--quiet', '-q', help="Don't print non-critical status messages to stderr", action='store_true')
|
||||
parser.add_argument('--offset', '-o', help='Set offset partition table', default='0x8000')
|
||||
parser.add_argument('--secure', help="Require app partitions to be suitable for secure boot", action='store_true')
|
||||
@ -477,9 +489,20 @@ def main():
|
||||
size = size_mb * 1024 * 1024 # flash memory uses honest megabytes!
|
||||
table_size = table.flash_size()
|
||||
if size < table_size:
|
||||
raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." %
|
||||
raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured "
|
||||
"flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." %
|
||||
(args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb))
|
||||
|
||||
# Make sure that the output directory is created
|
||||
output_dir = os.path.abspath(os.path.dirname(args.output))
|
||||
|
||||
if not os.path.exists(output_dir):
|
||||
try:
|
||||
os.makedirs(output_dir)
|
||||
except OSError as exc:
|
||||
if exc.errno != errno.EEXIST:
|
||||
raise
|
||||
|
||||
if input_is_binary:
|
||||
output = table.to_csv()
|
||||
with sys.stdout if args.output == '-' else open(args.output, 'w') as f:
|
||||
|
6
tools/partitions/huge_app.csv
Normal file
6
tools/partitions/huge_app.csv
Normal file
@ -0,0 +1,6 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x300000,
|
||||
eeprom, data, 0x99, 0x310000,0x1000,
|
||||
spiffs, data, spiffs, 0x311000,0xEF000,
|
|
@ -151,6 +151,9 @@ env.Append(
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "wifi_provisioning"),
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "wpa_supplicant"),
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "xtensa-debug-module"),
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "esp32-camera"),
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "esp-face"),
|
||||
join(FRAMEWORK_DIR, "tools", "sdk", "include", "fb_gfx"),
|
||||
join(FRAMEWORK_DIR, "cores", env.BoardConfig().get("build.core"))
|
||||
],
|
||||
|
||||
@ -160,7 +163,7 @@ env.Append(
|
||||
],
|
||||
|
||||
LIBS=[
|
||||
"-lgcc", "-lopenssl", "-lbtdm_app", "-lfatfs", "-lwps", "-lcoexist", "-lwear_levelling", "-lesp_http_client", "-lprotobuf-c", "-lhal", "-lnewlib", "-ldriver", "-lbootloader_support", "-lpp", "-lfreemodbus", "-lmesh", "-lsmartconfig", "-ljsmn", "-lwpa", "-lethernet", "-lphy", "-lapp_trace", "-lconsole", "-lulp", "-lwpa_supplicant", "-lfreertos", "-lbt", "-lmicro-ecc", "-lcxx", "-lxtensa-debug-module", "-ltcp_transport", "-lmdns", "-lvfs", "-lesp_ringbuf", "-lsoc", "-lcore", "-lsdmmc", "-llibsodium", "-lcoap", "-ltcpip_adapter", "-lprotocomm", "-lesp_event", "-lc_nano", "-lesp-tls", "-lasio", "-lrtc", "-lspi_flash", "-lwpa2", "-lwifi_provisioning", "-lesp32", "-lapp_update", "-lnghttp", "-lspiffs", "-lunity", "-lesp_https_server", "-lespnow", "-lnvs_flash", "-lesp_adc_cal", "-llog", "-lsmartconfig_ack", "-lexpat", "-lm", "-lmqtt", "-lc", "-lheap", "-lmbedtls", "-llwip", "-lnet80211", "-lesp_http_server", "-lpthread", "-ljson", "-lesp_https_ota", "-lstdc++"
|
||||
"-lgcc", "-lopenssl", "-lbtdm_app", "-lfatfs", "-lwps", "-lcoexist", "-lwear_levelling", "-lesp_http_client", "-lprotobuf-c", "-lhal", "-lnewlib", "-ldriver", "-lbootloader_support", "-lpp", "-lfreemodbus", "-lmesh", "-lsmartconfig", "-ljsmn", "-lwpa", "-lethernet", "-lphy", "-lfrmn", "-lapp_trace", "-lfr_coefficients", "-lconsole", "-lulp", "-lwpa_supplicant", "-lfreertos", "-lbt", "-lmicro-ecc", "-lesp32-camera", "-lcxx", "-lxtensa-debug-module", "-ltcp_transport", "-lmdns", "-lvfs", "-lmtmn", "-lesp_ringbuf", "-lsoc", "-lcore", "-lfb_gfx", "-lsdmmc", "-llibsodium", "-lcoap", "-ltcpip_adapter", "-lprotocomm", "-lesp_event", "-limage_util", "-lc_nano", "-lesp-tls", "-lasio", "-lrtc", "-lspi_flash", "-lwpa2", "-lwifi_provisioning", "-lesp32", "-lface_recognition", "-lapp_update", "-lnghttp", "-lspiffs", "-lface_detection", "-lunity", "-lesp_https_server", "-lespnow", "-lnvs_flash", "-lesp_adc_cal", "-llog", "-ldl_lib", "-lsmartconfig_ack", "-lexpat", "-lfd_coefficients", "-lm", "-lmqtt", "-lc", "-lheap", "-lmbedtls", "-llwip", "-lnet80211", "-lesp_http_server", "-lpthread", "-ljson", "-lesp_https_ota", "-lstdc++"
|
||||
],
|
||||
|
||||
LIBSOURCE_DIRS=[
|
||||
@ -206,7 +209,7 @@ env.Prepend(LIBS=libs)
|
||||
#
|
||||
|
||||
fwpartitions_dir = join(FRAMEWORK_DIR, "tools", "partitions")
|
||||
partitions_csv = env.BoardConfig().get("build.partitions", "default.csv")
|
||||
partitions_csv = env.BoardConfig().get("build.partitions", "huge_app.csv")
|
||||
env.Replace(
|
||||
PARTITIONS_TABLE_CSV=abspath(
|
||||
join(fwpartitions_dir, partitions_csv) if isfile(
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -20,6 +20,8 @@
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_partition.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_data_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
@ -41,6 +43,14 @@ extern "C"
|
||||
*/
|
||||
typedef uint32_t esp_ota_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Return esp_app_desc structure. This structure includes app version.
|
||||
*
|
||||
* Return description for running app.
|
||||
* @return Pointer to esp_app_desc structure.
|
||||
*/
|
||||
const esp_app_desc_t *esp_ota_get_app_description(void);
|
||||
|
||||
/**
|
||||
* @brief Commence an OTA update writing to the specified partition.
|
||||
|
||||
@ -170,6 +180,68 @@ const esp_partition_t* esp_ota_get_running_partition(void);
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_next_update_partition(const esp_partition_t *start_from);
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition Pointer to app partition. (only app partition)
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
* @return
|
||||
* - ESP_OK Successful.
|
||||
* - ESP_ERR_NOT_FOUND app_desc structure is not found. Magic word is incorrect.
|
||||
* - ESP_ERR_NOT_SUPPORTED Partition is not application.
|
||||
* - ESP_ERR_INVALID_ARG Arguments is NULL or if partition's offset exceeds partition size.
|
||||
* - ESP_ERR_INVALID_SIZE Read would go out of bounds of the partition.
|
||||
* - or one of error codes from lower-level flash driver.
|
||||
*/
|
||||
esp_err_t esp_ota_get_partition_description(const esp_partition_t *partition, esp_app_desc_t *app_desc);
|
||||
|
||||
/**
|
||||
* @brief This function is called to indicate that the running app is working well.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: if successful.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_valid_cancel_rollback();
|
||||
|
||||
/**
|
||||
* @brief This function is called to roll back to the previously workable app with reboot.
|
||||
*
|
||||
* If rollback is successful then device will reset else API will return with error code.
|
||||
* @return
|
||||
* - ESP_FAIL: if not successful.
|
||||
*/
|
||||
esp_err_t esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
|
||||
/**
|
||||
* @brief Returns last partition with invalid state (ESP_OTA_IMG_INVALID or ESP_OTA_IMG_ABORTED).
|
||||
*
|
||||
* @return partition.
|
||||
*/
|
||||
const esp_partition_t* esp_ota_get_last_invalid_partition();
|
||||
|
||||
/**
|
||||
* @brief Returns state for given partition.
|
||||
*
|
||||
* @param[in] partition Pointer to partition.
|
||||
* @param[out] ota_state state of partition (if this partition has a record in otadata).
|
||||
* @return
|
||||
* - ESP_OK: Successful.
|
||||
* - ESP_ERR_INVALID_ARG: partition or ota_state arguments were NULL.
|
||||
* - ESP_ERR_NOT_SUPPORTED: partition is not ota.
|
||||
* - ESP_ERR_NOT_FOUND: Partition table does not have otadata or state was not found for given partition.
|
||||
*/
|
||||
esp_err_t esp_ota_get_state_partition(const esp_partition_t *partition, esp_ota_img_states_t *ota_state);
|
||||
|
||||
/**
|
||||
* @brief Erase previous boot app partition and corresponding otadata select for this partition.
|
||||
*
|
||||
* When current app is marked to as valid then you can erase previous app partition.
|
||||
* @return
|
||||
* - ESP_OK: Successful, otherwise ESP_ERR.
|
||||
*/
|
||||
esp_err_t esp_ota_erase_last_boot_app_partition(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "esp_flash_data_types.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
/// Type of hold a GPIO in low state
|
||||
typedef enum {
|
||||
@ -23,21 +24,29 @@ typedef enum {
|
||||
} esp_comm_gpio_hold_t;
|
||||
|
||||
/**
|
||||
* @brief Calculate crc for the OTA data partition.
|
||||
* @brief Calculate crc for the OTA data select.
|
||||
*
|
||||
* @param[in] ota_data The OTA data partition.
|
||||
* @param[in] s The OTA data select.
|
||||
* @return Returns crc value.
|
||||
*/
|
||||
uint32_t bootloader_common_ota_select_crc(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Verifies the validity of the OTA data partition
|
||||
* @brief Verifies the validity of the OTA data select
|
||||
*
|
||||
* @param[in] ota_data The OTA data partition.
|
||||
* @param[in] s The OTA data select.
|
||||
* @return Returns true on valid, false otherwise.
|
||||
*/
|
||||
bool bootloader_common_ota_select_valid(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Returns true if OTADATA is not marked as bootable partition.
|
||||
*
|
||||
* @param[in] s The OTA data select.
|
||||
* @return Returns true if OTADATA invalid, false otherwise.
|
||||
*/
|
||||
bool bootloader_common_ota_select_invalid(const esp_ota_select_entry_t *s);
|
||||
|
||||
/**
|
||||
* @brief Check if the GPIO input is a long hold or a short hold.
|
||||
*
|
||||
@ -91,3 +100,27 @@ bool bootloader_common_label_search(const char *list, char *label);
|
||||
* - ESP_FAIL: An allocation error occurred.
|
||||
*/
|
||||
esp_err_t bootloader_common_get_sha256_of_partition(uint32_t address, uint32_t size, int type, uint8_t *out_sha_256);
|
||||
|
||||
/**
|
||||
* @brief Returns the number of active otadata.
|
||||
*
|
||||
* @param[in] two_otadata Pointer on array from two otadata structures.
|
||||
*
|
||||
* @return The number of active otadata (0 or 1).
|
||||
* - -1: If it does not have active otadata.
|
||||
*/
|
||||
int bootloader_common_get_active_otadata(esp_ota_select_entry_t *two_otadata);
|
||||
|
||||
/**
|
||||
* @brief Returns esp_app_desc structure for app partition. This structure includes app version.
|
||||
*
|
||||
* Returns a description for the requested app partition.
|
||||
* @param[in] partition App partition description.
|
||||
* @param[out] app_desc Structure of info about app.
|
||||
* @return
|
||||
* - ESP_OK: Successful.
|
||||
* - ESP_ERR_INVALID_ARG: The arguments passed are not valid.
|
||||
* - ESP_ERR_NOT_FOUND: app_desc structure is not found. Magic word is incorrect.
|
||||
* - ESP_FAIL: mapping is fail.
|
||||
*/
|
||||
esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t *partition, esp_app_desc_t *app_desc);
|
||||
|
@ -89,6 +89,25 @@ typedef struct {
|
||||
uint32_t data_len;
|
||||
} esp_image_segment_header_t;
|
||||
|
||||
#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */
|
||||
|
||||
/**
|
||||
* @brief Description about application.
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */
|
||||
uint32_t secure_version; /*!< Secure version */
|
||||
uint32_t reserv1[2]; /*!< --- */
|
||||
char version[32]; /*!< Application version */
|
||||
char project_name[32]; /*!< Project name */
|
||||
char time[16]; /*!< Compile time */
|
||||
char date[16]; /*!< Compile date*/
|
||||
char idf_ver[32]; /*!< Version IDF */
|
||||
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
|
||||
uint32_t reserv2[20]; /*!< --- */
|
||||
} esp_app_desc_t;
|
||||
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
|
||||
|
||||
#define ESP_IMAGE_MAX_SEGMENTS 16
|
||||
|
||||
/* Structure to hold on-flash image metadata */
|
||||
|
@ -405,7 +405,6 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode);
|
||||
*
|
||||
* For ORIG mode:
|
||||
* Bluetooth modem sleep is enabled in controller start up by default if CONFIG_BTDM_CONTROLLER_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request".
|
||||
* Note that currently there is problem in the combination use of bluetooth modem sleep and Dynamic Frequency Scaling(DFS). So do not enable DFS if bluetooth modem sleep is in use.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
|
@ -1140,7 +1140,7 @@ esp_err_t esp_ble_passkey_reply(esp_bd_addr_t bd_addr, bool accept, uint32_t pas
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reply the confirm value to the peer device in the legacy connection stage.
|
||||
* @brief Reply the confirm value to the peer device in the secure connection stage.
|
||||
*
|
||||
* @param[in] bd_addr : BD address of the peer device
|
||||
* @param[in] accept : numbers to compare are the same or different.
|
||||
|
@ -63,6 +63,7 @@
|
||||
#define CONFIG_MBEDTLS_PEM_WRITE_C 1
|
||||
#define CONFIG_BT_SPP_ENABLED 1
|
||||
#define CONFIG_BT_RESERVE_DRAM 0xdb5c
|
||||
#define CONFIG_APP_COMPILE_TIME_DATE 1
|
||||
#define CONFIG_CXX_EXCEPTIONS 1
|
||||
#define CONFIG_FATFS_FS_LOCK 0
|
||||
#define CONFIG_IP_LOST_TIMER_INTERVAL 120
|
||||
@ -76,6 +77,7 @@
|
||||
#define CONFIG_SPIRAM_SUPPORT 1
|
||||
#define CONFIG_LWIP_MAX_SOCKETS 10
|
||||
#define CONFIG_LWIP_NETIF_LOOPBACK 1
|
||||
#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread"
|
||||
#define CONFIG_EMAC_TASK_PRIORITY 20
|
||||
#define CONFIG_TIMER_TASK_STACK_DEPTH 2048
|
||||
#define CONFIG_TCP_MSS 1436
|
||||
@ -85,7 +87,6 @@
|
||||
#define CONFIG_TCPIP_TASK_AFFINITY_CPU0 1
|
||||
#define CONFIG_FATFS_CODEPAGE 850
|
||||
#define CONFIG_ULP_COPROC_RESERVE_MEM 512
|
||||
#define CONFIG_MB_UART_RXD 34
|
||||
#define CONFIG_LWIP_MAX_UDP_PCBS 16
|
||||
#define CONFIG_ESPTOOLPY_BAUD 921600
|
||||
#define CONFIG_INT_WDT_CHECK_CPU1 1
|
||||
@ -120,6 +121,7 @@
|
||||
#define CONFIG_SCAN_DUPLICATE_BY_DEVICE_ADDR 1
|
||||
#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1
|
||||
#define CONFIG_MB_SERIAL_TASK_STACK_SIZE 2048
|
||||
#define CONFIG_MBEDTLS_PSK_MODES 1
|
||||
#define CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO 1
|
||||
#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60
|
||||
#define CONFIG_SPIFFS_USE_MAGIC 1
|
||||
@ -164,11 +166,12 @@
|
||||
#define CONFIG_BTDM_LPCLK_SEL_MAIN_XTAL 1
|
||||
#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1
|
||||
#define CONFIG_LIBSODIUM_USE_MBEDTLS_SHA 1
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_PSK 1
|
||||
#define CONFIG_SW_COEXIST_PREFERENCE_WIFI 1
|
||||
#define CONFIG_DMA_RX_BUF_NUM 10
|
||||
#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_PSK 1
|
||||
#define CONFIG_TCP_SYNMAXRTX 6
|
||||
#define CONFIG_MB_UART_RTS 32
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1
|
||||
#define CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF 0
|
||||
#define CONFIG_HEAP_POISONING_LIGHT 1
|
||||
@ -187,6 +190,7 @@
|
||||
#define CONFIG_LWIP_SO_REUSE_RXTOALL 1
|
||||
#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT 20
|
||||
#define CONFIG_PARTITION_TABLE_SINGLE_APP 1
|
||||
#define CONFIG_XTENSA_IMPL 1
|
||||
#define CONFIG_UNITY_ENABLE_FLOAT 1
|
||||
#define CONFIG_ESP32_WIFI_RX_BA_WIN 6
|
||||
#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1
|
||||
@ -198,7 +202,9 @@
|
||||
#define CONFIG_MB_QUEUE_LENGTH 20
|
||||
#define CONFIG_SW_COEXIST_PREFERENCE_VALUE 0
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1
|
||||
#define CONFIG_OV2640_SUPPORT 1
|
||||
#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_PSK 1
|
||||
#define CONFIG_PPP_SUPPORT 1
|
||||
#define CONFIG_SPIRAM_SPEED_40M 1
|
||||
#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE 2048
|
||||
@ -228,6 +234,7 @@
|
||||
#define CONFIG_LOG_BOOTLOADER_LEVEL 0
|
||||
#define CONFIG_MBEDTLS_TLS_ENABLED 1
|
||||
#define CONFIG_LWIP_MAX_RAW_PCBS 16
|
||||
#define CONFIG_BTU_TASK_STACK_SIZE 4096
|
||||
#define CONFIG_SMP_ENABLE 1
|
||||
#define CONFIG_SPIRAM_SIZE -1
|
||||
#define CONFIG_MBEDTLS_SSL_SESSION_TICKETS 1
|
||||
@ -259,15 +266,17 @@
|
||||
#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1
|
||||
#define CONFIG_WL_SECTOR_SIZE 4096
|
||||
#define CONFIG_ESP32_DEBUG_OCDAWARE 1
|
||||
#define CONFIG_MB_UART_TXD 33
|
||||
#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1
|
||||
#define CONFIG_TIMER_TASK_PRIORITY 1
|
||||
#define CONFIG_PPP_PAP_SUPPORT 1
|
||||
#define CONFIG_MBEDTLS_TLS_CLIENT 1
|
||||
#define CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI 1
|
||||
#define CONFIG_BT_ENABLED 1
|
||||
#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY 1
|
||||
#define CONFIG_BT_SSP_ENABLED 1
|
||||
#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1
|
||||
#define CONFIG_MONITOR_BAUD 115200
|
||||
#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT -1
|
||||
#define CONFIG_ESP32_DEBUG_STUBS_ENABLE 1
|
||||
#define CONFIG_TCPIP_LWIP 1
|
||||
#define CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST 1
|
||||
@ -278,6 +287,7 @@
|
||||
#define CONFIG_MBEDTLS_HAVE_TIME 1
|
||||
#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1
|
||||
#define CONFIG_TCP_QUEUE_OOSEQ 1
|
||||
#define CONFIG_FATFS_ALLOC_PREFER_EXTRAM 1
|
||||
#define CONFIG_GATTS_ENABLE 1
|
||||
#define CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE 0
|
||||
#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1
|
||||
@ -287,6 +297,7 @@
|
||||
#define CONFIG_SUPPORT_TERMIOS 1
|
||||
#define CONFIG_CLASSIC_BT_ENABLED 1
|
||||
#define CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK 1
|
||||
#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_PSK 1
|
||||
#define CONFIG_OPENSSL_ASSERT_DO_NOTHING 1
|
||||
#define CONFIG_IDF_TARGET "esp32"
|
||||
#define CONFIG_WL_SECTOR_SIZE_4096 1
|
||||
@ -324,6 +335,7 @@
|
||||
#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1
|
||||
#define CONFIG_ESPTOOLPY_PORT "/dev/cu.usbserial-DO00EAB0"
|
||||
#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS 1
|
||||
#define CONFIG_TASK_WDT_PANIC 1
|
||||
#define CONFIG_UNITY_ENABLE_DOUBLE 1
|
||||
#define CONFIG_BLUEDROID_PINNED_TO_CORE 0
|
||||
#define CONFIG_BTDM_MODEM_SLEEP_MODE_ORIG 1
|
||||
|
@ -139,6 +139,7 @@ typedef struct {
|
||||
int dma_buf_count; /*!< I2S DMA Buffer Count */
|
||||
int dma_buf_len; /*!< I2S DMA Buffer Length */
|
||||
bool use_apll; /*!< I2S using APLL as main I2S clock, enable it to get accurate clock */
|
||||
bool tx_desc_auto_clear; /*!< I2S auto clear tx descriptor if there is underflow condition (helps in avoiding noise in case of data unavailability) */
|
||||
int fixed_mclk; /*!< I2S using fixed MCLK output. If use_apll = true and fixed_mclk > 0, then the clock output for i2s is fixed and equal to the fixed_mclk value.*/
|
||||
} i2s_config_t;
|
||||
|
||||
|
@ -80,6 +80,19 @@ typedef enum {
|
||||
RMT_CARRIER_LEVEL_MAX
|
||||
} rmt_carrier_level_t;
|
||||
|
||||
typedef enum {
|
||||
RMT_CHANNEL_UNINIT = 0, /*!< RMT channel uninitialized */
|
||||
RMT_CHANNEL_IDLE = 1, /*!< RMT channel status idle */
|
||||
RMT_CHANNEL_BUSY = 2, /*!< RMT channel status busy */
|
||||
} rmt_channel_status_t;
|
||||
|
||||
/**
|
||||
* @brief Data struct of RMT channel status
|
||||
*/
|
||||
typedef struct {
|
||||
rmt_channel_status_t status[RMT_CHANNEL_MAX]; /*!< Store the current status of each channel */
|
||||
} rmt_channel_status_result_t;
|
||||
|
||||
/**
|
||||
* @brief Data struct of RMT TX configure parameters
|
||||
*/
|
||||
@ -496,6 +509,7 @@ esp_err_t rmt_set_idle_level(rmt_channel_t channel, bool idle_out_en, rmt_idle_l
|
||||
* @param channel RMT channel (0-7)
|
||||
*
|
||||
* @param status Pointer to accept channel status.
|
||||
* Please refer to RMT_CHnSTATUS_REG(n=0~7) in `rmt_reg.h` for more details of each field.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
@ -679,6 +693,19 @@ esp_err_t rmt_driver_install(rmt_channel_t channel, size_t rx_buf_size, int intr
|
||||
*/
|
||||
esp_err_t rmt_driver_uninstall(rmt_channel_t channel);
|
||||
|
||||
/**
|
||||
* @brief Get the current status of eight channels.
|
||||
*
|
||||
* @note Do not call this function if it is possible that `rmt_driver_uninstall` will be called at the same time.
|
||||
*
|
||||
* @param[out] channel_status store the current status of each channel
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter is NULL
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t rmt_get_channel_status(rmt_channel_status_result_t *channel_status);
|
||||
|
||||
/**
|
||||
* @brief RMT send waveform from rmt_item array.
|
||||
*
|
||||
|
@ -73,7 +73,10 @@ struct spi_slave_transaction_t {
|
||||
size_t length; ///< Total data length, in bits
|
||||
size_t trans_len; ///< Transaction data length, in bits
|
||||
const void *tx_buffer; ///< Pointer to transmit buffer, or NULL for no MOSI phase
|
||||
void *rx_buffer; ///< Pointer to receive buffer, or NULL for no MISO phase
|
||||
void *rx_buffer; /**< Pointer to receive buffer, or NULL for no MISO phase.
|
||||
* When the DMA is anabled, must start at WORD boundary (``rx_buffer%4==0``),
|
||||
* and has length of a multiple of 4 bytes.
|
||||
*/
|
||||
void *user; ///< User-defined variable. Can be used to store eg transaction ID.
|
||||
};
|
||||
|
||||
|
@ -801,7 +801,7 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag);
|
||||
* light sleep. This function allows setting the threshold value.
|
||||
*
|
||||
* Stop bit and parity bits (if enabled) also contribute to the number of edges.
|
||||
* For example, letter 'a' with ASCII code 97 is encoded as 010001101 on the wire
|
||||
* For example, letter 'a' with ASCII code 97 is encoded as 0100001101 on the wire
|
||||
* (with 8n1 configuration), start and stop bits included. This sequence has 3
|
||||
* positive edges (transitions from 0 to 1). Therefore, to wake up the system
|
||||
* when 'a' is sent, set wakeup_threshold=3.
|
||||
@ -813,7 +813,10 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag);
|
||||
* correct baud rate all the time, select REF_TICK as UART clock source,
|
||||
* by setting use_ref_tick field in uart_config_t to true.
|
||||
*
|
||||
* @note in ESP32, UART2 does not support light sleep wakeup feature.
|
||||
* @note in ESP32, the wakeup signal can only be input via IO_MUX (i.e.
|
||||
* GPIO3 should be configured as function_1 to wake up UART0,
|
||||
* GPIO9 should be configured as function_5 to wake up UART1), UART2
|
||||
* does not support light sleep wakeup feature.
|
||||
*
|
||||
* @param uart_num UART number
|
||||
* @param wakeup_threshold number of RX edges for light sleep wakeup, value is 3 .. 0x3ff.
|
||||
|
336
tools/sdk/include/esp-face/dl_lib.h
Normal file
336
tools/sdk/include/esp-face/dl_lib.h
Normal file
@ -0,0 +1,336 @@
|
||||
#ifndef DL_LIB_H
|
||||
#define DL_LIB_H
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dl_lib_matrix.h"
|
||||
#include "dl_lib_matrixq.h"
|
||||
#include "dl_lib_matrix3d.h"
|
||||
#include "dl_lib_matrix3dq.h"
|
||||
|
||||
typedef int padding_state;
|
||||
/**
|
||||
* @brief Does a fast version of the exp() operation on a floating point number.
|
||||
*
|
||||
* As described in https://codingforspeed.com/using-faster-exponential-approximation/
|
||||
* Should be good til an input of 5 or so with a steps factor of 8.
|
||||
*
|
||||
* @param in Floating point input
|
||||
* @param steps Approximation steps. More is more precise. 8 or 10 should be good enough for most purposes.
|
||||
* @return Exp()'ed output
|
||||
*/
|
||||
fptp_t fast_exp(double x, int steps);
|
||||
|
||||
/**
|
||||
* @brief Does a softmax operation on a matrix.
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so,
|
||||
output results overwrite the input.
|
||||
*/
|
||||
void dl_softmax(const dl_matrix2d_t *in,
|
||||
dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a softmax operation on a quantized matrix.
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_softmax_q(const dl_matrix2dq_t *in, dl_matrix2dq_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a sigmoid operation on a floating point number
|
||||
*
|
||||
* @param in Floating point input
|
||||
* @return Sigmoid output
|
||||
*/
|
||||
fptp_t dl_sigmoid_op(fptp_t in);
|
||||
|
||||
/**
|
||||
* @brief Does a sigmoid operation on a matrix.
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_sigmoid(const dl_matrix2d_t *in, dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a tanh operation on a floating point number
|
||||
*
|
||||
* @param in Floating point input number
|
||||
* @return Tanh value
|
||||
*/
|
||||
fptp_t dl_tanh_op(fptp_t v);
|
||||
|
||||
/**
|
||||
* @brief Does a tanh operation on a matrix.
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_tanh(const dl_matrix2d_t *in, dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a relu (Rectifier Linear Unit) operation on a floating point number
|
||||
*
|
||||
* @param in Floating point input
|
||||
* @param clip If value is higher than this, it will be clipped to this value
|
||||
* @return Relu output
|
||||
*/
|
||||
fptp_t dl_relu_op(fptp_t in, fptp_t clip);
|
||||
|
||||
/**
|
||||
* @brief Does a ReLu operation on a matrix.
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param clip If values are higher than this, they will be clipped to this value
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_relu(const dl_matrix2d_t *in, fptp_t clip, dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Fully connected layer operation
|
||||
*
|
||||
* @param in Input vector
|
||||
* @param weight Weights of the neurons
|
||||
* @param bias Biases for the neurons. Can be NULL if a bias of 0 is required.
|
||||
* @param out Output array. Outputs are placed here. Needs to be an initialized, weight->w by in->h in size, matrix.
|
||||
*/
|
||||
void dl_fully_connect_layer(const dl_matrix2d_t *in,
|
||||
const dl_matrix2d_t *weight,
|
||||
const dl_matrix2d_t *bias,
|
||||
dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Pre-calculate the sqrtvari variable for the batch_normalize function.
|
||||
* The sqrtvari matrix depends on the variance and epsilon values, which normally are constant. Hence,
|
||||
* this matrix only needs to be calculated once. This function does that.
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
void dl_batch_normalize_get_sqrtvar(const dl_matrix2d_t *variance,
|
||||
fptp_t epsilon,
|
||||
dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Batch-normalize a matrix
|
||||
*
|
||||
* @param m The matrix to normalize
|
||||
* @param offset Offset matrix
|
||||
* @param scale Scale matrix
|
||||
* @param mean Mean matrix
|
||||
* @param sqrtvari Matrix precalculated using dl_batch_normalize_get_sqrtvar
|
||||
* @return
|
||||
*/
|
||||
void dl_batch_normalize(dl_matrix2d_t *m,
|
||||
const dl_matrix2d_t *offset,
|
||||
const dl_matrix2d_t *scale,
|
||||
const dl_matrix2d_t *mean,
|
||||
const dl_matrix2d_t *sqrtvari);
|
||||
|
||||
/**
|
||||
* @brief Do a basic LSTM layer pass.
|
||||
*
|
||||
* @warning Returns state_h pointer, so do not free result.
|
||||
|
||||
* @param in Input vector
|
||||
* @param state_c Internal state of the LSTM network
|
||||
* @param state_h Internal state (previous output values) of the LSTM network
|
||||
* @param weights Weights for the neurons
|
||||
* @param bias Bias for the neurons. Can be NULL if no bias is required
|
||||
* @return Output values of the neurons
|
||||
*/
|
||||
dl_matrix2d_t *dl_basic_lstm_layer(const dl_matrix2d_t *in,
|
||||
dl_matrix2d_t *state_c,
|
||||
dl_matrix2d_t *state_h,
|
||||
const dl_matrix2d_t *weight,
|
||||
const dl_matrix2d_t *bias);
|
||||
|
||||
/**
|
||||
* @brief Do a basic LSTM layer pass, partial quantized version.
|
||||
* This LSTM function accepts 16-bit fixed-point weights and 32-bit float-point bias.
|
||||
*
|
||||
* @warning Returns state_h pointer, so do not free result.
|
||||
|
||||
* @param in Input vector
|
||||
* @param state_c Internal state of the LSTM network
|
||||
* @param state_h Internal state (previous output values) of the LSTM network
|
||||
* @param weights Weights for the neurons, need to be quantised
|
||||
* @param bias Bias for the neurons. Can be NULL if no bias is required
|
||||
* @return Output values of the neurons
|
||||
*/
|
||||
dl_matrix2d_t *dl_basic_lstm_layer_quantised_weights(const dl_matrix2d_t *in,
|
||||
dl_matrix2d_t *state_c,
|
||||
dl_matrix2d_t *state_h,
|
||||
const dl_matrix2dq_t *weight,
|
||||
const dl_matrix2d_t *bias);
|
||||
|
||||
/**
|
||||
* @brief Do a fully-connected layer pass, fully-quantized version.
|
||||
*
|
||||
* @param in Input vector
|
||||
* @param weight Weights of the neurons
|
||||
* @param bias Bias values of the neurons. Can be NULL if no bias is needed.
|
||||
* @param shift Number of bits to shift the result back by. See dl_lib_matrixq.h for more info
|
||||
* @return Output values of the neurons
|
||||
*/
|
||||
void dl_fully_connect_layer_q(const dl_matrix2dq_t *in,
|
||||
const dl_matrix2dq_t *weight,
|
||||
const dl_matrix2dq_t *bias,
|
||||
dl_matrix2dq_t *out,
|
||||
int shift);
|
||||
|
||||
/**
|
||||
* @brief Do a basic LSTM layer pass, fully-quantized version
|
||||
*
|
||||
* @warning Returns state_h pointer, so do not free result.
|
||||
|
||||
* @param in Input vector
|
||||
* @param state_c Internal state of the LSTM network
|
||||
* @param state_h Internal state (previous output values) of the LSTM network
|
||||
* @param weights Weights for the neurons
|
||||
* @param bias Bias for the neurons. Can be NULL if no bias is required
|
||||
* @param shift Number of bits to shift the result back by. See dl_lib_matrixq.h for more info
|
||||
* @return Output values of the neurons
|
||||
*/
|
||||
dl_matrix2dq_t *dl_basic_lstm_layer_q(const dl_matrix2dq_t *in,
|
||||
dl_matrix2dq_t *state_c,
|
||||
dl_matrix2dq_t *state_h,
|
||||
const dl_matrix2dq_t *weight,
|
||||
const dl_matrix2dq_t *bias,
|
||||
int shift);
|
||||
|
||||
/**
|
||||
* @brief Batch-normalize a matrix, fully-quantized version
|
||||
*
|
||||
* @param m The matrix to normalize
|
||||
* @param offset Offset matrix
|
||||
* @param scale Scale matrix
|
||||
* @param mean Mean matrix
|
||||
* @param sqrtvari Matrix precalculated using dl_batch_normalize_get_sqrtvar
|
||||
* @param shift Number of bits to shift the result back by. See dl_lib_matrixq.h for more info
|
||||
* @return
|
||||
*/
|
||||
void dl_batch_normalize_q(dl_matrix2dq_t *m,
|
||||
const dl_matrix2dq_t *offset,
|
||||
const dl_matrix2dq_t *scale,
|
||||
const dl_matrix2dq_t *mean,
|
||||
const dl_matrix2dq_t *sqrtvari,
|
||||
int shift);
|
||||
|
||||
/**
|
||||
* @brief Does a relu (Rectifier Linear Unit) operation on a fixed-point number
|
||||
* This accepts and returns fixed-point 32-bit number with the last 15 bits being the bits after the decimal
|
||||
* point. (Equivalent to a mantissa in a quantized matrix with exponent -15.)
|
||||
*
|
||||
* @param in Fixed-point input
|
||||
* @param clip If value is higher than this, it will be clipped to this value
|
||||
* @return Relu output
|
||||
*/
|
||||
qtp_t dl_relu_q_op(qtp_t in,
|
||||
qtp_t clip);
|
||||
|
||||
/**
|
||||
* @brief Does a ReLu operation on a matrix, quantized version
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param clip If values are higher than this, they will be clipped to this value
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_relu_q(const dl_matrix2dq_t *in,
|
||||
fptp_t clip,
|
||||
dl_matrix2dq_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a sigmoid operation on a fixed-point number.
|
||||
* This accepts and returns a fixed-point 32-bit number with the last 15 bits being the bits after the decimal
|
||||
* point. (Equivalent to a mantissa in a quantized matrix with exponent -15.)
|
||||
*
|
||||
* @param in Fixed-point input
|
||||
* @return Sigmoid output
|
||||
*/
|
||||
int dl_sigmoid_op_q(const int in);
|
||||
|
||||
/**
|
||||
* @brief Does a sigmoid operation on a matrix, quantized version
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_sigmoid_q(const dl_matrix2dq_t *in,
|
||||
dl_matrix2dq_t *out);
|
||||
|
||||
/**
|
||||
* @brief Does a tanh operation on a matrix, quantized version
|
||||
*
|
||||
* @param in Input matrix
|
||||
* @param out Output matrix. Can be the same as the input matrix; if so, output results overwrite the input.
|
||||
*/
|
||||
void dl_tanh_q(const dl_matrix2dq_t *in,
|
||||
dl_matrix2dq_t *out);
|
||||
|
||||
/**
|
||||
* @brief Do a basic CNN layer pass.
|
||||
*
|
||||
* @Warning This just supports the single channel input image, and the output is single row matrix.
|
||||
That is to say, the height of output is 1, and the weight of output is out_channels*out_image_width*out_image_height
|
||||
*
|
||||
* @param in Input single channel image
|
||||
* @param weight Weights of the neurons, weight->w = out_channels, weight->h = filter_width*filter_height
|
||||
* @param bias Bias for the CNN layer.
|
||||
* @param filter_height The height of convolution kernel
|
||||
* @param filter_width The width of convolution kernel
|
||||
* @param out_channels The number of output channels of convolution kernel
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param pad One of `"VALID"` or `"SAME"`, 0 is "VALID" and the other is "SAME"
|
||||
* @param out The result of CNN layer, out->h=1.
|
||||
* @return The result of CNN layer.
|
||||
*/
|
||||
dl_matrix2d_t *dl_basic_conv_layer(const dl_matrix2d_t *in,
|
||||
const dl_matrix2d_t *weight,
|
||||
const dl_matrix2d_t *bias,
|
||||
int filter_width,
|
||||
int filter_height,
|
||||
const int out_channels,
|
||||
const int stride_x,
|
||||
const int stride_y,
|
||||
padding_state pad,
|
||||
const dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Do a basic CNN layer pass, quantised wersion.
|
||||
*
|
||||
* @Warning This just supports the single channel input image, and the output is single row matrix.
|
||||
That is to say, the height of output is 1, and the weight of output is out_channels*out_image_width*out_image_height
|
||||
*
|
||||
* @param in Input single channel image
|
||||
* @param weight Weights of the neurons, weight->w = out_channels, weight->h = filter_width*filter_height,
|
||||
* @param bias Bias of the neurons.
|
||||
* @param filter_height The height of convolution kernel
|
||||
* @param filter_width The width of convolution kernel
|
||||
* @param out_channels The number of output channels of convolution kernel
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param pad One of `"VALID"` or `"SAME"`, 0 is "VALID" and the other is "SAME"
|
||||
* @param out The result of CNN layer, out->h=1
|
||||
* @return The result of CNN layer
|
||||
*/
|
||||
dl_matrix2d_t *dl_basic_conv_layer_quantised_weight(const dl_matrix2d_t *in,
|
||||
const dl_matrix2dq_t *weight,
|
||||
const dl_matrix2d_t *bias,
|
||||
int filter_width,
|
||||
int filter_height,
|
||||
const int out_channels,
|
||||
const int stride_x,
|
||||
const int stride_y,
|
||||
padding_state pad,
|
||||
const dl_matrix2d_t *out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
47
tools/sdk/include/esp-face/dl_lib_coefgetter_if.h
Normal file
47
tools/sdk/include/esp-face/dl_lib_coefgetter_if.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef DL_LIB_COEFGETTER_IF_H
|
||||
#define DL_LIB_COEFGETTER_IF_H
|
||||
|
||||
#include "dl_lib_matrix.h"
|
||||
#include "dl_lib_matrixq.h"
|
||||
#include "dl_lib_matrix3d.h"
|
||||
#include "dl_lib_matrix3dq.h"
|
||||
|
||||
//Set this if the coefficient requested is a batch-normalization popvar matrix which needs to be preprocessed by
|
||||
//dl_batch_normalize_get_sqrtvar first.
|
||||
#define COEF_GETTER_HINT_BNVAR (1<<0)
|
||||
|
||||
/*
|
||||
This struct describes the basic information of model data:
|
||||
word_num: the number of wake words or speech commands
|
||||
word_list: the name list of wake words or speech commands
|
||||
thres_list: the threshold list of wake words or speech commands
|
||||
info_str: the string used to reflect the version and information of model data
|
||||
which consist of the architecture of network, the version of model data, wake words and their threshold
|
||||
*/
|
||||
typedef struct {
|
||||
int word_num;
|
||||
char **word_list;
|
||||
int *win_list;
|
||||
float *thresh_list;
|
||||
char *info_str;
|
||||
} model_info_t;
|
||||
|
||||
/*
|
||||
This struct describes a generic coefficient getter: a way to get the constant coefficients needed for a neural network.
|
||||
For the two getters, the name describes the name of the coefficient matrix, usually the same as the Numpy filename the
|
||||
coefficient was originally stored in. The arg argument can be used to optionally pass an additional user-defined argument
|
||||
to the getter (e.g. the directory to look for files in the case of the Numpy file loader getter). The hint argument
|
||||
is a bitwise OR of the COEF_GETTER_HINT_* flags or 0 when none is needed. Use the free_f/free_q functions to release the
|
||||
memory for the returned matrices, when applicable.
|
||||
*/
|
||||
typedef struct {
|
||||
const dl_matrix2d_t* (*getter_f)(const char *name, void *arg, int hint);
|
||||
const dl_matrix2dq_t* (*getter_q)(const char *name, void *arg, int hint);
|
||||
const dl_matrix3d_t* (*getter_3d)(const char *name, void *arg, int hint);
|
||||
const dl_matrix3dq_t* (*getter_3dq)(const char *name, void *arg, int hint);
|
||||
void (*free_f)(const dl_matrix2d_t *m);
|
||||
void (*free_q)(const dl_matrix2dq_t *m);
|
||||
const model_info_t* (*getter_info)(void *arg);
|
||||
} model_coeff_getter_t;
|
||||
|
||||
#endif
|
216
tools/sdk/include/esp-face/dl_lib_matrix.h
Normal file
216
tools/sdk/include/esp-face/dl_lib_matrix.h
Normal file
@ -0,0 +1,216 @@
|
||||
#ifndef DL_LIB_MATRIX_H
|
||||
#define DL_LIB_MATRIX_H
|
||||
|
||||
typedef float fptp_t;
|
||||
|
||||
|
||||
//Flags for matrices
|
||||
#define DL_MF_FOREIGNDATA (1<<0) /*< Matrix *item data actually points to another matrix and should not be freed */
|
||||
|
||||
//'Normal' float matrix
|
||||
typedef struct {
|
||||
int w; /*< Width */
|
||||
int h; /*< Height */
|
||||
int stride; /*< Row stride, essentially how many items to skip to get to the same position in the next row */
|
||||
int flags; /*< Flags. OR of DL_MF_* values */
|
||||
fptp_t *item; /*< Pointer to item array */
|
||||
} dl_matrix2d_t;
|
||||
|
||||
//Macro to quickly access the raw items in a matrix
|
||||
#define DL_ITM(m, x, y) m->item[(x)+(y)*m->stride]
|
||||
|
||||
|
||||
//#define DL_ITM3D(m, n, x, y, z) (m)->item[(n) * (m)->stride * (m)->c + (z) * (m)->stride + (y) * (m)->w + (x)]
|
||||
|
||||
/**
|
||||
* @brief Allocate a matrix
|
||||
*
|
||||
* @param w Width of the matrix
|
||||
* @param h Height of the matrix
|
||||
* @return The matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2d_t *dl_matrix_alloc(int w, int h);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Free a matrix
|
||||
* Frees the matrix structure and (if it doesn't have the DL_MF_FOREIGNDATA flag set) the m->items space as well.
|
||||
*
|
||||
* @param m Matrix to free
|
||||
*/
|
||||
void dl_matrix_free(dl_matrix2d_t *m);
|
||||
|
||||
/**
|
||||
* @brief Zero out the matrix
|
||||
* Sets all entries in the matrix to 0.
|
||||
*
|
||||
* @param m Matrix to zero
|
||||
*/
|
||||
void dl_matrix_zero(dl_matrix2d_t *m);
|
||||
|
||||
/**
|
||||
* @brief Generate a new matrix using a range of items from an existing matrix.
|
||||
* When using this, the data of the new matrix is not allocated/copied but it re-uses a pointer
|
||||
* to the existing data. Changing the data in the resulting matrix, as a result, will also change
|
||||
* the data in the existing matrix that has been sliced.
|
||||
*
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
* @param in Old matrix (with foreign data) to re-use. Passing NULL will allocate a new matrix.
|
||||
* @return The resulting slice matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2d_t *dl_matrix_slice(const dl_matrix2d_t *src, int x, int y, int w, int h, dl_matrix2d_t *in);
|
||||
|
||||
/**
|
||||
* @brief select a range of items from an existing matrix and flatten them into one dimension.
|
||||
*
|
||||
* @Warning The results are flattened in row-major order.
|
||||
*
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
* @param in Old matrix to re-use. Passing NULL will allocate a new matrix.
|
||||
* @return The resulting flatten matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2d_t *dl_matrix_flatten(const dl_matrix2d_t *src, int x, int y, int w, int h, dl_matrix2d_t *in);
|
||||
|
||||
/**
|
||||
* @brief Generate a matrix from existing floating-point data
|
||||
*
|
||||
* @param w Width of resulting matrix
|
||||
* @param h Height of resulting matrix
|
||||
* @param data Data to populate matrix with
|
||||
* @return A newaly allocated matrix populated with the given input data, or NULL if out of memory.
|
||||
*/
|
||||
dl_matrix2d_t *dl_matrix_from_data(int w, int h, int stride, const void *data);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Multiply a pair of matrices item-by-item: res=a*b
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Multiplicated data. Can be equal to a or b to overwrite that.
|
||||
*/
|
||||
void dl_matrix_mul(const dl_matrix2d_t *a, const dl_matrix2d_t *b, dl_matrix2d_t *res);
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of two matrices : res=a.b
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Dotproduct data. *Must* be a *different* matrix from a or b!
|
||||
*/
|
||||
void dl_matrix_dot(const dl_matrix2d_t *a, const dl_matrix2d_t *b, dl_matrix2d_t *res);
|
||||
|
||||
/**
|
||||
* @brief Add a pair of matrices item-by-item: res=a-b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Added data. Can be equal to a or b to overwrite that.
|
||||
*/
|
||||
void dl_matrix_add(const dl_matrix2d_t *a, const dl_matrix2d_t *b, dl_matrix2d_t *out);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Divide a pair of matrices item-by-item: res=a/b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Divided data. Can be equal to a or b to overwrite that.
|
||||
*/
|
||||
void dl_matrix_div(const dl_matrix2d_t *a, const dl_matrix2d_t *b, dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Subtract a matrix from another, item-by-item: res=a-b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Subtracted data. Can be equal to a or b to overwrite that.
|
||||
*/
|
||||
void dl_matrix_sub(const dl_matrix2d_t *a, const dl_matrix2d_t *b, dl_matrix2d_t *out);
|
||||
|
||||
/**
|
||||
* @brief Add a constant to every item of the matrix
|
||||
*
|
||||
* @param subj Matrix to add the constant to
|
||||
* @param add The constant
|
||||
*/
|
||||
void dl_matrix_add_const(dl_matrix2d_t *subj, const fptp_t add);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Concatenate the rows of two matrices into a new matrix
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @return A newly allocated array with as avlues a|b
|
||||
*/
|
||||
dl_matrix2d_t *dl_matrix_concat(const dl_matrix2d_t *a, const dl_matrix2d_t *b);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Print the contents of a matrix to stdout. Used for debugging.
|
||||
*
|
||||
* @param a The matrix to print.
|
||||
*/
|
||||
void dl_printmatrix(const dl_matrix2d_t *a);
|
||||
|
||||
/**
|
||||
* @brief Return the average square error given a correct and a test matrix.
|
||||
*
|
||||
* ...Well, more or less. If anything, it gives an indication of the error between
|
||||
* the two. Check the code for the exact implementation.
|
||||
*
|
||||
* @param a First of the two matrices to compare
|
||||
* @param b Second of the two matrices to compare
|
||||
* @return value indicating the relative difference between matrices
|
||||
*/
|
||||
float dl_matrix_get_avg_sq_err(const dl_matrix2d_t *a, const dl_matrix2d_t *b);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if two matrices have the same shape, that is, the same amount of rows and columns
|
||||
*
|
||||
* @param a First of the two matrices to compare
|
||||
* @param b Second of the two matrices to compare
|
||||
* @return true if the two matrices are shaped the same, false otherwise.
|
||||
*/
|
||||
int dl_matrix_same_shape(const dl_matrix2d_t *a, const dl_matrix2d_t *b);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get a specific item from the matrix
|
||||
*
|
||||
* Please use these for external matrix access instead of DL_ITM
|
||||
*
|
||||
* @param m Matrix to access
|
||||
* @param x Column address
|
||||
* @param y Row address
|
||||
* @return Value in that position
|
||||
*/
|
||||
inline static fptp_t dl_matrix_get(const dl_matrix2d_t *m, const int x, const int y) {
|
||||
return DL_ITM(m, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a specific item in the matrix to the given value
|
||||
*
|
||||
* Please use these for external matrix access instead of DL_ITM
|
||||
*
|
||||
* @param m Matrix to access
|
||||
* @param x Column address
|
||||
* @param y Row address
|
||||
* @param val Value to write to that position
|
||||
*/
|
||||
inline static void dl_matrix_set(dl_matrix2d_t *m, const int x, const int y, fptp_t val) {
|
||||
DL_ITM(m, x, y)=val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
420
tools/sdk/include/esp-face/dl_lib_matrix3d.h
Normal file
420
tools/sdk/include/esp-face/dl_lib_matrix3d.h
Normal file
@ -0,0 +1,420 @@
|
||||
#pragma once
|
||||
|
||||
typedef float fptp_t;
|
||||
typedef uint8_t uc_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DL_C_IMPL = 0,
|
||||
DL_XTENSA_IMPL = 1
|
||||
} dl_conv_mode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INPUT_UINT8 = 0,
|
||||
INPUT_FLOAT = 1,
|
||||
} dl_op_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PADDING_VALID = 0,
|
||||
PADDING_SAME = 1,
|
||||
} dl_padding_type;
|
||||
|
||||
/*
|
||||
* Matrix for 3d
|
||||
* @Warning: the sequence of variables is fixed, cannot be modified, otherwise there will be errors in esp_dsp_dot_float
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/******* fix start *******/
|
||||
int w; // Width
|
||||
int h; // Height
|
||||
int c; // Channel
|
||||
int n; // Number, to record filter's out_channels. input and output must be 1
|
||||
int stride;
|
||||
fptp_t *item;
|
||||
/******* fix end *******/
|
||||
} dl_matrix3d_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int w; // Width
|
||||
int h; // Height
|
||||
int c; // Channel
|
||||
int n; // Number, to record filter's out_channels. input and output must be 1
|
||||
int stride;
|
||||
uc_t *item;
|
||||
} dl_matrix3du_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int stride_x;
|
||||
int stride_y;
|
||||
dl_padding_type padding;
|
||||
dl_conv_mode mode;
|
||||
dl_op_type type;
|
||||
} dl_matrix3d_conv_config_t;
|
||||
|
||||
/*
|
||||
* @brief Allocate a 3D matrix with float items, the access sequence is NHWC
|
||||
*
|
||||
* @param n Number of matrix3d, for filters it is out channels, for others it is 1
|
||||
* @param w Width of matrix3d
|
||||
* @param h Height of matrix3d
|
||||
* @param c Channel of matrix3d
|
||||
* @return 3d matrix
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_alloc(int n, int w, int h, int c);
|
||||
|
||||
/*
|
||||
* @brief Allocate a 3D matrix with 8-bits items, the access sequence is NHWC
|
||||
*
|
||||
* @param n Number of matrix3d, for filters it is out channels, for others it is 1
|
||||
* @param w Width of matrix3d
|
||||
* @param h Height of matrix3d
|
||||
* @param c Channel of matrix3d
|
||||
* @return 3d matrix
|
||||
*/
|
||||
dl_matrix3du_t *dl_matrix3du_alloc(int n, int w, int h, int c);
|
||||
|
||||
/*
|
||||
* @brief Free a matrix3d
|
||||
*
|
||||
* @param m matrix3d with float items
|
||||
*/
|
||||
void dl_matrix3d_free(dl_matrix3d_t *m);
|
||||
|
||||
/*
|
||||
* @brief Free a matrix3d
|
||||
*
|
||||
* @param m matrix3d with 8-bits items
|
||||
*/
|
||||
void dl_matrix3du_free(dl_matrix3du_t *m);
|
||||
|
||||
/**
|
||||
* @brief Do a relu (Rectifier Linear Unit) operation, update the input matrix3d
|
||||
*
|
||||
* @param in Floating point input matrix3d
|
||||
* @param clip If value is higher than this, it will be clipped to this value
|
||||
*/
|
||||
void dl_matrix3d_relu(dl_matrix3d_t *m, fptp_t clip);
|
||||
|
||||
/**
|
||||
* @brief Do a leaky relu (Rectifier Linear Unit) operation, update the input matrix3d
|
||||
*
|
||||
* @param in Floating point input matrix3d
|
||||
* @param clip If value is higher than this, it will be clipped to this value
|
||||
* @param alpha If value is less than zero, it will be updated by multiplying this factor
|
||||
*/
|
||||
void dl_matrix3d_leaky_relu(dl_matrix3d_t *m, fptp_t clip, fptp_t alpha);
|
||||
|
||||
/**
|
||||
* @brief Do a softmax operation on a matrix3d
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
*/
|
||||
void dl_matrix3d_softmax(dl_matrix3d_t *m);
|
||||
|
||||
/**
|
||||
* @brief Do a general fully connected layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d, size is (1, w, 1, 1)
|
||||
* @param filter Weights of the neurons, size is (1, w, h, 1)
|
||||
* @param bias Bias for the fc layer, size is (1, 1, 1, h)
|
||||
* @return The result of fc layer, size is (1, 1, 1, h)
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_fc(dl_matrix3d_t *in,
|
||||
dl_matrix3d_t *filter,
|
||||
dl_matrix3d_t *bias);
|
||||
|
||||
/**
|
||||
* @brief Copy a range of float items from an existing matrix to a preallocated matrix
|
||||
*
|
||||
* @param dst The destination slice matrix
|
||||
* @param src The source matrix to slice
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
*/
|
||||
void dl_matrix3d_slice_copy(dl_matrix3d_t *dst,
|
||||
dl_matrix3d_t *src,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h);
|
||||
|
||||
/**
|
||||
* @brief Copy a range of 8-bits items from an existing matrix to a preallocated matrix
|
||||
*
|
||||
* @param dst The destination slice matrix
|
||||
* @param src The source matrix to slice
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
*/
|
||||
void dl_matrix3du_slice_copy(dl_matrix3du_t *dst,
|
||||
dl_matrix3du_t *src,
|
||||
int x,
|
||||
int y,
|
||||
int w,
|
||||
int h);
|
||||
|
||||
/**
|
||||
* @brief Do a general CNN layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param filter Weights of the neurons
|
||||
* @param bias Bias for the CNN layer
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of CNN layer
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_conv(dl_matrix3d_t *in,
|
||||
dl_matrix3d_t *filter,
|
||||
dl_matrix3d_t *bias,
|
||||
int stride_x,
|
||||
int stride_y,
|
||||
int padding,
|
||||
int mode);
|
||||
|
||||
/**
|
||||
* @brief Do a general CNN layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param filter Weights of the neurons
|
||||
* @param bias Bias for the CNN layer
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of CNN layer
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3du_conv(dl_matrix3du_t *in,
|
||||
dl_matrix3d_t *filter,
|
||||
dl_matrix3d_t *bias,
|
||||
int stride_x,
|
||||
int stride_y,
|
||||
int padding,
|
||||
int mode);
|
||||
|
||||
/**
|
||||
* @brief Do a depthwise CNN layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param filter Weights of the neurons
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of depthwise CNN layer
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_depthwise_conv(dl_matrix3d_t *in,
|
||||
dl_matrix3d_t *filter,
|
||||
int stride_x,
|
||||
int stride_y,
|
||||
int padding,
|
||||
int mode);
|
||||
|
||||
/**
|
||||
* @brief Do a mobilenet block forward, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param filter Weights of the neurons
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of depthwise CNN layer
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_mobilenet(void *in,
|
||||
dl_matrix3d_t *dilate,
|
||||
dl_matrix3d_t *depthwise,
|
||||
dl_matrix3d_t *compress,
|
||||
dl_matrix3d_t *bias,
|
||||
dl_matrix3d_t *prelu,
|
||||
dl_matrix3d_conv_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Do a global average pooling layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
*
|
||||
* @return The result of global average pooling layer
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_global_pool(dl_matrix3d_t *in);
|
||||
|
||||
/**
|
||||
* @brief Do a batch normalization operation, update the input matrix3d: input = input * scale + offset
|
||||
*
|
||||
* @param m Input matrix3d
|
||||
* @param scale scale matrix3d, scale = gamma/((moving_variance+sigma)^(1/2))
|
||||
* @param Offset Offset matrix3d, offset = beta-(moving_mean*gamma/((moving_variance+sigma)^(1/2)))
|
||||
*/
|
||||
void dl_matrix3d_batch_normalize(dl_matrix3d_t *m,
|
||||
dl_matrix3d_t *scale,
|
||||
dl_matrix3d_t *offset);
|
||||
|
||||
/**
|
||||
* @brief Add a pair of matrix3d item-by-item: res=in_1+in_2
|
||||
*
|
||||
* @param in_1 First Floating point input matrix3d
|
||||
* @param in_2 Second Floating point input matrix3d
|
||||
*
|
||||
* @return Added data
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_add(dl_matrix3d_t *in_1, dl_matrix3d_t *in_2);
|
||||
|
||||
/**
|
||||
* @brief Do a standard relu operation, update the input matrix3d
|
||||
*
|
||||
* @param m Floating point input matrix3d
|
||||
*/
|
||||
void dl_matrix3d_relu_std(dl_matrix3d_t *m);
|
||||
|
||||
/**
|
||||
* @brief Concatenate the channels of two matrix3ds into a new matrix3d
|
||||
*
|
||||
* @param in_1 First Floating point input matrix3d
|
||||
* @param in_2 Second Floating point input matrix3d
|
||||
*
|
||||
* @return A newly allocated matrix3d with as avlues in_1|in_2
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_concat(dl_matrix3d_t *in_1, dl_matrix3d_t *in_2);
|
||||
|
||||
/**
|
||||
* @brief Concatenate the channels of four matrix3ds into a new matrix3d
|
||||
*
|
||||
* @param in_1 First Floating point input matrix3d
|
||||
* @param in_2 Second Floating point input matrix3d
|
||||
* @param in_3 Third Floating point input matrix3d
|
||||
* @param in_4 Fourth Floating point input matrix3d
|
||||
*
|
||||
* @return A newly allocated matrix3d with as avlues in_1|in_2|in_3|in_4
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_concat_4(dl_matrix3d_t *in_1,
|
||||
dl_matrix3d_t *in_2,
|
||||
dl_matrix3d_t *in_3,
|
||||
dl_matrix3d_t *in_4);
|
||||
|
||||
/**
|
||||
* @brief Concatenate the channels of eight matrix3ds into a new matrix3d
|
||||
*
|
||||
* @param in_1 First Floating point input matrix3d
|
||||
* @param in_2 Second Floating point input matrix3d
|
||||
* @param in_3 Third Floating point input matrix3d
|
||||
* @param in_4 Fourth Floating point input matrix3d
|
||||
* @param in_5 Fifth Floating point input matrix3d
|
||||
* @param in_6 Sixth Floating point input matrix3d
|
||||
* @param in_7 Seventh Floating point input matrix3d
|
||||
* @param in_8 eighth Floating point input matrix3d
|
||||
*
|
||||
* @return A newly allocated matrix3d with as avlues in_1|in_2|in_3|in_4|in_5|in_6|in_7|in_8
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_concat_8(dl_matrix3d_t *in_1,
|
||||
dl_matrix3d_t *in_2,
|
||||
dl_matrix3d_t *in_3,
|
||||
dl_matrix3d_t *in_4,
|
||||
dl_matrix3d_t *in_5,
|
||||
dl_matrix3d_t *in_6,
|
||||
dl_matrix3d_t *in_7,
|
||||
dl_matrix3d_t *in_8);
|
||||
|
||||
/**
|
||||
* @brief Do a mobilefacenet block forward, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param pw Weights of the pointwise conv layer
|
||||
* @param pw_bn_scale The scale params of the batch_normalize layer after the pointwise conv layer
|
||||
* @param pw_bn_offset The offset params of the batch_normalize layer after the pointwise conv layer
|
||||
* @param dw Weights of the depthwise conv layer
|
||||
* @param dw_bn_scale The scale params of the batch_normalize layer after the depthwise conv layer
|
||||
* @param dw_bn_offset The offset params of the batch_normalize layer after the depthwise conv layer
|
||||
* @param pw_linear Weights of the pointwise linear conv layer
|
||||
* @param pw_linear_bn_scale The scale params of the batch_normalize layer after the pointwise linear conv layer
|
||||
* @param pw_linear_bn_offset The offset params of the batch_normalize layer after the pointwise linear conv layer
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of a mobilefacenet block
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_mobilefaceblock(void *in,
|
||||
dl_matrix3d_t *pw,
|
||||
dl_matrix3d_t *pw_bn_scale,
|
||||
dl_matrix3d_t *pw_bn_offset,
|
||||
dl_matrix3d_t *dw,
|
||||
dl_matrix3d_t *dw_bn_scale,
|
||||
dl_matrix3d_t *dw_bn_offset,
|
||||
dl_matrix3d_t *pw_linear,
|
||||
dl_matrix3d_t *pw_linear_bn_scale,
|
||||
dl_matrix3d_t *pw_linear_bn_offset,
|
||||
int stride_x,
|
||||
int stride_y,
|
||||
int padding,
|
||||
int mode,
|
||||
int shortcut);
|
||||
|
||||
/**
|
||||
* @brief Do a mobilefacenet block forward with 1x1 split conv, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input matrix3d
|
||||
* @param pw_1 Weights of the pointwise conv layer 1
|
||||
* @param pw_2 Weights of the pointwise conv layer 2
|
||||
* @param pw_bn_scale The scale params of the batch_normalize layer after the pointwise conv layer
|
||||
* @param pw_bn_offset The offset params of the batch_normalize layer after the pointwise conv layer
|
||||
* @param dw Weights of the depthwise conv layer
|
||||
* @param dw_bn_scale The scale params of the batch_normalize layer after the depthwise conv layer
|
||||
* @param dw_bn_offset The offset params of the batch_normalize layer after the depthwise conv layer
|
||||
* @param pw_linear_1 Weights of the pointwise linear conv layer 1
|
||||
* @param pw_linear_2 Weights of the pointwise linear conv layer 2
|
||||
* @param pw_linear_bn_scale The scale params of the batch_normalize layer after the pointwise linear conv layer
|
||||
* @param pw_linear_bn_offset The offset params of the batch_normalize layer after the pointwise linear conv layer
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect
|
||||
* If ESP_PLATFORM is not defined, this value is not used. Default is 0
|
||||
* @return The result of a mobilefacenet block
|
||||
*/
|
||||
dl_matrix3d_t *dl_matrix3d_mobilefaceblock_split(void *in,
|
||||
dl_matrix3d_t *pw_1,
|
||||
dl_matrix3d_t *pw_2,
|
||||
dl_matrix3d_t *pw_bn_scale,
|
||||
dl_matrix3d_t *pw_bn_offset,
|
||||
dl_matrix3d_t *dw,
|
||||
dl_matrix3d_t *dw_bn_scale,
|
||||
dl_matrix3d_t *dw_bn_offset,
|
||||
dl_matrix3d_t *pw_linear_1,
|
||||
dl_matrix3d_t *pw_linear_2,
|
||||
dl_matrix3d_t *pw_linear_bn_scale,
|
||||
dl_matrix3d_t *pw_linear_bn_offset,
|
||||
int stride_x,
|
||||
int stride_y,
|
||||
int padding,
|
||||
int mode,
|
||||
int shortcut);
|
||||
/**
|
||||
* @brief Print the matrix3d items
|
||||
*
|
||||
* @param m dl_matrix3d_t to be printed
|
||||
* @param message name of matrix
|
||||
*/
|
||||
void dl_matrix3d_print(dl_matrix3d_t *m, char *message);
|
||||
|
||||
/**
|
||||
* @brief Print the matrix3du items
|
||||
*
|
||||
* @param m dl_matrix3du_t to be printed
|
||||
* @param message name of matrix
|
||||
*/
|
||||
void dl_matrix3du_print(dl_matrix3du_t *m, char *message);
|
119
tools/sdk/include/esp-face/dl_lib_matrix3dq.h
Normal file
119
tools/sdk/include/esp-face/dl_lib_matrix3dq.h
Normal file
@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
#include "dl_lib_matrix3d.h"
|
||||
|
||||
typedef int16_t qtp_t;
|
||||
|
||||
/*
|
||||
* Matrix for 3d
|
||||
* @Warning: the sequence of variables is fixed, cannot be modified, otherwise there will be errors in esp_dsp_dot_float
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/******* fix start *******/
|
||||
int w; // Width
|
||||
int h; // Height
|
||||
int c; // Channel
|
||||
int n; // Number, to record filter's out_channels. input and output must be 1
|
||||
int stride;
|
||||
int exponent;
|
||||
qtp_t *item;
|
||||
/******* fix end *******/
|
||||
} dl_matrix3dq_t;
|
||||
|
||||
#define DL_QTP_SHIFT 15
|
||||
#define DL_QTP_RANGE ((1<<DL_QTP_SHIFT)-1)
|
||||
//#define DL_ITMQ(m, x, y) m->itemq[(y)+(x)*m->stride]
|
||||
#define DL_QTP_EXP_NA 255 //non-applicable exponent because matrix is null
|
||||
|
||||
#define DL_SHIFT_AUTO 32
|
||||
|
||||
/*
|
||||
* @brief Allocate a 3D matrix
|
||||
*
|
||||
* @param n,w,h,c number, width, height, channel
|
||||
* @return 3d matrix
|
||||
*/
|
||||
dl_matrix3dq_t *dl_matrix3dq_alloc(int n, int w, int h, int c, int e);
|
||||
|
||||
/*
|
||||
* @brief Free a 3D matrix
|
||||
*
|
||||
* @param m matrix
|
||||
*/
|
||||
void dl_matrix3dq_free(dl_matrix3dq_t *m);
|
||||
|
||||
/**
|
||||
* @brief Zero out the matrix
|
||||
* Sets all entries in the matrix to 0.
|
||||
*
|
||||
* @param m Matrix to zero
|
||||
*/
|
||||
|
||||
dl_matrix3d_t *dl_matrix3d_from_matrixq(dl_matrix3dq_t *m);
|
||||
dl_matrix3dq_t *dl_matrixq_from_matrix3d_qmf(dl_matrix3d_t *m,int exponent);
|
||||
dl_matrix3dq_t *dl_matrixq_from_matrix3d(dl_matrix3d_t *m);
|
||||
/**
|
||||
* @brief Copy a range of items from an existing matrix to a preallocated matrix
|
||||
*
|
||||
* @param in Old matrix (with foreign data) to re-use. Passing NULL will allocate a new matrix.
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
* @return The resulting slice matrix
|
||||
*/
|
||||
void dl_matrix3dq_slice_copy (dl_matrix3dq_t *dst, dl_matrix3dq_t *src, int x, int y, int w, int h);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Do a general CNN layer pass, dimension is (number, width, height, channel)
|
||||
*
|
||||
* @param in Input image
|
||||
* @param filter Weights of the neurons
|
||||
* @param bias Bias for the CNN layer.
|
||||
* @param stride_x The step length of the convolution window in x(width) direction
|
||||
* @param stride_y The step length of the convolution window in y(height) direction
|
||||
* @param padding One of VALID or SAME
|
||||
* @param mode Do convolution using C implement or xtensa implement, 0 or 1, with respect.
|
||||
* If ESP_PLATFORM is not defined, this value is not used.
|
||||
* @return The result of CNN layer.
|
||||
*/
|
||||
dl_matrix3dq_t *dl_matrix3dq_fc (dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_matrix3dq_t *bias, int exponent,int mode);
|
||||
|
||||
dl_matrix3dq_t *dl_matrix3dq_conv (dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_matrix3dq_t *bias,
|
||||
int stride_x, int stride_y, int padding, int exponent, int mode);
|
||||
dl_matrix3dq_t *dl_matrix3dq_conv_normal (dl_matrix3dq_t *in, dl_matrix3dq_t *filter, dl_matrix3dq_t *bias,
|
||||
int stride_x, int stride_y, int padding, int exponent, int mode);
|
||||
|
||||
/**
|
||||
* @brief Print the matrix3d items
|
||||
*
|
||||
* @param m dl_matrix3d_t to be printed
|
||||
* @param message name of matrix
|
||||
*/
|
||||
void dl_matrix3dq_print (dl_matrix3dq_t *m, char *message);
|
||||
|
||||
dl_matrix3dq_t *dl_matrix3dq_depthwise_conv (dl_matrix3dq_t *in, dl_matrix3dq_t *filter,
|
||||
int stride_x, int stride_y, int padding, int exponent, int mode);
|
||||
|
||||
void dl_matrix3dq_relu (dl_matrix3dq_t *m, fptp_t clip);
|
||||
|
||||
|
||||
|
||||
dl_matrix3dq_t *dl_matrix3dq_global_pool (dl_matrix3dq_t *in);
|
||||
void dl_matrix3dq_batch_normalize (dl_matrix3dq_t *m, dl_matrix3dq_t *scale, dl_matrix3dq_t *offset);
|
||||
dl_matrix3dq_t *dl_matrix3dq_add (dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, int exponent);
|
||||
void dl_matrix3dq_relu_std (dl_matrix3dq_t *m);
|
||||
dl_matrix3dq_t *dl_matrix3dq_mobilefaceblock (void *in, dl_matrix3dq_t *pw, dl_matrix3dq_t *pw_bn_scale,dl_matrix3dq_t *pw_bn_offset,
|
||||
dl_matrix3dq_t *dw, dl_matrix3dq_t *dw_bn_scale,dl_matrix3dq_t *dw_bn_offset,
|
||||
dl_matrix3dq_t *pw_linear, dl_matrix3dq_t *pw_linear_bn_scale,dl_matrix3dq_t *pw_linear_bn_offset,
|
||||
int pw_exponent,int dw_exponent,int pw_linear_exponent,int stride_x, int stride_y, int padding, int mode, int shortcut);
|
||||
|
||||
dl_matrix3dq_t *dl_matrix3dq_concat(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2);
|
||||
dl_matrix3dq_t *dl_matrix3dq_concat_4(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, dl_matrix3dq_t *in_3, dl_matrix3dq_t *in_4);
|
||||
dl_matrix3dq_t *dl_matrix3dq_concat_8(dl_matrix3dq_t *in_1, dl_matrix3dq_t *in_2, dl_matrix3dq_t *in_3, dl_matrix3dq_t *in_4, dl_matrix3dq_t *in_5, dl_matrix3dq_t *in_6, dl_matrix3dq_t *in_7, dl_matrix3dq_t *in_8);
|
||||
|
||||
dl_matrix3dq_t *dl_matrix3dq_mobilefaceblock_split (void *in, dl_matrix3dq_t *pw_1, dl_matrix3dq_t *pw_2, dl_matrix3dq_t *pw_bn_scale,dl_matrix3dq_t *pw_bn_offset,
|
||||
dl_matrix3dq_t *dw, dl_matrix3dq_t *dw_bn_scale,dl_matrix3dq_t *dw_bn_offset,
|
||||
dl_matrix3dq_t *pw_linear_1, dl_matrix3dq_t *pw_linear_2, dl_matrix3dq_t *pw_linear_bn_scale,dl_matrix3dq_t *pw_linear_bn_offset,
|
||||
int pw_exponent,int dw_exponent,int pw_linear_exponent,int stride_x, int stride_y, int padding, int mode, int shortcut);
|
359
tools/sdk/include/esp-face/dl_lib_matrixq.h
Normal file
359
tools/sdk/include/esp-face/dl_lib_matrixq.h
Normal file
@ -0,0 +1,359 @@
|
||||
#ifndef DL_LIB_MATRIXQ_H
|
||||
#define DL_LIB_MATRIXQ_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "dl_lib_matrix.h"
|
||||
|
||||
typedef int16_t qtp_t;
|
||||
|
||||
//Quantized matrix. Uses fixed numbers and has the storage for the rows/columns inverted
|
||||
//for easy use as a multiplicand without stressing out the flash cache too much.
|
||||
typedef struct {
|
||||
int w;
|
||||
int h;
|
||||
int stride; //Normally equals h, not w!
|
||||
int flags;
|
||||
int exponent; //The values in items should be multiplied by pow(2,exponent) to get the real values.
|
||||
qtp_t *itemq;
|
||||
} dl_matrix2dq_t;
|
||||
|
||||
#define DL_QTP_SHIFT 15
|
||||
#define DL_QTP_RANGE ((1<<DL_QTP_SHIFT)-1)
|
||||
#define DL_ITMQ(m, x, y) m->itemq[(y)+(x)*m->stride]
|
||||
#define DL_QTP_EXP_NA 255 //non-applicable exponent because matrix is null
|
||||
|
||||
#define DL_SHIFT_AUTO 32
|
||||
|
||||
/**
|
||||
* @info About quantized matrices and shift values
|
||||
*
|
||||
* Grab a coffee (or tea, or hot water) and sit down when you read this for the first
|
||||
* time. Quantized matrices can speed up your operations, but come with some quirks, and
|
||||
* it's good to understand how they work before using them.
|
||||
*
|
||||
* The data in the quantized matrix type is stored similarily to floating-point types:
|
||||
* when storing a real value, the value is stored as a mantissa (base number) and an
|
||||
* exponent. The 'real' value that can be re-derived from those two numbers is something
|
||||
* similar to mantissa*2^exponent. Up to this point, there's not that much difference from
|
||||
* the standard floating point implementations like e.g. IEEE-754.
|
||||
*
|
||||
* The difference with respect to quantized matrices is that for a quantized matrix, it is
|
||||
* assumed all values stored have more-or-less the same order of magnitude. This allows the
|
||||
* matrix to only store all the mantissas, while the exponents are shared; there is only one
|
||||
* exponent for the entire matrix. This makes it quicker to handle matrix operations - the
|
||||
* logic to fix the exponents only needs to happen once, while the rest can be done in simple
|
||||
* integer arithmetic. It also nets us some memory savings - while normally a floating point
|
||||
* number is 32-bit, storing only 16-bit mantissas as the matrix items almost halves the
|
||||
* memory requirements.
|
||||
*
|
||||
* While most of the details of handling the intricacies of the quantized matrixes are done
|
||||
* transparently by the code in dl_lib_matrixq.c, some implementation details leak out,
|
||||
* specifically in places where addition/subtraction/division happens.
|
||||
*
|
||||
* The problem is that the routines do not know what the size of the resulting operation is. For
|
||||
* instance, when adding two matrices of numbers, the resulting numbers *could* be large enough
|
||||
* to overflow the mantissa of the result if the exponent is the same. However, if by default we
|
||||
* assume the mantissas needs to be scaled back, we may lose precision.
|
||||
*
|
||||
* In order to counter this, all operations that have this issue have a ``shift`` argument. If
|
||||
* the argument is zero, the routine will be conservative, that is, increase the exponent of
|
||||
* the result to such an extent it's mathematically impossible a value in the result will exceed
|
||||
* the maximum value that can be stored. However, when this argument is larger than zero, the
|
||||
* algorithm will hold back on this scaling by the indicated amount of bits, preserving precision
|
||||
* but increasing the chance of some of the calculated values not fitting in the mantissa anymore.
|
||||
* If this happens, the value will be clipped to the largest (or, for negative values, smallest)
|
||||
* value possible. (Neural networks usually are okay with this happening for a limited amount
|
||||
* of matrix indices).
|
||||
*
|
||||
* For deciding on these shift values, it is recommended to start with a shift value of one, then
|
||||
* use dl_matrixq_check_sanity on the result. If this indicates clipping, lower the shift value.
|
||||
* If it indicates bits are under-used, increase it. Note that for adding and subtraction, only
|
||||
* shift values of 0 or 1 make sense; these routines will error out if you try to do something
|
||||
* else.
|
||||
*
|
||||
* For neural networks and other noise-tolerant applications, note that even when
|
||||
* dl_matrixq_check_sanity does not indicate any problems, twiddling with the shift value may lead
|
||||
* to slightly improved precision. Feel free to experiment.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Allocate a matrix
|
||||
*
|
||||
* @param w Width of the matrix
|
||||
* @param h Height of the matrix
|
||||
* @return The matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_alloc(int w, int h);
|
||||
|
||||
/**
|
||||
* @brief Convert a floating-point matrix to a quantized matrix
|
||||
*
|
||||
* @param m Floating-point matrix to convert
|
||||
* @param out Quantized matrix to re-use. If NULL, allocate a new one.
|
||||
* @Return The quantized version of the floating-point matrix
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_from_matrix2d(const dl_matrix2d_t *m, dl_matrix2dq_t *out);
|
||||
|
||||
|
||||
/**
|
||||
* TODO: DESCRIBE THIS FUNCTION
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_from_matrix2d_by_qmf(const dl_matrix2d_t *m, dl_matrix2dq_t *out, int m_bit, int f_bit);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Convert a quantized matrix to a floating-point one.
|
||||
*
|
||||
* @param m Floating-point matrix to convert
|
||||
* @param out Quantized matrix to re-use. If NULL, allocate a new one.
|
||||
* @Return The quantized version of the floating-point matrix
|
||||
**/
|
||||
dl_matrix2d_t *dl_matrix2d_from_matrixq(const dl_matrix2dq_t *m, dl_matrix2d_t *out);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Free a quantized matrix
|
||||
* Frees the matrix structure and (if it doesn't have the DL_MF_FOREIGNDATA flag set) the m->items space as well.
|
||||
*
|
||||
* @param m Matrix to free
|
||||
*/
|
||||
void dl_matrixq_free(dl_matrix2dq_t *m);
|
||||
|
||||
/**
|
||||
* @brief Zero out the matrix
|
||||
* Sets all entries in the matrix to 0.
|
||||
*
|
||||
* @param m Matrix to zero
|
||||
*/
|
||||
void dl_matrixq_zero(dl_matrix2dq_t *m);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of two quantized matrices : res=a.b, Result is a fixed-point matrix.
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Dotproduct data. *Must* be a *different* matrix from a or b!
|
||||
* @param shift Shift ratio
|
||||
*/
|
||||
void dl_matrixq_dot(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *res, int shift);
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of two quantized matrices: res=a.b, Result is a floating-point matrix.
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Dotproduct data. *Must* be a *different* matrix from a or b!
|
||||
*/
|
||||
void dl_matrixq_dot_matrix_out(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2d_t *res);
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of two quantized matrices : res=a.b. This always uses the simple & stupid C algo for the dot product.
|
||||
*
|
||||
* Result is a fixed-point matrix.
|
||||
*
|
||||
* Use this only if you expect something is wrong with the accelerated routines that dl_matrixq_dot calls; this function can be
|
||||
* much slower than dl_matrixq_dot .
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Dotproduct data. *Must* be a *different* matrix from a or b!
|
||||
* @param shift Shift ratio
|
||||
*/
|
||||
void dl_matrixq_dot_c_impl(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *res, int shift);
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of two quantized matrices : res=a.b. This always uses the simple & stupid C algo for the dot product.
|
||||
*
|
||||
* Result is a floating-point matrix.
|
||||
*
|
||||
* Use this only if you expect something is wrong with the accelerated routines that dl_matrixq_dot_matrix_out calls; this function can be
|
||||
* much slower than dl_matrixq_dot_matrix_out.
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Dotproduct data. *Must* be a *different* matrix from a or b!
|
||||
*/
|
||||
void dl_matrixq_dot_matrix_out_c_impl(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2d_t *res);
|
||||
|
||||
/**
|
||||
* @brief Do a dotproduct of a floating point and a quantized matrix. Result is a floating-point matrix.
|
||||
*
|
||||
* @param a First multiplicand; float matrix
|
||||
* @param b Second multiplicand; quantized matrix
|
||||
* @param res Dotproduct data; float matrix. *Must* be a *different* matrix from a or b!
|
||||
*/
|
||||
void dl_matrix_matrixq_dot(const dl_matrix2d_t *a, const dl_matrix2dq_t *b, dl_matrix2d_t *res);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Print the contents of a quantized matrix to stdout. Used for debugging.
|
||||
*
|
||||
* @param a The matrix to print.
|
||||
*/
|
||||
void dl_printmatrixq(const dl_matrix2dq_t *a);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Add a pair of quantizedmatrices item-by-item: res=a-b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Added data. Can be equal to a or b to overwrite that.
|
||||
* @param shift Shift value. Only 0 or 1 makes sense here. <ToDo: check>
|
||||
*/
|
||||
void dl_matrixq_add(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *res, int shift);
|
||||
|
||||
/**
|
||||
* @brief Generate a new matrix using a range of items from an existing matrix.
|
||||
* When using this, the data of the new matrix is not allocated/copied but it re-uses a pointer
|
||||
* to the existing data. Changing the data in the resulting matrix, as a result, will also change
|
||||
* the data in the existing matrix that has been sliced.
|
||||
*
|
||||
* @Warning In contrast to the floating point equivalent of this function, the fixed-point version
|
||||
* of this has the issue that as soon as the output exponent of one of the slices changes, the data
|
||||
* in the sliced matrix gets corrupted (because the exponent of that matrix is still the same.) If you
|
||||
* use this function, either treat the slices as read-only, or assume the sliced matrix contains
|
||||
* garbage after modifying the data in one of the slices.
|
||||
*
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
* @param in Old matrix (with foreign data) to re-use. Passing NULL will allocate a new matrix.
|
||||
* @return The resulting slice matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_slice(const dl_matrix2dq_t *src, int x, int y, int w, int h, dl_matrix2dq_t *in);
|
||||
|
||||
/**
|
||||
* @brief select a range of items from an existing matrix and flatten them into one dimension.
|
||||
*
|
||||
* @Warning The results are flattened in row-major order.
|
||||
*
|
||||
* @param x X-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param y Y-offset of the origin of the returned matrix within the sliced matrix
|
||||
* @param w Width of the resulting matrix
|
||||
* @param h Height of the resulting matrix
|
||||
* @param in Old matrix to re-use. Passing NULL will allocate a new matrix.
|
||||
* @return The resulting flatten matrix, or NULL if out of memory
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_flatten(const dl_matrix2dq_t *src, int x, int y, int w, int h, dl_matrix2dq_t *in);
|
||||
|
||||
/**
|
||||
* @brief Subtract a quantized matrix from another, item-by-item: res=a-b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Subtracted data. Can be equal to a or b to overwrite that.
|
||||
* @param shift Shift value. Only 0 or 1 makes sense here. <ToDo: check>
|
||||
*/
|
||||
void dl_matrixq_sub(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *res, int shift);
|
||||
|
||||
/**
|
||||
* @brief Multiply a pair of quantized matrices item-by-item: res=a*b
|
||||
*
|
||||
* @param a First multiplicand
|
||||
* @param b Second multiplicand
|
||||
* @param res Multiplicated data. Can be equal to a or b to overwrite that matrix.
|
||||
*/
|
||||
void dl_matrixq_mul(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *res);
|
||||
|
||||
/**
|
||||
* @brief Divide a pair of quantized matrices item-by-item: res=a/b
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @param res Divided data. Can be equal to a or b to overwrite that.
|
||||
*/
|
||||
void dl_matrixq_div(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b, dl_matrix2dq_t *out, int shift);
|
||||
|
||||
/**
|
||||
* @brief Check if two quantized matrices have the same shape, that is, the same amount of
|
||||
* rows and columns
|
||||
*
|
||||
* @param a First of the two matrices to compare
|
||||
* @param b Second of the two matrices to compare
|
||||
* @return true if the two matrices are shaped the same, false otherwise.
|
||||
*/
|
||||
int dl_matrixq_same_shape(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b);
|
||||
|
||||
/**
|
||||
* @brief Concatenate the rows of two quantized matrices into a new matrix
|
||||
*
|
||||
* @param a First matrix
|
||||
* @param b Second matrix
|
||||
* @return A newly allocated quantized matrix with as values a|b
|
||||
*/
|
||||
dl_matrix2dq_t *dl_matrixq_concat(const dl_matrix2dq_t *a, const dl_matrix2dq_t *b);
|
||||
|
||||
/**
|
||||
* @brief Add a constant to every item of the quantized matrix
|
||||
*
|
||||
* @param subj Matrix to add the constant to
|
||||
* @param add The constant
|
||||
*/
|
||||
void dl_matrixq_add_const(dl_matrix2dq_t *subj, const fptp_t add, int shift);
|
||||
|
||||
/**
|
||||
* @brief Check the sanity of a quantized matrix
|
||||
*
|
||||
* Due to the nature of quantized matrices, depending on the calculations a quantized
|
||||
* matrix is the result of and the shift values chosen in those calculations, a quantized
|
||||
* matrix may have an exponent and mantissas that lead to a loss of precision, either because
|
||||
* most significant mantissa bits are unused, or because a fair amount of mantissas are
|
||||
* clipped. This function checks if this is the case and will report a message to stdout
|
||||
* if significant loss of precision is detected.
|
||||
*
|
||||
* @param m The quantized matrix to check
|
||||
* @param name A string to be displayed in the message if the sanity check fails
|
||||
* @return True if matrix is sane, false otherwise
|
||||
**/
|
||||
|
||||
int dl_matrixq_check_sanity(dl_matrix2dq_t *m, const char *name);
|
||||
|
||||
/**
|
||||
* @brief re-adjust the exponent of the matrix to fit the mantissa better
|
||||
*
|
||||
* This function will shift up all the data in the mantissas so there are no
|
||||
* most-significant bits that are unused in all mantissas. It will also adjust
|
||||
* the exponent to keep the actua values in the matrix the same.
|
||||
*
|
||||
* Some operations done on a matrix, especially operations that re-use the
|
||||
* result of earlier operations done in the same way, can lead to the loss of
|
||||
* data because the exponent of the quantized matrix is never re-adjusted. You
|
||||
* can do that implicitely by calling this function.
|
||||
*
|
||||
* @param m The matrix to re-adjust
|
||||
**/
|
||||
void dl_matrixq_readjust_exp(dl_matrix2dq_t *m);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the floating-point value of a specific item from the quantized matrix
|
||||
*
|
||||
* @param m Matrix to access
|
||||
* @param x Column address
|
||||
* @param y Row address
|
||||
* @return Value in that position
|
||||
*/
|
||||
fptp_t dl_matrixq_get(const dl_matrix2dq_t *m, const int x, const int y);
|
||||
|
||||
/**
|
||||
* @brief Set a specific item in the quantized matrix to the given
|
||||
* floating-point value
|
||||
*
|
||||
* @warning If the given value is more than the exponent in the quantized matrix
|
||||
* allows for, all mantissas in the matrix will be shifted down to make the value
|
||||
* 'fit'. If, however, the exponent is such that the value would result in a
|
||||
* quantized mantissa of 0, nothing is done.
|
||||
*
|
||||
* @param m Matrix to access
|
||||
* @param x Column address
|
||||
* @param y Row address
|
||||
* @param val Value to write to that position
|
||||
*/
|
||||
void dl_matrixq_set(dl_matrix2dq_t *m, const int x, const int y, fptp_t val);
|
||||
|
||||
#endif
|
64
tools/sdk/include/esp-face/fd_forward.h
Normal file
64
tools/sdk/include/esp-face/fd_forward.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "image_util.h"
|
||||
#include "dl_lib.h"
|
||||
#include "mtmn.h"
|
||||
|
||||
static inline mtmn_config_t mtmn_init_config()
|
||||
{
|
||||
mtmn_config_t mtmn_config;
|
||||
mtmn_config.min_face = 80;
|
||||
mtmn_config.pyramid = 0.7;
|
||||
mtmn_config.p_threshold.score = 0.6;
|
||||
mtmn_config.p_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.score = 0.6;
|
||||
mtmn_config.r_threshold.nms = 0.7;
|
||||
mtmn_config.r_threshold.candidate_number = 4;
|
||||
mtmn_config.o_threshold.score = 0.6;
|
||||
mtmn_config.o_threshold.nms = 0.4;
|
||||
mtmn_config.o_threshold.candidate_number = 1;
|
||||
|
||||
return mtmn_config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Do MTMN face detection, return box and landmark infomation.
|
||||
*
|
||||
* @param image_matrix Image matrix, rgb888 format
|
||||
* @param config Configuration of MTMN i.e. score threshold, nms threshold, candidate number threshold, pyramid, min face size
|
||||
* @return box_array_t* A list of boxes and score.
|
||||
*/
|
||||
box_array_t *face_detect(dl_matrix3du_t *image_matrix,
|
||||
mtmn_config_t *config);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
45
tools/sdk/include/esp-face/fr_flash.h
Normal file
45
tools/sdk/include/esp-face/fr_flash.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "fr_forward.h"
|
||||
|
||||
#define FR_FLASH_TYPE 32
|
||||
#define FR_FLASH_SUBTYPE 32
|
||||
#define FR_FLASH_PARTITION_NAME "fr"
|
||||
#define FR_FLASH_INFO_FLAG 12138
|
||||
|
||||
/**
|
||||
* @brief Produce face id according to the input aligned face, and save it to dest_id and flash.
|
||||
*
|
||||
* @param l Face id list
|
||||
* @param aligned_face An aligned face
|
||||
* @return -2 Flash partition not found
|
||||
* @return 0 Enrollment finish
|
||||
* @return >=1 The left piece of aligned faces should be input
|
||||
*/
|
||||
int8_t enroll_face_id_to_flash(face_id_list *l,
|
||||
dl_matrix3du_t *aligned_face);
|
||||
|
||||
/**
|
||||
* @brief Read the enrolled face IDs from the flash.
|
||||
*
|
||||
* @param l Face id list
|
||||
* @return int8_t The number of IDs remaining in flash
|
||||
*/
|
||||
int8_t read_face_id_from_flash(face_id_list *l);
|
||||
|
||||
/**
|
||||
* @brief Delete the enrolled face IDs in the flash.
|
||||
*
|
||||
* @param l Face id list
|
||||
* @return int8_t The number of IDs remaining in flash
|
||||
*/
|
||||
int8_t delete_face_id_in_flash(face_id_list *l);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
116
tools/sdk/include/esp-face/fr_forward.h
Normal file
116
tools/sdk/include/esp-face/fr_forward.h
Normal file
@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "image_util.h"
|
||||
#include "dl_lib.h"
|
||||
#include "frmn.h"
|
||||
|
||||
#define FACE_WIDTH 56
|
||||
#define FACE_HEIGHT 56
|
||||
#define FACE_ID_SIZE 512
|
||||
#define FACE_REC_THRESHOLD 0.5
|
||||
|
||||
#define LEFT_EYE_X 0
|
||||
#define LEFT_EYE_Y 1
|
||||
#define RIGHT_EYE_X 6
|
||||
#define RIGHT_EYE_Y 7
|
||||
#define NOSE_X 4
|
||||
#define NOSE_Y 5
|
||||
|
||||
#define EYE_DIST_SET 16.5f
|
||||
#define NOSE_EYE_RATIO_THRES_MIN 0.49f
|
||||
#define NOSE_EYE_RATIO_THRES_MAX 2.04f
|
||||
|
||||
#define FLASH_INFO_FLAG 12138
|
||||
#define FLASH_PARTITION_NAME "fr"
|
||||
|
||||
/**
|
||||
* @brief HTTP Client events data
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t head; /*!< head index of the id list */
|
||||
uint8_t tail; /*!< tail index of the id list */
|
||||
uint8_t count; /*!< number of enrolled ids */
|
||||
uint8_t size; /*!< max len of id list */
|
||||
uint8_t confirm_times; /*!< images needed for one enrolling */
|
||||
dl_matrix3d_t **id_list; /*!< stores face id vectors */
|
||||
} face_id_list;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize face id list
|
||||
*
|
||||
* @param l Face id list
|
||||
* @param size Size of list, one list contains one vector
|
||||
* @param confirm_times Enroll times for one id
|
||||
* @return dl_matrix3du_t* Size: 1xFACE_WIDTHxFACE_HEIGHTx3
|
||||
*/
|
||||
void face_id_init(face_id_list *l, uint8_t size, uint8_t confirm_times);
|
||||
|
||||
/**
|
||||
* @brief Alloc memory for aligned face.
|
||||
*
|
||||
* @return dl_matrix3du_t* Size: 1xFACE_WIDTHxFACE_HEIGHTx3
|
||||
*/
|
||||
dl_matrix3du_t *aligned_face_alloc();
|
||||
|
||||
/**
|
||||
* @brief Align detected face to average face according to landmark
|
||||
*
|
||||
* @param onet_boxes Output of MTMN with box and landmark
|
||||
* @param src Image matrix, rgb888 format
|
||||
* @param dest Output image
|
||||
* @return ESP_OK Input face is good for recognition
|
||||
* @return ESP_FAIL Input face is not good for recognition
|
||||
*/
|
||||
int8_t align_face(box_array_t *onet_boxes,
|
||||
dl_matrix3du_t *src,
|
||||
dl_matrix3du_t *dest);
|
||||
|
||||
/**
|
||||
* @brief Add src_id to dest_id
|
||||
*
|
||||
* @param dest_id
|
||||
* @param src_id
|
||||
*/
|
||||
void add_face_id(dl_matrix3d_t *dest_id,
|
||||
dl_matrix3d_t *src_id);
|
||||
|
||||
/**
|
||||
* @brief Match face with the id_list, and return matched_id.
|
||||
*
|
||||
* @param algined_face An aligned face
|
||||
* @param id_list An ID list
|
||||
* @return int8_t Matched face id
|
||||
*/
|
||||
int8_t recognize_face(face_id_list *l,
|
||||
dl_matrix3du_t *algined_face);
|
||||
|
||||
/**
|
||||
* @brief Produce face id according to the input aligned face, and save it to dest_id.
|
||||
*
|
||||
* @param l face id list
|
||||
* @param aligned_face An aligned face
|
||||
* @param enroll_confirm_times Confirm times for each face id enrollment
|
||||
* @return -1 Wrong input enroll_confirm_times
|
||||
* @return 0 Enrollment finish
|
||||
* @return >=1 The left piece of aligned faces should be input
|
||||
*/
|
||||
int8_t enroll_face(face_id_list *l,
|
||||
dl_matrix3du_t *aligned_face);
|
||||
|
||||
/**
|
||||
* @brief Alloc memory for aligned face.
|
||||
*
|
||||
* @param l face id list
|
||||
* @return uint8_t left count
|
||||
*/
|
||||
uint8_t delete_face(face_id_list *l);
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
28
tools/sdk/include/esp-face/frmn.h
Normal file
28
tools/sdk/include/esp-face/frmn.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#if __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include "dl_lib.h"
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param in
|
||||
* @return dl_matrix3d_t*
|
||||
*/
|
||||
dl_matrix3d_t *frmn(dl_matrix3d_t *in);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param in
|
||||
* @return dl_matrix3dq_t*
|
||||
*/
|
||||
dl_matrix3dq_t *frmn_q(dl_matrix3dq_t *in, dl_conv_mode mode);
|
||||
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
275
tools/sdk/include/esp-face/image_util.h
Normal file
275
tools/sdk/include/esp-face/image_util.h
Normal file
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
#include "mtmn.h"
|
||||
|
||||
#define MAX_VALID_COUNT_PER_IMAGE (30)
|
||||
|
||||
#define DL_IMAGE_MIN(A, B) ((A) < (B) ? (A) : (B))
|
||||
#define DL_IMAGE_MAX(A, B) ((A) < (B) ? (B) : (A))
|
||||
|
||||
#define IMAGE_WIDTH 320
|
||||
#define IMAGE_HEIGHT 240
|
||||
|
||||
#define RGB565_MASK_RED 0xF800
|
||||
#define RGB565_MASK_GREEN 0x07E0
|
||||
#define RGB565_MASK_BLUE 0x001F
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fptp_t landmark_p[10];
|
||||
} landmark_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fptp_t box_p[4];
|
||||
} box_t;
|
||||
|
||||
typedef struct tag_box_list
|
||||
{
|
||||
box_t *box;
|
||||
landmark_t *landmark;
|
||||
int len;
|
||||
} box_array_t;
|
||||
|
||||
typedef struct tag_image_box
|
||||
{
|
||||
struct tag_image_box *next;
|
||||
fptp_t score;
|
||||
box_t box;
|
||||
box_t offset;
|
||||
landmark_t landmark;
|
||||
} image_box_t;
|
||||
|
||||
typedef struct tag_image_list
|
||||
{
|
||||
image_box_t *head;
|
||||
image_box_t *origin_head;
|
||||
int len;
|
||||
} image_list_t;
|
||||
|
||||
static inline void image_get_width_and_height(box_t *box, float *w, float *h)
|
||||
{
|
||||
*w = box->box_p[2] - box->box_p[0] + 1;
|
||||
*h = box->box_p[3] - box->box_p[1] + 1;
|
||||
}
|
||||
|
||||
static inline void image_get_area(box_t *box, float *area)
|
||||
{
|
||||
float w, h;
|
||||
image_get_width_and_height(box, &w, &h);
|
||||
*area = w * h;
|
||||
}
|
||||
|
||||
static inline void image_calibrate_by_offset(image_list_t *image_list)
|
||||
{
|
||||
for (image_box_t *head = image_list->head; head; head = head->next)
|
||||
{
|
||||
float w, h;
|
||||
image_get_width_and_height(&(head->box), &w, &h);
|
||||
head->box.box_p[0] = DL_IMAGE_MAX(0, head->box.box_p[0] + head->offset.box_p[0] * w);
|
||||
head->box.box_p[1] = DL_IMAGE_MAX(0, head->box.box_p[1] + head->offset.box_p[1] * w);
|
||||
head->box.box_p[2] += head->offset.box_p[2] * w;
|
||||
if (head->box.box_p[2] > IMAGE_WIDTH)
|
||||
{
|
||||
head->box.box_p[2] = IMAGE_WIDTH - 1;
|
||||
head->box.box_p[0] = IMAGE_WIDTH - w;
|
||||
}
|
||||
head->box.box_p[3] += head->offset.box_p[3] * h;
|
||||
if (head->box.box_p[3] > IMAGE_HEIGHT)
|
||||
{
|
||||
head->box.box_p[3] = IMAGE_HEIGHT - 1;
|
||||
head->box.box_p[1] = IMAGE_HEIGHT - h;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void image_landmark_calibrate(image_list_t *image_list)
|
||||
{
|
||||
for (image_box_t *head = image_list->head; head; head = head->next)
|
||||
{
|
||||
float w, h;
|
||||
image_get_width_and_height(&(head->box), &w, &h);
|
||||
head->landmark.landmark_p[0] = head->box.box_p[0] + head->landmark.landmark_p[0] * w;
|
||||
head->landmark.landmark_p[1] = head->box.box_p[1] + head->landmark.landmark_p[1] * h;
|
||||
|
||||
head->landmark.landmark_p[2] = head->box.box_p[0] + head->landmark.landmark_p[2] * w;
|
||||
head->landmark.landmark_p[3] = head->box.box_p[1] + head->landmark.landmark_p[3] * h;
|
||||
|
||||
head->landmark.landmark_p[4] = head->box.box_p[0] + head->landmark.landmark_p[4] * w;
|
||||
head->landmark.landmark_p[5] = head->box.box_p[1] + head->landmark.landmark_p[5] * h;
|
||||
|
||||
head->landmark.landmark_p[6] = head->box.box_p[0] + head->landmark.landmark_p[6] * w;
|
||||
head->landmark.landmark_p[7] = head->box.box_p[1] + head->landmark.landmark_p[7] * h;
|
||||
|
||||
head->landmark.landmark_p[8] = head->box.box_p[0] + head->landmark.landmark_p[8] * w;
|
||||
head->landmark.landmark_p[9] = head->box.box_p[1] + head->landmark.landmark_p[9] * h;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void image_rect2sqr(box_array_t *boxes, int width, int height)
|
||||
{
|
||||
for (int i = 0; i < boxes->len; i++)
|
||||
{
|
||||
box_t *box = &(boxes->box[i]);
|
||||
float w, h;
|
||||
image_get_width_and_height(box, &w, &h);
|
||||
float l = DL_IMAGE_MAX(w, h);
|
||||
|
||||
box->box_p[0] = DL_IMAGE_MAX(0, box->box_p[0] + 0.5 * (w - l));
|
||||
box->box_p[1] = DL_IMAGE_MAX(0, box->box_p[1] + 0.5 * (h - l));
|
||||
box->box_p[2] = box->box_p[0] + l - 1;
|
||||
if (box->box_p[2] > width)
|
||||
{
|
||||
box->box_p[2] = width - 1;
|
||||
box->box_p[0] = width - l;
|
||||
}
|
||||
box->box_p[3] = box->box_p[1] + l - 1;
|
||||
if (box->box_p[3] > height)
|
||||
{
|
||||
box->box_p[3] = height - 1;
|
||||
box->box_p[1] = height - l;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rgb565_to_888(uint16_t in, uint8_t *dst)
|
||||
{ /*{{{*/
|
||||
dst[0] = (in & RGB565_MASK_BLUE) << 3; // blue
|
||||
dst[1] = (in & RGB565_MASK_GREEN) >> 3; // green
|
||||
dst[2] = (in & RGB565_MASK_RED) >> 8; // red
|
||||
} /*}}}*/
|
||||
|
||||
static inline void rgb888_to_565(uint16_t *in, uint8_t r, uint8_t g, uint8_t b)
|
||||
{ /*{{{*/
|
||||
uint16_t rgb565 = 0;
|
||||
rgb565 = ((r >> 3) << 11);
|
||||
rgb565 |= ((g >> 2) << 5);
|
||||
rgb565 |= (b >> 3);
|
||||
*in = rgb565;
|
||||
} /*}}}*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param score
|
||||
* @param offset
|
||||
* @param width
|
||||
* @param height
|
||||
* @param p_net_size
|
||||
* @param score_threshold
|
||||
* @param scale
|
||||
* @return image_list_t*
|
||||
*/
|
||||
image_list_t *image_get_valid_boxes(fptp_t *score,
|
||||
fptp_t *offset,
|
||||
int width,
|
||||
int height,
|
||||
int p_net_size,
|
||||
fptp_t score_threshold,
|
||||
fptp_t scale);
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param image_sorted_list
|
||||
* @param insert_list
|
||||
*/
|
||||
void image_sort_insert_by_score(image_list_t *image_sorted_list, const image_list_t *insert_list);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param image_list
|
||||
* @param nms_threshold
|
||||
* @param same_area
|
||||
*/
|
||||
void image_nms_process(image_list_t *image_list, fptp_t nms_threshold, int same_area);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param dst_image
|
||||
* @param src_image
|
||||
* @param dst_w
|
||||
* @param dst_h
|
||||
* @param dst_c
|
||||
* @param src_w
|
||||
* @param src_h
|
||||
*/
|
||||
void image_resize_linear(uint8_t *dst_image, uint8_t *src_image, int dst_w, int dst_h, int dst_c, int src_w, int src_h);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param corp_image
|
||||
* @param src_image
|
||||
* @param rotate_angle
|
||||
* @param ratio
|
||||
* @param center
|
||||
*/
|
||||
void image_cropper(dl_matrix3du_t *corp_image, dl_matrix3du_t *src_image, float rotate_angle, float ratio, float *center);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param m
|
||||
* @param bmp
|
||||
* @param count
|
||||
*/
|
||||
void transform_input_image(uint8_t *m, uint16_t *bmp, int count);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param bmp
|
||||
* @param m
|
||||
* @param count
|
||||
*/
|
||||
void transform_output_image(uint16_t *bmp, uint8_t *m, int count);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param buf
|
||||
* @param boxes
|
||||
* @param width
|
||||
*/
|
||||
void draw_rectangle_rgb565(uint16_t *buf, box_array_t *boxes, int width);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param buf
|
||||
* @param boxes
|
||||
* @param width
|
||||
*/
|
||||
void draw_rectangle_rgb888(uint8_t *buf, box_array_t *boxes, int width);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
99
tools/sdk/include/esp-face/mtmn.h
Normal file
99
tools/sdk/include/esp-face/mtmn.h
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2018 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on ESPRESSIF SYSTEMS products only, in which case,
|
||||
* it is 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.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#include "dl_lib.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PNET = 0, /// P-Net
|
||||
RNET = 1, /// R-Net
|
||||
ONET = 2, /// O-Net
|
||||
} net_type_en;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float score; /// score threshold for filter candidates by score
|
||||
float nms; /// nms threshold for nms process
|
||||
int candidate_number; /// candidate number limitation for each net
|
||||
} threshold_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
net_type_en net_type; /// net type
|
||||
char *file_name; /// net name
|
||||
int w; /// net width
|
||||
int h; /// net height
|
||||
threshold_config_t threshold; /// threshold of net
|
||||
} net_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float min_face; /// the minimum size of face can be detected
|
||||
float pyramid; /// the pyramid scale
|
||||
threshold_config_t p_threshold; /// score, nms and candidate threshold of pnet
|
||||
threshold_config_t r_threshold; /// score, nms and candidate threshold of rnet
|
||||
threshold_config_t o_threshold; /// score, nms and candidate threshold of onet
|
||||
} mtmn_config_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
dl_matrix3d_t *category;
|
||||
dl_matrix3d_t *offset;
|
||||
dl_matrix3d_t *landmark;
|
||||
} mtmn_net_t;
|
||||
|
||||
/**
|
||||
* @brief Forward the pnet process, coarse detection
|
||||
*
|
||||
* @param in Image matrix, rgb888 format, size is 320x240
|
||||
* @return Scores for every pixel, and box offset with respect.
|
||||
*/
|
||||
mtmn_net_t *pnet(dl_matrix3du_t *in);
|
||||
|
||||
/**
|
||||
* @brief Forward the rnet process, fine determine the boxes from pnet
|
||||
*
|
||||
* @param in Image matrix, rgb888 format
|
||||
* @param threshold Score threshold to detect human face
|
||||
* @return Scores for every box, and box offset with respect.
|
||||
*/
|
||||
mtmn_net_t *rnet_with_score_verify(dl_matrix3du_t *in, float threshold);
|
||||
|
||||
/**
|
||||
* @brief Forward the onet process, fine determine the boxes from rnet
|
||||
*
|
||||
* @param in Image matrix, rgb888 format
|
||||
* @param threshold Score threshold to detect human face
|
||||
* @return Scores for every box, box offset, and landmark with respect.
|
||||
*/
|
||||
mtmn_net_t *onet_with_score_verify(dl_matrix3du_t *in, float threshold);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
179
tools/sdk/include/esp32-camera/esp_camera.h
Executable file
179
tools/sdk/include/esp32-camera/esp_camera.h
Executable file
@ -0,0 +1,179 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
/*
|
||||
* Example Use
|
||||
*
|
||||
static camera_config_t camera_example_config = {
|
||||
.pin_pwdn = PIN_PWDN,
|
||||
.pin_reset = PIN_RESET,
|
||||
.pin_xclk = PIN_XCLK,
|
||||
.pin_sscb_sda = PIN_SIOD,
|
||||
.pin_sscb_scl = PIN_SIOC,
|
||||
.pin_d7 = PIN_D7,
|
||||
.pin_d6 = PIN_D6,
|
||||
.pin_d5 = PIN_D5,
|
||||
.pin_d4 = PIN_D4,
|
||||
.pin_d3 = PIN_D3,
|
||||
.pin_d2 = PIN_D2,
|
||||
.pin_d1 = PIN_D1,
|
||||
.pin_d0 = PIN_D0,
|
||||
.pin_vsync = PIN_VSYNC,
|
||||
.pin_href = PIN_HREF,
|
||||
.pin_pclk = PIN_PCLK,
|
||||
|
||||
.xclk_freq_hz = 20000000,
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
.pixel_format = PIXFORMAT_JPEG,
|
||||
.frame_size = FRAMESIZE_SVGA,
|
||||
.jpeg_quality = 10,
|
||||
.fb_count = 2
|
||||
};
|
||||
|
||||
esp_err_t camera_example_init(){
|
||||
return esp_camera_init(&camera_example_config);
|
||||
}
|
||||
|
||||
esp_err_t camera_example_capture(){
|
||||
//capture a frame
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAG, "Frame buffer could not be acquired");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
//replace this with your own function
|
||||
display_image(fb->width, fb->height, fb->pixformat, fb->buf, fb->len);
|
||||
|
||||
//return the frame buffer back to be reused
|
||||
esp_camera_fb_return(fb);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "driver/ledc.h"
|
||||
#include "sensor.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configuration structure for camera initialization
|
||||
*/
|
||||
typedef struct {
|
||||
int pin_pwdn; /*!< GPIO pin for camera power down line */
|
||||
int pin_reset; /*!< GPIO pin for camera reset line */
|
||||
int pin_xclk; /*!< GPIO pin for camera XCLK line */
|
||||
int pin_sscb_sda; /*!< GPIO pin for camera SDA line */
|
||||
int pin_sscb_scl; /*!< GPIO pin for camera SCL line */
|
||||
int pin_d7; /*!< GPIO pin for camera D7 line */
|
||||
int pin_d6; /*!< GPIO pin for camera D6 line */
|
||||
int pin_d5; /*!< GPIO pin for camera D5 line */
|
||||
int pin_d4; /*!< GPIO pin for camera D4 line */
|
||||
int pin_d3; /*!< GPIO pin for camera D3 line */
|
||||
int pin_d2; /*!< GPIO pin for camera D2 line */
|
||||
int pin_d1; /*!< GPIO pin for camera D1 line */
|
||||
int pin_d0; /*!< GPIO pin for camera D0 line */
|
||||
int pin_vsync; /*!< GPIO pin for camera VSYNC line */
|
||||
int pin_href; /*!< GPIO pin for camera HREF line */
|
||||
int pin_pclk; /*!< GPIO pin for camera PCLK line */
|
||||
|
||||
int xclk_freq_hz; /*!< Frequency of XCLK signal, in Hz. Either 10KHz or 20KHz */
|
||||
|
||||
ledc_timer_t ledc_timer; /*!< LEDC timer to be used for generating XCLK */
|
||||
ledc_channel_t ledc_channel; /*!< LEDC channel to be used for generating XCLK */
|
||||
|
||||
pixformat_t pixel_format; /*!< Format of the pixel data: PIXFORMAT_ + YUV422|GRAYSCALE|RGB565|JPEG */
|
||||
framesize_t frame_size; /*!< Size of the output image: FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA */
|
||||
|
||||
int jpeg_quality; /*!< Quality of JPEG output. 0-63 lower means higher quality */
|
||||
size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */
|
||||
} camera_config_t;
|
||||
|
||||
/**
|
||||
* @brief Data structure of camera frame buffer
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t * buf; /*!< Pointer to the pixel data */
|
||||
size_t len; /*!< Length of the buffer in bytes */
|
||||
size_t width; /*!< Width of the buffer in pixels */
|
||||
size_t height; /*!< Height of the buffer in pixels */
|
||||
pixformat_t format; /*!< Format of the pixel data */
|
||||
} camera_fb_t;
|
||||
|
||||
#define ESP_ERR_CAMERA_BASE 0x20000
|
||||
#define ESP_ERR_CAMERA_NOT_DETECTED (ESP_ERR_CAMERA_BASE + 1)
|
||||
#define ESP_ERR_CAMERA_FAILED_TO_SET_FRAME_SIZE (ESP_ERR_CAMERA_BASE + 2)
|
||||
#define ESP_ERR_CAMERA_NOT_SUPPORTED (ESP_ERR_CAMERA_BASE + 3)
|
||||
|
||||
/**
|
||||
* @brief Initialize the camera driver
|
||||
*
|
||||
* @note call camera_probe before calling this function
|
||||
*
|
||||
* This function detects and configures camera over I2C interface,
|
||||
* allocates framebuffer and DMA buffers,
|
||||
* initializes parallel I2S input, and sets up DMA descriptors.
|
||||
*
|
||||
* Currently this function can only be called once and there is
|
||||
* no way to de-initialize this module.
|
||||
*
|
||||
* @param config Camera configuration parameters
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
*/
|
||||
esp_err_t esp_camera_init(const camera_config_t* config);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the camera driver
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if the driver hasn't been initialized yet
|
||||
*/
|
||||
esp_err_t esp_camera_deinit();
|
||||
|
||||
/**
|
||||
* @brief Obtain pointer to a frame buffer.
|
||||
*
|
||||
* @return pointer to the frame buffer
|
||||
*/
|
||||
camera_fb_t* esp_camera_fb_get();
|
||||
|
||||
/**
|
||||
* @brief Return the frame buffer to be reused again.
|
||||
*
|
||||
* @param fb Pointer to the frame buffer
|
||||
*/
|
||||
void esp_camera_fb_return(camera_fb_t * fb);
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the image sensor control structure
|
||||
*
|
||||
* @return pointer to the sensor
|
||||
*/
|
||||
sensor_t * esp_camera_sensor_get();
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "img_converters.h"
|
||||
|
43
tools/sdk/include/esp32-camera/esp_jpg_decode.h
Normal file
43
tools/sdk/include/esp32-camera/esp_jpg_decode.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _ESP_JPG_DECODE_H_
|
||||
#define _ESP_JPG_DECODE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum {
|
||||
JPG_SCALE_NONE,
|
||||
JPG_SCALE_2X,
|
||||
JPG_SCALE_4X,
|
||||
JPG_SCALE_8X,
|
||||
JPG_SCALE_MAX = JPG_SCALE_8X
|
||||
} jpg_scale_t;
|
||||
|
||||
typedef size_t (* jpg_reader_cb)(void * arg, size_t index, uint8_t *buf, size_t len);
|
||||
typedef bool (* jpg_writer_cb)(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t *data);
|
||||
|
||||
esp_err_t esp_jpg_decode(size_t len, jpg_scale_t scale, jpg_reader_cb reader, jpg_writer_cb writer, void * arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_JPG_DECODE_H_ */
|
126
tools/sdk/include/esp32-camera/img_converters.h
Normal file
126
tools/sdk/include/esp32-camera/img_converters.h
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _IMG_CONVERTERS_H_
|
||||
#define _IMG_CONVERTERS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_camera.h"
|
||||
|
||||
typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG buffer
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to BMP buffer
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to BMP buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to RGB888 buffer (used for face detection)
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param format Format of the source image
|
||||
* @param rgb_buf Pointer to the output buffer (width * height * 3)
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IMG_CONVERTERS_H_ */
|
127
tools/sdk/include/esp32-camera/sensor.h
Executable file
127
tools/sdk/include/esp32-camera/sensor.h
Executable file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Sensor abstraction layer.
|
||||
*
|
||||
*/
|
||||
#ifndef __SENSOR_H__
|
||||
#define __SENSOR_H__
|
||||
#include <stdint.h>
|
||||
|
||||
#define OV9650_PID (0x96)
|
||||
#define OV2640_PID (0x26)
|
||||
#define OV7725_PID (0x77)
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
PIXFORMAT_YUV422, // 2BPP/YUV422
|
||||
PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
|
||||
PIXFORMAT_JPEG, // JPEG/COMPRESSED
|
||||
PIXFORMAT_RGB888, // 3BPP/RGB888
|
||||
} pixformat_t;
|
||||
|
||||
typedef enum {
|
||||
FRAMESIZE_QQVGA, // 160x120
|
||||
FRAMESIZE_QQVGA2, // 128x160
|
||||
FRAMESIZE_QCIF, // 176x144
|
||||
FRAMESIZE_HQVGA, // 240x176
|
||||
FRAMESIZE_QVGA, // 320x240
|
||||
FRAMESIZE_CIF, // 400x296
|
||||
FRAMESIZE_VGA, // 640x480
|
||||
FRAMESIZE_SVGA, // 800x600
|
||||
FRAMESIZE_XGA, // 1024x768
|
||||
FRAMESIZE_SXGA, // 1280x1024
|
||||
FRAMESIZE_UXGA, // 1600x1200
|
||||
} framesize_t;
|
||||
|
||||
typedef enum {
|
||||
GAINCEILING_2X,
|
||||
GAINCEILING_4X,
|
||||
GAINCEILING_8X,
|
||||
GAINCEILING_16X,
|
||||
GAINCEILING_32X,
|
||||
GAINCEILING_64X,
|
||||
GAINCEILING_128X,
|
||||
} gainceiling_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t MIDH;
|
||||
uint8_t MIDL;
|
||||
uint8_t PID;
|
||||
uint8_t VER;
|
||||
} sensor_id_t;
|
||||
|
||||
typedef struct {
|
||||
framesize_t framesize;//0 - 10
|
||||
uint8_t quality;//0 - 63
|
||||
int8_t brightness;//-2 - 2
|
||||
int8_t contrast;//-2 - 2
|
||||
int8_t saturation;//-2 - 2
|
||||
uint8_t special_effect;//0 - 6
|
||||
uint8_t wb_mode;//0 - 4
|
||||
uint8_t awb;
|
||||
uint8_t awb_gain;
|
||||
uint8_t aec;
|
||||
uint8_t aec2;
|
||||
int8_t ae_level;//-2 - 2
|
||||
uint16_t aec_value;//0 - 1200
|
||||
uint8_t agc;
|
||||
uint8_t agc_gain;//0 - 30
|
||||
uint8_t gainceiling;//0 - 6
|
||||
uint8_t bpc;
|
||||
uint8_t wpc;
|
||||
uint8_t raw_gma;
|
||||
uint8_t lenc;
|
||||
uint8_t hmirror;
|
||||
uint8_t vflip;
|
||||
uint8_t dcw;
|
||||
uint8_t colorbar;
|
||||
} camera_status_t;
|
||||
|
||||
typedef struct _sensor sensor_t;
|
||||
typedef struct _sensor {
|
||||
sensor_id_t id; // Sensor ID.
|
||||
uint8_t slv_addr; // Sensor I2C slave address.
|
||||
pixformat_t pixformat;
|
||||
camera_status_t status;
|
||||
|
||||
// Sensor function pointers
|
||||
int (*init_status) (sensor_t *sensor);
|
||||
int (*reset) (sensor_t *sensor);
|
||||
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
|
||||
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
|
||||
int (*set_contrast) (sensor_t *sensor, int level);
|
||||
int (*set_brightness) (sensor_t *sensor, int level);
|
||||
int (*set_saturation) (sensor_t *sensor, int level);
|
||||
int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling);
|
||||
int (*set_quality) (sensor_t *sensor, int quality);
|
||||
int (*set_colorbar) (sensor_t *sensor, int enable);
|
||||
int (*set_whitebal) (sensor_t *sensor, int enable);
|
||||
int (*set_gain_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_exposure_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_hmirror) (sensor_t *sensor, int enable);
|
||||
int (*set_vflip) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_aec2) (sensor_t *sensor, int enable);
|
||||
int (*set_awb_gain) (sensor_t *sensor, int enable);
|
||||
int (*set_agc_gain) (sensor_t *sensor, int gain);
|
||||
int (*set_aec_value) (sensor_t *sensor, int gain);
|
||||
|
||||
int (*set_special_effect) (sensor_t *sensor, int effect);
|
||||
int (*set_wb_mode) (sensor_t *sensor, int mode);
|
||||
int (*set_ae_level) (sensor_t *sensor, int level);
|
||||
|
||||
int (*set_dcw) (sensor_t *sensor, int enable);
|
||||
int (*set_bpc) (sensor_t *sensor, int enable);
|
||||
int (*set_wpc) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_raw_gma) (sensor_t *sensor, int enable);
|
||||
int (*set_lenc) (sensor_t *sensor, int enable);
|
||||
} sensor_t;
|
||||
|
||||
// Resolution table (in camera.c)
|
||||
extern const int resolution[][2];
|
||||
|
||||
#endif /* __SENSOR_H__ */
|
@ -14,17 +14,19 @@
|
||||
#ifndef __ESP_ATTR_H__
|
||||
#define __ESP_ATTR_H__
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define ROMFN_ATTR
|
||||
|
||||
//Normally, the linker script will put all code and rodata in flash,
|
||||
//and all variables in shared RAM. These macros can be used to redirect
|
||||
//particular functions/variables to other memory regions.
|
||||
|
||||
// Forces code into IRAM instead of flash.
|
||||
#define IRAM_ATTR __attribute__((section(".iram1")))
|
||||
// Forces code into IRAM instead of flash
|
||||
#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__)
|
||||
|
||||
// Forces data into DRAM instead of flash
|
||||
#define DRAM_ATTR __attribute__((section(".dram1")))
|
||||
#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__)
|
||||
|
||||
// Forces data to be 4 bytes aligned
|
||||
#define WORD_ALIGNED_ATTR __attribute__((aligned(4)))
|
||||
@ -37,11 +39,11 @@
|
||||
#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;}))
|
||||
|
||||
// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst"
|
||||
#define RTC_IRAM_ATTR __attribute__((section(".rtc.text")))
|
||||
#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__)
|
||||
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
// Forces bss variable into external memory. "
|
||||
#define EXT_RAM_ATTR __attribute__((section(".ext_ram.bss")))
|
||||
#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__)
|
||||
#else
|
||||
#define EXT_RAM_ATTR
|
||||
#endif
|
||||
@ -49,26 +51,37 @@
|
||||
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
|
||||
// Any variable marked with this attribute will keep its value
|
||||
// during a deep sleep / wake cycle.
|
||||
#define RTC_DATA_ATTR __attribute__((section(".rtc.data")))
|
||||
#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__)
|
||||
|
||||
// Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst"
|
||||
#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata")))
|
||||
#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__)
|
||||
|
||||
// Allows to place data into RTC_SLOW memory.
|
||||
#define RTC_SLOW_ATTR __attribute__((section(".rtc.force_slow")))
|
||||
#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__)
|
||||
|
||||
// Allows to place data into RTC_FAST memory.
|
||||
#define RTC_FAST_ATTR __attribute__((section(".rtc.force_fast")))
|
||||
#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__)
|
||||
|
||||
// Forces data into noinit section to avoid initialization after restart.
|
||||
#define __NOINIT_ATTR __attribute__((section(".noinit")))
|
||||
#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__)
|
||||
|
||||
// Forces data into RTC slow memory of .noinit section.
|
||||
// Any variable marked with this attribute will keep its value
|
||||
// after restart or during a deep sleep / wake cycle.
|
||||
#define RTC_NOINIT_ATTR __attribute__((section(".rtc_noinit")))
|
||||
#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__)
|
||||
|
||||
// Forces to not inline function
|
||||
#define NOINLINE_ATTR __attribute__((noinline))
|
||||
|
||||
// Implementation for a unique custom section
|
||||
//
|
||||
// This prevents gcc producing "x causes a section type conflict with y"
|
||||
// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section
|
||||
//
|
||||
// Using unique sections also means --gc-sections can remove unused
|
||||
// data with a custom section type set
|
||||
#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER))))
|
||||
|
||||
#define _COUNTER_STRINGIFY(COUNTER) #COUNTER
|
||||
|
||||
#endif /* __ESP_ATTR_H__ */
|
||||
|
@ -24,11 +24,22 @@ extern "C"
|
||||
#define ESP_PARTITION_MAGIC 0x50AA
|
||||
#define ESP_PARTITION_MAGIC_MD5 0xEBEB
|
||||
|
||||
/// OTA_DATA states for checking operability of the app.
|
||||
typedef enum {
|
||||
ESP_OTA_IMG_NEW = 0x0U, /*!< Monitor the first boot. In bootloader this state is changed to ESP_OTA_IMG_PENDING_VERIFY. */
|
||||
ESP_OTA_IMG_PENDING_VERIFY = 0x1U, /*!< First boot for this app was. If while the second boot this state is then it will be changed to ABORTED. */
|
||||
ESP_OTA_IMG_VALID = 0x2U, /*!< App was confirmed as workable. App can boot and work without limits. */
|
||||
ESP_OTA_IMG_INVALID = 0x3U, /*!< App was confirmed as non-workable. This app will not selected to boot at all. */
|
||||
ESP_OTA_IMG_ABORTED = 0x4U, /*!< App could not confirm the workable or non-workable. In bootloader IMG_PENDING_VERIFY state will be changed to IMG_ABORTED. This app will not selected to boot at all. */
|
||||
ESP_OTA_IMG_UNDEFINED = 0xFFFFFFFFU, /*!< Undefined. App can boot and work without limits. */
|
||||
} esp_ota_img_states_t;
|
||||
|
||||
/* OTA selection structure (two copies in the OTA data partition.)
|
||||
Size of 32 bytes is friendly to flash encryption */
|
||||
typedef struct {
|
||||
uint32_t ota_seq;
|
||||
uint8_t seq_label[24];
|
||||
uint8_t seq_label[20];
|
||||
uint32_t ota_state;
|
||||
uint32_t crc; /* CRC32 of ota_seq field only */
|
||||
} esp_ota_select_entry_t;
|
||||
|
||||
|
@ -187,6 +187,11 @@ typedef enum {
|
||||
this event, and add the corresponding scan done handler in this event. */
|
||||
MESH_EVENT_NETWORK_STATE, /**< network state, such as whether current mesh network has a root. */
|
||||
MESH_EVENT_STOP_RECONNECTION, /**< the root stops reconnecting to the router and non-root devices stop reconnecting to their parents. */
|
||||
MESH_EVENT_FIND_NETWORK, /**< when the channel field in mesh configuration is set to zero, mesh stack will perform a
|
||||
full channel scan to find a mesh network that can join, and return the channel value
|
||||
after finding it. */
|
||||
MESH_EVENT_ROUTER_SWITCH, /**< if users specify BSSID of the router in mesh configuration, when the root connects to another
|
||||
router with the same SSID, this event will be posted and the new router information is attached. */
|
||||
MESH_EVENT_MAX,
|
||||
} mesh_event_id_t;
|
||||
|
||||
@ -310,6 +315,14 @@ typedef struct {
|
||||
mesh_addr_t rc_addr; /**< root address specified by users via API esp_mesh_waive_root() */
|
||||
} mesh_event_vote_started_t;
|
||||
|
||||
/**
|
||||
* @brief find a mesh network that this device can join
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t channel; /**< channel number of the new found network */
|
||||
uint8_t router_bssid[6]; /**< router BSSID */
|
||||
} mesh_event_find_network_t;
|
||||
|
||||
/**
|
||||
* @brief IP settings from LwIP stack
|
||||
*/
|
||||
@ -381,6 +394,11 @@ typedef struct {
|
||||
bool is_rootless; /**< whether current mesh network has a root */
|
||||
} mesh_event_network_state_t;
|
||||
|
||||
/**
|
||||
* @brief New router information
|
||||
*/
|
||||
typedef system_event_sta_connected_t mesh_event_router_switch_t;
|
||||
|
||||
/**
|
||||
* @brief Mesh event information
|
||||
*/
|
||||
@ -405,6 +423,8 @@ typedef union {
|
||||
mesh_event_root_fixed_t root_fixed; /**< fixed root */
|
||||
mesh_event_scan_done_t scan_done; /**< scan done */
|
||||
mesh_event_network_state_t network_state; /**< network state, such as whether current mesh network has a root. */
|
||||
mesh_event_find_network_t find_network; /**< network found that can join */
|
||||
mesh_event_router_switch_t router_switch; /**< new router information */
|
||||
} mesh_event_info_t;
|
||||
|
||||
/**
|
||||
@ -447,8 +467,14 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID */
|
||||
uint8_t ssid_len; /**< length of SSID */
|
||||
uint8_t bssid[6]; /**< BSSID, if router is hidden, this value is mandatory */
|
||||
uint8_t bssid[6]; /**< BSSID, if this value is specified, users should also specify "allow_router_switch". */
|
||||
uint8_t password[64]; /**< password */
|
||||
bool allow_router_switch; /**< if the BSSID is specified and this value is also set, when the router of this specified BSSID
|
||||
fails to be found after "fail" (mesh_attempts_t) times, the whole network is allowed to switch
|
||||
to another router with the same SSID. The new router might also be on a different channel.
|
||||
The default value is false.
|
||||
There is a risk that if the password is different between the new switched router and the previous
|
||||
one, the mesh network could be established but the root will never connect to the new switched router. */
|
||||
} mesh_router_t;
|
||||
|
||||
/**
|
||||
@ -464,6 +490,8 @@ typedef struct {
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t channel; /**< channel, the mesh network on */
|
||||
bool allow_channel_switch; /**< if this value is set, when "fail" (mesh_attempts_t) times is reached, device will change to
|
||||
a full channel scan for a network that could join. The default value is false. */
|
||||
mesh_event_cb_t event_cb; /**< mesh event callback */
|
||||
mesh_addr_t mesh_id; /**< mesh network identification */
|
||||
mesh_router_t router; /**< router configuration */
|
||||
@ -596,6 +624,7 @@ esp_err_t esp_mesh_stop(void);
|
||||
* - If the packet is to an external IP network, set this parameter to the IPv4:PORT combination.
|
||||
* This packet will be delivered to the root firstly, then the root will forward this packet to the final IP server address.
|
||||
* @param[in] data pointer to a sending mesh packet
|
||||
* - Field size should not exceed MESH_MPS. Note that the size of one mesh packet should not exceed MESH_MTU.
|
||||
* - Field proto should be set to data protocol in use (default is MESH_PROTO_BIN for binary).
|
||||
* - Field tos should be set to transmission tos (type of service) in use (default is MESH_TOS_P2P for point-to-point reliable).
|
||||
* @param[in] flag bitmap for data sent
|
||||
@ -1412,6 +1441,43 @@ esp_err_t esp_mesh_disconnect(void);
|
||||
*/
|
||||
esp_err_t esp_mesh_connect(void);
|
||||
|
||||
/**
|
||||
* @brief Flush scan result
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
*/
|
||||
esp_err_t esp_mesh_flush_scan_result(void);
|
||||
|
||||
/**
|
||||
* @brief Cause the root device to add Channel Switch Announcement Element (CSA IE) to beacon
|
||||
* - Set the new channel
|
||||
* - Set how many beacons with CSA IE will be sent before changing a new channel
|
||||
* - Enable the channel switch function
|
||||
*
|
||||
* @attention This API is only called by the root.
|
||||
*
|
||||
* @param[in] new_bssid the new router BSSID if the router changes
|
||||
* @param[in] csa_newchan the new channel number to which the whole network is moving
|
||||
* @param[in] csa_count channel switch period(beacon count), unit is based on beacon interval of its softAP, the default value is 15.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
*/
|
||||
esp_err_t esp_mesh_switch_channel(const uint8_t *new_bssid, int csa_newchan, int csa_count);
|
||||
|
||||
/**
|
||||
* @brief Get the router BSSID
|
||||
*
|
||||
* @param[out] router_bssid pointer to the router BSSID
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_WIFI_NOT_INIT
|
||||
* - ESP_ERR_WIFI_ARG
|
||||
*/
|
||||
esp_err_t esp_mesh_get_router_bssid(uint8_t *router_bssid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -156,6 +156,18 @@ esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_dat
|
||||
*/
|
||||
esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data);
|
||||
|
||||
/**
|
||||
* @brief Erase PHY calibration data which is stored in the NVS
|
||||
*
|
||||
* This is a function which can be used to trigger full calibration as a last-resort remedy
|
||||
* if partial calibration is used. It can be called in the application based on some conditions
|
||||
* (e.g. an option provided in some diagnostic mode).
|
||||
*
|
||||
* @return ESP_OK on success
|
||||
* @return others on fail. Please refer to NVS API return value error number.
|
||||
*/
|
||||
esp_err_t esp_phy_erase_cal_data_in_nvs(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize PHY and RF module
|
||||
*
|
||||
@ -214,6 +226,12 @@ esp_err_t esp_modem_sleep_register(modem_sleep_module_t module);
|
||||
*/
|
||||
esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module);
|
||||
|
||||
/**
|
||||
* @brief Get the time stamp when PHY/RF was switched on
|
||||
* @return return 0 if PHY/RF is never switched on. Otherwise return time in
|
||||
* microsecond since boot when phy/rf was last switched on
|
||||
*/
|
||||
int64_t esp_phy_rf_get_on_ts(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -46,6 +46,40 @@ typedef struct {
|
||||
void *storage; /**< storage for FreeRTOS queue */
|
||||
} wifi_static_queue_t;
|
||||
|
||||
/**
|
||||
* @brief WiFi log level
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_LOG_ERROR = 0, /*enabled by default*/
|
||||
WIFI_LOG_WARNING, /*enabled by default*/
|
||||
WIFI_LOG_INFO, /*enabled by default*/
|
||||
WIFI_LOG_DEBUG, /*can be set in menuconfig*/
|
||||
WIFI_LOG_VERBOSE, /*can be set in menuconfig*/
|
||||
} wifi_log_level_t;
|
||||
|
||||
/**
|
||||
* @brief WiFi log module definition
|
||||
*
|
||||
*/
|
||||
typedef enum {
|
||||
WIFI_LOG_MODULE_ALL = 0, /*all log modules */
|
||||
WIFI_LOG_MODULE_WIFI, /*logs related to WiFi*/
|
||||
WIFI_LOG_MODULE_COEX, /*logs related to WiFi and BT(or BLE) coexist*/
|
||||
WIFI_LOG_MODULE_MESH, /*logs related to Mesh*/
|
||||
} wifi_log_module_t;
|
||||
|
||||
/**
|
||||
* @brief WiFi log submodule definition
|
||||
*
|
||||
*/
|
||||
#define WIFI_LOG_SUBMODULE_ALL (0) /*all log submodules*/
|
||||
#define WIFI_LOG_SUBMODULE_INIT (1) /*logs related to initialization*/
|
||||
#define WIFI_LOG_SUBMODULE_IOCTL (1<<1) /*logs related to API calling*/
|
||||
#define WIFI_LOG_SUBMODULE_CONN (1<<2) /*logs related to connecting*/
|
||||
#define WIFI_LOG_SUBMODULE_SCAN (1<<3) /*logs related to scaning*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize Wi-Fi Driver
|
||||
* Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer,
|
||||
@ -224,6 +258,46 @@ void *wifi_calloc( size_t n, size_t size );
|
||||
*/
|
||||
esp_err_t esp_wifi_internal_update_mac_time( uint32_t time_delta );
|
||||
|
||||
/**
|
||||
* @brief Set current WiFi log level
|
||||
*
|
||||
* @param level Log level.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - ESP_FAIL: level is invalid
|
||||
*/
|
||||
esp_err_t esp_wifi_internal_set_log_level(wifi_log_level_t level);
|
||||
|
||||
/**
|
||||
* @brief Set current log module and submodule
|
||||
*
|
||||
* @param module Log module
|
||||
* @param submodule Log submodule
|
||||
* @param enable enable or disable
|
||||
* If module == 0 && enable == 0, all log modules are disabled.
|
||||
* If module == 0 && enable == 1, all log modules are enabled.
|
||||
* If submodule == 0 && enable == 0, all log submodules are disabled.
|
||||
* If submodule == 0 && enable == 1, all log submodules are enabled.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
* - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
|
||||
* - ESP_ERR_WIFI_ARG: invalid argument
|
||||
*/
|
||||
esp_err_t esp_wifi_internal_set_log_mod(wifi_log_module_t module, uint32_t submodule, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Get current WiFi log info
|
||||
*
|
||||
* @param log_level the return log level.
|
||||
* @param log_mod the return log module and submodule
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: succeed
|
||||
*/
|
||||
esp_err_t esp_wifi_internal_get_log(wifi_log_level_t *log_level, uint32_t *log_mod);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -19,6 +19,10 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
HTTPD_SSL_TRANSPORT_SECURE, // SSL Enabled
|
||||
HTTPD_SSL_TRANSPORT_INSECURE // SSL disabled
|
||||
@ -92,6 +96,10 @@ typedef struct httpd_ssl_config httpd_ssl_config_t;
|
||||
.open_fn = NULL, \
|
||||
.close_fn = NULL, \
|
||||
}, \
|
||||
.cacert_pem = NULL, \
|
||||
.cacert_len = 0, \
|
||||
.prvtkey_pem = NULL, \
|
||||
.prvtkey_len = 0, \
|
||||
.transport_mode = HTTPD_SSL_TRANSPORT_SECURE, \
|
||||
.port_secure = 443, \
|
||||
.port_insecure = 80, \
|
||||
@ -114,4 +122,8 @@ esp_err_t httpd_ssl_start(httpd_handle_t *handle, httpd_ssl_config_t *config);
|
||||
*/
|
||||
void httpd_ssl_stop(httpd_handle_t handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _ESP_HTTPS_SERVER_H_
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user