mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 10:06:07 +01:00
Compare commits
236 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce319bb499 | ||
|
|
4dbcc753fd | ||
|
|
6951cd79b7 | ||
|
|
eeb18f204d | ||
|
|
bfff2ef0b9 | ||
|
|
ef5ddac368 | ||
|
|
299b8f300e | ||
|
|
0b0802ad02 | ||
|
|
f8ce3a51d2 | ||
|
|
0e63e064fc | ||
|
|
8d6c763aba | ||
|
|
764747fb45 | ||
|
|
6bb2e0362b | ||
|
|
54dd05e698 | ||
|
|
328f00a559 | ||
|
|
14fda5c32a | ||
|
|
624bf49ee3 | ||
|
|
ab48cbe747 | ||
|
|
2a5094993c | ||
|
|
49d981f006 | ||
|
|
fb2abf933d | ||
|
|
b78e4a6099 | ||
|
|
e0df4490b3 | ||
|
|
7226793e41 | ||
|
|
934d33f950 | ||
|
|
a143b49492 | ||
|
|
f048cfb296 | ||
|
|
89fec64e91 | ||
|
|
bdb1e8af82 | ||
|
|
f40238a49d | ||
|
|
957b94469f | ||
|
|
c2255a3de7 | ||
|
|
caf5e49595 | ||
|
|
7782a37c97 | ||
|
|
f86f2ce587 | ||
|
|
7d1b81690b | ||
|
|
ac6a46262a | ||
|
|
bde464e8c1 | ||
|
|
b2e73c9360 | ||
|
|
863e18a4d7 | ||
|
|
d90f4e181a | ||
|
|
33c7053121 | ||
|
|
5f06f5b0a9 | ||
|
|
18baa45433 | ||
|
|
43c9a69f88 | ||
|
|
b313d07669 | ||
|
|
eb00a1d9c4 | ||
|
|
f1c9ac0a75 | ||
|
|
0b2a8b38ac | ||
|
|
561dd82236 | ||
|
|
66e0b5d9f6 | ||
|
|
08329b89c5 | ||
|
|
e8eb87e7c1 | ||
|
|
c621050f18 | ||
|
|
2fc5c54b8e | ||
|
|
e2fb26c0ad | ||
|
|
d53cc834c4 | ||
|
|
5755e4aad9 | ||
|
|
87ce6d949d | ||
|
|
e102f8e4e9 | ||
|
|
0fb0c6f74d | ||
|
|
5dfd0e4582 | ||
|
|
f311239c9c | ||
|
|
c3e729744a | ||
|
|
447611ba4a | ||
|
|
6637405358 | ||
|
|
32c74ba5b4 | ||
|
|
177f93844c | ||
|
|
d76d110f39 | ||
|
|
1584f35624 | ||
|
|
ac0c3ccfc9 | ||
|
|
3810fbf68c | ||
|
|
20b4f728e4 | ||
|
|
047230de25 | ||
|
|
107764c6be | ||
|
|
0819b19db2 | ||
|
|
4aedce7839 | ||
|
|
2d486d7c66 | ||
|
|
ba8a5c6990 | ||
|
|
1ae015c65f | ||
|
|
92681aa4c5 | ||
|
|
004438cee9 | ||
|
|
b7546cf6d4 | ||
|
|
cce5f56d67 | ||
|
|
eb58b7fc02 | ||
|
|
8f0362455a | ||
|
|
79fe05581c | ||
|
|
658b3b8635 | ||
|
|
77da5964bf | ||
|
|
0232725711 | ||
|
|
ff7f397705 | ||
|
|
d8fa96b20e | ||
|
|
15a9728f45 | ||
|
|
6c9439822b | ||
|
|
4b667d0039 | ||
|
|
19bbba5202 | ||
|
|
ad76d122e5 | ||
|
|
5ec69153b5 | ||
|
|
45427148f6 | ||
|
|
c5fb16836f | ||
|
|
63b6f911b6 | ||
|
|
dec9b17655 | ||
|
|
b8c4d4420e | ||
|
|
0b064a9cee | ||
|
|
4d186c81ff | ||
|
|
5cc7869c0f | ||
|
|
6a8450cbcb | ||
|
|
ca8781f956 | ||
|
|
311ae1a570 | ||
|
|
06b2718d7d | ||
|
|
0f574bc3e8 | ||
|
|
7e49c2a09e | ||
|
|
23cbadb9f6 | ||
|
|
fce2e43ef7 | ||
|
|
4f7a381eed | ||
|
|
6a0f1310e1 | ||
|
|
bb36185066 | ||
|
|
be8eac2fc5 | ||
|
|
e4ecf08e29 | ||
|
|
99c048a29d | ||
|
|
f49731a240 | ||
|
|
375662c69e | ||
|
|
e246ac578d | ||
|
|
d8dcd498a3 | ||
|
|
91b01c5fca | ||
|
|
30812dff49 | ||
|
|
31a90d1498 | ||
|
|
2d02da1574 | ||
|
|
33f77b2192 | ||
|
|
e079c30c54 | ||
|
|
eba9f54454 | ||
|
|
a0a39e98cd | ||
|
|
2144bd58f9 | ||
|
|
fdd87779d7 | ||
|
|
44514e24d1 | ||
|
|
8857ecb669 | ||
|
|
1871f53b5a | ||
|
|
1de47b1133 | ||
|
|
2e38e9f218 | ||
|
|
a48511145c | ||
|
|
ae87ac1960 | ||
|
|
d84a5f6e75 | ||
|
|
f4025fb18f | ||
|
|
9d4e31b01b | ||
|
|
5950c5df4a | ||
|
|
691b64d192 | ||
|
|
573ba8c424 | ||
|
|
511fa3e5dd | ||
|
|
cc3128d22a | ||
|
|
78e097738a | ||
|
|
534c52cebf | ||
|
|
8cf6d01098 | ||
|
|
aadbe7652e | ||
|
|
7735612a16 | ||
|
|
c22de350f6 | ||
|
|
95d5aac01a | ||
|
|
7a31db91ba | ||
|
|
344ded01ac | ||
|
|
4747669df8 | ||
|
|
a532c7c190 | ||
|
|
a6772c6fae | ||
|
|
6ec580d267 | ||
|
|
7805ab2b46 | ||
|
|
e6401f6840 | ||
|
|
c1738936a9 | ||
|
|
4813f062f7 | ||
|
|
1052102032 | ||
|
|
61eb19dfe8 | ||
|
|
9eb0b303f3 | ||
|
|
7abd5d9a84 | ||
|
|
d4ccaf6027 | ||
|
|
a57c797542 | ||
|
|
0cd76eebf0 | ||
|
|
d9a3bf8aac | ||
|
|
5e9238835e | ||
|
|
dd5d96d1ee | ||
|
|
3f613407fe | ||
|
|
36f6705083 | ||
|
|
261aef13b4 | ||
|
|
4c75234fa1 | ||
|
|
20e2106658 | ||
|
|
30bcd3b176 | ||
|
|
8986967a4d | ||
|
|
32072a3b25 | ||
|
|
8ff9826b3d | ||
|
|
6a02f719da | ||
|
|
2a0c763ba0 | ||
|
|
e1f4384813 | ||
|
|
c96f380346 | ||
|
|
b3978fb3cf | ||
|
|
80a75d7df2 | ||
|
|
b5d8852bd5 | ||
|
|
41fef2834c | ||
|
|
a7929010e8 | ||
|
|
b3a34beaae | ||
|
|
af04d39ecb | ||
|
|
f8e6dea9ce | ||
|
|
3eaa59cc18 | ||
|
|
169a2f5d5d | ||
|
|
80cb4dc472 | ||
|
|
00d3e2b11c | ||
|
|
90dd623d5b | ||
|
|
acaa193093 | ||
|
|
1f3962fbc9 | ||
|
|
f9e73526df | ||
|
|
73e472ec21 | ||
|
|
d0ccd8ff09 | ||
|
|
701f3a6429 | ||
|
|
4276799777 | ||
|
|
cb4f3bdff0 | ||
|
|
500f35f286 | ||
|
|
be8ece2413 | ||
|
|
9fbafaf23e | ||
|
|
5c421648d1 | ||
|
|
fddf6169f1 | ||
|
|
bf80cbff3e | ||
|
|
76b6cc6d4c | ||
|
|
ca657fd68c | ||
|
|
309b76061d | ||
|
|
cc6c0cb8f2 | ||
|
|
8ba87800c1 | ||
|
|
2c04db25ec | ||
|
|
54bad5a08a | ||
|
|
2576043456 | ||
|
|
468f6b77a1 | ||
|
|
0adf81ab79 | ||
|
|
99fe067ba8 | ||
|
|
79e3633e85 | ||
|
|
8d0bd95288 | ||
|
|
e22c40d097 | ||
|
|
f11f8e31fc | ||
|
|
564cd655fc | ||
|
|
6981171a6e | ||
|
|
1d1845580b | ||
|
|
eca64ee3c3 | ||
|
|
6a636b5b54 |
18
.github/workflows/conditional-build-test.yml
vendored
18
.github/workflows/conditional-build-test.yml
vendored
@@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||
jobs:
|
||||
determine-builds:
|
||||
name: Evaluate Required Builds
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 1
|
||||
# Map a step output to job output
|
||||
outputs:
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
tag-build:
|
||||
name: Build Tag FW
|
||||
needs: [determine-builds]
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code (with submodules)
|
||||
uses: actions/checkout@v4
|
||||
@@ -66,20 +66,26 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
environment:
|
||||
- OpenEPaperLink_Mini_AP
|
||||
- OpenEPaperLink_AP_and_Flasher
|
||||
#- OpenEPaperLink_Mini_AP
|
||||
#- OpenEPaperLink_AP_and_Flasher
|
||||
- ESP32_S3_16_8_YELLOW_AP
|
||||
- OpenEPaperLink_Mini_AP_v4
|
||||
runs-on: ubuntu-22.04
|
||||
- OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/setup-pio
|
||||
|
||||
- name: Build ${{ matrix.environment }}
|
||||
- name: Build ${{ matrix.environment }} binary
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment ${{ matrix.environment }}
|
||||
- name: Build ${{ matrix.environment }} filesystem
|
||||
if: ${{ matrix.environment != 'OpenEPaperLink_ESP32-PoE-ISO_AP' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --target buildfs --environment ${{ matrix.environment }}
|
||||
|
||||
|
||||
|
||||
|
||||
148
.github/workflows/release.yml
vendored
148
.github/workflows/release.yml
vendored
@@ -5,6 +5,12 @@ on:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
env:
|
||||
INCLUDE_C6_H2: true
|
||||
INCLUDE_MINI_AP: false
|
||||
INCLUDE_Nano_AP: false
|
||||
INCLUDE_S2_Tag_Flasher: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -20,14 +26,14 @@ jobs:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
# - name: Commit zipped files
|
||||
|
||||
# - name: Commit zipped files
|
||||
# run: |
|
||||
# git config --global user.name 'Bot'
|
||||
# git config --global user.email "bot@openepaperlink.de"
|
||||
# git commit -am "Zipped web files"
|
||||
# git push origin HEAD:master
|
||||
|
||||
|
||||
- name: Install PlatformIO Core
|
||||
run: pip install --upgrade platformio
|
||||
|
||||
@@ -41,7 +47,8 @@ jobs:
|
||||
run: |
|
||||
mkdir espbinaries
|
||||
|
||||
- name: esp-idf build
|
||||
- name: build ESP32-C6 firmware
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: latest
|
||||
@@ -49,14 +56,36 @@ jobs:
|
||||
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
|
||||
|
||||
- name: Add C6 files to release
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
run: |
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/bootloader.bin espbinaries/bootloader_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/partition_table/partition-table.bin espbinaries/partition-table_C6.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-C6/firmware_C6.json espbinaries
|
||||
|
||||
- name: build ESP32-H2 firmware
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
uses: espressif/esp-idf-ci-action@v1
|
||||
with:
|
||||
esp_idf_version: latest
|
||||
target: esp32h2
|
||||
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/'
|
||||
|
||||
- name: Add H2 files to release
|
||||
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
|
||||
run: |
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/OpenEPaperLink_esp32_H2.bin espbinaries/OpenEPaperLink_esp32_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/bootloader/bootloader.bin espbinaries/bootloader_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/partition_table/partition-table.bin espbinaries/partition-table_H2.bin
|
||||
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-H2/firmware_H2.json espbinaries
|
||||
|
||||
# - name: Zip web files
|
||||
# run: |
|
||||
# run: |
|
||||
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
|
||||
# python gzip_wwwfiles.py
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Mini_AP
|
||||
if: ${{ env.INCLUDE_MINI_AP == 'true' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -73,8 +102,9 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Mini_AP/firmware.bin espbinaries/OpenEPaperLink_Mini_AP.bin
|
||||
cp OpenEPaperLink_Mini_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_full.bin
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Nano_AP
|
||||
if: ${{ env.INCLUDE_Nano_AP == 'true' }}
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -91,11 +121,10 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin
|
||||
cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin
|
||||
|
||||
# - name: move files for big APs
|
||||
# run: |
|
||||
# cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/
|
||||
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_AP_and_Flasher
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -113,7 +142,6 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_AP_and_Flasher/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin
|
||||
cp OpenEPaperLink_AP_and_Flasher/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin
|
||||
|
||||
- name: Build firmware for ESP32_S3_16_8_YELLOW_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -149,7 +177,43 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp ESP32_S3_C6_NANO_AP/firmware.bin espbinaries/ESP32_S3_C6_NANO_AP.bin
|
||||
cp ESP32_S3_C6_NANO_AP/merged-firmware.bin espbinaries/ESP32_S3_C6_NANO_AP_full.bin
|
||||
|
||||
|
||||
- name: Build firmware for ESP32_S3_16_8_LILYGO_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment ESP32_S3_16_8_LILYGO_AP
|
||||
pio run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/boot_app0.bin
|
||||
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/firmware.bin
|
||||
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/bootloader.bin
|
||||
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/partitions.bin
|
||||
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
|
||||
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp ESP32_S3_16_8_LILYGO_AP/firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP.bin
|
||||
cp ESP32_S3_16_8_LILYGO_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP_full.bin
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Nano_TLSR
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment OpenEPaperLink_Nano_TLSR
|
||||
pio run --target buildfs --environment OpenEPaperLink_Nano_TLSR
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/boot_app0.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/firmware.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/bootloader.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/partitions.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
|
||||
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Nano_TLSR/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR.bin
|
||||
cp OpenEPaperLink_Nano_TLSR/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_full.bin
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_PoE_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
@@ -203,7 +267,65 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp BLE_ONLY_AP/firmware.bin espbinaries/BLE_ONLY_AP.bin
|
||||
cp BLE_ONLY_AP/merged-firmware.bin espbinaries/BLE_ONLY_AP_full.bin
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_Nano_TLSR_C6
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment OpenEPaperLink_Nano_TLSR_C6
|
||||
pio run --target buildfs --environment OpenEPaperLink_Nano_TLSR_C6
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/boot_app0.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/firmware.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/bootloader.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/partitions.bin
|
||||
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6
|
||||
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_Nano_TLSR_C6/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_C6.bin
|
||||
cp OpenEPaperLink_Nano_TLSR_C6/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_C6_full.bin
|
||||
|
||||
- name: Build firmware for ESP32_S3_16_8_4inch_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment ESP32_S3_16_8_4inch_AP
|
||||
pio run --target buildfs --environment ESP32_S3_16_8_4inch_AP
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/boot_app0.bin
|
||||
cp .pio/build/ESP32_S3_16_8_4inch_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/firmware.bin
|
||||
cp .pio/build/ESP32_S3_16_8_4inch_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/bootloader.bin
|
||||
cp .pio/build/ESP32_S3_16_8_4inch_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/partitions.bin
|
||||
cp .pio/build/ESP32_S3_16_8_4inch_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP
|
||||
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp ESP32_S3_16_8_4inch_AP/firmware.bin espbinaries/ESP32_S3_16_8_4inch_AP.bin
|
||||
cp ESP32_S3_16_8_4inch_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_4inch_AP_full.bin
|
||||
|
||||
- name: Build firmware for OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
mv data data.bak
|
||||
mkdir data
|
||||
pio run --target buildfs --environment OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
rmdir data
|
||||
mv data.bak data
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/boot_app0.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin
|
||||
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
|
||||
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode qio --flash_freq 80m --flash_size 4MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xD000 boot_app0.bin 0x10000 firmware.bin 0x3D0000 littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP.bin
|
||||
cp OpenEPaperLink_ESP32-PoE-ISO_AP/merged-firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP_full.bin
|
||||
|
||||
- name: generate release json file
|
||||
run: |
|
||||
mkdir jsonfiles
|
||||
@@ -217,10 +339,11 @@ jobs:
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
overwrite: true
|
||||
|
||||
|
||||
# this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed)
|
||||
|
||||
- name: Build firmware for Tag_Flasher
|
||||
if: ${{ env.INCLUDE_S2_Tag_Flasher == 'true' }}
|
||||
run: |
|
||||
cd Tag_Flasher/ESP32_Flasher
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
@@ -237,7 +360,6 @@ jobs:
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
|
||||
cp S2_Tag_Flasher/firmware.bin espbinaries/S2_Tag_Flasher.bin
|
||||
cp S2_Tag_Flasher/merged-firmware.bin espbinaries/S2_Tag_Flasher_full.bin
|
||||
|
||||
- name: Add esp bins to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -31,3 +31,6 @@ $PROJECT_DIR/
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
|
||||
# Jetbrains IDE
|
||||
.idea/
|
||||
|
||||
@@ -306,7 +306,7 @@ static bool blockRxLoop(const uint32_t timeout)
|
||||
bool success = false;
|
||||
// radioRxEnable(true);
|
||||
uint32_t t = clock_time();
|
||||
while (!clock_time_exceed(t, 2000 * 1000))
|
||||
while (!clock_time_exceed(t, timeout * 1000)) // 300 ms is enough here
|
||||
{
|
||||
int8_t ret = commsRxUnencrypted(inBuffer);
|
||||
if (ret > 1)
|
||||
@@ -611,7 +611,7 @@ static bool getDataBlock(const uint16_t blockSize)
|
||||
{
|
||||
// immediately start with the reception of the block data
|
||||
}
|
||||
blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed
|
||||
blockRxLoop(300); // BLOCK RX LOOP - receive a block, until the timeout has passed
|
||||
|
||||
#ifdef DEBUGBLOCKS
|
||||
printf("RX %d[", curBlock.blockId);
|
||||
@@ -940,4 +940,4 @@ void initializeProto()
|
||||
{
|
||||
getNumSlots();
|
||||
curHighSlotId = getHighSlotId();
|
||||
}
|
||||
}
|
||||
|
||||
42
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/compile.ps1
Normal file
42
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/compile.ps1
Normal file
@@ -0,0 +1,42 @@
|
||||
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
|
||||
|
||||
idf.py fullclean
|
||||
|
||||
idf.py build
|
||||
|
||||
#python -m esptool -p COM8 -b 460800 --before default_reset --after hard_reset --chip esp32c6 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_C6.bin
|
||||
|
||||
|
||||
#idf.py -p COM8 flash
|
||||
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM8
|
||||
#Connecting...
|
||||
#Chip is ESP32-C6 (QFN40) (revision v0.0)
|
||||
#Features: WiFi 6, BT 5, IEEE802.15.4
|
||||
#Crystal is 40MHz
|
||||
#MAC: 40:4c:ca:ff:fe:47:b4:f0
|
||||
#BASE MAC: 40:4c:ca:47:b4:f0
|
||||
#MAC_EXT: ff:fe
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 4MB
|
||||
#Flash will be erased from 0x00000000 to 0x00005fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x00010000 to 0x00051fff...
|
||||
#Compressed 22336 bytes to 13474...
|
||||
#Wrote 22336 bytes (13474 compressed) at 0x00000000 in 0.3 seconds (effective 624.9 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 104...
|
||||
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 361.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 268624 bytes to 140956...
|
||||
#Wrote 268624 bytes (140956 compressed) at 0x00010000 in 1.2 seconds (effective 1725.6 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Leaving...
|
||||
#Hard resetting via RTS pin...
|
||||
@@ -1,4 +1,4 @@
|
||||
menu "OEPL Hardware config"
|
||||
menu "OEPL config"
|
||||
|
||||
choice OEPL_HARDWARE_PROFILE
|
||||
prompt "Hardware profile"
|
||||
@@ -13,6 +13,15 @@ menu "OEPL Hardware config"
|
||||
config OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
bool "Custom"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_LILYGO
|
||||
bool "LILYGO-AP"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_4inch
|
||||
bool "4inchAP"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_ELECROW_C6
|
||||
bool "ELECROW-C6-AP"
|
||||
|
||||
endchoice
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
@@ -25,6 +34,16 @@ menu "OEPL Hardware config"
|
||||
int "GPIO - UART RX"
|
||||
default 2
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
depends on OEPL_HARDWARE_PROFILE_4inch
|
||||
int "GPIO - UART TX"
|
||||
default 16
|
||||
|
||||
config OEPL_HARDWARE_UART_RX
|
||||
depends on OEPL_HARDWARE_PROFILE_4inch
|
||||
int "GPIO - UART RX"
|
||||
default 17
|
||||
|
||||
config OEPL_SUBGIG_SUPPORT
|
||||
bool "Enable SubGhz Support"
|
||||
default "n"
|
||||
@@ -40,6 +59,7 @@ menu "OEPL Hardware config"
|
||||
default 18 if IDF_TARGET_ESP32C2
|
||||
default 19 if IDF_TARGET_ESP32C3
|
||||
default 30 if IDF_TARGET_ESP32C6
|
||||
default 30 if IDF_TARGET_ESP32H2
|
||||
|
||||
config MISO_GPIO
|
||||
int "CC1101 MISO GPIO"
|
||||
@@ -98,6 +118,16 @@ menu "OEPL Hardware config"
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
config OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Debug logging"
|
||||
default "n"
|
||||
|
||||
config OEPL_VERBOSE_DEBUG
|
||||
depends on OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Verbose Debug logging"
|
||||
default "n"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
|
||||
@@ -13,24 +13,16 @@
|
||||
|
||||
#include "radio.h"
|
||||
#include "proto.h"
|
||||
#include "utils.h"
|
||||
#include "second_uart.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "logging.h"
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
void DumpHex(void *AdrIn,int Len);
|
||||
bool CC1101_QuickCheck(void);
|
||||
|
||||
#define LOGE(format, ... ) \
|
||||
printf("%s#%d: " format,__FUNCTION__,__LINE__,## __VA_ARGS__)
|
||||
|
||||
#if 0
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#define LOG_HEX(x,y) DumpHex(x,y)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#define LOG_HEX(x,y)
|
||||
#endif
|
||||
|
||||
#define wait_Miso(level) CC1101_WaitMISO(__FUNCTION__,__LINE__,level)
|
||||
|
||||
// SPI Stuff
|
||||
#if CONFIG_SPI2_HOST
|
||||
@@ -39,6 +31,9 @@ void DumpHex(void *AdrIn,int Len);
|
||||
#define HOST_ID SPI3_HOST
|
||||
#endif
|
||||
|
||||
// Wait for up to 2 milliseconds for MISO to go low
|
||||
#define MISO_WAIT_TIMEOUT 2
|
||||
|
||||
// Address Config = No address check
|
||||
// Base Frequency = xxx.xxx
|
||||
// CRC Enable = false
|
||||
@@ -247,10 +242,10 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
SubGigErr Ret = SUBGIG_ERR_NONE;
|
||||
|
||||
do {
|
||||
gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
gpio_set_direction(CONFIG_CSN_GPIO, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(CONFIG_CSN_GPIO, 1);
|
||||
|
||||
if(!CC1101_QuickCheck()) {
|
||||
Ret = SUBGIG_CC1101_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
spi_bus_config_t buscfg = {
|
||||
.sclk_io_num = CONFIG_SCK_GPIO,
|
||||
.mosi_io_num = CONFIG_MOSI_GPIO,
|
||||
@@ -297,6 +292,7 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
}
|
||||
// Check Chip ID
|
||||
if(!CC1101_Present()) {
|
||||
LOGE("CC1101 not detected\n");
|
||||
Ret = SUBGIG_CC1101_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
@@ -314,7 +310,7 @@ SubGigErr SubGig_radio_init(uint8_t ch)
|
||||
} while(false);
|
||||
|
||||
if(ErrLine != 0) {
|
||||
LOG("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
|
||||
LOGA("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
|
||||
if(Err == 0) {
|
||||
Ret = ESP_FAIL;
|
||||
}
|
||||
@@ -453,8 +449,6 @@ int8_t SubGig_commsRxUnencrypted(uint8_t *data)
|
||||
if(RxBytes >= 2) {
|
||||
// NB: RxBytes includes the CRC, deduct it
|
||||
Ret = (uint8_t) RxBytes - 2;
|
||||
LOG("Received %d byte subgig frame:\n",Ret);
|
||||
LOG_HEX(data,Ret);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
@@ -477,7 +471,7 @@ int CheckSubGigState()
|
||||
}
|
||||
|
||||
if(Err != SUBGIG_ERR_NONE) {
|
||||
LOG("CheckSubGigState: returing %d\n",Err);
|
||||
LOGE("Returning %d\n",Err);
|
||||
}
|
||||
|
||||
return Err;
|
||||
@@ -558,5 +552,96 @@ void DumpHex(void *AdrIn,int Len)
|
||||
LOG_RAW("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Quick and hopefully safe check if a CC1101 is present.
|
||||
// Only the CSN and MISO GPIOs are configured for this test.
|
||||
// If they are and there's a CC1101 then MISO should go low when
|
||||
// CSN is low
|
||||
bool CC1101_QuickCheck()
|
||||
{
|
||||
// Init CSn and MISO
|
||||
esp_err_t Err = ESP_OK;
|
||||
bool Ret = false;
|
||||
int Line = 0;
|
||||
int MisoLevel;
|
||||
|
||||
do {
|
||||
Err = gpio_reset_pin(CONFIG_MISO_GPIO);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_set_direction(CONFIG_MISO_GPIO,GPIO_MODE_INPUT);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_set_pull_mode(CONFIG_MISO_GPIO,GPIO_PULLUP_ONLY);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
Err = gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
Err = gpio_set_direction(CONFIG_CSN_GPIO,GPIO_MODE_OUTPUT);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,1);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
// The CC1101 is not selected and MISO has a pullup so it should be high
|
||||
if(wait_Miso(1) != 1) {
|
||||
LOGA("Error: SubGhz MISO stuck low\n");
|
||||
break;
|
||||
}
|
||||
// Select the CC1101
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,0);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
MisoLevel = wait_Miso(0);
|
||||
|
||||
// Deselect the CC1101
|
||||
Err = gpio_set_level(CONFIG_CSN_GPIO,1);
|
||||
if(Err != ESP_OK) {
|
||||
Line = __LINE__;
|
||||
break;
|
||||
}
|
||||
|
||||
if(MisoLevel == 0) {
|
||||
Ret = true;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
|
||||
if(Line != 0) {
|
||||
LOGA("%s#%d: gpio call failed (0x%x)\n",__FUNCTION__,__LINE__,Err);
|
||||
}
|
||||
|
||||
if(Ret) {
|
||||
// Disable pullup, it's no longer needed
|
||||
gpio_set_pull_mode(CONFIG_MISO_GPIO,GPIO_FLOATING);
|
||||
}
|
||||
else {
|
||||
// CC1101 not present, deinit MISO and CSn GPIOs
|
||||
LOGE("CC1101 not detected\n");
|
||||
gpio_reset_pin(CONFIG_MISO_GPIO);
|
||||
gpio_reset_pin(CONFIG_CSN_GPIO);
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
|
||||
@@ -34,34 +34,12 @@
|
||||
#include <stdbool.h>
|
||||
#include <driver/spi_master.h>
|
||||
#include "proto.h"
|
||||
#include "utils.h"
|
||||
#include "second_uart.h"
|
||||
#include "cc1101_radio.h"
|
||||
#include "logging.h"
|
||||
#include "radio.h"
|
||||
|
||||
#define ENABLE_LOGGING 0
|
||||
|
||||
// LOGA - generic logging, always enabled
|
||||
#define LOGA(format, ... ) printf(format,## __VA_ARGS__)
|
||||
// LOGE - error logging, always enabled
|
||||
#define LOGE(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
|
||||
#if ENABLE_LOGGING
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#define ENABLE_VERBOSE_LOGGING 0
|
||||
|
||||
#if ENABLE_VERBOSE_LOGGING
|
||||
#define LOGV(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOGV_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
#else
|
||||
#define LOGV(format, ... )
|
||||
#define LOGB_RAW(format, ... )
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -197,7 +175,7 @@ uint8_t CC1101_readReg(uint8_t regAddr, uint8_t regType);
|
||||
void CC1101_writeReg(uint8_t regAddr, uint8_t value);
|
||||
void CC1101_setTxState(void);
|
||||
|
||||
void setIdleState(void);
|
||||
static void setIdleState(void);
|
||||
|
||||
spi_device_handle_t gSpiHndl;
|
||||
|
||||
@@ -288,7 +266,7 @@ static uint8_t gRfState;
|
||||
|
||||
#define cc1101_Select() gpio_set_level(CONFIG_CSN_GPIO, LOW)
|
||||
#define cc1101_Deselect() gpio_set_level(CONFIG_CSN_GPIO, HIGH)
|
||||
#define wait_Miso() while(gpio_get_level(CONFIG_MISO_GPIO)>0)
|
||||
#define wait_Miso() CC1101_WaitMISO(__FUNCTION__,__LINE__,0)
|
||||
#define getGDO0state() gpio_get_level(CONFIG_GDO0_GPIO)
|
||||
#define wait_GDO0_high() while(!getGDO0state())
|
||||
#define wait_GDO0_low() while(getGDO0state())
|
||||
@@ -627,20 +605,19 @@ int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
|
||||
uint8_t Rssi;
|
||||
uint8_t Lqi;
|
||||
int Ret;
|
||||
uint8_t FreqErr;
|
||||
int8_t FreqErr;
|
||||
int8_t FreqCorrection;
|
||||
|
||||
// Any data waiting to be read and no overflow?
|
||||
do {
|
||||
if(rxBytes & CC1101_RXFIFO_OVERFLOW_MASK) {
|
||||
LOGE("RxFifo overflow\n");
|
||||
// This occurs occasionally due to random noise, so do don't log
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
|
||||
if(rxBytes < 2) {
|
||||
// should have at least 2 bytes, packet len and one byte of data
|
||||
LOGE("Internal error, rxBytes = %d\n",rxBytes);
|
||||
Ret = -2;
|
||||
break;
|
||||
}
|
||||
@@ -672,22 +649,19 @@ int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
|
||||
if(pLqi != NULL) {
|
||||
*pLqi = Lqi & CC1101_LQI_MASK;
|
||||
}
|
||||
FreqErr = CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
|
||||
if(FreqErr != 0) {
|
||||
FreqErr += gFreqCorrection;
|
||||
if(gFreqErrSumCount < 255) {
|
||||
gFreqErrSum += FreqErr;
|
||||
gFreqErrSumCount++;
|
||||
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
|
||||
if(gFreqCorrection != FreqCorrection) {
|
||||
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
|
||||
gFreqCorrection = FreqCorrection;
|
||||
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
|
||||
}
|
||||
if(gFreqErrSumCount == 255) {
|
||||
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
|
||||
}
|
||||
}
|
||||
FreqErr = (int8_t) CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
|
||||
if(FreqErr != 0 && gFreqErrSumCount < 255) {
|
||||
gFreqErrSum += FreqErr + gFreqCorrection;
|
||||
gFreqErrSumCount++;
|
||||
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
|
||||
if(gFreqCorrection != FreqCorrection) {
|
||||
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
|
||||
gFreqCorrection = FreqCorrection;
|
||||
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
|
||||
}
|
||||
if(gFreqErrSumCount == 255) {
|
||||
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
|
||||
}
|
||||
}
|
||||
} while(false);
|
||||
|
||||
@@ -704,10 +678,18 @@ bool CC1101_Present()
|
||||
uint8_t PartNum = CC1101_readReg(CC1101_PARTNUM, CC1101_STATUS_REGISTER);
|
||||
uint8_t ChipVersion = CC1101_readReg(CC1101_VERSION, CC1101_STATUS_REGISTER);
|
||||
|
||||
if(PartNum == 0 && ChipVersion == 20) {
|
||||
if(PartNum == 0 && (ChipVersion == 20 || ChipVersion == 4)) {
|
||||
LOGA("CC1101 detected\n");
|
||||
Ret = true;
|
||||
}
|
||||
else {
|
||||
if(PartNum != 0) {
|
||||
LOGA("Invalid PartNum 0x%x\n",PartNum);
|
||||
}
|
||||
else {
|
||||
LOGA("Invalid or unsupported ChipVersion 0x%x\n",ChipVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
@@ -781,5 +763,24 @@ void CC1101_logState()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Wait for up to 2 milliseconds for MISO to go low
|
||||
#define MISO_WAIT_TIMEOUT 2
|
||||
int CC1101_WaitMISO(const char *Func,int Line,int level)
|
||||
{
|
||||
uint32_t Start = getMillis();
|
||||
int MisoLevel;
|
||||
|
||||
while((MisoLevel = gpio_get_level(CONFIG_MISO_GPIO)) != level) {
|
||||
if((getMillis() - Start) >= MISO_WAIT_TIMEOUT) {
|
||||
LOGA("%s#%d: timeout waiting for MISO to go %s\n",
|
||||
Func,Line,level ? "high" : "low");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return MisoLevel;
|
||||
}
|
||||
|
||||
#endif // CONFIG_OEPL_SUBGIG_SUPPORT
|
||||
|
||||
|
||||
@@ -29,6 +29,14 @@
|
||||
#ifndef __CC1101_RADIO_H_
|
||||
#define __CC1101_RADIO_H_
|
||||
|
||||
// Log to all
|
||||
#define LOGA(format, ... ) \
|
||||
uart_printf(format "\r",## __VA_ARGS__)
|
||||
|
||||
// Error log to all
|
||||
#define LOGE(format, ... ) \
|
||||
uart_printf("%s#%d: " format "\r",__FUNCTION__,__LINE__,## __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* CC1101 configuration registers
|
||||
*/
|
||||
@@ -113,6 +121,7 @@ void CC1101_DumpRegs(void);
|
||||
void CC1101_reset(void);
|
||||
void CC1101_logState(void);
|
||||
void CC1101_setRxState(void);
|
||||
int CC1101_WaitMISO(const char *Func,int Line,int level);
|
||||
|
||||
#endif // __CC1101_RADIO_H_
|
||||
|
||||
|
||||
23
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/logging.h
Executable file
23
ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/logging.h
Executable file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#if CONFIG_OEPL_DEBUG_PRINT
|
||||
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
|
||||
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
|
||||
void DumpHex(void *AdrIn,int Len);
|
||||
#define LOG_HEX(x,y) DumpHex(x,y)
|
||||
#else
|
||||
#define LOG(format, ... )
|
||||
#define LOG_RAW(format, ... )
|
||||
#define LOG_HEX(x,y)
|
||||
#endif
|
||||
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
#define LOGV(format, ... ) LOG(format,## __VA_ARGS__)
|
||||
#define LOGV_RAW(format, ... ) LOG_RAW(format,## __VA_ARGS__)
|
||||
#define LOGV_HEX(x,y) LOG_HEX(x,y)
|
||||
#else
|
||||
#define LOGV(format, ... )
|
||||
#define LOGV_RAW(format, ... )
|
||||
#define LOGV_HEX(x,y)
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include "radio.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "second_uart.h"
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#endif
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include <esp_mac.h>
|
||||
@@ -26,6 +28,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "logging.h"
|
||||
#include "SubGigRadio.h"
|
||||
|
||||
|
||||
@@ -33,6 +36,30 @@ static const char *TAG = "MAIN";
|
||||
|
||||
const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
const struct {
|
||||
uint8_t Type;
|
||||
const char *Name;
|
||||
} gPktTypeLookupTbl[] = {
|
||||
{PKT_TAG_RETURN_DATA, "TAG_RETURN_DATA"},
|
||||
{PKT_TAG_RETURN_DATA_ACK, "TAG_RETURN_DATA_ACK"},
|
||||
{PKT_AVAIL_DATA_SHORTREQ, "AVAIL_DATA_SHORTREQ"},
|
||||
{PKT_AVAIL_DATA_REQ, "AVAIL_DATA_REQ"},
|
||||
{PKT_AVAIL_DATA_INFO, "AVAIL_DATA_INFO"},
|
||||
{PKT_BLOCK_PARTIAL_REQUEST, "BLOCK_PARTIAL_REQUEST"},
|
||||
{PKT_BLOCK_REQUEST_ACK, "BLOCK_REQUEST_ACK"},
|
||||
{PKT_BLOCK_REQUEST, "BLOCK_REQUEST"},
|
||||
{PKT_BLOCK_PART, "BLOCK_PART"},
|
||||
{PKT_XFER_COMPLETE, "XFER_COMPLETE"},
|
||||
{PKT_XFER_COMPLETE_ACK, "XFER_COMPLETE_ACK"},
|
||||
{PKT_CANCEL_XFER, "CANCEL_XFER"},
|
||||
{PKT_PING, "PING"},
|
||||
{PKT_PONG, "PONG"},
|
||||
{0,NULL} // End of table
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#define DATATYPE_NOUPDATE 0
|
||||
#define HW_TYPE 0xC6
|
||||
|
||||
@@ -42,7 +69,7 @@ const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
|
||||
struct pendingData pendingDataArr[MAX_PENDING_MACS];
|
||||
|
||||
// VERSION GOES HERE!
|
||||
uint16_t version = 0x0019;
|
||||
uint16_t version = 0x001f;
|
||||
|
||||
#define RAW_PKT_PADDING 2
|
||||
|
||||
@@ -122,7 +149,7 @@ uint8_t getBlockDataLength() {
|
||||
}
|
||||
|
||||
// pendingdata slot stuff
|
||||
int8_t findSlotForMac(const uint8_t *mac) {
|
||||
int32_t findSlotForMac(const uint8_t *mac) {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (memcmp(mac, ((uint8_t *) &(pendingDataArr[c].targetMac)), 8) == 0) {
|
||||
if (pendingDataArr[c].attemptsLeft != 0) {
|
||||
@@ -132,7 +159,7 @@ int8_t findSlotForMac(const uint8_t *mac) {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int8_t findFreeSlot() {
|
||||
int32_t findFreeSlot() {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (pendingDataArr[c].attemptsLeft == 0) {
|
||||
return c;
|
||||
@@ -140,7 +167,7 @@ int8_t findFreeSlot() {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int8_t findSlotForVer(const uint8_t *ver) {
|
||||
int32_t findSlotForVer(const uint8_t *ver) {
|
||||
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
|
||||
if (memcmp(ver, ((uint8_t *) &(pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
|
||||
if (pendingDataArr[c].attemptsLeft != 0) return c;
|
||||
@@ -149,14 +176,14 @@ int8_t findSlotForVer(const uint8_t *ver) {
|
||||
return -1;
|
||||
}
|
||||
void deleteAllPendingDataForVer(const uint8_t *ver) {
|
||||
int8_t slot = -1;
|
||||
int32_t slot = -1;
|
||||
do {
|
||||
slot = findSlotForVer(ver);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
} while (slot != -1);
|
||||
}
|
||||
void deleteAllPendingDataForMac(const uint8_t *mac) {
|
||||
int8_t slot = -1;
|
||||
int32_t slot = -1;
|
||||
do {
|
||||
slot = findSlotForMac(mac);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
@@ -287,7 +314,7 @@ void processSerial(uint8_t lastchar) {
|
||||
if (bytesRemain == 0) {
|
||||
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
|
||||
struct pendingData *pd = (struct pendingData *) serialbuffer;
|
||||
int8_t slot = findSlotForMac(pd->targetMac);
|
||||
int32_t slot = findSlotForMac(pd->targetMac);
|
||||
if (slot == -1) slot = findFreeSlot();
|
||||
if (slot != -1) {
|
||||
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
|
||||
@@ -472,7 +499,7 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
lastBlockRequest = getMillis();
|
||||
} else {
|
||||
// we're talking to another mac, let this mac know we can't accomodate another request right now
|
||||
pr("BUSY!\n");
|
||||
pr("BUSY!\n\r");
|
||||
sendCancelXfer(rxHeader->src);
|
||||
return;
|
||||
}
|
||||
@@ -494,9 +521,9 @@ void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
|
||||
if (forceBlockDownload) {
|
||||
if ((getMillis() - nextBlockAttempt) > 380) {
|
||||
requestDataDownload = true;
|
||||
pr("FORCED\n");
|
||||
pr("FORCED\n\r");
|
||||
} else {
|
||||
pr("IGNORED\n");
|
||||
pr("IGNORED\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -597,7 +624,7 @@ void processXferComplete(uint8_t *buffer) {
|
||||
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
|
||||
memcpy((void *) lastAckMac, (void *) rxHeader->src, 8);
|
||||
espNotifyXferComplete(rxHeader->src);
|
||||
int8_t slot = findSlotForMac(rxHeader->src);
|
||||
int32_t slot = findSlotForMac(rxHeader->src);
|
||||
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
|
||||
}
|
||||
}
|
||||
@@ -645,7 +672,7 @@ void sendPart(uint8_t partNo) {
|
||||
}
|
||||
void sendBlockData() {
|
||||
if (getBlockDataLength() == 0) {
|
||||
pr("Invalid block request received, 0 parts..\n");
|
||||
pr("Invalid block request received, 0 parts..\n\r");
|
||||
requestedData.requestedParts[0] |= 0x01;
|
||||
}
|
||||
|
||||
@@ -658,7 +685,7 @@ void sendBlockData() {
|
||||
pr(".");
|
||||
}
|
||||
}
|
||||
pr("\n");
|
||||
pr("\n\r");
|
||||
|
||||
uint8_t partNo = 0;
|
||||
while (partNo < BLOCK_MAX_PARTS) {
|
||||
@@ -752,16 +779,36 @@ void app_main(void) {
|
||||
|
||||
pr("RES>");
|
||||
pr("RDY>");
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
ESP_LOGI(TAG, "C6 ready!");
|
||||
#else
|
||||
ESP_LOGI(TAG, "H2 ready!");
|
||||
#endif
|
||||
|
||||
housekeepingTimer = getMillis();
|
||||
while (1) {
|
||||
while ((getMillis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
|
||||
int8_t ret = commsRxUnencrypted(radiorxbuffer);
|
||||
int32_t ret = commsRxUnencrypted(radiorxbuffer);
|
||||
if (ret > 1) {
|
||||
led_flash(0);
|
||||
|
||||
uint8_t PktType = getPacketType(radiorxbuffer);
|
||||
#if CONFIG_OEPL_VERBOSE_DEBUG
|
||||
LOGV_RAW("Received %d byte ",ret);
|
||||
for(uint8_t i = 0; gPktTypeLookupTbl[i].Name != NULL; i++) {
|
||||
if(gPktTypeLookupTbl[i].Type == PktType) {
|
||||
LOGV_RAW("%s",gPktTypeLookupTbl[i].Name);
|
||||
break;
|
||||
}
|
||||
if(gPktTypeLookupTbl[i].Name == NULL) {
|
||||
LOGV_RAW("undefined (0x%02x)",PktType);
|
||||
}
|
||||
}
|
||||
LOGV_RAW(" packet:\n");
|
||||
LOGV_HEX(radiorxbuffer,ret);
|
||||
#endif
|
||||
// received a packet, lets see what it is
|
||||
switch (getPacketType(radiorxbuffer)) {
|
||||
switch (PktType) {
|
||||
case PKT_AVAIL_DATA_REQ:
|
||||
if (ret == 28) {
|
||||
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#define LED1 22
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#define LED2 23
|
||||
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||
#define LED2 25
|
||||
#endif
|
||||
|
||||
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
|
||||
#define PROTO_PAN_ID_SUBGHZ (0x1337) // PAN ID compression shall be used
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include "sdkconfig.h"
|
||||
// if you get an error about soc/lp_uart_reg.h not being found,
|
||||
// you didn't choose the right build target. :-)
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#endif
|
||||
#include "soc/uart_struct.h"
|
||||
#include "utils.h"
|
||||
#include <esp_mac.h>
|
||||
@@ -32,7 +34,6 @@ static const char *TAG = "RADIO";
|
||||
uint8_t mSelfMac[8];
|
||||
volatile uint8_t isInTransmit = 0;
|
||||
QueueHandle_t packet_buffer = NULL;
|
||||
|
||||
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
|
||||
ESP_EARLY_LOGI(TAG, "RX %d", frame[0]);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
@@ -40,6 +41,9 @@ void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *fr
|
||||
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
|
||||
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
|
||||
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
|
||||
if(esp_ieee802154_receive_handle_done(frame)) {
|
||||
ESP_EARLY_LOGI(TAG, "esp_ieee802154_receive_handle_done() failed");
|
||||
}
|
||||
}
|
||||
|
||||
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
|
||||
@@ -50,12 +54,23 @@ void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_erro
|
||||
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
|
||||
isInTransmit = 0;
|
||||
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
|
||||
if(ack != NULL) {
|
||||
if(esp_ieee802154_receive_handle_done(ack)) {
|
||||
ESP_EARLY_LOGI(TAG, "esp_ieee802154_receive_handle_done() failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool zigbee_is_enabled = false;
|
||||
void radio_init(uint8_t ch) {
|
||||
if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130);
|
||||
|
||||
// this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works
|
||||
if(zigbee_is_enabled)
|
||||
{
|
||||
zigbee_is_enabled = false;
|
||||
esp_ieee802154_disable();
|
||||
}
|
||||
zigbee_is_enabled = true;
|
||||
esp_ieee802154_enable();
|
||||
esp_ieee802154_set_channel(ch);
|
||||
// esp_ieee802154_set_txpower(int8_t power);
|
||||
@@ -101,8 +116,6 @@ bool radioTx(uint8_t *packet) {
|
||||
static uint8_t txPKT[130];
|
||||
#endif
|
||||
led_flash(1);
|
||||
while (isInTransmit) {
|
||||
}
|
||||
// while (getMillis() - lastZbTx < 6) {
|
||||
// }
|
||||
// lastZbTx = getMillis();
|
||||
@@ -114,6 +127,8 @@ bool radioTx(uint8_t *packet) {
|
||||
return SubGig_radioTx(packet);
|
||||
}
|
||||
#endif
|
||||
while (isInTransmit) {
|
||||
}
|
||||
isInTransmit = 1;
|
||||
esp_ieee802154_transmit(txPKT, false);
|
||||
return true;
|
||||
|
||||
@@ -19,10 +19,12 @@
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#endif
|
||||
static const char *TAG = "SECOND_UART";
|
||||
#include "second_uart.h"
|
||||
|
||||
static const char *TAG = "SECOND_UART";
|
||||
|
||||
#define BUF_SIZE (1024)
|
||||
#define RD_BUF_SIZE (BUF_SIZE)
|
||||
@@ -43,6 +45,8 @@ void init_second_uart() {
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
ESP_LOGI(TAG, "HARDWARE_UART_TX %d, CONFIG_OEPL_HARDWARE_UART_RX %d",
|
||||
CONFIG_OEPL_HARDWARE_UART_TX,CONFIG_OEPL_HARDWARE_UART_RX);
|
||||
ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0));
|
||||
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
|
||||
ESP_ERROR_CHECK(uart_set_pin(1, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
|
||||
|
||||
@@ -13,11 +13,17 @@ void uart_printf(const char *format, ...);
|
||||
#define pr uart_printf
|
||||
|
||||
#if defined(CONFIG_OEPL_HARDWARE_PROFILE_DEFAULT)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 3
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 2
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 3
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 2
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_LILYGO)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 24
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 23
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_POE_AP)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 5
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 18
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_ELECROW_C6)
|
||||
#define CONFIG_OEPL_HARDWARE_UART_TX 0
|
||||
#define CONFIG_OEPL_HARDWARE_UART_RX 1
|
||||
#elif defined(CONFIG_OEPL_HARDWARE_PROFILE_CUSTOM)
|
||||
#if !defined(CONFIG_OEPL_HARDWARE_UART_TX) || !defined(CONFIG_OEPL_HARDWARE_UART_RX)
|
||||
#error "No UART TX / RX pins defined. Please check menuconfig"
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include "proto.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_struct.h"
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32C6
|
||||
#include "soc/lp_uart_reg.h"
|
||||
#endif
|
||||
#include "nvs_flash.h"
|
||||
|
||||
void delay(int ms) { vTaskDelay(pdMS_TO_TICKS(ms)); }
|
||||
|
||||
@@ -7,4 +7,4 @@ CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_OEPL_SUBGIG_SUPPORT=y
|
||||
|
||||
CONFIG_IEEE802154_RX_BUFFER_SIZE=100
|
||||
|
||||
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/.gitignore
vendored
Normal file
8
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
build
|
||||
*.axf
|
||||
# Allow
|
||||
!*.bin
|
||||
|
||||
.vscode
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/CMakeLists.txt
Normal file
6
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(OpenEPaperLink_esp32_H2)
|
||||
45
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/compile.ps1
Normal file
45
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/compile.ps1
Normal file
@@ -0,0 +1,45 @@
|
||||
|
||||
#| Function | ESP32H2 Pin | ESP32S3 Pin
|
||||
#| :--------------------------------: | :-------------------: | :------------------
|
||||
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
|
||||
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
|
||||
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
|
||||
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
|
||||
|
||||
idf.py fullclean
|
||||
|
||||
idf.py build
|
||||
|
||||
#python -m esptool -p COM11 -b 460800 --before default_reset --after hard_reset --chip esp32h2 write_flash --flash_mode dio --flash_size detect --flash_freq 48m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_H2.bin
|
||||
|
||||
|
||||
#idf.py -p COM8 flash
|
||||
|
||||
|
||||
#Chip is ESP32-H2 (revision v0.1)
|
||||
#Features: BLE, IEEE802.15.4
|
||||
#Crystal is 32MHz
|
||||
#MAC: 74:4d:bd:ff:fe:63:84:e8
|
||||
#BASE MAC: 74:4d:bd:63:84:e8
|
||||
#MAC_EXT: ff:fe
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 4MB
|
||||
#Flash will be erased from 0x00000000 to 0x00005fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x00010000 to 0x0004dfff...
|
||||
#Compressed 22080 bytes to 13385...
|
||||
#Wrote 22080 bytes (13385 compressed) at 0x00000000 in 0.3 seconds (effective 511.5 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 104...
|
||||
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 309.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 253952 bytes to 133359...
|
||||
#Wrote 253952 bytes (133359 compressed) at 0x00010000 in 1.9 seconds (effective 1098.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
@@ -0,0 +1,3 @@
|
||||
idf_component_register( SRCS
|
||||
SRC_DIRS "../../OpenEPaperLink_esp32_C6_AP/main"
|
||||
INCLUDE_DIRS "../../OpenEPaperLink_esp32_C6_AP/main")
|
||||
111
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/Kconfig.projbuild
Normal file
111
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/main/Kconfig.projbuild
Normal file
@@ -0,0 +1,111 @@
|
||||
menu "OEPL config"
|
||||
|
||||
choice OEPL_HARDWARE_PROFILE
|
||||
prompt "Hardware profile"
|
||||
default OEPL_HARDWARE_PROFILE_LILYGO
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
bool "Custom"
|
||||
|
||||
config OEPL_HARDWARE_PROFILE_LILYGO
|
||||
bool "LILYGO-AP"
|
||||
|
||||
endchoice
|
||||
|
||||
config OEPL_HARDWARE_UART_TX
|
||||
depends on OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
int "GPIO - UART TX"
|
||||
default 3
|
||||
|
||||
config OEPL_HARDWARE_UART_RX
|
||||
depends on OEPL_HARDWARE_PROFILE_CUSTOM
|
||||
int "GPIO - UART RX"
|
||||
default 2
|
||||
|
||||
config OEPL_SUBGIG_SUPPORT
|
||||
bool "Enable SubGhz Support"
|
||||
default "n"
|
||||
|
||||
menu "CC1101 Configuration"
|
||||
depends on OEPL_SUBGIG_SUPPORT
|
||||
|
||||
config GPIO_RANGE_MAX
|
||||
int
|
||||
default 33 if IDF_TARGET_ESP32
|
||||
default 46 if IDF_TARGET_ESP32S2
|
||||
default 48 if IDF_TARGET_ESP32S3
|
||||
default 18 if IDF_TARGET_ESP32C2
|
||||
default 19 if IDF_TARGET_ESP32C3
|
||||
default 30 if IDF_TARGET_ESP32C6
|
||||
default 30 if IDF_TARGET_ESP32H2
|
||||
|
||||
config MISO_GPIO
|
||||
int "CC1101 MISO GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 7
|
||||
help
|
||||
Pin Number to be used as the MISO SPI signal.
|
||||
|
||||
config SCK_GPIO
|
||||
int "CC1101 SCK GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 0
|
||||
help
|
||||
Pin Number to be used as the SCK SPI signal.
|
||||
|
||||
config MOSI_GPIO
|
||||
int "CC1101 MOSI GPIO"
|
||||
default 1
|
||||
help
|
||||
Pin Number to be used as the MOSI SPI signal.
|
||||
|
||||
config CSN_GPIO
|
||||
int "CC1101 CSN GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 4
|
||||
help
|
||||
Pin Number to be used as the CSN SPI signal.
|
||||
|
||||
config GDO0_GPIO
|
||||
int "CC1101 GDO0 GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 5
|
||||
help
|
||||
Pin Number to be used as the GDO0 signal.
|
||||
|
||||
config GDO2_GPIO
|
||||
int "CC1101 GDO2 GPIO"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 6
|
||||
help
|
||||
Pin Number to be used as the GDO2 signal.
|
||||
|
||||
choice SPI_HOST
|
||||
prompt "SPI peripheral that controls this bus"
|
||||
default SPI2_HOST
|
||||
help
|
||||
Select SPI peripheral that controls this bus.
|
||||
config SPI2_HOST
|
||||
bool "SPI2_HOST"
|
||||
help
|
||||
Use SPI2_HOST. This is also called HSPI_HOST.
|
||||
config SPI3_HOST
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
bool "SPI3_HOST"
|
||||
help
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
endchoice
|
||||
endmenu
|
||||
|
||||
config OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Debug logging"
|
||||
default "n"
|
||||
|
||||
config OEPL_VERBOSE_DEBUG
|
||||
depends on OEPL_DEBUG_PRINT
|
||||
bool "Enable OEPL Verbose Debug logging"
|
||||
default "n"
|
||||
|
||||
endmenu
|
||||
|
||||
|
||||
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/partitions.csv
Normal file
5
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/partitions.csv
Normal file
@@ -0,0 +1,5 @@
|
||||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs,data,nvs,0x9000,0x6000,,
|
||||
factory,app,factory,0x10000,1M,,
|
||||
littlefs,data,spiffs,,3008K,,
|
||||
|
16
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/sdkconfig.defaults
Normal file
16
ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/sdkconfig.defaults
Normal file
@@ -0,0 +1,16 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32h2"
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
|
||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||
CONFIG_OEPL_HARDWARE_PROFILE_LILYGO=y
|
||||
CONFIG_OEPL_SUBGIG_SUPPORT=y
|
||||
CONFIG_MISO_GPIO=25
|
||||
CONFIG_SCK_GPIO=3
|
||||
CONFIG_MOSI_GPIO=11
|
||||
CONFIG_CSN_GPIO=8
|
||||
CONFIG_GDO0_GPIO=2
|
||||
CONFIG_GDO2_GPIO=22
|
||||
76
ESP32_AP-Flasher/compile.ps1
Normal file
76
ESP32_AP-Flasher/compile.ps1
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
#| Function | ESP32H2 Pin | ESP32S3 Pin
|
||||
#| :--------------------------------: | :-------------------: | :------------------
|
||||
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
|
||||
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
|
||||
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
|
||||
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
|
||||
|
||||
# cd ESP32_AP-Flasher
|
||||
|
||||
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
|
||||
python gzip_wwwfiles.py
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
# mkdir ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_LILYGO_AP\boot_app0.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\firmware.bin ESP32_S3_16_8_LILYGO_AP\firmware.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\bootloader.bin ESP32_S3_16_8_LILYGO_AP\bootloader.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\partitions.bin ESP32_S3_16_8_LILYGO_AP\partitions.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\littlefs.bin ESP32_S3_16_8_LILYGO_AP\littlefs.bin
|
||||
|
||||
copy ESP32_S3_16_8_LILYGO_AP\firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP.bin
|
||||
|
||||
copy ESP32_S3_16_8_LILYGO_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP_full.bin
|
||||
|
||||
cd ESP32_S3_16_8_LILYGO_AP
|
||||
|
||||
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
#python -m esptool -p COM12 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
cd ..
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM12
|
||||
#Connecting...
|
||||
#Chip is ESP32-S3 (QFN56) (revision v0.2)
|
||||
#Features: WiFi, BLE
|
||||
#Crystal is 40MHz
|
||||
#MAC: f4:12:fa:af:5b:9c
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 16MB
|
||||
#Flash will be erased from 0x00000000 to 0x00003fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x0000e000 to 0x0000ffff...
|
||||
#Flash will be erased from 0x00010000 to 0x00203fff...
|
||||
#Flash will be erased from 0x00910000 to 0x00feffff...
|
||||
#Compressed 15104 bytes to 10401...
|
||||
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.3 seconds (effective 375.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 146...
|
||||
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 272.1 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 8192 bytes to 47...
|
||||
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 447.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 2047040 bytes to 1259376...
|
||||
#Wrote 2047040 bytes (1259376 compressed) at 0x00010000 in 18.7 seconds (effective 876.9 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 7208960 bytes to 302805...
|
||||
#Wrote 7208960 bytes (302805 compressed) at 0x00910000 in 47.0 seconds (effective 1227.2 kbit/s)...
|
||||
#Hash of data verified.
|
||||
69
ESP32_AP-Flasher/compileyellow.ps1
Normal file
69
ESP32_AP-Flasher/compileyellow.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
# cd ESP32_AP-Flasher
|
||||
|
||||
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
|
||||
python gzip_wwwfiles.py
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
# mkdir ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_YELLOW_AP\boot_app0.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\firmware.bin ESP32_S3_16_8_YELLOW_AP\firmware.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\bootloader.bin ESP32_S3_16_8_YELLOW_AP\bootloader.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\partitions.bin ESP32_S3_16_8_YELLOW_AP\partitions.bin
|
||||
|
||||
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\littlefs.bin ESP32_S3_16_8_YELLOW_AP\littlefs.bin
|
||||
|
||||
copy ESP32_S3_16_8_YELLOW_AP\firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP.bin
|
||||
|
||||
copy ESP32_S3_16_8_YELLOW_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP_full.bin
|
||||
|
||||
cd ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
#python -m esptool -p COM4 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
|
||||
|
||||
cd ..
|
||||
|
||||
#esptool.py v4.7.0
|
||||
#Serial port COM4
|
||||
#Connecting...
|
||||
#Chip is ESP32-S3 (QFN56) (revision v0.2)
|
||||
#Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
|
||||
#Crystal is 40MHz
|
||||
#MAC: dc:da:0c:16:cf:4c
|
||||
#Uploading stub...
|
||||
#Running stub...
|
||||
#Stub running...
|
||||
#Changing baud rate to 460800
|
||||
#Changed.
|
||||
#Configuring flash size...
|
||||
#Auto-detected Flash size: 16MB
|
||||
#Flash will be erased from 0x00000000 to 0x00003fff...
|
||||
#Flash will be erased from 0x00008000 to 0x00008fff...
|
||||
#Flash will be erased from 0x0000e000 to 0x0000ffff...
|
||||
#Flash will be erased from 0x00010000 to 0x001dbfff...
|
||||
#Flash will be erased from 0x00910000 to 0x00feffff...
|
||||
#Compressed 15104 bytes to 10401...
|
||||
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.4 seconds (effective 277.3 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 3072 bytes to 146...
|
||||
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 425.0 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 8192 bytes to 47...
|
||||
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 632.5 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 1881424 bytes to 1196500...
|
||||
#Wrote 1881424 bytes (1196500 compressed) at 0x00010000 in 27.6 seconds (effective 544.8 kbit/s)...
|
||||
#Hash of data verified.
|
||||
#Compressed 7208960 bytes to 302804...
|
||||
#Wrote 7208960 bytes (302804 compressed) at 0x00910000 in 35.0 seconds (effective 1648.8 kbit/s)...
|
||||
#Hash of data verified.
|
||||
|
||||
BIN
ESP32_AP-Flasher/data/fonts/tahoma11.vlw
Normal file
BIN
ESP32_AP-Flasher/data/fonts/tahoma11.vlw
Normal file
Binary file not shown.
Binary file not shown.
64
ESP32_AP-Flasher/data/tagtypes/E2.json
Normal file
64
ESP32_AP-Flasher/data/tagtypes/E2.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"version": 1,
|
||||
"name": "LILYGO TPANEL 4\"",
|
||||
"width": 480,
|
||||
"height": 480,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 16,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ]
|
||||
},
|
||||
"shortlut": 0,
|
||||
"options": [ ],
|
||||
"contentids": [ 22, 1, 2, 3, 4, 8, 7, 19, 10, 11, 21 ],
|
||||
"template": {
|
||||
"21": [
|
||||
{ "box": [ 0, 0, 480, 480, 1 ] },
|
||||
{ "text": [ 10, 15, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 70, "IP address:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 70, "{ap_ip}", "bahnschrift30", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 10, 110, "Channel:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 110, "{ap_ch}", "bahnschrift30", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 10, 150, "Tag count:", "bahnschrift30", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 180, 150, "{ap_tagcount}", "bahnschrift30", 0, 0, 0, "1" ] }
|
||||
],
|
||||
"1": {
|
||||
"weekday": [ 240, 30, "Signika-SB.ttf", 90 ],
|
||||
"month": [ 240, 330, "Signika-SB.ttf", 90 ],
|
||||
"day": [ 240, 80, "Signika-SB.ttf", 250 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 95, "fonts/calibrib50" ],
|
||||
"temp": [ 20, 200, "fonts/calibrib100" ],
|
||||
"icon": [ 400, 30, 150, 2 ],
|
||||
"dir": [ 40, 70, 80 ],
|
||||
"umbrella": [ 325, 250, 150 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "Signika-SB.ttf", 150, 150, 110, 80, 60, 50 ],
|
||||
"xy": [ 240, 240 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 10, 20, "fonts/calibrib50" ],
|
||||
"column": [ 6, 80 ],
|
||||
"day": [ 40, 100, "fonts/bahnschrift30", 144, 270 ],
|
||||
"rain": [ 40, 320 ],
|
||||
"icon": [ 40, 180, 50 ],
|
||||
"wind": [ 17, 120 ],
|
||||
"line": [ 100, 340 ]
|
||||
},
|
||||
"10": {
|
||||
"title": [ 240, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 240, 35 ]
|
||||
},
|
||||
"11": {
|
||||
"rotate": 0,
|
||||
"mode": 1,
|
||||
"days": 4,
|
||||
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,54 +10,7 @@
|
||||
"/www/painter.js",
|
||||
"/www/setup.html",
|
||||
"/www/setup.js",
|
||||
"/www/upload-demo.html",
|
||||
"/fonts/weathericons30.vlw",
|
||||
"/fonts/weathericons70.vlw",
|
||||
"/fonts/weathericons78.vlw",
|
||||
"/fonts/calibrib120.vlw",
|
||||
"/fonts/calibrib150.vlw",
|
||||
"/fonts/calibrib50.vlw",
|
||||
"/fonts/calibrib60.vlw",
|
||||
"/fonts/BellCent10.vlw",
|
||||
"/tagtypes/00.json",
|
||||
"/tagtypes/01.json",
|
||||
"/tagtypes/02.json",
|
||||
"/tagtypes/05.json",
|
||||
"/tagtypes/11.json",
|
||||
"/tagtypes/21.json",
|
||||
"/tagtypes/22.json",
|
||||
"/tagtypes/26.json",
|
||||
"/tagtypes/27.json",
|
||||
"/tagtypes/2E.json",
|
||||
"/tagtypes/2F.json",
|
||||
"/tagtypes/30.json",
|
||||
"/tagtypes/31.json",
|
||||
"/tagtypes/32.json",
|
||||
"/tagtypes/33.json",
|
||||
"/tagtypes/34.json",
|
||||
"/tagtypes/35.json",
|
||||
"/tagtypes/36.json",
|
||||
"/tagtypes/40.json",
|
||||
"/tagtypes/41.json",
|
||||
"/tagtypes/42.json",
|
||||
"/tagtypes/43.json",
|
||||
"/tagtypes/55.json",
|
||||
"/tagtypes/60.json",
|
||||
"/tagtypes/61.json",
|
||||
"/tagtypes/62.json",
|
||||
"/tagtypes/80.json",
|
||||
"/tagtypes/81.json",
|
||||
"/tagtypes/82.json",
|
||||
"/tagtypes/83.json",
|
||||
"/tagtypes/B0.json",
|
||||
"/tagtypes/B1.json",
|
||||
"/tagtypes/B2.json",
|
||||
"/tagtypes/B3.json",
|
||||
"/tagtypes/B5.json",
|
||||
"/tagtypes/BD.json",
|
||||
"/tagtypes/BE.json",
|
||||
"/tagtypes/E0.json",
|
||||
"/tagtypes/E1.json",
|
||||
"/tagtypes/F0.json"
|
||||
"/www/flash.js",
|
||||
"/www/upload-demo.html"
|
||||
]
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ESP32_AP-Flasher/data/www/g5decoder.js.gz
Normal file
BIN
ESP32_AP-Flasher/data/www/g5decoder.js.gz
Normal file
Binary file not shown.
Binary file not shown.
BIN
ESP32_AP-Flasher/data/www/jsontemplate-demo-v2.html.gz
Normal file
BIN
ESP32_AP-Flasher/data/www/jsontemplate-demo-v2.html.gz
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7
ESP32_AP-Flasher/esp32_sdcard_only.csv
Normal file
7
ESP32_AP-Flasher/esp32_sdcard_only.csv
Normal file
@@ -0,0 +1,7 @@
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x1E0000,
|
||||
app1, app, ota_1, 0x1F0000,0x1E0000,
|
||||
spiffs, data, spiffs, 0x3D0000,0x20000,
|
||||
coredump, data, coredump,0x3F0000,0x10000,
|
||||
|
@@ -4,9 +4,9 @@
|
||||
|
||||
class SPIFFSEditor: public AsyncWebHandler {
|
||||
private:
|
||||
fs::FS _fs;
|
||||
mutable fs::FS _fs;
|
||||
String _username;
|
||||
String _password;
|
||||
String _password;
|
||||
bool _authenticated;
|
||||
uint32_t _startTime;
|
||||
public:
|
||||
@@ -15,10 +15,10 @@ class SPIFFSEditor: public AsyncWebHandler {
|
||||
#else
|
||||
SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
|
||||
#endif
|
||||
virtual bool canHandle(AsyncWebServerRequest *request) override final;
|
||||
virtual bool canHandle(AsyncWebServerRequest* request) const override final;
|
||||
virtual void handleRequest(AsyncWebServerRequest *request) override final;
|
||||
virtual void handleUpload(AsyncWebServerRequest *request, const String& filename, size_t index, uint8_t *data, size_t len, bool final) override final;
|
||||
virtual bool isRequestHandlerTrivial() override final {return false;}
|
||||
virtual bool isRequestHandlerTrivial() const override final {return false;}
|
||||
virtual String listFilesRecursively(String path, bool recursive = false);
|
||||
};
|
||||
|
||||
|
||||
@@ -6,5 +6,6 @@ uint8_t gicToOEPLtype(uint8_t gicType);
|
||||
bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice);
|
||||
bool BLE_is_image_pending(uint8_t address[8]);
|
||||
uint32_t compress_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len);
|
||||
uint32_t get_ATC_BLE_OEPL_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len, uint8_t* dataType, uint8_t* dataTypeArgument, uint16_t* nextCheckIn);
|
||||
|
||||
#endif
|
||||
|
||||
58
ESP32_AP-Flasher/include/cc_interface.h
Executable file
58
ESP32_AP-Flasher/include/cc_interface.h
Executable file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
|
||||
typedef void (*callbackPtr)(uint8_t percent);
|
||||
|
||||
class CC_interface
|
||||
{
|
||||
public:
|
||||
uint16_t begin(uint8_t CC, uint8_t DD, uint8_t RESET);
|
||||
void set_callback(callbackPtr callBack = nullptr);
|
||||
uint8_t set_lock_byte(uint8_t lock_byte);
|
||||
uint8_t erase_chip();
|
||||
void read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
|
||||
void read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
|
||||
void write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
|
||||
void set_pc(uint16_t address);
|
||||
uint8_t clock_init();
|
||||
uint8_t write_code_memory(uint16_t address, uint8_t buffer[], int len);
|
||||
uint8_t verify_code_memory(uint16_t address, uint8_t buffer[], int len);
|
||||
uint8_t opcode(uint8_t opCode);
|
||||
uint8_t opcode(uint8_t opCode, uint8_t opCode1);
|
||||
uint8_t opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2);
|
||||
uint8_t WR_CONFIG(uint8_t config);
|
||||
uint8_t WD_CONFIG();
|
||||
/* Send one byte and return one byte as answer */
|
||||
uint8_t send_cc_cmdS(uint8_t cmd);
|
||||
/* Send one byte and returns two bytes as answer */
|
||||
uint16_t send_cc_cmd(uint8_t cmd);
|
||||
void cc_send_byte(uint8_t in_byte);
|
||||
uint8_t cc_receive_byte();
|
||||
void enable_cc_debug();
|
||||
void reset_cc();
|
||||
|
||||
private:
|
||||
boolean dd_direction = 0; // 0=OUT 1=IN
|
||||
uint8_t _CC_PIN = -1;
|
||||
uint8_t _DD_PIN = -1;
|
||||
uint8_t _RESET_PIN = -1;
|
||||
uint8_t flash_opcode[30] = {
|
||||
0x75, 0xAD, 0x00, // Set Flash Address HIGH
|
||||
0x75, 0xAC, 0x00, // Set Flash Address LOW
|
||||
0x90, 0xF0, 0x00, // Set RAM Address to 0xF000
|
||||
0x75, 0xAE, 0x02, // Enable Flash Writing
|
||||
0x7D, 0x08, // Set Loop value to Half size as we write 2bytes at once 0x100
|
||||
0xE0, // Put DPTR to A
|
||||
0xF5, 0xAF, // Put A to FWDATA
|
||||
0xA3, // Increase DPTR;
|
||||
0xE0, // Put DPTR to A
|
||||
0xF5, 0xAF, // Put A to FWDATA
|
||||
0xA3, // Increase DPTR
|
||||
0xE5, 0xAE, // Wait till writing is done
|
||||
0x20, 0xE6, 0xFB,
|
||||
0xDD, 0xF1, // Loop trough all bytes
|
||||
0xA5 // Breakpoint
|
||||
};
|
||||
callbackPtr _callback = nullptr;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <LittleFS.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "makeimage.h"
|
||||
#include "tag_db.h"
|
||||
@@ -19,9 +20,9 @@ void checkVars();
|
||||
void drawNew(const uint8_t mac[8], tagRecord *&taginfo);
|
||||
bool updateTagImage(String &filename, const uint8_t *dst, uint16_t nextCheckin, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawString(TFT_eSprite &spr, String content, int16_t posx, int16_t posy, String font, byte align = 0, uint16_t color = TFT_BLACK, uint16_t size = 30, uint16_t bgcolor = TFT_WHITE);
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color = TFT_BLACK, uint16_t bgcolor = TFT_WHITE, float lineheight = 1);
|
||||
void drawTextBox(TFT_eSprite &spr, String &content, int16_t &posx, int16_t &posy, int16_t boxwidth, int16_t boxheight, String font, uint16_t color = TFT_BLACK, uint16_t bgcolor = TFT_WHITE, float lineheight = 1, byte align = TL_DATUM);
|
||||
void initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams);
|
||||
void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawDate(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams);
|
||||
void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo, imgParam &imageParams);
|
||||
@@ -48,4 +49,5 @@ void getLocation(JsonObject &cfgobj);
|
||||
void prepareNFCReq(const uint8_t *dst, const char *url);
|
||||
void prepareLUTreq(const uint8_t *dst, const String &input);
|
||||
void prepareConfigFile(const uint8_t *dst, const JsonObject &config);
|
||||
void prepareTIME_RAW(const uint8_t *dst, time_t now);
|
||||
void getTemplate(JsonDocument &json, const uint8_t id, const uint8_t hwtype);
|
||||
|
||||
@@ -1,4 +1,20 @@
|
||||
#include <Arduino.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
bool doC6flash(uint8_t doDownload);
|
||||
#if defined HAS_H2
|
||||
#define SHORT_CHIP_NAME "H2"
|
||||
#define OTA_BIN_DIR "ESP32-H2"
|
||||
#define ESP_CHIP_TYPE ESP32H2_CHIP
|
||||
#elif defined HAS_TSLR
|
||||
#define SHORT_CHIP_NAME "TSLR"
|
||||
#elif defined HAS_ELECROW_C6
|
||||
#define SHORT_CHIP_NAME "ELECROW_C6"
|
||||
#define OTA_BIN_DIR "ESP32-C6"
|
||||
#define ESP_CHIP_TYPE ESP32C6_CHIP
|
||||
#elif defined C6_OTA_FLASHING
|
||||
#define SHORT_CHIP_NAME "C6"
|
||||
#define OTA_BIN_DIR "ESP32-C6"
|
||||
#define ESP_CHIP_TYPE ESP32C6_CHIP
|
||||
#endif
|
||||
|
||||
bool FlashC6_H2(const char *Url);
|
||||
|
||||
@@ -1,6 +1,138 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
#ifdef HAS_LILYGO_TPANEL
|
||||
|
||||
#define LV_ATTRIBUTE_TICK_INC IRAM_ATTR
|
||||
#define TOUCH_MODULES_CST_MUTUAL
|
||||
|
||||
// SD
|
||||
#define SD_CS 38
|
||||
#define SD_SCLK 36
|
||||
#define SD_MOSI 35
|
||||
#define SD_MISO 37
|
||||
|
||||
// IIC
|
||||
#define IIC_SDA 17
|
||||
#define IIC_SCL 18
|
||||
|
||||
// ESP32H2
|
||||
#define ESP32H2_TX 48
|
||||
#define ESP32H2_RX 47
|
||||
|
||||
// #define T_Panel_V1_0_RS485
|
||||
#define T_Panel_V1_2_RS485
|
||||
// #define T_Panel_V1_2_CAN
|
||||
|
||||
#if defined T_Panel_V1_0_RS485
|
||||
#define RS485_TX 15
|
||||
#define RS485_RX 16
|
||||
#endif
|
||||
|
||||
#if defined T_Panel_V1_2_RS485
|
||||
#define RS485_TX 16
|
||||
#define RS485_RX 15
|
||||
#endif
|
||||
|
||||
#if defined T_Panel_V1_2_CAN
|
||||
#define CAN_TX 16
|
||||
#define CAN_RX 15
|
||||
#endif
|
||||
|
||||
// YDP395BT001-V2
|
||||
#define LCD_WIDTH 480
|
||||
#define LCD_HEIGHT 480
|
||||
#define LCD_VSYNC 40
|
||||
#define LCD_HSYNC 39
|
||||
#define LCD_PCLK 41
|
||||
#define LCD_B0 1
|
||||
#define LCD_B1 2
|
||||
#define LCD_B2 3
|
||||
#define LCD_B3 4
|
||||
#define LCD_B4 5
|
||||
#define LCD_G0 6
|
||||
#define LCD_G1 7
|
||||
#define LCD_G2 8
|
||||
#define LCD_G3 9
|
||||
#define LCD_G4 10
|
||||
#define LCD_G5 11
|
||||
#define LCD_R0 12
|
||||
#define LCD_R1 13
|
||||
#define LCD_R2 42
|
||||
#define LCD_R3 46
|
||||
#define LCD_R4 45
|
||||
#define LCD_BL 14
|
||||
|
||||
// CST3240
|
||||
#define CST3240_ADDRESS 0x5A
|
||||
#define TOUCH_SDA 17
|
||||
#define TOUCH_SCL 18
|
||||
#define TOUCH_INT 21
|
||||
#define TOUCH_RST 4
|
||||
|
||||
// XL95x5
|
||||
#define XL95X5_CS 17
|
||||
#define XL95X5_SCLK 15
|
||||
#define XL95X5_MOSI 16
|
||||
#define XL95X5_TOUCH_RST 4
|
||||
#define XL95X5_RS485_CON 7
|
||||
#define XL95X5_LCD_RST 5
|
||||
#define XL95X5_ESP32H2_IO12 1
|
||||
#define XL95X5_ESP32H2_IO4 2
|
||||
#define XL95X5_ESP32H2_IO5 3
|
||||
|
||||
// ESP32H2
|
||||
#define ESP32H2_EN 34
|
||||
#define ESP32H2_BOOT 33
|
||||
|
||||
#include "Arduino_GFX_Library.h"
|
||||
|
||||
extern Arduino_RGB_Display *gfx;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_4inch_TPANEL
|
||||
|
||||
#define LV_ATTRIBUTE_TICK_INC IRAM_ATTR
|
||||
#define TOUCH_MODULES_CST_MUTUAL
|
||||
|
||||
// esp32-4848S040
|
||||
#define LCD_WIDTH 480
|
||||
#define LCD_HEIGHT 480
|
||||
#define LCD_VSYNC 17
|
||||
#define LCD_HSYNC 16
|
||||
#define LCD_PCLK 21
|
||||
#define LCD_R0 0
|
||||
#define LCD_R1 11
|
||||
#define LCD_R2 12
|
||||
#define LCD_R3 13
|
||||
#define LCD_R4 14
|
||||
#define LCD_G0 8
|
||||
#define LCD_G1 20
|
||||
#define LCD_G2 3
|
||||
#define LCD_G3 46
|
||||
#define LCD_G4 9
|
||||
#define LCD_G5 10
|
||||
#define LCD_B0 15
|
||||
#define LCD_B1 4
|
||||
#define LCD_B2 5
|
||||
#define LCD_B3 6
|
||||
#define LCD_B4 7
|
||||
#define LCD_BL 38
|
||||
#define LCD_DE 18
|
||||
|
||||
#define SPI_LCD_CS 39
|
||||
#define SPI_LCD_SCLK 48
|
||||
#define SPI_LCD_MOSI 47
|
||||
|
||||
#include "Arduino_GFX_Library.h"
|
||||
|
||||
extern Arduino_RGB_Display *gfx;
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_TFT
|
||||
|
||||
extern TFT_eSPI tft2;
|
||||
@@ -10,4 +142,4 @@ extern bool tftOverride;
|
||||
void TFTLog(String text);
|
||||
void sendAvail(uint8_t wakeupReason);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -26,6 +26,7 @@ const uint8_t PROGMEM gamma8[] = {
|
||||
void ledTask(void* parameter);
|
||||
void setBrightness(int brightness);
|
||||
void updateBrightnessFromConfig();
|
||||
void ledcSet(uint8_t channel, uint8_t brightness);
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
extern CRGB rgbIdleColor;
|
||||
@@ -34,7 +35,6 @@ void shortBlink(CRGB cname);
|
||||
void showColorPattern(CRGB colorone, CRGB colortwo, CRGB colorthree);
|
||||
void rgbIdle();
|
||||
void addFadeColor(CRGB cname);
|
||||
|
||||
#endif
|
||||
|
||||
void quickBlink(uint8_t repeat);
|
||||
|
||||
@@ -17,7 +17,6 @@ struct imgParam {
|
||||
bool hasRed;
|
||||
uint8_t dataType;
|
||||
uint8_t dither;
|
||||
// bool grayLut = false;
|
||||
uint8_t bufferbpp = 8;
|
||||
uint8_t rotate = 0;
|
||||
uint16_t highlightColor = 2;
|
||||
@@ -39,6 +38,8 @@ struct imgParam {
|
||||
uint8_t preloadlut;
|
||||
|
||||
uint8_t zlib;
|
||||
uint8_t g5;
|
||||
uint8_t ts_option;
|
||||
};
|
||||
|
||||
void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams);
|
||||
|
||||
@@ -26,6 +26,7 @@ extern void processDataReq(struct espAvailDataReq* adr, bool local, IPAddress re
|
||||
extern void processTagReturnData(struct espTagReturnData* trd, uint8_t len, bool local);
|
||||
|
||||
extern bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t* payload = nullptr);
|
||||
bool sendTagMac(const uint8_t* dst, const uint64_t newmac, bool local);
|
||||
extern bool sendAPSegmentedData(const uint8_t* dst, String data, uint16_t icons, bool inverted, bool local);
|
||||
extern bool showAPSegmentedInfo(const uint8_t* dst, bool local);
|
||||
extern void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP);
|
||||
|
||||
@@ -12,8 +12,8 @@ extern struct espSetChannelPower curChannel;
|
||||
#define AP_STATE_NORADIO 7
|
||||
|
||||
struct APInfoS {
|
||||
bool isOnline = false;
|
||||
uint8_t state = AP_STATE_OFFLINE;
|
||||
volatile bool isOnline = false;
|
||||
volatile uint8_t state = AP_STATE_OFFLINE;
|
||||
uint8_t type;
|
||||
uint16_t version = 0;
|
||||
uint8_t channel;
|
||||
@@ -29,6 +29,17 @@ struct APInfoS {
|
||||
|
||||
extern struct APInfoS apInfo;
|
||||
|
||||
enum ApSerialState {
|
||||
SERIAL_STATE_NONE,
|
||||
SERIAL_STATE_INITIALIZED,
|
||||
SERIAL_STATE_STARTING,
|
||||
SERIAL_STATE_RUNNING,
|
||||
SERIAL_STATE_STOP,
|
||||
SERIAL_STATE_STOPPED
|
||||
};
|
||||
|
||||
extern volatile ApSerialState gSerialTaskState;
|
||||
|
||||
void APTask(void* parameter);
|
||||
|
||||
bool sendCancelPending(struct pendingData* pending);
|
||||
@@ -38,5 +49,5 @@ void APEnterEarlyReset();
|
||||
bool sendChannelPower(struct espSetChannelPower* scp);
|
||||
void rxSerialTask2(void* parameter);
|
||||
void APTagReset();
|
||||
bool bringAPOnline();
|
||||
bool bringAPOnline(uint8_t newState = AP_STATE_ONLINE);
|
||||
void setAPstate(bool isOnline, uint8_t state);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "FS.h"
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
#ifndef SD_CARD_SDMMC
|
||||
|
||||
#ifndef SD_CARD_SS
|
||||
#error SD_CARD_SS UNDEFINED
|
||||
#endif
|
||||
@@ -18,6 +20,8 @@
|
||||
|
||||
#ifndef SD_CARD_MOSI
|
||||
#define SD_CARD_MOSI 23
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -36,7 +40,9 @@ class DynStorage {
|
||||
extern SemaphoreHandle_t fsMutex;
|
||||
extern DynStorage Storage;
|
||||
extern fs::FS *contentFS;
|
||||
#ifndef SD_CARD_ONLY
|
||||
extern void copyFile(File in, File out);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define WAKEUP_REASON_NFC 3
|
||||
#define WAKEUP_REASON_BUTTON1 4
|
||||
#define WAKEUP_REASON_BUTTON2 5
|
||||
#define WAKEUP_REASON_BUTTON3 6
|
||||
#define WAKEUP_REASON_FAILED_OTA_FW 0xE0
|
||||
#define WAKEUP_REASON_FIRSTBOOT 0xFC
|
||||
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define NO_SUBGHZ_CHANNEL 255
|
||||
class tagRecord {
|
||||
public:
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0), updateLast(0) {}
|
||||
tagRecord() : mac{0}, version(0), alias(""), lastseen(0), nextupdate(0), contentMode(0), pendingCount(0), md5{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), apIp(IPAddress(0, 0, 0, 0)), pendingIdle(0), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0), invert(0), updateCount(0), updateLast(0) {}
|
||||
|
||||
uint8_t mac[8];
|
||||
uint8_t version;
|
||||
@@ -38,7 +38,6 @@ class tagRecord {
|
||||
bool isExternal;
|
||||
IPAddress apIp;
|
||||
uint16_t pendingIdle;
|
||||
bool hasCustomLUT;
|
||||
uint8_t rotate;
|
||||
uint8_t lut;
|
||||
uint16_t tagSoftwareVersion;
|
||||
@@ -64,16 +63,19 @@ struct Config {
|
||||
uint8_t language;
|
||||
uint8_t maxsleep;
|
||||
uint8_t stopsleep;
|
||||
uint8_t runStatus;
|
||||
volatile uint8_t runStatus;
|
||||
uint8_t preview;
|
||||
uint8_t nightlyreboot;
|
||||
uint8_t lock;
|
||||
uint8_t wifiPower;
|
||||
char timeZone[52];
|
||||
uint8_t sleepTime1;
|
||||
uint8_t sleepTime2;
|
||||
uint8_t ble;
|
||||
uint8_t discovery;
|
||||
String repo;
|
||||
String env;
|
||||
uint8_t showtimestamp;
|
||||
};
|
||||
|
||||
struct Color {
|
||||
@@ -91,6 +93,7 @@ struct HwType {
|
||||
uint8_t bpp;
|
||||
uint8_t shortlut;
|
||||
uint8_t zlib;
|
||||
uint8_t g5;
|
||||
uint16_t highlightColor;
|
||||
std::vector<Color> colortable;
|
||||
};
|
||||
@@ -111,7 +114,7 @@ extern void saveDB(const String& filename);
|
||||
extern bool loadDB(const String& filename);
|
||||
extern void destroyDB();
|
||||
extern uint32_t getTagCount();
|
||||
extern uint32_t getTagCount(uint32_t& timeoutcount);
|
||||
extern uint32_t getTagCount(uint32_t& timeoutcount, uint32_t& lowbattcount);
|
||||
extern void mac2hex(const uint8_t* mac, char* hexBuffer);
|
||||
extern bool hex2mac(const String& hexString, uint8_t* mac);
|
||||
extern void clearPending(tagRecord* taginfo);
|
||||
|
||||
@@ -1,26 +1,30 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "AsyncUDP.h"
|
||||
|
||||
#include "tag_db.h"
|
||||
#ifndef defudpcomm
|
||||
#define defudpcomm
|
||||
|
||||
extern Config config;
|
||||
|
||||
class UDPcomm {
|
||||
public:
|
||||
UDPcomm();
|
||||
~UDPcomm();
|
||||
void init();
|
||||
void getAPList();
|
||||
void netProcessDataReq(struct espAvailDataReq* eadr);
|
||||
void netProcessXferComplete(struct espXferComplete* xfc);
|
||||
void netProcessXferTimeout(struct espXferComplete* xfc);
|
||||
void netSendDataAvail(struct pendingData* pending);
|
||||
void netTaginfo(struct TagInfo* taginfoitem);
|
||||
private:
|
||||
AsyncUDP udp;
|
||||
void processPacket(AsyncUDPPacket packet);
|
||||
public:
|
||||
UDPcomm();
|
||||
~UDPcomm();
|
||||
void init();
|
||||
void getAPList();
|
||||
void netProcessDataReq(struct espAvailDataReq* eadr);
|
||||
void netProcessXferComplete(struct espXferComplete* xfc);
|
||||
void netProcessXferTimeout(struct espXferComplete* xfc);
|
||||
void netSendDataAvail(struct pendingData* pending);
|
||||
void netTaginfo(struct TagInfo* taginfoitem);
|
||||
|
||||
private:
|
||||
AsyncUDP udp;
|
||||
void processPacket(AsyncUDPPacket packet);
|
||||
void writeUdpPacket(uint8_t* buffer, uint16_t len, IPAddress senderIP);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void init_udp();
|
||||
void init_udp();
|
||||
|
||||
@@ -16,7 +16,8 @@ enum WifiStatus {
|
||||
WAIT_CONNECTING,
|
||||
CONNECTED,
|
||||
WAIT_RECONNECT,
|
||||
AP
|
||||
AP,
|
||||
ETHERNET
|
||||
};
|
||||
|
||||
class WifiManager {
|
||||
@@ -41,6 +42,7 @@ class WifiManager {
|
||||
bool waitForConnection();
|
||||
void pollSerial();
|
||||
static void terminalLog(String text);
|
||||
static String buildHostname(esp_mac_type_t mac_type);
|
||||
|
||||
public:
|
||||
WifiManager();
|
||||
@@ -53,6 +55,8 @@ class WifiManager {
|
||||
void startManagementServer();
|
||||
void poll();
|
||||
static void WiFiEvent(WiFiEvent_t event);
|
||||
void initEth();
|
||||
IPAddress localIP();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
163
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.cpp
Normal file
163
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
Arduino_DataBus::Arduino_DataBus() {}
|
||||
|
||||
void Arduino_DataBus::writeC8D8(uint8_t c, uint8_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16(uint8_t c, uint16_t d)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC16D16(uint16_t c, uint16_t d)
|
||||
{
|
||||
writeCommand16(c);
|
||||
write16(d);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
write16(d1);
|
||||
write16(d2);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
|
||||
{
|
||||
writeCommand(c);
|
||||
_data16.value = d1;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
_data16.value = d2;
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand(uint8_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendCommand16(uint16_t c)
|
||||
{
|
||||
beginWrite();
|
||||
writeCommand16(c);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData(uint8_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::sendData16(uint16_t d)
|
||||
{
|
||||
beginWrite();
|
||||
write16(d);
|
||||
endWrite();
|
||||
}
|
||||
|
||||
void Arduino_DataBus::batchOperation(const uint8_t *operations, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
uint8_t l = 0;
|
||||
switch (operations[i])
|
||||
{
|
||||
case BEGIN_WRITE:
|
||||
beginWrite();
|
||||
break;
|
||||
case WRITE_C8_D16:
|
||||
writeCommand(operations[++i]);
|
||||
l = 2;
|
||||
break;
|
||||
case WRITE_C8_D8:
|
||||
writeC8D8(operations[++i], operations[++i]);
|
||||
break;
|
||||
case WRITE_COMMAND_8:
|
||||
writeCommand(operations[++i]);
|
||||
break;
|
||||
case WRITE_C16_D16:
|
||||
|
||||
break;
|
||||
case WRITE_COMMAND_16:
|
||||
|
||||
break;
|
||||
case WRITE_DATA_8:
|
||||
l = 1;
|
||||
break;
|
||||
case WRITE_DATA_16:
|
||||
l = 2;
|
||||
break;
|
||||
case WRITE_BYTES:
|
||||
l = operations[++i];
|
||||
break;
|
||||
case END_WRITE:
|
||||
endWrite();
|
||||
break;
|
||||
case DELAY:
|
||||
delay(operations[++i]);
|
||||
break;
|
||||
default:
|
||||
printf("Unknown operation id at %d: %d", i, operations[i]);
|
||||
break;
|
||||
}
|
||||
while (l--)
|
||||
{
|
||||
write(operations[++i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_DataBus::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
|
||||
{
|
||||
while (repeat--)
|
||||
{
|
||||
writeBytes(data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
write16(idx[*(data++)]);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_DataBus::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
|
||||
{
|
||||
uint8_t *d = data;
|
||||
while (len--)
|
||||
{
|
||||
_data16.value = idx[*(d++)];
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
write(_data16.msb);
|
||||
write(_data16.lsb);
|
||||
}
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_DataBus::digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
}
|
||||
|
||||
int Arduino_DataBus::digitalRead(uint8_t pin)
|
||||
{
|
||||
}
|
||||
|
||||
292
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.h
Normal file
292
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_DataBus.h
Normal file
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_DATABUS_H_
|
||||
#define _ARDUINO_DATABUS_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define GFX_SKIP_OUTPUT_BEGIN -2
|
||||
#define GFX_NOT_DEFINED -1
|
||||
#define GFX_STR_HELPER(x) #x
|
||||
#define GFX_STR(x) GFX_STR_HELPER(x)
|
||||
|
||||
#if defined(__AVR__)
|
||||
#define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(TARGET_RP2040)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ESP8266)
|
||||
#define ESP8266SAFEBATCHBITSIZE (2048 * 8 * 9)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(ARDUINO_ARCH_STM32)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(__arm__)
|
||||
#if defined(ARDUINO_ARCH_SAMD)
|
||||
// Adafruit M0, M4
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CONFIG_ARCH_CHIP_CXD56XX) // Sony Spresense
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(RTL8722DM)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#elif defined(CORE_TEENSY)
|
||||
#define USE_FAST_PINIO ///< Use direct PORT register access
|
||||
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
typedef uint32_t ARDUINOGFX_PORT_t;
|
||||
#else
|
||||
// PJRC Teensy 3.x
|
||||
typedef uint8_t ARDUINOGFX_PORT_t;
|
||||
#endif
|
||||
#else
|
||||
// Arduino Due?
|
||||
// USE_FAST_PINIO not available here (yet)...Due has a totally different
|
||||
// GPIO register set and will require some changes elsewhere (e.g. in
|
||||
// constructors especially).
|
||||
#endif
|
||||
#else // !ARM
|
||||
// Unknow architecture, USE_FAST_PINIO is not available here (yet)
|
||||
// but don't worry about it too much...the digitalWrite() implementation
|
||||
// on these platforms is reasonably efficient and already RAM-resident,
|
||||
// only gotcha then is no parallel connection support for now.
|
||||
#endif // !ARM
|
||||
|
||||
#ifdef USE_FAST_PINIO
|
||||
typedef volatile ARDUINOGFX_PORT_t *PORTreg_t;
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
|
||||
#define SPI_DEFAULT_FREQ 16000000
|
||||
// Teensy 3.0, 3.1/3.2, 3.5, 3.6
|
||||
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
// Teensy 4.x
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(__AVR__) || defined(TEENSYDUINO)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define SPI_DEFAULT_FREQ 8000000
|
||||
#elif defined(ESP8266) || defined(ESP32)
|
||||
#define SPI_DEFAULT_FREQ 40000000
|
||||
#elif defined(RTL8722DM)
|
||||
#define SPI_DEFAULT_FREQ 20000000
|
||||
#elif defined(RASPI)
|
||||
#define SPI_DEFAULT_FREQ 80000000
|
||||
#elif defined(ARDUINO_ARCH_STM32F1)
|
||||
#define SPI_DEFAULT_FREQ 36000000
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define SPI_DEFAULT_FREQ 50000000
|
||||
#elif defined(F_CPU)
|
||||
#define SPI_DEFAULT_FREQ (F_CPU / 4)
|
||||
#else
|
||||
#define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED(x) (void)(x)
|
||||
#endif
|
||||
#define ATTR_UNUSED __attribute__((unused))
|
||||
|
||||
#define MSB_16(val) (((val)&0xFF00) >> 8) | (((val)&0xFF) << 8)
|
||||
#define MSB_16_SET(var, val) \
|
||||
{ \
|
||||
(var) = MSB_16(val); \
|
||||
}
|
||||
#define MSB_32_SET(var, val) \
|
||||
{ \
|
||||
uint8_t *v = (uint8_t *)&(val); \
|
||||
(var) = v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24); \
|
||||
}
|
||||
#define MSB_32_16_16_SET(var, v1, v2) \
|
||||
{ \
|
||||
(var) = (((uint32_t)v2 & 0xff00) << 8) | (((uint32_t)v2 & 0xff) << 24) | ((v1 & 0xff00) >> 8) | ((v1 & 0xff) << 8); \
|
||||
}
|
||||
#define MSB_32_8_ARRAY_SET(var, a) \
|
||||
{ \
|
||||
(var) = ((uint32_t)a[0] << 8 | a[1] | a[2] << 24 | a[3] << 16); \
|
||||
}
|
||||
|
||||
#if defined(ESP32)
|
||||
#define INLINE __attribute__((always_inline)) inline
|
||||
#else
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#include <esp_lcd_panel_io.h>
|
||||
#include <esp_lcd_panel_io_interface.h>
|
||||
#include <esp_pm.h>
|
||||
#include <esp_private/gdma.h>
|
||||
#include <hal/dma_types.h>
|
||||
#include <hal/lcd_hal.h>
|
||||
#include <soc/dport_reg.h>
|
||||
#include <soc/gpio_sig_map.h>
|
||||
#include <soc/lcd_cam_reg.h>
|
||||
#include <soc/lcd_cam_struct.h>
|
||||
|
||||
typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
|
||||
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
|
||||
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
|
||||
|
||||
struct esp_lcd_i80_bus_t
|
||||
{
|
||||
int bus_id; // Bus ID, index from 0
|
||||
portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
|
||||
lcd_hal_context_t hal; // Hal object
|
||||
size_t bus_width; // Number of data lines
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors
|
||||
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
|
||||
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM
|
||||
size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM
|
||||
lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
|
||||
lcd_panel_io_i80_t *cur_device; // Current working device
|
||||
LIST_HEAD(i80_device_list, lcd_panel_io_i80_t)
|
||||
device_list; // Head of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int exclusive : 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices
|
||||
};
|
||||
|
||||
struct lcd_i80_trans_descriptor_t
|
||||
{
|
||||
lcd_panel_io_i80_t *i80_device; // i80 device issuing this transaction
|
||||
int cmd_value; // Command value
|
||||
uint32_t cmd_cycles; // Command cycles
|
||||
const void *data; // Data buffer
|
||||
uint32_t data_length; // Data buffer size
|
||||
void *user_ctx; // private data used by trans_done_cb
|
||||
esp_lcd_panel_io_color_trans_done_cb_t trans_done_cb; // transaction done callback
|
||||
};
|
||||
|
||||
struct lcd_panel_io_i80_t
|
||||
{
|
||||
esp_lcd_panel_io_t base; // Base class of generic lcd panel io
|
||||
esp_lcd_i80_bus_t *bus; // Which bus the device is attached to
|
||||
int cs_gpio_num; // GPIO used for CS line
|
||||
unsigned int pclk_hz; // PCLK clock frequency
|
||||
size_t clock_prescale; // Prescaler coefficient, determined by user's configured PCLK frequency
|
||||
QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch
|
||||
QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller
|
||||
size_t queue_size; // Size of transaction queue
|
||||
size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet)
|
||||
int lcd_cmd_bits; // Bit width of LCD command
|
||||
int lcd_param_bits; // Bit width of LCD parameter
|
||||
void *user_ctx; // private data used when transfer color data
|
||||
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // color data trans done callback
|
||||
LIST_ENTRY(lcd_panel_io_i80_t)
|
||||
device_list_entry; // Entry of i80 device list
|
||||
struct
|
||||
{
|
||||
unsigned int dc_idle_level : 1; // Level of DC line in IDLE phase
|
||||
unsigned int dc_cmd_level : 1; // Level of DC line in CMD phase
|
||||
unsigned int dc_dummy_level : 1; // Level of DC line in DUMMY phase
|
||||
unsigned int dc_data_level : 1; // Level of DC line in DATA phase
|
||||
} dc_levels;
|
||||
struct
|
||||
{
|
||||
unsigned int cs_active_high : 1; // Whether the CS line is active on high level
|
||||
unsigned int reverse_color_bits : 1; // Reverse the data bits, D[N:0] -> D[0:N]
|
||||
unsigned int swap_color_bytes : 1; // Swap adjacent two data bytes before sending out
|
||||
unsigned int pclk_active_neg : 1; // The display will write data lines when there's a falling edge on WR line
|
||||
unsigned int pclk_idle_low : 1; // The WR line keeps at low level in IDLE phase
|
||||
} flags;
|
||||
lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool
|
||||
};
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8,
|
||||
WRITE_COMMAND_16,
|
||||
WRITE_DATA_8,
|
||||
WRITE_DATA_16,
|
||||
WRITE_BYTES,
|
||||
WRITE_C8_D8,
|
||||
WRITE_C8_D16,
|
||||
WRITE_C16_D16,
|
||||
END_WRITE,
|
||||
DELAY,
|
||||
} spi_operation_type_t;
|
||||
|
||||
union
|
||||
{
|
||||
uint16_t value;
|
||||
struct
|
||||
{
|
||||
uint8_t lsb;
|
||||
uint8_t msb;
|
||||
};
|
||||
} _data16;
|
||||
|
||||
class Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_DataBus();
|
||||
|
||||
void unused() { UNUSED(_data16); } // avoid compiler warning
|
||||
|
||||
virtual bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) = 0;
|
||||
virtual void beginWrite() = 0;
|
||||
virtual void endWrite() = 0;
|
||||
virtual void writeCommand(uint8_t c) = 0;
|
||||
virtual void writeCommand16(uint16_t c) = 0;
|
||||
virtual void write(uint8_t) = 0;
|
||||
virtual void write16(uint16_t) = 0;
|
||||
virtual void writeC8D8(uint8_t c, uint8_t d);
|
||||
virtual void writeC16D16(uint16_t c, uint16_t d);
|
||||
virtual void writeC8D16(uint8_t c, uint16_t d);
|
||||
virtual void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2);
|
||||
virtual void writeRepeat(uint16_t p, uint32_t len) = 0;
|
||||
virtual void writePixels(uint16_t *data, uint32_t len) = 0;
|
||||
|
||||
void sendCommand(uint8_t c);
|
||||
void sendCommand16(uint16_t c);
|
||||
void sendData(uint8_t d);
|
||||
void sendData16(uint16_t d);
|
||||
|
||||
void batchOperation(const uint8_t *operations, size_t len);
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writeBytes(uint8_t *data, uint32_t len) = 0;
|
||||
virtual void writePattern(uint8_t *data, uint8_t len, uint32_t repeat);
|
||||
virtual void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
virtual void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
virtual void digitalWrite(uint8_t pin, uint8_t val);
|
||||
virtual int digitalRead(uint8_t pin);
|
||||
|
||||
protected:
|
||||
int32_t _speed;
|
||||
int8_t _dataMode;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_DATABUS_H_
|
||||
279
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.cpp
Normal file
279
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#include "Arduino_G.h"
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Instatiate a GFX context for graphics! Can only be done by a superclass
|
||||
@param w Display width, in pixels
|
||||
@param h Display height, in pixels
|
||||
*/
|
||||
/**************************************************************************/
|
||||
Arduino_G::Arduino_G(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h)
|
||||
{
|
||||
}
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += y * framebuffer_w; // shift framebuffer to y offset
|
||||
row += x; // shift framebuffer to x offset
|
||||
if (((framebuffer_w & 1) == 0) && ((xskip & 1) == 0) && ((bitmap_w & 1) == 0))
|
||||
{
|
||||
uint32_t *row2 = (uint32_t *)row;
|
||||
uint32_t *from_bitmap2 = (uint32_t *)from_bitmap;
|
||||
int16_t framebuffer_w2 = framebuffer_w >> 1;
|
||||
int16_t xskip2 = xskip >> 1;
|
||||
int16_t w2 = bitmap_w >> 1;
|
||||
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int16_t i = 0; i < w2; ++i)
|
||||
{
|
||||
row2[i] = *from_bitmap2++;
|
||||
}
|
||||
from_bitmap2 += xskip2;
|
||||
row2 += framebuffer_w2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
for (int i = 0; i < bitmap_w; ++i)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
row += framebuffer_w;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += (x * framebuffer_h); // shift framebuffer to y offset
|
||||
p += (framebuffer_h - y - j); // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p += framebuffer_h;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *row = framebuffer;
|
||||
row += (max_Y - y) * framebuffer_w; // shift framebuffer to y offset
|
||||
row += framebuffer_w - x - bitmap_w; // shift framebuffer to x offset
|
||||
int16_t i;
|
||||
int16_t j = bitmap_h;
|
||||
while (j--)
|
||||
{
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
row[i] = *from_bitmap++;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
row -= framebuffer_w;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
|
||||
{
|
||||
int16_t max_X = framebuffer_w - 1;
|
||||
int16_t max_Y = framebuffer_h - 1;
|
||||
if (
|
||||
((x + bitmap_w - 1) < 0) || // Outside left
|
||||
((y + bitmap_h - 1) < 0) || // Outside top
|
||||
(x > max_X) || // Outside right
|
||||
(y > max_Y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + bitmap_h - 1) > max_Y)
|
||||
{
|
||||
bitmap_h -= (y + bitmap_h - 1) - max_Y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
from_bitmap -= y * bitmap_w;
|
||||
bitmap_h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + bitmap_w - 1) > max_X)
|
||||
{
|
||||
xskip = (x + bitmap_w - 1) - max_X;
|
||||
bitmap_w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
from_bitmap -= x;
|
||||
xskip -= x;
|
||||
bitmap_w += x;
|
||||
x = 0;
|
||||
}
|
||||
|
||||
uint16_t *p;
|
||||
int16_t i;
|
||||
for (int16_t j = 0; j < bitmap_h; j++)
|
||||
{
|
||||
p = framebuffer;
|
||||
p += ((max_X - x) * framebuffer_h); // shift framebuffer to y offset
|
||||
p += y + j; // shift framebuffer to x offset
|
||||
|
||||
i = bitmap_w;
|
||||
while (i--)
|
||||
{
|
||||
*p = *from_bitmap++;
|
||||
p -= framebuffer_h;
|
||||
}
|
||||
from_bitmap += xskip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
50
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.h
Normal file
50
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_G.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
#ifndef _ARDUINO_G_H_
|
||||
#define _ARDUINO_G_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
class Arduino_G
|
||||
{
|
||||
public:
|
||||
Arduino_G(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) = 0;
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) = 0;
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
|
||||
|
||||
protected:
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_G_H_
|
||||
|
||||
// utility functions
|
||||
bool gfx_draw_bitmap_to_framebuffer(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
|
||||
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
|
||||
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
|
||||
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
2898
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.cpp
Normal file
2898
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.cpp
Normal file
File diff suppressed because it is too large
Load Diff
447
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.h
Normal file
447
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/Arduino_GFX.h
Normal file
@@ -0,0 +1,447 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_GFX_H_
|
||||
#define _ARDUINO_GFX_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Print.h>
|
||||
#include "Arduino_G.h"
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
#include "gfxfont.h"
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#ifndef DEGTORAD
|
||||
#define DEGTORAD 0.017453292519943295769236907684886F
|
||||
#endif
|
||||
|
||||
|
||||
#define RGB565(r, g, b) ((((r)&0xF8) << 8) | (((g)&0xFC) << 3) | ((b) >> 3))
|
||||
#define RGB16TO24(c) ((((uint32_t)c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x1F) << 3))
|
||||
|
||||
#define RGB565_BLACK RGB565(0, 0, 0)
|
||||
#define RGB565_NAVY RGB565(0, 0, 123)
|
||||
#define RGB565_DARKGREEN RGB565(0, 125, 0)
|
||||
#define RGB565_DARKCYAN RGB565(0, 125, 123)
|
||||
#define RGB565_MAROON RGB565(123, 0, 0)
|
||||
#define RGB565_PURPLE RGB565(123, 0, 123)
|
||||
#define RGB565_OLIVE RGB565(123, 125, 0)
|
||||
#define RGB565_LIGHTGREY RGB565(198, 195, 198)
|
||||
#define RGB565_DARKGREY RGB565(123, 125, 123)
|
||||
#define RGB565_BLUE RGB565(0, 0, 255)
|
||||
#define RGB565_GREEN RGB565(0, 255, 0)
|
||||
#define RGB565_CYAN RGB565(0, 255, 255)
|
||||
#define RGB565_RED RGB565(255, 0, 0)
|
||||
#define RGB565_MAGENTA RGB565(255, 0, 255)
|
||||
#define RGB565_YELLOW RGB565(255, 255, 0)
|
||||
#define RGB565_WHITE RGB565(255, 255, 255)
|
||||
#define RGB565_ORANGE RGB565(255, 165, 0)
|
||||
#define RGB565_GREENYELLOW RGB565(173, 255, 41)
|
||||
#define RGB565_PINK RGB565(255, 130, 198)
|
||||
|
||||
// Color definitions
|
||||
#ifndef DISABLE_COLOR_DEFINES
|
||||
#define BLACK RGB565_BLACK
|
||||
#define NAVY RGB565_NAVY
|
||||
#define DARKGREEN RGB565_DARKGREEN
|
||||
#define DARKCYAN RGB565_DARKCYAN
|
||||
#define MAROON RGB565_MAROON
|
||||
#define PURPLE RGB565_PURPLE
|
||||
#define OLIVE RGB565_OLIVE
|
||||
#define LIGHTGREY RGB565_LIGHTGREY
|
||||
#define DARKGREY RGB565_DARKGREY
|
||||
#define BLUE RGB565_BLUE
|
||||
#define GREEN RGB565_GREEN
|
||||
#define CYAN RGB565_CYAN
|
||||
#define RED RGB565_RED
|
||||
#define MAGENTA RGB565_MAGENTA
|
||||
#define YELLOW RGB565_YELLOW
|
||||
#define WHITE RGB565_WHITE
|
||||
#define ORANGE RGB565_ORANGE
|
||||
#define GREENYELLOW RGB565_GREENYELLOW
|
||||
#define PINK RGB565_PINK
|
||||
#endif
|
||||
|
||||
// Many (but maybe not all) non-AVR board installs define macros
|
||||
// for compatibility with existing PROGMEM-reading AVR code.
|
||||
// Do our own checks and defines here for good measure...
|
||||
|
||||
#ifndef pgm_read_byte
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
#ifndef pgm_read_dword
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#endif
|
||||
// workaround of a15 asm compile error
|
||||
#ifdef ESP8266
|
||||
#undef pgm_read_word
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#endif
|
||||
|
||||
// Pointers are a peculiar case...typically 16-bit on AVR boards,
|
||||
// 32 bits elsewhere. Try to accommodate both...
|
||||
|
||||
#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr))
|
||||
#else
|
||||
#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
|
||||
#endif
|
||||
|
||||
#ifndef _swap_uint8_t
|
||||
#define _swap_uint8_t(a, b) \
|
||||
{ \
|
||||
uint8_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) \
|
||||
{ \
|
||||
int16_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _diff
|
||||
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
|
||||
#endif
|
||||
|
||||
#ifndef _ordered_in_range
|
||||
#define _ordered_in_range(v, a, b) ((a <= v) && (v <= b))
|
||||
#endif
|
||||
|
||||
#ifndef _in_range
|
||||
#define _in_range(v, a, b) ((a > b) ? _ordered_in_range(v, b, a) : _ordered_in_range(v, a, b))
|
||||
#endif
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
INLINE GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
|
||||
#else
|
||||
// expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->glyph + c;
|
||||
#endif //__AVR__
|
||||
}
|
||||
|
||||
INLINE uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont)
|
||||
{
|
||||
#ifdef __AVR__
|
||||
return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
|
||||
#else
|
||||
// expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning
|
||||
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
|
||||
// So expression may be simplified
|
||||
return gfxFont->bitmap;
|
||||
#endif //__AVR__
|
||||
}
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
class Arduino_GFX : public Print
|
||||
#else
|
||||
class Arduino_GFX : public Print, public Arduino_G
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
{
|
||||
public:
|
||||
Arduino_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
|
||||
virtual void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// TRANSACTION API / CORE DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void startWrite();
|
||||
virtual void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void endWrite(void);
|
||||
|
||||
// CONTROL API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void setRotation(uint8_t r);
|
||||
virtual void invertDisplay(bool i);
|
||||
virtual void displayOn();
|
||||
virtual void displayOff();
|
||||
|
||||
// BASIC DRAW API
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
// It's good to implement those, even if using transaction API
|
||||
void writePixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawPixel(int16_t x, int16_t y, uint16_t color);
|
||||
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void fillScreen(uint16_t color);
|
||||
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
|
||||
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
|
||||
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
|
||||
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
|
||||
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
|
||||
void setTextSize(uint8_t s);
|
||||
void setTextSize(uint8_t sx, uint8_t sy);
|
||||
void setTextSize(uint8_t sx, uint8_t sy, uint8_t pixel_margin);
|
||||
|
||||
#if !defined(ATTINY_CORE)
|
||||
void setFont(const GFXfont *f = NULL);
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
void setFont(const uint8_t *font);
|
||||
void setUTF8Print(bool isEnable);
|
||||
uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset);
|
||||
uint8_t u8g2_font_decode_get_unsigned_bits(uint8_t cnt);
|
||||
int8_t u8g2_font_decode_get_signed_bits(uint8_t cnt);
|
||||
void u8g2_font_decode_len(uint8_t len, uint8_t is_foreground, uint16_t color, uint16_t bg);
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
virtual void flush(void);
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
// adopt from LovyanGFX
|
||||
void drawEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void drawEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, uint16_t color);
|
||||
void fillEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
|
||||
void fillEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, int16_t delta, uint16_t color);
|
||||
void drawArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void fillArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
|
||||
void fillArcHelper(int16_t cx, int16_t cy, int16_t oradius, int16_t iradius, float start, float end, uint16_t color);
|
||||
|
||||
// TFT optimization code, too big for ATMEL family
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
#else // !defined(LITTLE_FOOT_PRINT)
|
||||
virtual void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
|
||||
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
|
||||
virtual void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
|
||||
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
|
||||
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text cursor location
|
||||
@param x X coordinate in pixels
|
||||
@param y Y coordinate in pixels
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setCursor(int16_t x, int16_t y)
|
||||
{
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with transparant background
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@note For 'transparent' background, background and foreground
|
||||
are set to same color rather than using a separate flag.
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c) { textcolor = textbgcolor = c; }
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set text font color with custom background color
|
||||
@param c 16-bit 5-6-5 Color to draw text with
|
||||
@param bg 16-bit 5-6-5 Color to draw background/fill with
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextColor(uint16_t c, uint16_t bg)
|
||||
{
|
||||
textcolor = c;
|
||||
textbgcolor = bg;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/*!
|
||||
@brief Set whether text that is too long for the screen width should
|
||||
automatically wrap around to the next line (else clip right).
|
||||
@param w true for wrapping, false for clipping
|
||||
*/
|
||||
/**********************************************************************/
|
||||
void setTextWrap(bool w) { wrap = w; }
|
||||
|
||||
virtual size_t write(uint8_t);
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get width of the display, accounting for current rotation
|
||||
@returns Width in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t width(void) const { return _width; };
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get height of the display, accounting for current rotation
|
||||
@returns Height in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t height(void) const { return _height; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get rotation setting for display
|
||||
@returns 0 thru 3 corresponding to 4 cardinal rotations
|
||||
*/
|
||||
/************************************************************************/
|
||||
uint8_t getRotation(void) const { return _rotation; }
|
||||
|
||||
// get current cursor position (get rotation safe maximum values,
|
||||
// using: width() for x, height() for y)
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor X location
|
||||
@returns X coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorX(void) const { return cursor_x; }
|
||||
|
||||
/************************************************************************/
|
||||
/*!
|
||||
@brief Get text cursor Y location
|
||||
@returns Y coordinate in pixels
|
||||
*/
|
||||
/************************************************************************/
|
||||
int16_t getCursorY(void) const { return cursor_y; };
|
||||
|
||||
/*!
|
||||
@brief Given 8-bit red, green and blue values, return a 'packed'
|
||||
16-bit color value in '565' RGB format (5 bits red, 6 bits
|
||||
green, 5 bits blue). This is just a mathematical operation,
|
||||
no hardware is touched.
|
||||
@param red 8-bit red brightnesss (0 = off, 255 = max).
|
||||
@param green 8-bit green brightnesss (0 = off, 255 = max).
|
||||
@param blue 8-bit blue brightnesss (0 = off, 255 = max).
|
||||
@return 'Packed' 16-bit color value (565 format).
|
||||
*/
|
||||
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue)
|
||||
{
|
||||
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
|
||||
}
|
||||
|
||||
protected:
|
||||
void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
|
||||
int16_t
|
||||
_width, ///< Display width as modified by current rotation
|
||||
_height, ///< Display height as modified by current rotation
|
||||
_max_x, ///< x zero base bound (_width - 1)
|
||||
_max_y, ///< y zero base bound (_height - 1)
|
||||
cursor_x, ///< x location to start print()ing text
|
||||
cursor_y; ///< y location to start print()ing text
|
||||
uint16_t
|
||||
textcolor, ///< 16-bit background color for print()
|
||||
textbgcolor; ///< 16-bit text color for print()
|
||||
uint8_t
|
||||
textsize_x, ///< Desired magnification in X-axis of text to print()
|
||||
textsize_y, ///< Desired magnification in Y-axis of text to print()
|
||||
text_pixel_margin, ///< Margin for each text pixel
|
||||
_rotation; ///< Display rotation (0 thru 3)
|
||||
bool
|
||||
wrap; ///< If set, 'wrap' text at right edge of display
|
||||
#if !defined(ATTINY_CORE)
|
||||
GFXfont *gfxFont; ///< Pointer to special font
|
||||
#endif // !defined(ATTINY_CORE)
|
||||
|
||||
#if defined(U8G2_FONT_SUPPORT)
|
||||
uint8_t *u8g2Font;
|
||||
bool _enableUTF8Print = false;
|
||||
uint8_t _utf8_state = 0;
|
||||
uint16_t _encoding;
|
||||
|
||||
uint8_t _u8g2_glyph_cnt;
|
||||
uint8_t _u8g2_bits_per_0;
|
||||
uint8_t _u8g2_bits_per_1;
|
||||
uint8_t _u8g2_bits_per_char_width;
|
||||
uint8_t _u8g2_bits_per_char_height;
|
||||
uint8_t _u8g2_bits_per_char_x;
|
||||
uint8_t _u8g2_bits_per_char_y;
|
||||
uint8_t _u8g2_bits_per_delta_x;
|
||||
int8_t _u8g2_max_char_width;
|
||||
int8_t _u8g2_max_char_height;
|
||||
uint16_t _u8g2_start_pos_upper_A;
|
||||
uint16_t _u8g2_start_pos_lower_a;
|
||||
uint16_t _u8g2_start_pos_unicode;
|
||||
uint8_t _u8g2_first_char;
|
||||
|
||||
uint8_t _u8g2_char_width;
|
||||
uint8_t _u8g2_char_height;
|
||||
int8_t _u8g2_char_x;
|
||||
int8_t _u8g2_char_y;
|
||||
int8_t _u8g2_delta_x;
|
||||
|
||||
int8_t _u8g2_dx;
|
||||
int8_t _u8g2_dy;
|
||||
uint16_t _u8g2_target_x;
|
||||
uint16_t _u8g2_target_y;
|
||||
|
||||
const uint8_t *_u8g2_decode_ptr;
|
||||
uint8_t _u8g2_decode_bit_pos;
|
||||
#endif // defined(U8G2_FONT_SUPPORT)
|
||||
|
||||
#if defined(LITTLE_FOOT_PRINT)
|
||||
int16_t
|
||||
WIDTH, ///< This is the 'raw' display width - never changes
|
||||
HEIGHT; ///< This is the 'raw' display height - never changes
|
||||
#endif // defined(LITTLE_FOOT_PRINT)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_GFX_H_
|
||||
@@ -0,0 +1,209 @@
|
||||
#ifndef _ARDUINO_GFX_LIBRARIES_H_
|
||||
#define _ARDUINO_GFX_LIBRARIES_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
#include "databus/Arduino_ESP32RGBPanel.h"
|
||||
#include "databus/Arduino_SWSPI.h"
|
||||
#include "databus/Arduino_XL9535SWSPI.h"
|
||||
|
||||
#include "Arduino_GFX.h" // Core graphics library
|
||||
|
||||
#include "display/Arduino_RGB_Display.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WIO_TERMINAL
|
||||
#define DF_GFX_CS LCD_SS_PIN
|
||||
#define DF_GFX_DC LCD_DC
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL LCD_BACKLIGHT
|
||||
#elif defined(ARDUINO_ESP32_S3_BOX)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ESP32_S3_BOX
|
||||
#define DF_GFX_SCK TFT_CLK
|
||||
#define DF_GFX_MOSI TFT_MOSI
|
||||
#define DF_GFX_MISO TFT_MISO
|
||||
#define DF_GFX_CS TFT_CS
|
||||
#define DF_GFX_DC TFT_DC
|
||||
#define DF_GFX_RST TFT_RST
|
||||
#define DF_GFX_BL TFT_BL
|
||||
#elif defined(ARDUINO_M5Stack_Core_ESP32) || defined(ARDUINO_M5STACK_FIRE)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_CORE
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 14
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 32
|
||||
#elif defined(ARDUINO_M5Stack_ATOMS3)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define M5STACK_ATOMS3
|
||||
#define DF_GFX_SCK 17
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 33
|
||||
#define DF_GFX_RST 34
|
||||
#define DF_GFX_BL 16
|
||||
#elif defined(ARDUINO_ODROID_ESP32)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define ODROID_GO
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO 19
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 21
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 14
|
||||
/* TTGO T-Watch */
|
||||
#elif defined(ARDUINO_T) || defined(ARDUINO_TWATCH_BASE) || defined(ARDUINO_TWATCH_2020_V1) || defined(ARDUINO_TWATCH_2020_V2)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define TTGO_T_WATCH
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST GFX_NOT_DEFINED
|
||||
#define DF_GFX_BL 12
|
||||
/* Waveshare RP2040-LCD-1.28 */
|
||||
#elif defined(ARDUINO_WAVESHARE_RP2040_LCD_1_28)
|
||||
#define DISPLAY_DEV_KIT
|
||||
#define WAVESHARE_RP2040_LCD_1_28
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 12
|
||||
#define DF_GFX_BL 25
|
||||
#define DF_GFX_SPI spi1
|
||||
#elif defined(ARDUINO_ARCH_NRF52840)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PJRC Teensy 4.x
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 39 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 40
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ARDUINO_BLACKPILL_F411CE)
|
||||
#define DF_GFX_SCK 5
|
||||
#define DF_GFX_MOSI 7
|
||||
#define DF_GFX_MISO 6
|
||||
#define DF_GFX_CS 4
|
||||
#define DF_GFX_DC 3
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 1
|
||||
#elif defined(TARGET_RP2040)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 19
|
||||
#define DF_GFX_MISO 16
|
||||
#define DF_GFX_CS 17
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 26
|
||||
#define DF_GFX_BL 28
|
||||
#define DF_GFX_SPI spi0
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32)
|
||||
#define DF_GFX_SCK 18
|
||||
#define DF_GFX_MOSI 23
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 5
|
||||
#define DF_GFX_DC 27
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 22
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 34
|
||||
#define DF_GFX_DC 38
|
||||
#define DF_GFX_RST 33
|
||||
#define DF_GFX_BL 21
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
#define DF_GFX_SCK 36
|
||||
#define DF_GFX_MOSI 35
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 40
|
||||
#define DF_GFX_DC 41
|
||||
#define DF_GFX_RST 42
|
||||
#define DF_GFX_BL 48
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define DF_GFX_SCK 4
|
||||
#define DF_GFX_MOSI 6
|
||||
#define DF_GFX_MISO GFX_NOT_DEFINED
|
||||
#define DF_GFX_CS 7
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(ESP8266)
|
||||
#define DF_GFX_SCK 14
|
||||
#define DF_GFX_MOSI 13
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 15
|
||||
#define DF_GFX_DC 4
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 5
|
||||
#elif defined(RTL8722DM)
|
||||
#if defined(BOARD_RTL8720DN_BW16)
|
||||
#define DF_GFX_SCK 10
|
||||
#define DF_GFX_MOSI 12
|
||||
#define DF_GFX_MISO 11
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 6
|
||||
#define DF_GFX_BL 3
|
||||
#elif defined(BOARD_RTL8722DM)
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 18
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 22
|
||||
#define DF_GFX_BL 23
|
||||
#elif defined(BOARD_RTL8722DM_MINI)
|
||||
#define DF_GFX_SCK 11
|
||||
#define DF_GFX_MOSI 9
|
||||
#define DF_GFX_MISO 10
|
||||
#define DF_GFX_CS 12
|
||||
#define DF_GFX_DC 14
|
||||
#define DF_GFX_RST 15
|
||||
#define DF_GFX_BL 13
|
||||
#else // old version
|
||||
#define DF_GFX_SCK 19
|
||||
#define DF_GFX_MOSI 21
|
||||
#define DF_GFX_MISO 20
|
||||
#define DF_GFX_CS 18 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 17
|
||||
#define DF_GFX_RST 2
|
||||
#define DF_GFX_BL 23
|
||||
#endif
|
||||
#elif defined(SEEED_XIAO_M0)
|
||||
#define DF_GFX_SCK 8
|
||||
#define DF_GFX_MOSI 10
|
||||
#define DF_GFX_MISO 9
|
||||
#define DF_GFX_CS 3 // GFX_NOT_DEFINED for display without CS pin
|
||||
#define DF_GFX_DC 2
|
||||
#define DF_GFX_RST 1
|
||||
#define DF_GFX_BL 0
|
||||
#else // default pins for Arduino Nano, Mini, Micro and more
|
||||
#define DF_GFX_SCK 13
|
||||
#define DF_GFX_MOSI 11
|
||||
#define DF_GFX_MISO 12
|
||||
#define DF_GFX_CS 9
|
||||
#define DF_GFX_DC 8
|
||||
#define DF_GFX_RST 7
|
||||
#define DF_GFX_BL 6
|
||||
#endif
|
||||
|
||||
#endif // _ARDUINO_GFX_LIBRARIES_H_
|
||||
@@ -0,0 +1,129 @@
|
||||
#include "Arduino_ESP32RGBPanel.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
Arduino_ESP32RGBPanel::Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg, int32_t prefer_speed, bool useBigEndian,
|
||||
uint16_t de_idle_high, uint16_t pclk_idle_high)
|
||||
: _de(de), _vsync(vsync), _hsync(hsync), _pclk(pclk),
|
||||
_r0(r0), _r1(r1), _r2(r2), _r3(r3), _r4(r4),
|
||||
_g0(g0), _g1(g1), _g2(g2), _g3(g3), _g4(g4), _g5(g5),
|
||||
_b0(b0), _b1(b1), _b2(b2), _b3(b3), _b4(b4),
|
||||
_hsync_polarity(hsync_polarity), _hsync_front_porch(hsync_front_porch), _hsync_pulse_width(hsync_pulse_width), _hsync_back_porch(hsync_back_porch),
|
||||
_vsync_polarity(vsync_polarity), _vsync_front_porch(vsync_front_porch), _vsync_pulse_width(vsync_pulse_width), _vsync_back_porch(vsync_back_porch),
|
||||
_pclk_active_neg(pclk_active_neg), _prefer_speed(prefer_speed), _useBigEndian(useBigEndian),
|
||||
_de_idle_high(de_idle_high), _pclk_idle_high(pclk_idle_high)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_ESP32RGBPanel::begin(int32_t speed)
|
||||
{
|
||||
if (speed == GFX_NOT_DEFINED)
|
||||
{
|
||||
#ifdef CONFIG_SPIRAM_MODE_QUAD
|
||||
_speed = 6000000L;
|
||||
#else
|
||||
_speed = 12000000L;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
_speed = speed;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16_t *Arduino_ESP32RGBPanel::getFrameBuffer(int16_t w, int16_t h)
|
||||
{
|
||||
esp_lcd_rgb_panel_config_t *_panel_config = (esp_lcd_rgb_panel_config_t *)heap_caps_calloc(1, sizeof(esp_lcd_rgb_panel_config_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
|
||||
_panel_config->clk_src = LCD_CLK_SRC_PLL160M;
|
||||
|
||||
_panel_config->timings.pclk_hz = (_prefer_speed == GFX_NOT_DEFINED) ? _speed : _prefer_speed;
|
||||
_panel_config->timings.h_res = w;
|
||||
_panel_config->timings.v_res = h;
|
||||
// The following parameters should refer to LCD spec
|
||||
_panel_config->timings.hsync_pulse_width = _hsync_pulse_width;
|
||||
_panel_config->timings.hsync_back_porch = _hsync_back_porch;
|
||||
_panel_config->timings.hsync_front_porch = _hsync_front_porch;
|
||||
_panel_config->timings.vsync_pulse_width = _vsync_pulse_width;
|
||||
_panel_config->timings.vsync_back_porch = _vsync_back_porch;
|
||||
_panel_config->timings.vsync_front_porch = _vsync_front_porch;
|
||||
_panel_config->timings.flags.hsync_idle_low = (_hsync_polarity == 0) ? 1 : 0;
|
||||
_panel_config->timings.flags.vsync_idle_low = (_vsync_polarity == 0) ? 1 : 0;
|
||||
_panel_config->timings.flags.de_idle_high = _de_idle_high;
|
||||
_panel_config->timings.flags.pclk_active_neg = _pclk_active_neg;
|
||||
_panel_config->timings.flags.pclk_idle_high = _pclk_idle_high;
|
||||
|
||||
_panel_config->data_width = 16; // RGB565 in parallel mode, thus 16bit in width
|
||||
_panel_config->sram_trans_align = 8;
|
||||
_panel_config->psram_trans_align = 64;
|
||||
_panel_config->hsync_gpio_num = _hsync;
|
||||
_panel_config->vsync_gpio_num = _vsync;
|
||||
_panel_config->de_gpio_num = _de;
|
||||
_panel_config->pclk_gpio_num = _pclk;
|
||||
|
||||
if (_useBigEndian)
|
||||
{
|
||||
_panel_config->data_gpio_nums[0] = _g3;
|
||||
_panel_config->data_gpio_nums[1] = _g4;
|
||||
_panel_config->data_gpio_nums[2] = _g5;
|
||||
_panel_config->data_gpio_nums[3] = _r0;
|
||||
_panel_config->data_gpio_nums[4] = _r1;
|
||||
_panel_config->data_gpio_nums[5] = _r2;
|
||||
_panel_config->data_gpio_nums[6] = _r3;
|
||||
_panel_config->data_gpio_nums[7] = _r4;
|
||||
_panel_config->data_gpio_nums[8] = _b0;
|
||||
_panel_config->data_gpio_nums[9] = _b1;
|
||||
_panel_config->data_gpio_nums[10] = _b2;
|
||||
_panel_config->data_gpio_nums[11] = _b3;
|
||||
_panel_config->data_gpio_nums[12] = _b4;
|
||||
_panel_config->data_gpio_nums[13] = _g0;
|
||||
_panel_config->data_gpio_nums[14] = _g1;
|
||||
_panel_config->data_gpio_nums[15] = _g2;
|
||||
}
|
||||
else
|
||||
{
|
||||
_panel_config->data_gpio_nums[0] = _b0;
|
||||
_panel_config->data_gpio_nums[1] = _b1;
|
||||
_panel_config->data_gpio_nums[2] = _b2;
|
||||
_panel_config->data_gpio_nums[3] = _b3;
|
||||
_panel_config->data_gpio_nums[4] = _b4;
|
||||
_panel_config->data_gpio_nums[5] = _g0;
|
||||
_panel_config->data_gpio_nums[6] = _g1;
|
||||
_panel_config->data_gpio_nums[7] = _g2;
|
||||
_panel_config->data_gpio_nums[8] = _g3;
|
||||
_panel_config->data_gpio_nums[9] = _g4;
|
||||
_panel_config->data_gpio_nums[10] = _g5;
|
||||
_panel_config->data_gpio_nums[11] = _r0;
|
||||
_panel_config->data_gpio_nums[12] = _r1;
|
||||
_panel_config->data_gpio_nums[13] = _r2;
|
||||
_panel_config->data_gpio_nums[14] = _r3;
|
||||
_panel_config->data_gpio_nums[15] = _r4;
|
||||
}
|
||||
|
||||
_panel_config->disp_gpio_num = GPIO_NUM_NC;
|
||||
|
||||
_panel_config->flags.disp_active_low = 0;
|
||||
_panel_config->flags.relax_on_idle = 0;
|
||||
_panel_config->flags.fb_in_psram = 1; // allocate frame buffer in PSRAM
|
||||
|
||||
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(_panel_config, &_panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_reset(_panel_handle));
|
||||
ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle));
|
||||
|
||||
uint16_t color = random(0xffff);
|
||||
ESP_ERROR_CHECK(_panel_handle->draw_bitmap(_panel_handle, 0, 0, 1, 1, &color));
|
||||
|
||||
_rgb_panel = __containerof(_panel_handle, esp_rgb_panel_t, base);
|
||||
|
||||
return (uint16_t *)_rgb_panel->fb;
|
||||
}
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,100 @@
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_ESP32RGBPANEL_H_
|
||||
#define _ARDUINO_ESP32RGBPANEL_H_
|
||||
|
||||
#include "esp_lcd_panel_io.h"
|
||||
#include "esp_lcd_panel_rgb.h"
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_lcd_panel_interface.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "esp_pm.h"
|
||||
#include "hal/dma_types.h"
|
||||
|
||||
#include "hal/lcd_hal.h"
|
||||
#include "hal/lcd_ll.h"
|
||||
|
||||
#include "esp32s3/rom/cache.h"
|
||||
// This function is located in ROM (also see esp_rom/${target}/ld/${target}.rom.ld)
|
||||
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
|
||||
// extract from esp-idf esp_lcd_rgb_panel.c
|
||||
struct esp_rgb_panel_t
|
||||
{
|
||||
esp_lcd_panel_t base; // Base class of generic lcd panel
|
||||
int panel_id; // LCD panel ID
|
||||
lcd_hal_context_t hal; // Hal layer object
|
||||
size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16)
|
||||
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
|
||||
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
|
||||
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
|
||||
intr_handle_t intr; // LCD peripheral interrupt handle
|
||||
esp_pm_lock_handle_t pm_lock; // Power management lock
|
||||
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
|
||||
uint8_t *fb; // Frame buffer
|
||||
size_t fb_size; // Size of frame buffer
|
||||
int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
|
||||
size_t resolution_hz; // Peripheral clock resolution
|
||||
esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
|
||||
gdma_channel_handle_t dma_chan; // DMA channel handle
|
||||
esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done
|
||||
void *user_ctx; // Reserved user's data of callback functions
|
||||
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
|
||||
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
|
||||
struct
|
||||
{
|
||||
unsigned int disp_en_level : 1; // The level which can turn on the screen by `disp_gpio_num`
|
||||
unsigned int stream_mode : 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
|
||||
unsigned int fb_in_psram : 1; // Whether the frame buffer is in PSRAM
|
||||
} flags;
|
||||
dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes`
|
||||
};
|
||||
|
||||
class Arduino_ESP32RGBPanel
|
||||
{
|
||||
public:
|
||||
Arduino_ESP32RGBPanel(
|
||||
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
|
||||
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
|
||||
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
|
||||
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
|
||||
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
|
||||
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
|
||||
uint16_t pclk_active_neg = 0, int32_t prefer_speed = GFX_NOT_DEFINED, bool useBigEndian = false,
|
||||
uint16_t de_idle_high = 0, uint16_t pclk_idle_high = 0);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED);
|
||||
|
||||
uint16_t *getFrameBuffer(int16_t w, int16_t h);
|
||||
|
||||
protected:
|
||||
private:
|
||||
int32_t _speed;
|
||||
int8_t _de, _vsync, _hsync, _pclk;
|
||||
int8_t _r0, _r1, _r2, _r3, _r4;
|
||||
int8_t _g0, _g1, _g2, _g3, _g4, _g5;
|
||||
int8_t _b0, _b1, _b2, _b3, _b4;
|
||||
uint16_t _hsync_polarity;
|
||||
uint16_t _hsync_front_porch;
|
||||
uint16_t _hsync_pulse_width;
|
||||
uint16_t _hsync_back_porch;
|
||||
uint16_t _vsync_polarity;
|
||||
uint16_t _vsync_front_porch;
|
||||
uint16_t _vsync_pulse_width;
|
||||
uint16_t _vsync_back_porch;
|
||||
uint16_t _pclk_active_neg;
|
||||
int32_t _prefer_speed;
|
||||
bool _useBigEndian;
|
||||
uint16_t _de_idle_high;
|
||||
uint16_t _pclk_idle_high;
|
||||
|
||||
esp_lcd_panel_handle_t _panel_handle = NULL;
|
||||
esp_rgb_panel_t *_rgb_panel;
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_ESP32RGBPANEL_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
@@ -0,0 +1,696 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#include "Arduino_SWSPI.h"
|
||||
|
||||
Arduino_SWSPI::Arduino_SWSPI(int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso /* = GFX_NOT_DEFINED */)
|
||||
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_SWSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
UNUSED(speed);
|
||||
UNUSED(dataMode);
|
||||
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_dc, OUTPUT);
|
||||
digitalWrite(_dc, HIGH); // Data mode
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_cs, OUTPUT);
|
||||
digitalWrite(_cs, HIGH); // Deselect
|
||||
}
|
||||
pinMode(_sck, OUTPUT);
|
||||
digitalWrite(_sck, LOW);
|
||||
pinMode(_mosi, OUTPUT);
|
||||
digitalWrite(_mosi, LOW);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_miso, INPUT);
|
||||
}
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(ARDUINO_ARCH_NRF52840)
|
||||
uint32_t pin;
|
||||
NRF_GPIO_Type *reg;
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_dc);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_dcPinMask = 1UL << pin;
|
||||
_dcPortSet = ®->OUTSET;
|
||||
_dcPortClr = ®->OUTCLR;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_cs);
|
||||
NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_csPinMask = 1UL << pin;
|
||||
_csPortSet = ®->OUTSET;
|
||||
_csPortClr = ®->OUTCLR;
|
||||
}
|
||||
pin = digitalPinToPinName((pin_size_t)_sck);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_sckPinMask = 1UL << pin;
|
||||
_sckPortSet = ®->OUTSET;
|
||||
_sckPortClr = ®->OUTCLR;
|
||||
pin = digitalPinToPinName((pin_size_t)_mosi);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_mosiPinMask = 1UL << pin;
|
||||
_mosiPortSet = ®->OUTSET;
|
||||
_mosiPortClr = ®->OUTCLR;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
pin = digitalPinToPinName((pin_size_t)_miso);
|
||||
reg = nrf_gpio_pin_port_decode(&pin);
|
||||
_misoPinMask = 1UL << pin;
|
||||
_misoPort = ®->IN;
|
||||
}
|
||||
#elif defined(TARGET_RP2040)
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_sckPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = (PORTreg_t)&sio_hw->gpio_set;
|
||||
_mosiPortClr = (PORTreg_t)&sio_hw->gpio_clr;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_csPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_sckPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_mosiPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)GPIO_IN_REG;
|
||||
}
|
||||
#elif defined(ESP32)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
if (_dc >= 32)
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
|
||||
_dcPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
|
||||
}
|
||||
else if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
}
|
||||
if (_cs >= 32)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
|
||||
_csPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
|
||||
}
|
||||
else if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_csPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
if (_sck >= 32)
|
||||
{
|
||||
_sckPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
|
||||
_sckPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
|
||||
}
|
||||
else
|
||||
{
|
||||
_sckPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_sckPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
}
|
||||
if (_mosi >= 32)
|
||||
{
|
||||
_mosiPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
|
||||
_mosiPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mosiPortSet = (PORTreg_t)&GPIO.out_w1ts;
|
||||
_mosiPortClr = (PORTreg_t)&GPIO.out_w1tc;
|
||||
}
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#elif defined(CORE_TEENSY)
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
#endif
|
||||
_dcPortSet = portSetRegister(_dc);
|
||||
_dcPortClr = portClearRegister(_dc);
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
#endif
|
||||
_csPortSet = portSetRegister(_cs);
|
||||
_csPortClr = portClearRegister(_cs);
|
||||
}
|
||||
#if !defined(KINETISK)
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
#endif
|
||||
_sckPortSet = portSetRegister(_sck);
|
||||
_sckPortClr = portClearRegister(_sck);
|
||||
#if !defined(KINETISK)
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
#endif
|
||||
_mosiPortSet = portSetRegister(_mosi);
|
||||
_mosiPortClr = portClearRegister(_mosi);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if !defined(KINETISK)
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
#endif
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#else // !CORE_TEENSY
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPinMask = digitalPinToBitMask(_dc);
|
||||
_dcPortSet = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTSET.reg);
|
||||
_dcPortClr = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTCLR.reg);
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPinMask = digitalPinToBitMask(_cs);
|
||||
_csPortSet = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTSET.reg);
|
||||
_csPortClr = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTCLR.reg);
|
||||
}
|
||||
_sckPinMask = digitalPinToBitMask(_sck);
|
||||
_sckPortSet = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTSET.reg);
|
||||
_sckPortClr = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTCLR.reg);
|
||||
_mosiPinMask = digitalPinToBitMask(_mosi);
|
||||
_mosiPortSet = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTSET.reg);
|
||||
_mosiPortClr = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTCLR.reg);
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
}
|
||||
#endif // end !CORE_TEENSY
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
|
||||
_dcPinMaskSet = digitalPinToBitMask(_dc);
|
||||
_dcPinMaskClr = ~_dcPinMaskSet;
|
||||
}
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
|
||||
_csPinMaskSet = digitalPinToBitMask(_cs);
|
||||
_csPinMaskClr = ~_csPinMaskSet;
|
||||
}
|
||||
_sckPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_sck));
|
||||
_sckPinMaskSet = digitalPinToBitMask(_sck);
|
||||
_sckPinMaskClr = ~_sckPinMaskSet;
|
||||
_mosiPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_mosi));
|
||||
_mosiPinMaskSet = digitalPinToBitMask(_mosi);
|
||||
_mosiPinMaskClr = ~_mosiPinMaskSet;
|
||||
if (_miso != GFX_NOT_DEFINED)
|
||||
{
|
||||
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
|
||||
_misoPinMask = digitalPinToBitMask(_miso);
|
||||
}
|
||||
#endif // !HAS_PORT_SET_CLR
|
||||
#endif // USE_FAST_PINIO
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::beginWrite()
|
||||
{
|
||||
if (_dc != GFX_NOT_DEFINED)
|
||||
{
|
||||
DC_HIGH();
|
||||
}
|
||||
CS_LOW();
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::endWrite()
|
||||
{
|
||||
CS_HIGH();
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
WRITE9BITCOMMAND(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeCommand16(uint16_t c)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
_data16.value = c;
|
||||
WRITE9BITCOMMAND(_data16.msb);
|
||||
WRITE9BITCOMMAND(_data16.lsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
DC_LOW();
|
||||
WRITE16(c);
|
||||
DC_HIGH();
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::write(uint8_t d)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
WRITE9BITDATA(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE(d);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::write16(uint16_t d)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
_data16.value = d;
|
||||
WRITE9BITDATA(_data16.msb);
|
||||
WRITE9BITDATA(_data16.lsb);
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE16(d);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
|
||||
{
|
||||
// ESP8266 avoid trigger watchdog
|
||||
#if defined(ESP8266)
|
||||
while (len > (ESP8266SAFEBATCHBITSIZE / 9))
|
||||
{
|
||||
WRITE9BITREPEAT(p, ESP8266SAFEBATCHBITSIZE / 9);
|
||||
len -= ESP8266SAFEBATCHBITSIZE / 9;
|
||||
yield();
|
||||
}
|
||||
WRITE9BITREPEAT(p, len);
|
||||
#else
|
||||
WRITE9BITREPEAT(p, len);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(ESP8266)
|
||||
while (len > (ESP8266SAFEBATCHBITSIZE / 8))
|
||||
{
|
||||
WRITEREPEAT(p, ESP8266SAFEBATCHBITSIZE / 8);
|
||||
len -= ESP8266SAFEBATCHBITSIZE / 8;
|
||||
yield();
|
||||
}
|
||||
WRITEREPEAT(p, len);
|
||||
#else
|
||||
WRITEREPEAT(p, len);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_SWSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(*data++);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_SWSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE(*data++);
|
||||
}
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITE9BITCOMMAND(uint8_t c)
|
||||
{
|
||||
// D/C bit, command
|
||||
SPI_MOSI_LOW();
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (c & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITE9BITDATA(uint8_t d)
|
||||
{
|
||||
// D/C bit, data
|
||||
SPI_MOSI_HIGH();
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITE(uint8_t d)
|
||||
{
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITE16(uint16_t d)
|
||||
{
|
||||
uint16_t bit = 0x8000;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
SPI_SCK_HIGH();
|
||||
bit >>= 1;
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITE9BITREPEAT(uint16_t p, uint32_t len)
|
||||
{
|
||||
if (p == 0xffff) // no need to set MOSI level while filling white
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
len *= 18; // 9-bit * 2
|
||||
while (len--)
|
||||
{
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_data16.value = p;
|
||||
while (len--)
|
||||
{
|
||||
WRITE9BITDATA(_data16.msb);
|
||||
WRITE9BITDATA(_data16.lsb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::WRITEREPEAT(uint16_t p, uint32_t len)
|
||||
{
|
||||
if ((p == 0x0000) || (p == 0xffff)) // no need to set MOSI level while filling black or white
|
||||
{
|
||||
if (p)
|
||||
{
|
||||
SPI_MOSI_HIGH();
|
||||
}
|
||||
else
|
||||
{
|
||||
SPI_MOSI_LOW();
|
||||
}
|
||||
len *= 16;
|
||||
while (len--)
|
||||
{
|
||||
SPI_SCK_HIGH();
|
||||
SPI_SCK_LOW();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (len--)
|
||||
{
|
||||
WRITE16(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******** low level bit twiddling **********/
|
||||
|
||||
INLINE void Arduino_SWSPI::DC_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortSet = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort |= _dcPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::DC_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_dcPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_dcPortClr = _dcPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_dcPort &= _dcPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_dc, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::CS_HIGH(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortSet = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort |= _csPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
|
||||
INLINE void Arduino_SWSPI::CS_LOW(void)
|
||||
{
|
||||
if (_cs != GFX_NOT_DEFINED)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_csPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_csPortClr = _csPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_csPort &= _csPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_cs, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI MOSI line HIGH.
|
||||
*/
|
||||
INLINE void Arduino_SWSPI::SPI_MOSI_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_mosiPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_mosiPortSet = _mosiPinMask;
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_mosiPort |= _mosiPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_mosi, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI MOSI line LOW.
|
||||
*/
|
||||
INLINE void Arduino_SWSPI::SPI_MOSI_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_mosiPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_mosiPortClr = _mosiPinMask;
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_mosiPort &= _mosiPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_mosi, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI SCK line HIGH.
|
||||
*/
|
||||
INLINE void Arduino_SWSPI::SPI_SCK_HIGH(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_sckPortSet = 1;
|
||||
#else // !KINETISK
|
||||
*_sckPortSet = _sckPinMask;
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
|
||||
for (volatile uint8_t i = 0; i < 1; i++)
|
||||
;
|
||||
#endif
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_sckPort |= _sckPinMaskSet;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_sck, HIGH);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Set the software (bitbang) SPI SCK line LOW.
|
||||
*/
|
||||
INLINE void Arduino_SWSPI::SPI_SCK_LOW(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
#if defined(KINETISK)
|
||||
*_sckPortClr = 1;
|
||||
#else // !KINETISK
|
||||
*_sckPortClr = _sckPinMask;
|
||||
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
|
||||
for (volatile uint8_t i = 0; i < 1; i++)
|
||||
;
|
||||
#endif
|
||||
#endif
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
*_sckPort &= _sckPinMaskClr;
|
||||
#endif // end !HAS_PORT_SET_CLR
|
||||
#else // !USE_FAST_PINIO
|
||||
digitalWrite(_sck, LOW);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Read the state of the software (bitbang) SPI MISO line.
|
||||
@return true if HIGH, false if LOW.
|
||||
*/
|
||||
INLINE bool Arduino_SWSPI::SPI_MISO_READ(void)
|
||||
{
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(KINETISK)
|
||||
return *_misoPort;
|
||||
#else // !KINETISK
|
||||
return *_misoPort & _misoPinMask;
|
||||
#endif // end !KINETISK
|
||||
#else // !USE_FAST_PINIO
|
||||
return digitalRead(_miso);
|
||||
#endif // end !USE_FAST_PINIO
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* start rewrite from:
|
||||
* https://github.com/adafruit/Adafruit-GFX-Library.git
|
||||
*/
|
||||
#ifndef _ARDUINO_SWSPI_H_
|
||||
#define _ARDUINO_SWSPI_H_
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
class Arduino_SWSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_SWSPI(int8_t dc, int8_t cs, int8_t _sck, int8_t _mosi, int8_t _miso = GFX_NOT_DEFINED); // Constructor
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
private:
|
||||
INLINE void WRITE9BITCOMMAND(uint8_t c);
|
||||
INLINE void WRITE9BITDATA(uint8_t d);
|
||||
INLINE void WRITE(uint8_t d);
|
||||
INLINE void WRITE16(uint16_t d);
|
||||
INLINE void WRITE9BITREPEAT(uint16_t p, uint32_t len);
|
||||
INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
|
||||
INLINE void DC_HIGH(void);
|
||||
INLINE void DC_LOW(void);
|
||||
INLINE void CS_HIGH(void);
|
||||
INLINE void CS_LOW(void);
|
||||
INLINE void SPI_MOSI_HIGH(void);
|
||||
INLINE void SPI_MOSI_LOW(void);
|
||||
INLINE void SPI_SCK_HIGH(void);
|
||||
INLINE void SPI_SCK_LOW(void);
|
||||
INLINE bool SPI_MISO_READ(void);
|
||||
|
||||
int8_t _dc, _cs;
|
||||
int8_t _sck, _mosi, _miso;
|
||||
|
||||
// CLASS INSTANCE VARIABLES --------------------------------------------
|
||||
|
||||
// Here be dragons! There's a big union of three structures here --
|
||||
// one each for hardware SPI, software (bitbang) SPI, and parallel
|
||||
// interfaces. This is to save some memory, since a display's connection
|
||||
// will be only one of these. The order of some things is a little weird
|
||||
// in an attempt to get values to align and pack better in RAM.
|
||||
|
||||
#if defined(USE_FAST_PINIO)
|
||||
#if defined(HAS_PORT_SET_CLR)
|
||||
PORTreg_t _csPortSet; ///< PORT register for chip select SET
|
||||
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
|
||||
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
|
||||
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
|
||||
PORTreg_t _mosiPortSet; ///< PORT register for MOSI SET
|
||||
PORTreg_t _mosiPortClr; ///< PORT register for MOSI CLEAR
|
||||
PORTreg_t _sckPortSet; ///< PORT register for SCK SET
|
||||
PORTreg_t _sckPortClr; ///< PORT register for SCK CLEAR
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _csPinMask; ///< Bitmask for chip select
|
||||
ARDUINOGFX_PORT_t _dcPinMask; ///< Bitmask for data/command
|
||||
ARDUINOGFX_PORT_t _mosiPinMask; ///< Bitmask for MOSI
|
||||
ARDUINOGFX_PORT_t _sckPinMask; ///< Bitmask for SCK
|
||||
#endif // !KINETISK
|
||||
#else // !HAS_PORT_SET_CLR
|
||||
PORTreg_t _mosiPort; ///< PORT register for MOSI
|
||||
PORTreg_t _sckPort; ///< PORT register for SCK
|
||||
PORTreg_t _csPort; ///< PORT register for chip select
|
||||
PORTreg_t _dcPort; ///< PORT register for data/command
|
||||
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for chip select SET (OR)
|
||||
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
|
||||
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _mosiPinMaskSet; ///< Bitmask for MOSI SET (OR)
|
||||
ARDUINOGFX_PORT_t _mosiPinMaskClr; ///< Bitmask for MOSI CLEAR (AND)
|
||||
ARDUINOGFX_PORT_t _sckPinMaskSet; ///< Bitmask for SCK SET (OR bitmask)
|
||||
ARDUINOGFX_PORT_t _sckPinMaskClr; ///< Bitmask for SCK CLEAR (AND)
|
||||
#endif // HAS_PORT_SET_CLR
|
||||
PORTreg_t _misoPort; ///< PORT (PIN) register for MISO
|
||||
#if !defined(KINETISK)
|
||||
ARDUINOGFX_PORT_t _misoPinMask; ///< Bitmask for MISO
|
||||
#endif // !KINETISK
|
||||
#endif // defined(USE_FAST_PINIO)
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_SWSPI_H_
|
||||
@@ -0,0 +1,276 @@
|
||||
#include "Arduino_XL9535SWSPI.h"
|
||||
|
||||
Arduino_XL9535SWSPI::Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire)
|
||||
: _sda(sda), _scl(scl), _pwd(pwd), _cs(cs), _sck(sck), _mosi(mosi), _wire(wire)
|
||||
{
|
||||
}
|
||||
|
||||
bool Arduino_XL9535SWSPI::begin(int32_t speed, int8_t dataMode)
|
||||
{
|
||||
UNUSED(speed);
|
||||
UNUSED(dataMode);
|
||||
|
||||
_address = XL9535_IIC_ADDRESS;
|
||||
_wire->beginTransmission(_address);
|
||||
if (!_wire->endTransmission())
|
||||
{
|
||||
Serial.println("Found xl9535");
|
||||
is_found = true;
|
||||
|
||||
if (_pwd != GFX_NOT_DEFINED)
|
||||
{
|
||||
this->pinMode(_pwd, OUTPUT);
|
||||
}
|
||||
this->pinMode(_cs, OUTPUT);
|
||||
this->pinMode(_sck, OUTPUT);
|
||||
this->pinMode(_mosi, OUTPUT);
|
||||
|
||||
if (_pwd != GFX_NOT_DEFINED)
|
||||
{
|
||||
this->digitalWrite(_pwd, 1);
|
||||
}
|
||||
this->digitalWrite(_cs, 1);
|
||||
this->digitalWrite(_sck, 1);
|
||||
this->digitalWrite(_mosi, 1);
|
||||
|
||||
// while(1)
|
||||
// {
|
||||
// this->digitalWrite(4, 0);
|
||||
// delay(1000);
|
||||
// this->digitalWrite(4, 1);
|
||||
// delay(1000);
|
||||
// }
|
||||
|
||||
// this->digitalWrite(_cs, 0);
|
||||
// this->digitalWrite(5, 1);
|
||||
// delay(100);
|
||||
// this->digitalWrite(5, 0);
|
||||
// delay(800);
|
||||
// this->digitalWrite(5, 1);
|
||||
// delay(800);
|
||||
// this->digitalWrite(_cs, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
is_found = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::beginWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 0);
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::endWrite()
|
||||
{
|
||||
this->digitalWrite(_cs, 1);
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeCommand(uint8_t c)
|
||||
{
|
||||
// D/C bit, command
|
||||
this->digitalWrite(_mosi, 0);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (c & bit)
|
||||
{
|
||||
this->digitalWrite(_mosi, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->digitalWrite(_mosi, 0);
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeCommand16(uint16_t)
|
||||
{
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::write(uint8_t d)
|
||||
{
|
||||
// D/C bit, data
|
||||
this->digitalWrite(_mosi, 1);
|
||||
this->digitalWrite(_sck, 0);
|
||||
this->digitalWrite(_sck, 1);
|
||||
|
||||
uint8_t bit = 0x80;
|
||||
while (bit)
|
||||
{
|
||||
if (d & bit)
|
||||
{
|
||||
this->digitalWrite(_mosi, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->digitalWrite(_mosi, 0);
|
||||
}
|
||||
this->digitalWrite(_sck, 0);
|
||||
bit >>= 1;
|
||||
this->digitalWrite(_sck, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::write16(uint16_t)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writeRepeat(uint16_t p, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::writePixels(uint16_t *data, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void Arduino_XL9535SWSPI::writeBytes(uint8_t *data, uint32_t len)
|
||||
{
|
||||
// not implemented
|
||||
}
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void Arduino_XL9535SWSPI::writeRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
_wire->write(data[i]);
|
||||
}
|
||||
_wire->endTransmission();
|
||||
}
|
||||
|
||||
uint8_t Arduino_XL9535SWSPI::readRegister(uint8_t reg, uint8_t *data, size_t len)
|
||||
{
|
||||
_wire->beginTransmission(_address);
|
||||
_wire->write(reg);
|
||||
_wire->endTransmission();
|
||||
_wire->requestFrom(_address, len);
|
||||
size_t index = 0;
|
||||
while (index < len)
|
||||
data[index++] = _wire->read();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::pinMode(uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
port = port & (~(1 << (pin - 10)));
|
||||
}
|
||||
else
|
||||
{
|
||||
port = port | (1 << (pin - 10));
|
||||
}
|
||||
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
port = port & (~(1 << pin));
|
||||
}
|
||||
else
|
||||
{
|
||||
port = port | (1 << pin);
|
||||
}
|
||||
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
void Arduino_XL9535SWSPI::pinMode8(uint8_t port, uint8_t pin, uint8_t mode)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t _pin = (mode != OUTPUT) ? pin : ~pin;
|
||||
if (port)
|
||||
{
|
||||
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &_pin, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &_pin, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_XL9535SWSPI::digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
uint8_t port = 0;
|
||||
uint8_t reg_data = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_OUTPUT_PORT_1_REG, ®_data, 1);
|
||||
reg_data = reg_data & (~(1 << (pin - 10)));
|
||||
port = reg_data | val << (pin - 10);
|
||||
this->writeRegister(XL9535_OUTPUT_PORT_1_REG, &port, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_OUTPUT_PORT_0_REG, ®_data, 1);
|
||||
reg_data = reg_data & (~(1 << pin));
|
||||
port = reg_data | val << pin;
|
||||
this->writeRegister(XL9535_OUTPUT_PORT_0_REG, &port, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
}
|
||||
|
||||
int Arduino_XL9535SWSPI::digitalRead(uint8_t pin)
|
||||
{
|
||||
if (is_found)
|
||||
{
|
||||
int state = 0;
|
||||
uint8_t port = 0;
|
||||
if (pin > 7)
|
||||
{
|
||||
this->readRegister(XL9535_INPUT_PORT_1_REG, &port, 1);
|
||||
state = port >> (pin - 10) & 0x01 ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->readRegister(XL9535_INPUT_PORT_0_REG, &port, 1);
|
||||
state = port >> pin & 0x01 ? 1 : 0;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("xl9535 not found");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
#ifndef _ARDUINO_XL9535SWSPI_H_
|
||||
#define _ARDUINO_XL9535SWSPI_H_
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
#include "Arduino_DataBus.h"
|
||||
|
||||
#define XL9535_IIC_ADDRESS 0X20
|
||||
|
||||
#define XL9535_INPUT_PORT_0_REG 0X00
|
||||
#define XL9535_INPUT_PORT_1_REG 0X01
|
||||
#define XL9535_OUTPUT_PORT_0_REG 0X02
|
||||
#define XL9535_OUTPUT_PORT_1_REG 0X03
|
||||
#define XL9535_INVERSION_PORT_0_REG 0X04
|
||||
#define XL9535_INVERSION_PORT_1_REG 0X05
|
||||
#define XL9535_CONFIG_PORT_0_REG 0X06
|
||||
#define XL9535_CONFIG_PORT_1_REG 0X07
|
||||
|
||||
class Arduino_XL9535SWSPI : public Arduino_DataBus
|
||||
{
|
||||
public:
|
||||
Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire = &Wire);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
|
||||
void beginWrite() override;
|
||||
void endWrite() override;
|
||||
void writeCommand(uint8_t) override;
|
||||
void writeCommand16(uint16_t) override;
|
||||
void write(uint8_t) override;
|
||||
void write16(uint16_t) override;
|
||||
void writeRepeat(uint16_t p, uint32_t len) override;
|
||||
void writePixels(uint16_t *data, uint32_t len) override;
|
||||
|
||||
#if !defined(LITTLE_FOOT_PRINT)
|
||||
void writeBytes(uint8_t *data, uint32_t len) override;
|
||||
#endif // !defined(LITTLE_FOOT_PRINT)
|
||||
|
||||
void pinMode(uint8_t pin, uint8_t mode);
|
||||
void pinMode8(uint8_t port, uint8_t pin, uint8_t mode);
|
||||
|
||||
void digitalWrite(uint8_t pin, uint8_t val) override;
|
||||
int digitalRead(uint8_t pin) override;
|
||||
|
||||
protected:
|
||||
void writeRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
uint8_t readRegister(uint8_t reg, uint8_t *data, size_t len);
|
||||
|
||||
uint8_t _address;
|
||||
bool is_found;
|
||||
|
||||
int8_t _sda, _scl, _pwd, _cs, _sck, _mosi;
|
||||
TwoWire *_wire;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_XL9535SWSPI_H_
|
||||
@@ -0,0 +1,493 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "Arduino_RGB_Display.h"
|
||||
|
||||
Arduino_RGB_Display::Arduino_RGB_Display(
|
||||
int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r, bool auto_flush,
|
||||
Arduino_DataBus *bus, int8_t rst, const uint8_t *init_operations, size_t init_operations_len)
|
||||
: Arduino_GFX(w, h), _rgbpanel(rgbpanel), _auto_flush(auto_flush),
|
||||
_bus(bus), _rst(rst), _init_operations(init_operations), _init_operations_len(init_operations_len)
|
||||
{
|
||||
_framebuffer_size = w * h * 2;
|
||||
MAX_X = WIDTH - 1;
|
||||
MAX_Y = HEIGHT - 1;
|
||||
setRotation(r);
|
||||
}
|
||||
|
||||
bool Arduino_RGB_Display::begin(int32_t speed)
|
||||
{
|
||||
if (_bus)
|
||||
{
|
||||
if (!_bus->begin())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_rst != GFX_NOT_DEFINED)
|
||||
{
|
||||
pinMode(_rst, OUTPUT);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(100);
|
||||
digitalWrite(_rst, LOW);
|
||||
delay(120);
|
||||
digitalWrite(_rst, HIGH);
|
||||
delay(120);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_bus)
|
||||
{
|
||||
// Software Rest
|
||||
_bus->sendCommand(0x01);
|
||||
delay(120);
|
||||
}
|
||||
}
|
||||
|
||||
if (_bus)
|
||||
{
|
||||
if (_init_operations_len > 0)
|
||||
{
|
||||
_bus->batchOperation((uint8_t *)_init_operations, _init_operations_len);
|
||||
}
|
||||
}
|
||||
|
||||
_rgbpanel->begin(speed);
|
||||
_framebuffer = _rgbpanel->getFrameBuffer(WIDTH, HEIGHT);
|
||||
|
||||
if (!_framebuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
|
||||
{
|
||||
uint16_t *fb = _framebuffer;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
fb += (int32_t)x * _height;
|
||||
fb += _max_y - y;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
fb += (int32_t)(_max_y - y) * _width;
|
||||
fb += _max_x - x;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
fb += (int32_t)(_max_x - x) * _height;
|
||||
fb += y;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
break;
|
||||
default: // case 0:
|
||||
fb += (int32_t)y * _width;
|
||||
fb += x;
|
||||
*fb = color;
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLine(x: %d, y: %d, h: %d)", x, y, h);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastHLineCore(_height - y - h, x, h, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastVLineCore(_max_x - x, _height - y - h, h, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastHLineCore(y, _max_x - x, h, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastVLineCore(x, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastVLineCore(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
|
||||
if (_ordered_in_range(x, 0, MAX_X) && h)
|
||||
{ // X on screen, nonzero height
|
||||
if (h < 0)
|
||||
{ // If negative height...
|
||||
y += h + 1; // Move Y to top edge
|
||||
h = -h; // Use positive height
|
||||
}
|
||||
if (y <= MAX_Y)
|
||||
{ // Not off bottom
|
||||
int16_t y2 = y + h - 1;
|
||||
if (y2 >= 0)
|
||||
{ // Not off top
|
||||
// Line partly or fully overlaps screen
|
||||
if (y < 0)
|
||||
{
|
||||
y = 0;
|
||||
h = y2 + 1;
|
||||
} // Clip top
|
||||
if (y2 > MAX_Y)
|
||||
{
|
||||
h = MAX_Y - y + 1;
|
||||
} // Clip bottom
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
if (_auto_flush)
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
Cache_WriteBack_Addr((uint32_t)fb, 2);
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (h--)
|
||||
{
|
||||
*fb = color;
|
||||
fb += WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
writeFastVLineCore(_max_y - y, x, w, color);
|
||||
break;
|
||||
case 2:
|
||||
writeFastHLineCore(_width - x - w, _max_y - y, w, color);
|
||||
break;
|
||||
case 3:
|
||||
writeFastVLineCore(y, _width - x - w, w, color);
|
||||
break;
|
||||
default: // case 0:
|
||||
writeFastHLineCore(x, y, w, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFastHLineCore(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color)
|
||||
{
|
||||
// log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
|
||||
if (_ordered_in_range(y, 0, MAX_Y) && w)
|
||||
{ // Y on screen, nonzero width
|
||||
if (w < 0)
|
||||
{ // If negative width...
|
||||
x += w + 1; // Move X to left edge
|
||||
w = -w; // Use positive width
|
||||
}
|
||||
if (x <= MAX_X)
|
||||
{ // Not off right
|
||||
int16_t x2 = x + w - 1;
|
||||
if (x2 >= 0)
|
||||
{ // Not off left
|
||||
// Line partly or fully overlaps screen
|
||||
if (x < 0)
|
||||
{
|
||||
x = 0;
|
||||
w = x2 + 1;
|
||||
} // Clip left
|
||||
if (x2 > MAX_X)
|
||||
{
|
||||
w = MAX_X - x + 1;
|
||||
} // Clip right
|
||||
|
||||
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
|
||||
uint32_t cachePos = (uint32_t)fb;
|
||||
int16_t writeSize = w * 2;
|
||||
while (w--)
|
||||
{
|
||||
*(fb++) = color;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, writeSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::writeFillRectPreclipped(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h, uint16_t color)
|
||||
{
|
||||
// log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
if (_rotation > 0)
|
||||
{
|
||||
int16_t t = x;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
x = WIDTH - y - h;
|
||||
y = t;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
case 2:
|
||||
x = WIDTH - x - w;
|
||||
y = HEIGHT - y - h;
|
||||
break;
|
||||
case 3:
|
||||
x = y;
|
||||
y = HEIGHT - t - w;
|
||||
t = w;
|
||||
w = h;
|
||||
h = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * WIDTH;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color;
|
||||
}
|
||||
row += WIDTH;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, WIDTH * h * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
x_skip += (x + w - 1) - _max_x;
|
||||
w -= (x + w - 1) - _max_x;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
x_skip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
row[i] = color_index[*bitmap++];
|
||||
}
|
||||
bitmap += x_skip;
|
||||
row += _width;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, _width * h * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::draw16bitRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
bool result;
|
||||
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 2:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
case 3:
|
||||
result = gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
break;
|
||||
default: // case 0:
|
||||
result = gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
if (_auto_flush)
|
||||
{
|
||||
uint32_t cachePos;
|
||||
size_t cache_size;
|
||||
switch (_rotation)
|
||||
{
|
||||
case 1:
|
||||
cachePos = (uint32_t)(_framebuffer + (x * WIDTH));
|
||||
cache_size = HEIGHT * w * 2;
|
||||
break;
|
||||
case 2:
|
||||
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - y) * WIDTH));
|
||||
cache_size = HEIGHT * h * 2;
|
||||
break;
|
||||
case 3:
|
||||
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - x) * WIDTH));
|
||||
cache_size = HEIGHT * w * 2;
|
||||
break;
|
||||
default: // case 0:
|
||||
cachePos = (uint32_t)(_framebuffer + (y * WIDTH) + x);
|
||||
cache_size = (WIDTH * (h - 1) + w) * 2;
|
||||
}
|
||||
Cache_WriteBack_Addr(cachePos, cache_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::draw16bitBeRGBBitmap(int16_t x, int16_t y,
|
||||
uint16_t *bitmap, int16_t w, int16_t h)
|
||||
{
|
||||
if (
|
||||
((x + w - 1) < 0) || // Outside left
|
||||
((y + h - 1) < 0) || // Outside top
|
||||
(x > _max_x) || // Outside right
|
||||
(y > _max_y) // Outside bottom
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_rotation > 0)
|
||||
{
|
||||
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t xskip = 0;
|
||||
if ((y + h - 1) > _max_y)
|
||||
{
|
||||
h -= (y + h - 1) - _max_y;
|
||||
}
|
||||
if (y < 0)
|
||||
{
|
||||
bitmap -= y * w;
|
||||
h += y;
|
||||
y = 0;
|
||||
}
|
||||
if ((x + w - 1) > _max_x)
|
||||
{
|
||||
xskip = (x + w - 1) - _max_x;
|
||||
w -= xskip;
|
||||
}
|
||||
if (x < 0)
|
||||
{
|
||||
bitmap -= x;
|
||||
xskip -= x;
|
||||
w += x;
|
||||
x = 0;
|
||||
}
|
||||
uint16_t *row = _framebuffer;
|
||||
row += y * _width;
|
||||
uint32_t cachePos = (uint32_t)row;
|
||||
row += x;
|
||||
uint16_t color;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
color = *bitmap++;
|
||||
MSB_16_SET(row[i], color);
|
||||
}
|
||||
bitmap += xskip;
|
||||
row += _width;
|
||||
}
|
||||
if (_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr(cachePos, _width * h * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Arduino_RGB_Display::flush(void)
|
||||
{
|
||||
if (!_auto_flush)
|
||||
{
|
||||
Cache_WriteBack_Addr((uint32_t)_framebuffer, _framebuffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t *Arduino_RGB_Display::getFramebuffer()
|
||||
{
|
||||
return _framebuffer;
|
||||
}
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
void Arduino_RGB_Display::XL_digitalWrite(uint8_t pin, uint8_t val)
|
||||
{
|
||||
_bus->digitalWrite(pin, val);
|
||||
}
|
||||
|
||||
int Arduino_RGB_Display::XL_digitalRead(uint8_t pin)
|
||||
{
|
||||
return _bus->digitalRead(pin);
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#include "../Arduino_DataBus.h"
|
||||
|
||||
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#ifndef _ARDUINO_RGB_DISPLAY_H_
|
||||
#define _ARDUINO_RGB_DISPLAY_H_
|
||||
|
||||
#include "../Arduino_GFX.h"
|
||||
#include "../databus/Arduino_ESP32RGBPanel.h"
|
||||
|
||||
|
||||
class Arduino_RGB_Display : public Arduino_GFX
|
||||
{
|
||||
public:
|
||||
Arduino_RGB_Display(
|
||||
int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r = 0, bool auto_flush = true,
|
||||
Arduino_DataBus *bus = NULL, int8_t rst = GFX_NOT_DEFINED, const uint8_t *init_operations = NULL, size_t init_operations_len = GFX_NOT_DEFINED);
|
||||
|
||||
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
|
||||
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
|
||||
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
|
||||
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint16_t color);
|
||||
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
|
||||
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint16_t color);
|
||||
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
|
||||
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
|
||||
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
|
||||
void flush(void) override;
|
||||
|
||||
uint16_t *getFramebuffer();
|
||||
|
||||
void XL_digitalWrite(uint8_t pin, uint8_t val);
|
||||
int XL_digitalRead(uint8_t pin);
|
||||
|
||||
protected:
|
||||
uint16_t *_framebuffer;
|
||||
size_t _framebuffer_size;
|
||||
Arduino_ESP32RGBPanel *_rgbpanel;
|
||||
bool _auto_flush;
|
||||
Arduino_DataBus *_bus;
|
||||
int8_t _rst;
|
||||
const uint8_t *_init_operations;
|
||||
size_t _init_operations_len;
|
||||
int16_t MAX_X, MAX_Y;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif // _ARDUINO_RGB_DISPLAY_H_
|
||||
|
||||
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
|
||||
280
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/font/glcdfont.h
Normal file
280
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/font/glcdfont.h
Normal file
@@ -0,0 +1,280 @@
|
||||
// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
|
||||
// See gfxfont.h for newer custom bitmap font info.
|
||||
|
||||
#ifndef FONT5X7_H
|
||||
#define FONT5X7_H
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#elif defined(ESP8266)
|
||||
#include <pgmspace.h>
|
||||
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
|
||||
// PROGMEM is defefind for T4 to place data in specific memory section
|
||||
#undef PROGMEM
|
||||
#define PROGMEM
|
||||
#else
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
// Standard ASCII 5x7 font
|
||||
|
||||
static const unsigned char font[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
|
||||
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
|
||||
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
|
||||
0x18, 0x3C, 0x7E, 0x3C, 0x18,
|
||||
0x1C, 0x57, 0x7D, 0x57, 0x1C,
|
||||
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
|
||||
0x00, 0x18, 0x3C, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
|
||||
0x00, 0x18, 0x24, 0x18, 0x00,
|
||||
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
|
||||
0x30, 0x48, 0x3A, 0x06, 0x0E,
|
||||
0x26, 0x29, 0x79, 0x29, 0x26,
|
||||
0x40, 0x7F, 0x05, 0x05, 0x07,
|
||||
0x40, 0x7F, 0x05, 0x25, 0x3F,
|
||||
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
|
||||
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
|
||||
0x14, 0x22, 0x7F, 0x22, 0x14,
|
||||
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
|
||||
0x06, 0x09, 0x7F, 0x01, 0x7F,
|
||||
0x00, 0x66, 0x89, 0x95, 0x6A,
|
||||
0x60, 0x60, 0x60, 0x60, 0x60,
|
||||
0x94, 0xA2, 0xFF, 0xA2, 0x94,
|
||||
0x08, 0x04, 0x7E, 0x04, 0x08,
|
||||
0x10, 0x20, 0x7E, 0x20, 0x10,
|
||||
0x08, 0x08, 0x2A, 0x1C, 0x08,
|
||||
0x08, 0x1C, 0x2A, 0x08, 0x08,
|
||||
0x1E, 0x10, 0x10, 0x10, 0x10,
|
||||
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
|
||||
0x30, 0x38, 0x3E, 0x38, 0x30,
|
||||
0x06, 0x0E, 0x3E, 0x0E, 0x06,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0x00, 0x00,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x14, 0x7F, 0x14, 0x7F, 0x14,
|
||||
0x24, 0x2A, 0x7F, 0x2A, 0x12,
|
||||
0x23, 0x13, 0x08, 0x64, 0x62,
|
||||
0x36, 0x49, 0x56, 0x20, 0x50,
|
||||
0x00, 0x08, 0x07, 0x03, 0x00,
|
||||
0x00, 0x1C, 0x22, 0x41, 0x00,
|
||||
0x00, 0x41, 0x22, 0x1C, 0x00,
|
||||
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
|
||||
0x08, 0x08, 0x3E, 0x08, 0x08,
|
||||
0x00, 0x80, 0x70, 0x30, 0x00,
|
||||
0x08, 0x08, 0x08, 0x08, 0x08,
|
||||
0x00, 0x00, 0x60, 0x60, 0x00,
|
||||
0x20, 0x10, 0x08, 0x04, 0x02,
|
||||
0x3E, 0x51, 0x49, 0x45, 0x3E,
|
||||
0x00, 0x42, 0x7F, 0x40, 0x00,
|
||||
0x72, 0x49, 0x49, 0x49, 0x46,
|
||||
0x21, 0x41, 0x49, 0x4D, 0x33,
|
||||
0x18, 0x14, 0x12, 0x7F, 0x10,
|
||||
0x27, 0x45, 0x45, 0x45, 0x39,
|
||||
0x3C, 0x4A, 0x49, 0x49, 0x31,
|
||||
0x41, 0x21, 0x11, 0x09, 0x07,
|
||||
0x36, 0x49, 0x49, 0x49, 0x36,
|
||||
0x46, 0x49, 0x49, 0x29, 0x1E,
|
||||
0x00, 0x00, 0x14, 0x00, 0x00,
|
||||
0x00, 0x40, 0x34, 0x00, 0x00,
|
||||
0x00, 0x08, 0x14, 0x22, 0x41,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x00, 0x41, 0x22, 0x14, 0x08,
|
||||
0x02, 0x01, 0x59, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x5D, 0x59, 0x4E,
|
||||
0x7C, 0x12, 0x11, 0x12, 0x7C,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x36,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x22,
|
||||
0x7F, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x49, 0x49, 0x49, 0x41,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x01,
|
||||
0x3E, 0x41, 0x41, 0x51, 0x73,
|
||||
0x7F, 0x08, 0x08, 0x08, 0x7F,
|
||||
0x00, 0x41, 0x7F, 0x41, 0x00,
|
||||
0x20, 0x40, 0x41, 0x3F, 0x01,
|
||||
0x7F, 0x08, 0x14, 0x22, 0x41,
|
||||
0x7F, 0x40, 0x40, 0x40, 0x40,
|
||||
0x7F, 0x02, 0x1C, 0x02, 0x7F,
|
||||
0x7F, 0x04, 0x08, 0x10, 0x7F,
|
||||
0x3E, 0x41, 0x41, 0x41, 0x3E,
|
||||
0x7F, 0x09, 0x09, 0x09, 0x06,
|
||||
0x3E, 0x41, 0x51, 0x21, 0x5E,
|
||||
0x7F, 0x09, 0x19, 0x29, 0x46,
|
||||
0x26, 0x49, 0x49, 0x49, 0x32,
|
||||
0x03, 0x01, 0x7F, 0x01, 0x03,
|
||||
0x3F, 0x40, 0x40, 0x40, 0x3F,
|
||||
0x1F, 0x20, 0x40, 0x20, 0x1F,
|
||||
0x3F, 0x40, 0x38, 0x40, 0x3F,
|
||||
0x63, 0x14, 0x08, 0x14, 0x63,
|
||||
0x03, 0x04, 0x78, 0x04, 0x03,
|
||||
0x61, 0x59, 0x49, 0x4D, 0x43,
|
||||
0x00, 0x7F, 0x41, 0x41, 0x41,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x00, 0x41, 0x41, 0x41, 0x7F,
|
||||
0x04, 0x02, 0x01, 0x02, 0x04,
|
||||
0x40, 0x40, 0x40, 0x40, 0x40,
|
||||
0x00, 0x03, 0x07, 0x08, 0x00,
|
||||
0x20, 0x54, 0x54, 0x78, 0x40,
|
||||
0x7F, 0x28, 0x44, 0x44, 0x38,
|
||||
0x38, 0x44, 0x44, 0x44, 0x28,
|
||||
0x38, 0x44, 0x44, 0x28, 0x7F,
|
||||
0x38, 0x54, 0x54, 0x54, 0x18,
|
||||
0x00, 0x08, 0x7E, 0x09, 0x02,
|
||||
0x18, 0xA4, 0xA4, 0x9C, 0x78,
|
||||
0x7F, 0x08, 0x04, 0x04, 0x78,
|
||||
0x00, 0x44, 0x7D, 0x40, 0x00,
|
||||
0x20, 0x40, 0x40, 0x3D, 0x00,
|
||||
0x7F, 0x10, 0x28, 0x44, 0x00,
|
||||
0x00, 0x41, 0x7F, 0x40, 0x00,
|
||||
0x7C, 0x04, 0x78, 0x04, 0x78,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x78,
|
||||
0x38, 0x44, 0x44, 0x44, 0x38,
|
||||
0xFC, 0x18, 0x24, 0x24, 0x18,
|
||||
0x18, 0x24, 0x24, 0x18, 0xFC,
|
||||
0x7C, 0x08, 0x04, 0x04, 0x08,
|
||||
0x48, 0x54, 0x54, 0x54, 0x24,
|
||||
0x04, 0x04, 0x3F, 0x44, 0x24,
|
||||
0x3C, 0x40, 0x40, 0x20, 0x7C,
|
||||
0x1C, 0x20, 0x40, 0x20, 0x1C,
|
||||
0x3C, 0x40, 0x30, 0x40, 0x3C,
|
||||
0x44, 0x28, 0x10, 0x28, 0x44,
|
||||
0x4C, 0x90, 0x90, 0x90, 0x7C,
|
||||
0x44, 0x64, 0x54, 0x4C, 0x44,
|
||||
0x00, 0x08, 0x36, 0x41, 0x00,
|
||||
0x00, 0x00, 0x77, 0x00, 0x00,
|
||||
0x00, 0x41, 0x36, 0x08, 0x00,
|
||||
0x02, 0x01, 0x02, 0x04, 0x02,
|
||||
0x3C, 0x26, 0x23, 0x26, 0x3C,
|
||||
0x1E, 0xA1, 0xA1, 0x61, 0x12,
|
||||
0x3A, 0x40, 0x40, 0x20, 0x7A,
|
||||
0x38, 0x54, 0x54, 0x55, 0x59,
|
||||
0x21, 0x55, 0x55, 0x79, 0x41,
|
||||
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
|
||||
0x21, 0x55, 0x54, 0x78, 0x40,
|
||||
0x20, 0x54, 0x55, 0x79, 0x40,
|
||||
0x0C, 0x1E, 0x52, 0x72, 0x12,
|
||||
0x39, 0x55, 0x55, 0x55, 0x59,
|
||||
0x39, 0x54, 0x54, 0x54, 0x59,
|
||||
0x39, 0x55, 0x54, 0x54, 0x58,
|
||||
0x00, 0x00, 0x45, 0x7C, 0x41,
|
||||
0x00, 0x02, 0x45, 0x7D, 0x42,
|
||||
0x00, 0x01, 0x45, 0x7C, 0x40,
|
||||
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
|
||||
0xF0, 0x28, 0x25, 0x28, 0xF0,
|
||||
0x7C, 0x54, 0x55, 0x45, 0x00,
|
||||
0x20, 0x54, 0x54, 0x7C, 0x54,
|
||||
0x7C, 0x0A, 0x09, 0x7F, 0x49,
|
||||
0x32, 0x49, 0x49, 0x49, 0x32,
|
||||
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
|
||||
0x32, 0x4A, 0x48, 0x48, 0x30,
|
||||
0x3A, 0x41, 0x41, 0x21, 0x7A,
|
||||
0x3A, 0x42, 0x40, 0x20, 0x78,
|
||||
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
|
||||
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
|
||||
0x3D, 0x40, 0x40, 0x40, 0x3D,
|
||||
0x3C, 0x24, 0xFF, 0x24, 0x24,
|
||||
0x48, 0x7E, 0x49, 0x43, 0x66,
|
||||
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
|
||||
0xFF, 0x09, 0x29, 0xF6, 0x20,
|
||||
0xC0, 0x88, 0x7E, 0x09, 0x03,
|
||||
0x20, 0x54, 0x54, 0x79, 0x41,
|
||||
0x00, 0x00, 0x44, 0x7D, 0x41,
|
||||
0x30, 0x48, 0x48, 0x4A, 0x32,
|
||||
0x38, 0x40, 0x40, 0x22, 0x7A,
|
||||
0x00, 0x7A, 0x0A, 0x0A, 0x72,
|
||||
0x7D, 0x0D, 0x19, 0x31, 0x7D,
|
||||
0x26, 0x29, 0x29, 0x2F, 0x28,
|
||||
0x26, 0x29, 0x29, 0x29, 0x26,
|
||||
0x30, 0x48, 0x4D, 0x40, 0x20,
|
||||
0x38, 0x08, 0x08, 0x08, 0x08,
|
||||
0x08, 0x08, 0x08, 0x08, 0x38,
|
||||
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
|
||||
0x2F, 0x10, 0x28, 0x34, 0xFA,
|
||||
0x00, 0x00, 0x7B, 0x00, 0x00,
|
||||
0x08, 0x14, 0x2A, 0x14, 0x22,
|
||||
0x22, 0x14, 0x2A, 0x14, 0x08,
|
||||
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
|
||||
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
|
||||
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x00,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x00,
|
||||
0x10, 0x10, 0xFF, 0x00, 0xFF,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x14, 0x14, 0x14, 0xFC, 0x00,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xFF,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xFC,
|
||||
0x14, 0x14, 0x17, 0x10, 0x1F,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0x1F, 0x00,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x10,
|
||||
0x10, 0x10, 0x10, 0xF0, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0xFF, 0x10,
|
||||
0x00, 0x00, 0x00, 0xFF, 0x14,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x17,
|
||||
0x00, 0x00, 0xFC, 0x04, 0xF4,
|
||||
0x14, 0x14, 0x17, 0x10, 0x17,
|
||||
0x14, 0x14, 0xF4, 0x04, 0xF4,
|
||||
0x00, 0x00, 0xFF, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x14, 0x14,
|
||||
0x14, 0x14, 0xF7, 0x00, 0xF7,
|
||||
0x14, 0x14, 0x14, 0x17, 0x14,
|
||||
0x10, 0x10, 0x1F, 0x10, 0x1F,
|
||||
0x14, 0x14, 0x14, 0xF4, 0x14,
|
||||
0x10, 0x10, 0xF0, 0x10, 0xF0,
|
||||
0x00, 0x00, 0x1F, 0x10, 0x1F,
|
||||
0x00, 0x00, 0x00, 0x1F, 0x14,
|
||||
0x00, 0x00, 0x00, 0xFC, 0x14,
|
||||
0x00, 0x00, 0xF0, 0x10, 0xF0,
|
||||
0x10, 0x10, 0xFF, 0x10, 0xFF,
|
||||
0x14, 0x14, 0x14, 0xFF, 0x14,
|
||||
0x10, 0x10, 0x10, 0x1F, 0x00,
|
||||
0x00, 0x00, 0x00, 0xF0, 0x10,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||
0xFF, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x38, 0x44, 0x44, 0x38, 0x44,
|
||||
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
|
||||
0x7E, 0x02, 0x02, 0x06, 0x06,
|
||||
0x02, 0x7E, 0x02, 0x7E, 0x02,
|
||||
0x63, 0x55, 0x49, 0x41, 0x63,
|
||||
0x38, 0x44, 0x44, 0x3C, 0x04,
|
||||
0x40, 0x7E, 0x20, 0x1E, 0x20,
|
||||
0x06, 0x02, 0x7E, 0x02, 0x02,
|
||||
0x99, 0xA5, 0xE7, 0xA5, 0x99,
|
||||
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
|
||||
0x4C, 0x72, 0x01, 0x72, 0x4C,
|
||||
0x30, 0x4A, 0x4D, 0x4D, 0x30,
|
||||
0x30, 0x48, 0x78, 0x48, 0x30,
|
||||
0xBC, 0x62, 0x5A, 0x46, 0x3D,
|
||||
0x3E, 0x49, 0x49, 0x49, 0x00,
|
||||
0x7E, 0x01, 0x01, 0x01, 0x7E,
|
||||
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
|
||||
0x44, 0x44, 0x5F, 0x44, 0x44,
|
||||
0x40, 0x51, 0x4A, 0x44, 0x40,
|
||||
0x40, 0x44, 0x4A, 0x51, 0x40,
|
||||
0x00, 0x00, 0xFF, 0x01, 0x03,
|
||||
0xE0, 0x80, 0xFF, 0x00, 0x00,
|
||||
0x08, 0x08, 0x6B, 0x6B, 0x08,
|
||||
0x36, 0x12, 0x36, 0x24, 0x36,
|
||||
0x00, 0x06, 0x09, 0x09, 0x06,
|
||||
0x00, 0x00, 0x18, 0x18, 0x00,
|
||||
0x00, 0x00, 0x10, 0x10, 0x00,
|
||||
0x30, 0x40, 0xFF, 0x01, 0x01,
|
||||
0x00, 0x1F, 0x01, 0x01, 0x1E,
|
||||
0x00, 0x19, 0x1D, 0x17, 0x12,
|
||||
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
|
||||
};
|
||||
#endif // FONT5X7_H
|
||||
31
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/gfxfont.h
Normal file
31
ESP32_AP-Flasher/lib2/Arduino_GFX-1.3.7/src/gfxfont.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// Font structures for newer Adafruit_GFX (1.1 and later).
|
||||
// Example fonts are included in 'Fonts' directory.
|
||||
// To use a font in your Arduino sketch, #include the corresponding .h
|
||||
// file and pass address of GFXfont struct to setFont(). Pass NULL to
|
||||
// revert to 'classic' fixed-space bitmap font.
|
||||
|
||||
#ifndef _GFXFONT_H_
|
||||
#define _GFXFONT_H_
|
||||
|
||||
/// Font data stored PER GLYPH
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
|
||||
uint8_t width; ///< Bitmap dimensions in pixels
|
||||
uint8_t height; ///< Bitmap dimensions in pixels
|
||||
uint8_t xAdvance; ///< Distance to advance cursor (x axis)
|
||||
int8_t xOffset; ///< X dist from cursor pos to UL corner
|
||||
int8_t yOffset; ///< Y dist from cursor pos to UL corner
|
||||
} GFXglyph;
|
||||
|
||||
/// Data stored for FONT AS A WHOLE
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *bitmap; ///< Glyph bitmaps, concatenated
|
||||
GFXglyph *glyph; ///< Glyph array
|
||||
uint8_t first; ///< ASCII extents (first char)
|
||||
uint8_t last; ///< ASCII extents (last char)
|
||||
uint8_t yAdvance; ///< Newline distance (y axis)
|
||||
} GFXfont;
|
||||
|
||||
#endif // _GFXFONT_H_
|
||||
114
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.cpp
Normal file
114
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "Arduino.h"
|
||||
#include <Touch_GT911.h>
|
||||
#include <Wire.h>
|
||||
|
||||
Touch_GT911::Touch_GT911(uint8_t _sda, uint8_t _scl, uint16_t _width, uint16_t _height) :
|
||||
pinSda(_sda), pinScl(_scl), width(_width), height(_height) {
|
||||
}
|
||||
TPoint::TPoint(void) {
|
||||
id = x = y = size = 0;
|
||||
}
|
||||
TPoint::TPoint(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _size) {
|
||||
id = _id;
|
||||
x = _x;
|
||||
y = _y;
|
||||
size = _size;
|
||||
}
|
||||
bool TPoint::operator==(TPoint point) {
|
||||
return ((point.x == x) && (point.y == y) && (point.size == size));
|
||||
}
|
||||
bool TPoint::operator!=(TPoint point) {
|
||||
return ((point.x != x) || (point.y != y) || (point.size != size));
|
||||
}
|
||||
void Touch_GT911::begin(uint8_t _addr) {
|
||||
addr = _addr;
|
||||
Wire.begin(pinSda, pinScl);
|
||||
}
|
||||
void Touch_GT911::calculateChecksum() {
|
||||
uint8_t checksum;
|
||||
for (uint8_t i=0; i<GT911_CONFIG_SIZE; i++) {
|
||||
checksum += configBuf[i];
|
||||
}
|
||||
checksum = (~checksum) + 1;
|
||||
configBuf[GT911_CONFIG_CHKSUM - GT911_CONFIG_START] = checksum;
|
||||
}
|
||||
void Touch_GT911::reConfig() {
|
||||
calculateChecksum();
|
||||
writeByteData(GT911_CONFIG_CHKSUM, configBuf[GT911_CONFIG_CHKSUM-GT911_CONFIG_START]);
|
||||
writeByteData(GT911_CONFIG_FRESH, 1);
|
||||
}
|
||||
void Touch_GT911::setResolution(uint16_t _width, uint16_t _height) {
|
||||
configBuf[GT911_X_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_width);
|
||||
configBuf[GT911_X_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_width);
|
||||
configBuf[GT911_Y_OUTPUT_MAX_LOW - GT911_CONFIG_START] = lowByte(_height);
|
||||
configBuf[GT911_Y_OUTPUT_MAX_HIGH - GT911_CONFIG_START] = highByte(_height);
|
||||
reConfig();
|
||||
}
|
||||
void Touch_GT911::read(void) {
|
||||
uint8_t data[7];
|
||||
uint8_t id;
|
||||
uint16_t x, y, size;
|
||||
|
||||
uint8_t pointInfo = readByteData(GT911_POINT_INFO);
|
||||
uint8_t bufferStatus = pointInfo >> 7 & 1;
|
||||
uint8_t proximityValid = pointInfo >> 5 & 1;
|
||||
uint8_t haveKey = pointInfo >> 4 & 1;
|
||||
isLargeDetect = pointInfo >> 6 & 1;
|
||||
touches = pointInfo & 0xF;
|
||||
isTouched = touches > 0;
|
||||
if (bufferStatus == 1 && isTouched) {
|
||||
for (uint8_t i=0; i<touches; i++) {
|
||||
readBlockData(data, GT911_POINT_1 + i * 8, 7);
|
||||
points[i] = readPoint(data);
|
||||
}
|
||||
}
|
||||
writeByteData(GT911_POINT_INFO, 0);
|
||||
}
|
||||
TPoint Touch_GT911::readPoint(uint8_t *data) {
|
||||
uint16_t temp;
|
||||
uint8_t id = data[0];
|
||||
uint16_t x = data[1] + (data[2] << 8);
|
||||
uint16_t y = data[3] + (data[4] << 8);
|
||||
uint16_t size = data[5] + (data[6] << 8);
|
||||
x = width - x;
|
||||
y = height - y;
|
||||
return TPoint(id, x, y, size);
|
||||
}
|
||||
void Touch_GT911::writeByteData(uint16_t reg, uint8_t val) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.write(val);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
uint8_t Touch_GT911::readByteData(uint16_t reg) {
|
||||
uint8_t x;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(addr, (uint8_t)1);
|
||||
x = Wire.read();
|
||||
return x;
|
||||
}
|
||||
void Touch_GT911::writeBlockData(uint16_t reg, uint8_t *val, uint8_t size) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
// Wire.write(val, size);
|
||||
for (uint8_t i=0; i<size; i++) {
|
||||
Wire.write(val[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
}
|
||||
void Touch_GT911::readBlockData(uint8_t *buf, uint16_t reg, uint8_t size) {
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(highByte(reg));
|
||||
Wire.write(lowByte(reg));
|
||||
Wire.endTransmission();
|
||||
Wire.requestFrom(addr, size);
|
||||
for (uint8_t i=0; i<size; i++) {
|
||||
buf[i] = Wire.read();
|
||||
}
|
||||
}
|
||||
|
||||
116
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.h
Normal file
116
ESP32_AP-Flasher/lib2/gt911-touch/src/Touch_GT911.h
Normal file
@@ -0,0 +1,116 @@
|
||||
|
||||
#ifndef Touch_GT911_H
|
||||
#define Touch_GT911_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#define GT911_ADDR1 (uint8_t)0x5D
|
||||
#define GT911_ADDR2 (uint8_t)0x14
|
||||
|
||||
// Real-time command (Write only)
|
||||
#define GT911_COMMAND (uint16_t)0x8040
|
||||
#define GT911_ESD_CHECK (uint16_t)0x8041
|
||||
#define GT911_COMMAND_CHECK (uint16_t)0x8046
|
||||
|
||||
#define GT911_STRETCH_R0 (uint16_t)0x805E
|
||||
#define GT911_STRETCH_R1 (uint16_t)0x805F
|
||||
#define GT911_STRETCH_R2 (uint16_t)0x8060
|
||||
#define GT911_STRETCH_RM (uint16_t)0x8061
|
||||
#define GT911_DRV_GROUPA_NUM (uint16_t)0x8062
|
||||
#define GT911_CONFIG_START (uint16_t)0x8047
|
||||
#define GT911_CONFIG_VERSION (uint16_t)0x8047
|
||||
#define GT911_X_OUTPUT_MAX_LOW (uint16_t)0x8048
|
||||
#define GT911_X_OUTPUT_MAX_HIGH (uint16_t)0x8049
|
||||
#define GT911_Y_OUTPUT_MAX_LOW (uint16_t)0x804A
|
||||
#define GT911_Y_OUTPUT_MAX_HIGH (uint16_t)0x804B
|
||||
#define GT911_TOUCH_NUMBER (uint16_t)0x804C
|
||||
#define GT911_MODULE_SWITCH_1 (uint16_t)0x804D
|
||||
#define GT911_MODULE_SWITCH_2 (uint16_t)0x804E
|
||||
#define GT911_SHAKE_COUNT (uint16_t)0x804F
|
||||
#define GT911_FILTER (uint16_t)0x8050
|
||||
#define GT911_LARGE_TOUCH (uint16_t)0x8051
|
||||
#define GT911_NOISE_REDUCTION (uint16_t)0x8052
|
||||
#define GT911_SCREEN_TOUCH_LEVEL (uint16_t)0x8053
|
||||
#define GT911_SCREEN_RELEASE_LEVEL (uint16_t)0x8054
|
||||
#define GT911_LOW_POWER_CONTROL (uint16_t)0x8055
|
||||
#define GT911_REFRESH_RATE (uint16_t)0x8056
|
||||
#define GT911_X_THRESHOLD (uint16_t)0x8057
|
||||
#define GT911_Y_THRESHOLD (uint16_t)0x8058
|
||||
#define GT911_SPACE_TOP_BOTTOM (uint16_t)0x805B
|
||||
#define GT911_PANEL_TX_GAIN (uint16_t)0x806B
|
||||
#define GT911_PANEL_RX_GAIN (uint16_t)0x806C
|
||||
#define GT911_PANEL_DUMP_SHIFT (uint16_t)0x806D
|
||||
#define GT911_DRV_FRAME_CONTROL (uint16_t)0x806E
|
||||
#define GT911_CHARGING_LEVEL_UP (uint16_t)0x806F
|
||||
#define GT911_MODULE_SWITCH3 (uint16_t)0x8070
|
||||
#define GT911_GESTURE_DIS (uint16_t)0X8071
|
||||
#define GT911_GESTURE_LONG_PRESS_TIME (uint16_t)0x8072
|
||||
#define GT911_X_Y_SLOPE_ADJUST (uint16_t)0X8073
|
||||
#define GT911_GESTURE_CONTROL (uint16_t)0X8074
|
||||
#define GT911_GESTURE_SWITCH1 (uint16_t)0X8075
|
||||
#define GT911_GESTURE_SWITCH2 (uint16_t)0X8076
|
||||
#define GT911_GESTURE_REFRESH_RATE (uint16_t)0x8077
|
||||
#define GT911_GESTURE_TOUCH_LEVEL (uint16_t)0x8078
|
||||
#define GT911_NEWGREENWAKEUPLEVEL (uint16_t)0x8079
|
||||
#define GT911_FREQ_HOPPING_START (uint16_t)0x807A
|
||||
#define GT911_CONFIG_CHKSUM (uint16_t)0X80FF
|
||||
#define GT911_CONFIG_FRESH (uint16_t)0X8100
|
||||
#define GT911_CONFIG_SIZE (uint16_t)0xFF-0x46
|
||||
// Coordinate information
|
||||
#define GT911_PRODUCT_ID (uint16_t)0X8140
|
||||
#define GT911_FIRMWARE_VERSION (uint16_t)0X8140
|
||||
#define GT911_RESOLUTION (uint16_t)0X8140
|
||||
#define GT911_VENDOR_ID (uint16_t)0X8140
|
||||
#define GT911_IMFORMATION (uint16_t)0X8140
|
||||
#define GT911_POINT_INFO (uint16_t)0X814E
|
||||
#define GT911_POINT_1 (uint16_t)0X814F
|
||||
#define GT911_POINT_2 (uint16_t)0X8157
|
||||
#define GT911_POINT_3 (uint16_t)0X815F
|
||||
#define GT911_POINT_4 (uint16_t)0X8167
|
||||
#define GT911_POINT_5 (uint16_t)0X816F
|
||||
#define GT911_POINTS_REG {GT911_POINT_1, GT911_POINT_2, GT911_POINT_3, GT911_POINT_4, GT911_POINT_5}
|
||||
|
||||
class TPoint {
|
||||
public:
|
||||
TPoint(void);
|
||||
TPoint(uint8_t id, uint16_t x, uint16_t y, uint16_t size);
|
||||
|
||||
bool operator==(TPoint);
|
||||
bool operator!=(TPoint);
|
||||
|
||||
uint8_t id;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint8_t size;
|
||||
};
|
||||
|
||||
class Touch_GT911 {
|
||||
public:
|
||||
Touch_GT911(uint8_t _sda, uint8_t _scl,uint16_t _width, uint16_t _height);
|
||||
void begin(uint8_t _addr=GT911_ADDR1);
|
||||
void setRotation(uint8_t rot);
|
||||
void setResolution(uint16_t _width, uint16_t _height);
|
||||
uint8_t getGesture(void);
|
||||
void read(void);
|
||||
uint8_t isLargeDetect;
|
||||
uint8_t touches = 0;
|
||||
bool isTouched = false;
|
||||
TPoint points[5];
|
||||
private:
|
||||
void calculateChecksum();
|
||||
void reConfig();
|
||||
TPoint readPoint(uint8_t *data);
|
||||
void writeByteData(uint16_t reg, uint8_t val);
|
||||
uint8_t readByteData(uint16_t reg);
|
||||
void writeBlockData(uint16_t reg, uint8_t *val, uint8_t size);
|
||||
void readBlockData(uint8_t *buf, uint16_t reg, uint8_t size);
|
||||
uint8_t addr;
|
||||
uint8_t pinSda;
|
||||
uint8_t pinScl;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t configBuf[GT911_CONFIG_SIZE];
|
||||
};
|
||||
|
||||
#endif // Touch_GT911_H
|
||||
File diff suppressed because it is too large
Load Diff
23
ESP32_AP-Flasher/prepare_sdcard.sh
Executable file
23
ESP32_AP-Flasher/prepare_sdcard.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
if [[ -d $1 ]]; then
|
||||
rm -rf $1/*
|
||||
cp -r data/* $1
|
||||
rm $1/www/*
|
||||
cp -r wwwroot/* $1/www/
|
||||
cp ../binaries/ESP32-C6/firmware.json $1
|
||||
for f in bootloader partition-table OpenEPaperLink_esp32_C6
|
||||
do
|
||||
if [[ -e ../ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/${f}.bin ]]; then
|
||||
cp ../ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/${f}.bin $1
|
||||
else
|
||||
cp ../binaries/ESP32-C6/${f}.bin $1
|
||||
fi
|
||||
done
|
||||
mkdir $1/current
|
||||
echo "[[]]" > $1/current/tagDB.json
|
||||
echo "OK"
|
||||
else
|
||||
echo "$1 is not a directory"
|
||||
exit 1
|
||||
fi
|
||||
@@ -8,7 +8,7 @@ SPIFFSEditor::SPIFFSEditor(const fs::FS &fs, const String &username, const Strin
|
||||
: _fs(fs), _username(username), _password(password), _authenticated(false), _startTime(0) {
|
||||
}
|
||||
|
||||
bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) {
|
||||
bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) const {
|
||||
if (request->url().equalsIgnoreCase("/edit")) {
|
||||
if (request->method() == HTTP_GET) {
|
||||
if (request->hasParam("list")) {
|
||||
@@ -34,7 +34,6 @@ bool SPIFFSEditor::canHandle(AsyncWebServerRequest *request) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
request->addInterestingHeader("If-Modified-Since");
|
||||
return true;
|
||||
} else if (request->method() == HTTP_POST || request->method() == HTTP_DELETE || request->method() == HTTP_PUT) {
|
||||
return true;
|
||||
@@ -91,7 +90,7 @@ void SPIFFSEditor::handleRequest(AsyncWebServerRequest *request) {
|
||||
if (request->header("If-Modified-Since").equals(buildTime)) {
|
||||
request->send(304);
|
||||
} else {
|
||||
AsyncWebServerResponse *response = request->beginResponse(_fs, "/www/edit.html");
|
||||
AsyncWebServerResponse *response = request->beginResponse(_fs, "/www/edit.html", "text/html");
|
||||
response->addHeader("Last-Modified", buildTime);
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
@@ -64,6 +64,16 @@ uint8_t gicToOEPLtype(uint8_t gicType) {
|
||||
}
|
||||
}
|
||||
|
||||
struct BleAdvDataStruct {
|
||||
uint16_t manu_id; // 0x1337 for us
|
||||
uint8_t version;
|
||||
uint16_t hw_type;
|
||||
uint16_t fw_version;
|
||||
uint16_t capabilities;
|
||||
uint16_t battery_mv;
|
||||
uint8_t counter;
|
||||
} __packed;
|
||||
|
||||
bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) {
|
||||
Serial.print("BLE Advertised Device found: ");
|
||||
Serial.println(advertisedDevice.toString().c_str());
|
||||
@@ -85,7 +95,12 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) {
|
||||
for (int i = 0; i < advertisedDevice.getManufacturerData().length(); i++)
|
||||
Serial.printf("%02X", manuData[i]);
|
||||
Serial.printf("\r\n");
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
memcpy(&manuData, (uint8_t*)advertisedDevice.getManufacturerData().data(), manuDatalen);
|
||||
#else
|
||||
// [Nic] suggested fix for arduino 3.x by copilot, but I cannot test it
|
||||
memcpy(&manuData, (uint8_t*)advertisedDevice.getManufacturerData().c_str(), manuDatalen);
|
||||
#endif
|
||||
if (manuDatalen == 7 && manuData[0] == 0x53 && manuData[1] == 0x50) { // Lets check for a Gicisky E-Paper display
|
||||
|
||||
struct espAvailDataReq theAdvData;
|
||||
@@ -103,10 +118,46 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) {
|
||||
theAdvData.src[7] = manuData[6];
|
||||
theAdvData.adr.batteryMv = manuData[3] * 100;
|
||||
theAdvData.adr.lastPacketRSSI = advertisedDevice.getRSSI();
|
||||
theAdvData.adr.lastPacketLQI = advertisedDevice.getRSSI();
|
||||
theAdvData.adr.hwType = gicToOEPLtype(manuData[2]);
|
||||
theAdvData.adr.tagSoftwareVersion = manuData[4] << 8 | manuData[5];
|
||||
theAdvData.adr.capabilities = 0x00;
|
||||
|
||||
processDataReq(&theAdvData, true);
|
||||
return true;
|
||||
} else if (manuDatalen >= sizeof(BleAdvDataStruct) && manuData[0] == 0x37 && manuData[1] == 0x13) { // Lets check for a Gicisky E-Paper display
|
||||
Serial.printf("ATC BLE OEPL Detected\r\n");
|
||||
struct espAvailDataReq theAdvData;
|
||||
struct BleAdvDataStruct inAdvData;
|
||||
|
||||
memset((uint8_t*)&theAdvData, 0x00, sizeof(espAvailDataReq));
|
||||
memcpy(&inAdvData, manuData, sizeof(BleAdvDataStruct));
|
||||
/*Serial.printf("manu_id %04X\r\n", inAdvData.manu_id);
|
||||
Serial.printf("version %04X\r\n", inAdvData.version);
|
||||
Serial.printf("hw_type %04X\r\n", inAdvData.hw_type);
|
||||
Serial.printf("fw_version %04X\r\n", inAdvData.fw_version);
|
||||
Serial.printf("capabilities %04X\r\n", inAdvData.capabilities);
|
||||
Serial.printf("battery_mv %u\r\n", inAdvData.battery_mv);
|
||||
Serial.printf("counter %u\r\n", inAdvData.counter);*/
|
||||
if (inAdvData.version != 1) {
|
||||
printf("Version currently not supported!\r\n");
|
||||
return false;
|
||||
}
|
||||
uint8_t macReversed[6];
|
||||
memcpy(&macReversed, (uint8_t*)advertisedDevice.getAddress().getNative(), 6);
|
||||
theAdvData.src[0] = macReversed[5];
|
||||
theAdvData.src[1] = macReversed[4];
|
||||
theAdvData.src[2] = macReversed[3];
|
||||
theAdvData.src[3] = macReversed[2];
|
||||
theAdvData.src[4] = macReversed[1];
|
||||
theAdvData.src[5] = macReversed[0];
|
||||
theAdvData.src[6] = manuData[0]; // We use this do find out what type of display we got for compression^^
|
||||
theAdvData.src[7] = manuData[1];
|
||||
theAdvData.adr.batteryMv = inAdvData.battery_mv;
|
||||
theAdvData.adr.lastPacketRSSI = advertisedDevice.getRSSI();
|
||||
theAdvData.adr.hwType = inAdvData.hw_type & 0xff;
|
||||
theAdvData.adr.tagSoftwareVersion = inAdvData.fw_version;
|
||||
theAdvData.adr.capabilities = inAdvData.capabilities & 0xff;
|
||||
processDataReq(&theAdvData, true);
|
||||
return true;
|
||||
}
|
||||
@@ -133,7 +184,6 @@ bool BLE_filter_add_device(BLEAdvertisedDevice advertisedDevice) {
|
||||
theAdvData.adr.hwType = ATC_MI_THERMOMETER;
|
||||
theAdvData.adr.tagSoftwareVersion = 0x00;
|
||||
theAdvData.adr.capabilities = 0x00;
|
||||
|
||||
processDataReq(&theAdvData, true);
|
||||
Serial.printf("We got an ATC_MiThermometer via BLE\r\n");
|
||||
return true;
|
||||
@@ -150,6 +200,14 @@ bool BLE_is_image_pending(uint8_t address[8]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* taginfo = tagDB.at(c);
|
||||
if (taginfo->pendingCount > 0 && taginfo->version == 0 && (taginfo->mac[7] == 0x13) && (taginfo->mac[6] == 0x37)) {
|
||||
memcpy(address, taginfo->mac, 8);
|
||||
Serial.printf("ATC BLE OEPL data Waiting\r\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -374,4 +432,37 @@ uint32_t compress_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len) {
|
||||
return len_compressed;
|
||||
}
|
||||
|
||||
uint32_t get_ATC_BLE_OEPL_image(uint8_t address[8], uint8_t* buffer, uint32_t max_len, uint8_t* dataType, uint8_t* dataTypeArgument, uint16_t* nextCheckIn) {
|
||||
uint32_t t = millis();
|
||||
PendingItem* queueItem = getQueueItem(address, 0);
|
||||
if (queueItem == nullptr) {
|
||||
prepareCancelPending(address);
|
||||
Serial.printf("blockrequest: couldn't find taginfo %02X%02X%02X%02X%02X%02X%02X%02X\r\n", address[7], address[6], address[5], address[4], address[3], address[2], address[1], address[0]);
|
||||
return 0;
|
||||
}
|
||||
if (queueItem->data == nullptr) {
|
||||
fs::File file = contentFS->open(queueItem->filename);
|
||||
if (!file) {
|
||||
Serial.print("No current file. " + String(queueItem->filename) + " Canceling request\r\n");
|
||||
prepareCancelPending(address);
|
||||
return 0;
|
||||
}
|
||||
queueItem->data = getDataForFile(file);
|
||||
Serial.println("Reading file " + String(queueItem->filename) + " in " + String(millis() - t) + "ms");
|
||||
file.close();
|
||||
}
|
||||
if (queueItem->len > max_len) {
|
||||
Serial.print("The upload is too big better cencel it\r\n");
|
||||
prepareCancelPending(address);
|
||||
return 0;
|
||||
}
|
||||
*dataType = queueItem->pendingdata.availdatainfo.dataType;
|
||||
*dataTypeArgument = queueItem->pendingdata.availdatainfo.dataTypeArgument;
|
||||
*nextCheckIn = queueItem->pendingdata.availdatainfo.nextCheckIn;
|
||||
uint32_t len_compressed = queueItem->len;
|
||||
memcpy(buffer, queueItem->data, queueItem->len);
|
||||
Serial.print("Data is prepared Len: " + String(queueItem->len) + "\r\n");
|
||||
return queueItem->len;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#ifdef HAS_BLE_WRITER
|
||||
#include <Arduino.h>
|
||||
#include <MD5Builder.h>
|
||||
|
||||
#include "BLEDevice.h"
|
||||
#include "ble_filter.h"
|
||||
@@ -7,12 +8,13 @@
|
||||
|
||||
#define INTERVAL_BLE_SCANNING_SECONDS 60
|
||||
#define INTERVAL_HANDLE_PENDING_SECONDS 10
|
||||
#define BUFFER_MAX_SIZE_COMPRESSING 100000
|
||||
#define BUFFER_MAX_SIZE_COMPRESSING 135000
|
||||
|
||||
#define BLE_MAIN_STATE_IDLE 0
|
||||
#define BLE_MAIN_STATE_PREPARE 1
|
||||
#define BLE_MAIN_STATE_CONNECT 2
|
||||
#define BLE_MAIN_STATE_UPLOAD 3
|
||||
#define BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD 4
|
||||
|
||||
int ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
uint32_t last_ble_scan = 0;
|
||||
@@ -23,9 +25,25 @@ uint32_t last_ble_scan = 0;
|
||||
#define BLE_UPLOAD_STATE_UPLOAD 5
|
||||
int BLE_upload_state = BLE_UPLOAD_STATE_INIT;
|
||||
|
||||
#define BLE_CMD_ACK_CMD 99
|
||||
#define BLE_CMD_AVAILDATA 100
|
||||
#define BLE_CMD_BLK_DATA 101
|
||||
#define BLE_CMD_ERR_BLKPRT 196
|
||||
#define BLE_CMD_ACK_BLKPRT 197
|
||||
#define BLE_CMD_REQ 198
|
||||
#define BLE_CMD_ACK 199
|
||||
#define BLE_CMD_ACK_IS_SHOWN 200
|
||||
#define BLE_CMD_ACK_FW_UPDATED 201
|
||||
|
||||
struct AvailDataInfo BLEavaildatainfo = {0};
|
||||
struct blockRequest BLEblkRequst = {0};
|
||||
|
||||
bool BLE_connected = false;
|
||||
bool BLE_new_notify = false;
|
||||
|
||||
static BLEUUID ATC_BLE_OEPL_ServiceUUID((uint16_t)0x1337);
|
||||
static BLEUUID ATC_BLE_OEPL_CtrlUUID((uint16_t)0x1337);
|
||||
|
||||
static BLEUUID gicServiceUUID((uint16_t)0xfef0);
|
||||
static BLEUUID gicCtrlUUID((uint16_t)0xfef1);
|
||||
static BLEUUID gicImgUUID((uint16_t)0xfef2);
|
||||
@@ -33,20 +51,21 @@ static BLEUUID gicImgUUID((uint16_t)0xfef2);
|
||||
BLERemoteCharacteristic* ctrlChar;
|
||||
BLERemoteCharacteristic* imgChar;
|
||||
BLEAdvertisedDevice* myDevice;
|
||||
|
||||
BLEClient* pClient;
|
||||
|
||||
uint8_t BLE_notify_buffer[255] = {0};
|
||||
uint8_t BLE_notify_buffer[256] = {0};
|
||||
|
||||
uint32_t curr_part = 0;
|
||||
uint8_t BLE_buff[255];
|
||||
uint32_t BLE_err_counter = 0;
|
||||
uint32_t BLE_curr_part = 0;
|
||||
uint32_t BLE_max_block_parts = 0;
|
||||
uint8_t BLE_mini_buff[256];
|
||||
|
||||
uint32_t BLE_last_notify = 0;
|
||||
uint32_t BLE_last_pending_check = 0;
|
||||
uint8_t BLE_curr_address[8] = {0};
|
||||
|
||||
uint32_t compressed_len = 0;
|
||||
uint8_t* buffer;
|
||||
uint32_t BLE_compressed_len = 0;
|
||||
uint8_t* BLE_image_buffer;
|
||||
|
||||
static void notifyCallback(
|
||||
BLERemoteCharacteristic* pBLERemoteCharacteristic,
|
||||
@@ -81,7 +100,13 @@ class MyClientCallback : public BLEClientCallbacks {
|
||||
}
|
||||
};
|
||||
|
||||
bool BLE_connect(uint8_t addr[8]) {
|
||||
enum BLE_CONNECTION_TYPE {
|
||||
BLE_TYPE_GICISKY = 0,
|
||||
BLE_TYPE_ATC_BLE_OEPL
|
||||
};
|
||||
|
||||
bool BLE_connect(uint8_t addr[8], BLE_CONNECTION_TYPE conn_type) {
|
||||
BLE_err_counter = 0;
|
||||
uint8_t temp_Address[] = {addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]};
|
||||
Serial.printf("BLE Connecting to: %02X:%02X:%02X:%02X:%02X:%02X\r\n", addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
|
||||
pClient = BLEDevice::createClient();
|
||||
@@ -92,25 +117,27 @@ bool BLE_connect(uint8_t addr[8]) {
|
||||
return false;
|
||||
}
|
||||
uint32_t timeStart = millis();
|
||||
while (millis() - timeStart <= 5000) {// We wait for a few seconds as otherwise the connection might not be ready!
|
||||
while (millis() - timeStart <= 5000) { // We wait for a few seconds as otherwise the connection might not be ready!
|
||||
delay(100);
|
||||
}
|
||||
if (!BLE_connected)
|
||||
return false;
|
||||
Serial.printf("BLE starting to get service\r\n");
|
||||
BLERemoteService* pRemoteService = pClient->getService(gicServiceUUID);
|
||||
BLERemoteService* pRemoteService = pClient->getService((conn_type == BLE_TYPE_GICISKY) ? gicServiceUUID : ATC_BLE_OEPL_ServiceUUID);
|
||||
if (pRemoteService == nullptr) {
|
||||
Serial.printf("BLE Service failed\r\n");
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
imgChar = pRemoteService->getCharacteristic(gicImgUUID);
|
||||
if (imgChar == nullptr) {
|
||||
Serial.printf("BLE IMG Char failed\r\n");
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
if (conn_type == BLE_TYPE_GICISKY) {
|
||||
imgChar = pRemoteService->getCharacteristic(gicImgUUID);
|
||||
if (imgChar == nullptr) {
|
||||
Serial.printf("BLE IMG Char failed\r\n");
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ctrlChar = pRemoteService->getCharacteristic(gicCtrlUUID);
|
||||
ctrlChar = pRemoteService->getCharacteristic((conn_type == BLE_TYPE_GICISKY) ? gicCtrlUUID : ATC_BLE_OEPL_CtrlUUID);
|
||||
if (ctrlChar == nullptr) {
|
||||
Serial.printf("BLE ctrl Char failed\r\n");
|
||||
pClient->disconnect();
|
||||
@@ -147,6 +174,49 @@ void BLE_startScan(uint32_t timeout) {
|
||||
pBLEScan->start(timeout, false);
|
||||
}
|
||||
|
||||
#define BLOCK_DATA_SIZE_BLE 4096
|
||||
#define BLOCK_PART_DATA_SIZE_BLE 230
|
||||
uint8_t tempBlockBuffer[BLOCK_DATA_SIZE_BLE + 4];
|
||||
uint8_t tempPacketBuffer[2 + 3 + BLOCK_PART_DATA_SIZE_BLE];
|
||||
void ATC_BLE_OEPL_PrepareBlk(uint8_t indexBlockId) {
|
||||
if (BLE_image_buffer == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint32_t bufferPosition = (BLOCK_DATA_SIZE_BLE * indexBlockId);
|
||||
uint32_t lenNow = BLOCK_DATA_SIZE_BLE;
|
||||
uint16_t crcCalc = 0;
|
||||
if ((BLE_compressed_len - bufferPosition) < BLOCK_DATA_SIZE_BLE)
|
||||
lenNow = (BLE_compressed_len - bufferPosition);
|
||||
tempBlockBuffer[0] = lenNow & 0xff;
|
||||
tempBlockBuffer[1] = (lenNow >> 8) & 0xff;
|
||||
for (uint16_t c = 0; c < lenNow; c++) {
|
||||
tempBlockBuffer[4 + c] = BLE_image_buffer[c + bufferPosition];
|
||||
crcCalc += tempBlockBuffer[4 + c];
|
||||
}
|
||||
tempBlockBuffer[2] = crcCalc & 0xff;
|
||||
tempBlockBuffer[3] = (crcCalc >> 8) & 0xff;
|
||||
BLE_max_block_parts = (4 + lenNow) / BLOCK_PART_DATA_SIZE_BLE;
|
||||
if ((4 + lenNow) % BLOCK_PART_DATA_SIZE_BLE)
|
||||
BLE_max_block_parts++;
|
||||
Serial.println("Preparing block: " + String(indexBlockId) + " BuffPos: " + String(bufferPosition) + " LenNow: " + String(lenNow) + " MaxBLEparts: " + String(BLE_max_block_parts));
|
||||
BLE_curr_part = 0;
|
||||
}
|
||||
|
||||
void ATC_BLE_OEPL_SendPart(uint8_t indexBlockId, uint8_t indexPkt) {
|
||||
uint8_t crcCalc = indexBlockId + indexPkt;
|
||||
for (uint16_t c = 0; c < BLOCK_PART_DATA_SIZE_BLE; c++) {
|
||||
tempPacketBuffer[5 + c] = tempBlockBuffer[c + (BLOCK_PART_DATA_SIZE_BLE * indexPkt)];
|
||||
crcCalc += tempPacketBuffer[5 + c];
|
||||
}
|
||||
tempPacketBuffer[0] = 0x00;
|
||||
tempPacketBuffer[1] = 0x65;
|
||||
tempPacketBuffer[2] = crcCalc;
|
||||
tempPacketBuffer[3] = indexBlockId;
|
||||
tempPacketBuffer[4] = indexPkt;
|
||||
Serial.println("BLE Sending packet Len " + String(sizeof(tempPacketBuffer)));
|
||||
ctrlChar->writeValue(tempPacketBuffer, sizeof(tempPacketBuffer), true);
|
||||
}
|
||||
|
||||
void BLETask(void* parameter) {
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
Serial.println("BLE task started");
|
||||
@@ -162,25 +232,79 @@ void BLETask(void* parameter) {
|
||||
}
|
||||
if (millis() - BLE_last_pending_check >= (INTERVAL_HANDLE_PENDING_SECONDS * 1000)) {
|
||||
if (BLE_is_image_pending(BLE_curr_address)) {
|
||||
delay(4000); // We better wait here, since the pending image needs to be created first
|
||||
Serial.println("BLE Image is pending");
|
||||
// Here we create the compressed buffer
|
||||
buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING);
|
||||
if (buffer == nullptr) {
|
||||
Serial.println("BLE Could not create buffer!");
|
||||
compressed_len = 0;
|
||||
} else {
|
||||
compressed_len = compress_image(BLE_curr_address, buffer, BUFFER_MAX_SIZE_COMPRESSING);
|
||||
Serial.printf("BLE Compressed Length: %i\r\n", compressed_len);
|
||||
// then we connect to BLE to send the compressed data
|
||||
if (compressed_len && BLE_connect(BLE_curr_address)) {
|
||||
curr_part = 0;
|
||||
memset(BLE_notify_buffer, 0x00, sizeof(BLE_notify_buffer));
|
||||
BLE_upload_state = BLE_UPLOAD_STATE_INIT;
|
||||
ble_main_state = BLE_MAIN_STATE_UPLOAD;
|
||||
BLE_new_notify = true; // trigger the upload here
|
||||
Serial.println("BLE Image is pending but we wait a bit");
|
||||
delay(5000); // We better wait here, since the pending image needs to be created first
|
||||
if (BLE_curr_address[7] == 0x13 && BLE_curr_address[6] == 0x37) { // This is an ATC BLE OEPL display
|
||||
// Here we create the compressed buffer
|
||||
BLE_image_buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING);
|
||||
if (BLE_image_buffer == nullptr) {
|
||||
Serial.println("BLE Could not create buffer!");
|
||||
BLE_compressed_len = 0;
|
||||
} else {
|
||||
free(buffer);
|
||||
uint8_t dataType = 0x00;
|
||||
uint8_t dataTypeArgument = 0x00;
|
||||
uint16_t nextCheckin = 0x00;
|
||||
BLE_compressed_len = get_ATC_BLE_OEPL_image(BLE_curr_address, BLE_image_buffer, BUFFER_MAX_SIZE_COMPRESSING, &dataType, &dataTypeArgument, &nextCheckin);
|
||||
Serial.printf("BLE data Length: %i\r\n", BLE_compressed_len);
|
||||
// then we connect to BLE to send the compressed data
|
||||
if (BLE_compressed_len && BLE_connect(BLE_curr_address, BLE_TYPE_ATC_BLE_OEPL)) {
|
||||
BLE_err_counter = 0;
|
||||
BLE_curr_part = 0;
|
||||
memset(BLE_notify_buffer, 0x00, sizeof(BLE_notify_buffer));
|
||||
|
||||
uint8_t md5bytes[16];
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
md5.add(BLE_image_buffer, BLE_compressed_len);
|
||||
md5.calculate();
|
||||
md5.getBytes(md5bytes);
|
||||
|
||||
BLEavaildatainfo.dataType = dataType;
|
||||
BLEavaildatainfo.dataVer = *((uint64_t*)md5bytes);
|
||||
BLEavaildatainfo.dataSize = BLE_compressed_len;
|
||||
BLEavaildatainfo.dataTypeArgument = dataTypeArgument;
|
||||
BLEavaildatainfo.nextCheckIn = nextCheckin;
|
||||
BLEavaildatainfo.checksum = 0;
|
||||
for (uint16_t c = 1; c < sizeof(struct AvailDataInfo); c++) {
|
||||
BLEavaildatainfo.checksum += (uint8_t)((uint8_t*)&BLEavaildatainfo)[c];
|
||||
}
|
||||
BLE_upload_state = BLE_UPLOAD_STATE_INIT;
|
||||
ble_main_state = BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD;
|
||||
BLE_new_notify = true; // trigger the upload here
|
||||
} else {
|
||||
free(BLE_image_buffer);
|
||||
if (BLE_err_counter++ >= 5) { // 5 Retries for a BLE Connection
|
||||
struct espXferComplete reportStruct;
|
||||
memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8);
|
||||
processXferComplete(&reportStruct, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else { // This is a Gicisky display
|
||||
// Here we create the compressed buffer
|
||||
BLE_image_buffer = (uint8_t*)malloc(BUFFER_MAX_SIZE_COMPRESSING);
|
||||
if (BLE_image_buffer == nullptr) {
|
||||
Serial.println("BLE Could not create buffer!");
|
||||
BLE_compressed_len = 0;
|
||||
} else {
|
||||
BLE_compressed_len = compress_image(BLE_curr_address, BLE_image_buffer, BUFFER_MAX_SIZE_COMPRESSING);
|
||||
Serial.printf("BLE Compressed Length: %i\r\n", BLE_compressed_len);
|
||||
// then we connect to BLE to send the compressed data
|
||||
if (BLE_compressed_len && BLE_connect(BLE_curr_address, BLE_TYPE_GICISKY)) {
|
||||
BLE_err_counter = 0;
|
||||
BLE_curr_part = 0;
|
||||
memset(BLE_notify_buffer, 0x00, sizeof(BLE_notify_buffer));
|
||||
BLE_upload_state = BLE_UPLOAD_STATE_INIT;
|
||||
ble_main_state = BLE_MAIN_STATE_UPLOAD;
|
||||
BLE_new_notify = true; // trigger the upload here
|
||||
} else {
|
||||
free(BLE_image_buffer);
|
||||
if (BLE_err_counter++ >= 5) { // 5 Retries for a BLE Connection
|
||||
struct espXferComplete reportStruct;
|
||||
memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8);
|
||||
processXferComplete(&reportStruct, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BLE_last_pending_check = millis();
|
||||
@@ -196,25 +320,25 @@ void BLETask(void* parameter) {
|
||||
switch (BLE_upload_state) {
|
||||
default:
|
||||
case BLE_UPLOAD_STATE_INIT:
|
||||
BLE_buff[0] = 1;
|
||||
ctrlChar->writeValue(BLE_buff, 1);
|
||||
BLE_mini_buff[0] = 1;
|
||||
ctrlChar->writeValue(BLE_mini_buff, 1);
|
||||
break;
|
||||
case BLE_UPLOAD_STATE_SIZE:
|
||||
BLE_buff[0] = 0x02;
|
||||
BLE_buff[1] = compressed_len & 0xff;
|
||||
BLE_buff[2] = (compressed_len >> 8) & 0xff;
|
||||
BLE_buff[3] = (compressed_len >> 16) & 0xff;
|
||||
BLE_buff[4] = (compressed_len >> 24) & 0xff;
|
||||
BLE_buff[5] = 0x00;
|
||||
ctrlChar->writeValue(BLE_buff, 6);
|
||||
BLE_mini_buff[0] = 0x02;
|
||||
BLE_mini_buff[1] = BLE_compressed_len & 0xff;
|
||||
BLE_mini_buff[2] = (BLE_compressed_len >> 8) & 0xff;
|
||||
BLE_mini_buff[3] = (BLE_compressed_len >> 16) & 0xff;
|
||||
BLE_mini_buff[4] = (BLE_compressed_len >> 24) & 0xff;
|
||||
BLE_mini_buff[5] = 0x00;
|
||||
ctrlChar->writeValue(BLE_mini_buff, 6);
|
||||
break;
|
||||
case BLE_UPLOAD_STATE_START:
|
||||
BLE_buff[0] = 0x03;
|
||||
ctrlChar->writeValue(BLE_buff, 1);
|
||||
BLE_mini_buff[0] = 0x03;
|
||||
ctrlChar->writeValue(BLE_mini_buff, 1);
|
||||
break;
|
||||
case BLE_UPLOAD_STATE_UPLOAD:
|
||||
if (BLE_notify_buffer[2] == 0x08) {
|
||||
free(buffer);
|
||||
free(BLE_image_buffer);
|
||||
pClient->disconnect();
|
||||
ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
BLE_last_pending_check = millis();
|
||||
@@ -222,35 +346,103 @@ void BLETask(void* parameter) {
|
||||
struct espXferComplete reportStruct;
|
||||
memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8);
|
||||
processXferComplete(&reportStruct, true);
|
||||
curr_part = 0;
|
||||
BLE_err_counter = 0;
|
||||
BLE_curr_part = 0;
|
||||
} else {
|
||||
uint32_t req_curr_part = (BLE_notify_buffer[6] << 24) | (BLE_notify_buffer[5] << 24) | (BLE_notify_buffer[4] << 24) | BLE_notify_buffer[3];
|
||||
if (req_curr_part != curr_part) {
|
||||
Serial.printf("Something went wrong, expected req part: %i but got: %i we better abort here.\r\n", req_curr_part, curr_part);
|
||||
free(buffer);
|
||||
if (req_curr_part != BLE_curr_part) {
|
||||
Serial.printf("Something went wrong, expected req part: %i but got: %i we better abort here.\r\n", req_curr_part, BLE_curr_part);
|
||||
free(BLE_image_buffer);
|
||||
pClient->disconnect();
|
||||
ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
BLE_last_pending_check = millis();
|
||||
}
|
||||
uint32_t curr_len = 240;
|
||||
if (compressed_len - (curr_part * 240) < 240)
|
||||
curr_len = compressed_len - (curr_part * 240);
|
||||
BLE_buff[0] = curr_part & 0xff;
|
||||
BLE_buff[1] = (curr_part >> 8) & 0xff;
|
||||
BLE_buff[2] = (curr_part >> 16) & 0xff;
|
||||
BLE_buff[3] = (curr_part >> 24) & 0xff;
|
||||
memcpy((uint8_t*)&BLE_buff[4], (uint8_t*)&buffer[curr_part * 240], curr_len);
|
||||
imgChar->writeValue(BLE_buff, curr_len + 4);
|
||||
Serial.printf("BLE sending part: %i\r\n", curr_part);
|
||||
curr_part++;
|
||||
if (BLE_compressed_len - (BLE_curr_part * 240) < 240)
|
||||
curr_len = BLE_compressed_len - (BLE_curr_part * 240);
|
||||
BLE_mini_buff[0] = BLE_curr_part & 0xff;
|
||||
BLE_mini_buff[1] = (BLE_curr_part >> 8) & 0xff;
|
||||
BLE_mini_buff[2] = (BLE_curr_part >> 16) & 0xff;
|
||||
BLE_mini_buff[3] = (BLE_curr_part >> 24) & 0xff;
|
||||
memcpy((uint8_t*)&BLE_mini_buff[4], (uint8_t*)&BLE_image_buffer[BLE_curr_part * 240], curr_len);
|
||||
imgChar->writeValue(BLE_mini_buff, curr_len + 4);
|
||||
Serial.printf("BLE sending part: %i\r\n", BLE_curr_part);
|
||||
BLE_curr_part++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (millis() - BLE_last_notify > 30000) { // Something odd, better reset connection!
|
||||
Serial.println("BLE err going back to IDLE");
|
||||
free(buffer);
|
||||
free(BLE_image_buffer);
|
||||
pClient->disconnect();
|
||||
BLE_err_counter = 0;
|
||||
ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
BLE_last_pending_check = millis();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BLE_MAIN_STATE_ATC_BLE_OEPL_UPLOAD: {
|
||||
if (BLE_connected && BLE_new_notify) {
|
||||
BLE_new_notify = false;
|
||||
BLE_last_notify = millis();
|
||||
switch (BLE_upload_state) {
|
||||
default:
|
||||
case BLE_UPLOAD_STATE_INIT:
|
||||
BLE_mini_buff[0] = 0x00;
|
||||
BLE_mini_buff[1] = 0x64;
|
||||
memcpy((uint8_t*)&BLE_mini_buff[2], &BLEavaildatainfo, sizeof(struct AvailDataInfo));
|
||||
ctrlChar->writeValue(BLE_mini_buff, sizeof(struct AvailDataInfo) + 2);
|
||||
BLE_upload_state = BLE_UPLOAD_STATE_UPLOAD;
|
||||
break;
|
||||
case BLE_UPLOAD_STATE_UPLOAD: {
|
||||
uint8_t notifyLen = BLE_notify_buffer[0];
|
||||
uint16_t notifyCMD = (BLE_notify_buffer[1] << 8) | BLE_notify_buffer[2];
|
||||
Serial.println("BLE CMD " + String(notifyCMD));
|
||||
switch (notifyCMD) {
|
||||
case BLE_CMD_REQ:
|
||||
if (notifyLen == (sizeof(struct blockRequest) + 2)) {
|
||||
Serial.println("We got a request for a BLK");
|
||||
memcpy(&BLEblkRequst, &BLE_notify_buffer[3], sizeof(struct blockRequest));
|
||||
BLE_curr_part = 0;
|
||||
ATC_BLE_OEPL_PrepareBlk(BLEblkRequst.blockId);
|
||||
ATC_BLE_OEPL_SendPart(BLEblkRequst.blockId, BLE_curr_part);
|
||||
}
|
||||
break;
|
||||
case BLE_CMD_ACK_BLKPRT:
|
||||
BLE_curr_part++;
|
||||
BLE_err_counter = 0;
|
||||
case BLE_CMD_ERR_BLKPRT:
|
||||
if (BLE_curr_part <= BLE_max_block_parts && BLE_err_counter++ < 15) {
|
||||
ATC_BLE_OEPL_SendPart(BLEblkRequst.blockId, BLE_curr_part);
|
||||
break;
|
||||
} // FALLTROUGH!!! We cancel the upload if we land here since we dont have so many parts of a block!
|
||||
case BLE_CMD_ACK:
|
||||
case BLE_CMD_ACK_IS_SHOWN:
|
||||
case BLE_CMD_ACK_FW_UPDATED:
|
||||
Serial.println("BLE Upload done");
|
||||
free(BLE_image_buffer);
|
||||
pClient->disconnect();
|
||||
ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
BLE_last_pending_check = millis();
|
||||
// Done and the image is refreshing now
|
||||
struct espXferComplete reportStruct;
|
||||
memcpy((uint8_t*)&reportStruct.src, BLE_curr_address, 8);
|
||||
processXferComplete(&reportStruct, true);
|
||||
BLE_err_counter = 0;
|
||||
BLE_max_block_parts = 0;
|
||||
BLE_curr_part = 0;
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} else {
|
||||
if (millis() - BLE_last_notify > 30000) { // Something odd, better reset connection!
|
||||
Serial.println("BLE err going back to IDLE");
|
||||
free(BLE_image_buffer);
|
||||
pClient->disconnect();
|
||||
BLE_err_counter = 0;
|
||||
ble_main_state = BLE_MAIN_STATE_IDLE;
|
||||
BLE_last_pending_check = millis();
|
||||
}
|
||||
|
||||
397
ESP32_AP-Flasher/src/cc_interface.cpp
Executable file
397
ESP32_AP-Flasher/src/cc_interface.cpp
Executable file
@@ -0,0 +1,397 @@
|
||||
#include <Arduino.h>
|
||||
#include "cc_interface.h"
|
||||
|
||||
uint16_t CC_interface::begin(uint8_t CC, uint8_t DD, uint8_t RESET)
|
||||
{
|
||||
_CC_PIN = CC;
|
||||
_DD_PIN = DD;
|
||||
_RESET_PIN = RESET;
|
||||
|
||||
pinMode(_CC_PIN, OUTPUT);
|
||||
pinMode(_DD_PIN, OUTPUT);
|
||||
pinMode(_RESET_PIN, OUTPUT);
|
||||
digitalWrite(_CC_PIN, LOW);
|
||||
digitalWrite(_DD_PIN, HIGH);
|
||||
digitalWrite(_RESET_PIN, HIGH);
|
||||
|
||||
enable_cc_debug();
|
||||
uint16_t device_id_answer = send_cc_cmd(0x68);
|
||||
opcode(0x00); // NOP
|
||||
clock_init(); // Even with failed clock init return the device id, because if the device is locked setting clock will fail
|
||||
return device_id_answer;
|
||||
}
|
||||
|
||||
void CC_interface::set_callback(callbackPtr callBack)
|
||||
{
|
||||
_callback = callBack;
|
||||
}
|
||||
|
||||
uint8_t CC_interface::set_lock_byte(uint8_t lock_byte)
|
||||
{
|
||||
lock_byte = lock_byte & 0x1f; // Max lock byte value
|
||||
WR_CONFIG(0x01); // Select flash info Page
|
||||
opcode(0x00); // NOP
|
||||
|
||||
opcode(0xE5, 0x92);
|
||||
opcode(0x75, 0x92, 0x00);
|
||||
opcode(0xE5, 0x83);
|
||||
opcode(0xE5, 0x82);
|
||||
opcode(0x90, 0xF0, 0x00);
|
||||
opcode(0x74, 0xFF);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, lock_byte); // Transmit the set lock byte
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x90, 0x00, 0x00);
|
||||
opcode(0x75, 0x92, 0x00);
|
||||
opcode(0x74, 0x00);
|
||||
|
||||
opcode(0x00); // NOP
|
||||
|
||||
opcode(0xE5, 0x92);
|
||||
opcode(0x75, 0x92, 0x00);
|
||||
opcode(0xE5, 0x83);
|
||||
opcode(0xE5, 0x82);
|
||||
opcode(0x90, 0xF8, 0x00);
|
||||
opcode(0x74, 0xF0);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0x00);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0xDF);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0xAF);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0x00);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0x02);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0x12);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x74, 0x4A);
|
||||
opcode(0xF0);
|
||||
opcode(0xA3); // Increase Pointer
|
||||
opcode(0x90, 0x00, 0x00);
|
||||
opcode(0x75, 0x92, 0x00);
|
||||
opcode(0x74, 0x00);
|
||||
|
||||
opcode(0x00); // NOP
|
||||
|
||||
opcode(0xE5, 0xC6);
|
||||
opcode(0x74, 0x00);
|
||||
opcode(0x75, 0xAB, 0x23);
|
||||
opcode(0x75, 0xD5, 0xF8);
|
||||
opcode(0x75, 0xD4, 0x00);
|
||||
opcode(0x75, 0xD6, 0x01);
|
||||
opcode(0x75, 0xAD, 0x00);
|
||||
opcode(0x75, 0xAC, 0x00);
|
||||
opcode(0x75, 0xAE, 0x02);
|
||||
|
||||
opcode(0x00); // NOP
|
||||
|
||||
opcode(0xE5, 0xAE);
|
||||
opcode(0x74, 0x00);
|
||||
|
||||
return WR_CONFIG(0x00); // Select normal flash page
|
||||
}
|
||||
|
||||
uint8_t CC_interface::erase_chip()
|
||||
{
|
||||
opcode(0x00); // NOP
|
||||
send_cc_cmdS(0x14);
|
||||
int timeout = millis() + 100;
|
||||
while (!(send_cc_cmdS(0x34) & 0x80))
|
||||
{
|
||||
if (millis() > timeout)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CC_interface::read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[])
|
||||
{
|
||||
int last_callback = 0;
|
||||
opcode(0x75, 0xc7, 0x01);
|
||||
opcode(0x90, address >> 8, address);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
opcode(0xe4);
|
||||
buffer[i] = opcode(0x93);
|
||||
opcode(0xa3);
|
||||
if (i - last_callback > 100)
|
||||
{
|
||||
last_callback = i;
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
uint8_t percent = ((float)((float)i / (float)len) * 100.0);
|
||||
if (percent < 0)
|
||||
percent = 0;
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
_callback(percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_callback != nullptr)
|
||||
_callback(100);
|
||||
}
|
||||
|
||||
void CC_interface::read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[])
|
||||
{
|
||||
opcode(0x90, address >> 8, address);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
buffer[i] = opcode(0xe0);
|
||||
opcode(0xa3);
|
||||
}
|
||||
}
|
||||
|
||||
void CC_interface::write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[])
|
||||
{
|
||||
opcode(0x90, address >> 8, address);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
opcode(0x74, buffer[i]);
|
||||
opcode(0xf0);
|
||||
opcode(0xa3);
|
||||
}
|
||||
}
|
||||
|
||||
void CC_interface::set_pc(uint16_t address)
|
||||
{
|
||||
opcode(0x02, address >> 8, address);
|
||||
}
|
||||
|
||||
uint8_t CC_interface::clock_init()
|
||||
{
|
||||
opcode(0x75, 0xc6, 0x00);
|
||||
int timeout = millis() + 100;
|
||||
while (!(opcode(0xe5, 0xbe) & 0x40))
|
||||
{
|
||||
if (millis() > timeout)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t CC_interface::write_code_memory(uint16_t address, uint8_t buffer[], int len)
|
||||
{
|
||||
int entry_len = len;
|
||||
if (len % 2 != 0)
|
||||
len++;
|
||||
int position = 0;
|
||||
int len_per_transfer = 64;
|
||||
address = address / 2;
|
||||
while (len)
|
||||
{
|
||||
flash_opcode[2] = (address >> 8) & 0xff;
|
||||
flash_opcode[5] = address & 0xff;
|
||||
flash_opcode[13] = (len > len_per_transfer) ? (len_per_transfer / 2) : (len / 2);
|
||||
write_xdata_memory(0xf000, len_per_transfer, &buffer[position]);
|
||||
write_xdata_memory(0xf100, sizeof(flash_opcode), flash_opcode);
|
||||
opcode(0x75, 0xC7, 0x51);
|
||||
set_pc(0xf100);
|
||||
send_cc_cmdS(0x4c);
|
||||
int timeout = millis() + 500;
|
||||
while (!(send_cc_cmdS(0x34) & 0x08))
|
||||
{
|
||||
if (millis() > timeout)
|
||||
{
|
||||
if (_callback != nullptr)
|
||||
_callback(0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
uint8_t percent = 100 - ((float)((float)len / (float)entry_len) * 100.0);
|
||||
if (percent < 0)
|
||||
percent = 0;
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
_callback(percent);
|
||||
}
|
||||
len -= flash_opcode[13] * 2;
|
||||
position += flash_opcode[13] * 2;
|
||||
address += flash_opcode[13];
|
||||
}
|
||||
if (_callback != nullptr)
|
||||
_callback(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t CC_interface::verify_code_memory(uint16_t address, uint8_t buffer[], int len)
|
||||
{
|
||||
int last_callback = 0;
|
||||
opcode(0x75, 0xc7, 0x01);
|
||||
opcode(0x90, address >> 8, address);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
opcode(0xe4);
|
||||
if (buffer[i] != opcode(0x93))
|
||||
{
|
||||
if (_callback != nullptr)
|
||||
_callback(0);
|
||||
return 1;
|
||||
}
|
||||
opcode(0xa3);
|
||||
if (i - last_callback > 100)
|
||||
{
|
||||
last_callback = i;
|
||||
if (_callback != nullptr)
|
||||
{
|
||||
uint8_t percent = ((float)((float)i / (float)len) * 100.0);
|
||||
if (percent < 0)
|
||||
percent = 0;
|
||||
if (percent > 100)
|
||||
percent = 100;
|
||||
_callback(percent);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_callback != nullptr)
|
||||
_callback(100);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t CC_interface::opcode(uint8_t opCode)
|
||||
{
|
||||
cc_send_byte(0x55);
|
||||
cc_send_byte(opCode);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1)
|
||||
{
|
||||
cc_send_byte(0x56);
|
||||
cc_send_byte(opCode);
|
||||
cc_send_byte(opCode1);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2)
|
||||
{
|
||||
cc_send_byte(0x57);
|
||||
cc_send_byte(opCode);
|
||||
cc_send_byte(opCode1);
|
||||
cc_send_byte(opCode2);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint8_t CC_interface::WR_CONFIG(uint8_t config)
|
||||
{
|
||||
cc_send_byte(0x1d);
|
||||
cc_send_byte(config);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint8_t CC_interface::WD_CONFIG()
|
||||
{
|
||||
cc_send_byte(0x24);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint8_t CC_interface::send_cc_cmdS(uint8_t cmd)
|
||||
{
|
||||
cc_send_byte(cmd);
|
||||
return cc_receive_byte();
|
||||
}
|
||||
|
||||
uint16_t CC_interface::send_cc_cmd(uint8_t cmd)
|
||||
{
|
||||
cc_send_byte(cmd);
|
||||
return (cc_receive_byte() << 8) + cc_receive_byte();
|
||||
}
|
||||
|
||||
void CC_interface::cc_send_byte(uint8_t in_byte)
|
||||
{
|
||||
if (dd_direction == 1)
|
||||
{
|
||||
dd_direction = 0;
|
||||
pinMode(_DD_PIN, OUTPUT);
|
||||
digitalWrite(_DD_PIN, LOW);
|
||||
}
|
||||
for (int i = 8; i; i--)
|
||||
{
|
||||
if (in_byte & 0x80)
|
||||
digitalWrite(_DD_PIN, HIGH);
|
||||
else
|
||||
digitalWrite(_DD_PIN, LOW);
|
||||
|
||||
digitalWrite(_CC_PIN, HIGH);
|
||||
in_byte <<= 1;
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(_CC_PIN, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CC_interface::cc_receive_byte()
|
||||
{
|
||||
uint8_t out_byte = 0x00;
|
||||
if (dd_direction == 0)
|
||||
{
|
||||
dd_direction = 1;
|
||||
pinMode(_DD_PIN, INPUT);
|
||||
digitalWrite(_DD_PIN, LOW);
|
||||
}
|
||||
for (int i = 8; i; i--)
|
||||
{
|
||||
digitalWrite(_CC_PIN, HIGH);
|
||||
delayMicroseconds(5);
|
||||
out_byte <<= 1;
|
||||
if (digitalRead(_DD_PIN))
|
||||
out_byte |= 0x01;
|
||||
digitalWrite(_CC_PIN, LOW);
|
||||
delayMicroseconds(5);
|
||||
}
|
||||
return out_byte;
|
||||
}
|
||||
|
||||
void CC_interface::enable_cc_debug()
|
||||
{
|
||||
if (dd_direction == 0)
|
||||
{
|
||||
dd_direction = 1;
|
||||
pinMode(_DD_PIN, INPUT);
|
||||
digitalWrite(_DD_PIN, HIGH);
|
||||
}
|
||||
delay(5);
|
||||
digitalWrite(_RESET_PIN, LOW);
|
||||
delay(2);
|
||||
digitalWrite(_CC_PIN, HIGH);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(_CC_PIN, LOW);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(_CC_PIN, HIGH);
|
||||
delayMicroseconds(5);
|
||||
digitalWrite(_CC_PIN, LOW);
|
||||
delay(2);
|
||||
digitalWrite(_RESET_PIN, HIGH);
|
||||
delay(2);
|
||||
}
|
||||
|
||||
void CC_interface::reset_cc()
|
||||
{
|
||||
if (dd_direction == 0)
|
||||
{
|
||||
dd_direction = 1;
|
||||
pinMode(_DD_PIN, INPUT);
|
||||
digitalWrite(_DD_PIN, HIGH);
|
||||
}
|
||||
delay(5);
|
||||
digitalWrite(_RESET_PIN, LOW);
|
||||
delay(5);
|
||||
digitalWrite(_RESET_PIN, HIGH);
|
||||
delay(2);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,14 @@
|
||||
#include "storage.h"
|
||||
#include "tag_db.h"
|
||||
#include "web.h"
|
||||
#include "espflasher.h"
|
||||
#include "util.h"
|
||||
|
||||
#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__)
|
||||
|
||||
#ifndef FLASHER_DEBUG_PORT
|
||||
#define FLASHER_DEBUG_PORT 2
|
||||
#endif
|
||||
|
||||
esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate) {
|
||||
esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
|
||||
@@ -120,150 +128,197 @@ esp_loader_error_t flash_binary(String &file_path, size_t address) {
|
||||
|
||||
bool downloadAndWriteBinary(String &filename, const char *url) {
|
||||
HTTPClient binaryHttp;
|
||||
Serial.println(url);
|
||||
bool Ret = false;
|
||||
bool bHaveFsMutex = false;
|
||||
|
||||
LOG("downloadAndWriteBinary: url %s\n",url);
|
||||
binaryHttp.begin(url);
|
||||
binaryHttp.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||
int binaryResponseCode = binaryHttp.GET();
|
||||
Serial.println(binaryResponseCode);
|
||||
if (binaryResponseCode == HTTP_CODE_OK) {
|
||||
do {
|
||||
int binaryResponseCode = binaryHttp.GET();
|
||||
if(binaryResponseCode != HTTP_CODE_OK) {
|
||||
wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url));
|
||||
break;
|
||||
}
|
||||
int contentLength = binaryHttp.getSize();
|
||||
Serial.println(contentLength);
|
||||
LOG("contentLength %d\r\n",contentLength);
|
||||
if(contentLength < 0) {
|
||||
wsSerial("Couldn't get contentLength");
|
||||
break;
|
||||
}
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
bHaveFsMutex = true;
|
||||
File file = contentFS->open(filename, "wb");
|
||||
if (file) {
|
||||
wsSerial("downloading " + String(filename));
|
||||
WiFiClient *stream = binaryHttp.getStreamPtr();
|
||||
uint8_t buffer[1024];
|
||||
size_t totalBytesRead = 0;
|
||||
time_t timeOut = millis() + 5000;
|
||||
// while (stream->available()) {
|
||||
while (millis() < timeOut) {
|
||||
size_t bytesRead = stream->readBytes(buffer, sizeof(buffer));
|
||||
if(!file) {
|
||||
wsSerial("file open error " + String(filename));
|
||||
break;
|
||||
}
|
||||
wsSerial("downloading " + String(filename));
|
||||
WiFiClient *stream = binaryHttp.getStreamPtr();
|
||||
uint8_t buffer[1024];
|
||||
size_t totalBytesRead = 0;
|
||||
// timeout if we don't average at least 1k bytes/second
|
||||
unsigned long timeOut = millis() + contentLength;
|
||||
while(stream->connected() && totalBytesRead < contentLength) {
|
||||
size_t bytesRead;
|
||||
size_t bytesToRead;
|
||||
if(stream->available()) {
|
||||
bytesToRead = min(sizeof(buffer), (size_t) stream->available());
|
||||
bytesRead = stream->readBytes(buffer, bytesToRead);
|
||||
if(bytesRead == 0 || millis() > timeOut) {
|
||||
wsSerial("Download time out");
|
||||
break;
|
||||
}
|
||||
file.write(buffer, bytesRead);
|
||||
totalBytesRead += bytesRead;
|
||||
if (totalBytesRead == contentLength) break;
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
file.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
binaryHttp.end();
|
||||
|
||||
file = contentFS->open(filename, "r");
|
||||
if (file) {
|
||||
if (totalBytesRead == contentLength || (contentLength == 0 && file.size() > 0)) {
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
wsSerial("Download failed, " + String(file.size()) + " bytes");
|
||||
file.close();
|
||||
}
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
wsSerial("file open error " + String(filename));
|
||||
}
|
||||
} else {
|
||||
wsSerial("http error " + String(binaryResponseCode) + " fetching " + String(url));
|
||||
}
|
||||
file.close();
|
||||
|
||||
if(!stream->connected()) {
|
||||
wsSerial("Connection dropped during transfer");
|
||||
break;
|
||||
}
|
||||
file = contentFS->open(filename, "r");
|
||||
if(!file) {
|
||||
wsSerial("file open error " + String(filename));
|
||||
break;
|
||||
}
|
||||
if(file.size() == contentLength) {
|
||||
Ret = true;
|
||||
} else {
|
||||
wsSerial("Download failed, " + String(file.size()) + " bytes");
|
||||
}
|
||||
file.close();
|
||||
} while(false);
|
||||
binaryHttp.setReuse(false);
|
||||
binaryHttp.end();
|
||||
return false;
|
||||
if(bHaveFsMutex) {
|
||||
xSemaphoreGive(fsMutex);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
bool doC6flash(uint8_t doDownload) {
|
||||
String filenameFirmwareLocal = "/firmware.json";
|
||||
DynamicJsonDocument jsonDoc(1024);
|
||||
if (doDownload) {
|
||||
const String githubUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6/firmware.json";
|
||||
if (downloadAndWriteBinary(filenameFirmwareLocal, githubUrl.c_str())) {
|
||||
File readfile = contentFS->open(filenameFirmwareLocal, "r");
|
||||
if (!readfile) {
|
||||
Serial.println("load firmware.json: Failed to open file");
|
||||
return false;
|
||||
}
|
||||
DeserializationError jsonError = deserializeJson(jsonDoc, readfile);
|
||||
bool FlashC6_H2(const char *RepoUrl) {
|
||||
String JsonFilename = "/firmware_" SHORT_CHIP_NAME ".json" ;
|
||||
bool Ret = false;
|
||||
bool bLoaderInit = false;
|
||||
bool bDownload = strlen(RepoUrl) > 0;
|
||||
int retry;
|
||||
JsonDocument jsonDoc;
|
||||
|
||||
if (!jsonError) {
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for (JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
// String binaryUrl = "https://raw.githubusercontent.com/" + config.repo + "/master/binaries/ESP32-C6" + String(filename);
|
||||
String binaryUrl = "http://www.openepaperlink.eu/binaries/ESP32-C6" + String(filename);
|
||||
for (int retry = 0; retry < 10; retry++) {
|
||||
if (downloadAndWriteBinary(filename, binaryUrl.c_str())) {
|
||||
break;
|
||||
}
|
||||
wsSerial("Retry " + String(retry));
|
||||
if (retry < 9) {
|
||||
delay(1000);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wsSerial("json error fetching " + String(githubUrl));
|
||||
return false;
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
|
||||
do {
|
||||
if(bDownload) {
|
||||
String FileUrl = RepoUrl + JsonFilename;
|
||||
if(!downloadAndWriteBinary(JsonFilename, FileUrl.c_str())) {
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
File readfile = contentFS->open(filenameFirmwareLocal, "r");
|
||||
if (!readfile) {
|
||||
Serial.println("load local firmware.json: Failed to open file");
|
||||
return false;
|
||||
|
||||
File readfile = contentFS->open(JsonFilename, "r");
|
||||
if(!readfile) {
|
||||
wsSerial("load " + JsonFilename + ": Failed to open file");
|
||||
return true;
|
||||
}
|
||||
DeserializationError jsonError = deserializeJson(jsonDoc, readfile);
|
||||
}
|
||||
|
||||
const loader_esp32_config_t config = {
|
||||
.baud_rate = 115200,
|
||||
.uart_port = 2,
|
||||
.uart_rx_pin = FLASHER_DEBUG_TXD,
|
||||
.uart_tx_pin = FLASHER_DEBUG_RXD,
|
||||
.reset_trigger_pin = FLASHER_AP_RESET,
|
||||
.gpio0_trigger_pin = FLASHER_DEBUG_PROG,
|
||||
};
|
||||
if(jsonError) {
|
||||
wsSerial(String("json error parsing") + JsonFilename);
|
||||
break;
|
||||
}
|
||||
|
||||
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Serial initialization failed");
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
if(!bDownload) {
|
||||
Ret = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (connect_to_target(115200) == ESP_LOADER_SUCCESS) {
|
||||
if (esp_loader_get_target() == ESP32C6_CHIP) {
|
||||
wsSerial("Connected to ESP32-C6");
|
||||
int maxRetries = 5;
|
||||
esp_loader_error_t err;
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for(JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
String binaryUrl = RepoUrl + filename;
|
||||
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for (JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
const char *addressStr = obj["address"];
|
||||
uint32_t address = strtoul(addressStr, NULL, 16);
|
||||
|
||||
for (int retry = 0; retry < maxRetries; retry++) {
|
||||
err = flash_binary(filename, address);
|
||||
if (err == ESP_LOADER_SUCCESS) break;
|
||||
Serial.printf("Flash failed with error %d. Retrying...\n", err);
|
||||
for(retry = 0; retry < 10; retry++) {
|
||||
if(downloadAndWriteBinary(filename, binaryUrl.c_str())) {
|
||||
break;
|
||||
}
|
||||
wsSerial("Retry " + String(retry));
|
||||
if(retry < 9) {
|
||||
delay(1000);
|
||||
}
|
||||
if (err != ESP_LOADER_SUCCESS) {
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Serial.println("Done!");
|
||||
} else {
|
||||
wsSerial("Connected to wrong ESP32 type");
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
if(retry == 10) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wsSerial("Connection to the C6 failed");
|
||||
if(retry < 10) {
|
||||
Ret = true;
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(Ret == true) do {
|
||||
Ret = false;
|
||||
const loader_esp32_config_t config = {
|
||||
.baud_rate = 115200,
|
||||
.uart_port = FLASHER_DEBUG_PORT,
|
||||
.uart_rx_pin = FLASHER_DEBUG_TXD,
|
||||
.uart_tx_pin = FLASHER_DEBUG_RXD,
|
||||
.reset_trigger_pin = FLASHER_AP_RESET,
|
||||
.gpio0_trigger_pin = FLASHER_DEBUG_PROG,
|
||||
};
|
||||
|
||||
bLoaderInit = true;
|
||||
if(loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Serial initialization failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(connect_to_target(115200) != ESP_LOADER_SUCCESS) {
|
||||
wsSerial("Connection to the " SHORT_CHIP_NAME " failed");
|
||||
break;
|
||||
}
|
||||
|
||||
if(esp_loader_get_target() != ESP_CHIP_TYPE) {
|
||||
wsSerial("Connected to wrong ESP32 type");
|
||||
break;
|
||||
}
|
||||
wsSerial("Connected to ESP32-" SHORT_CHIP_NAME);
|
||||
int maxRetries = 5;
|
||||
esp_loader_error_t err;
|
||||
|
||||
JsonArray jsonArray = jsonDoc.as<JsonArray>();
|
||||
for(JsonObject obj : jsonArray) {
|
||||
String filename = "/" + obj["filename"].as<String>();
|
||||
const char *addressStr = obj["address"];
|
||||
uint32_t address = strtoul(addressStr, NULL, 16);
|
||||
|
||||
for(int retry = 0; retry < maxRetries; retry++) {
|
||||
err = flash_binary(filename, address);
|
||||
if(err == ESP_LOADER_SUCCESS) {
|
||||
Ret = true;
|
||||
break;
|
||||
}
|
||||
Serial.printf("Flash failed with error %d. Retrying...\n", err);
|
||||
delay(1000);
|
||||
}
|
||||
if(err != ESP_LOADER_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Serial.println("Done!");
|
||||
} while(false);
|
||||
|
||||
if(bLoaderInit) {
|
||||
loader_port_esp32_deinit();
|
||||
return false;
|
||||
}
|
||||
loader_port_esp32_deinit();
|
||||
return true;
|
||||
|
||||
LOG("%s#%d: ",__FUNCTION__,__LINE__); util::printHeap();
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "storage.h"
|
||||
#include "time.h"
|
||||
#include "zbs_interface.h"
|
||||
#include <WiFi.h>
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#include "webflasher.h"
|
||||
@@ -178,7 +179,7 @@ bool flasher::getInfoBlockType() {
|
||||
}
|
||||
|
||||
bool flasher::findTagByMD5() {
|
||||
DynamicJsonDocument doc(3000);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/tag_md5_db.json", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -207,7 +208,7 @@ bool flasher::findTagByMD5() {
|
||||
}
|
||||
|
||||
bool flasher::findTagByType(uint8_t type) {
|
||||
DynamicJsonDocument doc(3000);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/tag_md5_db.json", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -265,7 +266,7 @@ bool flasher::getFirmwareMac() {
|
||||
void flasher::getMacFromWiFi() {
|
||||
mac[0] = 0x00;
|
||||
mac[1] = 0x00;
|
||||
esp_read_mac(mac + 2, ESP_MAC_WIFI_SOFTAP);
|
||||
WiFi.softAPmacAddress(mac + 2);
|
||||
}
|
||||
|
||||
bool flasher::backupFlash() {
|
||||
@@ -447,7 +448,7 @@ bool flasher::writeFlashFromPackOffset(fs::File *file, uint16_t length) {
|
||||
}
|
||||
|
||||
bool flasher::writeFlashFromPack(String filename, uint8_t type) {
|
||||
DynamicJsonDocument doc(1024);
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open(filename, "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -507,7 +508,7 @@ bool flasher::writeBlock(uint16_t offset, uint8_t *data, uint16_t len, bool info
|
||||
|
||||
#ifndef C6_OTA_FLASHING
|
||||
uint16_t getAPUpdateVersion(uint8_t type) {
|
||||
StaticJsonDocument<512> doc;
|
||||
JsonDocument doc;
|
||||
fs::File readfile = contentFS->open("/AP_FW_Pack.bin", "r");
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
|
||||
203
ESP32_AP-Flasher/src/g5/Group5.h
Normal file
203
ESP32_AP-Flasher/src/g5/Group5.h
Normal file
@@ -0,0 +1,203 @@
|
||||
#ifndef __GROUP5__
|
||||
#define __GROUP5__
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
//
|
||||
// Group5 1-bit image compression library
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
//
|
||||
// The name "Group5" is derived from the CCITT Group4 standard
|
||||
// This code is based on a lot of the good ideas from CCITT T.6
|
||||
// for FAX image compression, but modified to work in a very
|
||||
// constrained environment. The Huffman tables for horizontal
|
||||
// mode have been replaced with a simple 2-bit flag followed by
|
||||
// short or long counts of a fixed length. The short codes are
|
||||
// always 3 bits (run lengths 0-7) and the long codes are the
|
||||
// number of bits needed to encode the width of the image.
|
||||
// For example, if a 320 pixel wide image is being compressed,
|
||||
// the longest horizontal run needed is 320, which requires 9
|
||||
// bits to encode. The 2 prefix bits have the following meaning:
|
||||
// 00 = short, short (3+3 bits)
|
||||
// 01 = short, long (3+N bits)
|
||||
// 10 = long, short (N+3 bits)
|
||||
// 11 = long, long (N+N bits)
|
||||
// The rest of the code works identically to Group4 2D FAX
|
||||
//
|
||||
// Caution - this is the maximum number of color changes per line
|
||||
// The default value is set low to work embedded systems with little RAM
|
||||
// for font compression, this is plenty since each line of a character should have
|
||||
// a maximum of 7 color changes
|
||||
// You can define this in your compiler macros to override the default vlaue
|
||||
//
|
||||
|
||||
|
||||
#define MAX_IMAGE_FLIPS 640
|
||||
|
||||
#ifndef MAX_IMAGE_FLIPS
|
||||
#ifdef __AVR__
|
||||
#define MAX_IMAGE_FLIPS 32
|
||||
#else
|
||||
#define MAX_IMAGE_FLIPS 512
|
||||
#endif // __AVR__
|
||||
#endif
|
||||
// Horizontal prefix bits
|
||||
enum {
|
||||
HORIZ_SHORT_SHORT=0,
|
||||
HORIZ_SHORT_LONG,
|
||||
HORIZ_LONG_SHORT,
|
||||
HORIZ_LONG_LONG
|
||||
};
|
||||
|
||||
// Return code for encoder and decoder
|
||||
enum {
|
||||
G5_SUCCESS = 0,
|
||||
G5_INVALID_PARAMETER,
|
||||
G5_DECODE_ERROR,
|
||||
G5_UNSUPPORTED_FEATURE,
|
||||
G5_ENCODE_COMPLETE,
|
||||
G5_DECODE_COMPLETE,
|
||||
G5_NOT_INITIALIZED,
|
||||
G5_DATA_OVERFLOW,
|
||||
G5_MAX_FLIPS_EXCEEDED
|
||||
};
|
||||
//
|
||||
// Decoder state
|
||||
//
|
||||
typedef struct g5_dec_image_tag
|
||||
{
|
||||
int iWidth, iHeight; // image size
|
||||
int iError;
|
||||
int y; // last y value drawn
|
||||
int iVLCSize;
|
||||
int iHLen; // length of 'long' horizontal codes for this image
|
||||
int iPitch; // width in bytes of output buffer
|
||||
uint32_t u32Accum; // fractional scaling accumulator
|
||||
uint32_t ulBitOff, ulBits; // vlc decode variables
|
||||
uint8_t *pSrc, *pBuf; // starting & current buffer pointer
|
||||
int16_t *pCur, *pRef; // current state of current vs reference flips
|
||||
int16_t CurFlips[MAX_IMAGE_FLIPS];
|
||||
int16_t RefFlips[MAX_IMAGE_FLIPS];
|
||||
} G5DECIMAGE;
|
||||
|
||||
// Due to unaligned memory causing an exception, we have to do these macros the slow way
|
||||
#ifdef __AVR__
|
||||
// assume PROGMEM as the source of data
|
||||
inline uint32_t TIFFMOTOLONG(uint8_t *p)
|
||||
{
|
||||
uint32_t u32 = pgm_read_dword(p);
|
||||
return __builtin_bswap32(u32);
|
||||
}
|
||||
#else
|
||||
#define TIFFMOTOLONG(p) (((uint32_t)(*p)<<24UL) + ((uint32_t)(*(p+1))<<16UL) + ((uint32_t)(*(p+2))<<8UL) + (uint32_t)(*(p+3)))
|
||||
#endif // __AVR__
|
||||
|
||||
#define TOP_BIT 0x80000000
|
||||
#define MAX_VALUE 0xffffffff
|
||||
// Must be a 32-bit target processor
|
||||
#define REGISTER_WIDTH 32
|
||||
#define BIGUINT uint32_t
|
||||
|
||||
//
|
||||
// G5 Encoder
|
||||
//
|
||||
|
||||
typedef struct pil_buffered_bits
|
||||
{
|
||||
unsigned char *pBuf; // buffer pointer
|
||||
uint32_t ulBits; // buffered bits
|
||||
uint32_t ulBitOff; // current bit offset
|
||||
uint32_t ulDataSize; // available data
|
||||
} BUFFERED_BITS;
|
||||
|
||||
//
|
||||
// Encoder state
|
||||
//
|
||||
typedef struct g5_enc_image_tag
|
||||
{
|
||||
int iWidth, iHeight; // image size
|
||||
int iError;
|
||||
int y; // last y encoded
|
||||
int iOutSize;
|
||||
int iDataSize; // generated output size
|
||||
uint8_t *pOutBuf;
|
||||
int16_t *pCur, *pRef; // pointers to swap current and reference lines
|
||||
BUFFERED_BITS bb;
|
||||
int16_t CurFlips[MAX_IMAGE_FLIPS];
|
||||
int16_t RefFlips[MAX_IMAGE_FLIPS];
|
||||
} G5ENCIMAGE;
|
||||
|
||||
// 16-bit marker at the start of a BB_FONT file
|
||||
// (BitBank FontFile)
|
||||
#define BB_FONT_MARKER 0xBBFF
|
||||
// 16-bit marker at the start of a BB_BITMAP file
|
||||
// (BitBank BitmapFile)
|
||||
#define BB_BITMAP_MARKER 0xBBBF
|
||||
|
||||
// Font info per character (glyph)
|
||||
typedef struct {
|
||||
uint16_t bitmapOffset; // Offset to compressed bitmap data for this glyph (starting from the end of the BB_GLYPH[] array)
|
||||
uint8_t width; // bitmap width in pixels
|
||||
uint8_t xAdvance; // total width in pixels (bitmap + padding)
|
||||
uint16_t height; // bitmap height in pixels
|
||||
int16_t xOffset; // left padding to upper left corner
|
||||
int16_t yOffset; // padding from baseline to upper left corner (usually negative)
|
||||
} BB_GLYPH;
|
||||
|
||||
// This structure is stored at the beginning of a BB_FONT file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit Marker defining a BB_FONT file
|
||||
uint16_t first; // first char (ASCII value)
|
||||
uint16_t last; // last char (ASCII value)
|
||||
uint16_t height; // total height of font
|
||||
uint32_t rotation; // store this as 32-bits to not have a struct packing problem
|
||||
BB_GLYPH glyphs[]; // Array of glyphs (one for each char)
|
||||
} BB_FONT;
|
||||
|
||||
// This structure defines the start of a compressed bitmap file
|
||||
typedef struct {
|
||||
uint16_t u16Marker; // 16-bit marker defining a BB_BITMAP file
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t size; // compressed data size (not including this 8-byte header)
|
||||
} BB_BITMAP;
|
||||
|
||||
#ifdef __cplusplus
|
||||
//
|
||||
// The G5 classes wrap portable C code which does the actual work
|
||||
//
|
||||
class G5ENCODER
|
||||
{
|
||||
public:
|
||||
int init(int iWidth, int iHeight, uint8_t *pOut, int iOutSize);
|
||||
int encodeLine(uint8_t *pPixels);
|
||||
int size();
|
||||
|
||||
private:
|
||||
G5ENCIMAGE _g5enc;
|
||||
};
|
||||
class G5DECODER
|
||||
{
|
||||
public:
|
||||
int init(int iWidth, int iHeight, uint8_t *pData, int iDataSize);
|
||||
int decodeLine(uint8_t *pOut);
|
||||
|
||||
private:
|
||||
G5DECIMAGE _g5dec;
|
||||
};
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __GROUP5__
|
||||
338
ESP32_AP-Flasher/src/g5/g5dec.inl
Normal file
338
ESP32_AP-Flasher/src/g5/g5dec.inl
Normal file
@@ -0,0 +1,338 @@
|
||||
//
|
||||
// Group5
|
||||
// A 1-bpp image decoder
|
||||
//
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
#include "Group5.h"
|
||||
|
||||
/*
|
||||
The code tree that follows has: bit_length, decode routine
|
||||
These codes are for Group 4 (MMR) decoding
|
||||
|
||||
01 = vertneg1, 11h = vert1, 20h = horiz, 30h = pass, 12h = vert2
|
||||
02 = vertneg2, 13h = vert3, 03 = vertneg3, 90h = trash
|
||||
*/
|
||||
|
||||
static const uint8_t code_table[128] =
|
||||
{0x90, 0, 0x40, 0, /* trash, uncompr mode - codes 0 and 1 */
|
||||
3, 7, /* V(-3) pos = 2 */
|
||||
0x13, 7, /* V(3) pos = 3 */
|
||||
2, 6, 2, 6, /* V(-2) pos = 4,5 */
|
||||
0x12, 6, 0x12, 6, /* V(2) pos = 6,7 */
|
||||
0x30, 4, 0x30, 4, 0x30, 4, 0x30, 4, /* pass pos = 8->F */
|
||||
0x30, 4, 0x30, 4, 0x30, 4, 0x30, 4,
|
||||
0x20, 3, 0x20, 3, 0x20, 3, 0x20, 3, /* horiz pos = 10->1F */
|
||||
0x20, 3, 0x20, 3, 0x20, 3, 0x20, 3,
|
||||
0x20, 3, 0x20, 3, 0x20, 3, 0x20, 3,
|
||||
0x20, 3, 0x20, 3, 0x20, 3, 0x20, 3,
|
||||
/* V(-1) pos = 20->2F */
|
||||
1, 3, 1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3, 1, 3,
|
||||
0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3, /* V(1) pos = 30->3F */
|
||||
0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3,
|
||||
0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3,
|
||||
0x11, 3, 0x11, 3, 0x11, 3, 0x11, 3};
|
||||
|
||||
static int g5_decode_init(G5DECIMAGE *pImage, int iWidth, int iHeight, uint8_t *pData, int iDataSize)
|
||||
{
|
||||
if (pImage == NULL || iWidth < 1 || iHeight < 1 || pData == NULL || iDataSize < 1)
|
||||
return G5_INVALID_PARAMETER;
|
||||
|
||||
pImage->iVLCSize = iDataSize;
|
||||
pImage->pSrc = pData;
|
||||
pImage->ulBitOff = 0;
|
||||
pImage->y = 0;
|
||||
pImage->ulBits = TIFFMOTOLONG(pData); // preload the first 32 bits of data
|
||||
pImage->iWidth = iWidth;
|
||||
pImage->iHeight = iHeight;
|
||||
return G5_SUCCESS;
|
||||
|
||||
} /* g5_decode_init() */
|
||||
|
||||
static void G5DrawLine(G5DECIMAGE *pPage, int16_t *pCurFlips, uint8_t *pOut)
|
||||
{
|
||||
int x, len, run;
|
||||
uint8_t lBit, rBit, *p;
|
||||
int iStart = 0, xright = pPage->iWidth;
|
||||
uint8_t *pDest;
|
||||
|
||||
iStart = 0;
|
||||
|
||||
pDest = pOut;
|
||||
len = (xright+7)>>3; // number of bytes to generate
|
||||
for (x=0; x<len; x++) {
|
||||
pOut[x] = 0xff; // start with white and only draw the black runs
|
||||
}
|
||||
x = 0;
|
||||
while (x < xright) { // while the scaled x is within the window bounds
|
||||
x = *pCurFlips++; // black starting point
|
||||
run = *pCurFlips++ - x; // get the black run
|
||||
x -= iStart;
|
||||
if (x >= xright || run == 0)
|
||||
break;
|
||||
if ((x + run) > 0) { /* If the run is visible, draw it */
|
||||
if (x < 0) {
|
||||
run += x; /* draw only visible part of run */
|
||||
x = 0;
|
||||
}
|
||||
if ((x + run) > xright) { /* Don't let it go off right edge */
|
||||
run = xright - x;
|
||||
}
|
||||
/* Draw this run */
|
||||
lBit = 0xff << (8 - (x & 7));
|
||||
rBit = 0xff >> ((x + run) & 7);
|
||||
len = ((x+run)>>3) - (x >> 3);
|
||||
p = &pDest[x >> 3];
|
||||
if (len == 0) {
|
||||
lBit |= rBit;
|
||||
*p &= lBit;
|
||||
} else {
|
||||
*p++ &= lBit;
|
||||
while (len > 1) {
|
||||
*p++ = 0;
|
||||
len--;
|
||||
}
|
||||
*p = rBit;
|
||||
}
|
||||
} // visible run
|
||||
} /* while drawing line */
|
||||
} /* G5DrawLine() */
|
||||
//
|
||||
// Initialize internal structures to decode the image
|
||||
//
|
||||
static void Decode_Begin(G5DECIMAGE *pPage)
|
||||
{
|
||||
int i, xsize;
|
||||
int16_t *CurFlips, *RefFlips;
|
||||
|
||||
xsize = pPage->iWidth;
|
||||
|
||||
RefFlips = pPage->RefFlips;
|
||||
CurFlips = pPage->CurFlips;
|
||||
|
||||
/* Seed the current and reference line with XSIZE for V(0) codes */
|
||||
for (i=0; i<MAX_IMAGE_FLIPS-2; i++) {
|
||||
RefFlips[i] = xsize;
|
||||
CurFlips[i] = xsize;
|
||||
}
|
||||
/* Prefill both current and reference lines with 7fff to prevent it from
|
||||
walking off the end if the data gets bunged and the current X is > XSIZE
|
||||
3-16-94 */
|
||||
CurFlips[i] = RefFlips[i] = 0x7fff;
|
||||
CurFlips[i+1] = RefFlips[i+1] = 0x7fff;
|
||||
|
||||
pPage->pCur = CurFlips;
|
||||
pPage->pRef = RefFlips;
|
||||
pPage->pBuf = pPage->pSrc;
|
||||
pPage->ulBits = TIFFMOTOLONG(pPage->pSrc); // load 32 bits to start
|
||||
pPage->ulBitOff = 0;
|
||||
// Calculate the number of bits needed for a long horizontal code
|
||||
#ifdef __AVR__
|
||||
pPage->iHLen = 16 - __builtin_clz(pPage->iWidth);
|
||||
#else
|
||||
pPage->iHLen = 32 - __builtin_clz(pPage->iWidth);
|
||||
#endif
|
||||
} /* Decode_Begin() */
|
||||
//
|
||||
// Decode a single line of G5 data (private function)
|
||||
//
|
||||
static int DecodeLine(G5DECIMAGE *pPage)
|
||||
{
|
||||
signed int a0, a0_p, b1;
|
||||
int16_t *pCur, *pRef, *RefFlips, *CurFlips;
|
||||
int xsize, tot_run=0, tot_run1 = 0;
|
||||
int32_t sCode;
|
||||
uint32_t lBits;
|
||||
uint32_t ulBits, ulBitOff;
|
||||
uint8_t *pBuf/*, *pBufEnd*/;
|
||||
uint32_t u32HMask, u32HLen; // horizontal code mask and length
|
||||
|
||||
pCur = CurFlips = pPage->pCur;
|
||||
pRef = RefFlips = pPage->pRef;
|
||||
ulBits = pPage->ulBits;
|
||||
ulBitOff = pPage->ulBitOff;
|
||||
pBuf = pPage->pBuf;
|
||||
// pBufEnd = &pPage->pSrc[pPage->iVLCSize];
|
||||
u32HLen = pPage->iHLen;
|
||||
u32HMask = (1 << u32HLen) - 1;
|
||||
a0 = -1;
|
||||
xsize = pPage->iWidth;
|
||||
|
||||
while (a0 < xsize) { /* Decode this line */
|
||||
if (ulBitOff > (REGISTER_WIDTH-8)) { // need at least 7 unused bits
|
||||
pBuf += (ulBitOff >> 3);
|
||||
ulBitOff &= 7;
|
||||
ulBits = TIFFMOTOLONG(pBuf);
|
||||
}
|
||||
if ((int32_t)(ulBits << ulBitOff) < 0) { /* V(0) code is the most frequent case (1 bit) */
|
||||
a0 = *pRef++;
|
||||
ulBitOff++; // length = 1 bit
|
||||
*pCur++ = a0;
|
||||
} else { /* Slower method for the less frequence codes */
|
||||
lBits = (ulBits >> ((REGISTER_WIDTH - 8) - ulBitOff)) & 0xfe; /* Only the first 7 bits are useful */
|
||||
sCode = code_table[lBits]; /* Get the code type as an 8-bit value */
|
||||
ulBitOff += code_table[lBits+1]; /* Get the code length */
|
||||
switch (sCode) {
|
||||
case 1: /* V(-1) */
|
||||
case 2: /* V(-2) */
|
||||
case 3: /* V(-3) */
|
||||
a0 = *pRef - sCode; /* A0 = B1 - x */
|
||||
*pCur++ = a0;
|
||||
if (pRef == RefFlips) {
|
||||
pRef += 2;
|
||||
}
|
||||
pRef--;
|
||||
while (a0 >= *pRef) {
|
||||
pRef += 2;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11: /* V(1) */
|
||||
case 0x12: /* V(2) */
|
||||
case 0x13: /* V(3) */
|
||||
a0 = *pRef++; /* A0 = B1 */
|
||||
b1 = a0;
|
||||
a0 += sCode & 7; /* A0 = B1 + x */
|
||||
if (b1 != xsize && a0 < xsize) {
|
||||
while (a0 >= *pRef) {
|
||||
pRef += 2;
|
||||
}
|
||||
}
|
||||
if (a0 > xsize) {
|
||||
a0 = xsize;
|
||||
}
|
||||
*pCur++ = a0;
|
||||
break;
|
||||
|
||||
case 0x20: /* Horizontal codes */
|
||||
if (ulBitOff > (REGISTER_WIDTH-16)) { // need at least 16 unused bits
|
||||
pBuf += (ulBitOff >> 3);
|
||||
ulBitOff &= 7;
|
||||
ulBits = TIFFMOTOLONG(pBuf);
|
||||
}
|
||||
a0_p = a0;
|
||||
if (a0 < 0) {
|
||||
a0_p = 0;
|
||||
}
|
||||
lBits = (ulBits >> ((REGISTER_WIDTH - 2) - ulBitOff)) & 0x3; // get 2-bit prefix for code type
|
||||
// There are 4 possible horizontal cases: short/short, short/long, long/short, long/long
|
||||
// These are encoded in a 2-bit prefix code, followed by 3 bits for short or N bits for long code
|
||||
// N is the log base 2 of the image width (e.g. 320 pixels requires 9 bits)
|
||||
ulBitOff += 2;
|
||||
switch (lBits) {
|
||||
case HORIZ_SHORT_SHORT:
|
||||
tot_run = (ulBits >> ((REGISTER_WIDTH - 3) - ulBitOff)) & 0x7; // get 3-bit short length
|
||||
ulBitOff += 3;
|
||||
tot_run1 = (ulBits >> ((REGISTER_WIDTH - 3) - ulBitOff)) & 0x7; // get 3-bit short length
|
||||
ulBitOff += 3;
|
||||
break;
|
||||
case HORIZ_SHORT_LONG:
|
||||
tot_run = (ulBits >> ((REGISTER_WIDTH - 3) - ulBitOff)) & 0x7; // get 3-bit short length
|
||||
ulBitOff += 3;
|
||||
tot_run1 = (ulBits >> ((REGISTER_WIDTH - u32HLen) - ulBitOff)) & u32HMask; // get long length
|
||||
ulBitOff += u32HLen;
|
||||
break;
|
||||
case HORIZ_LONG_SHORT:
|
||||
tot_run = (ulBits >> ((REGISTER_WIDTH - u32HLen) - ulBitOff)) & u32HMask; // get long length
|
||||
ulBitOff += u32HLen;
|
||||
tot_run1 = (ulBits >> ((REGISTER_WIDTH - 3) - ulBitOff)) & 0x7; // get 3-bit short length
|
||||
ulBitOff += 3;
|
||||
break;
|
||||
case HORIZ_LONG_LONG:
|
||||
tot_run = (ulBits >> ((REGISTER_WIDTH - u32HLen) - ulBitOff)) & u32HMask; // get long length
|
||||
ulBitOff += u32HLen;
|
||||
if (ulBitOff > (REGISTER_WIDTH-16)) { // need at least 16 unused bits
|
||||
pBuf += (ulBitOff >> 3);
|
||||
ulBitOff &= 7;
|
||||
ulBits = TIFFMOTOLONG(pBuf);
|
||||
}
|
||||
tot_run1 = (ulBits >> ((REGISTER_WIDTH - u32HLen) - ulBitOff)) & u32HMask; // get long length
|
||||
ulBitOff += u32HLen;
|
||||
break;
|
||||
} // switch on lBits
|
||||
a0 = a0_p + tot_run;
|
||||
*pCur++ = a0;
|
||||
a0 += tot_run1;
|
||||
if (a0 < xsize) {
|
||||
while (a0 >= *pRef) {
|
||||
pRef += 2;
|
||||
}
|
||||
}
|
||||
*pCur++ = a0;
|
||||
break;
|
||||
|
||||
case 0x30: /* Pass code */
|
||||
pRef++; /* A0 = B2, iRef+=2 */
|
||||
a0 = *pRef++;
|
||||
break;
|
||||
|
||||
default: /* ERROR */
|
||||
pPage->iError = G5_DECODE_ERROR;
|
||||
goto pilreadg5z;
|
||||
} /* switch */
|
||||
} /* Slow climb */
|
||||
}
|
||||
/*--- Convert flips data into run lengths ---*/
|
||||
*pCur++ = xsize; /* Terminate the line properly */
|
||||
*pCur++ = xsize;
|
||||
pilreadg5z:
|
||||
// Save the current VLC decoder state
|
||||
pPage->ulBits = ulBits;
|
||||
pPage->ulBitOff = ulBitOff;
|
||||
pPage->pBuf = pBuf;
|
||||
return pPage->iError;
|
||||
} /* DecodeLine() */
|
||||
//
|
||||
// Decompress the VLC data
|
||||
//
|
||||
static int g5_decode_line(G5DECIMAGE *pPage, uint8_t *pOut)
|
||||
{
|
||||
int rc;
|
||||
uint8_t *pBufEnd;
|
||||
int16_t *t1;
|
||||
|
||||
if (pPage == NULL || pOut == NULL)
|
||||
return G5_INVALID_PARAMETER;
|
||||
if (pPage->y >= pPage->iHeight)
|
||||
return G5_DECODE_COMPLETE;
|
||||
|
||||
pPage->iError = G5_SUCCESS;
|
||||
|
||||
if (pPage->y == 0) { // first time through
|
||||
Decode_Begin(pPage);
|
||||
}
|
||||
pBufEnd = &pPage->pSrc[pPage->iVLCSize];
|
||||
|
||||
if (pPage->pBuf >= pBufEnd) { // read past the end, error
|
||||
pPage->iError = G5_DECODE_ERROR;
|
||||
return G5_DECODE_ERROR;
|
||||
}
|
||||
rc = DecodeLine(pPage);
|
||||
if (rc == G5_SUCCESS) {
|
||||
// Draw the current line
|
||||
G5DrawLine(pPage, pPage->pCur, pOut);
|
||||
/*--- Swap current and reference lines ---*/
|
||||
t1 = pPage->pRef;
|
||||
pPage->pRef = pPage->pCur;
|
||||
pPage->pCur = t1;
|
||||
pPage->y++;
|
||||
if (pPage->y >= pPage->iHeight) {
|
||||
pPage->iError = G5_DECODE_COMPLETE;
|
||||
}
|
||||
} else {
|
||||
pPage->iError = rc;
|
||||
}
|
||||
return pPage->iError;
|
||||
} /* Decode() */
|
||||
|
||||
305
ESP32_AP-Flasher/src/g5/g5enc.inl
Normal file
305
ESP32_AP-Flasher/src/g5/g5enc.inl
Normal file
@@ -0,0 +1,305 @@
|
||||
//
|
||||
// G5 Encoder
|
||||
// A 1-bpp image encoding library
|
||||
//
|
||||
// Written by Larry Bank
|
||||
// Copyright (c) 2024 BitBank Software, Inc.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file ./LICENSE.
|
||||
//
|
||||
// As of the Change Date specified in that file, in accordance with
|
||||
// the Business Source License, use of this software will be governed
|
||||
// by the Apache License, Version 2.0, included in the file
|
||||
// ./APL.txt.
|
||||
#include "Group5.h"
|
||||
|
||||
/* Number of consecutive 1 bits in a byte from MSB to LSB */
|
||||
static uint8_t bitcount[256] =
|
||||
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0-15 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16-31 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 32-47 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 48-63 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 64-79 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80-95 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 96-111 */
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 112-127 */
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 128-143 */
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 144-159 */
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 160-175 */
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 176-191 */
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 192-207 */
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* 208-223 */
|
||||
3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, /* 224-239 */
|
||||
4,4,4,4,4,4,4,4,5,5,5,5,6,6,7,8}; /* 240-255 */
|
||||
|
||||
/* Table of vertical codes for G5 encoding */
|
||||
/* code followed by length, starting with v(-3) */
|
||||
static const uint8_t vtable[14] =
|
||||
{3,7, /* V(-3) = 0000011 */
|
||||
3,6, /* V(-2) = 000011 */
|
||||
3,3, /* V(-1) = 011 */
|
||||
1,1, /* V(0) = 1 */
|
||||
2,3, /* V(1) = 010 */
|
||||
2,6, /* V(2) = 000010 */
|
||||
2,7}; /* V(3) = 0000010 */
|
||||
|
||||
|
||||
static void G5ENCInsertCode(BUFFERED_BITS *bb, BIGUINT ulCode, int iLen)
|
||||
{
|
||||
if ((bb->ulBitOff + iLen) > REGISTER_WIDTH) { // need to write data
|
||||
bb->ulBits |= (ulCode >> (bb->ulBitOff + iLen - REGISTER_WIDTH)); // partial bits on first word
|
||||
*(BIGUINT *)bb->pBuf = __builtin_bswap32(bb->ulBits);
|
||||
bb->pBuf += sizeof(BIGUINT);
|
||||
bb->ulBits = ulCode << ((REGISTER_WIDTH*2) - (bb->ulBitOff + iLen));
|
||||
bb->ulBitOff += iLen - REGISTER_WIDTH;
|
||||
} else {
|
||||
bb->ulBits |= (ulCode << (REGISTER_WIDTH - bb->ulBitOff - iLen));
|
||||
bb->ulBitOff += iLen;
|
||||
}
|
||||
} /* G5ENCInsertCode() */
|
||||
//
|
||||
// Flush any buffered bits to the output
|
||||
//
|
||||
static void G5ENCFlushBits(BUFFERED_BITS *bb)
|
||||
{
|
||||
while (bb->ulBitOff >= 8)
|
||||
{
|
||||
*bb->pBuf++ = (unsigned char) (bb->ulBits >> (REGISTER_WIDTH - 8));
|
||||
bb->ulBits <<= 8;
|
||||
bb->ulBitOff -= 8;
|
||||
}
|
||||
*bb->pBuf++ = (unsigned char) (bb->ulBits >> (REGISTER_WIDTH - 8));
|
||||
bb->ulBitOff = 0;
|
||||
bb->ulBits = 0;
|
||||
} /* G5ENCFlushBits() */
|
||||
//
|
||||
// Initialize the compressor
|
||||
// This must be called before adding data to the output
|
||||
//
|
||||
int g5_encode_init(G5ENCIMAGE *pImage, int iWidth, int iHeight, uint8_t *pOut, int iOutSize)
|
||||
{
|
||||
int iError = G5_SUCCESS;
|
||||
|
||||
if (pImage == NULL || iHeight <= 0)
|
||||
return G5_INVALID_PARAMETER;
|
||||
pImage->iWidth = iWidth; // image size
|
||||
pImage->iHeight = iHeight;
|
||||
pImage->pCur = pImage->CurFlips;
|
||||
pImage->pRef = pImage->RefFlips;
|
||||
pImage->pOutBuf = pOut; // optional output buffer
|
||||
pImage->iOutSize = iOutSize; // output buffer pre-allocated size
|
||||
pImage->iDataSize = 0; // no data yet
|
||||
pImage->y = 0;
|
||||
for (int i=0; i<MAX_IMAGE_FLIPS; i++) {
|
||||
pImage->RefFlips[i] = iWidth;
|
||||
pImage->CurFlips[i] = iWidth;
|
||||
}
|
||||
pImage->bb.pBuf = pImage->pOutBuf;
|
||||
pImage->bb.ulBits = 0;
|
||||
pImage->bb.ulBitOff = 0;
|
||||
pImage->iError = iError;
|
||||
return iError;
|
||||
} /* g5_encode_init() */
|
||||
//
|
||||
// Internal function to convert uncompressed 1-bit per pixel data
|
||||
// into the run-end data needed to feed the G5 encoder
|
||||
//
|
||||
static int G5ENCEncodeLine(unsigned char *buf, int xsize, int16_t *pDest)
|
||||
{
|
||||
int iCount, xborder;
|
||||
uint8_t i, c;
|
||||
int8_t cBits;
|
||||
int iLen;
|
||||
int16_t x;
|
||||
int16_t *pLimit = pDest + (MAX_IMAGE_FLIPS-4);
|
||||
|
||||
xborder = xsize;
|
||||
iCount = (xsize + 7) >> 3; /* Number of bytes per line */
|
||||
cBits = 8;
|
||||
iLen = 0; /* Current run length */
|
||||
x = 0;
|
||||
|
||||
c = *buf++; /* Get the first byte to start */
|
||||
iCount--;
|
||||
while (iCount >=0) {
|
||||
if (pDest >= pLimit) return G5_MAX_FLIPS_EXCEEDED;
|
||||
i = bitcount[c]; /* Get the number of consecutive bits */
|
||||
iLen += i; /* Add this length to total run length */
|
||||
c <<= i;
|
||||
cBits -= i; /* Minus the number in a byte */
|
||||
if (cBits <= 0)
|
||||
{
|
||||
iLen += cBits; /* Adjust length */
|
||||
cBits = 8;
|
||||
c = *buf++; /* Get another data byte */
|
||||
iCount--;
|
||||
continue; /* Keep doing white until color change */
|
||||
}
|
||||
c = ~c; /* flip color to count black pixels */
|
||||
/* Store the white run length */
|
||||
xborder -= iLen;
|
||||
if (xborder < 0)
|
||||
{
|
||||
iLen += xborder; /* Make sure run length is not past end */
|
||||
break;
|
||||
}
|
||||
x += iLen;
|
||||
*pDest++ = x;
|
||||
iLen = 0;
|
||||
doblack:
|
||||
i = bitcount[c]; /* Get consecutive bits */
|
||||
iLen += i; /* Add to total run length */
|
||||
c <<= i;
|
||||
cBits -= i;
|
||||
if (cBits <= 0)
|
||||
{
|
||||
iLen += cBits; /* Adjust length */
|
||||
cBits = 8;
|
||||
c = *buf++; /* Get another data byte */
|
||||
c = ~c; /* Flip color to find black */
|
||||
iCount--;
|
||||
if (iCount < 0)
|
||||
break;
|
||||
goto doblack;
|
||||
}
|
||||
/* Store the black run length */
|
||||
c = ~c; /* Flip color again to find white pixels */
|
||||
xborder -= iLen;
|
||||
if (xborder < 0)
|
||||
{
|
||||
iLen += xborder; /* Make sure run length is not past end */
|
||||
break;
|
||||
}
|
||||
x += iLen;
|
||||
*pDest++ = x;
|
||||
iLen = 0;
|
||||
} /* while */
|
||||
|
||||
x += iLen;
|
||||
if (pDest >= pLimit) return G5_MAX_FLIPS_EXCEEDED;
|
||||
*pDest++ = x;
|
||||
*pDest++ = x; // Store a few more XSIZE to end the line
|
||||
*pDest++ = x; // so that the compressor doesn't go past
|
||||
*pDest++ = x; // the end of the line
|
||||
return G5_SUCCESS;
|
||||
} /* G5ENCEncodeLine() */
|
||||
//
|
||||
// Compress a line of pixels and add it to the output
|
||||
// the input format is expected to be MSB (most significant bit) first
|
||||
// for example, pixel 0 is in byte 0 at bit 7 (0x80)
|
||||
// Returns G5ENC_SUCCESS for each line if all is well and G5ENC_IMAGE_COMPLETE
|
||||
// for the last line
|
||||
//
|
||||
int g5_encode_encodeLine(G5ENCIMAGE *pImage, uint8_t *pPixels)
|
||||
{
|
||||
int16_t a0, a0_c, b2, a1;
|
||||
int dx, run1, run2;
|
||||
int xsize, iErr, iHighWater;
|
||||
int iCur, iRef, iLen;
|
||||
int iHLen; // number of bits for long horizontal codes
|
||||
int16_t *CurFlips, *RefFlips;
|
||||
BUFFERED_BITS bb;
|
||||
|
||||
if (pImage == NULL || pPixels == NULL)
|
||||
return G5_INVALID_PARAMETER;
|
||||
iHighWater = pImage->iOutSize - 32;
|
||||
iHLen = 32 - __builtin_clz(pImage->iWidth);
|
||||
memcpy(&bb, &pImage->bb, sizeof(BUFFERED_BITS)); // keep local copy
|
||||
CurFlips = pImage->pCur;
|
||||
RefFlips = pImage->pRef;
|
||||
xsize = pImage->iWidth; /* For performance reasons */
|
||||
|
||||
// Convert the incoming line of pixels into run-end data
|
||||
iErr = G5ENCEncodeLine(pPixels, pImage->iWidth, CurFlips);
|
||||
if (iErr != G5_SUCCESS) return iErr; // exceeded the maximum number of color changes
|
||||
/* Encode this line as G5 */
|
||||
a0 = a0_c = 0;
|
||||
iCur = iRef = 0;
|
||||
while (a0 < xsize) {
|
||||
b2 = RefFlips[iRef+1];
|
||||
a1 = CurFlips[iCur];
|
||||
if (b2 < a1) { /* Is b2 to the left of a1? */
|
||||
/* yes, do pass mode */
|
||||
a0 = b2;
|
||||
iRef += 2;
|
||||
G5ENCInsertCode(&bb, 1, 4); /* Pass code = 0001 */
|
||||
} else { /* Try vertical and horizontal mode */
|
||||
dx = RefFlips[iRef] - a1; /* b1 - a1 */
|
||||
if (dx > 3 || dx < -3) { /* Horizontal mode */
|
||||
G5ENCInsertCode(&bb, 1, 3); /* Horizontal code = 001 */
|
||||
run1 = CurFlips[iCur] - a0;
|
||||
run2 = CurFlips[iCur+1] - CurFlips[iCur];
|
||||
if (run1 < 8) {
|
||||
if (run2 < 8) { // short, short
|
||||
G5ENCInsertCode(&bb, HORIZ_SHORT_SHORT, 2); /* short, short = 00 */
|
||||
G5ENCInsertCode(&bb, run1, 3);
|
||||
G5ENCInsertCode(&bb, run2, 3);
|
||||
} else { // short, long
|
||||
G5ENCInsertCode(&bb, HORIZ_SHORT_LONG, 2); /* short, long = 01 */
|
||||
G5ENCInsertCode(&bb, run1, 3);
|
||||
G5ENCInsertCode(&bb, run2, iHLen);
|
||||
}
|
||||
} else { // first run is long
|
||||
if (run2 < 8) { // long, short
|
||||
G5ENCInsertCode(&bb, HORIZ_LONG_SHORT, 2); /* long, short = 10 */
|
||||
G5ENCInsertCode(&bb, run1, iHLen);
|
||||
G5ENCInsertCode(&bb, run2, 3);
|
||||
} else { // long, long
|
||||
G5ENCInsertCode(&bb, HORIZ_LONG_LONG, 2); /* long, long = 11 */
|
||||
G5ENCInsertCode(&bb, run1, iHLen);
|
||||
G5ENCInsertCode(&bb, run2, iHLen);
|
||||
}
|
||||
}
|
||||
a0 = CurFlips[iCur+1]; /* a0 = a2 */
|
||||
if (a0 != xsize) {
|
||||
iCur += 2; /* Skip two color flips */
|
||||
while (RefFlips[iRef] != xsize && RefFlips[iRef] <= a0) {
|
||||
iRef += 2;
|
||||
}
|
||||
}
|
||||
} else { /* Vertical mode */
|
||||
dx = (dx + 3) * 2; /* Convert to index table */
|
||||
G5ENCInsertCode(&bb, vtable[dx], vtable[dx+1]);
|
||||
a0 = a1;
|
||||
a0_c = 1-a0_c;
|
||||
if (a0 != xsize) {
|
||||
if (iRef != 0) {
|
||||
iRef -= 2;
|
||||
}
|
||||
iRef++; /* Skip a color change in cur and ref */
|
||||
iCur++;
|
||||
while (RefFlips[iRef] <= a0 && RefFlips[iRef] != xsize) {
|
||||
iRef += 2;
|
||||
}
|
||||
}
|
||||
} /* vertical mode */
|
||||
} /* horiz/vert mode */
|
||||
} /* while x < xsize */
|
||||
iLen = (int)(bb.pBuf-pImage->pOutBuf);
|
||||
if (iLen >= iHighWater) { // not enough space
|
||||
pImage->iError = iErr = G5_DATA_OVERFLOW; // we don't have a better error
|
||||
return iErr;
|
||||
}
|
||||
if (pImage->y == pImage->iHeight-1) { // last line of image
|
||||
G5ENCFlushBits(&bb); // output the final buffered bits
|
||||
// wrap up final output
|
||||
pImage->iDataSize = (int)(bb.pBuf-pImage->pOutBuf);
|
||||
iErr = G5_ENCODE_COMPLETE;
|
||||
}
|
||||
pImage->pCur = RefFlips; // swap current and reference lines
|
||||
pImage->pRef = CurFlips;
|
||||
pImage->y++;
|
||||
memcpy(&pImage->bb, &bb, sizeof(bb));
|
||||
return iErr;
|
||||
} /* g5_encode_encodeLine() */
|
||||
//
|
||||
// Returns the number of bytes of G5 created by the encoder
|
||||
//
|
||||
int g5_encode_getOutSize(G5ENCIMAGE *pImage)
|
||||
{
|
||||
int iSize = 0;
|
||||
if (pImage != NULL)
|
||||
iSize = pImage->iDataSize;
|
||||
return iSize;
|
||||
} /* g5_encode_getOutSize() */
|
||||
@@ -12,14 +12,346 @@
|
||||
#include "ips_display.h"
|
||||
|
||||
#define YELLOW_SENSE 8 // sense AP hardware
|
||||
|
||||
#ifdef HAS_ELECROW_ADV_2_8
|
||||
#define TFT_BACKLIGHT 38
|
||||
#else
|
||||
#define TFT_BACKLIGHT 14
|
||||
#endif
|
||||
|
||||
TFT_eSPI tft2 = TFT_eSPI();
|
||||
uint8_t YellowSense = 0;
|
||||
bool tftLogscreen = true;
|
||||
bool tftOverride = false;
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL
|
||||
static const uint8_t st7701_type9_init_operations_lilygo[] = {
|
||||
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
|
||||
|
||||
WRITE_C8_D8, 0xEF, 0x08,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
|
||||
|
||||
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
|
||||
WRITE_C8_D16, 0xC1, 0x0B, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xC2,
|
||||
WRITE_BYTES, 3, 0x30, 0x02, 0x37,
|
||||
|
||||
WRITE_C8_D8, 0xCC, 0x10,
|
||||
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x09,
|
||||
0x08, 0x23, 0x05, 0x11,
|
||||
0x0F, 0x28, 0x2D, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x0F, 0x16, 0x0E,
|
||||
0x11, 0x07, 0x09, 0x08,
|
||||
0x09, 0x23, 0x05, 0x11,
|
||||
0x0F, 0x28, 0x2D, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
|
||||
|
||||
WRITE_C8_D8, 0xB0, 0x4D,
|
||||
WRITE_C8_D8, 0xB1, 0x33,
|
||||
WRITE_C8_D8, 0xB2, 0x87,
|
||||
WRITE_C8_D8, 0xB5, 0x4B,
|
||||
WRITE_C8_D8, 0xB7, 0x8C,
|
||||
WRITE_C8_D8, 0xB8, 0x20,
|
||||
WRITE_C8_D8, 0xC1, 0x78,
|
||||
WRITE_C8_D8, 0xC2, 0x78,
|
||||
WRITE_C8_D8, 0xD0, 0x88,
|
||||
|
||||
WRITE_COMMAND_8, 0xE0,
|
||||
WRITE_BYTES, 3, 0x00, 0x00, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xE1,
|
||||
WRITE_BYTES, 11,
|
||||
0x02, 0xF0, 0x00, 0x00,
|
||||
0x03, 0xF0, 0x00, 0x00,
|
||||
0x00, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE2,
|
||||
WRITE_BYTES, 12,
|
||||
0x10, 0x10, 0x40, 0x40,
|
||||
0xF2, 0xF0, 0x00, 0x00,
|
||||
0xF2, 0xF0, 0x00, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xE3,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE4, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE5,
|
||||
WRITE_BYTES, 16,
|
||||
0x07, 0xEF, 0xF0, 0xF0,
|
||||
0x09, 0xF1, 0xF0, 0xF0,
|
||||
0x03, 0xF3, 0xF0, 0xF0,
|
||||
0x05, 0xED, 0xF0, 0xF0,
|
||||
|
||||
WRITE_COMMAND_8, 0xE6,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE7, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE8,
|
||||
WRITE_BYTES, 16,
|
||||
0x08, 0xF0, 0xF0, 0xF0,
|
||||
0x0A, 0xF2, 0xF0, 0xF0,
|
||||
0x04, 0xF4, 0xF0, 0xF0,
|
||||
0x06, 0xEE, 0xF0, 0xF0,
|
||||
|
||||
WRITE_COMMAND_8, 0xEB,
|
||||
WRITE_BYTES, 7,
|
||||
0x00, 0x00, 0xE4, 0xE4,
|
||||
0x44, 0x88, 0x40,
|
||||
|
||||
WRITE_C8_D16, 0xEC, 0x78, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xED,
|
||||
WRITE_BYTES, 16,
|
||||
0x20, 0xF9, 0x87, 0x76,
|
||||
0x65, 0x54, 0x4F, 0xFF,
|
||||
0xFF, 0xF4, 0x45, 0x56,
|
||||
0x67, 0x78, 0x9F, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xEF,
|
||||
WRITE_BYTES, 6,
|
||||
0x10, 0x0D, 0x04, 0x08,
|
||||
0x3F, 0x1F,
|
||||
|
||||
// WRITE_C8_D8, 0xCD, 0x05,//Test
|
||||
|
||||
WRITE_C8_D8, 0x3A, 0x55,
|
||||
|
||||
WRITE_C8_D8, 0x36, 0x08,
|
||||
|
||||
WRITE_COMMAND_8, 0x11,
|
||||
|
||||
// WRITE_COMMAND_8, 0xFF,//Test
|
||||
// WRITE_BYTES, 5,
|
||||
// 0x77, 0x01, 0x00, 0x00,
|
||||
// 0x12,
|
||||
|
||||
// WRITE_C8_D8, 0xD1, 0x81,//Test
|
||||
// WRITE_C8_D8, 0xD2, 0x08,//Test
|
||||
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
|
||||
// WRITE_C8_D8, 0x35, 0x00,//Test
|
||||
// WRITE_C8_D8, 0xCE, 0x04,//Test
|
||||
|
||||
// WRITE_COMMAND_8, 0xF2,//Test
|
||||
// WRITE_BYTES, 4,
|
||||
// 0xF0, 0xA3, 0xA3, 0x71,
|
||||
|
||||
END_WRITE};
|
||||
Arduino_DataBus* bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
|
||||
XL95X5_CS /* XL CS */, XL95X5_SCLK /* XL SCK */, XL95X5_MOSI /* XL MOSI */);
|
||||
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
|
||||
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true /* useBigEndian */,
|
||||
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
|
||||
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
|
||||
|
||||
#else
|
||||
static const uint8_t st7701_4848S040_init[] = {
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
|
||||
|
||||
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
|
||||
WRITE_C8_D16, 0xC1, 0x0D, 0x02,
|
||||
WRITE_C8_D16, 0xC2, 0x31, 0x05,
|
||||
WRITE_C8_D8, 0xCD, 0x00, // 0xCD, 0x08 !!
|
||||
|
||||
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08,
|
||||
0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18,
|
||||
|
||||
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
|
||||
WRITE_BYTES, 16,
|
||||
0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08,
|
||||
0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18,
|
||||
|
||||
// PAGE1
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
|
||||
|
||||
WRITE_C8_D8, 0xB0, 0x60, // Vop=4.7375v
|
||||
WRITE_C8_D8, 0xB1, 0x32, // VCOM=32
|
||||
WRITE_C8_D8, 0xB2, 0x07, // VGH=15v
|
||||
WRITE_C8_D8, 0xB3, 0x80,
|
||||
WRITE_C8_D8, 0xB5, 0x49, // VGL=-10.17v
|
||||
WRITE_C8_D8, 0xB7, 0x85,
|
||||
WRITE_C8_D8, 0xB8, 0x21, // AVDD=6.6 & AVCL=-4.6
|
||||
WRITE_C8_D8, 0xC1, 0x78,
|
||||
WRITE_C8_D8, 0xC2, 0x78,
|
||||
|
||||
WRITE_COMMAND_8, 0xE0,
|
||||
WRITE_BYTES, 3, 0x00, 0x1B, 0x02,
|
||||
|
||||
WRITE_COMMAND_8, 0xE1,
|
||||
WRITE_BYTES, 11,
|
||||
0x08, 0xA0, 0x00, 0x00,
|
||||
0x07, 0xA0, 0x00, 0x00,
|
||||
0x00, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE2,
|
||||
WRITE_BYTES, 12,
|
||||
0x11, 0x11, 0x44, 0x44,
|
||||
0xED, 0xA0, 0x00, 0x00,
|
||||
0xEC, 0xA0, 0x00, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xE3,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE4, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE5,
|
||||
WRITE_BYTES, 16,
|
||||
0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0,
|
||||
0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0,
|
||||
|
||||
WRITE_COMMAND_8, 0xE6,
|
||||
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
|
||||
|
||||
WRITE_C8_D16, 0xE7, 0x44, 0x44,
|
||||
|
||||
WRITE_COMMAND_8, 0xE8,
|
||||
WRITE_BYTES, 16,
|
||||
0x09, 0xE8, 0xD8, 0xA0,
|
||||
0x0B, 0xEA, 0xD8, 0xA0,
|
||||
0x0D, 0xEC, 0xD8, 0xA0,
|
||||
0x0F, 0xEE, 0xD8, 0xA0,
|
||||
|
||||
WRITE_COMMAND_8, 0xEB,
|
||||
WRITE_BYTES, 7, 0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40,
|
||||
|
||||
WRITE_C8_D16, 0xEC, 0x3C, 0x00,
|
||||
|
||||
WRITE_COMMAND_8, 0xED,
|
||||
WRITE_BYTES, 16,
|
||||
0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA,
|
||||
|
||||
//-----------VAP & VAN---------------
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
|
||||
|
||||
WRITE_C8_D8, 0xE5, 0xE4,
|
||||
|
||||
WRITE_COMMAND_8, 0xFF,
|
||||
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// WRITE_COMMAND_8, 0x21, // 0x20 normal, 0x21 IPS !!
|
||||
WRITE_C8_D8, 0x3A, 0x50, // 0x70 RGB888, 0x60 RGB666, 0x50 RGB565
|
||||
WRITE_COMMAND_8, 0x11, // Sleep Out
|
||||
END_WRITE,
|
||||
|
||||
DELAY, 120,
|
||||
|
||||
BEGIN_WRITE,
|
||||
WRITE_COMMAND_8, 0x29, // Display On
|
||||
END_WRITE};
|
||||
Arduino_DataBus* bus = new Arduino_SWSPI(
|
||||
GFX_NOT_DEFINED /* DC */, SPI_LCD_CS /* CS */, SPI_LCD_SCLK /* SCK */, SPI_LCD_MOSI /* MOSI */, GFX_NOT_DEFINED /* MISO */);
|
||||
Arduino_ESP32RGBPanel* rgbpanel = new Arduino_ESP32RGBPanel(
|
||||
LCD_DE /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
|
||||
LCD_R0 /* B0 */, LCD_R1 /* B1 */, LCD_R2 /* B2 */, LCD_R3 /* B3 */, LCD_R4 /* B4 */,
|
||||
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
|
||||
LCD_B0 /* R0 */, LCD_B1 /* R1 */, LCD_B2 /* R2 */, LCD_B3 /* R3 */, LCD_B4 /* R4 */,
|
||||
1 /* hsync_polarity */, 10 /* hsync_front_porch */, 8 /* hsync_pulse_width */, 50 /* hsync_back_porch */,
|
||||
1 /* vsync_polarity */, 10 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 20 /* vsync_back_porch */,
|
||||
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true);
|
||||
Arduino_RGB_Display* gfx = new Arduino_RGB_Display(
|
||||
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
|
||||
bus, -1 /* RST */, st7701_4848S040_init, sizeof(st7701_4848S040_init));
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined HAS_GT911_TOUCH
|
||||
#include <Wire.h>
|
||||
#include <Touch_GT911.h>
|
||||
#define TOUCH_GT911_SCL 45
|
||||
#define TOUCH_GT911_SDA 19
|
||||
int touch_last_x = 0, touch_last_y = 0;
|
||||
uint32_t last_touch_read = 0;
|
||||
uint8_t is_new_touch_checked = false;
|
||||
Touch_GT911 ts = Touch_GT911(TOUCH_GT911_SDA, TOUCH_GT911_SCL, max(480, 0), max(480, 0));
|
||||
|
||||
void touch_init()
|
||||
{
|
||||
ts.begin();
|
||||
}
|
||||
void touch_loop()
|
||||
{
|
||||
if (millis() - last_touch_read >= 50) {
|
||||
last_touch_read = millis();
|
||||
ts.read();
|
||||
if (ts.isTouched)
|
||||
{
|
||||
touch_last_x = map(ts.points[0].x, 480, 0, 0, 480 - 1);
|
||||
touch_last_y = map(ts.points[0].y, 480, 0, 0, 480 - 1);
|
||||
Serial.printf("Touch position X: %i Y: %i\r\n", touch_last_x, touch_last_y);
|
||||
if(is_new_touch_checked == false)
|
||||
{
|
||||
is_new_touch_checked = true;
|
||||
if(touch_last_x <= 240)
|
||||
sendAvail(WAKEUP_REASON_BUTTON1);
|
||||
else
|
||||
sendAvail(WAKEUP_REASON_BUTTON2);
|
||||
}
|
||||
}else{
|
||||
is_new_touch_checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void touch_init()
|
||||
{
|
||||
}
|
||||
void touch_loop()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void TFTLog(String text) {
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
gfx->setTextSize(2);
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
gfx->fillScreen(BLACK);
|
||||
gfx->setCursor(0, 0);
|
||||
tftLogscreen = true;
|
||||
}
|
||||
if (text.isEmpty()) return;
|
||||
gfx->setTextColor(WHITE);
|
||||
gfx->println(text);
|
||||
|
||||
#else
|
||||
|
||||
if (tftLogscreen == false) {
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 0, (tft2.width() == 160 ? 1 : 2));
|
||||
@@ -53,6 +385,7 @@ void TFTLog(String text) {
|
||||
tft2.setTextColor(TFT_GREEN);
|
||||
}
|
||||
tft2.println(text);
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t findId(uint8_t mac[8]) {
|
||||
@@ -72,7 +405,13 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
memcpy(&eadr.src, mac, 6);
|
||||
eadr.adr.lastPacketRSSI = WiFi.RSSI();
|
||||
eadr.adr.currentChannel = config.channel;
|
||||
#ifdef TFT_HW_TYPE
|
||||
eadr.adr.hwType = TFT_HW_TYPE;
|
||||
#elif defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
eadr.adr.hwType = 0xE2;
|
||||
#else
|
||||
eadr.adr.hwType = (tft2.width() == 160 ? 0xE1 : 0xE0);
|
||||
#endif
|
||||
eadr.adr.wakeupReason = wakeupReason;
|
||||
eadr.adr.capabilities = 0;
|
||||
eadr.adr.tagSoftwareVersion = 0;
|
||||
@@ -81,25 +420,65 @@ void sendAvail(uint8_t wakeupReason) {
|
||||
}
|
||||
|
||||
void yellow_ap_display_init(void) {
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
|
||||
tftLogscreen = true;
|
||||
|
||||
pinMode(LCD_BL, OUTPUT);
|
||||
digitalWrite(LCD_BL, HIGH);
|
||||
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcAttachPin(LCD_BL, 1);
|
||||
ledcSetup(1, 1000, 8);
|
||||
ledcWrite(1, config.tft); // brightness
|
||||
#else
|
||||
ledcAttachChannel(LCD_BL, 1000, 8, 1);
|
||||
ledcWriteChannel(1, config.tft);
|
||||
#endif
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL
|
||||
Wire.begin(IIC_SDA, IIC_SCL);
|
||||
#endif
|
||||
gfx->begin();
|
||||
gfx->fillScreen(BLACK);
|
||||
|
||||
#else
|
||||
#ifdef HAS_ELECROW_C6
|
||||
YellowSense = 0;
|
||||
#else
|
||||
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
|
||||
#endif
|
||||
pinMode(TFT_BACKLIGHT, OUTPUT);
|
||||
digitalWrite(TFT_BACKLIGHT, LOW);
|
||||
|
||||
tft2.init();
|
||||
#ifdef ST7735_NANO_TLSR
|
||||
YellowSense = 0;
|
||||
tft2.setRotation(1);
|
||||
#else
|
||||
tft2.setRotation(YellowSense == 1 ? 1 : 3);
|
||||
#endif
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(12, 0, (tft2.width() == 160 ? 1 : 2));
|
||||
tft2.setTextColor(TFT_WHITE);
|
||||
tftLogscreen = true;
|
||||
|
||||
ledcSetup(6, 5000, 8);
|
||||
ledcAttachPin(TFT_BACKLIGHT, 6);
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(1, 5000, 8);
|
||||
ledcAttachPin(TFT_BACKLIGHT, 1);
|
||||
ledcWrite(1, config.tft);
|
||||
if (tft2.width() == 160) {
|
||||
GPIO.func_out_sel_cfg[TFT_BACKLIGHT].inv_sel = 1;
|
||||
}
|
||||
ledcWrite(6, config.tft);
|
||||
#else
|
||||
ledcAttachChannel(TFT_BACKLIGHT, 5000, 8, 1);
|
||||
ledcWriteChannel(1, config.tft);
|
||||
if (tft2.width() == 160) ledcOutputInvert(TFT_BACKLIGHT, true);
|
||||
#endif
|
||||
#endif
|
||||
touch_init();
|
||||
}
|
||||
|
||||
void yellow_ap_display_loop(void) {
|
||||
@@ -141,7 +520,19 @@ void yellow_ap_display_loop(void) {
|
||||
void* spriteData = spr.getPointer();
|
||||
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
|
||||
file.close();
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData));
|
||||
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t*)spriteData, dx, dy);
|
||||
spr.deleteSprite();
|
||||
#else
|
||||
spr.pushSprite(0, 0);
|
||||
#endif
|
||||
|
||||
tftLogscreen = false;
|
||||
|
||||
struct espXferComplete xfc = {0};
|
||||
@@ -150,6 +541,7 @@ void yellow_ap_display_loop(void) {
|
||||
}
|
||||
last_update = millis();
|
||||
}
|
||||
touch_loop();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -29,8 +29,8 @@ void updateLanguageFromConfig() {
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument doc(1024);
|
||||
StaticJsonDocument<80> filter;
|
||||
JsonDocument doc;
|
||||
JsonDocument filter;
|
||||
filter[String(currentLanguage)] = true;
|
||||
const DeserializationError error = deserializeJson(doc, file, DeserializationOption::Filter(filter));
|
||||
file.close();
|
||||
|
||||
@@ -36,6 +36,14 @@ struct ledInstruction {
|
||||
bool reQueue = false;
|
||||
};
|
||||
|
||||
void ledcSet(uint8_t channel, uint8_t brightness) {
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcWrite(channel, brightness);
|
||||
#else
|
||||
ledcWriteChannel(channel, brightness);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
|
||||
void addToRGBQueue(struct ledInstructionRGB* rgb, bool requeue) {
|
||||
@@ -132,8 +140,9 @@ void rgbIdleStep() {
|
||||
|
||||
void setBrightness(int brightness) {
|
||||
maxledbrightness = brightness;
|
||||
#ifdef HAS_TFT
|
||||
ledcWrite(6, config.tft);
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL || HAS_TFT
|
||||
ledcSet(1, config.tft);
|
||||
#endif
|
||||
#ifdef HAS_RGB_LED
|
||||
FastLED.setBrightness(maxledbrightness);
|
||||
@@ -145,8 +154,8 @@ void updateBrightnessFromConfig() {
|
||||
if (newbrightness != maxledbrightness) {
|
||||
setBrightness(newbrightness);
|
||||
}
|
||||
#ifdef HAS_TFT
|
||||
ledcWrite(6, config.tft);
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL || HAS_TFT
|
||||
ledcSet(1, config.tft);
|
||||
#endif
|
||||
if (apInfo.state == AP_STATE_NORADIO) addFadeMono(config.led);
|
||||
}
|
||||
@@ -167,11 +176,9 @@ void addFadeMono(uint8_t value) {
|
||||
}
|
||||
|
||||
void showMono(uint8_t brightness) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ledcWrite(7, 255 - gamma8[brightness]);
|
||||
#else
|
||||
ledcWrite(7, gamma8[brightness]);
|
||||
#endif
|
||||
if (FLASHER_LED != -1) {
|
||||
ledcSet(7, gamma8[brightness]);
|
||||
}
|
||||
}
|
||||
|
||||
void quickBlink(uint8_t repeat) {
|
||||
@@ -213,11 +220,13 @@ void ledTask(void* parameter) {
|
||||
|
||||
ledQueue = xQueueCreate(30, sizeof(struct ledInstruction*));
|
||||
|
||||
ledcSetup(7, 5000, 8);
|
||||
if (FLASHER_LED != -1) {
|
||||
digitalWrite(FLASHER_LED, HIGH);
|
||||
pinMode(FLASHER_LED, OUTPUT);
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(7, 5000, 8);
|
||||
ledcAttachPin(FLASHER_LED, 7);
|
||||
#else
|
||||
ledcAttachChannel(FLASHER_LED, 1000, 8, 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct ledInstruction* monoled = nullptr;
|
||||
@@ -288,7 +297,7 @@ void ledTask(void* parameter) {
|
||||
if (monoled->fadeTime <= 1) {
|
||||
showMono(monoled->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (monoled->fadeTime) {
|
||||
monoled->fadeTime--;
|
||||
@@ -304,4 +313,4 @@ void ledTask(void* parameter) {
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
#include <Arduino.h>
|
||||
#include <WiFi.h>
|
||||
#include <time.h>
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
#include <ETH.h>
|
||||
#endif
|
||||
|
||||
#include "contentmanager.h"
|
||||
#include "flasher.h"
|
||||
@@ -26,7 +29,9 @@
|
||||
#include "udp.h"
|
||||
#include "util.h"
|
||||
#include "web.h"
|
||||
#ifdef HAS_BLE_WRITER
|
||||
#include "ble_writer.h"
|
||||
#endif
|
||||
|
||||
util::Timer intervalContentRunner(seconds(1));
|
||||
util::Timer intervalSysinfo(seconds(5));
|
||||
@@ -46,7 +51,12 @@ void delayedStart(void* parameter) {
|
||||
}
|
||||
|
||||
void setup() {
|
||||
#ifdef UART_LOGGING_TX_ONLY_PIN
|
||||
Serial.begin(115200, SERIAL_8N1, -1, UART_LOGGING_TX_ONLY_PIN);
|
||||
gpio_set_drive_capability((gpio_num_t)FLASHER_AP_RXD, GPIO_DRIVE_CAP_0);
|
||||
#else
|
||||
Serial.begin(115200);
|
||||
#endif
|
||||
#if ARDUINO_USB_CDC_ON_BOOT == 1
|
||||
Serial.setTxTimeoutMs(0); // workaround bug in USB CDC that slows down serial output when no usb connected
|
||||
#endif
|
||||
@@ -112,6 +122,7 @@ void setup() {
|
||||
}
|
||||
*/
|
||||
|
||||
wm.initEth();
|
||||
initAPconfig();
|
||||
|
||||
updateLanguageFromConfig();
|
||||
@@ -148,7 +159,12 @@ void setup() {
|
||||
// We'll need to start the 'usbflasher' task for boards with a second (USB) port. This can be used as a 'flasher' interface, using a python script on the host
|
||||
xTaskCreate(usbFlasherTask, "usbflasher", 10000, NULL, 5, NULL);
|
||||
#else
|
||||
|
||||
#ifdef ETHERNET_CLK_MODE
|
||||
if (!(ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_IN || ETHERNET_CLK_MODE == ETH_CLOCK_GPIO0_OUT))
|
||||
#endif
|
||||
pinMode(0, INPUT_PULLUP);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
|
||||
@@ -15,6 +15,12 @@
|
||||
#include "ips_display.h"
|
||||
#endif
|
||||
|
||||
#include "commstructs.h"
|
||||
#ifndef SAVE_SPACE
|
||||
#include "g5/Group5.h"
|
||||
#include "g5/g5enc.inl"
|
||||
#endif
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
@@ -69,14 +75,43 @@ struct Error {
|
||||
int32_t b;
|
||||
};
|
||||
|
||||
uint32_t colorDistance(Color &c1, Color &c2, Error &e1) {
|
||||
e1.r = constrain(e1.r, -255, 255);
|
||||
e1.g = constrain(e1.g, -255, 255);
|
||||
e1.b = constrain(e1.b, -255, 255);
|
||||
uint32_t colorDistance(const Color &c1, const Color &c2, const Error &e1) {
|
||||
int32_t r_diff = c1.r + e1.r - c2.r;
|
||||
int32_t g_diff = c1.g + e1.g - c2.g;
|
||||
int32_t b_diff = c1.b + e1.b - c2.b;
|
||||
return 3 * r_diff * r_diff + 6 * g_diff * g_diff + b_diff * b_diff;
|
||||
if (abs(c1.r - c1.g) < 20 && abs(c1.b - c1.g) < 20) {
|
||||
if (abs(c2.r - c2.g) > 20 || abs(c2.b - c2.g) > 20) return 4294967295; // don't select color pixels on black and white
|
||||
}
|
||||
return 3 * r_diff * r_diff + 5.47 * g_diff * g_diff + 1.53 * b_diff * b_diff;
|
||||
}
|
||||
|
||||
std::tuple<int, int, float, float> findClosestColors(const Color &pixel, const std::vector<Color> &palette) {
|
||||
int closestIndex = -1, secondClosestIndex = -1;
|
||||
float closestDist = std::numeric_limits<float>::max();
|
||||
float secondClosestDist = std::numeric_limits<float>::max();
|
||||
for (size_t i = 0; i < palette.size(); ++i) {
|
||||
float dist = colorDistance(pixel, palette[i], (Error){0, 0, 0});
|
||||
if (dist < closestDist) {
|
||||
secondClosestIndex = closestIndex;
|
||||
secondClosestDist = closestDist;
|
||||
closestIndex = i;
|
||||
closestDist = dist;
|
||||
} else if (dist < secondClosestDist) {
|
||||
secondClosestIndex = i;
|
||||
secondClosestDist = dist;
|
||||
}
|
||||
}
|
||||
if (closestIndex != -1 && secondClosestIndex != -1) {
|
||||
auto rgbValue = [](const Color &color) {
|
||||
return (color.r << 16) | (color.g << 8) | color.b;
|
||||
};
|
||||
|
||||
if (rgbValue(palette[secondClosestIndex]) > rgbValue(palette[closestIndex])) {
|
||||
std::swap(closestIndex, secondClosestIndex);
|
||||
std::swap(closestDist, secondClosestDist);
|
||||
}
|
||||
}
|
||||
return { closestIndex, secondClosestIndex, closestDist, secondClosestDist};
|
||||
}
|
||||
|
||||
void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer_size, bool is_red) {
|
||||
@@ -84,7 +119,7 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
|
||||
if (imageParams.rotatebuffer % 2) {
|
||||
//turn the image 90 or 270
|
||||
// turn the image 90 or 270
|
||||
rotate = (rotate + 3) % 4;
|
||||
rotate = (rotate + (imageParams.rotatebuffer - 1)) % 4;
|
||||
bufw = spr.height();
|
||||
@@ -106,11 +141,7 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
Error *error_bufferold = new Error[bufw + 4];
|
||||
Error *error_buffernew = new Error[bufw + 4];
|
||||
|
||||
const uint8_t ditherMatrix[4][4] = {
|
||||
{0, 9, 2, 10},
|
||||
{12, 5, 14, 6},
|
||||
{3, 11, 1, 8},
|
||||
{15, 7, 13, 4}};
|
||||
size_t bitOffset = 0;
|
||||
|
||||
memset(error_bufferold, 0, bufw * sizeof(Error));
|
||||
for (uint16_t y = 0; y < bufh; y++) {
|
||||
@@ -131,43 +162,72 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
break;
|
||||
}
|
||||
|
||||
if (imageParams.dither == 2) {
|
||||
// Ordered dithering
|
||||
uint8_t ditherValue = ditherMatrix[y % 4][x % 4];
|
||||
error_bufferold[x].r = (ditherValue << 4) - 120; // * 256 / 16 - 128 + 8
|
||||
error_bufferold[x].g = (ditherValue << 4) - 120;
|
||||
error_bufferold[x].b = (ditherValue << 4) - 120;
|
||||
}
|
||||
|
||||
int best_color_index = 0;
|
||||
uint32_t best_color_distance = colorDistance(color, palette[0], error_bufferold[x]);
|
||||
|
||||
for (int i = 1; i < num_colors; i++) {
|
||||
if (best_color_distance == 0) break;
|
||||
uint32_t distance = colorDistance(color, palette[i], error_bufferold[x]);
|
||||
if (distance < best_color_distance) {
|
||||
best_color_distance = distance;
|
||||
best_color_index = i;
|
||||
if (imageParams.dither == 2) {
|
||||
// special ordered dithering
|
||||
auto [c1Index, c2Index, distC1, distC2] = findClosestColors(color, palette);
|
||||
Color c1 = palette[c1Index];
|
||||
Color c2 = palette[c2Index];
|
||||
float weight = distC1 / (distC1 + distC2);
|
||||
if (weight <= 0.03) {
|
||||
best_color_index = c1Index;
|
||||
} else if (weight < 0.30) {
|
||||
best_color_index = ((y % 2 && ((y / 2 + x) % 2)) ? c2Index : c1Index);
|
||||
} else if (weight < 0.70) {
|
||||
best_color_index = ((x + y) % 2 ? c2Index : c1Index);
|
||||
} else if (weight < 0.97) {
|
||||
best_color_index = ((y % 2 && ((y / 2 + x) % 2)) % 2 ? c1Index : c2Index);
|
||||
} else {
|
||||
best_color_index = c2Index;
|
||||
}
|
||||
}
|
||||
uint8_t bitIndex = 7 - (x % 8);
|
||||
uint32_t byteIndex = (y * bufw + x) / 8;
|
||||
|
||||
// this looks a bit ugly, but it's performing better than shorter notations
|
||||
switch (best_color_index) {
|
||||
case 1:
|
||||
if (!is_red)
|
||||
if (imageParams.dither == 1 || imageParams.dither == 0) {
|
||||
uint32_t best_color_distance = colorDistance(color, palette[0], error_bufferold[x]);
|
||||
|
||||
for (int i = 1; i < num_colors; i++) {
|
||||
if (best_color_distance == 0) break;
|
||||
uint32_t distance = colorDistance(color, palette[i], error_bufferold[x]);
|
||||
if (distance < best_color_distance) {
|
||||
best_color_distance = distance;
|
||||
best_color_index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (imageParams.bpp == 3 || imageParams.bpp == 4) {
|
||||
size_t byteIndex = bitOffset / 8;
|
||||
uint8_t bitIndex = bitOffset % 8;
|
||||
|
||||
if (bitIndex + imageParams.bpp <= 8) {
|
||||
buffer[byteIndex] |= best_color_index << (8 - bitIndex - imageParams.bpp);
|
||||
} else {
|
||||
uint8_t highPart = best_color_index >> (bitIndex + imageParams.bpp - 8);
|
||||
uint8_t lowPart = best_color_index & ((1 << (bitIndex + imageParams.bpp - 8)) - 1);
|
||||
buffer[byteIndex] |= highPart;
|
||||
buffer[byteIndex + 1] |= lowPart << (8 - (bitIndex + imageParams.bpp - 8));
|
||||
}
|
||||
bitOffset += imageParams.bpp;
|
||||
} else {
|
||||
uint8_t bitIndex = 7 - (x % 8);
|
||||
uint32_t byteIndex = (y * bufw + x) / 8;
|
||||
|
||||
// this looks a bit ugly, but it's performing better than shorter notations
|
||||
switch (best_color_index) {
|
||||
case 1:
|
||||
if (!is_red)
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 2:
|
||||
imageParams.hasRed = true;
|
||||
if (is_red)
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 3:
|
||||
imageParams.hasRed = true;
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 2:
|
||||
imageParams.hasRed = true;
|
||||
if (is_red)
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 3:
|
||||
imageParams.hasRed = true;
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (imageParams.dither == 1) {
|
||||
@@ -178,34 +238,44 @@ void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t
|
||||
color.g + error_bufferold[x].g - palette[best_color_index].g,
|
||||
color.b + error_bufferold[x].b - palette[best_color_index].b};
|
||||
|
||||
error_buffernew[x].r += error.r >> 2;
|
||||
error_buffernew[x].g += error.g >> 2;
|
||||
error_buffernew[x].b += error.b >> 2;
|
||||
float scaling_factor = 255.0f / std::max(std::abs(error.r), std::max(std::abs(error.g), std::abs(error.b)));
|
||||
if (scaling_factor < 1.0f) {
|
||||
error.r *= scaling_factor;
|
||||
error.g *= scaling_factor;
|
||||
error.b *= scaling_factor;
|
||||
}
|
||||
|
||||
error_buffernew[x].r += error.r / 4;
|
||||
error_buffernew[x].g += error.g / 4;
|
||||
error_buffernew[x].b += error.b / 4;
|
||||
|
||||
if (x > 0) {
|
||||
error_buffernew[x - 1].r += error.r >> 3;
|
||||
error_buffernew[x - 1].g += error.g >> 3;
|
||||
error_buffernew[x - 1].b += error.b >> 3;
|
||||
error_buffernew[x - 1].r += error.r / 8;
|
||||
error_buffernew[x - 1].g += error.g / 8;
|
||||
error_buffernew[x - 1].b += error.b / 8;
|
||||
}
|
||||
|
||||
if (x > 1) {
|
||||
error_buffernew[x - 2].r += error.r >> 4;
|
||||
error_buffernew[x - 2].g += error.g >> 4;
|
||||
error_buffernew[x - 2].b += error.b >> 4;
|
||||
error_buffernew[x - 2].r += error.r / 16;
|
||||
error_buffernew[x - 2].g += error.g / 16;
|
||||
error_buffernew[x - 2].b += error.b / 16;
|
||||
}
|
||||
error_buffernew[x + 1].r += error.r >> 3;
|
||||
error_buffernew[x + 1].g += error.g >> 3;
|
||||
error_buffernew[x + 1].b += error.b >> 3;
|
||||
|
||||
error_bufferold[x + 1].r += error.r >> 2;
|
||||
error_bufferold[x + 1].g += error.g >> 2;
|
||||
error_bufferold[x + 1].b += error.b >> 2;
|
||||
error_buffernew[x + 1].r += error.r / 8;
|
||||
error_buffernew[x + 1].g += error.g / 8;
|
||||
error_buffernew[x + 1].b += error.b / 8;
|
||||
|
||||
error_buffernew[x + 2].r += error.r >> 4;
|
||||
error_buffernew[x + 2].g += error.g >> 4;
|
||||
error_buffernew[x + 2].b += error.b >> 4;
|
||||
error_bufferold[x + 1].r += error.r / 4;
|
||||
error_bufferold[x + 1].g += error.g / 4;
|
||||
error_bufferold[x + 1].b += error.b / 4;
|
||||
|
||||
error_bufferold[x + 2].r += error.r >> 3;
|
||||
error_bufferold[x + 2].g += error.g >> 3;
|
||||
error_bufferold[x + 2].b += error.b >> 3;
|
||||
error_buffernew[x + 2].r += error.r / 16;
|
||||
error_buffernew[x + 2].g += error.g / 16;
|
||||
error_buffernew[x + 2].b += error.b / 16;
|
||||
|
||||
error_bufferold[x + 2].r += error.r / 8;
|
||||
error_bufferold[x + 2].g += error.g / 8;
|
||||
error_bufferold[x + 2].b += error.b / 8;
|
||||
}
|
||||
}
|
||||
memcpy(error_bufferold, error_buffernew, bufw * sizeof(Error));
|
||||
@@ -225,7 +295,10 @@ size_t prepareHeader(uint8_t headerbuf[], uint16_t bufw, uint16_t bufh, imgParam
|
||||
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 3 : 1), &bufw, sizeof(uint16_t));
|
||||
memcpy(headerbuf + (imageParams.rotatebuffer % 2 == 1 ? 1 : 3), &bufh, sizeof(uint16_t));
|
||||
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
if (imageParams.bpp == 3 || imageParams.bpp == 4) {
|
||||
totalbytes = buffer_size * imageParams.bpp + headersize;
|
||||
headerbuf[5] = imageParams.bpp;
|
||||
} else if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
totalbytes = buffer_size * 2 + headersize;
|
||||
headerbuf[5] = 2;
|
||||
} else {
|
||||
@@ -265,15 +338,96 @@ void rewriteHeader(File &f_out) {
|
||||
f_out.write(flg);
|
||||
}
|
||||
|
||||
#ifndef SAVE_SPACE
|
||||
uint8_t *g5Compress(uint16_t width, uint16_t height, uint8_t *buffer, uint16_t buffersize, uint16_t &outBufferSize) {
|
||||
G5ENCIMAGE g5enc;
|
||||
int rc;
|
||||
uint8_t *outbuffer = (uint8_t *)ps_malloc(buffersize+16384);
|
||||
if (outbuffer == NULL) {
|
||||
Serial.println("Failed to allocate the output buffer for the G5 encoder");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rc = g5_encode_init(&g5enc, width, height, outbuffer, buffersize);
|
||||
for (int y = 0; y < height && rc == G5_SUCCESS; y++) {
|
||||
rc = g5_encode_encodeLine(&g5enc, buffer);
|
||||
buffer += (width / 8);
|
||||
if (rc != G5_SUCCESS) break;
|
||||
}
|
||||
if (rc == G5_ENCODE_COMPLETE) {
|
||||
outBufferSize = g5_encode_getOutSize(&g5enc);
|
||||
} else {
|
||||
printf("Encode failed! rc=%d\n", rc);
|
||||
free(outbuffer);
|
||||
return nullptr;
|
||||
}
|
||||
return outbuffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The "ts_option" is a bitmapped variable with a default value of 1
|
||||
// which is black on white, long format @ bottom right.
|
||||
//
|
||||
// b2, b1, b0:
|
||||
// 0 - no timestamp
|
||||
// 1 - bottom right
|
||||
// 2 - top right
|
||||
// 3 - bottom left
|
||||
// 4 - top left
|
||||
// 5 -> 7 reserved
|
||||
// b3:
|
||||
// 0 - long format (year-month-day hr:min)
|
||||
// 1 - short format (month-day hr:min)
|
||||
// b4:
|
||||
// 0 - black on white
|
||||
// 1 - white on black
|
||||
// b5 -> b7: reserved
|
||||
//
|
||||
void doTimestamp(TFT_eSprite *spr, uint8_t ts_option) {
|
||||
time_t now = time(nullptr);
|
||||
struct tm *timeinfo = localtime(&now);
|
||||
char buffer[20];
|
||||
strftime(buffer, sizeof(buffer),
|
||||
(ts_option & 0x8) ? "%m-%d %H:%M" : "%Y-%m-%d %H:%M",timeinfo);
|
||||
int ts_chars = strlen(buffer);
|
||||
|
||||
uint16_t char_color;
|
||||
uint16_t bg_color;
|
||||
|
||||
if(ts_option & 0x10) {
|
||||
char_color = TFT_WHITE;
|
||||
bg_color= TFT_BLACK;
|
||||
}
|
||||
else {
|
||||
char_color = TFT_BLACK;
|
||||
bg_color = TFT_WHITE;
|
||||
}
|
||||
|
||||
ts_option = (ts_option & 0x3) - 1;
|
||||
|
||||
int32_t ts_x = (ts_option & 2) ? 1 : spr->width() - ts_chars * 6 - 2;
|
||||
int32_t ts_y = (ts_option & 1) ? 1 : spr->height() - 10;
|
||||
|
||||
spr->drawRect(ts_x - 1, ts_y - 1, ts_chars * 6 + 1, 9, bg_color);
|
||||
spr->setTextColor(char_color, bg_color);
|
||||
spr->setCursor(ts_x,ts_y);
|
||||
spr->print(buffer);
|
||||
}
|
||||
|
||||
void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
long t = millis();
|
||||
|
||||
if (imageParams.ts_option) doTimestamp(&spr,imageParams.ts_option);
|
||||
#ifdef HAS_TFT
|
||||
extern uint8_t YellowSense;
|
||||
if (fileout == "direct") {
|
||||
if (tftOverride == false) {
|
||||
TFT_eSprite spr2 = TFT_eSprite(&tft2);
|
||||
#ifdef ST7735_NANO_TLSR
|
||||
tft2.setRotation(1);
|
||||
#else
|
||||
tft2.setRotation(YellowSense == 1 ? 1 : 3);
|
||||
#endif
|
||||
spr2.createSprite(spr.width(), spr.height());
|
||||
spr2.setColorDepth(spr.getColorDepth());
|
||||
|
||||
@@ -282,7 +436,19 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
size_t dataSize = spr.width() * spr.height() * (spr.getColorDepth() / 8);
|
||||
memcpy(spriteData2, spriteData, dataSize);
|
||||
|
||||
#if defined HAS_LILYGO_TPANEL || defined HAS_4inch_TPANEL
|
||||
if (spr.getColorDepth() == 16) {
|
||||
long dy = spr.height();
|
||||
long dx = spr.width();
|
||||
|
||||
uint16_t *data = static_cast<uint16_t *>(const_cast<void *>(spriteData2));
|
||||
|
||||
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData2, dx, dy);
|
||||
spr2.deleteSprite();
|
||||
}
|
||||
#else
|
||||
spr2.pushSprite(0, 0);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -301,6 +467,7 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
#else
|
||||
uint8_t *buffer = (uint8_t *)malloc(buffer_size);
|
||||
imageParams.zlib = 0;
|
||||
imageParams.g5 = 0;
|
||||
#endif
|
||||
if (!buffer) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
@@ -341,6 +508,69 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
free(comp);
|
||||
|
||||
rewriteHeader(f_out);
|
||||
#ifndef SAVE_SPACE
|
||||
} else if (imageParams.g5) {
|
||||
// handling for G5-compressed image data
|
||||
|
||||
uint8_t headerbuf[6];
|
||||
prepareHeader(headerbuf, bufw, bufh, imageParams, buffer_size);
|
||||
f_out.write(headerbuf, sizeof(headerbuf));
|
||||
|
||||
uint16_t height = imageParams.height; // spr.height();
|
||||
uint16_t width = imageParams.width;
|
||||
spr.width();
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
uint8_t *newbuffer = (uint8_t *)ps_realloc(buffer, 2 * buffer_size);
|
||||
if (newbuffer == NULL) {
|
||||
Serial.println("Failed to allocate larger buffer for 2bpp G5");
|
||||
free(buffer);
|
||||
f_out.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
return;
|
||||
}
|
||||
buffer = newbuffer;
|
||||
spr2color(spr, imageParams, buffer + buffer_size, buffer_size, true);
|
||||
buffer_size *= 2;
|
||||
// double the height, to do two layers sequentially
|
||||
if (imageParams.rotatebuffer % 2) {
|
||||
width *= 2;
|
||||
} else {
|
||||
height *= 2;
|
||||
}
|
||||
}
|
||||
uint16_t outbufferSize = 0;
|
||||
uint8_t *outBuffer;
|
||||
bool compressionSuccessful = true;
|
||||
if (imageParams.rotatebuffer % 2) {
|
||||
outBuffer = g5Compress(height, width, buffer, buffer_size, outbufferSize);
|
||||
} else {
|
||||
outBuffer = g5Compress(width, height, buffer, buffer_size, outbufferSize);
|
||||
}
|
||||
if (outBuffer == NULL) {
|
||||
Serial.println("Failed to compress G5");
|
||||
compressionSuccessful = false;
|
||||
} else {
|
||||
printf("Compressed %d to %d bytes\n", buffer_size, outbufferSize);
|
||||
if (outbufferSize > buffer_size) {
|
||||
printf("That wasn't very useful, falling back to raw\n");
|
||||
compressionSuccessful = false;
|
||||
} else {
|
||||
f_out.write(outBuffer, outbufferSize);
|
||||
}
|
||||
free(outBuffer);
|
||||
}
|
||||
if (!compressionSuccessful) {
|
||||
// if we failed to compress the image, or the resulting image was larger than a raw file, fallback
|
||||
imageParams.g5 = false;
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_2BPP;
|
||||
} else {
|
||||
imageParams.dataType = DATATYPE_IMG_RAW_1BPP;
|
||||
}
|
||||
f_out.seek(0);
|
||||
f_out.write(buffer, buffer_size);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
f_out.write(buffer, buffer_size);
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
@@ -352,6 +582,24 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
free(buffer);
|
||||
} break;
|
||||
|
||||
case 3:
|
||||
case 4: {
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
size_t buffer_size = (bufw * bufh) / 8 * imageParams.bpp;
|
||||
uint8_t *buffer = (uint8_t *)ps_malloc(buffer_size);
|
||||
if (!buffer) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
util::printLargestFreeBlock();
|
||||
f_out.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
return;
|
||||
}
|
||||
spr2color(spr, imageParams, buffer, buffer_size, false);
|
||||
f_out.write(buffer, buffer_size);
|
||||
|
||||
free(buffer);
|
||||
} break;
|
||||
|
||||
case 16: {
|
||||
size_t spriteDataSize = (spr.getColorDepth() == 1) ? (spr.width() * spr.height() / 8) : ((spr.getColorDepth() == 8) ? (spr.width() * spr.height()) : ((spr.getColorDepth() == 16) ? (spr.width() * spr.height() * 2) : 0));
|
||||
f_out.write((const uint8_t *)spr.getPointer(), spriteDataSize);
|
||||
|
||||
@@ -273,7 +273,10 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
case DATATYPE_IMG_DIFF:
|
||||
case DATATYPE_IMG_ZLIB:
|
||||
case DATATYPE_IMG_RAW_1BPP:
|
||||
case DATATYPE_IMG_RAW_2BPP: {
|
||||
case DATATYPE_IMG_RAW_2BPP:
|
||||
case DATATYPE_IMG_G5:
|
||||
case DATATYPE_IMG_RAW_3BPP:
|
||||
case DATATYPE_IMG_RAW_4BPP: {
|
||||
char hexmac[17];
|
||||
mac2hex(pending->targetMac, hexmac);
|
||||
String filename = "/current/" + String(hexmac) + "_" + String(millis() % 1000000) + ".pending";
|
||||
@@ -336,8 +339,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
break;
|
||||
}
|
||||
case DATATYPE_NFC_RAW_CONTENT:
|
||||
case DATATYPE_NFC_URL_DIRECT:
|
||||
case DATATYPE_CUSTOM_LUT_OTA: {
|
||||
case DATATYPE_NFC_URL_DIRECT: {
|
||||
char hexmac[17];
|
||||
mac2hex(pending->targetMac, hexmac);
|
||||
char dataUrl[80];
|
||||
@@ -346,7 +348,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
snprintf(dataUrl, sizeof(dataUrl), "http://%s/getdata?mac=%s&md5=%s", remoteIP.toString().c_str(), hexmac, md5);
|
||||
wsLog("GET " + String(dataUrl));
|
||||
HTTPClient http;
|
||||
logLine("http DATATYPE_CUSTOM_LUT_OTA " + String(dataUrl));
|
||||
logLine("http DATATYPE_NFC_* " + String(dataUrl));
|
||||
http.begin(dataUrl);
|
||||
int httpCode = http.GET();
|
||||
if (httpCode == 200) {
|
||||
@@ -445,9 +447,11 @@ void processXferComplete(struct espXferComplete* xfc, bool local) {
|
||||
contentFS->remove(dst_path);
|
||||
}
|
||||
if (contentFS->exists(queueItem->filename)) {
|
||||
if (config.preview && (queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP || queueItem->pendingdata.availdatainfo.dataType == DATATYPE_IMG_ZLIB)) {
|
||||
uint8_t dataType = queueItem->pendingdata.availdatainfo.dataType;
|
||||
if (config.preview && dataType != DATATYPE_FW_UPDATE && dataType != DATATYPE_NOUPDATE) {
|
||||
contentFS->rename(queueItem->filename, String(dst_path));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (queueItem->pendingdata.availdatainfo.dataType != DATATYPE_FW_UPDATE) contentFS->remove(queueItem->filename);
|
||||
}
|
||||
}
|
||||
@@ -503,9 +507,9 @@ void processXferTimeout(struct espXferComplete* xfc, bool local) {
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->pendingIdle = 60;
|
||||
clearPending(taginfo);
|
||||
while (dequeueItem(xfc->src)) {
|
||||
};
|
||||
}
|
||||
while (dequeueItem(xfc->src)) {
|
||||
};
|
||||
|
||||
checkQueue(xfc->src);
|
||||
|
||||
@@ -556,15 +560,14 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
|
||||
taginfo->apIp = IPAddress(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (taginfo->pendingIdle == 0) {
|
||||
taginfo->expectedNextCheckin = now + 60;
|
||||
if (taginfo->pendingIdle == 0 || countQueueItem(eadr->src) > 0) {
|
||||
if (taginfo->expectedNextCheckin < now + 60) taginfo->expectedNextCheckin = now + 60;
|
||||
} else if (taginfo->pendingIdle == 9999) {
|
||||
taginfo->expectedNextCheckin = 3216153600;
|
||||
taginfo->pendingIdle = 0;
|
||||
} else {
|
||||
taginfo->expectedNextCheckin = now + taginfo->pendingIdle;
|
||||
taginfo->pendingIdle = 0;
|
||||
}
|
||||
taginfo->pendingIdle = 0;
|
||||
taginfo->lastseen = now;
|
||||
|
||||
if (eadr->adr.lastPacketRSSI != 0) {
|
||||
@@ -603,6 +606,7 @@ void processDataReq(struct espAvailDataReq* eadr, bool local, IPAddress remoteIP
|
||||
if (local) {
|
||||
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X%02X%02X\r\n\0", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0]);
|
||||
Serial.print(buffer);
|
||||
checkQueue(eadr->src); // experiemental 3/26/25: redundant check
|
||||
}
|
||||
|
||||
if (local) {
|
||||
@@ -748,6 +752,35 @@ bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local, const uint8_t*
|
||||
}
|
||||
}
|
||||
|
||||
bool sendTagMac(const uint8_t* dst, const uint64_t newmac, bool local) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_COMMAND_DATA;
|
||||
pending.availdatainfo.dataTypeArgument = 0x23;
|
||||
pending.availdatainfo.nextCheckIn = 0;
|
||||
|
||||
|
||||
pending.availdatainfo.dataVer = newmac;
|
||||
pending.availdatainfo.dataSize = 0;
|
||||
|
||||
pending.attemptsLeft = MAX_XFER_ATTEMPTS;
|
||||
Serial.printf(">Tag %02X%02X%02X%02X%02X%02X%02X%02X Mac set\r\n\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
|
||||
|
||||
tagRecord* taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->pendingCount++;
|
||||
wsSendTaginfo(taginfo->mac, SYNC_TAGSTATUS);
|
||||
}
|
||||
|
||||
if (local) {
|
||||
return queueDataAvail(&pending, true);
|
||||
} else {
|
||||
queueDataAvail(&pending, false);
|
||||
udpsync.netSendDataAvail(&pending);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void updateTaginfoitem(struct TagInfo* taginfoitem, IPAddress remoteIP) {
|
||||
tagRecord* taginfo = tagRecord::findByMAC(taginfoitem->mac);
|
||||
|
||||
@@ -800,7 +833,7 @@ bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) {
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* taginfo2 = tagDB.at(c);
|
||||
if (taginfo2->contentMode == 20 && taginfo2->version == 0) {
|
||||
DynamicJsonDocument doc(500);
|
||||
JsonDocument doc;
|
||||
deserializeJson(doc, taginfo2->modeConfigJson);
|
||||
JsonObject cfgobj = doc.as<JsonObject>();
|
||||
uint8_t mac[8] = {0};
|
||||
@@ -953,20 +986,23 @@ bool queueDataAvail(struct pendingData* pending, bool local) {
|
||||
taginfo->data = nullptr;
|
||||
} else {
|
||||
newPending.data = nullptr;
|
||||
|
||||
// optional: read data early, don't wait for block request.
|
||||
fs::File file = contentFS->open(newPending.filename);
|
||||
if (file) {
|
||||
newPending.data = getDataForFile(file);
|
||||
Serial.println("Reading file " + String(newPending.filename));
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Warning: not found: " + String(newPending.filename));
|
||||
|
||||
if (pendingQueue.size() < 5) { // maximized to 5 to save some memory
|
||||
// optional: read data early, don't wait for block request.
|
||||
fs::File file = contentFS->open(newPending.filename);
|
||||
if (file) {
|
||||
newPending.data = getDataForFile(file);
|
||||
Serial.println("Reading file " + String(newPending.filename));
|
||||
file.close();
|
||||
} else {
|
||||
Serial.println("Warning: not found: " + String(newPending.filename));
|
||||
}
|
||||
}
|
||||
}
|
||||
newPending.len = taginfo->len;
|
||||
|
||||
if ((pending->availdatainfo.dataType == DATATYPE_IMG_RAW_1BPP || pending->availdatainfo.dataType == DATATYPE_IMG_RAW_2BPP || pending->availdatainfo.dataType == DATATYPE_IMG_ZLIB) && (pending->availdatainfo.dataTypeArgument & 0xF8) == 0x00) {
|
||||
uint8_t dataType = pending->availdatainfo.dataType;
|
||||
if (dataType != DATATYPE_FW_UPDATE && dataType != DATATYPE_NOUPDATE && pending->availdatainfo.dataTypeArgument & 0xF8 == 0x00) {
|
||||
// in case of an image (no preload), remove already queued images
|
||||
pendingQueue.erase(std::remove_if(pendingQueue.begin(), pendingQueue.end(),
|
||||
[pending](const PendingItem& item) {
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <MD5Builder.h>
|
||||
#include <Update.h>
|
||||
|
||||
#include "flasher.h"
|
||||
#include "espflasher.h"
|
||||
#include "leds.h"
|
||||
#include "serialap.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "util.h"
|
||||
#include "web.h"
|
||||
|
||||
|
||||
#ifndef BUILD_ENV_NAME
|
||||
#define BUILD_ENV_NAME unknown
|
||||
#endif
|
||||
@@ -30,9 +32,11 @@
|
||||
|
||||
#define STR_IMPL(x) #x
|
||||
#define STR(x) STR_IMPL(x)
|
||||
#define LOG(format, ... ) Serial.printf(format,## __VA_ARGS__)
|
||||
|
||||
|
||||
void handleSysinfoRequest(AsyncWebServerRequest* request) {
|
||||
StaticJsonDocument<250> doc;
|
||||
JsonDocument doc;
|
||||
doc["alias"] = config.alias;
|
||||
doc["env"] = STR(BUILD_ENV_NAME);
|
||||
doc["buildtime"] = STR(BUILD_TIME);
|
||||
@@ -41,11 +45,20 @@ void handleSysinfoRequest(AsyncWebServerRequest* request) {
|
||||
doc["psramsize"] = ESP.getPsramSize();
|
||||
doc["flashsize"] = ESP.getFlashChipSize();
|
||||
doc["rollback"] = Update.canRollBack();
|
||||
#if defined C6_OTA_FLASHING
|
||||
doc["hasC6"] = 1;
|
||||
#else
|
||||
doc["ap_version"] = apInfo.version;
|
||||
|
||||
doc["hasC6"] = 0;
|
||||
doc["hasH2"] = 0;
|
||||
doc["hasTslr"] = 0;
|
||||
|
||||
#if defined HAS_H2
|
||||
doc["hasH2"] = 1;
|
||||
#elif defined HAS_TSLR
|
||||
doc["hasTslr"] = 1;
|
||||
#elif defined C6_OTA_FLASHING
|
||||
doc["hasC6"] = 1;
|
||||
#endif
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
doc["hasFlasher"] = 1;
|
||||
#else
|
||||
@@ -66,7 +79,7 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
const String filePath = request->getParam("path")->value();
|
||||
File file = contentFS->open(filePath, "r");
|
||||
if (!file) {
|
||||
StaticJsonDocument<64> doc;
|
||||
JsonDocument doc;
|
||||
doc["filesize"] = 0;
|
||||
doc["md5"] = "";
|
||||
String jsonResponse;
|
||||
@@ -85,7 +98,7 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
|
||||
file.close();
|
||||
|
||||
StaticJsonDocument<128> doc;
|
||||
JsonDocument doc;
|
||||
doc["filesize"] = fileSize;
|
||||
doc["md5"] = md5Hash;
|
||||
String jsonResponse;
|
||||
@@ -135,12 +148,13 @@ void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
uploadInfo->bufferSize = 0;
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
final = true;
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
|
||||
memcpy(uploadInfo->buffer, data, len);
|
||||
uploadInfo->bufferSize = len;
|
||||
@@ -153,11 +167,12 @@ void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_
|
||||
if (file) {
|
||||
file.write(uploadInfo->buffer, uploadInfo->bufferSize);
|
||||
file.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
} else {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("Failed to open file for appending: " + uploadfilename);
|
||||
error = true;
|
||||
}
|
||||
xSemaphoreGive(fsMutex);
|
||||
request->_tempObject = nullptr;
|
||||
delete uploadInfo;
|
||||
}
|
||||
@@ -289,22 +304,29 @@ void handleRollback(AsyncWebServerRequest* request) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef C6_OTA_FLASHING
|
||||
void C6firmwareUpdateTask(void* parameter) {
|
||||
uint8_t doDownload = *((uint8_t*)parameter);
|
||||
char* urlPtr = reinterpret_cast<char*>(parameter);
|
||||
|
||||
LOG("C6firmwareUpdateTask: url '%s'\n", urlPtr);
|
||||
wsSerial("Stopping AP service");
|
||||
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
gSerialTaskState = SERIAL_STATE_STOP;
|
||||
config.runStatus = RUNSTATUS_STOP;
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
extern bool rxSerialStopTask2;
|
||||
rxSerialStopTask2 = true;
|
||||
#endif
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
Serial1.end();
|
||||
setAPstate(false, AP_STATE_FLASHING);
|
||||
|
||||
wsSerial("C6 flash starting");
|
||||
wsSerial(SHORT_CHIP_NAME " flash starting");
|
||||
|
||||
bool result = doC6flash(doDownload);
|
||||
bool result = FlashC6_H2(urlPtr);
|
||||
|
||||
wsSerial("C6 flash end");
|
||||
wsSerial(SHORT_CHIP_NAME " flash end");
|
||||
|
||||
if (result) {
|
||||
setAPstate(false, AP_STATE_OFFLINE);
|
||||
@@ -314,36 +336,65 @@ void C6firmwareUpdateTask(void* parameter) {
|
||||
|
||||
wsSerial("starting monitor");
|
||||
Serial1.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
rxSerialStopTask2 = false;
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL);
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL);
|
||||
#endif
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
wsSerial("resetting AP");
|
||||
APTagReset();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
|
||||
apInfo.version = 0;
|
||||
wsSerial("bringing AP online");
|
||||
if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN;
|
||||
// if (bringAPOnline(AP_STATE_REQUIRED_POWER_CYCLE)) config.runStatus = RUNSTATUS_STOP;
|
||||
if (bringAPOnline(AP_STATE_ONLINE)) {
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
|
||||
wsSerial("Finished!");
|
||||
} else {
|
||||
wsSerial("Flashing failed. :-(");
|
||||
// Wait for version info to arrive
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
if(apInfo.version == 0) {
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
wsSerial("Finished!");
|
||||
char buffer[50];
|
||||
snprintf(buffer,sizeof(buffer),
|
||||
"ESP32-" SHORT_CHIP_NAME " version is now %04x", apInfo.version);
|
||||
wsSerial(String(buffer));
|
||||
}
|
||||
else if(apInfo.version == 0) {
|
||||
wsSerial("AP failed to come online. :-(");
|
||||
}
|
||||
else {
|
||||
wsSerial("Flashing failed. :-(");
|
||||
}
|
||||
// wsSerial("Reboot system now");
|
||||
// wsSerial("[reboot]");
|
||||
free(urlPtr);
|
||||
vTaskDelay(30000 / portTICK_PERIOD_MS);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void handleUpdateC6(AsyncWebServerRequest* request) {
|
||||
#if defined C6_OTA_FLASHING
|
||||
uint8_t doDownload = 1;
|
||||
if (request->hasParam("download", true)) {
|
||||
doDownload = atoi(request->getParam("download", true)->value().c_str());
|
||||
if (request->hasParam("url",true)) {
|
||||
const char* urlStr = request->getParam("url", true)->value().c_str();
|
||||
char* urlCopy = strdup(urlStr);
|
||||
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6400, urlCopy, 10, NULL);
|
||||
request->send(200, "Ok");
|
||||
}
|
||||
xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6144, &doDownload, 10, NULL);
|
||||
request->send(200, "Ok");
|
||||
else {
|
||||
LOG("Sending bad request");
|
||||
request->send(400, "Bad request");
|
||||
}
|
||||
#elif defined(SHORT_CHIP_NAME)
|
||||
request->send(400, SHORT_CHIP_NAME " flashing not implemented");
|
||||
#else
|
||||
request->send(400, "C6 flashing not implemented");
|
||||
request->send(400, "C6/H2 flashing not implemented");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -355,7 +406,7 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||
request->send(200, "No update actions needed");
|
||||
return;
|
||||
}
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
const JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
||||
for (const auto& filePath : deleteFiles) {
|
||||
@@ -367,4 +418,4 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||
wsSerial("Cleanup finished");
|
||||
request->send(200, "Clean up finished");
|
||||
contentFS->remove("/update_actions.json");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "settings.h"
|
||||
#include "leds.h"
|
||||
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
@@ -34,16 +35,21 @@ void rampTagPower(uint8_t* pin, bool up) {
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
|
||||
#endif
|
||||
if (up) {
|
||||
#if ESP_ARDUINO_VERSION_MAJOR == 2
|
||||
ledcSetup(0, 50000, 8);
|
||||
ledcWrite(0, 254);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
#else
|
||||
ledcWriteChannel(0, 254);
|
||||
ledcAttachChannel(pin[0], 50000, 8, 0);
|
||||
#endif
|
||||
pinMode(FLASHER_EXT_RESET, OUTPUT);
|
||||
digitalWrite(FLASHER_EXT_RESET, LOW);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 254; c != 0xFF; c--) {
|
||||
ledcWrite(0, c);
|
||||
ledcSet(0, c);
|
||||
delayMicroseconds(700);
|
||||
}
|
||||
digitalWrite(pin[0], LOW);
|
||||
@@ -52,14 +58,14 @@ void rampTagPower(uint8_t* pin, bool up) {
|
||||
digitalWrite(FLASHER_EXT_RESET, INPUT_PULLUP);
|
||||
} else {
|
||||
ledcSetup(0, 50000, 8);
|
||||
ledcWrite(0, 0);
|
||||
ledcSet(0, 0);
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
pinMode(pin[0], OUTPUT);
|
||||
pinMode(FLASHER_EXT_RESET, INPUT_PULLDOWN);
|
||||
ledcAttachPin(pin[0], 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
for (uint8_t c = 0; c < 0xFF; c++) {
|
||||
ledcWrite(0, c);
|
||||
ledcSet(0, c);
|
||||
if (c > 250) {
|
||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||
} else {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <HardwareSerial.h>
|
||||
#include <system.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#include "commstructs.h"
|
||||
#include "contentmanager.h"
|
||||
@@ -13,6 +15,9 @@
|
||||
#include "storage.h"
|
||||
#include "web.h"
|
||||
#include "zbs_interface.h"
|
||||
#include "wifimanager.h"
|
||||
|
||||
#define LOG(format, ...) printf(format, ##__VA_ARGS__)
|
||||
|
||||
QueueHandle_t rxCmdQueue;
|
||||
SemaphoreHandle_t txActive;
|
||||
@@ -25,7 +30,9 @@ SemaphoreHandle_t txActive;
|
||||
volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT;
|
||||
|
||||
#define AP_SERIAL_PORT Serial1
|
||||
#ifndef FLASHER_DEBUG_SHARED
|
||||
volatile bool rxSerialStopTask2 = false;
|
||||
#endif
|
||||
|
||||
uint8_t channelList[6];
|
||||
struct espSetChannelPower curChannel = {0, 11, 10};
|
||||
@@ -42,6 +49,8 @@ struct espSetChannelPower curChannel = {0, 11, 10};
|
||||
volatile uint32_t lastAPActivity = 0;
|
||||
struct APInfoS apInfo;
|
||||
|
||||
volatile ApSerialState gSerialTaskState;
|
||||
|
||||
struct rxCmd {
|
||||
uint8_t* data;
|
||||
uint8_t len;
|
||||
@@ -150,12 +159,28 @@ void setAPstate(bool isOnline, uint8_t state) {
|
||||
CRGB::Red,
|
||||
CRGB::YellowGreen};
|
||||
rgbIdleColor = colorMap[state];
|
||||
#ifdef BLE_ONLY
|
||||
rgbIdleColor = CRGB::Green;
|
||||
#endif
|
||||
#ifdef BLE_ONLY
|
||||
rgbIdleColor = CRGB::Green;
|
||||
#endif
|
||||
rgbIdlePeriod = (isOnline ? 767 : 255);
|
||||
if (isOnline) rgbIdle();
|
||||
#endif
|
||||
#ifdef FLASHER_DEBUG_SHARED
|
||||
// Flasher shares port with AP comms
|
||||
if (state == AP_STATE_FLASHING) {
|
||||
LOG("Shared COM port, gSerialTaskState %d\n", gSerialTaskState);
|
||||
gSerialTaskState = SERIAL_STATE_STOP;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
vTaskDelay(1 / portTICK_RATE_MS);
|
||||
if (gSerialTaskState == SERIAL_STATE_STOPPED) {
|
||||
gSerialTaskState = SERIAL_STATE_NONE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG("gSerialTaskState %d\n", gSerialTaskState);
|
||||
}
|
||||
#endif
|
||||
wsSendSysteminfo();
|
||||
}
|
||||
|
||||
// Reset the tag
|
||||
@@ -384,46 +409,49 @@ void rxCmdProcessor(void* parameter) {
|
||||
txActive = xSemaphoreCreateBinary();
|
||||
xSemaphoreGive(txActive);
|
||||
while (1) {
|
||||
struct rxCmd* rxcmd = nullptr;
|
||||
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
|
||||
if (q == pdTRUE) {
|
||||
switch (rxcmd->type) {
|
||||
case RX_CMD_RQB:
|
||||
processBlockRequest((struct espBlockRequest*)rxcmd->data);
|
||||
if (apInfo.isOnline) {
|
||||
struct rxCmd* rxcmd = nullptr;
|
||||
BaseType_t q = xQueueReceive(rxCmdQueue, &rxcmd, 10);
|
||||
if (q == pdTRUE) {
|
||||
switch (rxcmd->type) {
|
||||
case RX_CMD_RQB:
|
||||
processBlockRequest((struct espBlockRequest*)rxcmd->data);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Blue);
|
||||
// shortBlink(CRGB::Blue);
|
||||
#endif
|
||||
quickBlink(3);
|
||||
break;
|
||||
case RX_CMD_ADR:
|
||||
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
|
||||
quickBlink(3);
|
||||
break;
|
||||
case RX_CMD_ADR:
|
||||
processDataReq((struct espAvailDataReq*)rxcmd->data, true);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Aqua);
|
||||
// shortBlink(CRGB::Aqua);
|
||||
#endif
|
||||
quickBlink(1);
|
||||
break;
|
||||
case RX_CMD_XFC:
|
||||
processXferComplete((struct espXferComplete*)rxcmd->data, true);
|
||||
quickBlink(1);
|
||||
break;
|
||||
case RX_CMD_XFC:
|
||||
processXferComplete((struct espXferComplete*)rxcmd->data, true);
|
||||
#ifdef HAS_RGB_LED
|
||||
// shortBlink(CRGB::Purple);
|
||||
// shortBlink(CRGB::Purple);
|
||||
#endif
|
||||
break;
|
||||
case RX_CMD_XTO:
|
||||
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
|
||||
break;
|
||||
case RX_CMD_RSET:
|
||||
Serial.println("AP did reset, resending pending\r\n");
|
||||
refreshAllPending();
|
||||
sendChannelPower(&curChannel);
|
||||
break;
|
||||
case RX_CMD_TRD:
|
||||
// received tag return data
|
||||
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
|
||||
break;
|
||||
break;
|
||||
case RX_CMD_XTO:
|
||||
processXferTimeout((struct espXferComplete*)rxcmd->data, true);
|
||||
break;
|
||||
case RX_CMD_RSET:
|
||||
Serial.println("AP did reset, resending pending\r\n");
|
||||
refreshAllPending();
|
||||
sendChannelPower(&curChannel);
|
||||
break;
|
||||
case RX_CMD_TRD:
|
||||
// received tag return data
|
||||
processTagReturnData((struct espTagReturnData*)rxcmd->data, rxcmd->len, true);
|
||||
break;
|
||||
}
|
||||
if (rxcmd->data) free(rxcmd->data);
|
||||
if (rxcmd) free(rxcmd);
|
||||
}
|
||||
if (rxcmd->data) free(rxcmd->data);
|
||||
if (rxcmd) free(rxcmd);
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
void rxSerialTask(void* parameter) {
|
||||
@@ -435,7 +463,9 @@ void rxSerialTask(void* parameter) {
|
||||
static char lastchar = 0;
|
||||
static uint8_t charindex = 0;
|
||||
|
||||
while (1) {
|
||||
gSerialTaskState = SERIAL_STATE_RUNNING;
|
||||
LOG("rxSerialTask starting\n");
|
||||
while (gSerialTaskState == SERIAL_STATE_RUNNING) {
|
||||
while (AP_SERIAL_PORT.available()) {
|
||||
lastchar = AP_SERIAL_PORT.read();
|
||||
switch (RXState) {
|
||||
@@ -506,8 +536,8 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espBlockRequest) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
// don't set APstate heree, as it interferes with the flashing process
|
||||
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
if (strncmp(cmdbuffer, "ADR>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_DATA_REQ;
|
||||
@@ -516,8 +546,8 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espAvailDataReq) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
// don't set APstate heree, as it interferes with the flashing process
|
||||
// if (apInfo.isOnline == false && config.runStatus == RUNSTATUS_RUN) setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
if (strncmp(cmdbuffer, "XFC>", 4) == 0) {
|
||||
RXState = ZBS_RX_WAIT_XFERCOMPLETE;
|
||||
@@ -540,8 +570,6 @@ void rxSerialTask(void* parameter) {
|
||||
packetp = (uint8_t*)calloc(sizeof(struct espTagReturnData) + 8, 1);
|
||||
memset(cmdbuffer, 0x00, 4);
|
||||
lastAPActivity = millis();
|
||||
if (apInfo.isOnline == false)
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
}
|
||||
break;
|
||||
case ZBS_RX_BLOCK_REQUEST:
|
||||
@@ -666,10 +694,26 @@ void rxSerialTask(void* parameter) {
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
} // end of while(1)
|
||||
|
||||
AP_SERIAL_PORT.end();
|
||||
gSerialTaskState = SERIAL_STATE_STOPPED;
|
||||
LOG("rxSerialTask stopped\n");
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED)
|
||||
uint32_t millisDiff(uint32_t m) {
|
||||
uint32_t ms = millis();
|
||||
if (ms >= m)
|
||||
return ms - m;
|
||||
else
|
||||
return UINT32_MAX - m + ms + 1;
|
||||
}
|
||||
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
void rxSerialTask2(void* parameter) {
|
||||
char rxStr[100] = {0};
|
||||
int rxStrCount = 0;
|
||||
uint32_t modemResetHoldoff = millis();
|
||||
char lastchar = 0;
|
||||
time_t startTime = millis();
|
||||
int charCount = 0;
|
||||
@@ -681,6 +725,33 @@ void rxSerialTask2(void* parameter) {
|
||||
|
||||
// debug info
|
||||
Serial.write(lastchar);
|
||||
|
||||
rxStr[rxStrCount] = lastchar;
|
||||
if (lastchar == '\n' || lastchar == '\r') {
|
||||
if (strncmp(rxStr, "receive buffer full, drop the current frame", 43) == 0 && millisDiff(modemResetHoldoff) > 20000) {
|
||||
modemResetHoldoff = millis();
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
config.runStatus = RUNSTATUS_STOP;
|
||||
Serial.println("IEEE802.15.4 modem stuck case detected, resetting...");
|
||||
APTagReset();
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
Serial.println("bringing AP online again");
|
||||
if (bringAPOnline()) {
|
||||
config.runStatus = RUNSTATUS_RUN;
|
||||
Serial.println("Finished!");
|
||||
} else {
|
||||
Serial.println("Failed!");
|
||||
}
|
||||
logLine("IEEE802.15.4 modem reset " + (config.runStatus == RUNSTATUS_RUN) ? ("ok") : ("failed"));
|
||||
}
|
||||
rxStrCount = 0;
|
||||
memset(rxStr, 0, sizeof(rxStr));
|
||||
} else if (rxStrCount < sizeof(rxStr) - 2) {
|
||||
rxStrCount++;
|
||||
} else {
|
||||
rxStrCount = 0;
|
||||
memset(rxStr, 0, sizeof(rxStr));
|
||||
}
|
||||
}
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
|
||||
@@ -688,7 +759,7 @@ void rxSerialTask2(void* parameter) {
|
||||
if (currentTime - startTime >= 1000) {
|
||||
if (charCount > 6000) {
|
||||
rxSerialStopTask2 = true;
|
||||
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second");
|
||||
Serial.println("Serial monitor stopped because of flooding (" + String(charCount) + " characters per second)");
|
||||
}
|
||||
startTime = currentTime;
|
||||
charCount = 0;
|
||||
@@ -733,7 +804,7 @@ void checkWaitPowerCycle() {
|
||||
#endif
|
||||
}
|
||||
void segmentedShowIp() {
|
||||
IPAddress IP = WiFi.localIP();
|
||||
IPAddress IP = wm.localIP();
|
||||
char temp[12];
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
sendAPSegmentedData(apInfo.mac, (String) "IP Addr", 0x0200, true, true);
|
||||
@@ -746,12 +817,36 @@ void segmentedShowIp() {
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
bool bringAPOnline() {
|
||||
#ifdef BLE_ONLY
|
||||
bool bringAPOnline(uint8_t newState) {
|
||||
#ifdef BLE_ONLY
|
||||
apInfo.state = AP_STATE_NORADIO;
|
||||
#endif
|
||||
#endif
|
||||
if (apInfo.state == AP_STATE_NORADIO) return true;
|
||||
if (apInfo.state == AP_STATE_FLASHING) return false;
|
||||
|
||||
if (gSerialTaskState != SERIAL_STATE_INITIALIZED) {
|
||||
#ifdef HAS_ELECROW_ADV_2_8
|
||||
// Set GPIO45 low to connect the wireless interface to the multiplexed pins
|
||||
pinMode(45, OUTPUT);
|
||||
digitalWrite(45, LOW);
|
||||
#endif
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#elif defined(HAS_EXT_FLASHER)
|
||||
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
|
||||
#elif (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#endif
|
||||
gSerialTaskState = SERIAL_STATE_INITIALIZED;
|
||||
}
|
||||
if (gSerialTaskState != SERIAL_STATE_RUNNING) {
|
||||
gSerialTaskState = SERIAL_STATE_STARTING;
|
||||
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
setAPstate(false, AP_STATE_OFFLINE);
|
||||
// try without rebooting
|
||||
AP_SERIAL_PORT.updateBaudRate(115200);
|
||||
@@ -788,18 +883,18 @@ bool bringAPOnline() {
|
||||
}
|
||||
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
setAPstate(true, AP_STATE_ONLINE);
|
||||
setAPstate(newState == AP_STATE_ONLINE ? true : false, newState);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool checkRadio() {
|
||||
#ifdef BLE_ONLY
|
||||
#ifdef BLE_ONLY
|
||||
return false;
|
||||
#endif
|
||||
#ifndef C6_OTA_FLASHING
|
||||
#endif
|
||||
#ifndef C6_OTA_FLASHING
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
// make a short between FLASHER_AP_TXD and FLASHER_AP_RXD to indicate that no radio is present
|
||||
// e.g. for flasher only, or just to use the S3 to generate images for smaller AP's
|
||||
pinMode(FLASHER_AP_TXD, OUTPUT);
|
||||
@@ -823,25 +918,11 @@ void APTask(void* parameter) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if (AP_PROCESS_PORT == FLASHER_AP_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#ifdef HAS_EXT_FLASHER
|
||||
#if (AP_PROCESS_PORT == FLASHER_EXT_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_EXT_RXD, FLASHER_EXT_TXD);
|
||||
#endif
|
||||
#if (AP_PROCESS_PORT == FLASHER_ALTRADIO_PORT)
|
||||
AP_SERIAL_PORT.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
xTaskCreate(rxCmdProcessor, "rxCmdProcessor", 6000, NULL, 15, NULL);
|
||||
xTaskCreate(rxSerialTask, "rxSerialTask", 1750, NULL, 11, NULL);
|
||||
#ifdef FLASHER_DEBUG_RXD
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, 2, NULL);
|
||||
#endif
|
||||
|
||||
#if defined(FLASHER_DEBUG_RXD) && !defined(FLASHER_DEBUG_SHARED)
|
||||
xTaskCreate(rxSerialTask2, "rxSerialTask2", 1850, NULL, 2, NULL);
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
#endif
|
||||
bringAPOnline();
|
||||
|
||||
#ifndef C6_OTA_FLASHING
|
||||
@@ -876,7 +957,7 @@ void APTask(void* parameter) {
|
||||
if (FLASHER_AP_MOSI != -1) {
|
||||
fsversion = getAPUpdateVersion(apInfo.type);
|
||||
if ((fsversion) && (apInfo.version != fsversion)) {
|
||||
Serial.printf("Firmware version on LittleFS: %04X\r\n", fsversion);
|
||||
Serial.printf("Firmware version on FS: %04X\r\n", fsversion);
|
||||
|
||||
Serial.printf("We're going to try to update the AP's FW in\r\n");
|
||||
flashCountDown(30);
|
||||
|
||||
@@ -2,22 +2,63 @@
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
#include "FS.h"
|
||||
#ifdef SD_CARD_SDMMC
|
||||
#include "SD_MMC.h"
|
||||
#define SDCARD SD_MMC
|
||||
#else
|
||||
#include "SD.h"
|
||||
#include "SPI.h"
|
||||
#define SDCARD SD
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
#include "LittleFS.h"
|
||||
#endif
|
||||
|
||||
DynStorage::DynStorage() : isInited(0) {}
|
||||
|
||||
SemaphoreHandle_t fsMutex;
|
||||
SemaphoreHandle_t fsMutex = NULL;
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
static void initLittleFS() {
|
||||
LittleFS.begin();
|
||||
contentFS = &LittleFS;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
static bool sd_init_done = false;
|
||||
#ifdef SD_CARD_SDMMC
|
||||
static void initSDCard() {
|
||||
if(!SD_MMC.begin("/sdcard", true, true, BOARD_MAX_SDMMC_FREQ, 5)){
|
||||
Serial.println("Card Mount Failed");
|
||||
return;
|
||||
}
|
||||
uint8_t cardType = SD_MMC.cardType();
|
||||
|
||||
if(cardType == CARD_NONE){
|
||||
Serial.println("No SD_MMC card attached");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.print("SD_MMC Card Type: ");
|
||||
if(cardType == CARD_MMC){
|
||||
Serial.println("MMC");
|
||||
} else if(cardType == CARD_SD){
|
||||
Serial.println("SDSC");
|
||||
} else if(cardType == CARD_SDHC){
|
||||
Serial.println("SDHC");
|
||||
} else {
|
||||
Serial.println("UNKNOWN");
|
||||
}
|
||||
|
||||
uint64_t cardSize = SD_MMC.cardSize() / (1024 * 1024);
|
||||
Serial.printf("SD_MMC Card Size: %lluMB\n", cardSize);
|
||||
|
||||
contentFS = &SD_MMC;
|
||||
}
|
||||
#else
|
||||
static SPIClass* spi;
|
||||
|
||||
static void initSDCard() {
|
||||
@@ -45,15 +86,19 @@ static void initSDCard() {
|
||||
contentFS = &SD;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint64_t DynStorage::freeSpace(){
|
||||
this->begin();
|
||||
#ifdef HAS_SDCARD
|
||||
return SD.totalBytes() - SD.usedBytes();
|
||||
return SDCARD.totalBytes() - SDCARD.usedBytes();
|
||||
#endif
|
||||
#ifndef SD_CARD_ONLY
|
||||
return LittleFS.totalBytes() - LittleFS.usedBytes();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
void copyFile(File in, File out) {
|
||||
Serial.print("Copying ");
|
||||
Serial.print(in.path());
|
||||
@@ -127,14 +172,25 @@ void copyIfNeeded(const char* path) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void DynStorage::begin() {
|
||||
fsMutex = xSemaphoreCreateMutex();
|
||||
if(fsMutex == NULL) {
|
||||
fsMutex = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
#ifndef SD_CARD_ONLY
|
||||
initLittleFS();
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
initSDCard();
|
||||
|
||||
if(!sd_init_done) {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
initSDCard();
|
||||
xSemaphoreGive(fsMutex);
|
||||
sd_init_done = true;
|
||||
}
|
||||
#ifndef SD_CARD_ONLY
|
||||
copyIfNeeded("/index.html");
|
||||
copyIfNeeded("/fonts");
|
||||
copyIfNeeded("/www");
|
||||
@@ -143,6 +199,7 @@ void DynStorage::begin() {
|
||||
copyIfNeeded("/tag_md5_db.json");
|
||||
copyIfNeeded("/update_actions.json");
|
||||
copyIfNeeded("/content_template.json");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (!contentFS->exists("/current")) {
|
||||
@@ -155,7 +212,17 @@ void DynStorage::begin() {
|
||||
|
||||
void DynStorage::end() {
|
||||
#ifdef HAS_SDCARD
|
||||
#ifndef SD_CARD_ONLY
|
||||
initLittleFS();
|
||||
#endif
|
||||
#ifdef SD_CARD_SDMMC
|
||||
#ifndef SD_CARD_ONLY
|
||||
contentFS = &LittleFS;
|
||||
#endif
|
||||
SD_MMC.end();
|
||||
sd_init_done = false;
|
||||
#else
|
||||
#ifndef SD_CARD_ONLY
|
||||
if (SD_CARD_CLK == FLASHER_AP_CLK ||
|
||||
SD_CARD_MISO == FLASHER_AP_MISO ||
|
||||
SD_CARD_MOSI == FLASHER_AP_MOSI) {
|
||||
@@ -171,7 +238,8 @@ void DynStorage::end() {
|
||||
|
||||
contentFS = &LittleFS;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ void timeSyncCallback(struct timeval* tv) {
|
||||
}
|
||||
|
||||
void initTime(void* parameter) {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
if (!(WiFi.status() == WL_CONNECTED || wm.wifiStatus == ETHERNET)) {
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
sntp_set_time_sync_notification_cb(timeSyncCallback);
|
||||
|
||||
@@ -67,25 +67,24 @@ bool hex2mac(const String& hexString, uint8_t* mac) {
|
||||
}
|
||||
|
||||
String tagDBtoJson(const uint8_t mac[8], uint8_t startPos) {
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonArray tags = doc.createNestedArray("tags");
|
||||
JsonDocument doc;
|
||||
JsonArray tags = doc["tags"].to<JsonArray>();
|
||||
|
||||
for (uint32_t c = startPos; c < tagDB.size(); ++c) {
|
||||
const tagRecord* taginfo = tagDB.at(c);
|
||||
|
||||
const bool select = !mac || memcmp(taginfo->mac, mac, 8) == 0;
|
||||
if (select && taginfo->version == 0) {
|
||||
JsonObject tag = tags.createNestedObject();
|
||||
JsonObject tag = tags.add<JsonObject>();
|
||||
fillNode(tag, taginfo);
|
||||
if (measureJson(doc) > 5000) {
|
||||
doc["continu"] = c + 1;
|
||||
break;
|
||||
}
|
||||
if (mac) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.capacity() - doc.memoryUsage() < doc.memoryUsage() / (c + 1) + 500) {
|
||||
doc["continu"] = c + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doc.as<String>();
|
||||
@@ -126,7 +125,7 @@ void fillNode(JsonObject& tag, const tagRecord* taginfo) {
|
||||
}
|
||||
|
||||
void saveDB(const String& filename) {
|
||||
DynamicJsonDocument doc(2500);
|
||||
JsonDocument doc;
|
||||
|
||||
const long t = millis();
|
||||
|
||||
@@ -138,8 +137,10 @@ void saveDB(const String& filename) {
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
String backupFilename = filename + ".bak";
|
||||
if (!contentFS->rename(filename.c_str(), backupFilename.c_str())) {
|
||||
xSemaphoreGive(fsMutex);
|
||||
logLine("error renaming tagDB to .bak");
|
||||
wsErr("error renaming tagDB to .bak");
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ void saveDB(const String& filename) {
|
||||
doc.clear();
|
||||
|
||||
if (taginfo->version == 0) {
|
||||
JsonObject tag = doc.createNestedObject();
|
||||
JsonObject tag = doc.add<JsonObject>();
|
||||
fillNode(tag, taginfo);
|
||||
if (c > 0) {
|
||||
file.write(',');
|
||||
@@ -186,7 +187,7 @@ bool loadDB(const String& filename) {
|
||||
bool parsing = true;
|
||||
|
||||
if (readfile.find("[")) {
|
||||
DynamicJsonDocument doc(1000);
|
||||
JsonDocument doc;
|
||||
while (parsing) {
|
||||
DeserializationError err = deserializeJson(doc, readfile);
|
||||
if (!err) {
|
||||
@@ -210,7 +211,7 @@ bool loadDB(const String& filename) {
|
||||
taginfo->nextupdate = (uint32_t)tag["nextupdate"];
|
||||
taginfo->expectedNextCheckin = (uint32_t)tag["nextcheckin"];
|
||||
if (taginfo->expectedNextCheckin < now) {
|
||||
taginfo->expectedNextCheckin = now + 1800;
|
||||
taginfo->expectedNextCheckin = now + 60;
|
||||
}
|
||||
taginfo->pendingCount = 0;
|
||||
taginfo->alias = tag["alias"].as<String>();
|
||||
@@ -268,10 +269,10 @@ void destroyDB() {
|
||||
|
||||
uint32_t getTagCount() {
|
||||
uint32_t temp = 0;
|
||||
return getTagCount(temp);
|
||||
return getTagCount(temp, temp);
|
||||
}
|
||||
|
||||
uint32_t getTagCount(uint32_t& timeoutcount) {
|
||||
uint32_t getTagCount(uint32_t& timeoutcount, uint32_t& lowbattcount) {
|
||||
uint32_t tagcount = 0;
|
||||
time_t now;
|
||||
time(&now);
|
||||
@@ -279,12 +280,13 @@ uint32_t getTagCount(uint32_t& timeoutcount) {
|
||||
if (!taginfo->isExternal) tagcount++;
|
||||
const int32_t timeout = now - taginfo->lastseen;
|
||||
if (taginfo->expectedNextCheckin < 3600) {
|
||||
// not initialised, timeout if not seen last 10 minutes
|
||||
if (timeout > 600) timeoutcount++;
|
||||
} else if (now - taginfo->expectedNextCheckin > 600) {
|
||||
// expected checkin is behind, timeout if not seen last 10 minutes
|
||||
if (timeout > 600) timeoutcount++;
|
||||
// not initialised, timeout if not seen last 5 minutes
|
||||
if (timeout > config.maxsleep * 60 + 300) timeoutcount++;
|
||||
} else if (now - static_cast<time_t>(taginfo->expectedNextCheckin) > 600) {
|
||||
// expected checkin is behind, timeout if not seen last 5 minutes
|
||||
if (timeout > config.maxsleep * 60 + 300) timeoutcount++;
|
||||
}
|
||||
if (taginfo->batteryMv < 2400 && taginfo->batteryMv != 0 && taginfo->batteryMv != 1337) lowbattcount++;
|
||||
}
|
||||
return tagcount;
|
||||
}
|
||||
@@ -307,7 +309,7 @@ void clearPending(tagRecord* taginfo) {
|
||||
}
|
||||
|
||||
void initAPconfig() {
|
||||
DynamicJsonDocument APconfig(500);
|
||||
JsonDocument APconfig;
|
||||
File configFile = contentFS->open("/current/apconfig.json", "r");
|
||||
if (configFile) {
|
||||
DeserializationError error = deserializeJson(APconfig, configFile);
|
||||
@@ -318,27 +320,30 @@ void initAPconfig() {
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
config.channel = APconfig.containsKey("channel") ? APconfig["channel"] : 0;
|
||||
config.subghzchannel = APconfig.containsKey("subghzchannel") ? APconfig["subghzchannel"] : 0;
|
||||
config.channel = APconfig["channel"].is<uint8_t>() ? APconfig["channel"] : 0;
|
||||
config.subghzchannel = APconfig["subghzchannel"].is<uint8_t>() ? APconfig["subghzchannel"] : 0;
|
||||
if (APconfig["alias"]) strlcpy(config.alias, APconfig["alias"], sizeof(config.alias));
|
||||
config.led = APconfig.containsKey("led") ? APconfig["led"] : 255;
|
||||
config.tft = APconfig.containsKey("tft") ? APconfig["tft"] : 255;
|
||||
config.language = APconfig.containsKey("language") ? APconfig["language"] : 0;
|
||||
config.maxsleep = APconfig.containsKey("maxsleep") ? APconfig["maxsleep"] : 10;
|
||||
config.stopsleep = APconfig.containsKey("stopsleep") ? APconfig["stopsleep"] : 1;
|
||||
config.preview = APconfig.containsKey("preview") ? APconfig["preview"] : 1;
|
||||
config.lock = APconfig.containsKey("lock") ? APconfig["lock"] : 0;
|
||||
config.sleepTime1 = APconfig.containsKey("sleeptime1") ? APconfig["sleeptime1"] : 0;
|
||||
config.sleepTime2 = APconfig.containsKey("sleeptime2") ? APconfig["sleeptime2"] : 0;
|
||||
config.ble = APconfig.containsKey("ble") ? APconfig["ble"] : 0;
|
||||
#ifdef BLE_ONLY
|
||||
config.ble = true;
|
||||
#endif
|
||||
config.led = APconfig["led"].is<uint8_t>() ? APconfig["led"] : 255;
|
||||
config.tft = APconfig["tft"].is<uint8_t>() ? APconfig["tft"] : 255;
|
||||
config.language = APconfig["language"].is<uint8_t>() ? APconfig["language"] : 0;
|
||||
config.maxsleep = APconfig["maxsleep"].is<uint8_t>() ? APconfig["maxsleep"] : 10;
|
||||
config.stopsleep = APconfig["stopsleep"].is<uint8_t>() ? APconfig["stopsleep"] : 1;
|
||||
config.preview = APconfig["preview"].is<uint8_t>() ? APconfig["preview"] : 1;
|
||||
config.nightlyreboot = APconfig["nightlyreboot"].is<uint8_t>() ? APconfig["nightlyreboot"] : 1;
|
||||
config.lock = APconfig["lock"].is<uint8_t>() ? APconfig["lock"] : 0;
|
||||
config.sleepTime1 = APconfig["sleeptime1"].is<uint8_t>() ? APconfig["sleeptime1"] : 0;
|
||||
config.sleepTime2 = APconfig["sleeptime2"].is<uint8_t>() ? APconfig["sleeptime2"] : 0;
|
||||
config.ble = APconfig["ble"].is<uint8_t>() ? APconfig["ble"] : 0;
|
||||
config.discovery = APconfig["discovery"].is<uint8_t>() ? APconfig["discovery"] : 0;
|
||||
config.showtimestamp = APconfig["showtimestamp"].is<uint8_t>() ? APconfig["showtimestamp"] : 0;
|
||||
#ifdef BLE_ONLY
|
||||
config.ble = true;
|
||||
#endif
|
||||
// default wifi power 8.5 dbM
|
||||
// see https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiGeneric.h#L111
|
||||
config.wifiPower = APconfig.containsKey("wifipower") ? APconfig["wifipower"] : 34;
|
||||
config.repo = APconfig.containsKey("repo") ? APconfig["repo"].as<String>() : String("jjwbruijn/OpenEPaperLink");
|
||||
config.env = APconfig.containsKey("env") ? APconfig["env"].as<String>() : String(STR(BUILD_ENV_NAME));
|
||||
config.wifiPower = APconfig["wifipower"].is<uint8_t>() ? APconfig["wifipower"] : 34;
|
||||
config.repo = APconfig["repo"].is<String>() ? APconfig["repo"].as<String>() : String("OpenEPaperLink/OpenEPaperLink");
|
||||
config.env = APconfig["env"].is<String>() ? APconfig["env"].as<String>() : String(STR(BUILD_ENV_NAME));
|
||||
if (APconfig["timezone"]) {
|
||||
strlcpy(config.timeZone, APconfig["timezone"], sizeof(config.timeZone));
|
||||
} else {
|
||||
@@ -349,7 +354,7 @@ void initAPconfig() {
|
||||
void saveAPconfig() {
|
||||
xSemaphoreTake(fsMutex, portMAX_DELAY);
|
||||
fs::File configFile = contentFS->open("/current/apconfig.json", "w");
|
||||
DynamicJsonDocument APconfig(500);
|
||||
JsonDocument APconfig;
|
||||
APconfig["channel"] = config.channel;
|
||||
APconfig["subghzchannel"] = config.subghzchannel;
|
||||
APconfig["alias"] = config.alias;
|
||||
@@ -359,6 +364,7 @@ void saveAPconfig() {
|
||||
APconfig["maxsleep"] = config.maxsleep;
|
||||
APconfig["stopsleep"] = config.stopsleep;
|
||||
APconfig["preview"] = config.preview;
|
||||
APconfig["nightlyreboot"] = config.nightlyreboot;
|
||||
APconfig["lock"] = config.lock;
|
||||
APconfig["wifipower"] = config.wifiPower;
|
||||
APconfig["timezone"] = config.timeZone;
|
||||
@@ -367,6 +373,8 @@ void saveAPconfig() {
|
||||
APconfig["ble"] = config.ble;
|
||||
APconfig["repo"] = config.repo;
|
||||
APconfig["env"] = config.env;
|
||||
APconfig["discovery"] = config.discovery;
|
||||
APconfig["showtimestamp"] = config.showtimestamp;
|
||||
serializeJsonPretty(APconfig, configFile);
|
||||
configFile.close();
|
||||
xSemaphoreGive(fsMutex);
|
||||
@@ -383,16 +391,17 @@ HwType getHwType(const uint8_t id) {
|
||||
File jsonFile = contentFS->open(filename, "r");
|
||||
|
||||
if (jsonFile) {
|
||||
StaticJsonDocument<150> filter;
|
||||
JsonDocument filter;
|
||||
filter["width"] = true;
|
||||
filter["height"] = true;
|
||||
filter["rotatebuffer"] = true;
|
||||
filter["bpp"] = true;
|
||||
filter["shortlut"] = true;
|
||||
filter["zlib_compression"] = true;
|
||||
filter["g5_compression"] = true;
|
||||
filter["highlight_color"] = true;
|
||||
filter["colortable"] = true;
|
||||
StaticJsonDocument<1000> doc;
|
||||
JsonDocument doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonFile, DeserializationOption::Filter(filter));
|
||||
jsonFile.close();
|
||||
if (error) {
|
||||
@@ -406,12 +415,17 @@ HwType getHwType(const uint8_t id) {
|
||||
hwType.rotatebuffer = doc["rotatebuffer"];
|
||||
hwType.bpp = doc["bpp"];
|
||||
hwType.shortlut = doc["shortlut"];
|
||||
if (doc.containsKey("zlib_compression")) {
|
||||
if (doc["zlib_compression"].is<const char*>()) {
|
||||
hwType.zlib = strtol(doc["zlib_compression"], nullptr, 16);
|
||||
} else {
|
||||
hwType.zlib = 0;
|
||||
}
|
||||
hwType.highlightColor = doc.containsKey("highlight_color") ? doc["highlight_color"].as<uint16_t>() : 2;
|
||||
if (doc["g5_compression"].is<const char*>()) {
|
||||
hwType.g5 = strtol(doc["g5_compression"], nullptr, 16);
|
||||
} else {
|
||||
hwType.g5 = 0;
|
||||
}
|
||||
hwType.highlightColor = doc["highlight_color"].is<uint16_t>() ? doc["highlight_color"].as<uint16_t>() : 2;
|
||||
JsonObject colorTable = doc["colortable"];
|
||||
for (auto kv : colorTable) {
|
||||
JsonArray color = kv.value();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user