mirror of
https://github.com/OpenEPaperLink/OpenEPaperLink.git
synced 2026-03-21 14:06:31 +01:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77cbf92281 | ||
|
|
c4022e45f9 | ||
|
|
a13c220565 | ||
|
|
3989ecc3a3 | ||
|
|
cb0f029900 | ||
|
|
443714e9dc | ||
|
|
f3f163fa00 | ||
|
|
8848cfc0f8 | ||
|
|
6c91c78aa1 | ||
|
|
98baa020ff | ||
|
|
56e1e9e6b6 | ||
|
|
2817aa7e38 | ||
|
|
2292aeaf7e | ||
|
|
3472b5d4b6 | ||
|
|
19f6a093d3 | ||
|
|
d6734a7f79 | ||
|
|
da487fbc5f | ||
|
|
3b7fd7d1f6 | ||
|
|
f4273630ee | ||
|
|
0cbb9e770e | ||
|
|
9dfb37b376 | ||
|
|
e457475ea7 | ||
|
|
806b2dc9e0 | ||
|
|
2b7fc93043 | ||
|
|
6a711c99eb | ||
|
|
ffd0acff72 | ||
|
|
a9c9812525 | ||
|
|
03ce036083 | ||
|
|
a98ad537ea | ||
|
|
2726b4d2fe | ||
|
|
fd5adb40f8 | ||
|
|
89346b5d77 | ||
|
|
7ac57577df | ||
|
|
09f7466f6f | ||
|
|
55e50b1920 | ||
|
|
7cb5e13a7f | ||
|
|
6f08af2c67 | ||
|
|
e185ddd99b | ||
|
|
3079101c48 | ||
|
|
0b66a23ce4 | ||
|
|
41c7cb843f |
81
.github/workflows/build-test.yml
vendored
Normal file
81
.github/workflows/build-test.yml
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
name: Firmware build test
|
||||
|
||||
on: [push,pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pip
|
||||
~/.platformio/.cache
|
||||
key: ${{ runner.os }}-pio
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
- name: Install PlatformIO Core
|
||||
run: pip install --upgrade platformio
|
||||
|
||||
- name: Build Simple_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment Simple_AP
|
||||
pio run --target buildfs --environment Simple_AP
|
||||
|
||||
- name: Build OpenEPaperLink_Mini_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment OpenEPaperLink_Mini_AP
|
||||
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
|
||||
|
||||
# - name: Build OpenEPaperLink_Nano_AP
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment OpenEPaperLink_Nano_AP
|
||||
# pio run --target buildfs --environment OpenEPaperLink_Nano_AP
|
||||
|
||||
- name: Build OpenEPaperLink_AP_and_Flasher
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment OpenEPaperLink_AP_and_Flasher
|
||||
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
|
||||
|
||||
# - name: Build Wemos_d1_mini32_AP
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment Wemos_d1_mini32_AP
|
||||
# pio run --target buildfs --environment Wemos_d1_mini32_AP
|
||||
|
||||
# - name: Build M5Stack_Core_ONE_AP
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment M5Stack_Core_ONE_AP
|
||||
# pio run --target buildfs --environment M5Stack_Core_ONE_AP
|
||||
|
||||
- name: Build ESP32_S3_16_8_YELLOW_AP]
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment ESP32_S3_16_8_YELLOW_AP
|
||||
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
|
||||
|
||||
# - name: Build Sonoff_zb_bridge_P_AP
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment Sonoff_zb_bridge_P_AP
|
||||
# pio run --target buildfs --environment Sonoff_zb_bridge_P_AP
|
||||
|
||||
# - name: Build OpenEPaperLink_CC1352P
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment OpenEPaperLink_CC1352P
|
||||
# pio run --target buildfs --environment OpenEPaperLink_CC1352P
|
||||
|
||||
# - name: OutdoorAP
|
||||
# run: |
|
||||
# cd ESP32_AP-Flasher
|
||||
# pio run --environment OutdoorAP
|
||||
# pio run --target buildfs --environment OutdoorAP
|
||||
57
.github/workflows/esp32-build-test.yml
vendored
57
.github/workflows/esp32-build-test.yml
vendored
@@ -1,57 +0,0 @@
|
||||
name: ESP32 firmware builf test
|
||||
|
||||
on: [push,pull_request]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
~/.cache/pip
|
||||
~/.platformio/.cache
|
||||
key: ${{ runner.os }}-pio
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
- name: Install PlatformIO Core
|
||||
run: pip install --upgrade platformio
|
||||
|
||||
- name: Build Simple_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment Simple_AP
|
||||
pio run --target buildfs --environment Simple_AP
|
||||
|
||||
- name: Build OpenEPaperLink_Mini_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment OpenEPaperLink_Mini_AP
|
||||
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
|
||||
|
||||
- name: Build OpenEPaperLink_Nano_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment OpenEPaperLink_Nano_AP
|
||||
pio run --target buildfs --environment OpenEPaperLink_Nano_AP
|
||||
|
||||
- name: Build OpenEPaperLink_AP_and_Flasher
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment OpenEPaperLink_AP_and_Flasher
|
||||
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
|
||||
|
||||
- name: Build Wemos_d1_mini32_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment Wemos_d1_mini32_AP
|
||||
pio run --target buildfs --environment Wemos_d1_mini32_AP
|
||||
|
||||
- name: Build M5Stack_Core_ONE_AP
|
||||
run: |
|
||||
cd ESP32_AP-Flasher
|
||||
pio run --environment M5Stack_Core_ONE_AP
|
||||
pio run --target buildfs --environment M5Stack_Core_ONE_AP
|
||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -21,6 +21,18 @@ jobs:
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
# - name: Zip web files
|
||||
# run: |
|
||||
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
|
||||
# python gzip_wwwfiles.py
|
||||
|
||||
# - 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
|
||||
|
||||
@@ -138,6 +150,24 @@ 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
|
||||
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
|
||||
pio run --environment ESP32_S3_16_8_YELLOW_AP
|
||||
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
|
||||
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP
|
||||
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/boot_app0.bin
|
||||
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/firmware.bin
|
||||
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/bootloader.bin
|
||||
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/partitions.bin
|
||||
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/littlefs.bin
|
||||
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_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_YELLOW_AP/firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP.bin
|
||||
cp ESP32_S3_16_8_YELLOW_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP_full.bin
|
||||
|
||||
- name: generate release json file
|
||||
run: |
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
build
|
||||
*.axf
|
||||
# Allow
|
||||
!*.bin
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
const char font[256][40]={
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
|
||||
{0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21
|
||||
{0x00,0x00,0xC0,0x18,0xC0,0x18,0xC0,0x18,0xC0,0x18,0xC0,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
|
||||
{0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x22,0x00,0x11,0x00,0x11,0x00,0x11,0xE0,0xFF,0x80,0x08,0x80,0x08,0x80,0x08,0xE0,0x7F,0x40,0x04,0x40,0x04,0x20,0x02,0x20,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x23
|
||||
{0x00,0x00,0x00,0x04,0x00,0x1F,0x80,0x3F,0xC0,0x24,0xC0,0x04,0xC0,0x04,0x80,0x07,0x00,0x07,0x00,0x1C,0x00,0x1C,0x00,0x34,0x00,0x34,0x40,0x34,0xC0,0x1F,0x80,0x0F,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x24
|
||||
{0x00,0x00,0x00,0x00,0xE0,0x81,0x30,0x43,0x30,0x23,0x30,0x13,0x30,0x0B,0x30,0x0B,0xE0,0x05,0x00,0x7A,0x00,0xCD,0x00,0xCD,0x80,0xCC,0x40,0xCC,0x20,0xCC,0x10,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x25
|
||||
{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0x80,0x19,0x80,0x19,0x80,0x0D,0x00,0x07,0xC0,0x03,0x60,0xC6,0x30,0xCE,0x30,0xCC,0x30,0x78,0x70,0x78,0xE0,0x7F,0xC0,0xEF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x26
|
||||
{0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27
|
||||
{0x00,0x00,0x00,0x30,0x00,0x3C,0x00,0x0E,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x0E,0x00,0x3C,0x00,0x30,0x00,0x00}, // 0x28
|
||||
{0x00,0x00,0xC0,0x00,0xC0,0x03,0x00,0x07,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x07,0xC0,0x03,0xC0,0x00,0x00,0x00}, // 0x29
|
||||
{0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x60,0x33,0xE0,0x3C,0x00,0x00,0x80,0x0D,0xC0,0x19,0x80,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2A
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xE0,0x7F,0xE0,0x7F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2B
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x00}, // 0x2C
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E
|
||||
{0x00,0x00,0x00,0x60,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x0C,0x00,0x0C,0x00,0x06,0x00,0x06,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x80,0x01,0xC0,0x00,0xC0,0x00,0x60,0x00,0x00,0x00}, // 0x2F
|
||||
{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0xC0,0x30,0xC0,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x30,0xC0,0x30,0x80,0x1F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x30
|
||||
{0x00,0x00,0x00,0x00,0x00,0x06,0xC0,0x07,0x60,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x31
|
||||
{0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0x40,0x38,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32
|
||||
{0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x3F,0x40,0x30,0x00,0x30,0x00,0x18,0x80,0x0F,0x80,0x0F,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x30,0x40,0x38,0xC0,0x1F,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33
|
||||
{0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x1C,0x00,0x1E,0x00,0x1A,0x00,0x19,0x80,0x19,0xC0,0x18,0x40,0x18,0xE0,0x7F,0xE0,0x7F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x34
|
||||
{0x00,0x00,0x00,0x00,0x80,0x3F,0x80,0x3F,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x0F,0x80,0x1F,0x00,0x38,0x00,0x30,0x00,0x30,0x00,0x38,0x80,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35
|
||||
{0x00,0x00,0x00,0x00,0x00,0x0F,0x80,0x1F,0xC0,0x11,0xC0,0x00,0x60,0x00,0x60,0x0E,0x60,0x1F,0xE0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0xC0,0x38,0xC0,0x1F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x36
|
||||
{0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x60,0x00,0x30,0x00,0x10,0x00,0x18,0x00,0x0C,0x00,0x04,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x03,0x80,0x01,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x37
|
||||
{0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x1F,0xC0,0x18,0xC0,0x18,0xC0,0x19,0x80,0x0F,0x00,0x07,0xC0,0x1E,0x60,0x38,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x38
|
||||
{0x00,0x00,0x00,0x00,0x80,0x07,0xC0,0x1F,0xE0,0x18,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x37,0x80,0x33,0x00,0x30,0x00,0x18,0x40,0x1C,0xC0,0x0F,0x80,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x39
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x06,0x00,0x02,0x00,0x03,0x00,0x00}, // 0x3B
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x70,0x00,0x3C,0x00,0x0E,0x80,0x03,0xE0,0x00,0x80,0x03,0x00,0x0E,0x00,0x3C,0x00,0x70,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3C
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0xE0,0x00,0xC0,0x03,0x00,0x07,0x00,0x1C,0x00,0x70,0x00,0x1C,0x00,0x07,0xC0,0x03,0xE0,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3E
|
||||
{0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x3F,0x20,0x38,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3F
|
||||
{0x00,0x00,0x00,0x00,0x00,0x1F,0x80,0x31,0xC0,0x60,0x60,0x7C,0x30,0x66,0x30,0x63,0x30,0x63,0x30,0x73,0x30,0x73,0x30,0x6F,0x60,0xE6,0x60,0x00,0xC0,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x40
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x0F,0x00,0x0F,0x00,0x0D,0x80,0x19,0x80,0x19,0xC0,0x38,0xC0,0x30,0xC0,0x3F,0xE0,0x7F,0x60,0x60,0x60,0x60,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x41
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x1F,0x60,0x18,0x60,0x18,0x60,0x0C,0xE0,0x07,0xE0,0x0F,0x60,0x18,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x1F,0xE0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x42
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x7F,0xC0,0x41,0xC0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xC0,0x00,0xC0,0x43,0x80,0x7F,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x43
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0xE0,0x1F,0x60,0x38,0x60,0x70,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x30,0x60,0x38,0xE0,0x1F,0xE0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x44
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x45
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x7F,0xC0,0x7F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x3F,0xC0,0x3F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x46
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x80,0x7F,0xC0,0x41,0xC0,0x00,0x60,0x00,0x60,0x00,0x60,0x78,0x60,0x78,0x60,0x60,0xC0,0x60,0xC0,0x61,0x80,0x7F,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x47
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x3F,0xE0,0x3F,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x48
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x1F,0xE0,0x1F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0xE0,0x1F,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x49
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0x80,0x1F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0xC0,0x0F,0xC0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x70,0x60,0x38,0x60,0x1C,0x60,0x0E,0x60,0x06,0x60,0x03,0xE0,0x03,0x60,0x07,0x60,0x0E,0x60,0x1C,0x60,0x38,0x60,0x70,0x60,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4B
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x7F,0xC0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4C
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x70,0x70,0xF0,0x78,0xB0,0x68,0xB0,0x68,0xB0,0x6D,0x30,0x65,0x30,0x65,0x30,0x67,0x30,0x62,0x30,0x60,0x30,0x60,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x60,0xE0,0x60,0xE0,0x61,0xE0,0x61,0x60,0x63,0x60,0x67,0x60,0x66,0x60,0x6E,0x60,0x6C,0x60,0x78,0x60,0x78,0x60,0x70,0x60,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4E
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0xE0,0x38,0x70,0x70,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x70,0x70,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4F
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x1F,0xC0,0x3F,0xC0,0x70,0xC0,0x60,0xC0,0x60,0xC0,0x70,0xC0,0x3F,0xC0,0x0F,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x50
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0xE0,0x38,0x70,0x70,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x38,0x00,0xF0,0x00,0x40,0x00,0x00}, // 0x51
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0xE0,0x1F,0x60,0x18,0x60,0x18,0x60,0x18,0x60,0x1C,0xE0,0x0F,0xE0,0x07,0x60,0x0E,0x60,0x1C,0x60,0x38,0x60,0x70,0x60,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x52
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x0F,0xC0,0x1F,0x60,0x10,0x60,0x00,0xE0,0x00,0xC0,0x03,0x80,0x0F,0x00,0x3C,0x00,0x30,0x00,0x30,0x60,0x38,0xE0,0x1F,0xC0,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x53
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0xFF,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x54
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x55
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0x60,0x60,0x60,0x60,0xE0,0x60,0xC0,0x30,0xC0,0x30,0xC0,0x31,0x80,0x19,0x80,0x1B,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x56
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xC0,0x30,0xC0,0x30,0xC0,0x20,0x46,0x20,0x46,0x20,0x6E,0x60,0x6F,0x60,0x69,0x60,0x69,0x60,0x39,0xC0,0x39,0xC0,0x39,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x57
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xE0,0xE0,0x60,0xC0,0x30,0x80,0x19,0x80,0x0F,0x00,0x0F,0x00,0x06,0x00,0x0F,0x80,0x1D,0x80,0x19,0xC0,0x30,0x60,0x70,0x30,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x58
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xC0,0x60,0x60,0xC0,0x30,0xC0,0x31,0x80,0x19,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x59
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0x60,0x00,0xE0,0x7F,0xE0,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5A
|
||||
{0x00,0x00,0x00,0x3F,0x00,0x3F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x3F,0x00,0x3F,0x00,0x00}, // 0x5B
|
||||
{0x00,0x00,0x60,0x00,0xC0,0x00,0xC0,0x00,0x80,0x01,0x80,0x01,0x80,0x01,0x00,0x03,0x00,0x03,0x00,0x06,0x00,0x06,0x00,0x0C,0x00,0x0C,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x30,0x00,0x30,0x00,0x60,0x00,0x00}, // 0x5C
|
||||
{0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0xC0,0x0F,0xC0,0x0F,0x00,0x00}, // 0x5D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x0E,0x00,0x0A,0x00,0x0B,0x00,0x1B,0x80,0x11,0x80,0x31,0xC0,0x30,0xC0,0x20,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5E
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0xFF,0xF0,0xFF,0x00,0x00,0x00,0x00}, // 0x5F
|
||||
{0x00,0x06,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0xC0,0x3F,0x40,0x30,0x00,0x30,0x00,0x30,0x80,0x3F,0xC0,0x30,0x60,0x30,0x60,0x38,0xE0,0xFF,0xC0,0xE7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x61
|
||||
{0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x0E,0x60,0x1F,0xE0,0x39,0xE0,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x18,0xE0,0x1F,0x60,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x62
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xC0,0x3F,0xC0,0x21,0xE0,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x3F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x63
|
||||
{0x00,0x00,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x3F,0x80,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x64
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x1F,0xC0,0x38,0x60,0x30,0xE0,0x3F,0xE0,0x3F,0x60,0x00,0x60,0x00,0xC0,0x20,0xC0,0x3F,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x65
|
||||
{0x00,0x00,0x00,0x7E,0x00,0x7F,0x00,0x03,0x00,0x03,0xE0,0x7F,0xE0,0x7F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x66
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x3F,0x80,0x37,0x00,0x30,0x40,0x38,0xC0,0x1F,0x80,0x0F}, // 0x67
|
||||
{0x00,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x1E,0x60,0x3F,0xE0,0x31,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x68
|
||||
{0x00,0x00,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69
|
||||
{0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x80,0x1F,0x80,0x1F,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0xC0,0x0F,0xC0,0x07}, // 0x6A
|
||||
{0x00,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x70,0xC0,0x38,0xC0,0x1C,0xC0,0x0E,0xC0,0x06,0xC0,0x07,0xC0,0x0E,0xC0,0x1C,0xC0,0x38,0xC0,0x70,0xC0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6B
|
||||
{0x00,0x00,0xC0,0x0F,0xC0,0x0F,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x39,0xF0,0x7F,0x70,0x67,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x30,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x1E,0x60,0x3F,0xE0,0x31,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6E
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x3F,0xC0,0x30,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xC0,0x30,0xC0,0x3F,0x00,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6F
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x0F,0xE0,0x1F,0xE0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x18,0xE0,0x1F,0x60,0x0F,0x60,0x00,0x60,0x00,0x60,0x00,0x60,0x00}, // 0x70
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x37,0xC0,0x3F,0xC0,0x38,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0xE0,0x38,0xC0,0x37,0x80,0x33,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x30}, // 0x71
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3C,0xC0,0x3E,0xC0,0x23,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x72
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x1F,0xC0,0x1F,0xC0,0x00,0xC0,0x00,0xC0,0x03,0x00,0x1F,0x00,0x38,0x00,0x30,0x40,0x30,0xC0,0x1F,0x80,0x0F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x03,0xE0,0x7F,0xE0,0x7F,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x7F,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x74
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x30,0x60,0x3C,0xE0,0x37,0xC0,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0,0x20,0xC0,0x30,0xC0,0x30,0x80,0x11,0x80,0x19,0x80,0x19,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x76
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0xC0,0x30,0xC6,0x30,0xC6,0x20,0x4E,0x60,0x4F,0x60,0x49,0x60,0x69,0x60,0x79,0xC0,0x39,0xC0,0x30,0xC0,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x77
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x70,0xC0,0x30,0x80,0x19,0x80,0x0B,0x00,0x0F,0x00,0x06,0x00,0x0F,0x80,0x1D,0x80,0x19,0xC0,0x30,0x60,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x78
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0xC0,0x20,0xC0,0x30,0xC0,0x31,0x80,0x19,0x80,0x19,0x00,0x0B,0x00,0x0F,0x00,0x0F,0x00,0x06,0x00,0x06,0x00,0x02,0x00,0x03,0xC0,0x03,0xC0,0x01}, // 0x79
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x3F,0xE0,0x3F,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x3F,0xE0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7A
|
||||
{0x00,0x00,0x00,0x3C,0x00,0x3E,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xC0,0x03,0xC0,0x03,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3E,0x00,0x3C,0x00,0x00}, // 0x7B
|
||||
{0x00,0x00,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x00}, // 0x7C
|
||||
{0x00,0x00,0xC0,0x03,0xC0,0x07,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x3C,0x00,0x3C,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0xC0,0x07,0xC0,0x03,0x00,0x00}, // 0x7D
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x43,0xE0,0x7F,0x20,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7E
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x3F,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x20,0xC0,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0x7F
|
||||
};
|
||||
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2.bin
Executable file
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2.bin
Executable file
Binary file not shown.
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2_ota.bin
Executable file
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA-0.2_ota.bin
Executable file
Binary file not shown.
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA.bin
Normal file
BIN
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/88MZ100_7.4_BETA.bin
Normal file
Binary file not shown.
@@ -1,10 +1,11 @@
|
||||
|
||||
MZ_FLASHER=python ../88MZ100_Flasher/88MZ100_Uart_flasher.py
|
||||
|
||||
ARMGCC=armgcc/bin/
|
||||
ARMGCC=/usr/bin/
|
||||
CC=$(ARMGCC)arm-none-eabi-gcc
|
||||
AS=$(ARMGCC)arm-none-eabi-as
|
||||
OBJCOPY=$(ARMGCC)arm-none-eabi-objcopy
|
||||
|
||||
#-Wall
|
||||
CC_WARNING_FLAGS=-Wall -Wformat=0 -Wattributes -Wstrict-aliasing=0
|
||||
CC_FlAGS=-mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c99
|
||||
@@ -16,10 +17,15 @@ C_EXECUTABLE :=$(C_SOURCES:.c=)
|
||||
COMPORT = COM12
|
||||
|
||||
|
||||
build: clean compile create_ota_img flash_uart_flash
|
||||
build: compile
|
||||
only: clean compile create_ota_img
|
||||
uart: clean compile flash_uart
|
||||
|
||||
#build: clean compile create_ota_img flash_uart_flash
|
||||
#only: clean compile create_ota_img
|
||||
#uart: clean compile flash_uart
|
||||
|
||||
|
||||
compile:
|
||||
@mkdir -p build
|
||||
@$(AS) -mcpu=cortex-m3 --gdwarf-2 -mthumb-interwork -o build/startup.o startup.S
|
||||
@@ -40,16 +46,8 @@ compile:
|
||||
@$(CC) $(CC_FlAGS) -c mz100_gpt.c -o build/mz100_gpt.o
|
||||
@$(CC) $(CC_FlAGS) -c mz100_sleep.c -o build/mz100_sleep.o
|
||||
@$(CC) $(CC_FlAGS) -c mz100_uart.c -o build/mz100_uart.o
|
||||
# UZLIB
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/adler32.c -o build/adler32.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/crc32.c -o build/crc32.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/defl_static.c -o build/defl_static.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/genlz77.c -o build/genlz77.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfgzip.c -o build/tinfgzip.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinflate.c -o build/tinflate.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfzlib.c -o build/tinfzlib.o
|
||||
# UZLIB END
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c compression.c -o build/compression.o
|
||||
@$(CC) $(CC_FlAGS) -c mz100_aon_ram.c -o build/mz100_aon_ram.o
|
||||
@$(CC) $(CC_FlAGS) -c printf.c -o build/printf.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c zigbee.c -o build/zigbee.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c ccm.c -o build/ccm.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c chars.c -o build/chars.o
|
||||
@@ -61,10 +59,10 @@ compile:
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c timer.c -o build/timer.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c util.c -o build/util.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c gpio.c -o build/gpio.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c nfc.c -o build/nfc.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c epd.c -o build/epd.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c userinterface.c -o build/userinterface.o
|
||||
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c main.c -o build/main.o
|
||||
@$(CC) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) build/main.o build/adler32.o build/crc32.o build/defl_static.o build/genlz77.o build/tinfgzip.o build/tinflate.o build/tinfzlib.o build/compression.o build/zigbee.o build/ccm.o build/chars.o build/drawing.o build/powermgt.o build/syncedproto.o build/comms.o build/settings.o build/timer.o build/util.o build/gpio.o build/nfc.o build/epd.o build/mz100_sleep.o build/core_cm3.o build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o build/startup.o -o main.axf
|
||||
@$(CC) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) build/main.o build/userinterface.o build/printf.o build/mz100_aon_ram.o build/zigbee.o build/chars.o build/drawing.o build/powermgt.o build/syncedproto.o build/comms.o build/settings.o build/timer.o build/util.o build/gpio.o build/epd.o build/mz100_sleep.o build/core_cm3.o build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o build/startup.o -o main.axf
|
||||
@$(OBJCOPY) -v -O binary main.axf main.bin
|
||||
|
||||
clean:
|
||||
@@ -83,4 +81,4 @@ flash_dump:
|
||||
@$(MZ_FLASHER) $(COMPORT) read dump.bin
|
||||
|
||||
create_ota_img:
|
||||
@$(MZ_FLASHER) img main.bin UPDT0028.BIN
|
||||
@$(MZ_FLASHER) img main.bin UPDT0028.BIN
|
||||
|
||||
@@ -1,96 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "comms.h"
|
||||
#include "proto.h"
|
||||
|
||||
#include <stdint.h>
|
||||
//#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ccm.h"
|
||||
#include "proto.h"
|
||||
|
||||
extern uint8_t Zigbee_tx_buffer(uint8_t tx_buffer[], int len);
|
||||
|
||||
static uint8_t packet[128];
|
||||
static uint8_t mSeq = 0;
|
||||
uint8_t mLastLqi = 0;
|
||||
int8_t mLastRSSI = 0;
|
||||
|
||||
uint8_t commsGetLastPacketLQI(void)
|
||||
{
|
||||
return mLastLqi;
|
||||
uint8_t commsGetLastPacketLQI(void) {
|
||||
return mLastLqi;
|
||||
}
|
||||
|
||||
int8_t commsGetLastPacketRSSI(void)
|
||||
{
|
||||
return mLastRSSI;
|
||||
int8_t commsGetLastPacketRSSI(void) {
|
||||
return mLastRSSI;
|
||||
}
|
||||
|
||||
static inline void __attribute__((always_inline)) macCopy(uint8_t *restrict dst, const uint8_t *restrict src)
|
||||
{
|
||||
((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
|
||||
((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
|
||||
static inline void __attribute__((always_inline)) macCopy(uint8_t *restrict dst, const uint8_t *restrict src) {
|
||||
((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
|
||||
((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
|
||||
}
|
||||
|
||||
static inline bool __attribute__((always_inline)) macIsEq(const uint8_t *restrict dst, const uint8_t *restrict src)
|
||||
{
|
||||
return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1];
|
||||
}
|
||||
|
||||
bool commsTx(struct CommsInfo *info, bool bcast, const void *packet_in, uint32_t len)
|
||||
{
|
||||
uint8_t nonce[AES_CCM_NONCE_SIZE] = {};
|
||||
struct MacFrameNormal *mfn;
|
||||
struct MacFrameBcast *mfb;
|
||||
uint32_t hdrSz;
|
||||
char *payload;
|
||||
static const struct MacFcs normalFcs = {
|
||||
.frameType = FRAME_TYPE_DATA,
|
||||
.panIdCompressed = 1,
|
||||
.destAddrType = ADDR_MODE_LONG,
|
||||
.srcAddrType = ADDR_MODE_LONG,
|
||||
};
|
||||
static const struct MacFcs broadcastFcs = {
|
||||
.frameType = FRAME_TYPE_DATA,
|
||||
.destAddrType = ADDR_MODE_SHORT,
|
||||
.srcAddrType = ADDR_MODE_LONG,
|
||||
};
|
||||
|
||||
if (len > COMMS_MAX_PACKET_SZ)
|
||||
return false;
|
||||
|
||||
if (bcast)
|
||||
{
|
||||
mfb = (struct MacFrameBcast *)packet;
|
||||
hdrSz = sizeof(struct MacFrameBcast);
|
||||
payload = (char *)(mfb + 1);
|
||||
mfb->fcs = broadcastFcs;
|
||||
mfb->seq = mSeq++;
|
||||
mfb->dstPan = 0xffff;
|
||||
mfb->dstAddr = 0xffff;
|
||||
mfb->srcPan = PROTO_PAN_ID;
|
||||
macCopy(mfb->src, info->myMac);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfn = (struct MacFrameNormal *)packet;
|
||||
hdrSz = sizeof(struct MacFrameNormal);
|
||||
payload = (char *)(mfn + 1);
|
||||
mfn->fcs = normalFcs;
|
||||
mfn->seq = mSeq++;
|
||||
mfn->pan = PROTO_PAN_ID;
|
||||
macCopy(mfn->dst, info->masterMac);
|
||||
macCopy(mfn->src, info->myMac);
|
||||
}
|
||||
|
||||
*(uint32_t *)nonce = (*info->nextIV)++;
|
||||
macCopy(nonce + sizeof(uint32_t), info->myMac);
|
||||
memcpy(payload, packet_in, len);
|
||||
|
||||
aesCcmEnc((void *)packet, (void *)packet, hdrSz, len, info->encrKey, nonce);
|
||||
*(uint32_t *)(payload + len + AES_CCM_MIC_SIZE) = *(uint32_t *)nonce; // send nonce
|
||||
|
||||
len += hdrSz;
|
||||
len += AES_CCM_MIC_SIZE;
|
||||
len += sizeof(uint32_t);
|
||||
|
||||
return !Zigbee_tx_buffer((uint8_t *)&packet, len);
|
||||
static inline bool __attribute__((always_inline)) macIsEq(const uint8_t *restrict dst, const uint8_t *restrict src) {
|
||||
return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1];
|
||||
}
|
||||
|
||||
extern volatile uint8_t rx_buffer[0x400];
|
||||
@@ -98,94 +34,16 @@ extern volatile uint8_t new_rx;
|
||||
extern volatile uint8_t new_rssi;
|
||||
extern volatile int rx_len;
|
||||
|
||||
int32_t __attribute__((noinline)) commsRx(struct CommsInfo *info, void *data, uint8_t *fromMacP)
|
||||
{
|
||||
uint8_t *buf = packet, nonce[13] = {}, fromMac[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint32_t len, minNeedLen, hdrLen = 0;
|
||||
struct MacFrameFromMaster *mfm;
|
||||
struct MacFrameNormal *mfn;
|
||||
|
||||
// sort out how many bytes minimum are a valid packet
|
||||
minNeedLen = sizeof(struct MacFrameFromMaster); // mac header
|
||||
minNeedLen += sizeof(uint8_t); // packet type
|
||||
minNeedLen += AES_CCM_MIC_SIZE; // MIC
|
||||
minNeedLen += sizeof(uint32_t); // nonce counter
|
||||
minNeedLen += 2 * sizeof(uint8_t); // RSSI/LQI
|
||||
|
||||
if (!new_rx)
|
||||
return COMMS_RX_ERR_NO_PACKETS;
|
||||
|
||||
// some basic checks
|
||||
mfm = (struct MacFrameFromMaster *)rx_buffer;
|
||||
if (rx_len >= sizeof(packet) || rx_len < minNeedLen || mfm->fcs.frameType != FRAME_TYPE_DATA ||
|
||||
mfm->fcs.secure || mfm->fcs.frameVer || mfm->fcs.destAddrType != ADDR_MODE_LONG || !mfm->fcs.panIdCompressed ||
|
||||
(mfm->fcs.srcAddrType != ADDR_MODE_LONG && mfm->fcs.srcAddrType != ADDR_MODE_SHORT) ||
|
||||
mfm->pan != PROTO_PAN_ID || !macIsEq(mfm->dst, info->myMac))
|
||||
{
|
||||
new_rx = 0;
|
||||
return COMMS_RX_ERR_INVALID_PACKET;
|
||||
}
|
||||
|
||||
// copy out and release buffer
|
||||
memcpy(buf, &rx_buffer, len = rx_len - 2 * sizeof(uint8_t));
|
||||
mLastLqi = rx_buffer[len + 0];
|
||||
mLastRSSI = rx_buffer[len + 1];
|
||||
|
||||
mfm = (struct MacFrameFromMaster *)buf;
|
||||
mfn = (struct MacFrameNormal *)buf;
|
||||
new_rx = 0;
|
||||
|
||||
// sort out header len, copy mac into nonce
|
||||
if (mfm->fcs.srcAddrType == ADDR_MODE_LONG)
|
||||
{
|
||||
|
||||
macCopy(fromMac, mfn->src);
|
||||
hdrLen = sizeof(struct MacFrameNormal);
|
||||
|
||||
// re-verify needed length
|
||||
minNeedLen -= sizeof(struct MacFrameFromMaster);
|
||||
minNeedLen += sizeof(struct MacFrameNormal);
|
||||
|
||||
if (rx_len < minNeedLen)
|
||||
return COMMS_RX_ERR_INVALID_PACKET;
|
||||
}
|
||||
else if (mfm->fcs.srcAddrType == ADDR_MODE_SHORT)
|
||||
{
|
||||
|
||||
macCopy(fromMac, info->masterMac);
|
||||
hdrLen = sizeof(struct MacFrameFromMaster);
|
||||
}
|
||||
|
||||
// sort out the nonce
|
||||
macCopy(nonce + sizeof(uint32_t), fromMac);
|
||||
*(uint32_t *)nonce = *(uint32_t *)(buf + len - sizeof(uint32_t));
|
||||
|
||||
// decrypt and auth
|
||||
len -= hdrLen + AES_CCM_MIC_SIZE + sizeof(uint32_t);
|
||||
|
||||
if (!aesCcmDec(buf, buf, hdrLen, len, info->encrKey, nonce))
|
||||
return COMMS_RX_ERR_MIC_FAIL;
|
||||
|
||||
if (fromMacP)
|
||||
macCopy(fromMacP, fromMac);
|
||||
|
||||
memcpy(data, buf + hdrLen, len);
|
||||
|
||||
return len;
|
||||
int32_t __attribute__((noinline)) commsRxUnenc(void *data) {
|
||||
if (!new_rx)
|
||||
return COMMS_RX_ERR_NO_PACKETS;
|
||||
memcpy(data, (uint8_t*)&rx_buffer, rx_len);
|
||||
mLastLqi = 255 - new_rssi;
|
||||
mLastRSSI = new_rssi;
|
||||
new_rx = 0;
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
int32_t __attribute__((noinline)) commsRxUnenc(void *data)
|
||||
{
|
||||
if (!new_rx)
|
||||
return COMMS_RX_ERR_NO_PACKETS;
|
||||
memcpy(data, &rx_buffer, rx_len);
|
||||
mLastLqi = 255 - new_rssi;
|
||||
mLastRSSI = new_rssi;
|
||||
new_rx = 0;
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
void commsTxNoCpy(uint8_t *packetp)
|
||||
{
|
||||
Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2));
|
||||
void commsTxNoCpy(uint8_t *packetp) {
|
||||
Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2));
|
||||
}
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
#include <stdint.h>
|
||||
#include "ccm.h"
|
||||
|
||||
struct CommsInfo {
|
||||
const uint8_t *myMac;
|
||||
const uint8_t *masterMac;
|
||||
const void *encrKey;
|
||||
uint32_t *nextIV;
|
||||
};
|
||||
extern uint8_t mLastLqi;
|
||||
extern int8_t mLastRSSI;
|
||||
|
||||
@@ -23,8 +17,6 @@ extern int8_t mLastRSSI;
|
||||
|
||||
#define COMMS_MAX_PACKET_SZ (127 /* max phy len */ - 21 /* max mac frame with panID compression */ - 2 /* FCS len */ - AES_CCM_MIC_SIZE - COMMS_IV_SIZE)
|
||||
|
||||
bool commsTx(struct CommsInfo *info, bool bcast, const void *packet, uint32_t len);
|
||||
int32_t commsRx(struct CommsInfo *info, void *data, uint8_t *fromMac); //returns length or COMMS_RX_ERR_*
|
||||
|
||||
uint8_t commsGetLastPacketLQI(void);
|
||||
int8_t commsGetLastPacketRSSI(void);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#include "compression.h"
|
||||
#include "uzlib/src/uzlib.h"
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "uzlib/src/uzlib.h"
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdbool.h>
|
||||
#include "printf.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "eeprom.h"
|
||||
@@ -11,366 +12,22 @@
|
||||
#include "util.h"
|
||||
#include "epd.h"
|
||||
|
||||
#define COMPRESSION_BITPACKED_3x5_to_7 0x62700357 // 3 pixels of 5 possible colors in 7 bits
|
||||
#define COMPRESSION_BITPACKED_5x3_to_8 0x62700538 // 5 pixels of 3 possible colors in 8 bits
|
||||
#define COMPRESSION_BITPACKED_3x6_to_8 0x62700368 // 3 pixels of 6 possible colors in 8 bits
|
||||
|
||||
struct BitmapFileHeader
|
||||
{
|
||||
uint8_t sig[2];
|
||||
uint32_t fileSz;
|
||||
uint8_t rfu[4];
|
||||
uint32_t dataOfst;
|
||||
uint32_t headerSz; // 40
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
uint16_t colorplanes; // must be one
|
||||
uint16_t bpp;
|
||||
uint32_t compression;
|
||||
uint32_t dataLen; // may be 0
|
||||
uint32_t pixelsPerMeterX;
|
||||
uint32_t pixelsPerMeterY;
|
||||
uint32_t numColors; // if zero, assume 2^bpp
|
||||
uint32_t numImportantColors;
|
||||
};
|
||||
|
||||
struct BitmapClutEntry
|
||||
{
|
||||
uint8_t b, g, r, x;
|
||||
};
|
||||
|
||||
struct BitmapDrawInfo
|
||||
{
|
||||
// dimensions
|
||||
uint16_t w, h, effectiveW, effectiveH, stride /* 0 -> 1, 5 - >7, 255 -> 256 */;
|
||||
uint8_t numColorsM1;
|
||||
|
||||
// data start
|
||||
uint32_t dataAddr;
|
||||
|
||||
// compression state
|
||||
uint8_t packetPixelDivVal;
|
||||
uint8_t packetNumPixels;
|
||||
uint8_t packetBitSz;
|
||||
uint8_t packetBitMask; // derived from the above
|
||||
|
||||
// flags
|
||||
uint8_t bpp : 4;
|
||||
uint8_t bottomUp : 1;
|
||||
};
|
||||
|
||||
uint8_t mPassNo = 0;
|
||||
|
||||
static const uint8_t mColorMap[][6] = {
|
||||
// colors are: B, DG, G, LG, W, R
|
||||
// phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
|
||||
{1, 1, 1, 1, 0, 0}, // lo plane (B)
|
||||
|
||||
{0, 0, 0, 0, 0, 1} // hi plane (R)
|
||||
};
|
||||
|
||||
static uint8_t mClutMap[256];
|
||||
static uint8_t mClutMapRed[256];
|
||||
static struct BitmapDrawInfo mDrawInfo;
|
||||
|
||||
static uint32_t drawPrvParseHeader(uint32_t addr) // return clut addr or zero on error
|
||||
{
|
||||
/*struct BitmapFileHeader bmph;
|
||||
uint16_t packetsPerRow;
|
||||
|
||||
addr += sizeof(struct EepromImageHeader);
|
||||
eepromRead(addr, &bmph, sizeof(bmph));
|
||||
|
||||
if (bmph.sig[0] != 'B' || bmph.sig[1] != 'M')
|
||||
goto fail;
|
||||
|
||||
if (bmph.colorplanes != 1)
|
||||
goto fail;
|
||||
|
||||
if ((&bmph.headerSz - 40)) // < 40
|
||||
goto fail;
|
||||
|
||||
if (bmph.bpp > 8)
|
||||
goto fail;
|
||||
|
||||
mDrawInfo.bpp = bmph.bpp;
|
||||
|
||||
if (!(&bmph.headerSz - 257)) // >= 257
|
||||
goto fail;
|
||||
|
||||
if ((&bmph.numColors))
|
||||
mDrawInfo.numColorsM1 = (uint8_t)bmph.numColors - (uint8_t)1;
|
||||
else
|
||||
mDrawInfo.numColorsM1 = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp) - (uint8_t)1;
|
||||
|
||||
if (!(&bmph.height))
|
||||
goto fail;
|
||||
|
||||
if ((&bmph.width - 1) || !(&bmph.width - 0xffff))
|
||||
goto fail;
|
||||
mDrawInfo.w = bmph.width;
|
||||
|
||||
if ((&bmph.height) < 0)
|
||||
{
|
||||
if ((&bmph.height + 0xffff)) // carries if val too negative
|
||||
goto fail;
|
||||
mDrawInfo.h = -bmph.height;
|
||||
mDrawInfo.bottomUp = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(&bmph.headerSz - 0xffff)) // no carry if val too big
|
||||
goto fail;
|
||||
mDrawInfo.h = bmph.height;
|
||||
mDrawInfo.bottomUp = true;
|
||||
}
|
||||
|
||||
if (bmph.compression)
|
||||
{
|
||||
printf("compression is not supported ;(");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
mDrawInfo.packetPixelDivVal = 0;
|
||||
mDrawInfo.packetNumPixels = 1;
|
||||
if (mDrawInfo.bpp > 1)
|
||||
{
|
||||
mDrawInfo.packetBitSz = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mDrawInfo.packetBitSz = 1; // mDrawInfo.bpp;
|
||||
}
|
||||
|
||||
// mDrawInfo.stride = mathPrvDiv32x8(mathPrvMul16x8((mDrawInfo.w + mDrawInfo.packetNumPixels - 1), mDrawInfo.packetBitSz) + 31, 32) * 4UL;
|
||||
// mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1;
|
||||
|
||||
packetsPerRow = (mDrawInfo.w + mDrawInfo.packetNumPixels - 1) / (mDrawInfo.packetNumPixels);
|
||||
mDrawInfo.stride = (((packetsPerRow * mDrawInfo.packetBitSz) + 31) / 32) * 4UL;
|
||||
mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1;
|
||||
|
||||
// calc effective size
|
||||
mDrawInfo.effectiveH = (mDrawInfo.h > SCREEN_HEIGHT) ? SCREEN_HEIGHT : mDrawInfo.h;
|
||||
mDrawInfo.effectiveW = (mDrawInfo.w > SCREEN_WIDTH) ? SCREEN_WIDTH : mDrawInfo.w;
|
||||
|
||||
// calc addrs
|
||||
mDrawInfo.dataAddr = addr + bmph.dataOfst;
|
||||
return addr + bmph.dataOfst - sizeof(struct BitmapClutEntry) * (1 + mDrawInfo.numColorsM1);
|
||||
|
||||
fail:
|
||||
printf("Tried to parse the bmp header, didn't work...");*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void drawPrvLoadAndMapClut(uint32_t clutAddr)
|
||||
{
|
||||
/*struct BitmapClutEntry clut;
|
||||
uint8_t i;
|
||||
|
||||
// convert clut to our understanding of color
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
uint8_t entry;
|
||||
|
||||
eepromRead(clutAddr, &clut, sizeof(clut));
|
||||
clutAddr += sizeof(struct BitmapClutEntry);
|
||||
|
||||
if (SCREEN_EXTRA_COLOR_INDEX >= 0 && clut.r == 0xff && (clut.g == 0xff || clut.g == 0) && clut.b == 0) // yellow/red
|
||||
entry = SCREEN_EXTRA_COLOR_INDEX;
|
||||
else
|
||||
{
|
||||
uint16_t intensity = 0;
|
||||
|
||||
intensity += (0x37 * clut.r);
|
||||
intensity += (0xB7 * clut.g);
|
||||
intensity += (0x12 * clut.b);
|
||||
// adds up to 0xff00 -> fix it
|
||||
intensity += (uint8_t)(intensity >> 8);
|
||||
|
||||
entry = (intensity * SCREEN_NUM_GREYS) >> 16;
|
||||
entry += SCREEN_FIRST_GREY_IDX;
|
||||
}
|
||||
// printf("mapped clut %u (%d %d %d) -> %d\n", i, clut.r, clut.g, clut.b, entry);
|
||||
mClutMap[i] = entry;
|
||||
} while (i++ != mDrawInfo.numColorsM1);
|
||||
|
||||
// replicate clut down if not a full 256-entry clut
|
||||
if (mDrawInfo.bpp != 8)
|
||||
{
|
||||
uint8_t num = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp);
|
||||
|
||||
// we can use the fact that our memcpy always copies forward
|
||||
memcpy(mClutMap + num, mClutMap, (uint8_t)256 - (uint8_t)num);
|
||||
}*/
|
||||
}
|
||||
|
||||
static void drawPrvDecodeImageOnce(void)
|
||||
{
|
||||
/*uint8_t rowBuf[SCREEN_WIDTH];
|
||||
uint16_t er, c;
|
||||
if (mDrawInfo.bottomUp)
|
||||
er = mDrawInfo.effectiveH - 1;
|
||||
else
|
||||
er = 0;
|
||||
while (1)
|
||||
{ // we account differently for loop gets compiled worse
|
||||
uint8_t inIdx = 0, bitpoolInUsed = 0, bitpoolIn = 0;
|
||||
uint16_t nBytesOut = 0;
|
||||
|
||||
#if SCREEN_TX_BPP == 4
|
||||
uint8_t txPrev = 0;
|
||||
bool emit = false;
|
||||
#else
|
||||
uint8_t bitpoolOutUsedUsed = 0;
|
||||
uint16_t bitpoolOut = 0;
|
||||
#endif
|
||||
// get a row
|
||||
epdDeselect();
|
||||
eepromRead((er * mDrawInfo.stride) + mDrawInfo.dataAddr, rowBuf, mDrawInfo.stride);
|
||||
epdSelect();
|
||||
// convert to our format
|
||||
c = mDrawInfo.effectiveW;
|
||||
do
|
||||
{
|
||||
// uartTx('.');
|
||||
uint8_t packet, packetIdx, packetMembers = mDrawInfo.packetNumPixels;
|
||||
|
||||
if (bitpoolInUsed >= mDrawInfo.packetBitSz)
|
||||
{
|
||||
bitpoolInUsed -= mDrawInfo.packetBitSz;
|
||||
packet = bitpoolIn >> bitpoolInUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t packetBitSz = mDrawInfo.packetBitSz;
|
||||
uint8_t t = rowBuf[inIdx++];
|
||||
|
||||
packet = (bitpoolIn << (packetBitSz - bitpoolInUsed)) | (t >> (8 - (packetBitSz - bitpoolInUsed)));
|
||||
bitpoolInUsed += 8 - packetBitSz;
|
||||
|
||||
bitpoolIn = t;
|
||||
}
|
||||
packet &= mDrawInfo.packetBitMask;
|
||||
|
||||
// val is now a packet - unpack it
|
||||
if (packetMembers > c)
|
||||
packetMembers = c;
|
||||
|
||||
for (packetIdx = 0; packetIdx < packetMembers; packetIdx++)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
// extract
|
||||
if (mDrawInfo.packetPixelDivVal)
|
||||
{
|
||||
val = packet % mDrawInfo.packetPixelDivVal;
|
||||
packet /= mDrawInfo.packetPixelDivVal;
|
||||
}
|
||||
else
|
||||
val = packet;
|
||||
|
||||
// map
|
||||
val = mClutMap[val];
|
||||
|
||||
// get bits out
|
||||
#if SCREEN_TX_BPP == 4
|
||||
|
||||
if (emit)
|
||||
{
|
||||
emit = false;
|
||||
ByteDecode(txPrev | val);
|
||||
nBytesOut++;
|
||||
txPrev = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
emit = true;
|
||||
txPrev = val << 4;
|
||||
}
|
||||
|
||||
#else
|
||||
bitpoolOut <<= SCREEN_TX_BPP;
|
||||
bitpoolOut |= val;
|
||||
bitpoolOutUsedUsed += SCREEN_TX_BPP;
|
||||
if (bitpoolOutUsedUsed >= 8)
|
||||
{
|
||||
ByteDecode(bitpoolOut >> (bitpoolOutUsedUsed -= 8));
|
||||
bitpoolOut &= (1 << bitpoolOutUsedUsed) - 1;
|
||||
nBytesOut++;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
c -= packetMembers;
|
||||
} while (c);
|
||||
|
||||
#if SCREEN_TX_BPP == 4
|
||||
|
||||
if (emit)
|
||||
{
|
||||
ByteDecode(txPrev);
|
||||
nBytesOut++;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if (bitpoolOutUsedUsed)
|
||||
{
|
||||
ByteDecode(bitpoolOut);
|
||||
nBytesOut++;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// if we did not produce enough bytes, do so
|
||||
nBytesOut = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8 - nBytesOut;
|
||||
while (nBytesOut--)
|
||||
ByteDecode(SCREEN_BYTE_FILL);
|
||||
|
||||
// update row
|
||||
if (mDrawInfo.bottomUp)
|
||||
{
|
||||
if (er)
|
||||
er--;
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
er++;
|
||||
if (er == mDrawInfo.effectiveH)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fill the rest of the screen
|
||||
for (er = mDrawInfo.effectiveH - SCREEN_HEIGHT; er; er--)
|
||||
{
|
||||
for (c = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8; c; c--)
|
||||
{
|
||||
ByteDecode(SCREEN_BYTE_FILL);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
static uint8_t prev, step = 0;
|
||||
|
||||
void ByteDecode(uint8_t byte)
|
||||
{
|
||||
/*prev <<= 2;
|
||||
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
|
||||
if (++step == 4)
|
||||
{
|
||||
step = 0;
|
||||
Display_Write_byte(prev);
|
||||
}*/
|
||||
}
|
||||
|
||||
void drawImageAtAddress(uint32_t addr, uint8_t lut)
|
||||
{
|
||||
struct EepromImageHeader *eih = (struct EepromImageHeader *)mClutMap;
|
||||
eepromRead(addr, mClutMap, sizeof(struct EepromImageHeader));
|
||||
uint8_t prevVal = 0;
|
||||
switch (eih->dataType)
|
||||
{
|
||||
case DATATYPE_IMG_RAW_1BPP:
|
||||
@@ -430,34 +87,6 @@ void drawImageAtAddress(uint32_t addr, uint8_t lut)
|
||||
display_send_stop();
|
||||
epd_refresh_and_sleep();
|
||||
break;
|
||||
case DATATYPE_IMG_BMP:;
|
||||
uint32_t clutAddr;
|
||||
printf("sending BMP to EPD - ");
|
||||
/*clutAddr = drawPrvParseHeader(addr);
|
||||
if (!clutAddr)
|
||||
return;
|
||||
drawPrvLoadAndMapClut(clutAddr);
|
||||
|
||||
epdSetup();
|
||||
if (lut)
|
||||
selectLUT(lut);
|
||||
mPassNo = 0;
|
||||
beginFullscreenImage();
|
||||
beginWriteFramebuffer(EPD_COLOR_BLACK);
|
||||
prev = 0;
|
||||
step = 0;
|
||||
drawPrvDecodeImageOnce();
|
||||
endWriteFramebuffer();
|
||||
mPassNo++;
|
||||
beginFullscreenImage();
|
||||
beginWriteFramebuffer(EPD_COLOR_RED);
|
||||
prev = 0;
|
||||
step = 0;
|
||||
drawPrvDecodeImageOnce();
|
||||
endWriteFramebuffer();*/
|
||||
|
||||
printf(" complete.\n");
|
||||
break;
|
||||
default: // prevent drawing from an unknown file image type
|
||||
printf("Image with type 0x%02X was requested, but we don't know what to do with that currently...\n", eih->dataType);
|
||||
return;
|
||||
|
||||
1110
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c
Normal file → Executable file
1110
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/epd.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define DISPLAY_WIDTH (640)
|
||||
#define DISPLAY_HEIGHT (384)
|
||||
@@ -16,6 +17,18 @@
|
||||
#define FORE_COLOR_2 4
|
||||
#define FORE_COLOR_3 0
|
||||
|
||||
#define EPD_LUT_DEFAULT 0
|
||||
#define EPD_LUT_NO_REPEATS 1
|
||||
#define EPD_LUT_FAST_NO_REDS 2
|
||||
#define EPD_LUT_FAST 3
|
||||
|
||||
#define EPD_DIRECTION_X false
|
||||
#define EPD_DIRECTION_Y true
|
||||
#define EPD_SIZE_SINGLE false
|
||||
#define EPD_SIZE_DOUBLE true
|
||||
#define EPD_COLOR_RED true
|
||||
#define EPD_COLOR_BLACK false
|
||||
|
||||
void init_GPIO_EPD();
|
||||
void display_send_buffer();
|
||||
|
||||
@@ -25,5 +38,16 @@ void display_tx_byte(uint8_t data);
|
||||
void display_send_start(uint8_t inverted);
|
||||
void display_send_stop();
|
||||
|
||||
void setDisplayWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye);
|
||||
|
||||
void init_epd();
|
||||
void refresh_epd();
|
||||
void refresh_epd();
|
||||
|
||||
void lutBeginTX(uint8_t reg);
|
||||
void lutEndTX();
|
||||
|
||||
void epd_pin_enable(int a1);
|
||||
|
||||
|
||||
void fillWindow(uint16_t x, uint16_t y, uint16_t xe, uint16_t ye, uint8_t color);
|
||||
void epdPrintf(uint16_t x, uint16_t y, bool color, const char* c, ...);
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
#include "nfc.h"
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "mz100_pinmux.h"
|
||||
#include "mz100_gpio.h"
|
||||
#include "util.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
void NVIC_some_IRQ1(unsigned int a1)
|
||||
{
|
||||
|
||||
898
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c
Normal file → Executable file
898
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.c
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -4,8 +4,9 @@ GROUP(-lgcc -lc -lnosys)
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x100000, LENGTH = 80k
|
||||
RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 16k
|
||||
RAM1 (rwx) : ORIGIN = 0x20124000 , LENGTH = 16k
|
||||
RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 2k
|
||||
AONSHADOW (rwx) : ORIGIN = 0x20128000 - 2k, LENGTH = 2k
|
||||
AON (rwx) : ORIGIN = 0x20130000 , LENGTH = 4k
|
||||
}
|
||||
|
||||
ENTRY(Reset_Handler)
|
||||
@@ -123,6 +124,27 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
|
||||
.aon (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_start_of_aon = .;
|
||||
*(.aon)
|
||||
*(.aon.*)
|
||||
. = ALIGN(4);
|
||||
_end_of_aon = .;
|
||||
|
||||
} > AON
|
||||
.aonshadow (NOLOAD):
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_start_of_aonshadow = .;
|
||||
*(.aonshadow)
|
||||
*(.aonshadow.*)
|
||||
. = ALIGN(4);
|
||||
_end_of_aonshadow = .;
|
||||
|
||||
} > AONSHADOW
|
||||
}
|
||||
|
||||
|
||||
|
||||
43
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.c
Normal file
43
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "mz100_aon_ram.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
__attribute__((section(".aon"))) volatile uint32_t aonChecksum;
|
||||
__attribute__((section(".aon"))) volatile uint8_t aonShadow[AONSHADOW_SIZE];
|
||||
|
||||
bool aonRamValid = false;
|
||||
|
||||
void clearAonRam() {
|
||||
memset((void *)0x130000, 0, 4096);
|
||||
}
|
||||
|
||||
bool loadValidateAonRam() {
|
||||
uint32_t testchecksum = aonChecksum;
|
||||
aonChecksum = 0x00000000;
|
||||
uint32_t checksum = 0xABBA5FF5;
|
||||
for (uint32_t c = 0x130000; c < 0x131000; c += 4) {
|
||||
checksum += *(uint32_t *)c;
|
||||
}
|
||||
if (checksum == testchecksum) {
|
||||
// immediately invalidate the checksum; if we reboot, we want a clean reboot
|
||||
aonChecksum = 0x5445A00A;
|
||||
memcpy((void *)(0x128000 - AONSHADOW_SIZE), (uint8_t*)aonShadow, AONSHADOW_SIZE);
|
||||
return true;
|
||||
} else {
|
||||
clearAonRam();
|
||||
memset((void *)(0x128000 - AONSHADOW_SIZE), 0, AONSHADOW_SIZE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void saveAonRam() {
|
||||
memcpy((uint8_t*)aonShadow, (void *)(0x128000 - AONSHADOW_SIZE), AONSHADOW_SIZE);
|
||||
aonChecksum = 0x00000000;
|
||||
uint32_t checksum = 0xABBA5FF5;
|
||||
for (uint32_t c = 0x130000; c < 0x131000; c += 4) {
|
||||
checksum += *(uint32_t *)c;
|
||||
}
|
||||
aonChecksum = checksum;
|
||||
}
|
||||
11
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.h
Normal file
11
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/mz100_aon_ram.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "stdint.h"
|
||||
#include "stdbool.h"
|
||||
|
||||
|
||||
#define AONSHADOW_SIZE 2048
|
||||
|
||||
extern bool aonRamValid;
|
||||
|
||||
bool loadValidateAonRam();
|
||||
void saveAonRam();
|
||||
void clearAonRam();
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "core_cm3.h"
|
||||
#include "mz100_gpio.h"
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "gpio.h"
|
||||
#include "main.h"
|
||||
#include "proto.h"
|
||||
#include "printf.h"
|
||||
|
||||
extern void saveAonRam();
|
||||
|
||||
void AON_level_VDD(int state)
|
||||
{
|
||||
@@ -90,9 +93,11 @@ extern struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received fro
|
||||
extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not
|
||||
void sleep_with_with_wakeup(uint32_t sleep_time_ms)
|
||||
{
|
||||
memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest));
|
||||
memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo));
|
||||
printf("sleep: %u\r\n", sleep_time_ms);
|
||||
saveAonRam();
|
||||
//memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest));
|
||||
//memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo));
|
||||
//sleep_time_ms = 10000;
|
||||
printf("sleep! %u\n", sleep_time_ms);
|
||||
uint32_t sleep_time_ms_1;
|
||||
AON_level_VDD(7);
|
||||
AON_level_VAA(0);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "core_cm3.h"
|
||||
#include "mz100_gpio.h"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include "nfc.h"
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
@@ -17,6 +17,8 @@
|
||||
#include "timer.h"
|
||||
#include "epd.h"
|
||||
#include "proto.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
#define WHO_AM_I 0x04
|
||||
uint8_t i2c_address = 0xAA;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
143
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c
Normal file → Executable file
143
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/powermgt.c
Normal file → Executable file
@@ -3,64 +3,69 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
// #include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "mz100_sleep.h"
|
||||
#include "zigbee.h"
|
||||
#include "eeprom.h"
|
||||
|
||||
#include "board.h"
|
||||
#include "screen.h"
|
||||
#include "eeprom.h"
|
||||
#include "main.h"
|
||||
#include "util.h"
|
||||
#include "mz100_sleep.h"
|
||||
#include "printf.h"
|
||||
#include "screen.h"
|
||||
#include "syncedproto.h"
|
||||
#include <stdbool.h>
|
||||
#include "util.h"
|
||||
#include "zigbee.h"
|
||||
|
||||
uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
|
||||
uint8_t dataReqAttemptArrayIndex = 0;
|
||||
uint8_t dataReqLastAttempt = 0;
|
||||
uint16_t nextCheckInFromAP = 0;
|
||||
uint8_t wakeUpReason = 0;
|
||||
uint8_t scanAttempts = 0;
|
||||
__attribute__((section(".aonshadow"))) uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
|
||||
__attribute__((section(".aonshadow"))) uint8_t dataReqAttemptArrayIndex = 0;
|
||||
__attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt = 0;
|
||||
__attribute__((section(".aonshadow"))) uint16_t nextCheckInFromAP = 0;
|
||||
__attribute__((section(".aonshadow"))) uint8_t wakeUpReason = 0;
|
||||
__attribute__((section(".aonshadow"))) uint8_t scanAttempts = 0;
|
||||
|
||||
int8_t temperature = 0;
|
||||
uint16_t batteryVoltage = 0;
|
||||
bool lowBattery = false;
|
||||
uint16_t longDataReqCounter = 0;
|
||||
uint16_t voltageCheckCounter = 0;
|
||||
__attribute__((section(".aonshadow"))) int8_t temperature = 0;
|
||||
__attribute__((section(".aonshadow"))) uint16_t batteryVoltage = 0;
|
||||
__attribute__((section(".aonshadow"))) bool lowBattery = false;
|
||||
__attribute__((section(".aonshadow"))) uint16_t longDataReqCounter = 0;
|
||||
__attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter = 0;
|
||||
|
||||
uint8_t capabilities = 0;
|
||||
__attribute__((section(".aonshadow"))) uint8_t capabilities = 0;
|
||||
|
||||
bool spiActive = false;
|
||||
bool uartActive = false;
|
||||
bool eepromActive = false;
|
||||
bool i2cActive = false;
|
||||
extern int8_t adcSampleTemperature(void); // in degrees C
|
||||
|
||||
uint8_t checkButtonOrJig()
|
||||
{
|
||||
extern int8_t adcSampleTemperature(void); // in degrees C
|
||||
|
||||
uint8_t checkButtonOrJig() {
|
||||
return DETECT_P1_0_NOTHING;
|
||||
}
|
||||
|
||||
void setupPortsInitial()
|
||||
{
|
||||
void setupPortsInitial() {
|
||||
}
|
||||
|
||||
void initPowerSaving(const uint16_t initialValue)
|
||||
{
|
||||
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++)
|
||||
{
|
||||
uint16_t doVoltageReading() {
|
||||
batteryVoltage = (uint16_t)measureBattery();
|
||||
if (batteryVoltage < BATTERY_VOLTAGE_MINIMUM) {
|
||||
lowBattery = true;
|
||||
} else {
|
||||
lowBattery = false;
|
||||
}
|
||||
return batteryVoltage;
|
||||
}
|
||||
|
||||
void initPowerSaving(const uint16_t initialValue) {
|
||||
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
|
||||
dataReqAttemptArr[c] = initialValue;
|
||||
}
|
||||
}
|
||||
|
||||
static void configSPI(const bool setup)
|
||||
{
|
||||
|
||||
static void configSPI(const bool setup) {
|
||||
spiActive = setup;
|
||||
}
|
||||
|
||||
static void configUART(const bool setup)
|
||||
{
|
||||
static void configUART(const bool setup) {
|
||||
/* if (setup == uartActive)
|
||||
return;
|
||||
uartActive = setup;
|
||||
@@ -70,69 +75,64 @@ static void configUART(const bool setup)
|
||||
Serial.end();*/
|
||||
}
|
||||
|
||||
static void configEEPROM(const bool setup)
|
||||
{
|
||||
static void configEEPROM(const bool setup) {
|
||||
}
|
||||
|
||||
static void configI2C(const bool setup)
|
||||
{
|
||||
static void configI2C(const bool setup) {
|
||||
}
|
||||
|
||||
void powerUp(const uint8_t parts)
|
||||
{
|
||||
printf("Power up: %d\r\n", parts);
|
||||
if (parts & INIT_RADIO)
|
||||
{
|
||||
void powerUp(const uint8_t parts) {
|
||||
// printf("Power up: %d\r\n", parts);
|
||||
if (parts & INIT_RADIO) {
|
||||
radioInit();
|
||||
// radioRxFilterCfg(mSelfMac, 0x10000, PROTO_PAN_ID);
|
||||
// radioSetTxPower(10);
|
||||
if (currentChannel >= 11 && currentChannel <= 27)
|
||||
{
|
||||
if (currentChannel >= 11 && currentChannel <= 27) {
|
||||
radioSetChannel(currentChannel);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
radioSetChannel(RADIO_FIRST_CHANNEL);
|
||||
}
|
||||
}
|
||||
if (parts & INIT_UART) {
|
||||
configUART(true);
|
||||
}
|
||||
if (parts & INIT_EPD) {
|
||||
configSPI(true);
|
||||
}
|
||||
if (parts & INIT_EEPROM) {
|
||||
configEEPROM(true);
|
||||
}
|
||||
if (parts & INIT_I2C) {
|
||||
configI2C(true);
|
||||
}
|
||||
}
|
||||
|
||||
void powerDown(const uint8_t parts)
|
||||
{
|
||||
printf("Power down: %d\r\n", parts);
|
||||
void powerDown(const uint8_t parts) {
|
||||
// printf("Power down: %d\r\n", parts);
|
||||
}
|
||||
|
||||
void doSleep(const uint32_t t)
|
||||
{
|
||||
void doSleep(const uint32_t t) {
|
||||
printf("Sleeping for: %d ms\r\n", t);
|
||||
// sleepForMs(t);
|
||||
delay(t);
|
||||
}
|
||||
|
||||
uint32_t getNextScanSleep(const bool increment)
|
||||
{
|
||||
if (increment)
|
||||
{
|
||||
uint32_t getNextScanSleep(const bool increment) {
|
||||
if (increment) {
|
||||
if (scanAttempts < 255)
|
||||
scanAttempts++;
|
||||
}
|
||||
|
||||
if (scanAttempts < INTERVAL_1_ATTEMPTS)
|
||||
{
|
||||
if (scanAttempts < INTERVAL_1_ATTEMPTS) {
|
||||
return INTERVAL_1_TIME;
|
||||
}
|
||||
else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))
|
||||
{
|
||||
} else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)) {
|
||||
return INTERVAL_2_TIME;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return INTERVAL_3_TIME;
|
||||
}
|
||||
}
|
||||
|
||||
void addAverageValue()
|
||||
{
|
||||
void addAverageValue() {
|
||||
uint16_t curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE;
|
||||
curval *= dataReqLastAttempt;
|
||||
curval /= DATA_REQ_MAX_ATTEMPTS;
|
||||
@@ -141,14 +141,11 @@ void addAverageValue()
|
||||
dataReqAttemptArrayIndex++;
|
||||
}
|
||||
|
||||
uint16_t getNextSleep()
|
||||
{
|
||||
/*uint16_t avg = 0;
|
||||
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++)
|
||||
{
|
||||
uint16_t getNextSleep() {
|
||||
uint16_t avg = 0;
|
||||
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++) {
|
||||
avg += dataReqAttemptArr[c];
|
||||
}
|
||||
avg /= POWER_SAVING_SMOOTHING;
|
||||
return avg;*/
|
||||
return 30;
|
||||
return avg;
|
||||
}
|
||||
@@ -60,20 +60,22 @@ extern void doSleep(const uint32_t t);
|
||||
extern void addAverageValue();
|
||||
extern uint16_t getNextSleep();
|
||||
|
||||
extern uint16_t doVoltageReading();
|
||||
|
||||
extern uint32_t getNextScanSleep(const bool increment);
|
||||
extern void initPowerSaving(const uint16_t initialValue);
|
||||
|
||||
extern uint8_t wakeUpReason;
|
||||
|
||||
extern uint8_t capabilities;
|
||||
extern __attribute__((section(".aonshadow"))) uint8_t capabilities;
|
||||
|
||||
extern uint16_t nextCheckInFromAP;
|
||||
extern uint8_t dataReqLastAttempt;
|
||||
extern int8_t temperature;
|
||||
extern uint16_t batteryVoltage;
|
||||
extern bool lowBattery;
|
||||
extern uint8_t scanAttempts;
|
||||
extern uint16_t longDataReqCounter;
|
||||
extern uint16_t voltageCheckCounter;
|
||||
extern __attribute__((section(".aonshadow"))) uint8_t dataReqLastAttempt;
|
||||
extern __attribute__((section(".aonshadow"))) int8_t temperature;
|
||||
extern __attribute__((section(".aonshadow"))) uint16_t batteryVoltage;
|
||||
extern __attribute__((section(".aonshadow"))) bool lowBattery;
|
||||
extern __attribute__((section(".aonshadow"))) uint8_t scanAttempts;
|
||||
extern __attribute__((section(".aonshadow"))) uint16_t longDataReqCounter;
|
||||
extern __attribute__((section(".aonshadow"))) uint16_t voltageCheckCounter;
|
||||
|
||||
#endif
|
||||
914
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.c
Normal file
914
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.c
Normal file
@@ -0,0 +1,914 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// \author (c) Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
//
|
||||
// \license The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
|
||||
// embedded systems with a very limited resources. These routines are thread
|
||||
// safe and reentrant!
|
||||
// Use this instead of the bloated standard/newlib printf cause these use
|
||||
// malloc for printf (and may not be thread safe).
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
|
||||
// printf_config.h header file
|
||||
// default: undefined
|
||||
#ifdef PRINTF_INCLUDE_CONFIG_H
|
||||
#include "printf_config.h"
|
||||
#endif
|
||||
|
||||
|
||||
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
|
||||
// numeric number including padded zeros (dynamically created on stack)
|
||||
// default: 32 byte
|
||||
#ifndef PRINTF_NTOA_BUFFER_SIZE
|
||||
#define PRINTF_NTOA_BUFFER_SIZE 32U
|
||||
#endif
|
||||
|
||||
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
|
||||
// float number including padded zeros (dynamically created on stack)
|
||||
// default: 32 byte
|
||||
#ifndef PRINTF_FTOA_BUFFER_SIZE
|
||||
#define PRINTF_FTOA_BUFFER_SIZE 32U
|
||||
#endif
|
||||
|
||||
// support for the floating point type (%f)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
|
||||
#define PRINTF_SUPPORT_FLOAT
|
||||
#endif
|
||||
|
||||
// support for exponential floating point notation (%e/%g)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
|
||||
#define PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif
|
||||
|
||||
// define the default floating point precision
|
||||
// default: 6 digits
|
||||
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
|
||||
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
|
||||
#endif
|
||||
|
||||
// define the largest float suitable to print with %f
|
||||
// default: 1e9
|
||||
#ifndef PRINTF_MAX_FLOAT
|
||||
#define PRINTF_MAX_FLOAT 1e9
|
||||
#endif
|
||||
|
||||
// support for the long long types (%llu or %p)
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
|
||||
#define PRINTF_SUPPORT_LONG_LONG
|
||||
#endif
|
||||
|
||||
// support for the ptrdiff_t type (%t)
|
||||
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
|
||||
// default: activated
|
||||
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
|
||||
#define PRINTF_SUPPORT_PTRDIFF_T
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// internal flag definitions
|
||||
#define FLAGS_ZEROPAD (1U << 0U)
|
||||
#define FLAGS_LEFT (1U << 1U)
|
||||
#define FLAGS_PLUS (1U << 2U)
|
||||
#define FLAGS_SPACE (1U << 3U)
|
||||
#define FLAGS_HASH (1U << 4U)
|
||||
#define FLAGS_UPPERCASE (1U << 5U)
|
||||
#define FLAGS_CHAR (1U << 6U)
|
||||
#define FLAGS_SHORT (1U << 7U)
|
||||
#define FLAGS_LONG (1U << 8U)
|
||||
#define FLAGS_LONG_LONG (1U << 9U)
|
||||
#define FLAGS_PRECISION (1U << 10U)
|
||||
#define FLAGS_ADAPT_EXP (1U << 11U)
|
||||
|
||||
|
||||
// import float.h for DBL_MAX
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
#include <float.h>
|
||||
#endif
|
||||
|
||||
|
||||
// output function type
|
||||
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
|
||||
|
||||
|
||||
// wrapper (used as buffer) for output function type
|
||||
typedef struct {
|
||||
void (*fct)(char character, void* arg);
|
||||
void* arg;
|
||||
} out_fct_wrap_type;
|
||||
|
||||
|
||||
// internal buffer output
|
||||
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
if (idx < maxlen) {
|
||||
((char*)buffer)[idx] = character;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// internal null output
|
||||
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
(void)character; (void)buffer; (void)idx; (void)maxlen;
|
||||
}
|
||||
|
||||
|
||||
// internal _putchar wrapper
|
||||
static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
(void)buffer; (void)idx; (void)maxlen;
|
||||
if (character) {
|
||||
_putchar(character);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// internal output function wrapper
|
||||
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)
|
||||
{
|
||||
(void)idx; (void)maxlen;
|
||||
if (character) {
|
||||
// buffer is the output fct pointer
|
||||
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// internal secure strlen
|
||||
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
|
||||
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
|
||||
{
|
||||
const char* s;
|
||||
for (s = str; *s && maxsize--; ++s);
|
||||
return (unsigned int)(s - str);
|
||||
}
|
||||
|
||||
|
||||
// internal test if char is a digit (0-9)
|
||||
// \return true if char is a digit
|
||||
static inline bool _is_digit(char ch)
|
||||
{
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
|
||||
// internal ASCII string to unsigned int conversion
|
||||
static unsigned int _atoi(const char** str)
|
||||
{
|
||||
unsigned int i = 0U;
|
||||
while (_is_digit(**str)) {
|
||||
i = i * 10U + (unsigned int)(*((*str)++) - '0');
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
// output the specified string in reverse, taking care of any zero-padding
|
||||
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
|
||||
{
|
||||
const size_t start_idx = idx;
|
||||
|
||||
// pad spaces up to given width
|
||||
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
|
||||
for (size_t i = len; i < width; i++) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
// reverse string
|
||||
while (len) {
|
||||
out(buf[--len], buffer, idx++, maxlen);
|
||||
}
|
||||
|
||||
// append pad spaces up to given width
|
||||
if (flags & FLAGS_LEFT) {
|
||||
while (idx - start_idx < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
// internal itoa format
|
||||
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
// pad leading zeros
|
||||
if (!(flags & FLAGS_LEFT)) {
|
||||
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
// handle hash
|
||||
if (flags & FLAGS_HASH) {
|
||||
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
|
||||
len--;
|
||||
if (len && (base == 16U)) {
|
||||
len--;
|
||||
}
|
||||
}
|
||||
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'x';
|
||||
}
|
||||
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'X';
|
||||
}
|
||||
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = 'b';
|
||||
}
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_NTOA_BUFFER_SIZE) {
|
||||
if (negative) {
|
||||
buf[len++] = '-';
|
||||
}
|
||||
else if (flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
}
|
||||
else if (flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
|
||||
// internal itoa for 'long' type
|
||||
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if (!value) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if (!(flags & FLAGS_PRECISION) || value) {
|
||||
do {
|
||||
const char digit = (char)(value % base);
|
||||
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||
}
|
||||
|
||||
|
||||
// internal itoa for 'long long' type
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_NTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
|
||||
// no hash for 0 values
|
||||
if (!value) {
|
||||
flags &= ~FLAGS_HASH;
|
||||
}
|
||||
|
||||
// write if precision != 0 and value is != 0
|
||||
if (!(flags & FLAGS_PRECISION) || value) {
|
||||
do {
|
||||
const char digit = (char)(value % base);
|
||||
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
|
||||
value /= base;
|
||||
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
|
||||
}
|
||||
|
||||
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
|
||||
}
|
||||
#endif // PRINTF_SUPPORT_LONG_LONG
|
||||
|
||||
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
|
||||
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
|
||||
#endif
|
||||
|
||||
|
||||
// internal ftoa for fixed decimal floating point
|
||||
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
char buf[PRINTF_FTOA_BUFFER_SIZE];
|
||||
size_t len = 0U;
|
||||
double diff = 0.0;
|
||||
|
||||
// powers of 10
|
||||
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
|
||||
// test for special values
|
||||
if (value != value)
|
||||
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
|
||||
if (value < -DBL_MAX)
|
||||
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
|
||||
if (value > DBL_MAX)
|
||||
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
|
||||
|
||||
// test for very large values
|
||||
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
|
||||
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
#else
|
||||
return 0U;
|
||||
#endif
|
||||
}
|
||||
|
||||
// test for negative
|
||||
bool negative = false;
|
||||
if (value < 0) {
|
||||
negative = true;
|
||||
value = 0 - value;
|
||||
}
|
||||
|
||||
// set default precision, if not set explicitly
|
||||
if (!(flags & FLAGS_PRECISION)) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
|
||||
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
|
||||
buf[len++] = '0';
|
||||
prec--;
|
||||
}
|
||||
|
||||
int whole = (int)value;
|
||||
double tmp = (value - whole) * pow10[prec];
|
||||
unsigned long frac = (unsigned long)tmp;
|
||||
diff = tmp - frac;
|
||||
|
||||
if (diff > 0.5) {
|
||||
++frac;
|
||||
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
|
||||
if (frac >= pow10[prec]) {
|
||||
frac = 0;
|
||||
++whole;
|
||||
}
|
||||
}
|
||||
else if (diff < 0.5) {
|
||||
}
|
||||
else if ((frac == 0U) || (frac & 1U)) {
|
||||
// if halfway, round up if odd OR if last digit is 0
|
||||
++frac;
|
||||
}
|
||||
|
||||
if (prec == 0U) {
|
||||
diff = value - (double)whole;
|
||||
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
|
||||
// exactly 0.5 and ODD, then round up
|
||||
// 1.5 -> 2, but 2.5 -> 2
|
||||
++whole;
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned int count = prec;
|
||||
// now do fractional part, as an unsigned number
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
--count;
|
||||
buf[len++] = (char)(48U + (frac % 10U));
|
||||
if (!(frac /= 10U)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add extra 0s
|
||||
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
// add decimal
|
||||
buf[len++] = '.';
|
||||
}
|
||||
}
|
||||
|
||||
// do whole part, number is reversed
|
||||
while (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
buf[len++] = (char)(48 + (whole % 10));
|
||||
if (!(whole /= 10)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// pad leading zeros
|
||||
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
|
||||
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
|
||||
width--;
|
||||
}
|
||||
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
|
||||
buf[len++] = '0';
|
||||
}
|
||||
}
|
||||
|
||||
if (len < PRINTF_FTOA_BUFFER_SIZE) {
|
||||
if (negative) {
|
||||
buf[len++] = '-';
|
||||
}
|
||||
else if (flags & FLAGS_PLUS) {
|
||||
buf[len++] = '+'; // ignore the space if the '+' exists
|
||||
}
|
||||
else if (flags & FLAGS_SPACE) {
|
||||
buf[len++] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
|
||||
}
|
||||
|
||||
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
|
||||
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
|
||||
{
|
||||
// check for NaN and special values
|
||||
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
|
||||
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
|
||||
}
|
||||
|
||||
// determine the sign
|
||||
const bool negative = value < 0;
|
||||
if (negative) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// default precision
|
||||
if (!(flags & FLAGS_PRECISION)) {
|
||||
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
|
||||
}
|
||||
|
||||
// determine the decimal exponent
|
||||
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
|
||||
union {
|
||||
uint64_t U;
|
||||
double F;
|
||||
} conv;
|
||||
|
||||
conv.F = value;
|
||||
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
|
||||
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
|
||||
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
|
||||
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
|
||||
// now we want to compute 10^expval but we want to be sure it won't overflow
|
||||
exp2 = (int)(expval * 3.321928094887362 + 0.5);
|
||||
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
|
||||
const double z2 = z * z;
|
||||
conv.U = (uint64_t)(exp2 + 1023) << 52U;
|
||||
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
|
||||
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
|
||||
// correct for rounding errors
|
||||
if (value < conv.F) {
|
||||
expval--;
|
||||
conv.F /= 10;
|
||||
}
|
||||
|
||||
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
|
||||
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
|
||||
|
||||
// in "%g" mode, "prec" is the number of *significant figures* not decimals
|
||||
if (flags & FLAGS_ADAPT_EXP) {
|
||||
// do we want to fall-back to "%f" mode?
|
||||
if ((value >= 1e-4) && (value < 1e6)) {
|
||||
if ((int)prec > expval) {
|
||||
prec = (unsigned)((int)prec - expval - 1);
|
||||
}
|
||||
else {
|
||||
prec = 0;
|
||||
}
|
||||
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
|
||||
// no characters in exponent
|
||||
minwidth = 0U;
|
||||
expval = 0;
|
||||
}
|
||||
else {
|
||||
// we use one sigfig for the whole part
|
||||
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
|
||||
--prec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// will everything fit?
|
||||
unsigned int fwidth = width;
|
||||
if (width > minwidth) {
|
||||
// we didn't fall-back so subtract the characters required for the exponent
|
||||
fwidth -= minwidth;
|
||||
} else {
|
||||
// not enough characters, so go back to default sizing
|
||||
fwidth = 0U;
|
||||
}
|
||||
if ((flags & FLAGS_LEFT) && minwidth) {
|
||||
// if we're padding on the right, DON'T pad the floating part
|
||||
fwidth = 0U;
|
||||
}
|
||||
|
||||
// rescale the float value
|
||||
if (expval) {
|
||||
value /= conv.F;
|
||||
}
|
||||
|
||||
// output the floating part
|
||||
const size_t start_idx = idx;
|
||||
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
|
||||
|
||||
// output the exponent part
|
||||
if (minwidth) {
|
||||
// output the exponential symbol
|
||||
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
|
||||
// output the exponent value
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
|
||||
// might need to right-pad spaces
|
||||
if (flags & FLAGS_LEFT) {
|
||||
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif // PRINTF_SUPPORT_FLOAT
|
||||
|
||||
|
||||
// internal vsnprintf
|
||||
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
|
||||
{
|
||||
unsigned int flags, width, precision, n;
|
||||
size_t idx = 0U;
|
||||
|
||||
if (!buffer) {
|
||||
// use null output function
|
||||
out = _out_null;
|
||||
}
|
||||
|
||||
while (*format)
|
||||
{
|
||||
// format specifier? %[flags][width][.precision][length]
|
||||
if (*format != '%') {
|
||||
// no
|
||||
out(*format, buffer, idx++, maxlen);
|
||||
format++;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// yes, evaluate it
|
||||
format++;
|
||||
}
|
||||
|
||||
// evaluate flags
|
||||
flags = 0U;
|
||||
do {
|
||||
switch (*format) {
|
||||
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
|
||||
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
|
||||
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
|
||||
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
|
||||
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
|
||||
default : n = 0U; break;
|
||||
}
|
||||
} while (n);
|
||||
|
||||
// evaluate width field
|
||||
width = 0U;
|
||||
if (_is_digit(*format)) {
|
||||
width = _atoi(&format);
|
||||
}
|
||||
else if (*format == '*') {
|
||||
const int w = va_arg(va, int);
|
||||
if (w < 0) {
|
||||
flags |= FLAGS_LEFT; // reverse padding
|
||||
width = (unsigned int)-w;
|
||||
}
|
||||
else {
|
||||
width = (unsigned int)w;
|
||||
}
|
||||
format++;
|
||||
}
|
||||
|
||||
// evaluate precision field
|
||||
precision = 0U;
|
||||
if (*format == '.') {
|
||||
flags |= FLAGS_PRECISION;
|
||||
format++;
|
||||
if (_is_digit(*format)) {
|
||||
precision = _atoi(&format);
|
||||
}
|
||||
else if (*format == '*') {
|
||||
const int prec = (int)va_arg(va, int);
|
||||
precision = prec > 0 ? (unsigned int)prec : 0U;
|
||||
format++;
|
||||
}
|
||||
}
|
||||
|
||||
// evaluate length field
|
||||
switch (*format) {
|
||||
case 'l' :
|
||||
flags |= FLAGS_LONG;
|
||||
format++;
|
||||
if (*format == 'l') {
|
||||
flags |= FLAGS_LONG_LONG;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
case 'h' :
|
||||
flags |= FLAGS_SHORT;
|
||||
format++;
|
||||
if (*format == 'h') {
|
||||
flags |= FLAGS_CHAR;
|
||||
format++;
|
||||
}
|
||||
break;
|
||||
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
|
||||
case 't' :
|
||||
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
#endif
|
||||
case 'j' :
|
||||
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
case 'z' :
|
||||
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
|
||||
format++;
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
// evaluate specifier
|
||||
switch (*format) {
|
||||
case 'd' :
|
||||
case 'i' :
|
||||
case 'u' :
|
||||
case 'x' :
|
||||
case 'X' :
|
||||
case 'o' :
|
||||
case 'b' : {
|
||||
// set the base
|
||||
unsigned int base;
|
||||
if (*format == 'x' || *format == 'X') {
|
||||
base = 16U;
|
||||
}
|
||||
else if (*format == 'o') {
|
||||
base = 8U;
|
||||
}
|
||||
else if (*format == 'b') {
|
||||
base = 2U;
|
||||
}
|
||||
else {
|
||||
base = 10U;
|
||||
flags &= ~FLAGS_HASH; // no hash for dec format
|
||||
}
|
||||
// uppercase
|
||||
if (*format == 'X') {
|
||||
flags |= FLAGS_UPPERCASE;
|
||||
}
|
||||
|
||||
// no plus or space flag for u, x, X, o, b
|
||||
if ((*format != 'i') && (*format != 'd')) {
|
||||
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
|
||||
}
|
||||
|
||||
// ignore '0' flag when precision is given
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
flags &= ~FLAGS_ZEROPAD;
|
||||
}
|
||||
|
||||
// convert the integer
|
||||
if ((*format == 'i') || (*format == 'd')) {
|
||||
// signed
|
||||
if (flags & FLAGS_LONG_LONG) {
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
const long long value = va_arg(va, long long);
|
||||
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||
#endif
|
||||
}
|
||||
else if (flags & FLAGS_LONG) {
|
||||
const long value = va_arg(va, long);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||
}
|
||||
else {
|
||||
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// unsigned
|
||||
if (flags & FLAGS_LONG_LONG) {
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
|
||||
#endif
|
||||
}
|
||||
else if (flags & FLAGS_LONG) {
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
|
||||
}
|
||||
else {
|
||||
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
#if defined(PRINTF_SUPPORT_FLOAT)
|
||||
case 'f' :
|
||||
case 'F' :
|
||||
if (*format == 'F') flags |= FLAGS_UPPERCASE;
|
||||
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||
format++;
|
||||
break;
|
||||
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
|
||||
case 'e':
|
||||
case 'E':
|
||||
case 'g':
|
||||
case 'G':
|
||||
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
|
||||
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
|
||||
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
|
||||
format++;
|
||||
break;
|
||||
#endif // PRINTF_SUPPORT_EXPONENTIAL
|
||||
#endif // PRINTF_SUPPORT_FLOAT
|
||||
case 'c' : {
|
||||
unsigned int l = 1U;
|
||||
// pre padding
|
||||
if (!(flags & FLAGS_LEFT)) {
|
||||
while (l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// char output
|
||||
out((char)va_arg(va, int), buffer, idx++, maxlen);
|
||||
// post padding
|
||||
if (flags & FLAGS_LEFT) {
|
||||
while (l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 's' : {
|
||||
const char* p = va_arg(va, char*);
|
||||
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
|
||||
// pre padding
|
||||
if (flags & FLAGS_PRECISION) {
|
||||
l = (l < precision ? l : precision);
|
||||
}
|
||||
if (!(flags & FLAGS_LEFT)) {
|
||||
while (l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
// string output
|
||||
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
|
||||
out(*(p++), buffer, idx++, maxlen);
|
||||
}
|
||||
// post padding
|
||||
if (flags & FLAGS_LEFT) {
|
||||
while (l++ < width) {
|
||||
out(' ', buffer, idx++, maxlen);
|
||||
}
|
||||
}
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'p' : {
|
||||
width = sizeof(void*) * 2U;
|
||||
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
|
||||
if (is_ll) {
|
||||
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
|
||||
#if defined(PRINTF_SUPPORT_LONG_LONG)
|
||||
}
|
||||
#endif
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
|
||||
case '%' :
|
||||
out('%', buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
|
||||
default :
|
||||
out(*format, buffer, idx++, maxlen);
|
||||
format++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// termination
|
||||
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
|
||||
|
||||
// return written chars without terminating \0
|
||||
return (int)idx;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int printf_(const char* format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
char buffer[1];
|
||||
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int sprintf_(char* buffer, const char* format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int snprintf_(char* buffer, size_t count, const char* format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int vprintf_(const char* format, va_list va)
|
||||
{
|
||||
char buffer[1];
|
||||
return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
|
||||
}
|
||||
|
||||
|
||||
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va)
|
||||
{
|
||||
return _vsnprintf(_out_buffer, buffer, count, format, va);
|
||||
}
|
||||
|
||||
|
||||
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
const out_fct_wrap_type out_fct_wrap = { out, arg };
|
||||
const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
|
||||
va_end(va);
|
||||
return ret;
|
||||
}
|
||||
116
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.h
Normal file
116
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/printf.h
Normal file
@@ -0,0 +1,116 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// \author (c) Marco Paland (info@paland.com)
|
||||
// 2014-2019, PALANDesign Hannover, Germany
|
||||
//
|
||||
// \license The MIT License (MIT)
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
|
||||
// embedded systems with a very limited resources.
|
||||
// Use this instead of bloated standard/newlib printf.
|
||||
// These routines are thread safe and reentrant.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _PRINTF_H_
|
||||
#define _PRINTF_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Output a character to a custom device like UART, used by the printf() function
|
||||
* This function is declared here only. You have to write your custom implementation somewhere
|
||||
* \param character Character to output
|
||||
*/
|
||||
void _putchar(char character);
|
||||
|
||||
/**
|
||||
* Tiny printf implementation
|
||||
* You have to implement _putchar if you use printf()
|
||||
* To avoid conflicts with the regular printf() API it is overridden by macro defines
|
||||
* and internal underscore-appended functions like printf_() are used
|
||||
* \param format A string that specifies the format of the output
|
||||
* \return The number of characters that are written into the array, not counting the terminating null character
|
||||
*/
|
||||
#define printf printf_
|
||||
int printf_(const char* format, ...);
|
||||
|
||||
|
||||
/**
|
||||
* Tiny sprintf implementation
|
||||
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
|
||||
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
|
||||
* \param format A string that specifies the format of the output
|
||||
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
|
||||
*/
|
||||
#define sprintf sprintf_
|
||||
int sprintf_(char* buffer, const char* format, ...);
|
||||
|
||||
|
||||
/**
|
||||
* Tiny snprintf/vsnprintf implementation
|
||||
* \param buffer A pointer to the buffer where to store the formatted string
|
||||
* \param count The maximum number of characters to store in the buffer, including a terminating null character
|
||||
* \param format A string that specifies the format of the output
|
||||
* \param va A value identifying a variable arguments list
|
||||
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
|
||||
* null character. A value equal or larger than count indicates truncation. Only when the returned value
|
||||
* is non-negative and less than count, the string has been completely written.
|
||||
*/
|
||||
#define snprintf snprintf_
|
||||
#define vsnprintf vsnprintf_
|
||||
int snprintf_(char* buffer, size_t count, const char* format, ...);
|
||||
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va);
|
||||
|
||||
|
||||
/**
|
||||
* Tiny vprintf implementation
|
||||
* \param format A string that specifies the format of the output
|
||||
* \param va A value identifying a variable arguments list
|
||||
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
|
||||
*/
|
||||
#define vprintf vprintf_
|
||||
int vprintf_(const char* format, va_list va);
|
||||
|
||||
|
||||
/**
|
||||
* printf with output function
|
||||
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
|
||||
* \param out An output function which takes one character and an argument pointer
|
||||
* \param arg An argument pointer for user data passed to output function
|
||||
* \param format A string that specifies the format of the output
|
||||
* \return The number of characters that are sent to the output function, not counting the terminating null character
|
||||
*/
|
||||
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // _PRINTF_H_
|
||||
@@ -4,49 +4,49 @@
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
All communications are direct from tag to station, EXCEPT association (tag will broadcast).
|
||||
All comms shall be encrypted and authenticated with AES-CCM. Shared key shall be burned into the firmware.
|
||||
Master shall provision new key at association. All non-bcast packets shall have pan id compression.
|
||||
Master may skip "from" field. Tag checking in confirms it got the master's provisioning reply.
|
||||
|
||||
Sadly filtering on MZ100 fails for long addr with no src addr. so short addr for src is used
|
||||
|
||||
T = tag, S = station
|
||||
|
||||
PACKET TYPE USE PAYLOAD STRUCT NOTES
|
||||
ASSOC_REQ T2bcast TagInfo tag's info and assoc request (encrypted with shared key)
|
||||
ASSOC_RESP S2T AssocInfo tag's association info (encrypted with shared key)
|
||||
CHECKIN T2S CheckinInfo tag checking in occasionally
|
||||
CHECKOUT S2T PendingInfo station's checkin reply telling tag what we have for it
|
||||
CHUNK_REQ T2S ChunkReqInfo tag requesting a piece of data
|
||||
CHUNK_RESP S2T ChunkInfo station provides chunk
|
||||
All communications are direct from tag to station, EXCEPT association (tag will broadcast).
|
||||
All comms shall be encrypted and authenticated with AES-CCM. Shared key shall be burned into the firmware.
|
||||
Master shall provision new key at association. All non-bcast packets shall have pan id compression.
|
||||
Master may skip "from" field. Tag checking in confirms it got the master's provisioning reply.
|
||||
|
||||
Sadly filtering on MZ100 fails for long addr with no src addr. so short addr for src is used
|
||||
|
||||
T = tag, S = station
|
||||
|
||||
PACKET TYPE USE PAYLOAD STRUCT NOTES
|
||||
ASSOC_REQ T2bcast TagInfo tag's info and assoc request (encrypted with shared key)
|
||||
ASSOC_RESP S2T AssocInfo tag's association info (encrypted with shared key)
|
||||
CHECKIN T2S CheckinInfo tag checking in occasionally
|
||||
CHECKOUT S2T PendingInfo station's checkin reply telling tag what we have for it
|
||||
CHUNK_REQ T2S ChunkReqInfo tag requesting a piece of data
|
||||
CHUNK_RESP S2T ChunkInfo station provides chunk
|
||||
|
||||
*/
|
||||
|
||||
#define PROTO_PRESHARED_KEY {0x34D906D3, 0xE3E5298E, 0x3429BF58, 0xC1022081}
|
||||
#define PROTO_PRESHARED_KEY \
|
||||
{ 0x34D906D3, 0xE3E5298E, 0x3429BF58, 0xC1022081 }
|
||||
|
||||
#define PROTO_PAN_ID (0x4447) //PAN ID compression shall be used
|
||||
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
|
||||
|
||||
#define PKT_ASSOC_REQ (0xF0)
|
||||
#define PKT_ASSOC_RESP (0xF1)
|
||||
#define PKT_CHECKIN (0xF2)
|
||||
#define PKT_CHECKOUT (0xF3)
|
||||
#define PKT_CHUNK_REQ (0xF4)
|
||||
#define PKT_CHUNK_RESP (0xF5)
|
||||
#define PKT_ASSOC_REQ (0xF0)
|
||||
#define PKT_ASSOC_RESP (0xF1)
|
||||
#define PKT_CHECKIN (0xF2)
|
||||
#define PKT_CHECKOUT (0xF3)
|
||||
#define PKT_CHUNK_REQ (0xF4)
|
||||
#define PKT_CHUNK_RESP (0xF5)
|
||||
|
||||
#define PROTO_VER_0 (0)
|
||||
#define PROTO_VER_CURRENT (PROTO_VER_0)
|
||||
#define PROTO_VER_0 (0)
|
||||
#define PROTO_VER_CURRENT (PROTO_VER_0)
|
||||
|
||||
#define PROTO_COMPR_TYPE_LZ (0x0001)
|
||||
#define PROTO_COMPR_TYPE_BITPACK (0x0002)
|
||||
|
||||
#define PROTO_MAX_DL_LEN (88)
|
||||
#define PROTO_COMPR_TYPE_LZ (0x0001)
|
||||
#define PROTO_COMPR_TYPE_BITPACK (0x0002)
|
||||
|
||||
#define PROTO_MAX_DL_LEN (88)
|
||||
|
||||
//////////////// NEW
|
||||
|
||||
#include "tag_types.h"
|
||||
|
||||
/*
|
||||
// power saving algorithm
|
||||
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
|
||||
#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current
|
||||
@@ -68,7 +68,7 @@
|
||||
#define INTERVAL_2_TIME 7200UL // Try every 2 hours
|
||||
#define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day)
|
||||
#define INTERVAL_3_TIME 86400UL // Finally, try every day
|
||||
|
||||
*/
|
||||
#pragma pack(1)
|
||||
enum TagScreenType {
|
||||
TagScreenEink_BW_1bpp,
|
||||
@@ -96,8 +96,6 @@ enum TagScreenType {
|
||||
TagScreenTypeOther = 0x7f,
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
|
||||
|
||||
#define ADDR_MODE_NONE (0)
|
||||
@@ -122,7 +120,7 @@ struct MacFcs {
|
||||
uint8_t destAddrType : 2;
|
||||
uint8_t frameVer : 2;
|
||||
uint8_t srcAddrType : 2;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct MacFrameFromMaster {
|
||||
struct MacFcs fcs;
|
||||
@@ -130,7 +128,7 @@ struct MacFrameFromMaster {
|
||||
uint16_t pan;
|
||||
uint8_t dst[8];
|
||||
uint16_t from;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct MacFrameNormal {
|
||||
struct MacFcs fcs;
|
||||
@@ -138,7 +136,7 @@ struct MacFrameNormal {
|
||||
uint16_t pan;
|
||||
uint8_t dst[8];
|
||||
uint8_t src[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct MacFrameBcast {
|
||||
struct MacFcs fcs;
|
||||
@@ -147,7 +145,7 @@ struct MacFrameBcast {
|
||||
uint16_t dstAddr;
|
||||
uint16_t srcPan;
|
||||
uint8_t src[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
|
||||
#define PKT_AVAIL_DATA_REQ 0xE5
|
||||
@@ -175,7 +173,7 @@ struct AvailDataReq {
|
||||
uint8_t currentChannel;
|
||||
uint8_t customMode;
|
||||
uint8_t reserved[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct oldAvailDataReq {
|
||||
uint8_t checksum;
|
||||
@@ -186,7 +184,7 @@ struct oldAvailDataReq {
|
||||
uint8_t hwType;
|
||||
uint8_t wakeupReason;
|
||||
uint8_t capabilities;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct AvailDataInfo {
|
||||
uint8_t checksum;
|
||||
@@ -195,31 +193,31 @@ struct AvailDataInfo {
|
||||
uint8_t dataType;
|
||||
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
|
||||
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
|
||||
} ;
|
||||
} __attribute__((packed)) ;
|
||||
|
||||
struct pendingData {
|
||||
struct AvailDataInfo availdatainfo;
|
||||
uint16_t attemptsLeft;
|
||||
uint8_t targetMac[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct blockPart {
|
||||
uint8_t checksum;
|
||||
uint8_t blockId;
|
||||
uint8_t blockPart;
|
||||
uint8_t data[];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct blockData {
|
||||
uint16_t size;
|
||||
uint16_t checksum;
|
||||
uint8_t data[];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct burstMacData {
|
||||
uint16_t offset;
|
||||
uint8_t targetMac[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
#define BLOCK_PART_DATA_SIZE 99
|
||||
#define BLOCK_MAX_PARTS 42
|
||||
@@ -238,140 +236,131 @@ struct blockRequest {
|
||||
struct blockRequestAck {
|
||||
uint8_t checksum;
|
||||
uint16_t pleaseWaitMs;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct espBlockRequest {
|
||||
uint8_t checksum;
|
||||
uint64_t ver;
|
||||
uint8_t blockId;
|
||||
uint8_t src[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct espXferComplete {
|
||||
uint8_t checksum;
|
||||
uint8_t src[8];
|
||||
} ;
|
||||
};
|
||||
|
||||
struct espAvailDataReq {
|
||||
uint8_t checksum;
|
||||
uint8_t src[8];
|
||||
struct AvailDataReq adr;
|
||||
} ;
|
||||
};
|
||||
|
||||
struct espSetChannelPower {
|
||||
uint8_t checksum;
|
||||
uint8_t channel;
|
||||
uint8_t power;
|
||||
} ;
|
||||
};
|
||||
#pragma pack(0)
|
||||
///////////////// NEW END
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((packed))
|
||||
#define __packed __attribute__((packed))
|
||||
#endif
|
||||
struct TagState {
|
||||
uint64_t swVer;
|
||||
uint16_t hwType;
|
||||
uint16_t batteryMv;
|
||||
uint64_t swVer;
|
||||
uint16_t hwType;
|
||||
uint16_t batteryMv;
|
||||
} __packed;
|
||||
|
||||
struct TagInfo {
|
||||
uint8_t protoVer; //PROTO_VER_*
|
||||
struct TagState state;
|
||||
uint8_t rfu1[1]; //shall be ignored for now
|
||||
uint16_t screenPixWidth;
|
||||
uint16_t screenPixHeight;
|
||||
uint16_t screenMmWidth;
|
||||
uint16_t screenMmHeight;
|
||||
uint16_t compressionsSupported; //COMPR_TYPE_* bitfield
|
||||
uint16_t maxWaitMsec; //how long tag will wait for packets before going to sleep
|
||||
uint8_t screenType; //enum TagScreenType
|
||||
uint8_t rfu[11]; //shall be zero for now
|
||||
uint8_t protoVer; // PROTO_VER_*
|
||||
struct TagState state;
|
||||
uint8_t rfu1[1]; // shall be ignored for now
|
||||
uint16_t screenPixWidth;
|
||||
uint16_t screenPixHeight;
|
||||
uint16_t screenMmWidth;
|
||||
uint16_t screenMmHeight;
|
||||
uint16_t compressionsSupported; // COMPR_TYPE_* bitfield
|
||||
uint16_t maxWaitMsec; // how long tag will wait for packets before going to sleep
|
||||
uint8_t screenType; // enum TagScreenType
|
||||
uint8_t rfu[11]; // shall be zero for now
|
||||
} __packed;
|
||||
|
||||
struct AssocInfo {
|
||||
uint32_t checkinDelay; //space between checkins, in msec
|
||||
uint32_t retryDelay; //if download fails mid-way wait thi smany msec to retry (IFF progress was made)
|
||||
uint16_t failedCheckinsTillBlank; //how many fails till we go blank
|
||||
uint16_t failedCheckinsTillDissoc; //how many fails till we dissociate
|
||||
uint32_t newKey[4];
|
||||
uint8_t rfu[8]; //shall be zero for now
|
||||
uint32_t checkinDelay; // space between checkins, in msec
|
||||
uint32_t retryDelay; // if download fails mid-way wait thi smany msec to retry (IFF progress was made)
|
||||
uint16_t failedCheckinsTillBlank; // how many fails till we go blank
|
||||
uint16_t failedCheckinsTillDissoc; // how many fails till we dissociate
|
||||
uint32_t newKey[4];
|
||||
uint8_t rfu[8]; // shall be zero for now
|
||||
} __packed;
|
||||
|
||||
#define CHECKIN_TEMP_OFFSET 0x7f
|
||||
#define CHECKIN_TEMP_OFFSET 0x7f
|
||||
|
||||
struct CheckinInfo {
|
||||
struct TagState state;
|
||||
uint8_t lastPacketLQI; //zero if not reported/not supported to be reported
|
||||
int8_t lastPacketRSSI; //zero if not reported/not supported to be reported
|
||||
uint8_t temperature; //zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C
|
||||
uint8_t rfu[6]; //shall be zero for now
|
||||
struct TagState state;
|
||||
uint8_t lastPacketLQI; // zero if not reported/not supported to be reported
|
||||
int8_t lastPacketRSSI; // zero if not reported/not supported to be reported
|
||||
uint8_t temperature; // zero if not reported/not supported to be reported. else, this minus CHECKIN_TEMP_OFFSET is temp in degrees C
|
||||
uint8_t rfu[6]; // shall be zero for now
|
||||
} __packed;
|
||||
|
||||
struct PendingInfo {
|
||||
uint64_t imgUpdateVer;
|
||||
uint32_t imgUpdateSize;
|
||||
uint64_t osUpdateVer; //version of OS update avail
|
||||
uint32_t osUpdateSize;
|
||||
uint8_t rfu[8]; //shall be zero for now
|
||||
uint64_t imgUpdateVer;
|
||||
uint32_t imgUpdateSize;
|
||||
uint64_t osUpdateVer; // version of OS update avail
|
||||
uint32_t osUpdateSize;
|
||||
uint8_t rfu[8]; // shall be zero for now
|
||||
} __packed;
|
||||
|
||||
struct ChunkReqInfo {
|
||||
uint64_t versionRequested;
|
||||
uint32_t offset;
|
||||
uint8_t len;
|
||||
uint8_t osUpdatePlz : 1;
|
||||
uint8_t rfu[6]; //shall be zero for now
|
||||
uint64_t versionRequested;
|
||||
uint32_t offset;
|
||||
uint8_t len;
|
||||
uint8_t osUpdatePlz : 1;
|
||||
uint8_t rfu[6]; // shall be zero for now
|
||||
} __packed;
|
||||
|
||||
struct ChunkInfo {
|
||||
uint32_t offset;
|
||||
uint8_t osUpdatePlz : 1;
|
||||
uint8_t rfu; //shall be zero for now
|
||||
uint8_t data[]; //no data means request is out of bounds of this version no longer exists
|
||||
uint32_t offset;
|
||||
uint8_t osUpdatePlz : 1;
|
||||
uint8_t rfu; // shall be zero for now
|
||||
uint8_t data[]; // no data means request is out of bounds of this version no longer exists
|
||||
} __packed;
|
||||
|
||||
#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0]
|
||||
|
||||
#define VERSION_SIGNIFICANT_MASK (0x0000ffffffffffffull)
|
||||
|
||||
#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
|
||||
#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0]
|
||||
#define HW_TYPE_42_INCH_SAMSUNG (1)
|
||||
#define HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST (0xEFF8)
|
||||
|
||||
#define HW_TYPE_74_INCH_DISPDATA (2)
|
||||
#define HW_TYPE_74_INCH_DISPDATA_FRAME_MODE (3)
|
||||
#define HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define VERSION_SIGNIFICANT_MASK (0x0000ffffffffffffull)
|
||||
#define HW_TYPE_ZBD_EPOP50 (4)
|
||||
#define HW_TYPE_ZBD_EPOP50_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_42_INCH_SAMSUNG (1)
|
||||
#define HW_TYPE_42_INCH_SAMSUNG_ROM_VER_OFST (0xEFF8)
|
||||
#define HW_TYPE_ZBD_EPOP900 (5)
|
||||
#define HW_TYPE_ZBD_EPOP900_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_74_INCH_DISPDATA (2)
|
||||
#define HW_TYPE_74_INCH_DISPDATA_FRAME_MODE (3)
|
||||
#define HW_TYPE_74_INCH_DISPDATA_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_ZBD_EPOP50 (4)
|
||||
#define HW_TYPE_ZBD_EPOP50_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_ZBD_EPOP900 (5)
|
||||
#define HW_TYPE_ZBD_EPOP900_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_29_INCH_DISPDATA (6)
|
||||
#define HW_TYPE_29_INCH_DISPDATA_FRAME_MODE (7)
|
||||
#define HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_29_INCH_ZBS_026 (8)
|
||||
#define HW_TYPE_29_INCH_ZBS_026_FRAME_MODE (9)
|
||||
#define HW_TYPE_29_INCH_ZBS_025 (10)
|
||||
#define HW_TYPE_29_INCH_ZBS_025_FRAME_MODE (11)
|
||||
#define HW_TYPE_29_INCH_ZBS_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_74_INCH_BWR (40)
|
||||
#define HW_TYPE_74_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
#define HW_TYPE_58_INCH_BWR (41)
|
||||
#define HW_TYPE_58_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
#define HW_TYPE_42_INCH_BWR (42)
|
||||
#define HW_TYPE_42_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
#define HW_TYPE_29_INCH_DISPDATA (6)
|
||||
#define HW_TYPE_29_INCH_DISPDATA_FRAME_MODE (7)
|
||||
#define HW_TYPE_29_INCH_DISPDATA_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_29_INCH_ZBS_026 (8)
|
||||
#define HW_TYPE_29_INCH_ZBS_026_FRAME_MODE (9)
|
||||
#define HW_TYPE_29_INCH_ZBS_025 (10)
|
||||
#define HW_TYPE_29_INCH_ZBS_025_FRAME_MODE (11)
|
||||
#define HW_TYPE_29_INCH_ZBS_ROM_VER_OFST (0x008b)
|
||||
|
||||
#define HW_TYPE_74_INCH_BWR (40)
|
||||
#define HW_TYPE_74_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
#define HW_TYPE_58_INCH_BWR (41)
|
||||
#define HW_TYPE_58_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
#define HW_TYPE_42_INCH_BWR (42)
|
||||
#define HW_TYPE_42_INCH_BWR_ROM_VER_OFST (0x0160)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,143 +3,24 @@
|
||||
#include "eeprom.h"
|
||||
#include "util.h"
|
||||
#include "mz100_flash.h"
|
||||
#include "powermgt.h"
|
||||
|
||||
__attribute__((section(".aonshadow"))) struct tagsettings tagSettings = {0};
|
||||
extern uint8_t blockXferBuffer[];
|
||||
uint8_t* infopageTempBuffer = 1024 + blockXferBuffer;
|
||||
|
||||
|
||||
#define EEPROM_NUM_SETTINGS_PAGES (EEPROM_SETTINGS_AREA_LEN / EEPROM_PAGE_SIZE)
|
||||
#define SETTINGS_MAGIC (0x31415926)
|
||||
|
||||
|
||||
|
||||
static uint32_t mCurSettingsAddr;
|
||||
|
||||
static void settingsPrvDoWriteAtLocation(uint32_t addr, struct Settings* settings)
|
||||
{
|
||||
settings->hdr.revision++;
|
||||
mCurSettingsAddr = addr;
|
||||
FLASH_Write(false, addr, (uint8_t*)settings, sizeof(struct Settings));
|
||||
}
|
||||
|
||||
//this is impossible to call before calling read. thus mCurSettingsAddr will be set
|
||||
void settingsPrvDoWrite(struct Settings* settings)
|
||||
{
|
||||
struct SettingsHeader sh;
|
||||
uint32_t i, addr;
|
||||
uint8_t byte;
|
||||
|
||||
|
||||
//first we try to fit in the current page, after current (latest) settings
|
||||
if (mCurSettingsAddr) {
|
||||
|
||||
FLASH_Read(0, mCurSettingsAddr, (uint8_t*)&sh, sizeof(struct SettingsHeader));
|
||||
addr = mCurSettingsAddr + sh.structSize;
|
||||
|
||||
//is there space?
|
||||
if (addr % EEPROM_PAGE_SIZE != 0 && addr % EEPROM_PAGE_SIZE + sizeof(struct Settings) <= EEPROM_PAGE_SIZE) {
|
||||
|
||||
//is it erased
|
||||
for (i = 0; i < sizeof(struct Settings); i++) {
|
||||
|
||||
FLASH_Read(0, addr, &byte, 1);
|
||||
if (byte != 0xff)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == sizeof(struct Settings)) {
|
||||
|
||||
settingsPrvDoWriteAtLocation(addr, settings);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//we need to erase - use next page (or 0th page if no current page at all)
|
||||
if (mCurSettingsAddr) {
|
||||
|
||||
addr = (mCurSettingsAddr + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
|
||||
if (addr == EEPROM_SETTINGS_AREA_START + EEPROM_SETTINGS_AREA_LEN)
|
||||
addr = EEPROM_SETTINGS_AREA_START;
|
||||
}
|
||||
else
|
||||
addr = EEPROM_SETTINGS_AREA_START;
|
||||
|
||||
qspiEraseRange(addr, EEPROM_PAGE_SIZE);
|
||||
settingsPrvDoWriteAtLocation(addr, settings);
|
||||
}
|
||||
|
||||
void settingsRead(struct Settings* settings)
|
||||
{
|
||||
uint32_t bestAddr = 0, page, ofst;
|
||||
uint64_t bestRevision = 0;
|
||||
struct SettingsHeader sh;
|
||||
bool doWrite = true;
|
||||
|
||||
for (page = 0; page < EEPROM_NUM_SETTINGS_PAGES; page++) {
|
||||
|
||||
for (ofst = 0; ofst < EEPROM_PAGE_SIZE - sizeof(struct SettingsHeader); ofst += sh.structSize) {
|
||||
|
||||
uint32_t addr = EEPROM_SETTINGS_AREA_START + page * EEPROM_PAGE_SIZE + ofst;
|
||||
|
||||
FLASH_Read(0, addr, (uint8_t*)&sh, sizeof(struct SettingsHeader));
|
||||
|
||||
//sanity checks. struct is only allowed to grow in size...
|
||||
if (sh.magic != SETTINGS_MAGIC || ofst + sh.structSize > EEPROM_PAGE_SIZE || sh.structSize > sizeof(struct Settings))
|
||||
break;
|
||||
|
||||
if (sh.revision > bestRevision) {
|
||||
bestRevision = sh.revision;
|
||||
bestAddr = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestAddr) {
|
||||
FLASH_Read(0, bestAddr, (uint8_t*)&sh, sizeof(struct SettingsHeader)); //to get size
|
||||
FLASH_Read(0, bestAddr, (uint8_t*)settings, sh.structSize);
|
||||
mCurSettingsAddr = bestAddr;
|
||||
}
|
||||
else {
|
||||
settings->hdr.structVersion = SETTINGS_VER_NONE;
|
||||
settings->hdr.revision = 1;
|
||||
mCurSettingsAddr = 0;
|
||||
}
|
||||
|
||||
//migrate
|
||||
switch (settings->hdr.structVersion) {
|
||||
|
||||
//current version here - mark as such
|
||||
case SETTINGS_CURRENT:
|
||||
doWrite = false;
|
||||
break;
|
||||
|
||||
case SETTINGS_VER_NONE: //migrate to v1
|
||||
memset(settings, 0, sizeof(*settings));
|
||||
settings->hdr.magic = SETTINGS_MAGIC;
|
||||
//fallthrough
|
||||
|
||||
case SETTINGS_VER_1: //migrate to v2
|
||||
settings->prevDlProgress = 0xffff;
|
||||
//fallthrough
|
||||
|
||||
case SETTINGS_VER_2: //migrate to v3
|
||||
settings->lastRxedRSSI = 0;
|
||||
//fallthrough
|
||||
|
||||
//new migrations here in order from lower vers to higher vers
|
||||
|
||||
settings->hdr.structVersion = SETTINGS_CURRENT;
|
||||
settings->hdr.structSize = sizeof(struct Settings);
|
||||
break;
|
||||
}
|
||||
|
||||
if (doWrite)
|
||||
settingsPrvDoWrite(settings);
|
||||
}
|
||||
|
||||
void settingsWrite(struct Settings* settings)
|
||||
{
|
||||
struct Settings s;
|
||||
|
||||
settingsRead(&s);
|
||||
if (memcmp(&s, settings, sizeof(struct Settings)))
|
||||
settingsPrvDoWrite(settings);
|
||||
void loadDefaultSettings() {
|
||||
tagSettings.settingsVer = SETTINGS_STRUCT_VERSION;
|
||||
tagSettings.enableFastBoot = DEFAULT_SETTING_FASTBOOT;
|
||||
tagSettings.enableRFWake = DEFAULT_SETTING_RFWAKE;
|
||||
tagSettings.enableTagRoaming = DEFAULT_SETTING_TAGROAMING;
|
||||
tagSettings.enableScanForAPAfterTimeout = DEFAULT_SETTING_SCANFORAP;
|
||||
tagSettings.enableLowBatSymbol = DEFAULT_SETTING_LOWBATSYMBOL;
|
||||
tagSettings.enableNoRFSymbol = DEFAULT_SETTING_NORFSYMBOL;
|
||||
tagSettings.customMode = 0;
|
||||
tagSettings.fastBootCapabilities = 0;
|
||||
tagSettings.minimumCheckInTime = INTERVAL_BASE;
|
||||
tagSettings.fixedChannel = 0;
|
||||
tagSettings.batLowVoltage = BATTERY_VOLTAGE_MINIMUM;
|
||||
}
|
||||
@@ -1,65 +1,41 @@
|
||||
#ifndef _SETTINGS_H_
|
||||
#define _SETTINGS_H_
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SETTINGS_VER_NONE (0x00000000)
|
||||
#define SETTINGS_VER_1 (0x00000001)
|
||||
#define SETTINGS_VER_2 (0x00000002)
|
||||
#define SETTINGS_VER_3 (0x00000003)
|
||||
#define FW_VERSION 20 // version number (max 2.5.5 :) )
|
||||
#define FW_VERSION_SUFFIX "-75" // suffix, like -RC1 or whatever.
|
||||
// #define DEBUGBLOCKS // uncomment to enable extra debug information on the block transfers
|
||||
// #define PRINT_LUT // uncomment if you want the tag to print the LUT for the current temperature bracket
|
||||
|
||||
struct SettingsHeader {
|
||||
uint32_t magic;
|
||||
uint64_t revision;
|
||||
uint8_t structVersion;
|
||||
uint8_t structSize; //incl this header
|
||||
#define SETTINGS_STRUCT_VERSION 0x01
|
||||
|
||||
#define DEFAULT_SETTING_FASTBOOT 0
|
||||
#define DEFAULT_SETTING_RFWAKE 0
|
||||
#define DEFAULT_SETTING_TAGROAMING 0
|
||||
#define DEFAULT_SETTING_SCANFORAP 1
|
||||
#define DEFAULT_SETTING_LOWBATSYMBOL 1
|
||||
#define DEFAULT_SETTING_NORFSYMBOL 1
|
||||
|
||||
struct tagsettings {
|
||||
uint8_t settingsVer; // the version of the struct as written to the infopage
|
||||
uint8_t enableFastBoot; // default 0; if set, it will skip splashscreen
|
||||
uint8_t enableRFWake; // default 0; if set, it will enable RF wake. This will add about ~0.9µA idle power consumption
|
||||
uint8_t enableTagRoaming; // default 0; if set, the tag will scan for an accesspoint every few check-ins. This will increase power consumption quite a bit
|
||||
uint8_t enableScanForAPAfterTimeout; // default 1; if a the tag failed to check in, after a few attempts it will try to find a an AP on other channels
|
||||
uint8_t enableLowBatSymbol; // default 1; tag will show 'low battery' icon on screen if the battery is depleted
|
||||
uint8_t enableNoRFSymbol; // default 1; tag will show 'no signal' icon on screen if it failed to check in for a longer period of time
|
||||
uint8_t fastBootCapabilities; // holds the byte with 'capabilities' as detected during a normal tag boot; allows the tag to skip detecting buttons and NFC chip
|
||||
uint8_t customMode; // default 0; if anything else, tag will bootup in a different 'mode'
|
||||
uint16_t batLowVoltage; // Low battery threshold voltage (2450 for 2.45v). defaults to BATTERY_VOLTAGE_MINIMUM from powermgt.h
|
||||
uint16_t minimumCheckInTime; // defaults to BASE_INTERVAL from powermgt.h
|
||||
uint8_t fixedChannel; // default 0; if set to a valid channel number, the tag will stick to that channel
|
||||
} __attribute__((packed));
|
||||
|
||||
enum SettingsThingType {
|
||||
SettingsThingTypeNone,
|
||||
SettingsThingTypeImage,
|
||||
SettingsThingTypeUpdate,
|
||||
};
|
||||
extern __attribute__((section(".aonshadow")))struct tagsettings tagSettings;
|
||||
|
||||
#define SETTING_CHANNEL_OFFSET 11
|
||||
|
||||
struct Settings { //V1
|
||||
struct SettingsHeader hdr;
|
||||
|
||||
//master address
|
||||
uint8_t masterMac[8];
|
||||
|
||||
//encryption things
|
||||
uint32_t encrKey[4];
|
||||
uint32_t nextIV;
|
||||
|
||||
//checkin tracking
|
||||
uint32_t checkinDelay; //space between checkins, in msec
|
||||
uint32_t retryDelay;
|
||||
uint16_t failedCheckinsTillBlank; //how many fails till we go blank
|
||||
uint16_t failedCheckinsTillDissoc; //how many fails till we dissociate
|
||||
uint16_t numFailedCheckins;
|
||||
|
||||
//state
|
||||
uint8_t lastRxedLQI;
|
||||
uint8_t isPaired : 1;
|
||||
uint8_t channel : 4; //minus SETTING_CHANNEL_OFFSET
|
||||
uint8_t reserved : 3;
|
||||
|
||||
uint16_t prevDlProgress;
|
||||
|
||||
int8_t lastRxedRSSI;
|
||||
uint32_t helperInit;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
#define SETTINGS_CURRENT SETTINGS_VER_3
|
||||
|
||||
|
||||
void settingsRead(struct Settings* settings);
|
||||
void settingsWrite(struct Settings* settings);
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
void loadDefaultSettings();
|
||||
void writeSettings();
|
||||
void loadSettings();
|
||||
void loadSettingsFromBuffer(uint8_t* p);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
extern uint8_t mSelfMac[];
|
||||
extern uint8_t currentChannel;
|
||||
extern __attribute__((section(".aonshadow"))) uint8_t mSelfMac[];
|
||||
extern __attribute__((section(".aonshadow"))) volatile uint8_t currentChannel;
|
||||
extern __attribute__((section(".aonshadow"))) struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send
|
||||
extern __attribute__((section(".aonshadow"))) struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received from the AP // __attribute__((section(".aon")))
|
||||
|
||||
|
||||
extern uint8_t APmac[];
|
||||
|
||||
extern uint8_t curImgSlot;
|
||||
extern __attribute__((section(".aonshadow"))) uint8_t curImgSlot;
|
||||
|
||||
extern void setupRadio(void);
|
||||
extern void killRadio(void);
|
||||
|
||||
181
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.c
Normal file
181
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.c
Normal file
@@ -0,0 +1,181 @@
|
||||
#include "userinterface.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bitmaps.h"
|
||||
#include "board.h"
|
||||
#include "comms.h"
|
||||
#include "epd.h"
|
||||
#include "font.h"
|
||||
#include "powermgt.h"
|
||||
#include "printf.h"
|
||||
#include "proto.h"
|
||||
#include "screen.h"
|
||||
#include "settings.h"
|
||||
#include "syncedproto.h" // for APmac / Channel
|
||||
#include "timer.h"
|
||||
|
||||
const uint16_t fwVersion = FW_VERSION;
|
||||
const char fwVersionSuffix[] = FW_VERSION_SUFFIX;
|
||||
|
||||
extern uint8_t capabilities;
|
||||
|
||||
bool __attribute__((section(".aonshadow"))) lowBatteryShown = false;
|
||||
bool __attribute__((section(".aonshadow"))) noAPShown = false;
|
||||
|
||||
void addCapabilities() {
|
||||
// if (capabilities) epdpr("Options: ");
|
||||
if (capabilities & CAPABILITY_HAS_NFC) {
|
||||
// epdpr("-NFC");
|
||||
if (capabilities & CAPABILITY_NFC_WAKE) {
|
||||
// epdpr("+WAKE");
|
||||
} else {
|
||||
// epdpr(" ");
|
||||
}
|
||||
}
|
||||
if (capabilities & CAPABILITY_HAS_WAKE_BUTTON) {
|
||||
// epdpr("-WAKE BUTTON");
|
||||
}
|
||||
}
|
||||
|
||||
void addOverlay() {
|
||||
if ((currentChannel == 0) && (tagSettings.enableNoRFSymbol)) {
|
||||
// loadRawBitmap(ant, SCREEN_WIDTH - 24, 6, EPD_COLOR_BLACK);
|
||||
// loadRawBitmap(cross, SCREEN_WIDTH - 16, 13, EPD_COLOR_RED);
|
||||
noAPShown = true;
|
||||
} else {
|
||||
noAPShown = false;
|
||||
}
|
||||
if ((batteryVoltage < tagSettings.batLowVoltage) && (tagSettings.enableLowBatSymbol)) {
|
||||
// loadRawBitmap(battery, SCREEN_WIDTH - 16, SCREEN_HEIGHT - 10, EPD_COLOR_BLACK);
|
||||
lowBatteryShown = true;
|
||||
} else {
|
||||
lowBatteryShown = false;
|
||||
}
|
||||
}
|
||||
|
||||
void afterFlashScreenSaver() {
|
||||
// selectLUT(EPD_LUT_DEFAULT);
|
||||
// clearScreen();
|
||||
|
||||
#if (SCREEN_WIDTH == 400) // 4.2"
|
||||
epdPrintBegin(3, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
epdpr("OpenEPaperLink");
|
||||
epdPrintEnd();
|
||||
#endif
|
||||
// drawWithSleep();
|
||||
}
|
||||
|
||||
void showSplashScreen() {
|
||||
// selectLUT(EPD_LUT_NO_REPEATS);
|
||||
// clearScreen();
|
||||
#if (SCREEN_WIDTH == 400) // 4.2"
|
||||
epdPrintBegin(3, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
epdpr("Starting");
|
||||
epdPrintEnd();
|
||||
|
||||
epdPrintBegin(2, 252, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
addCapabilities();
|
||||
epdPrintEnd();
|
||||
|
||||
epdPrintBegin(3, 268, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
epdpr("zbs42v033 %d.%d.%d%s", fwVersion / 100, (fwVersion % 100) / 10, (fwVersion % 10), fwVersionSuffix);
|
||||
epdPrintEnd();
|
||||
epdPrintBegin(3, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_RED);
|
||||
epdpr("MAC: %02X:%02X", mSelfMac[7], mSelfMac[6]);
|
||||
epdpr(":%02X:%02X", mSelfMac[5], mSelfMac[4]);
|
||||
epdpr(":%02X:%02X", mSelfMac[3], mSelfMac[2]);
|
||||
epdpr(":%02X:%02X", mSelfMac[1], mSelfMac[0]);
|
||||
epdPrintEnd();
|
||||
|
||||
loadRawBitmap(oepli, 136, 22, EPD_COLOR_BLACK);
|
||||
loadRawBitmap(cloud, 136, 10, EPD_COLOR_RED);
|
||||
|
||||
uint8_t __xdata buffer[17];
|
||||
spr(buffer, "%02X%02X", mSelfMac[7], mSelfMac[6]);
|
||||
spr(buffer + 4, "%02X%02X", mSelfMac[5], mSelfMac[4]);
|
||||
spr(buffer + 8, "%02X%02X", mSelfMac[3], mSelfMac[2]);
|
||||
spr(buffer + 12, "%02X%02X", mSelfMac[1], mSelfMac[0]);
|
||||
printBarcode(buffer, 392, 264);
|
||||
printBarcode(buffer, 384, 264);
|
||||
|
||||
#endif
|
||||
// drawWithSleep();
|
||||
}
|
||||
|
||||
void showApplyUpdate() {
|
||||
// selectLUT(1);
|
||||
// clearScreen();
|
||||
#if (SCREEN_WIDTH == 400)
|
||||
epdPrintBegin(136, 134, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
#endif
|
||||
|
||||
// epdpr("Updating!");
|
||||
// epdPrintEnd();
|
||||
// drawNoWait();
|
||||
}
|
||||
|
||||
void showAPFound() {
|
||||
|
||||
init_epd();
|
||||
fillWindow(0, 0, 640, 384, 1);
|
||||
epdPrintf(10, 10, 1, "OpenEPaperLink");
|
||||
epdPrintf(10, 40, 1, "AP Found at channel %d", currentChannel);
|
||||
epdPrintf(10, 60, 1, "AP MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", APmac[7], APmac[6], APmac[5], APmac[4], APmac[3], APmac[2], APmac[1], APmac[0]);
|
||||
|
||||
epdPrintf(10, 330, 1, "Battery: %d.%dV", batteryVoltage / 1000, batteryVoltage % 1000);
|
||||
epdPrintf(10, 350, 1, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
|
||||
epd_refresh_and_sleep();
|
||||
}
|
||||
|
||||
void showNoAP() {
|
||||
init_epd();
|
||||
fillWindow(0, 0, 640, 384, 1);
|
||||
epdPrintf(10, 10, 1, "OpenEPaperLink ");
|
||||
epdPrintf(10, 40, 1, "No AP found... We'll try again in a little while though!");
|
||||
epdPrintf(10, 350, 1, "Tag MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
|
||||
|
||||
epd_refresh_and_sleep();
|
||||
}
|
||||
|
||||
void showLongTermSleep() {
|
||||
// selectLUT(EPD_LUT_NO_REPEATS);
|
||||
// clearScreen();
|
||||
|
||||
// epdPrintBegin(2, SCREEN_HEIGHT - 16, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
// epdpr("zZ");
|
||||
// epdPrintEnd();
|
||||
|
||||
addOverlay();
|
||||
// drawWithSleep();
|
||||
}
|
||||
void showNoEEPROM() {
|
||||
// selectLUT(EPD_LUT_NO_REPEATS);
|
||||
// clearScreen();
|
||||
#if (SCREEN_WIDTH == 400) // 4.2"
|
||||
epdPrintBegin(50, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
epdpr("EEPROM FAILED :(");
|
||||
epdPrintEnd();
|
||||
loadRawBitmap(failed, 176, 126, EPD_COLOR_RED);
|
||||
epdPrintBegin(100, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
epdpr("Sleeping forever :'(");
|
||||
epdPrintEnd();
|
||||
#endif
|
||||
// drawWithSleep();
|
||||
}
|
||||
|
||||
void showNoMAC() {
|
||||
// selectLUT(EPD_LUT_NO_REPEATS);
|
||||
// clearScreen();
|
||||
#if (SCREEN_WIDTH == 400) // 4.2"
|
||||
epdPrintBegin(100, 3, EPD_DIRECTION_X, EPD_SIZE_DOUBLE, EPD_COLOR_BLACK);
|
||||
epdpr("NO MAC SET :(");
|
||||
epdPrintEnd();
|
||||
loadRawBitmap(failed, 176, 126, EPD_COLOR_RED);
|
||||
epdPrintBegin(100, 284, EPD_DIRECTION_X, EPD_SIZE_SINGLE, EPD_COLOR_BLACK);
|
||||
epdpr("Sleeping forever :'(");
|
||||
epdPrintEnd();
|
||||
#endif
|
||||
// drawWithSleep();
|
||||
}
|
||||
22
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.h
Normal file
22
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/userinterface.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef _UI_H_
|
||||
#define _UI_H_
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void addOverlay();
|
||||
|
||||
void afterFlashScreenSaver();
|
||||
void showSplashScreen();
|
||||
void showApplyUpdate();
|
||||
void showAPFound();
|
||||
void showNoAP();
|
||||
void showLongTermSleep();
|
||||
void showNoEEPROM();
|
||||
void showNoMAC();
|
||||
|
||||
extern const uint16_t fwVersion;
|
||||
extern const char fwVersionSuffix[];
|
||||
extern __attribute__((section(".aon"))) bool lowBatteryShown;
|
||||
extern __attribute__((section(".aon"))) bool noAPShown;
|
||||
|
||||
#endif
|
||||
@@ -1,213 +1,185 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include "eeprom.h"
|
||||
#include "timer.h"
|
||||
#include "mz100.h"
|
||||
#include "util.h"
|
||||
#include "mz100_flash.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
//#include <stdio.h>
|
||||
#include "printf.h"
|
||||
|
||||
#include "eeprom.h"
|
||||
#include "mz100.h"
|
||||
#include "mz100_adc.h"
|
||||
#include "mz100_flash.h"
|
||||
#include "mz100_wdt.h"
|
||||
#include "timer.h"
|
||||
|
||||
void wdt10s()
|
||||
{
|
||||
void wdt10s() {
|
||||
WDT_RestartCounter();
|
||||
}
|
||||
void wdt30s()
|
||||
{
|
||||
void wdt30s() {
|
||||
WDT_RestartCounter();
|
||||
}
|
||||
void wdt60s()
|
||||
{
|
||||
void wdt60s() {
|
||||
WDT_RestartCounter();
|
||||
}
|
||||
|
||||
void delay(int cnt)
|
||||
{
|
||||
volatile unsigned int i;
|
||||
for (i = 107 * cnt; i; --i)
|
||||
;
|
||||
void delay(int cnt) {
|
||||
volatile unsigned int i;
|
||||
for (i = 107 * cnt; i; --i)
|
||||
;
|
||||
}
|
||||
|
||||
void delay_us(unsigned int result)
|
||||
{
|
||||
volatile unsigned int i;
|
||||
void delay_us(unsigned int result) {
|
||||
volatile unsigned int i;
|
||||
|
||||
for (i = 0; i < result; ++i)
|
||||
;
|
||||
for (i = 0; i < result; ++i)
|
||||
;
|
||||
}
|
||||
|
||||
uint16_t crc16(uint16_t cur_crc, uint8_t data)
|
||||
{
|
||||
cur_crc ^= data;
|
||||
for (uint8_t i = 8; i > 0; i--)
|
||||
{
|
||||
if ((cur_crc & 0x001) != 0)
|
||||
{
|
||||
cur_crc >>= 1;
|
||||
cur_crc ^= 0x8005; // poly
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_crc >>= 1;
|
||||
}
|
||||
}
|
||||
return cur_crc;
|
||||
uint16_t crc16(uint16_t cur_crc, uint8_t data) {
|
||||
cur_crc ^= data;
|
||||
for (uint8_t i = 8; i > 0; i--) {
|
||||
if ((cur_crc & 0x001) != 0) {
|
||||
cur_crc >>= 1;
|
||||
cur_crc ^= 0x8005; // poly
|
||||
} else {
|
||||
cur_crc >>= 1;
|
||||
}
|
||||
}
|
||||
return cur_crc;
|
||||
}
|
||||
|
||||
uint32_t measureTemp(void)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
ADC_CFG_Type adc_config;
|
||||
adc_config.adcResolution = ADC_RESOLUTION_14BIT;
|
||||
adc_config.adcVrefSource = ADC_VREF_INTERNAL; // 1.2V
|
||||
adc_config.adcGainSel = ADC_GAIN_1;
|
||||
adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4;
|
||||
adc_config.adcBiasMode = ADC_BIAS_FULL;
|
||||
uint32_t measureTemp(void) {
|
||||
uint32_t result = 0;
|
||||
ADC_CFG_Type adc_config;
|
||||
adc_config.adcResolution = ADC_RESOLUTION_14BIT;
|
||||
adc_config.adcVrefSource = ADC_VREF_INTERNAL; // 1.2V
|
||||
adc_config.adcGainSel = ADC_GAIN_1;
|
||||
adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4;
|
||||
adc_config.adcBiasMode = ADC_BIAS_FULL;
|
||||
|
||||
ADC_Reset();
|
||||
ADC_ModeSelect(ADC_MODE_TSENSOR);
|
||||
ADC_TSensorConfig(ADC_TEMPP, ADC_SENSOR_INTERNAL);
|
||||
ADC_Init(&adc_config);
|
||||
ADC_Enable();
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
}
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
result += (ADC_GetConversionResult() - 458) / 1.7;
|
||||
}
|
||||
result /= 128;
|
||||
printf("Temp: %iC\r\n", result);
|
||||
return result;
|
||||
ADC_Reset();
|
||||
ADC_ModeSelect(ADC_MODE_TSENSOR);
|
||||
ADC_TSensorConfig(ADC_TEMPP, ADC_SENSOR_INTERNAL);
|
||||
ADC_Init(&adc_config);
|
||||
ADC_Enable();
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
}
|
||||
for (int i = 0; i < 128; i++) {
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
result += (ADC_GetConversionResult() - 458) / 1.7;
|
||||
}
|
||||
result /= 128;
|
||||
printf("Temp: %iC\r\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t measureBattery(void)
|
||||
{
|
||||
uint32_t result = 0;
|
||||
ADC_CFG_Type adc_config;
|
||||
adc_config.adcResolution = ADC_RESOLUTION_16BIT;
|
||||
adc_config.adcVrefSource = ADC_VREF_VCAU; // 1.8V
|
||||
adc_config.adcGainSel = ADC_GAIN_1; // range 0 - 1.8V
|
||||
adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4;
|
||||
adc_config.adcBiasMode = ADC_BIAS_FULL;
|
||||
uint32_t measureBattery(void) {
|
||||
uint32_t result = 0;
|
||||
ADC_CFG_Type adc_config;
|
||||
adc_config.adcResolution = ADC_RESOLUTION_16BIT;
|
||||
adc_config.adcVrefSource = ADC_VREF_VCAU; // 1.8V
|
||||
adc_config.adcGainSel = ADC_GAIN_1; // range 0 - 1.8V
|
||||
adc_config.adcClockDivider = ADC_CLOCK_DIVIDER_4;
|
||||
adc_config.adcBiasMode = ADC_BIAS_FULL;
|
||||
|
||||
ADC_Reset();
|
||||
ADC_ModeSelect(ADC_MODE_ADC);
|
||||
ADC_ChannelConfig(ADC_VBATS); // 0.33 of Actual Voltage
|
||||
ADC_Init(&adc_config);
|
||||
ADC_Enable();
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
}
|
||||
for (int i = 0; i < 128; i++)
|
||||
{
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
result += ADC_GetConversionResult() * 5940 / 32768;
|
||||
}
|
||||
result /= 128;
|
||||
printf("Voltage: %imV\r\n", result);
|
||||
return result;
|
||||
ADC_Reset();
|
||||
ADC_ModeSelect(ADC_MODE_ADC);
|
||||
ADC_ChannelConfig(ADC_VBATS); // 0.33 of Actual Voltage
|
||||
ADC_Init(&adc_config);
|
||||
ADC_Enable();
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
}
|
||||
for (int i = 0; i < 128; i++) {
|
||||
ADC_ConversionStart();
|
||||
ADC_IntClr(ADC_RDY);
|
||||
while (!ADC_GetStatus(ADC_STATUS_RDY))
|
||||
;
|
||||
ADC_ConversionStop();
|
||||
result += ADC_GetConversionResult() * 5940 / 32768;
|
||||
}
|
||||
result /= 128;
|
||||
printf("Voltage: %imV\r\n", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void qspiEraseRange(uint32_t addr, uint32_t len)
|
||||
{
|
||||
uint64_t time;
|
||||
// round starting address down
|
||||
if (addr % EEPROM_PAGE_SIZE)
|
||||
{
|
||||
len += addr % EEPROM_PAGE_SIZE;
|
||||
addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
|
||||
}
|
||||
void qspiEraseRange(uint32_t addr, uint32_t len) {
|
||||
uint64_t time;
|
||||
// round starting address down
|
||||
if (addr % EEPROM_PAGE_SIZE) {
|
||||
len += addr % EEPROM_PAGE_SIZE;
|
||||
addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// round length up
|
||||
len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
|
||||
// round length up
|
||||
len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
|
||||
|
||||
while (len)
|
||||
{
|
||||
while (len) {
|
||||
uint32_t now;
|
||||
bool ok;
|
||||
|
||||
uint32_t now;
|
||||
bool ok;
|
||||
WDT_RestartCounter();
|
||||
if (!(addr % 0x10000) && len >= 0x10000) {
|
||||
ok = FLASH_Block64KErase(addr / 0x10000);
|
||||
now = 0x10000;
|
||||
} else if (!(addr % 0x8000) && len >= 0x8000) {
|
||||
ok = FLASH_Block32KErase(addr / 0x8000);
|
||||
now = 0x8000;
|
||||
} else {
|
||||
ok = FLASH_SectorErase(addr / 0x1000);
|
||||
now = 0x1000;
|
||||
}
|
||||
|
||||
WDT_RestartCounter();
|
||||
if (!(addr % 0x10000) && len >= 0x10000)
|
||||
{
|
||||
ok = FLASH_Block64KErase(addr / 0x10000);
|
||||
now = 0x10000;
|
||||
}
|
||||
else if (!(addr % 0x8000) && len >= 0x8000)
|
||||
{
|
||||
ok = FLASH_Block32KErase(addr / 0x8000);
|
||||
now = 0x8000;
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = FLASH_SectorErase(addr / 0x1000);
|
||||
now = 0x1000;
|
||||
}
|
||||
if (!ok)
|
||||
printf("ERZ fail at 0x%08x + %u\r\n", addr, now);
|
||||
|
||||
if (!ok)
|
||||
printf("ERZ fail at 0x%08x + %u\r\n", addr, now);
|
||||
|
||||
addr += now;
|
||||
len -= now;
|
||||
if (len)
|
||||
{
|
||||
// let the caps recharge
|
||||
time = timerGet();
|
||||
while (timerGet() - time < TIMER_TICKS_PER_SEC / 10)
|
||||
;
|
||||
}
|
||||
}
|
||||
WDT_RestartCounter();
|
||||
addr += now;
|
||||
len -= now;
|
||||
if (len) {
|
||||
// let the caps recharge
|
||||
time = timerGet();
|
||||
while (timerGet() - time < TIMER_TICKS_PER_SEC / 10)
|
||||
;
|
||||
}
|
||||
}
|
||||
WDT_RestartCounter();
|
||||
}
|
||||
|
||||
bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len)
|
||||
{
|
||||
FLASH_Write(false, addr, srcP, len);
|
||||
return true;
|
||||
bool eepromWrite(uint32_t addr, const void *srcP, uint16_t len) {
|
||||
FLASH_Write(false, addr, (void*)srcP, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eepromErase(uint32_t addr, uint16_t nSec)
|
||||
{
|
||||
qspiEraseRange(addr, nSec);
|
||||
return true;
|
||||
bool eepromErase(uint32_t addr, uint16_t nSec) {
|
||||
qspiEraseRange(addr, nSec);
|
||||
return true;
|
||||
}
|
||||
|
||||
void eepromRead(uint32_t addr, void *dstP, uint16_t len)
|
||||
{
|
||||
uint8_t *dst = (uint8_t *)dstP;
|
||||
FLASH_Read(0, addr, dst, len);
|
||||
void eepromRead(uint32_t addr, void *dstP, uint16_t len) {
|
||||
uint8_t *dst = (uint8_t *)dstP;
|
||||
FLASH_Read(0, addr, dst, len);
|
||||
}
|
||||
uint32_t eepromGetSize(void)
|
||||
{
|
||||
return EEPROM_IMG_LEN;
|
||||
uint32_t eepromGetSize(void) {
|
||||
return EEPROM_IMG_LEN;
|
||||
}
|
||||
|
||||
void radioShutdown(void)
|
||||
{
|
||||
// i have no idea what these do, determined by writing random registers and watching the current drawn
|
||||
*(volatile uint32_t *)0x4C000000 = 0;
|
||||
*(volatile uint32_t *)0x4C010000 = 0;
|
||||
*(volatile uint32_t *)0x4C010004 = 0x10000000;
|
||||
void radioShutdown(void) {
|
||||
// i have no idea what these do, determined by writing random registers and watching the current drawn
|
||||
*(volatile uint32_t *)0x4C000000 = 0;
|
||||
*(volatile uint32_t *)0x4C010000 = 0;
|
||||
*(volatile uint32_t *)0x4C010004 = 0x10000000;
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <stdio.h>
|
||||
//#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "util.h"
|
||||
#include "zigbee.h"
|
||||
#include "printf.h"
|
||||
|
||||
volatile uint8_t calibration_irq_ocoured = 0;
|
||||
volatile uint8_t zigbee_tx_done = 0;
|
||||
@@ -145,24 +146,29 @@ void fill_rx_regs()
|
||||
;
|
||||
}
|
||||
|
||||
void sub_1021E6()
|
||||
void load_calib()
|
||||
{
|
||||
int v0;
|
||||
unsigned int v1;
|
||||
unsigned int i;
|
||||
|
||||
v0 = (*(volatile unsigned int *)0x4C01000C);
|
||||
v1 = get_register(0x130004);
|
||||
v1 = zigbeeCalibData.len;
|
||||
(*(volatile unsigned int *)0x4C010000) |= 4u;
|
||||
while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) == 0)
|
||||
;
|
||||
for (i = 0; i < v1; ++i)
|
||||
set_register(v0 + 4 * i + 0x4C014000, *(uint32_t *)(4 * i + 0x130008));
|
||||
set_register(v0 + 4 * i + 0x4C014000, zigbeeCalibData.data[i]);
|
||||
(*(volatile unsigned int *)0x4C010000) &= ~4u;
|
||||
while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) != 0)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// It is from 0x130000 up to 0x1301000 But you can only use 0x130404 up to the 0x1301000
|
||||
|
||||
|
||||
void save_calib_in_ram()
|
||||
{
|
||||
int v0;
|
||||
@@ -171,14 +177,14 @@ void save_calib_in_ram()
|
||||
|
||||
v0 = (*(volatile unsigned int *)0x4C01000C) + 0x4C014000;
|
||||
v1 = ((unsigned int)(uint8_t)((*(volatile unsigned int *)0x4C010008) >> 2) + 3) >> 2;
|
||||
set_register(0x130000u, 0x464C4147);
|
||||
set_register(0x130004u, v1);
|
||||
zigbeeCalibData.isValid = true;
|
||||
(*(volatile unsigned int *)0x4C01001C) = -5;
|
||||
(*(volatile unsigned int *)0x4C010000) |= 2u;
|
||||
while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) == 0)
|
||||
;
|
||||
for (i = 0; i < v1; ++i)
|
||||
set_register(4 * i + 0x130008, *(uint32_t *)(v0 + 4 * i));
|
||||
for (i = 0; i < v1; ++i){
|
||||
zigbeeCalibData.data[i] = *(uint32_t *)(v0 + 4 * i);
|
||||
}
|
||||
(*(volatile unsigned int *)0x4C010000) &= ~2u;
|
||||
while (((*(volatile unsigned int *)0x4C010008) & 0x1000000) != 0)
|
||||
;
|
||||
@@ -189,12 +195,12 @@ int inner_calibration()
|
||||
int is_in_ram;
|
||||
|
||||
(*(volatile unsigned int *)0x4C010000) |= 0x20u;
|
||||
if (get_register(0x130000) == 0x464C4147)
|
||||
if(zigbeeCalibData.isValid)
|
||||
{
|
||||
is_in_ram = 1;
|
||||
(*(volatile unsigned int *)0x4C010000) |= 8u;
|
||||
(*(volatile unsigned int *)0x4C010000) &= ~0x10u;
|
||||
sub_1021E6();
|
||||
load_calib();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include <stdlib.h>
|
||||
|
||||
extern uint8_t channelList[6];
|
||||
|
||||
@@ -10,4 +11,11 @@ uint8_t Zigbee_tx_buffer(uint8_t *tx_buffer, int len);
|
||||
void radioInit();
|
||||
void radioSetChannel(uint8_t channel);
|
||||
void radioRxEnable(uint8_t channel);
|
||||
void radioRxFlush();
|
||||
void radioRxFlush();
|
||||
|
||||
struct zigbeeCalibDataStruct {
|
||||
uint16_t len;
|
||||
bool isValid;
|
||||
uint32_t data[30];
|
||||
};
|
||||
extern __attribute__((section(".aon"))) volatile struct zigbeeCalibDataStruct zigbeeCalibData;
|
||||
|
||||
7
ESP32_AP-Flasher/32MB_partition table.csv
Normal file
7
ESP32_AP-Flasher/32MB_partition table.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, 0x480000,
|
||||
app1, app, ota_1, 0x490000,0x480000,
|
||||
spiffs, data, spiffs, 0x910000,0x16E0000,
|
||||
coredump, data, coredump,0x1FF0000,0x10000,
|
||||
|
@@ -1,129 +0,0 @@
|
||||
{
|
||||
"1": {
|
||||
"0": {
|
||||
"weekday": [ 76, 10, "fonts/calibrib30" ],
|
||||
"month": [ 76, 120, "fonts/calibrib30" ],
|
||||
"day": [ 76, 42, "fonts/calibrib100" ]
|
||||
},
|
||||
"1": {
|
||||
"weekday": [ 148, 10, "fonts/calibrib60" ],
|
||||
"date": [ 148, 73, "fonts/calibrib50" ]
|
||||
},
|
||||
"2": {
|
||||
"weekday": [ 200, 25, "fonts/calibrib60" ],
|
||||
"month": [ 200, 225, "fonts/calibrib60" ],
|
||||
"day": [ 200, 95, "fonts/calibrib150" ]
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"0": {
|
||||
"fonts": [ "fonts/calibrib120", "fonts/calibrib80", "fonts/calibrib50", "fonts/calibrib50" ],
|
||||
"xy": [ 76, 83 ]
|
||||
},
|
||||
"1": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120", "fonts/calibrib100" ],
|
||||
"xy": [ 148, 74 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120" ],
|
||||
"xy": [ 200, 148 ]
|
||||
}
|
||||
},
|
||||
"4": {
|
||||
"0": {
|
||||
"location": [ 10, 145, "t0_14b_tf" ],
|
||||
"wind": [ 140, 10, "fonts/bahnschrift30" ],
|
||||
"temp": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"icon": [ 75, 26, 70, 1 ],
|
||||
"dir": [ 110, -12, 40 ],
|
||||
"umbrella": [ 125, 110, 30 ]
|
||||
},
|
||||
"1": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"wind": [ 280, 5, "fonts/bahnschrift30" ],
|
||||
"temp": [ 5, 65, "fonts/bahnschrift70" ],
|
||||
"icon": [ 285, 20, 70, 2 ],
|
||||
"dir": [ 245, -12, 40 ],
|
||||
"umbrella": [ 190, -50, 25 ]
|
||||
},
|
||||
"2": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 83, "fonts/calibrib60" ],
|
||||
"temp": [ 20, 170, "fonts/calibrib150" ],
|
||||
"icon": [ 385, 0, 100, 2 ],
|
||||
"dir": [ 40, 50, 80 ],
|
||||
"umbrella": [ 325, 155, 78 ]
|
||||
}
|
||||
},
|
||||
"8": {
|
||||
"1": {
|
||||
"location": [ 5, 12, "t0_14b_tf" ],
|
||||
"column": [ 5, 59 ],
|
||||
"day": [ 30, 18, "fonts/twcondensed20", 41, 108 ],
|
||||
"icon": [ 30, 55, 30 ],
|
||||
"wind": [ 18, 26 ],
|
||||
"line": [ 20, 128 ]
|
||||
},
|
||||
"2": {
|
||||
"location": [ 10, 10, "fonts/calibrib30" ],
|
||||
"column": [ 6, 66 ],
|
||||
"day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ],
|
||||
"rain": [ 34, 260 ],
|
||||
"icon": [ 32, 145, 30 ],
|
||||
"wind": [ 17, 90 ],
|
||||
"line": [ 50, 300 ]
|
||||
}
|
||||
},
|
||||
"9": {
|
||||
"1": {
|
||||
"title": [ 5, 3, "fonts/bahnschrift20" ],
|
||||
"items": 8,
|
||||
"line": [ 5, 34, 13 ],
|
||||
"font": "glasstown_nbp_tf"
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/calibrib30" ],
|
||||
"items": 12,
|
||||
"line": [ 10, 60, 20 ],
|
||||
"font": "7x14_tf"
|
||||
}
|
||||
},
|
||||
"10": {
|
||||
"0": {
|
||||
"title": [ 10, 15, "t0_14b_tf" ],
|
||||
"pos": [ 76, 20 ]
|
||||
},
|
||||
"1": {
|
||||
"title": [ 10, 5, "fonts/bahnschrift20" ],
|
||||
"pos": [ 149, 25 ]
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 200, 30 ]
|
||||
}
|
||||
},
|
||||
"11": {
|
||||
"1": {
|
||||
"title": [ 5, 2, "fonts/bahnschrift20" ],
|
||||
"date": [ 290, 2 ],
|
||||
"items": 7,
|
||||
"red": [ 0, 21, 296, 14 ],
|
||||
"line": [ 5, 32, 15, "t0_14b_tf", 50 ]
|
||||
},
|
||||
"2": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"date": [ 390, 10 ],
|
||||
"items": 12,
|
||||
"red": [ 0, 48, 400, 17 ],
|
||||
"line": [ 10, 61, 18, "7x14_tf", 60 ]
|
||||
}
|
||||
},
|
||||
"16": {
|
||||
"1": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"title": [ 247, 11, "glasstown_nbp_tf" ],
|
||||
"cols": [ 1, 125, 12, "glasstown_nbp_tf" ],
|
||||
"bars": [ 5, 111, 10 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
48
ESP32_AP-Flasher/data/tagtypes/00.json
Normal file
48
ESP32_AP-Flasher/data/tagtypes/00.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "ST‐GR16000 1.54\"",
|
||||
"width": 152,
|
||||
"height": 152,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 76, 10, "fonts/calibrib30" ],
|
||||
"month": [ 76, 120, "fonts/calibrib30" ],
|
||||
"day": [ 76, 42, "fonts/calibrib100" ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "fonts/calibrib120", "fonts/calibrib80", "fonts/calibrib50", "fonts/calibrib50" ],
|
||||
"xy": [ 76, 83 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 10, 145, "t0_14b_tf" ],
|
||||
"wind": [ 140, 10, "fonts/bahnschrift30" ],
|
||||
"temp": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"icon": [ 75, 26, 70, 1 ],
|
||||
"dir": [ 110, -12, 40 ],
|
||||
"umbrella": [ 125, 110, 30 ]
|
||||
},
|
||||
"10": {
|
||||
"title": [ 10, 15, "t0_14b_tf" ],
|
||||
"pos": [ 76, 20 ]
|
||||
},
|
||||
"21": [
|
||||
{ "text": [ 2, 5, "OpenEpaperLink", "bahnschrift20", 1, 0, 0 ] },
|
||||
{ "text": [ 2, 25, "Access Point", "bahnschrift20", 1, 0, 0 ] },
|
||||
{ "text": [ 3, 65, "IP address:", "glasstown_nbp_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 10, 80, "{ap_ip}", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 3, 95, "Channel:", "glasstown_nbp_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 10, 110, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 3, 125, "Tag count:", "glasstown_nbp_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 10, 140, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] }
|
||||
]
|
||||
}
|
||||
}
|
||||
73
ESP32_AP-Flasher/data/tagtypes/01.json
Normal file
73
ESP32_AP-Flasher/data/tagtypes/01.json
Normal file
@@ -0,0 +1,73 @@
|
||||
{
|
||||
"name": "ST‐GR29000 2.9\"",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
"rotatebuffer": 1,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [148, 10, "fonts/calibrib60"],
|
||||
"date": [148, 73, "fonts/calibrib50"]
|
||||
},
|
||||
"16": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"title": [ 247, 11, "glasstown_nbp_tf" ],
|
||||
"cols": [ 1, 125, 12, "glasstown_nbp_tf" ],
|
||||
"bars": [ 5, 111, 10 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": ["fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120", "fonts/calibrib100"],
|
||||
"xy": [148, 74]
|
||||
},
|
||||
"4": {
|
||||
"location": [5, 5, "fonts/bahnschrift30"],
|
||||
"wind": [280, 5, "fonts/bahnschrift30"],
|
||||
"temp": [5, 65, "fonts/bahnschrift70"],
|
||||
"icon": [285, 20, 70, 2],
|
||||
"dir": [245, -12, 40],
|
||||
"umbrella": [190, -50, 25]
|
||||
},
|
||||
"8": {
|
||||
"location": [5, 12, "t0_14b_tf"],
|
||||
"column": [5, 59],
|
||||
"day": [30, 18, "fonts/twcondensed20", 41, 108],
|
||||
"icon": [30, 55, 30],
|
||||
"wind": [18, 26],
|
||||
"line": [20, 128]
|
||||
},
|
||||
"9": {
|
||||
"title": [5, 3, "fonts/bahnschrift20"],
|
||||
"items": 8,
|
||||
"line": [5, 34, 13],
|
||||
"font": "glasstown_nbp_tf"
|
||||
},
|
||||
"10": {
|
||||
"title": [10, 5, "fonts/bahnschrift20"],
|
||||
"pos": [149, 25]
|
||||
},
|
||||
"11": {
|
||||
"title": [5, 2, "fonts/bahnschrift20"],
|
||||
"date": [290, 2],
|
||||
"items": 7,
|
||||
"red": [0, 21, 296, 14],
|
||||
"line": [5, 32, 15, "t0_14b_tf", 50]
|
||||
},
|
||||
"21": [
|
||||
{ "text": [ 5, 5, "OpenEpaperLink AP", "bahnschrift20", 1, 0, 0 ] },
|
||||
{ "text": [ 5, 50, "IP address:", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 120, 50, "{ap_ip}", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 5, 70, "Channel:", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 120, 70, "{ap_ch}", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 5, 90, "Tag count:", "t0_14b_tf", 1, 0, 0 ] },
|
||||
{ "text": [ 120, 90, "{ap_tagcount}", "t0_14b_tf", 1, 0, 0 ] }
|
||||
]
|
||||
}
|
||||
}
|
||||
60
ESP32_AP-Flasher/data/tagtypes/02.json
Normal file
60
ESP32_AP-Flasher/data/tagtypes/02.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "ST‐GR420B3N2 4.2\"",
|
||||
"width": 400,
|
||||
"height": 300,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 200, 25, "fonts/calibrib60" ],
|
||||
"month": [ 200, 225, "fonts/calibrib60" ],
|
||||
"day": [ 200, 95, "fonts/calibrib150" ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120" ],
|
||||
"xy": [ 200, 148 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 83, "fonts/calibrib60" ],
|
||||
"temp": [ 20, 170, "fonts/calibrib150" ],
|
||||
"icon": [ 385, 0, 100, 2 ],
|
||||
"dir": [ 40, 50, 80 ],
|
||||
"umbrella": [ 325, 155, 78 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 10, 10, "fonts/calibrib30" ],
|
||||
"column": [ 6, 66 ],
|
||||
"day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ],
|
||||
"rain": [ 34, 260 ],
|
||||
"icon": [ 32, 145, 30 ],
|
||||
"wind": [ 17, 90 ],
|
||||
"line": [ 50, 300 ]
|
||||
},
|
||||
"9": {
|
||||
"title": [ 10, 10, "fonts/calibrib30" ],
|
||||
"items": 12,
|
||||
"line": [ 10, 60, 20 ],
|
||||
"font": "7x14_tf"
|
||||
},
|
||||
"10": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 200, 30 ]
|
||||
},
|
||||
"11": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"date": [ 390, 10 ],
|
||||
"items": 12,
|
||||
"red": [ 0, 48, 400, 17 ],
|
||||
"line": [ 10, 61, 18, "7x14_tf", 60 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
60
ESP32_AP-Flasher/data/tagtypes/05.json
Normal file
60
ESP32_AP-Flasher/data/tagtypes/05.json
Normal file
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "ST‐GR750BN 7.4\"",
|
||||
"width": 640,
|
||||
"height": 384,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [ 200, 25, "fonts/calibrib60" ],
|
||||
"month": [ 200, 225, "fonts/calibrib60" ],
|
||||
"day": [ 200, 95, "fonts/calibrib150" ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": [ "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120" ],
|
||||
"xy": [ 200, 148 ]
|
||||
},
|
||||
"4": {
|
||||
"location": [ 20, 20, "fonts/calibrib30" ],
|
||||
"wind": [ 90, 83, "fonts/calibrib60" ],
|
||||
"temp": [ 20, 170, "fonts/calibrib150" ],
|
||||
"icon": [ 385, 0, 100, 2 ],
|
||||
"dir": [ 40, 50, 80 ],
|
||||
"umbrella": [ 325, 155, 78 ]
|
||||
},
|
||||
"8": {
|
||||
"location": [ 10, 10, "fonts/calibrib30" ],
|
||||
"column": [ 6, 66 ],
|
||||
"day": [ 33, 60, "fonts/bahnschrift20", 104, 230 ],
|
||||
"rain": [ 34, 260 ],
|
||||
"icon": [ 32, 145, 30 ],
|
||||
"wind": [ 17, 90 ],
|
||||
"line": [ 50, 300 ]
|
||||
},
|
||||
"9": {
|
||||
"title": [ 10, 10, "fonts/calibrib30" ],
|
||||
"items": 12,
|
||||
"line": [ 10, 60, 20 ],
|
||||
"font": "7x14_tf"
|
||||
},
|
||||
"10": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift20" ],
|
||||
"pos": [ 200, 30 ]
|
||||
},
|
||||
"11": {
|
||||
"title": [ 10, 10, "fonts/bahnschrift30" ],
|
||||
"date": [ 390, 10 ],
|
||||
"items": 12,
|
||||
"red": [ 0, 48, 400, 17 ],
|
||||
"line": [ 10, 61, 18, "7x14_tf", 60 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
16
ESP32_AP-Flasher/data/tagtypes/11.json
Normal file
16
ESP32_AP-Flasher/data/tagtypes/11.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "ST-GR2900L 2.9\" (UC8151)",
|
||||
"width": 296,
|
||||
"height": 128,
|
||||
"rotatebuffer": 1,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"usetemplate": 1
|
||||
}
|
||||
64
ESP32_AP-Flasher/data/tagtypes/33.json
Normal file
64
ESP32_AP-Flasher/data/tagtypes/33.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "EL029GSWRN 2.9\"",
|
||||
"width": 384,
|
||||
"height": 168,
|
||||
"rotatebuffer": 1,
|
||||
"bpp": 2,
|
||||
"colors": 3,
|
||||
"colortable": {
|
||||
"white": [255, 255, 255],
|
||||
"black": [0, 0, 0],
|
||||
"red": [255, 0, 0],
|
||||
"gray": [150, 150, 150]
|
||||
},
|
||||
"capabilities": ["button", "customlut"],
|
||||
"template": {
|
||||
"1": {
|
||||
"weekday": [148, 10, "fonts/calibrib60"],
|
||||
"date": [148, 73, "fonts/calibrib50"]
|
||||
},
|
||||
"16": {
|
||||
"location": [ 5, 5, "fonts/bahnschrift30" ],
|
||||
"title": [ 247, 11, "glasstown_nbp_tf" ],
|
||||
"cols": [ 1, 125, 12, "glasstown_nbp_tf" ],
|
||||
"bars": [ 5, 111, 10 ]
|
||||
},
|
||||
"2": {
|
||||
"fonts": ["fonts/calibrib150", "fonts/calibrib150", "fonts/calibrib120", "fonts/calibrib100"],
|
||||
"xy": [148, 74]
|
||||
},
|
||||
"4": {
|
||||
"location": [5, 5, "fonts/bahnschrift30"],
|
||||
"wind": [280, 5, "fonts/bahnschrift30"],
|
||||
"temp": [5, 65, "fonts/bahnschrift70"],
|
||||
"icon": [285, 20, 70, 2],
|
||||
"dir": [245, -12, 40],
|
||||
"umbrella": [190, -50, 25]
|
||||
},
|
||||
"8": {
|
||||
"location": [5, 12, "t0_14b_tf"],
|
||||
"column": [5, 59],
|
||||
"day": [30, 18, "fonts/twcondensed20", 41, 108],
|
||||
"icon": [30, 55, 30],
|
||||
"wind": [18, 26],
|
||||
"line": [20, 128]
|
||||
},
|
||||
"9": {
|
||||
"title": [5, 3, "fonts/bahnschrift20"],
|
||||
"items": 8,
|
||||
"line": [5, 34, 13],
|
||||
"font": "glasstown_nbp_tf"
|
||||
},
|
||||
"10": {
|
||||
"title": [10, 5, "fonts/bahnschrift20"],
|
||||
"pos": [149, 25]
|
||||
},
|
||||
"11": {
|
||||
"title": [5, 2, "fonts/bahnschrift20"],
|
||||
"date": [290, 2],
|
||||
"items": 7,
|
||||
"red": [0, 21, 296, 14],
|
||||
"line": [5, 32, 15, "t0_14b_tf", 50]
|
||||
}
|
||||
}
|
||||
}
|
||||
29
ESP32_AP-Flasher/data/tagtypes/E0.json
Normal file
29
ESP32_AP-Flasher/data/tagtypes/E0.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "TFT 320x170",
|
||||
"width": 320,
|
||||
"height": 170,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 16,
|
||||
"colors": 4,
|
||||
"colortable": {
|
||||
"white": [ 255, 255, 255 ],
|
||||
"black": [ 0, 0, 0 ],
|
||||
"red": [ 255, 0, 0 ],
|
||||
"gray": [ 150, 150, 150 ]
|
||||
},
|
||||
"capabilities": [ ],
|
||||
"contentids": [ 0, 1, 2, 3, 4, 8, 16, 9, 7, 19, 10, 11, 21 ],
|
||||
"usetemplate": 1,
|
||||
"template": {
|
||||
"21": [
|
||||
{ "box": [ 0, 0, 320, 170, 1 ] },
|
||||
{ "text": [ 5, 5, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
|
||||
{ "text": [ 5, 60, "IP address:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 60, "{ap_ip}", "bahnschrift20", 0, 0, 0, 1 ] },
|
||||
{ "text": [ 5, 85, "Channel:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 85, "{ap_ch}", "bahnschrift20", 0, 0, 0, "1" ] },
|
||||
{ "text": [ 5, 110, "Tag count:", "bahnschrift20", "#888888", 0, 0, 1 ] },
|
||||
{ "text": [ 120, 110, "{ap_tagcount}", "bahnschrift20", 0, 0, 0, "1" ] }
|
||||
]
|
||||
}
|
||||
}
|
||||
12
ESP32_AP-Flasher/data/tagtypes/F0.json
Normal file
12
ESP32_AP-Flasher/data/tagtypes/F0.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "SLT‐EM007 Segmented",
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"rotatebuffer": 0,
|
||||
"bpp": 1,
|
||||
"colors": 0,
|
||||
"colortable": {},
|
||||
"capabilities": [],
|
||||
"template": {
|
||||
}
|
||||
}
|
||||
@@ -14,8 +14,13 @@
|
||||
"/alignment.jpg",
|
||||
"/gradient.jpg",
|
||||
"/demo_image_generator.py",
|
||||
"/www/content_cards.json",
|
||||
"/www/favicon.ico",
|
||||
"/www/index.html",
|
||||
"/www/jsontemplate-demo.html",
|
||||
"/www/main.css",
|
||||
"/www/main.js",
|
||||
"/www/ota.js",
|
||||
"/www/painter.js",
|
||||
"/www/setup.html",
|
||||
"/www/setup.js",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
ESP32_AP-Flasher/data/www/variables-demo.html.gz
Normal file
BIN
ESP32_AP-Flasher/data/www/variables-demo.html.gz
Normal file
Binary file not shown.
@@ -16,7 +16,7 @@ def gzip_files(source_folder, destination_folder):
|
||||
|
||||
print(f"Gzipping: {file}")
|
||||
|
||||
with open(source_file_path, 'rb') as f_in, gzip.open(destination_file_path, 'wb') as f_out:
|
||||
with open(source_file_path, 'rb') as f_in, gzip.GzipFile(destination_file_path, 'wb', mtime=0) as f_out:
|
||||
shutil.copyfileobj(f_in, f_out)
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -24,4 +24,3 @@ if __name__ == "__main__":
|
||||
destination_folder = "data/www" # Replace with the path of the destination folder
|
||||
|
||||
gzip_files(source_folder, destination_folder)
|
||||
|
||||
|
||||
@@ -9,40 +9,40 @@
|
||||
struct contentTypes {
|
||||
uint16_t id;
|
||||
String name;
|
||||
uint16_t tagTypes;
|
||||
uint16_t tagTypes;
|
||||
void (*functionname)();
|
||||
String description;
|
||||
String optionList;
|
||||
String description;
|
||||
String optionList;
|
||||
};
|
||||
|
||||
void contentRunner();
|
||||
void drawNew(uint8_t mac[8], bool buttonPressed, tagRecord *&taginfo);
|
||||
bool updateTagImage(String &filename, 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 = 0);
|
||||
void checkVars();
|
||||
void drawNew(const uint8_t mac[8], const bool buttonPressed, 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 initSprite(TFT_eSprite &spr, int w, int h, imgParam &imageParams);
|
||||
void drawDate(String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawNumber(String &filename, int32_t count, int32_t thresholdred, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawWeather(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawForecast(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawIdentify(String &filename, 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);
|
||||
int getImgURL(String &filename, String URL, time_t fetched, imgParam &imageParams, String MAC);
|
||||
bool getRssFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
bool getCalFeed(String &filename, String URL, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawQR(String &filename, String qrcontent, String title, tagRecord *&taginfo, imgParam &imageParams);
|
||||
uint8_t drawBuienradar(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawAPinfo(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams);
|
||||
int getJsonTemplateFile(String &filename, String jsonfile, tagRecord *&taginfo, imgParam &imageParams);
|
||||
int getJsonTemplateUrl(String &filename, String URL, time_t fetched, String MAC, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawJsonStream(Stream &stream, String &filename, tagRecord *&taginfo, imgParam &imageParams);
|
||||
void drawElement(const JsonObject &element, TFT_eSprite &spr);
|
||||
uint16_t getColor(uint8_t color);
|
||||
uint16_t getColor(const String &color);
|
||||
char *formatHttpDate(time_t t);
|
||||
String urlEncode(const char *msg);
|
||||
int windSpeedToBeaufort(float windSpeed);
|
||||
String windDirectionIcon(int degrees);
|
||||
int windSpeedToBeaufort(const float windSpeed);
|
||||
String windDirectionIcon(const int degrees);
|
||||
void getLocation(JsonObject &cfgobj);
|
||||
void prepareNFCReq(uint8_t* dst, const char* url);
|
||||
void prepareLUTreq(uint8_t *dst, String input);
|
||||
void prepareConfigFile(uint8_t *dst, JsonObject config);
|
||||
void getTemplate(JsonDocument &json, const char *filePath, uint8_t id, uint8_t hwtype);
|
||||
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 getTemplate(JsonDocument &json, const uint8_t id, const uint8_t hwtype);
|
||||
void setU8G2Font(const String &title, U8g2_for_TFT_eSPI &u8f);
|
||||
void showIpAddress(String dst);
|
||||
|
||||
@@ -5,6 +5,24 @@
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
|
||||
const uint8_t PROGMEM gamma8[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
||||
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
||||
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
||||
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
|
||||
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
|
||||
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
|
||||
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
|
||||
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255};
|
||||
|
||||
void ledTask(void* parameter);
|
||||
void setBrightness(int brightness);
|
||||
void updateBrightnessFromConfig();
|
||||
|
||||
@@ -3,14 +3,21 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
extern TFT_eSPI tft;
|
||||
|
||||
struct imgParam {
|
||||
bool hasRed;
|
||||
uint8_t dataType;
|
||||
bool dither;
|
||||
bool grayLut = false;
|
||||
uint8_t bpp = 8;
|
||||
uint8_t bufferbpp = 8;
|
||||
uint8_t rotate = 0;
|
||||
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t rotatebuffer;
|
||||
uint8_t bpp;
|
||||
|
||||
char segments[12];
|
||||
uint16_t symbols;
|
||||
bool invert;
|
||||
|
||||
@@ -4,20 +4,21 @@ extern void addCRC(void* p, uint8_t len);
|
||||
extern bool checkCRC(void* p, uint8_t len);
|
||||
|
||||
extern void processBlockRequest(struct espBlockRequest* br);
|
||||
extern void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin);
|
||||
extern void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* dst);
|
||||
extern bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin);
|
||||
extern void prepareCancelPending(const uint8_t dst[8]);
|
||||
extern void prepareIdleReq(const uint8_t* dst, uint16_t nextCheckin);
|
||||
extern void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, const uint8_t* dst);
|
||||
extern bool prepareDataAvail(String* filename, uint8_t dataType, const uint8_t* dst, uint16_t nextCheckin);
|
||||
extern void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP);
|
||||
extern void processXferComplete(struct espXferComplete* xfc, bool local);
|
||||
extern void processXferTimeout(struct espXferComplete* xfc, bool local);
|
||||
extern void processDataReq(struct espAvailDataReq* adr, bool local);
|
||||
|
||||
extern bool sendTagCommand(uint8_t* dst, uint8_t cmd, bool local);
|
||||
extern bool sendAPSegmentedData(uint8_t* dst, String data, uint16_t icons, bool inverted, bool local);
|
||||
extern bool showAPSegmentedInfo(uint8_t* dst, bool local);
|
||||
extern bool sendTagCommand(const uint8_t* dst, uint8_t cmd, 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);
|
||||
bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending);
|
||||
|
||||
void refreshAllPending();
|
||||
void updateContent(uint8_t* dst);
|
||||
void updateContent(const uint8_t* dst);
|
||||
void setAPchannel();
|
||||
|
||||
@@ -8,6 +8,6 @@ void handleGetExtUrl(AsyncWebServerRequest* request);
|
||||
void handleLittleFSUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final);
|
||||
void handleUpdateOTA(AsyncWebServerRequest* request);
|
||||
void firmwareUpdateTask(void* parameter);
|
||||
void updateFirmware(const char* url, const char* expectedMd5, size_t size);
|
||||
void updateFirmware(const char* url, const char* expectedMd5, const size_t size);
|
||||
void handleRollback(AsyncWebServerRequest* request);
|
||||
void handleUpdateActions(AsyncWebServerRequest* request);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#pragma pack(push, 1)
|
||||
@@ -18,8 +19,7 @@
|
||||
|
||||
class tagRecord {
|
||||
public:
|
||||
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0),
|
||||
dataType(0), filename(""), data(nullptr), len(0) {}
|
||||
tagRecord() : mac{0}, alias(""), lastseen(0), nextupdate(0), contentMode(0), pending(false), md5{0}, md5pending{0}, expectedNextCheckin(0), modeConfigJson(""), LQI(0), RSSI(0), temperature(0), batteryMv(0), hwType(0), wakeupReason(0), capabilities(0), lastfullupdate(0), isExternal(false), pendingIdle(0), hasCustomLUT(false), rotate(0), lut(0), tagSoftwareVersion(0), currentChannel(0), dataType(0), filename(""), data(nullptr), len(0) {}
|
||||
|
||||
uint8_t mac[8];
|
||||
String alias;
|
||||
@@ -52,7 +52,7 @@ class tagRecord {
|
||||
uint8_t* data;
|
||||
uint32_t len;
|
||||
|
||||
static tagRecord* findByMAC(uint8_t mac[8]);
|
||||
static tagRecord* findByMAC(const uint8_t mac[8]);
|
||||
};
|
||||
|
||||
struct Config {
|
||||
@@ -68,21 +68,38 @@ struct Config {
|
||||
char timeZone[52];
|
||||
};
|
||||
|
||||
struct HwType {
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint8_t rotatebuffer;
|
||||
uint8_t bpp;
|
||||
};
|
||||
|
||||
struct varStruct {
|
||||
String value;
|
||||
bool changed;
|
||||
};
|
||||
|
||||
// extern SemaphoreHandle_t tagDBOwner;
|
||||
extern Config config;
|
||||
extern std::vector<tagRecord*> tagDB;
|
||||
extern std::unordered_map<int, HwType> hwtype;
|
||||
extern std::unordered_map<std::string, varStruct> varDB;
|
||||
extern DynamicJsonDocument APconfig;
|
||||
String tagDBtoJson(uint8_t mac[8] = nullptr, uint8_t startPos = 0);
|
||||
bool deleteRecord(uint8_t mac[8]);
|
||||
void fillNode(JsonObject &tag, tagRecord* &taginfo);
|
||||
String tagDBtoJson(const uint8_t mac[8] = nullptr, uint8_t startPos = 0);
|
||||
bool deleteRecord(const uint8_t mac[8]);
|
||||
void fillNode(JsonObject& tag, tagRecord*& taginfo);
|
||||
void saveDB(String filename);
|
||||
void loadDB(String filename);
|
||||
void destroyDB();
|
||||
uint8_t getTagCount();
|
||||
void mac2hex(uint8_t* mac, char* hexBuffer);
|
||||
uint32_t getTagCount();
|
||||
uint32_t getTagCount(uint32_t& timeoutcount);
|
||||
void mac2hex(const uint8_t* mac, char* hexBuffer);
|
||||
bool hex2mac(const String& hexString, uint8_t* mac);
|
||||
void clearPending(tagRecord* taginfo);
|
||||
void initAPconfig();
|
||||
void saveAPconfig();
|
||||
HwType getHwType(uint8_t id);
|
||||
bool setVarDB(const std::string& key, const String& value);
|
||||
|
||||
#pragma pack(pop)
|
||||
#pragma pack(pop)
|
||||
|
||||
107
ESP32_AP-Flasher/include/util.h
Normal file
107
ESP32_AP-Flasher/include/util.h
Normal file
@@ -0,0 +1,107 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#include "web.h"
|
||||
|
||||
namespace util {
|
||||
|
||||
/// @brief Can be used to wrap a stream and see what's going on
|
||||
class DebugStream : public Stream {
|
||||
public:
|
||||
DebugStream(Stream &stream) : _stream(stream) {}
|
||||
|
||||
int available() override {
|
||||
return _stream.available();
|
||||
}
|
||||
|
||||
int read() override {
|
||||
int data = _stream.read();
|
||||
Serial.write(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
int peek() override {
|
||||
int data = _stream.peek();
|
||||
Serial.print("Peek: ");
|
||||
Serial.println(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void flush() override {
|
||||
_stream.flush();
|
||||
Serial.println("Flush");
|
||||
}
|
||||
|
||||
size_t write(uint8_t data) override {
|
||||
Serial.write(data);
|
||||
return _stream.write(data);
|
||||
}
|
||||
|
||||
size_t write(const uint8_t *buffer, size_t size) override {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
Serial.print("Write: ");
|
||||
Serial.println(buffer[i]);
|
||||
}
|
||||
return _stream.write(buffer, size);
|
||||
}
|
||||
|
||||
private:
|
||||
Stream &_stream;
|
||||
};
|
||||
|
||||
/// @brief Prints free heap, allocatbale heap and free stack
|
||||
static void printHeap() {
|
||||
const uint32_t freeStack = uxTaskGetStackHighWaterMark(NULL);
|
||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||
}
|
||||
|
||||
/// @brief Prints the maximum continuous heap space
|
||||
static void printLargestFreeBlock() {
|
||||
Serial.println("Maximum Continuous Heap Space: " + String(heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)));
|
||||
}
|
||||
|
||||
/// @brief Do a GET request to the given url and fill the given json with the response
|
||||
/// @param url Request URL
|
||||
/// @param json Json document to fill
|
||||
/// @param timeout Request timeout
|
||||
/// @param redirects Redirects handling
|
||||
/// @return True on success, false on error (httpCode != 200 || deserialization error)
|
||||
static bool httpGetJson(String &url, JsonDocument &json, const uint16_t timeout, JsonDocument *filter = nullptr) //, const followRedirects_t redirects = followRedirects_t::HTTPC_DISABLE_FOLLOW_REDIRECTS)
|
||||
{
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
http.setTimeout(timeout);
|
||||
// http.setFollowRedirects(redirects);
|
||||
const int httpCode = http.GET();
|
||||
if (httpCode != 200) {
|
||||
http.end();
|
||||
wsErr("http " + httpCode);
|
||||
return false;
|
||||
}
|
||||
|
||||
DeserializationError error;
|
||||
if (filter) {
|
||||
error = deserializeJson(json, http.getString(), DeserializationOption::Filter(*filter));
|
||||
} else {
|
||||
error = deserializeJson(json, http.getString());
|
||||
}
|
||||
http.end();
|
||||
if (error) {
|
||||
Serial.println(error.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// @brief Check if the given string is empty or contains "null"
|
||||
///
|
||||
/// @param str String to check
|
||||
/// @return True if empty or null, false if not
|
||||
static inline bool isEmptyOrNull(const String &str) {
|
||||
return str.isEmpty() || str == "null";
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
@@ -9,9 +9,9 @@ void doJsonUpload(AsyncWebServerRequest *request);
|
||||
extern void networkProcess(void *parameter);
|
||||
void wsLog(String text);
|
||||
void wsErr(String text);
|
||||
void wsSendTaginfo(uint8_t *mac, uint8_t syncMode);
|
||||
void wsSendTaginfo(const uint8_t *mac, uint8_t syncMode);
|
||||
void wsSendSysteminfo();
|
||||
void wsSendAPitem(struct APlist* apitem);
|
||||
void wsSendAPitem(struct APlist *apitem);
|
||||
void wsSerial(String text);
|
||||
uint8_t wsClientCount();
|
||||
|
||||
|
||||
@@ -34,73 +34,6 @@ build_flags =
|
||||
-D ILI9341_DRIVER
|
||||
-D SMOOTH_FONT
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an SONOFF ZB Bridge-P
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:Sonoff_zb_bridge_P_AP]
|
||||
board = esp32dev
|
||||
board_build.partitions = default.csv
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
|
||||
-D POWER_NO_SOFT_POWER
|
||||
; -DBOARD_HAS_PSRAM
|
||||
; -mfix-esp32-psram-cache-issue
|
||||
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=-1
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=19
|
||||
-D FLASHER_AP_RXD=23
|
||||
-D FLASHER_LED=2
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the UniRfInterface PCB with EBYTE E79 CC1352P Module
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OpenEPaperLink_CC1352P]
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board=lolin_s2_mini
|
||||
board_build.partitions = default.csv
|
||||
build_unflags =
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D OPENEPAPERLINK_MINI_AP_PCB
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=21
|
||||
-D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=16
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_LED=2
|
||||
-D FLASHER_RGB_LED=-1
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the Mini_AP
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
@@ -317,3 +250,162 @@ build_flags =
|
||||
-D SMOOTH_FONT
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:ESP32_S3_16_8_YELLOW_AP]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = large_spiffs_16MB.csv
|
||||
build_unflags =
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
-D ILI9341_DRIVER
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D YELLOW_IPS_AP
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=47
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=18
|
||||
-D FLASHER_LED=14
|
||||
-D ST7789_DRIVER
|
||||
-D TFT_WIDTH=170
|
||||
-D TFT_HEIGHT=320
|
||||
-D TFT_MISO=-1
|
||||
-D TFT_MOSI=13
|
||||
-D TFT_SCLK=12
|
||||
-D TFT_CS=10
|
||||
-D TFT_DC=11
|
||||
-D TFT_RST=1
|
||||
-D TFT_RGB_ORDER=TFT_BGR
|
||||
-D USE_HSPI_PORT
|
||||
-D LOAD_FONT2
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.flash_mode=qio
|
||||
board_build.arduino.memory_type = qio_opi
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 16MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects an SONOFF ZB Bridge-P
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:Sonoff_zb_bridge_P_AP]
|
||||
board = esp32dev
|
||||
board_build.partitions = default.csv
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
|
||||
-D POWER_NO_SOFT_POWER
|
||||
; -DBOARD_HAS_PSRAM
|
||||
; -mfix-esp32-psram-cache-issue
|
||||
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=-1
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=19
|
||||
-D FLASHER_AP_RXD=23
|
||||
-D FLASHER_LED=2
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration expects the UniRfInterface PCB with EBYTE E79 CC1352P Module
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OpenEPaperLink_CC1352P]
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board=lolin_s2_mini
|
||||
board_build.partitions = default.csv
|
||||
build_unflags =
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D OPENEPAPERLINK_MINI_AP_PCB
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=21
|
||||
-D FLASHER_AP_POWER={-1} ;this board has no soft power control
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=16
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_LED=2
|
||||
-D FLASHER_RGB_LED=-1
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 4194304
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 4MB
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
; !!! this configuration is work in progress, do not use for now
|
||||
;
|
||||
; ----------------------------------------------------------------------------------------
|
||||
[env:OutdoorAP]
|
||||
board = esp32-s3-devkitc-1
|
||||
board_build.partitions = 32MB_partition table.csv
|
||||
build_unflags =
|
||||
-D ARDUINO_USB_MODE=1
|
||||
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
|
||||
build_flags =
|
||||
${env.build_flags}
|
||||
-D OutdoorAP
|
||||
-D HAS_RGB_LED
|
||||
-D CORE_DEBUG_LEVEL=0
|
||||
-D ARDUINO_USB_MODE=0
|
||||
-D CONFIG_ESP32S3_SPIRAM_SUPPORT=1
|
||||
-D CONFIG_SPIRAM_USE_MALLOC=1
|
||||
-D POWER_NO_SOFT_POWER
|
||||
-D BOARD_HAS_PSRAM
|
||||
-D CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC=y
|
||||
-D FLASHER_AP_SS=-1
|
||||
-D FLASHER_AP_CLK=-1
|
||||
-D FLASHER_AP_MOSI=-1
|
||||
-D FLASHER_AP_MISO=-1
|
||||
-D FLASHER_AP_RESET=47
|
||||
-D FLASHER_AP_POWER={-1}
|
||||
-D FLASHER_AP_TEST=-1
|
||||
-D FLASHER_AP_TXD=17
|
||||
-D FLASHER_AP_RXD=18
|
||||
-D FLASHER_LED=21
|
||||
-D FLASHER_RGB_LED=38
|
||||
build_src_filter =
|
||||
+<*>-<usbflasher.cpp>-<swd.cpp>
|
||||
board_build.flash_mode=opi
|
||||
board_build.arduino.memory_type = opi_opi
|
||||
board_build.psram_type=qspi_opi
|
||||
board_upload.maximum_size = 16777216
|
||||
board_upload.maximum_ram_size = 327680
|
||||
board_upload.flash_size = 32MB
|
||||
#upload_flags = --no-stub
|
||||
|
||||
@@ -129,6 +129,13 @@ void SPIFFSEditor::handleUpload(AsyncWebServerRequest *request, const String &fi
|
||||
if (filename.c_str()[0] != '/') {
|
||||
request->_tempFile = _fs.open("/" + filename, "w");
|
||||
} else {
|
||||
int lastSlash = filename.lastIndexOf('/');
|
||||
if (lastSlash != -1) {
|
||||
String folderPath = filename.substring(0, lastSlash);
|
||||
if (!_fs.exists(folderPath)) {
|
||||
_fs.mkdir(folderPath);
|
||||
}
|
||||
}
|
||||
request->_tempFile = _fs.open(filename, "w");
|
||||
}
|
||||
_startTime = millis();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
96
ESP32_AP-Flasher/src/ips_display.cpp
Normal file
96
ESP32_AP-Flasher/src/ips_display.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifdef YELLOW_IPS_AP
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#include <TFT_eSPI.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
#include "commstructs.h"
|
||||
#include "newproto.h"
|
||||
#include "storage.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
TFT_eSPI tft2 = TFT_eSPI();
|
||||
bool first_run = 0;
|
||||
time_t last_update = 0;
|
||||
time_t last_checkin = 0;
|
||||
int32_t tftid = -1;
|
||||
|
||||
int32_t findId(uint8_t mac[8]) {
|
||||
for (uint32_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tag = nullptr;
|
||||
tag = tagDB.at(c);
|
||||
if (memcmp(tag->mac, mac, 8) == 0) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void sendAvail(uint8_t wakeupReason) {
|
||||
struct espAvailDataReq eadr = {0};
|
||||
uint8_t mac[6];
|
||||
WiFi.macAddress(mac);
|
||||
memcpy(&eadr.src, mac, 6);
|
||||
eadr.adr.lastPacketRSSI = WiFi.RSSI();
|
||||
eadr.adr.currentChannel = WiFi.channel();
|
||||
eadr.adr.hwType = 0xE0;
|
||||
eadr.adr.wakeupReason = wakeupReason;
|
||||
eadr.adr.capabilities = 0;
|
||||
eadr.adr.tagSoftwareVersion = 0;
|
||||
eadr.adr.customMode = 0;
|
||||
processDataReq(&eadr, true);
|
||||
if (wakeupReason) tftid = findId(eadr.src);
|
||||
}
|
||||
|
||||
void yellow_ap_display_init(void) {
|
||||
tft2.init();
|
||||
tft2.setRotation(3);
|
||||
|
||||
tft2.fillScreen(TFT_BLACK);
|
||||
tft2.setCursor(0, 0, 2);
|
||||
tft2.setTextColor(TFT_WHITE);
|
||||
tft2.println(" Init\n");
|
||||
}
|
||||
|
||||
void yellow_ap_display_loop(void) {
|
||||
if (millis() - last_checkin >= 60000) {
|
||||
sendAvail(0);
|
||||
last_checkin = millis();
|
||||
}
|
||||
if (millis() - last_update >= 1000) {
|
||||
if (first_run == 0) {
|
||||
sendAvail(0xFC);
|
||||
first_run = 1;
|
||||
}
|
||||
|
||||
// if ((uint32_t)WiFi.localIP() == (uint32_t)0) {}
|
||||
|
||||
tagRecord* tag = nullptr;
|
||||
tag = tagDB.at(tftid);
|
||||
if (tag->pending) {
|
||||
String filename = tag->filename;
|
||||
fs::File file = contentFS->open(filename);
|
||||
if (!file) {
|
||||
Serial.print("No current file. Canceling request\n");
|
||||
prepareCancelPending(tag->mac);
|
||||
return;
|
||||
}
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft2);
|
||||
if (tag->len == tft2.width() * tft2.height() * 2) spr.setColorDepth(16);
|
||||
if (tag->len == tft2.width() * tft2.height()) spr.setColorDepth(8);
|
||||
spr.createSprite(tft2.width(), tft2.height());
|
||||
void* spriteData = spr.getPointer();
|
||||
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
|
||||
file.close();
|
||||
spr.pushSprite(0,0);
|
||||
|
||||
struct espXferComplete xfc = {0};
|
||||
memcpy(xfc.src, tag->mac, 8);
|
||||
processXferComplete(&xfc, true);
|
||||
}
|
||||
last_update = millis();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <FastLED.h>
|
||||
#endif
|
||||
|
||||
#include "leds.h"
|
||||
#include "settings.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
@@ -32,24 +33,6 @@ struct ledInstruction {
|
||||
bool reQueue = false;
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM gamma8[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
||||
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
||||
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
||||
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
||||
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
|
||||
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
|
||||
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
|
||||
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
|
||||
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255};
|
||||
|
||||
#ifdef HAS_RGB_LED
|
||||
|
||||
void addToRGBQueue(struct ledInstructionRGB* rgb, bool requeue) {
|
||||
@@ -197,7 +180,11 @@ void addFadeMono(uint8_t value) {
|
||||
}
|
||||
|
||||
void showMono(uint8_t brightness) {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
ledcWrite(7, gamma8[brightness]);
|
||||
#else
|
||||
ledcWrite(7, 255 - gamma8[brightness]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void quickBlink(uint8_t repeat) {
|
||||
@@ -335,7 +322,7 @@ void ledTask(void* parameter) {
|
||||
showMono(monoled->value);
|
||||
}
|
||||
} else {
|
||||
//monoIdleStep();
|
||||
// monoIdleStep();
|
||||
}
|
||||
} else {
|
||||
if (monoled->fadeTime) {
|
||||
|
||||
@@ -3,12 +3,11 @@
|
||||
#include <WiFi.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "storage.h"
|
||||
#include "contentmanager.h"
|
||||
#include "flasher.h"
|
||||
#include "makeimage.h"
|
||||
#include "serialap.h"
|
||||
#include "settings.h"
|
||||
#include "storage.h"
|
||||
#include "system.h"
|
||||
#include "tag_db.h"
|
||||
|
||||
@@ -19,6 +18,7 @@
|
||||
#include "language.h"
|
||||
#include "leds.h"
|
||||
#include "udp.h"
|
||||
#include "util.h"
|
||||
#include "web.h"
|
||||
|
||||
void pinTest();
|
||||
@@ -35,12 +35,15 @@ void delayedStart(void* parameter) {
|
||||
|
||||
void timeTask(void* parameter) {
|
||||
wsSendSysteminfo();
|
||||
Serial.printf("Free heap: %.2f kB\n", ESP.getFreeHeap() / 1024.0f);
|
||||
util::printHeap();
|
||||
while (1) {
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE || config.runStatus != RUNSTATUS_RUN) wsSendSysteminfo();
|
||||
if (now % 5 == 0 || apInfo.state != AP_STATE_ONLINE || config.runStatus != RUNSTATUS_RUN) {
|
||||
wsSendSysteminfo();
|
||||
checkVars();
|
||||
}
|
||||
if (now % 300 == 6 && config.runStatus != RUNSTATUS_STOP) saveDB("/current/tagDB.json");
|
||||
if (apInfo.state == AP_STATE_ONLINE) contentRunner();
|
||||
|
||||
@@ -51,6 +54,10 @@ void timeTask(void* parameter) {
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.print(">\n");
|
||||
#ifdef YELLOW_IPS_AP
|
||||
extern void yellow_ap_display_init(void);
|
||||
yellow_ap_display_init();
|
||||
#endif
|
||||
|
||||
xTaskCreate(ledTask, "ledhandler", 2000, NULL, 2, NULL);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
@@ -154,8 +161,13 @@ void loop() {
|
||||
while (1) {
|
||||
// pinTest();
|
||||
while (1) {
|
||||
#ifdef YELLOW_IPS_AP
|
||||
extern void yellow_ap_display_loop(void);
|
||||
yellow_ap_display_loop();
|
||||
#else
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
// pinTest();
|
||||
#endif
|
||||
}
|
||||
#ifdef OPENEPAPERLINK_PCB
|
||||
if (extTagConnected()) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#include "storage.h"
|
||||
#include <TFT_eSPI.h>
|
||||
#include <TJpg_Decoder.h>
|
||||
#include <makeimage.h>
|
||||
#include <web.h>
|
||||
|
||||
#include "leds.h"
|
||||
#include "storage.h"
|
||||
#include "util.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite spr = TFT_eSprite(&tft);
|
||||
|
||||
@@ -24,7 +27,7 @@ void jpg2buffer(String filein, String fileout, imgParam &imageParams) {
|
||||
filein = "/" + filein;
|
||||
}
|
||||
TJpgDec.getFsJpgSize(&w, &h, filein, *contentFS);
|
||||
if (w==0 && h==0) {
|
||||
if (w == 0 && h == 0) {
|
||||
wsErr("invalid jpg");
|
||||
return;
|
||||
}
|
||||
@@ -38,10 +41,10 @@ void jpg2buffer(String filein, String fileout, imgParam &imageParams) {
|
||||
spr.createSprite(w, h);
|
||||
if (spr.getPointer() == nullptr) {
|
||||
wsErr("low on memory. Fallback to 1bpp");
|
||||
Serial.println("Maximum Continuous Heap Space: " + String(heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)));
|
||||
util::printLargestFreeBlock();
|
||||
spr.setColorDepth(1);
|
||||
spr.setBitmapColor(TFT_WHITE, TFT_BLACK);
|
||||
imageParams.bpp = 1;
|
||||
imageParams.bufferbpp = 1;
|
||||
spr.createSprite(w, h);
|
||||
}
|
||||
if (spr.getPointer() == nullptr) {
|
||||
@@ -63,38 +66,31 @@ struct Color {
|
||||
};
|
||||
|
||||
struct Error {
|
||||
float r;
|
||||
float g;
|
||||
float b;
|
||||
int32_t r;
|
||||
int32_t g;
|
||||
int32_t b;
|
||||
};
|
||||
|
||||
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 + 1 * b_diff * b_diff;
|
||||
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);
|
||||
int32_t r_diff = gamma8[c1.r] + e1.r - gamma8[c2.r];
|
||||
int32_t g_diff = gamma8[c1.g] + e1.g - gamma8[c2.g];
|
||||
int32_t b_diff = gamma8[c1.b] + e1.b - gamma8[c2.b];
|
||||
return 22 * r_diff * r_diff + 50 * g_diff * g_diff + 20 * b_diff * b_diff;
|
||||
}
|
||||
|
||||
uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size, bool is_red) {
|
||||
|
||||
bool dither = true;
|
||||
void spr2color(TFT_eSprite &spr, imgParam &imageParams, uint8_t *buffer, size_t buffer_size, bool is_red) {
|
||||
uint8_t rotate = imageParams.rotate;
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
|
||||
if (bufw > bufh && bufw!=400 && bufh!=300 && bufw!=800 && bufh!=480 && bufw!=640 && bufh!=384) {
|
||||
if (imageParams.rotatebuffer) {
|
||||
rotate = (rotate + 3) % 4;
|
||||
bufw = spr.height();
|
||||
bufh = spr.width();
|
||||
}
|
||||
|
||||
*buffer_size = (bufw * bufh) / 8;
|
||||
uint8_t *buffer = (uint8_t*) malloc(*buffer_size);
|
||||
if (!buffer) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
Serial.println("Maximum Continuous Heap Space: " + String(heap_caps_get_largest_free_block(MALLOC_CAP_DEFAULT)));
|
||||
return nullptr;
|
||||
}
|
||||
memset(buffer, 0, *buffer_size);
|
||||
memset(buffer, 0, buffer_size);
|
||||
|
||||
std::vector<Color> palette = {
|
||||
{255, 255, 255}, // White
|
||||
@@ -107,7 +103,7 @@ uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size,
|
||||
Serial.println("rendering with gray");
|
||||
}
|
||||
int num_colors = palette.size();
|
||||
if (imageParams.bpp == 1) num_colors = 2;
|
||||
if (imageParams.bufferbpp == 1) num_colors = 2;
|
||||
Color color;
|
||||
Error *error_bufferold = new Error[bufw + 4];
|
||||
Error *error_buffernew = new Error[bufw + 4];
|
||||
@@ -134,6 +130,7 @@ uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size,
|
||||
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;
|
||||
@@ -147,12 +144,12 @@ uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size,
|
||||
// this looks a bit ugly, but it's performing better than shorter notations
|
||||
switch (best_color_index) {
|
||||
case 1:
|
||||
if(!is_red)
|
||||
if (!is_red)
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 2:
|
||||
imageParams.hasRed = true;
|
||||
if(is_red)
|
||||
if (is_red)
|
||||
buffer[byteIndex] |= (1 << bitIndex);
|
||||
break;
|
||||
case 3:
|
||||
@@ -163,39 +160,39 @@ uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size,
|
||||
|
||||
if (imageParams.dither) {
|
||||
Error error = {
|
||||
static_cast<float>(color.r) + error_bufferold[x].r - static_cast<float>(palette[best_color_index].r),
|
||||
static_cast<float>(color.g) + error_bufferold[x].g - static_cast<float>(palette[best_color_index].g),
|
||||
static_cast<float>(color.b) + error_bufferold[x].b - static_cast<float>(palette[best_color_index].b) };
|
||||
color.r + error_bufferold[x].r - palette[best_color_index].r,
|
||||
color.g + error_bufferold[x].g - palette[best_color_index].g,
|
||||
color.b + error_bufferold[x].b - palette[best_color_index].b};
|
||||
|
||||
// Burkes Dithering
|
||||
error_buffernew[x].r += error.r / 4.0f;
|
||||
error_buffernew[x].g += error.g / 4.0f;
|
||||
error_buffernew[x].b += error.b / 4.0f;
|
||||
error_buffernew[x].r += error.r >> 2;
|
||||
error_buffernew[x].g += error.g >> 2;
|
||||
error_buffernew[x].b += error.b >> 2;
|
||||
if (x > 0) {
|
||||
error_buffernew[x - 1].r += error.r / 8.0f;
|
||||
error_buffernew[x - 1].g += error.g / 8.0f;
|
||||
error_buffernew[x - 1].b += error.b / 8.0f;
|
||||
error_buffernew[x - 1].r += error.r >> 3;
|
||||
error_buffernew[x - 1].g += error.g >> 3;
|
||||
error_buffernew[x - 1].b += error.b >> 3;
|
||||
}
|
||||
if (x > 1) {
|
||||
error_buffernew[x - 2].r += error.r / 16.0f;
|
||||
error_buffernew[x - 2].g += error.g / 16.0f;
|
||||
error_buffernew[x - 2].b += error.b / 16.0f;
|
||||
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 + 1].r += error.r / 8.0f;
|
||||
error_buffernew[x + 1].g += error.g / 8.0f;
|
||||
error_buffernew[x + 1].b += error.b / 8.0f;
|
||||
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 / 4.0f;
|
||||
error_bufferold[x + 1].g += error.g / 4.0f;
|
||||
error_bufferold[x + 1].b += error.b / 4.0f;
|
||||
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 + 2].r += error.r / 16.0f;
|
||||
error_buffernew[x + 2].g += error.g / 16.0f;
|
||||
error_buffernew[x + 2].b += error.b / 16.0f;
|
||||
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 + 2].r += error.r / 8.0f;
|
||||
error_bufferold[x + 2].g += error.g / 8.0f;
|
||||
error_bufferold[x + 2].b += error.b / 8.0f;
|
||||
error_bufferold[x + 2].r += error.r >> 3;
|
||||
error_bufferold[x + 2].g += error.g >> 3;
|
||||
error_bufferold[x + 2].b += error.b >> 3;
|
||||
}
|
||||
}
|
||||
memcpy(error_bufferold, error_buffernew, bufw * sizeof(Error));
|
||||
@@ -204,30 +201,53 @@ uint8_t *spr2color(TFT_eSprite &spr, imgParam &imageParams, size_t *buffer_size,
|
||||
delete[] error_buffernew;
|
||||
delete[] error_bufferold;
|
||||
|
||||
return buffer;
|
||||
return;
|
||||
}
|
||||
|
||||
void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
|
||||
long t = millis();
|
||||
Storage.begin();
|
||||
|
||||
fs::File f_out = contentFS->open(fileout, "w");
|
||||
size_t bufferSize;
|
||||
|
||||
uint8_t *blackBuffer = (uint8_t*) spr2color(spr, imageParams, &bufferSize, false);
|
||||
if(!blackBuffer)
|
||||
#ifdef YELLOW_IPS_AP
|
||||
if (fileout == "direct") {
|
||||
tft.setRotation(3);
|
||||
spr.pushSprite(0, 0);
|
||||
return;
|
||||
f_out.write(blackBuffer, bufferSize);
|
||||
free(blackBuffer);
|
||||
if (imageParams.hasRed) {
|
||||
uint8_t *redBuffer = (uint8_t*) spr2color(spr, imageParams, &bufferSize, true);
|
||||
if(!redBuffer) {
|
||||
imageParams.hasRed = false;
|
||||
return;
|
||||
}
|
||||
f_out.write(redBuffer, bufferSize);
|
||||
free(redBuffer);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
fs::File f_out = contentFS->open(fileout, "w");
|
||||
|
||||
switch (imageParams.bpp) {
|
||||
case 1:
|
||||
case 2: {
|
||||
long bufw = spr.width(), bufh = spr.height();
|
||||
size_t buffer_size = (bufw * bufh) / 8;
|
||||
#ifdef BOARD_HAS_PSRAM
|
||||
uint8_t *buffer = (uint8_t *)ps_malloc(buffer_size);
|
||||
#else
|
||||
uint8_t *buffer = (uint8_t *)malloc(buffer_size);
|
||||
#endif
|
||||
if (!buffer) {
|
||||
Serial.println("Failed to allocate buffer");
|
||||
util::printLargestFreeBlock();
|
||||
return;
|
||||
}
|
||||
spr2color(spr, imageParams, buffer, buffer_size, false);
|
||||
f_out.write(buffer, buffer_size);
|
||||
|
||||
if (imageParams.hasRed && imageParams.bpp > 1) {
|
||||
spr2color(spr, imageParams, buffer, buffer_size, true);
|
||||
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);
|
||||
} break;
|
||||
}
|
||||
|
||||
f_out.close();
|
||||
Serial.println("finished writing buffer " + String(millis() - t) + "ms");
|
||||
|
||||
@@ -3,15 +3,13 @@
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "storage.h"
|
||||
#include <MD5Builder.h>
|
||||
#include <makeimage.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "storage.h"
|
||||
#include "commstructs.h"
|
||||
#include "serialap.h"
|
||||
#include "settings.h"
|
||||
#include "storage.h"
|
||||
#include "system.h"
|
||||
#include "tag_db.h"
|
||||
#include "udp.h"
|
||||
@@ -48,7 +46,7 @@ uint8_t* getDataForFile(fs::File* file) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void prepareCancelPending(uint8_t dst[8]) {
|
||||
void prepareCancelPending(const uint8_t dst[8]) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
sendCancelPending(&pending);
|
||||
@@ -64,7 +62,7 @@ void prepareCancelPending(uint8_t dst[8]) {
|
||||
wsSendTaginfo(dst, SYNC_TAGSTATUS);
|
||||
}
|
||||
|
||||
void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
|
||||
void prepareIdleReq(const uint8_t* dst, uint16_t nextCheckin) {
|
||||
if (nextCheckin > config.maxsleep) nextCheckin = config.maxsleep;
|
||||
if (nextCheckin > 0) {
|
||||
struct pendingData pending = {0};
|
||||
@@ -80,9 +78,8 @@ void prepareIdleReq(uint8_t* dst, uint16_t nextCheckin) {
|
||||
}
|
||||
}
|
||||
|
||||
void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* dst) {
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(dst);
|
||||
void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, const uint8_t* dst) {
|
||||
tagRecord* taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo == nullptr) {
|
||||
wsErr("Tag not found, this shouldn't happen.");
|
||||
return;
|
||||
@@ -118,10 +115,18 @@ void prepareDataAvail(uint8_t* data, uint16_t len, uint8_t dataType, uint8_t* ds
|
||||
wsSendTaginfo(dst, SYNC_TAGSTATUS);
|
||||
}
|
||||
|
||||
bool prepareDataAvail(String* filename, uint8_t dataType, uint8_t* dst, uint16_t nextCheckin) {
|
||||
bool prepareDataAvail(String* filename, uint8_t dataType, const uint8_t* dst, uint16_t nextCheckin) {
|
||||
if (nextCheckin > config.maxsleep) nextCheckin = config.maxsleep;
|
||||
if (wsClientCount() && config.stopsleep == 1) nextCheckin=0;
|
||||
|
||||
if (wsClientCount() && config.stopsleep == 1) nextCheckin = 0;
|
||||
#ifdef YELLOW_IPS_AP
|
||||
if (*filename == "direct") {
|
||||
char dst_path[64];
|
||||
sprintf(dst_path, "/current/%02X%02X%02X%02X%02X%02X%02X%02X.raw\0", dst[7], dst[6], dst[5], dst[4], dst[3], dst[2], dst[1], dst[0]);
|
||||
contentFS->remove(dst_path);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo == nullptr) {
|
||||
@@ -305,7 +310,7 @@ void prepareExternalDataAvail(struct pendingData* pending, IPAddress remoteIP) {
|
||||
taginfo->dataType = pending->availdatainfo.dataType;
|
||||
taginfo->pending = true;
|
||||
taginfo->len = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
http.end();
|
||||
break;
|
||||
@@ -482,9 +487,12 @@ void processDataReq(struct espAvailDataReq* eadr, bool local) {
|
||||
|
||||
if (local) {
|
||||
const char* reason = "";
|
||||
if (eadr->adr.wakeupReason == WAKEUP_REASON_FIRSTBOOT) reason = "Booting";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_NETWORK_SCAN) reason = "Network scan";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_WDT_RESET) reason = "Watchdog reset";
|
||||
if (eadr->adr.wakeupReason == WAKEUP_REASON_FIRSTBOOT)
|
||||
reason = "Booting";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_NETWORK_SCAN)
|
||||
reason = "Network scan";
|
||||
else if (eadr->adr.wakeupReason == WAKEUP_REASON_WDT_RESET)
|
||||
reason = "Watchdog reset";
|
||||
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X %s", eadr->src[7], eadr->src[6], eadr->src[5], eadr->src[4], eadr->src[3], eadr->src[2], eadr->src[1], eadr->src[0], reason);
|
||||
logLine(buffer);
|
||||
}
|
||||
@@ -507,11 +515,11 @@ void processDataReq(struct espAvailDataReq* eadr, bool local) {
|
||||
}
|
||||
if (local) {
|
||||
sprintf(buffer, "<ADR %02X%02X%02X%02X%02X%02X%02X%02X\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);
|
||||
} else {
|
||||
sprintf(buffer, "<REMOTE ADR %02X%02X%02X%02X%02X%02X%02X%02X\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]);
|
||||
// sprintf(buffer, "<REMOTE ADR %02X%02X%02X%02X%02X%02X%02X%02X\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);
|
||||
wsSendTaginfo(eadr->src, SYNC_TAGSTATUS);
|
||||
if (local) {
|
||||
udpsync.netProcessDataReq(eadr);
|
||||
@@ -532,7 +540,7 @@ void refreshAllPending() {
|
||||
}
|
||||
};
|
||||
|
||||
void updateContent(uint8_t* dst) {
|
||||
void updateContent(const uint8_t* dst) {
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(dst);
|
||||
if (taginfo != nullptr) {
|
||||
@@ -557,7 +565,7 @@ void setAPchannel() {
|
||||
}
|
||||
}
|
||||
|
||||
bool sendAPSegmentedData(uint8_t* dst, String data, uint16_t icons, bool inverted, bool local) {
|
||||
bool sendAPSegmentedData(const uint8_t* dst, String data, uint16_t icons, bool inverted, bool local) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_UK_SEGMENTED;
|
||||
@@ -577,7 +585,7 @@ bool sendAPSegmentedData(uint8_t* dst, String data, uint16_t icons, bool inverte
|
||||
}
|
||||
}
|
||||
|
||||
bool showAPSegmentedInfo(uint8_t* dst, bool local) {
|
||||
bool showAPSegmentedInfo(const uint8_t* dst, bool local) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_UK_SEGMENTED;
|
||||
@@ -597,7 +605,7 @@ bool showAPSegmentedInfo(uint8_t* dst, bool local) {
|
||||
}
|
||||
}
|
||||
|
||||
bool sendTagCommand(uint8_t* dst, uint8_t cmd, bool local) {
|
||||
bool sendTagCommand(const uint8_t* dst, uint8_t cmd, bool local) {
|
||||
struct pendingData pending = {0};
|
||||
memcpy(pending.targetMac, dst, 8);
|
||||
pending.availdatainfo.dataType = DATATYPE_COMMAND_DATA;
|
||||
@@ -673,7 +681,6 @@ bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) {
|
||||
JsonObject cfgobj = doc.as<JsonObject>();
|
||||
uint8_t mac[8] = {0};
|
||||
if (hex2mac(cfgobj["mac"], mac) && memcmp(mac, taginfo->mac, sizeof(mac)) == 0) {
|
||||
|
||||
if (taginfo->data == nullptr) {
|
||||
fs::File file = contentFS->open(taginfo->filename);
|
||||
if (!file) {
|
||||
@@ -687,7 +694,7 @@ bool checkMirror(struct tagRecord* taginfo, struct pendingData* pending) {
|
||||
taginfo2->expectedNextCheckin = taginfo->expectedNextCheckin;
|
||||
taginfo2->filename = taginfo->filename;
|
||||
taginfo2->len = taginfo->len;
|
||||
taginfo2->data = taginfo->data; // copy buffer pointer
|
||||
taginfo2->data = taginfo->data; // copy buffer pointer
|
||||
taginfo2->dataType = taginfo->dataType;
|
||||
taginfo2->pending = true;
|
||||
taginfo2->nextupdate = 3216153600;
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <FS.h>
|
||||
#include <HTTPClient.h>
|
||||
#include "storage.h"
|
||||
#include <MD5Builder.h>
|
||||
#include <Update.h>
|
||||
|
||||
#include "storage.h"
|
||||
#include "tag_db.h"
|
||||
#include "util.h"
|
||||
#include "web.h"
|
||||
|
||||
#ifndef BUILD_ENV_NAME
|
||||
@@ -38,7 +39,7 @@ void handleSysinfoRequest(AsyncWebServerRequest* request) {
|
||||
doc["flashsize"] = ESP.getFlashChipSize();
|
||||
doc["rollback"] = Update.canRollBack();
|
||||
|
||||
size_t bufferSize = measureJson(doc) + 1;
|
||||
const size_t bufferSize = measureJson(doc) + 1;
|
||||
AsyncResponseStream* response = request->beginResponseStream("application/json", bufferSize);
|
||||
serializeJson(doc, *response);
|
||||
request->send(response);
|
||||
@@ -50,7 +51,7 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
return;
|
||||
}
|
||||
|
||||
String filePath = request->getParam("path")->value();
|
||||
const String filePath = request->getParam("path")->value();
|
||||
File file = contentFS->open(filePath, "r");
|
||||
if (!file) {
|
||||
StaticJsonDocument<64> doc;
|
||||
@@ -62,13 +63,13 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t fileSize = file.size();
|
||||
const size_t fileSize = file.size();
|
||||
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
md5.addStream(file, fileSize);
|
||||
md5.calculate();
|
||||
String md5Hash = md5.toString();
|
||||
const String md5Hash = md5.toString();
|
||||
|
||||
file.close();
|
||||
|
||||
@@ -77,22 +78,21 @@ void handleCheckFile(AsyncWebServerRequest* request) {
|
||||
doc["md5"] = md5Hash;
|
||||
String jsonResponse;
|
||||
serializeJson(doc, jsonResponse);
|
||||
|
||||
request->send(200, "application/json", jsonResponse);
|
||||
}
|
||||
|
||||
void handleGetExtUrl(AsyncWebServerRequest* request) {
|
||||
if (request->hasParam("url")) {
|
||||
String url = request->getParam("url")->value();
|
||||
const String url = request->getParam("url")->value();
|
||||
HTTPClient http;
|
||||
http.begin(url);
|
||||
http.setConnectTimeout(5000);
|
||||
http.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||
int httpResponseCode = http.GET();
|
||||
const int httpResponseCode = http.GET();
|
||||
if (httpResponseCode > 0) {
|
||||
Serial.println(httpResponseCode);
|
||||
String contentType = http.header("Content-Type");
|
||||
size_t contentLength = http.getSize();
|
||||
const String contentType = http.header("Content-Type");
|
||||
const size_t contentLength = http.getSize();
|
||||
if (contentLength > 0) {
|
||||
String content = http.getString();
|
||||
AsyncWebServerResponse* response = request->beginResponse(200, contentType, content);
|
||||
@@ -169,7 +169,7 @@ void firmwareUpdateTask(void* parameter) {
|
||||
} else {
|
||||
const char* url = params->url.c_str();
|
||||
const char* md5 = params->md5.c_str();
|
||||
size_t size = params->size;
|
||||
const size_t size = params->size;
|
||||
updateFirmware(url, md5, size);
|
||||
}
|
||||
|
||||
@@ -177,9 +177,8 @@ void firmwareUpdateTask(void* parameter) {
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
||||
uint32_t freeStack = uxTaskGetStackHighWaterMark(NULL);
|
||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||
void updateFirmware(const char* url, const char* expectedMd5, const size_t size) {
|
||||
util::printHeap();
|
||||
|
||||
config.runStatus = RUNSTATUS_STOP;
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
@@ -194,11 +193,9 @@ void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
||||
|
||||
httpClient.begin(url);
|
||||
httpClient.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||
freeStack = uxTaskGetStackHighWaterMark(NULL);
|
||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||
int httpCode = httpClient.GET();
|
||||
freeStack = uxTaskGetStackHighWaterMark(NULL);
|
||||
Serial.printf("Free heap: %d allocatable: %d stack: %d\n", ESP.getFreeHeap(), ESP.getMaxAllocHeap(), freeStack);
|
||||
util::printHeap();
|
||||
const int httpCode = httpClient.GET();
|
||||
util::printHeap();
|
||||
|
||||
if (httpCode == HTTP_CODE_OK) {
|
||||
if (Update.begin(size)) {
|
||||
@@ -215,7 +212,7 @@ void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
||||
}
|
||||
});
|
||||
|
||||
size_t written = Update.writeStream(httpClient.getStream());
|
||||
const size_t written = Update.writeStream(httpClient.getStream());
|
||||
if (written == httpClient.getSize()) {
|
||||
if (Update.end(true)) {
|
||||
wsSerial("Firmware update successful");
|
||||
@@ -248,7 +245,7 @@ void updateFirmware(const char* url, const char* expectedMd5, size_t size) {
|
||||
|
||||
void handleRollback(AsyncWebServerRequest* request) {
|
||||
if (Update.canRollBack()) {
|
||||
bool rollbackSuccess = Update.rollBack();
|
||||
const bool rollbackSuccess = Update.rollBack();
|
||||
if (rollbackSuccess) {
|
||||
request->send(200, "Rollback successful");
|
||||
wsSerial("Rollback successful");
|
||||
@@ -276,7 +273,7 @@ void handleUpdateActions(AsyncWebServerRequest* request) {
|
||||
}
|
||||
StaticJsonDocument<1000> doc;
|
||||
DeserializationError error = deserializeJson(doc, file);
|
||||
JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
||||
const JsonArray deleteFiles = doc["deletefile"].as<JsonArray>();
|
||||
for (const auto& filePath : deleteFiles) {
|
||||
if (contentFS->remove(filePath.as<const char*>())) {
|
||||
wsSerial("deleted file: " + filePath.as<String>());
|
||||
|
||||
@@ -533,17 +533,11 @@ void rxSerialTask(void* parameter) {
|
||||
}
|
||||
|
||||
void ShowAPInfo() {
|
||||
Serial.printf("| AP Information - type %02X |\n", apInfo.type);
|
||||
Serial.printf("| Channel | 0x%02X |\n", apInfo.channel);
|
||||
Serial.printf("| Power | %02X |\n", apInfo.power);
|
||||
Serial.printf("| MAC | %02X%02X%02X%02X%02X%02X%02X%02X |\n", apInfo.mac[7], apInfo.mac[6], apInfo.mac[5], apInfo.mac[4], apInfo.mac[3], apInfo.mac[2], apInfo.mac[1], apInfo.mac[0]);
|
||||
Serial.printf("| Version | 0x%04X |\n", apInfo.version);
|
||||
|
||||
if (apInfo.type == SOLUM_154_SSD1619 || apInfo.type == SOLUM_29_SSD1619 || apInfo.type == SOLUM_29_UC8151 || apInfo.type == SOLUM_42_SSD1619) {
|
||||
char macString[50];
|
||||
sprintf(macString, "%02X%02X%02X%02X%02X%02X%02X%02X", apInfo.mac[7], apInfo.mac[6], apInfo.mac[5], apInfo.mac[4], apInfo.mac[3], apInfo.mac[2], apInfo.mac[1], apInfo.mac[0]);
|
||||
showIpAddress(macString);
|
||||
}
|
||||
Serial.printf("| AP Info - type %02X |\n", apInfo.type);
|
||||
Serial.printf("| Ch | 0x%02X |\n", apInfo.channel);
|
||||
Serial.printf("| Power| %02X |\n", apInfo.power);
|
||||
Serial.printf("| MAC | %02X%02X%02X%02X%02X%02X%02X%02X |\n", apInfo.mac[7], apInfo.mac[6], apInfo.mac[5], apInfo.mac[4], apInfo.mac[3], apInfo.mac[2], apInfo.mac[1], apInfo.mac[0]);
|
||||
Serial.printf("| Ver | 0x%04X |\n", apInfo.version);
|
||||
}
|
||||
|
||||
void notifySegmentedFlash() {
|
||||
|
||||
@@ -3,18 +3,26 @@
|
||||
#include <Arduino.h>
|
||||
#include <ArduinoJson.h>
|
||||
#include <FS.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "storage.h"
|
||||
#include "language.h"
|
||||
#include "storage.h"
|
||||
#include "util.h"
|
||||
|
||||
std::vector<tagRecord*> tagDB;
|
||||
std::unordered_map<std::string, varStruct> varDB;
|
||||
std::unordered_map<int, HwType> hwdata = {
|
||||
{0, {152, 152, 0, 2}},
|
||||
{1, {296, 128, 1, 2}},
|
||||
{2, {400, 300, 0, 2}}};
|
||||
|
||||
Config config;
|
||||
// SemaphoreHandle_t tagDBOwner;
|
||||
|
||||
tagRecord* tagRecord::findByMAC(uint8_t mac[8]) {
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tagRecord::findByMAC(const uint8_t mac[8]) {
|
||||
for (int32_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tag = nullptr;
|
||||
tag = tagDB.at(c);
|
||||
if (memcmp(tag->mac, mac, 8) == 0) {
|
||||
@@ -24,10 +32,9 @@ tagRecord* tagRecord::findByMAC(uint8_t mac[8]) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool deleteRecord(uint8_t mac[8]) {
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tag = nullptr;
|
||||
tag = tagDB.at(c);
|
||||
bool deleteRecord(const uint8_t mac[8]) {
|
||||
for (int32_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tag = tagDB.at(c);
|
||||
if (memcmp(tag->mac, mac, 8) == 0) {
|
||||
if (tag->data != nullptr) {
|
||||
free(tag->data);
|
||||
@@ -41,7 +48,7 @@ bool deleteRecord(uint8_t mac[8]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void mac2hex(uint8_t* mac, char* hexBuffer) {
|
||||
void mac2hex(const uint8_t* mac, char* hexBuffer) {
|
||||
sprintf(hexBuffer, "%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
mac[7], mac[6], mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);
|
||||
}
|
||||
@@ -55,14 +62,14 @@ bool hex2mac(const String& hexString, uint8_t* mac) {
|
||||
mac[6] = 0;
|
||||
mac[7] = 0;
|
||||
return (sscanf(hexString.c_str(), "%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
|
||||
&mac[5], &mac[4], &mac[3], &mac[2], &mac[1], &mac[0]) == 6);
|
||||
&mac[5], &mac[4], &mac[3], &mac[2], &mac[1], &mac[0]) == 6);
|
||||
} else {
|
||||
return (sscanf(hexString.c_str(), "%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX",
|
||||
&mac[7], &mac[6], &mac[5], &mac[4], &mac[3], &mac[2], &mac[1], &mac[0]) == 8);
|
||||
&mac[7], &mac[6], &mac[5], &mac[4], &mac[3], &mac[2], &mac[1], &mac[0]) == 8);
|
||||
}
|
||||
}
|
||||
|
||||
String tagDBtoJson(uint8_t mac[8], uint8_t startPos) {
|
||||
String tagDBtoJson(const uint8_t mac[8], uint8_t startPos) {
|
||||
DynamicJsonDocument doc(5000);
|
||||
JsonArray tags = doc.createNestedArray("tags");
|
||||
|
||||
@@ -85,15 +92,15 @@ String tagDBtoJson(uint8_t mac[8], uint8_t startPos) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (doc.capacity() - doc.memoryUsage() < doc.memoryUsage()/(c+1) + 150) {
|
||||
doc["continu"] = c+1;
|
||||
if (doc.capacity() - doc.memoryUsage() < doc.memoryUsage() / (c + 1) + 500) {
|
||||
doc["continu"] = c + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return doc.as<String>();
|
||||
}
|
||||
|
||||
void fillNode(JsonObject &tag, tagRecord* &taginfo) {
|
||||
void fillNode(JsonObject& tag, tagRecord*& taginfo) {
|
||||
char hexmac[17];
|
||||
mac2hex(taginfo->mac, hexmac);
|
||||
tag["mac"] = String(hexmac);
|
||||
@@ -137,7 +144,7 @@ void saveDB(String filename) {
|
||||
|
||||
file.write('[');
|
||||
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
for (int32_t c = 0; c < tagDB.size(); c++) {
|
||||
doc.clear();
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagDB.at(c);
|
||||
@@ -199,16 +206,16 @@ void loadDB(String filename) {
|
||||
taginfo->lastseen = (uint32_t)tag["lastseen"];
|
||||
taginfo->nextupdate = (uint32_t)tag["nextupdate"];
|
||||
taginfo->expectedNextCheckin = (uint16_t)tag["nextcheckin"];
|
||||
if (taginfo->expectedNextCheckin < now - 1800) {
|
||||
taginfo->expectedNextCheckin = now + 1800;
|
||||
if (taginfo->expectedNextCheckin < now) {
|
||||
taginfo->expectedNextCheckin = now + 1800;
|
||||
}
|
||||
taginfo->pending = false;
|
||||
taginfo->alias = tag["alias"].as<String>();
|
||||
taginfo->contentMode = tag["contentMode"];
|
||||
taginfo->LQI = tag["LQI"];
|
||||
taginfo->RSSI = tag["RSSI"];
|
||||
taginfo->temperature = tag["temperature"];
|
||||
taginfo->batteryMv = tag["batteryMv"];
|
||||
taginfo->LQI = tag["LQI"];
|
||||
taginfo->RSSI = tag["RSSI"];
|
||||
taginfo->temperature = tag["temperature"];
|
||||
taginfo->batteryMv = tag["batteryMv"];
|
||||
taginfo->hwType = (uint8_t)tag["hwType"];
|
||||
taginfo->wakeupReason = tag["wakeupReason"];
|
||||
taginfo->capabilities = tag["capabilities"];
|
||||
@@ -234,8 +241,8 @@ void loadDB(String filename) {
|
||||
|
||||
void destroyDB() {
|
||||
Serial.println("destoying DB");
|
||||
Serial.printf("before, free heap: %d\n", ESP.getFreeHeap());
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
util::printHeap();
|
||||
for (uint32_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* tag = nullptr;
|
||||
tag = tagDB.at(c);
|
||||
if (tag->data != nullptr) {
|
||||
@@ -245,15 +252,32 @@ void destroyDB() {
|
||||
delete tagDB[c];
|
||||
tagDB.erase(tagDB.begin() + c);
|
||||
}
|
||||
Serial.printf("after, free heap: %d\n", ESP.getFreeHeap());
|
||||
util::printHeap();
|
||||
}
|
||||
|
||||
uint8_t getTagCount() {
|
||||
uint8_t tagcount = 0;
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
uint32_t getTagCount() {
|
||||
uint32_t temp = 0;
|
||||
return getTagCount(temp);
|
||||
}
|
||||
|
||||
uint32_t getTagCount(uint32_t& timeoutcount) {
|
||||
uint32_t tagcount = 0;
|
||||
time_t now;
|
||||
time(&now);
|
||||
for (uint32_t c = 0; c < tagDB.size(); c++) {
|
||||
tagRecord* taginfo = nullptr;
|
||||
taginfo = tagDB.at(c);
|
||||
if (taginfo->isExternal == false) tagcount++;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return tagcount;
|
||||
}
|
||||
@@ -261,15 +285,13 @@ uint8_t getTagCount() {
|
||||
void clearPending(tagRecord* taginfo) {
|
||||
taginfo->filename = String();
|
||||
if (taginfo->data != nullptr) {
|
||||
|
||||
//check if this is the last copy of the buffer
|
||||
// check if this is the last copy of the buffer
|
||||
int datacount = 0;
|
||||
for (int16_t c = 0; c < tagDB.size(); c++) {
|
||||
for (uint32_t c = 0; c < tagDB.size(); c++) {
|
||||
if (tagDB.at(c)->data == taginfo->data) datacount++;
|
||||
}
|
||||
if (datacount == 1) free(taginfo->data);
|
||||
taginfo->data = nullptr;
|
||||
|
||||
}
|
||||
taginfo->pending = false;
|
||||
}
|
||||
@@ -318,4 +340,56 @@ void saveAPconfig() {
|
||||
APconfig["timezone"] = config.timeZone;
|
||||
serializeJsonPretty(APconfig, configFile);
|
||||
configFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
HwType getHwType(uint8_t id) {
|
||||
try {
|
||||
return hwdata.at(id);
|
||||
} catch (const std::out_of_range&) {
|
||||
char filename[20];
|
||||
snprintf(filename, sizeof(filename), "/tagtypes/%02X.json", id);
|
||||
Serial.printf("read %s\n", filename);
|
||||
File jsonFile = contentFS->open(filename, "r");
|
||||
|
||||
if (jsonFile) {
|
||||
StaticJsonDocument<100> filter;
|
||||
filter["width"] = true;
|
||||
filter["height"] = true;
|
||||
filter["rotatebuffer"] = true;
|
||||
filter["bpp"] = true;
|
||||
StaticJsonDocument<250> doc;
|
||||
DeserializationError error = deserializeJson(doc, jsonFile, DeserializationOption::Filter(filter));
|
||||
jsonFile.close();
|
||||
if (error) {
|
||||
Serial.println("json error in " + String(filename));
|
||||
Serial.println(error.c_str());
|
||||
} else {
|
||||
hwdata[id].width = doc["width"];
|
||||
hwdata[id].height = doc["height"];
|
||||
hwdata[id].rotatebuffer = doc["rotatebuffer"];
|
||||
hwdata[id].bpp = doc["bpp"];
|
||||
return hwdata.at(id);
|
||||
}
|
||||
}
|
||||
return {0, 0, 0, 0};
|
||||
}
|
||||
}
|
||||
|
||||
bool setVarDB(const std::string& key, const String& value) {
|
||||
auto it = varDB.find(key);
|
||||
if (it == varDB.end()) {
|
||||
varStruct newVar;
|
||||
newVar.value = value;
|
||||
newVar.changed = true;
|
||||
varDB[key] = newVar;
|
||||
return true;
|
||||
} else {
|
||||
if (it->second.value != value) {
|
||||
it->second.value = value;
|
||||
it->second.changed = true;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,12 @@ void wsErr(String text) {
|
||||
if (wsMutex) xSemaphoreGive(wsMutex);
|
||||
}
|
||||
|
||||
size_t dbSize(){
|
||||
size_t dbSize() {
|
||||
size_t size = tagDB.size() * sizeof(tagRecord);
|
||||
for(auto &tag : tagDB) {
|
||||
if (tag->data)
|
||||
for (auto &tag : tagDB) {
|
||||
if (tag->data) {
|
||||
size += tag->len;
|
||||
}
|
||||
size += tag->modeConfigJson.length();
|
||||
}
|
||||
return size;
|
||||
@@ -89,12 +90,24 @@ void wsSendSysteminfo() {
|
||||
sys["wifistatus"] = WiFi.status();
|
||||
sys["wifissid"] = WiFi.SSID();
|
||||
|
||||
uint32_t timeoutcount = 0;
|
||||
uint32_t tagcount = getTagCount(timeoutcount);
|
||||
char result[40];
|
||||
if (timeoutcount > 0) {
|
||||
snprintf(result, sizeof(result), "%lu / %lu, %lu timed out", tagcount, tagDB.size(), timeoutcount);
|
||||
} else {
|
||||
snprintf(result, sizeof(result), "%lu / %lu", tagcount, tagDB.size());
|
||||
}
|
||||
setVarDB("ap_tagcount", result);
|
||||
setVarDB("ap_ip", WiFi.localIP().toString());
|
||||
setVarDB("ap_ch", String(apInfo.channel));
|
||||
|
||||
xSemaphoreTake(wsMutex, portMAX_DELAY);
|
||||
ws.textAll(doc.as<String>());
|
||||
xSemaphoreGive(wsMutex);
|
||||
}
|
||||
|
||||
void wsSendTaginfo(uint8_t *mac, uint8_t syncMode) {
|
||||
void wsSendTaginfo(const uint8_t *mac, uint8_t syncMode) {
|
||||
if (syncMode != SYNC_DELETE) {
|
||||
String json = "";
|
||||
json = tagDBtoJson(mac);
|
||||
@@ -189,6 +202,7 @@ void init_web() {
|
||||
});
|
||||
|
||||
server.serveStatic("/current", *contentFS, "/current/").setCacheControl("max-age=604800");
|
||||
server.serveStatic("/tagtypes", *contentFS, "/tagtypes/").setCacheControl("max-age=604800");
|
||||
server.serveStatic("/", *contentFS, "/www/").setDefaultFile("index.html");
|
||||
|
||||
server.on(
|
||||
@@ -296,6 +310,9 @@ void init_web() {
|
||||
if (strcmp(cmdValue, "reset") == 0) {
|
||||
sendTagCommand(mac, CMD_DO_RESET_SETTINGS, !taginfo->isExternal);
|
||||
}
|
||||
if (strcmp(cmdValue, "deepsleep") == 0) {
|
||||
sendTagCommand(mac, CMD_DO_DEEPSLEEP, !taginfo->isExternal);
|
||||
}
|
||||
request->send(200, "text/plain", "Ok, done");
|
||||
} else {
|
||||
request->send(200, "text/plain", "Error: mac not found");
|
||||
@@ -360,6 +377,37 @@ void init_web() {
|
||||
request->send(200, "text/plain", "Ok, saved");
|
||||
});
|
||||
|
||||
server.on("/set_var", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
if (request->hasParam("key", true) && request->hasParam("val", true)) {
|
||||
std::string key = request->getParam("key", true)->value().c_str();
|
||||
String val = request->getParam("val", true)->value();
|
||||
Serial.printf("set key %s value %s\n", key.c_str(), val);
|
||||
setVarDB(key, val);
|
||||
request->send(200, "text/plain", "Ok, saved");
|
||||
} else {
|
||||
request->send(500, "text/plain", "param error");
|
||||
}
|
||||
});
|
||||
server.on("/set_vars", HTTP_POST, [](AsyncWebServerRequest *request) {
|
||||
if (request->hasParam("json", true)) {
|
||||
DynamicJsonDocument jsonDocument(2048);
|
||||
DeserializationError error = deserializeJson(jsonDocument, request->getParam("json", true)->value());
|
||||
if (error) {
|
||||
request->send(400, "text/plain", "Failed to parse JSON");
|
||||
return;
|
||||
}
|
||||
for (JsonPair kv : jsonDocument.as<JsonObject>()) {
|
||||
std::string key = kv.key().c_str();
|
||||
String val = kv.value().as<String>();
|
||||
Serial.printf("set key %s value %s\n", key.c_str(), val);
|
||||
setVarDB(key, val);
|
||||
}
|
||||
request->send(200, "text/plain", "JSON uploaded and processed");
|
||||
} else {
|
||||
request->send(400, "text/plain", "No 'json' parameter found in request");
|
||||
}
|
||||
});
|
||||
|
||||
// setup
|
||||
|
||||
server.on("/setup", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
@@ -435,10 +483,7 @@ void init_web() {
|
||||
|
||||
server.on("/backup_db", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
saveDB("/current/tagDB.json");
|
||||
File file = contentFS->open("/current/tagDB.json", "r");
|
||||
AsyncWebServerResponse *response = request->beginResponse(file, "tagDB.json", String(), true);
|
||||
request->send(response);
|
||||
file.close();
|
||||
request->send(*contentFS, "/current/tagDB.json", String(), true);
|
||||
});
|
||||
|
||||
server.on("/sysinfo", HTTP_GET, handleSysinfoRequest);
|
||||
@@ -486,16 +531,20 @@ void doImageUpload(AsyncWebServerRequest *request, String filename, size_t index
|
||||
request->_tempFile.close();
|
||||
if (request->hasParam("mac", true)) {
|
||||
String dst = request->getParam("mac", true)->value();
|
||||
bool dither = true;
|
||||
if (request->hasParam("dither", true)) {
|
||||
if (request->getParam("dither", true)->value() == "0") dither = false;
|
||||
}
|
||||
uint8_t mac[8];
|
||||
if (hex2mac(dst, mac)) {
|
||||
tagRecord *taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(mac);
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->modeConfigJson = "{\"filename\":\"" + dst + ".jpg\",\"timetolive\":\"0\",\"dither\":\"" + String(dither) + "\",\"delete\":\"1\"}";
|
||||
bool dither = true;
|
||||
if (request->hasParam("dither", true)) {
|
||||
if (request->getParam("dither", true)->value() == "0") dither = false;
|
||||
}
|
||||
uint32_t ttl = 0;
|
||||
if (request->hasParam("ttl", true)) {
|
||||
ttl = request->getParam("ttl", true)->value().toInt();
|
||||
}
|
||||
taginfo->modeConfigJson = "{\"filename\":\"" + dst + ".jpg\",\"timetolive\":\"" + String(ttl) + "\",\"dither\":\"" + String(dither) + "\",\"delete\":\"1\"}";
|
||||
taginfo->contentMode = 0;
|
||||
taginfo->nextupdate = 0;
|
||||
wsSendTaginfo(mac, SYNC_USERCFG);
|
||||
@@ -517,19 +566,23 @@ void doJsonUpload(AsyncWebServerRequest *request) {
|
||||
}
|
||||
if (request->hasParam("mac", true) && request->hasParam("json", true)) {
|
||||
String dst = request->getParam("mac", true)->value();
|
||||
File file = LittleFS.open("/" + dst + ".json", "w");
|
||||
if (!file) {
|
||||
request->send(400, "text/plain", "Failed to create file");
|
||||
return;
|
||||
}
|
||||
file.print(request->getParam("json", true)->value());
|
||||
file.close();
|
||||
uint8_t mac[8];
|
||||
if (hex2mac(dst, mac)) {
|
||||
File file = LittleFS.open("/current/" + dst + ".json", "w");
|
||||
if (!file) {
|
||||
request->send(400, "text/plain", "Failed to create file");
|
||||
return;
|
||||
}
|
||||
file.print(request->getParam("json", true)->value());
|
||||
file.close();
|
||||
tagRecord *taginfo = nullptr;
|
||||
taginfo = tagRecord::findByMAC(mac);
|
||||
if (taginfo != nullptr) {
|
||||
taginfo->modeConfigJson = "{\"filename\":\"/" + dst + ".json\"}";
|
||||
uint32_t ttl = 0;
|
||||
if (request->hasParam("ttl", true)) {
|
||||
ttl = request->getParam("ttl", true)->value().toInt();
|
||||
}
|
||||
taginfo->modeConfigJson = "{\"filename\":\"/current/" + dst + ".json\",\"interval\":\"" + String(ttl) + "\"}";
|
||||
taginfo->contentMode = 19;
|
||||
taginfo->nextupdate = 0;
|
||||
wsSendTaginfo(mac, SYNC_USERCFG);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -42,6 +44,7 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
@@ -56,7 +59,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -75,6 +80,7 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
51,
|
||||
17
|
||||
]
|
||||
}
|
||||
@@ -88,7 +94,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -107,6 +115,8 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
]
|
||||
}
|
||||
@@ -120,7 +130,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -151,6 +163,8 @@
|
||||
"hwtype": [
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -180,6 +194,7 @@
|
||||
"desc": "Dutch rain predictions for the next two hours. Only works for locations in the Netherlands and Belgium.",
|
||||
"hwtype": [
|
||||
1,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -210,6 +225,8 @@
|
||||
"hwtype": [
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -241,6 +258,8 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -266,19 +285,27 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
{
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"desc": "Full URL of the json template. See OpenEpaperLink wiki for the right json format",
|
||||
"desc": "Full URL of the json template. See OpenEpaperLink wiki for the right json format. Specify a url OR a filename",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "filename",
|
||||
"name": "Filename",
|
||||
"desc": "Filename of the json template. See OpenEpaperLink wiki for the right json format. Specify a url OR a filename",
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"key": "interval",
|
||||
"name": "Interval",
|
||||
"desc": "How often (in minutes) the template is being fetched. Minimum is 3 minutes.",
|
||||
"desc": "In case of an url, wow often (in minutes) the template is being fetched. Minimum is 3 minutes.",
|
||||
"type": "int"
|
||||
}
|
||||
]
|
||||
@@ -291,6 +318,7 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51
|
||||
],
|
||||
@@ -316,6 +344,8 @@
|
||||
"hwtype": [
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -347,7 +377,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -436,7 +468,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -448,7 +482,9 @@
|
||||
"options": {
|
||||
"0": "Reboot",
|
||||
"1": "Scan Channels",
|
||||
"2": "Clear settings"
|
||||
"2": "Clear settings",
|
||||
"3": "Enter Deep Sleep"
|
||||
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -461,7 +497,9 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
17,
|
||||
51,
|
||||
240
|
||||
],
|
||||
"param": [
|
||||
@@ -563,6 +601,8 @@
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
5,
|
||||
51,
|
||||
17
|
||||
],
|
||||
"param": [
|
||||
@@ -573,5 +613,11 @@
|
||||
"type": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"name": "Display access point info",
|
||||
"desc": "Displays information about the currently connected access point",
|
||||
"hwtype": [0, 1]
|
||||
}
|
||||
]
|
||||
@@ -612,8 +612,8 @@
|
||||
if (status != 200) {
|
||||
alert("ERROR[" + status + "]: " + responseText);
|
||||
} else {
|
||||
treeRoot.removeChild(treeRoot.childNodes[0]);
|
||||
httpGet(treeRoot, "/");
|
||||
var el = ge(path);
|
||||
el.parentNode.removeChild(el);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
<button id="cfgclrpending">clear pending</button>
|
||||
<button id="cfgtagreboot">reboot</button>
|
||||
<button id="cfgscan">scan</button>
|
||||
<button id="cfgdeepsleep">deep sleep</button>
|
||||
<button id="cfgreset">reset settings</button>
|
||||
<button id="cfgdelete" title="remove"><img src="data:image/gif;base64,R0lGODlhEAAQAPMAANXV1e3t7d/f39HR0dvb2/Hx8dTU1OLi4urq6mZmZpmZmf///wAAAAAAAAAAAAAAACH5BAEAAAwALAAAAAAQABAAAARBkMlJq71Yrp3ZXkr4WWCYnOZSgQVyEMYwJCq1nHhe20qgCAoA7QLyAYU7njE4JPV+zOSkCEUSFbmTVPPpbjvgTAQAOw== "></button>
|
||||
</p>
|
||||
@@ -68,7 +69,7 @@
|
||||
<p>
|
||||
<label for="apcfgchid">Channel</label>
|
||||
<select id="apcfgchid">
|
||||
<option value="0">auto</option>
|
||||
<option value="0" selected>auto</option>
|
||||
<option value="11">11</option>
|
||||
<option value="15">15</option>
|
||||
<option value="20">20</option>
|
||||
@@ -82,7 +83,7 @@
|
||||
<select id="apcfgledbrightness">
|
||||
<option value="-1">off</option>
|
||||
<option value="64">25%</option>
|
||||
<option value="128">50%</option>
|
||||
<option value="128" selected>50%</option>
|
||||
<option value="192">75%</option>
|
||||
<option value="255">100%</option>
|
||||
</select>
|
||||
@@ -90,7 +91,7 @@
|
||||
<p>
|
||||
<label for="apcfglanguage">Content language</label>
|
||||
<select id="apcfglanguage">
|
||||
<option value="0">EN English</option>
|
||||
<option value="0" selected>EN English</option>
|
||||
<option value="1">NL Nederlands</option>
|
||||
<option value="2">DE Deutsch</option>
|
||||
</select>
|
||||
@@ -101,7 +102,7 @@ longer periods when no updates are expected
|
||||
the maximum sleep time.">
|
||||
<label for="apclatency">Maximum sleep</label>
|
||||
<select id="apclatency">
|
||||
<option value="0">shortest (40 sec)</option>
|
||||
<option value="0" selected>shortest (40 sec)</option>
|
||||
<option value="5">5 minutes</option>
|
||||
<option value="10">10 minute</option>
|
||||
<option value="30">30 minutes</option>
|
||||
@@ -113,14 +114,14 @@ Latency will be around 40 seconds.">
|
||||
<label for="apcpreventsleep">Shorten latency during config</label>
|
||||
<select id="apcpreventsleep">
|
||||
<option value="0">no</option>
|
||||
<option value="1">yes</option>
|
||||
<option value="1" selected>yes</option>
|
||||
</select>
|
||||
</p>
|
||||
<p title="Turn off preview images on the webpage if you want to manage many tags,
|
||||
to save file system space">
|
||||
<label for="apcpreview">Preview images</label>
|
||||
<select id="apcpreview">
|
||||
<option value="1">yes</option>
|
||||
<option value="1" selected>yes</option>
|
||||
<option value="0">no</option>
|
||||
</select>
|
||||
</p>
|
||||
@@ -134,7 +135,7 @@ to save file system space">
|
||||
<option value="60">15.0 dBm</option>
|
||||
<option value="52">13.0 dBm</option>
|
||||
<option value="44">11.0 dBm</option>
|
||||
<option value="34">8.5 dBm</option>
|
||||
<option value="34" selected>8.5 dBm</option>
|
||||
<option value="28">7.0 dBm</option>
|
||||
<option value="20">5.0 dBm</option>
|
||||
<option value="8">2.0 dBm</option>
|
||||
@@ -144,7 +145,7 @@ to save file system space">
|
||||
<label for="apctimezone">Local time zone</label>
|
||||
<select id="apctimezone">
|
||||
<optgroup label="Europe">
|
||||
<option value="CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00">Central European Time</option>
|
||||
<option value="CET-1CEST-2,M3.5.0/02:00:00,M10.5.0/03:00:00" selected>Central European Time</option>
|
||||
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Athens, Greece</option>
|
||||
<option value="GMT+0IST-1,M3.5.0/01:00:00,M10.5.0/02:00:00">Dublin, Ireland</option>
|
||||
<option value="EET-2EEST-3,M3.5.0/03:00:00,M10.5.0/04:00:00">Helsinki, Finland</option>
|
||||
@@ -171,6 +172,7 @@ to save file system space">
|
||||
<option value="NZST-12NZDT-13,M9.4.0/02:00:00,M4.1.0/03:00:00">New Zealand</option>
|
||||
</optgroup>
|
||||
<optgroup label="Asia">
|
||||
<option value="JST-9">Tokyo</option>
|
||||
<option value="WIB-7">Jakarta</option>
|
||||
<option value="GMT+2">Jerusalem</option>
|
||||
<option value="SGT-8">Singapore</option>
|
||||
|
||||
@@ -122,7 +122,7 @@ select {
|
||||
position: fixed;
|
||||
top: 65px;
|
||||
left: 15px;
|
||||
width: 380px;
|
||||
min-width: 380px;
|
||||
padding: 15px;
|
||||
background-color: #f0e6d3;
|
||||
z-index: 999;
|
||||
@@ -425,6 +425,11 @@ ul.messages li.new {
|
||||
background-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.drophighlight {
|
||||
border: 1px solid red;
|
||||
box-shadow: 7px 10px 52px -19px rgba(255, 0, 0, 0.63);
|
||||
}
|
||||
|
||||
/* painter */
|
||||
|
||||
#canvasdiv {
|
||||
|
||||
@@ -8,48 +8,7 @@ const WAKEUP_REASON_FIRSTBOOT = 0xFC;
|
||||
const WAKEUP_REASON_NETWORK_SCAN = 0xFD;
|
||||
const WAKEUP_REASON_WDT_RESET = 0xFE;
|
||||
|
||||
const models = ["1.54\" 152x152px", "2.9\" 296x128px", "4.2\" 400x300px"];
|
||||
models[240] = "Segmented tag"
|
||||
models[17] = "2.9\" 296x128px (UC8151)"
|
||||
models[0x30] = "1.6\" BWR 200x200px"
|
||||
models[0x38] = "1.6\" BWY 200x200px"
|
||||
models[0x31] = "2.2\" BWR 296x160px"
|
||||
models[0x39] = "2.2\" BWY 296x160px"
|
||||
models[0x32] = "2.6\" BWR 360x184px"
|
||||
models[0x3A] = "2.6\" BWY 360x184px"
|
||||
models[0x33] = "2.9\" BWR 384x168px"
|
||||
models[0x3B] = "2.9\" BWY 384x168px"
|
||||
models[0x34] = "4.2\" BWR 400x300px"
|
||||
models[0x3C] = "4.2\" BWY 400x300px"
|
||||
models[0x35] = "6.0\" BWR 600x448px"
|
||||
models[0x3D] = "6.0\" BWY 600x448px"
|
||||
models[0x36] = "7.5\" BWR 880x528px"
|
||||
models[0x3E] = "7.5\" BWY 880x528px"
|
||||
models[0x37] = "11.6\" BWR 640x960px"
|
||||
models[0x3F] = "11.6\" BWY 640x960px"
|
||||
|
||||
|
||||
const displaySizeLookup = { 0: [152, 152, 4], 1: [128, 296, 2], 2: [400, 300, 2] }; // w, h, rotate
|
||||
displaySizeLookup[17] = [128, 296, 2];
|
||||
displaySizeLookup[240] = [0, 0, 0];
|
||||
displaySizeLookup[0x30] = [200, 200, 4];//"1.6\" BWR 200x200px"
|
||||
displaySizeLookup[0x38] = [200, 200, 4];//"1.6\" BWY 200x200px"
|
||||
displaySizeLookup[0x31] = [296, 160, 2];//"2.2\" BWR 296x160px"
|
||||
displaySizeLookup[0x39] = [296, 160, 2];//"2.2\" BWY 296x160px"
|
||||
displaySizeLookup[0x32] = [360, 184, 2];//"2.6\" BWR 360x184px"
|
||||
displaySizeLookup[0x3A] = [360, 184, 2];//"2.6\" BWY 360x184px"
|
||||
displaySizeLookup[0x33] = [384, 168, 2];//"2.9\" BWR 384x168px"
|
||||
displaySizeLookup[0x3B] = [384, 168, 2];//"2.9\" BWY 384x168px"
|
||||
displaySizeLookup[0x34] = [400, 300, 2];//"4.2\" BWR 400x300px"
|
||||
displaySizeLookup[0x3C] = [400, 300, 2];//"4.2\" BWY 400x300px"
|
||||
displaySizeLookup[0x35] = [600, 448, 2];//"6.0\" BWR 600x448px"
|
||||
displaySizeLookup[0x3D] = [600, 448, 2];//"6.0\" BWY 600x448px"
|
||||
displaySizeLookup[0x36] = [880, 528, 2];//"7.5\" BWR 880x528px"
|
||||
displaySizeLookup[0x3E] = [880, 528, 2];//"7.5\" BWY 880x528px"
|
||||
displaySizeLookup[0x37] = [640, 960, 4];//"11.6\" BWR 640x960px"
|
||||
displaySizeLookup[0x3F] = [640, 960, 4];//"11.6\" BWY 640x960px"
|
||||
|
||||
const colorTable = { 0: [255, 255, 255], 1: [0, 0, 0], 2: [255, 0, 0], 3: [150, 150, 150] };
|
||||
let tagTypes = {};
|
||||
|
||||
const apstate = [
|
||||
{ state: "offline", color: "red" },
|
||||
@@ -71,18 +30,10 @@ const imageQueue = [];
|
||||
let isProcessing = false;
|
||||
let servertimediff = 0;
|
||||
let paintLoaded = false, paintShow = false;
|
||||
var cardconfig;
|
||||
let cardconfig;
|
||||
let otamodule;
|
||||
|
||||
window.addEventListener("load", function () {
|
||||
fetch("/get_ap_config")
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.alias) {
|
||||
$(".logo").innerHTML = data.alias;
|
||||
this.document.title = data.alias;
|
||||
}
|
||||
});
|
||||
fetch('/content_cards.json')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
@@ -93,8 +44,17 @@ window.addEventListener("load", function () {
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert("I can\'t load /www/content_cards.json.\r\nHave you upload it to the data partition?");
|
||||
alert("I can't load /www/content_cards.json.\r\nHave you upload it to the data partition?");
|
||||
});
|
||||
fetch("/get_ap_config")
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.alias) {
|
||||
$(".logo").innerHTML = data.alias;
|
||||
this.document.title = data.alias;
|
||||
}
|
||||
});
|
||||
dropUpload();
|
||||
});
|
||||
|
||||
let socket;
|
||||
@@ -143,7 +103,7 @@ function connect() {
|
||||
servertimediff = (Date.now() / 1000) - msg.sys.currtime;
|
||||
}
|
||||
if (msg.apitem) {
|
||||
var row = $("#aptable").insertRow();
|
||||
let row = $("#aptable").insertRow();
|
||||
row.insertCell(0).innerHTML = "<a href=\"http://" + msg.apitem.ip + "\" target=\"_new\">" + msg.apitem.ip + "</a>";
|
||||
row.insertCell(1).innerHTML = msg.apitem.alias;
|
||||
row.insertCell(2).innerHTML = msg.apitem.count;
|
||||
@@ -151,7 +111,7 @@ function connect() {
|
||||
row.insertCell(4).innerHTML = msg.apitem.version;
|
||||
}
|
||||
if (msg.console) {
|
||||
if (otamodule && typeof(otamodule.print) === "function") {
|
||||
if (otamodule && typeof (otamodule.print) === "function") {
|
||||
let color = "#c0c0c0";
|
||||
if (msg.console.startsWith("Fail") || msg.console.startsWith("Err")) {
|
||||
color = "red";
|
||||
@@ -168,20 +128,20 @@ function connect() {
|
||||
}
|
||||
|
||||
function convertSize(bytes) {
|
||||
if (bytes >= 1073741824) { bytes = (bytes / 1073741824).toFixed(2) + " GB"; }
|
||||
else if (bytes >= 1048576) { bytes = (bytes / 1048576).toFixed(2) + " MB"; }
|
||||
else if (bytes >= 1024) { bytes = (bytes / 1024).toFixed(2) + " kB"; }
|
||||
else if (bytes > 1) { bytes = bytes + " bytes"; }
|
||||
else if (bytes == 1) { bytes = bytes + " byte"; }
|
||||
else { bytes = "0 bytes"; }
|
||||
if (bytes >= 1073741824) { bytes = (bytes / 1073741824).toFixed(2) + " GB"; }
|
||||
else if (bytes >= 1048576) { bytes = (bytes / 1048576).toFixed(2) + " MB"; }
|
||||
else if (bytes >= 1024) { bytes = (bytes / 1024).toFixed(2) + " kB"; }
|
||||
else if (bytes > 1) { bytes = bytes + " bytes"; }
|
||||
else if (bytes == 1) { bytes = bytes + " byte"; }
|
||||
else { bytes = "0 bytes"; }
|
||||
return bytes;
|
||||
}
|
||||
|
||||
function processTags(tagArray) {
|
||||
for (const element of tagArray) {
|
||||
tagmac = element.mac;
|
||||
const tagmac = element.mac;
|
||||
|
||||
var div = $('#tag' + tagmac);
|
||||
let div = $('#tag' + tagmac);
|
||||
if (div == null) {
|
||||
div = $('#tagtemplate').cloneNode(true);
|
||||
div.setAttribute('id', 'tag' + tagmac);
|
||||
@@ -214,7 +174,11 @@ function processTags(tagArray) {
|
||||
if (contentDefObj) $('#tag' + tagmac + ' .contentmode').innerHTML = contentDefObj.name;
|
||||
if (element.RSSI) {
|
||||
div.dataset.hwtype = element.hwType;
|
||||
$('#tag' + tagmac + ' .model').innerHTML = models[element.hwType];
|
||||
(async () => {
|
||||
const localTagmac = tagmac;
|
||||
const data = await getTagtype(element.hwType);
|
||||
$('#tag' + localTagmac + ' .model').innerHTML = data.name;
|
||||
})();
|
||||
let statusline = "";
|
||||
if (element.RSSI != 100) {
|
||||
if (element.ch > 0) statusline += `CH ${element.ch}, `;
|
||||
@@ -239,15 +203,15 @@ function processTags(tagArray) {
|
||||
|
||||
if (element.contentMode == 20) {
|
||||
$('#tag' + tagmac + ' .tagimg').style.display = 'none';
|
||||
} else if (div.dataset.hash != element.hash && div.dataset.hwtype > -1 && (element.isexternal == false || element.contentMode != 12)) {
|
||||
} else if (div.dataset.hash != element.hash && div.dataset.hwtype > -1 && (!element.isexternal || element.contentMode != 12)) {
|
||||
loadImage(tagmac, '/current/' + tagmac + '.raw?' + element.hash);
|
||||
div.dataset.hash = element.hash;
|
||||
}
|
||||
if (element.isexternal == true && element.contentMode == 12) $('#tag' + tagmac + ' .tagimg').style.display = 'none';
|
||||
if (element.isexternal && element.contentMode == 12) $('#tag' + tagmac + ' .tagimg').style.display = 'none';
|
||||
|
||||
if (element.nextupdate > 1672531200 && element.nextupdate != 3216153600) {
|
||||
var date = new Date(element.nextupdate * 1000);
|
||||
var options = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false };
|
||||
const date = new Date(element.nextupdate * 1000);
|
||||
const options = { hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false };
|
||||
$('#tag' + tagmac + ' .nextupdate').innerHTML = "<span>next update</span>" + date.toLocaleString('nl-NL', options);
|
||||
} else {
|
||||
$('#tag' + tagmac + ' .nextupdate').innerHTML = "";
|
||||
@@ -274,6 +238,7 @@ function processTags(tagArray) {
|
||||
case WAKEUP_REASON_TIMED:
|
||||
break;
|
||||
case WAKEUP_REASON_BOOT:
|
||||
case WAKEUP_REASON_FIRSTBOOT:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "<font color=yellow>First boot</font>"
|
||||
$('#tag' + tagmac).style.background = "#b0d0b0";
|
||||
break;
|
||||
@@ -284,10 +249,6 @@ function processTags(tagArray) {
|
||||
case WAKEUP_REASON_NFC:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "NFC wakeup"
|
||||
break;
|
||||
case WAKEUP_REASON_FIRSTBOOT:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "<font color=yellow>First boot</font>"
|
||||
$('#tag' + tagmac).style.background = "#b0d0b0";
|
||||
break;
|
||||
case WAKEUP_REASON_NETWORK_SCAN:
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "<font color=yellow>Network scan</font>"
|
||||
$('#tag' + tagmac).style.background = "#c0c0d0";
|
||||
@@ -308,10 +269,11 @@ function processTags(tagArray) {
|
||||
}
|
||||
|
||||
function updatecards() {
|
||||
if (servertimediff > 1000000000) servertimediff = 0;
|
||||
$('#taglist').querySelectorAll('[data-mac]').forEach(item => {
|
||||
let tagmac = item.dataset.mac;
|
||||
|
||||
if (item.dataset.lastseen && item.dataset.lastseen > 1672531200) {
|
||||
if (item.dataset.lastseen && item.dataset.lastseen > (Date.now() / 1000) - servertimediff - 30 * 24 * 3600 * 60) {
|
||||
let idletime = (Date.now() / 1000) - servertimediff - item.dataset.lastseen;
|
||||
$('#tag' + tagmac + ' .lastseen').innerHTML = "<span>last seen</span>" + displayTime(Math.floor(idletime)) + " ago";
|
||||
if ((Date.now() / 1000) - servertimediff - 600 > item.dataset.nextcheckin) {
|
||||
@@ -334,6 +296,8 @@ function updatecards() {
|
||||
if (item.dataset.nextcheckin > 1672531200 && parseInt(item.dataset.wakeupreason) == 0) {
|
||||
let nextcheckin = item.dataset.nextcheckin - ((Date.now() / 1000) - servertimediff);
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "<span>expected checkin</span>" + displayTime(Math.floor(nextcheckin));
|
||||
} else {
|
||||
$('#tag' + tagmac + ' .nextcheckin').innerHTML = "";
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -371,7 +335,7 @@ function loadContentCard(mac) {
|
||||
fetch("/get_db?mac=" + mac)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
var tagdata = data.tags[0];
|
||||
const tagdata = data.tags[0];
|
||||
$('#cfgalias').value = tagdata.alias;
|
||||
$('#cfgmore').style.display = "none";
|
||||
if (populateSelectTag(tagdata.hwType, tagdata.capabilities)) {
|
||||
@@ -424,7 +388,7 @@ $('#cfgsave').onclick = function () {
|
||||
formData.append("alias", $('#cfgalias').value);
|
||||
|
||||
if (contentMode) {
|
||||
extraoptions.forEach(element => {
|
||||
extraoptions?.forEach(element => {
|
||||
if ($('#opt' + element.key)) {
|
||||
obj[element.key] = $('#opt' + element.key).value;
|
||||
}
|
||||
@@ -462,7 +426,7 @@ function sendCmd(mac, cmd) {
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(data => {
|
||||
var div = $('#tag' + $('#cfgmac').dataset.mac);
|
||||
let div = $('#tag' + $('#cfgmac').dataset.mac);
|
||||
if (cmd == "del") div.remove();
|
||||
showMessage(data);
|
||||
})
|
||||
@@ -491,6 +455,10 @@ $('#cfgscan').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "scan");
|
||||
}
|
||||
|
||||
$('#cfgdeepsleep').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "deepsleep");
|
||||
}
|
||||
|
||||
$('#cfgreset').onclick = function () {
|
||||
sendCmd($('#cfgmac').dataset.mac, "reset");
|
||||
}
|
||||
@@ -504,9 +472,9 @@ $('#rebootbutton').onclick = function () {
|
||||
}
|
||||
|
||||
$('#apconfigbutton').onclick = function () {
|
||||
var table = document.getElementById("aptable");
|
||||
var rowCount = table.rows.length;
|
||||
for (var i = rowCount - 1; i > 0; i--) {
|
||||
let table = document.getElementById("aptable");
|
||||
const rowCount = table.rows.length;
|
||||
for (let i = rowCount - 1; i > 0; i--) {
|
||||
table.deleteRow(i);
|
||||
}
|
||||
fetch("/get_ap_config")
|
||||
@@ -569,8 +537,7 @@ $('#paintbutton').onclick = function () {
|
||||
$('#customoptions').innerHTML = "<div id=\"buttonbar\"></div><div id=\"canvasdiv\"></div><div id=\"layersdiv\"></div><p id=\"savebar\"></p>";
|
||||
const mac = $('#cfgmac').dataset.mac
|
||||
const hwtype = $('#tag' + mac).dataset.hwtype;
|
||||
var [width, height] = displaySizeLookup[hwtype] || [0, 0];
|
||||
if (height > width) [width, height] = [height, width];
|
||||
const [width, height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
|
||||
if (paintLoaded) {
|
||||
startPainter(mac, width, height);
|
||||
} else {
|
||||
@@ -582,7 +549,7 @@ $('#paintbutton').onclick = function () {
|
||||
}
|
||||
|
||||
function loadScript(url, callback) {
|
||||
var script = document.createElement('script');
|
||||
let script = document.createElement('script');
|
||||
script.src = url;
|
||||
script.onload = function () {
|
||||
if (callback) {
|
||||
@@ -595,7 +562,7 @@ function loadScript(url, callback) {
|
||||
function contentselected() {
|
||||
let contentMode = $('#cfgcontent').value;
|
||||
$('#customoptions').innerHTML = "";
|
||||
var obj = {};
|
||||
let obj = {};
|
||||
if ($('#cfgcontent').dataset.json && ($('#cfgcontent').dataset.json != "null")) {
|
||||
obj = JSON.parse($('#cfgcontent').dataset.json);
|
||||
}
|
||||
@@ -607,15 +574,15 @@ function contentselected() {
|
||||
}
|
||||
$('#paintbutton').style.display = (contentMode == 0 ? 'inline-block' : 'none');
|
||||
let extraoptions = contentDef?.param ?? null;
|
||||
extraoptions.forEach(element => {
|
||||
var label = document.createElement("label");
|
||||
extraoptions?.forEach(element => {
|
||||
let label = document.createElement("label");
|
||||
label.innerHTML = element.name;
|
||||
label.setAttribute("for", 'opt' + element.key);
|
||||
if (element.desc) {
|
||||
label.style.cursor = 'help';
|
||||
label.title = element.desc;
|
||||
}
|
||||
var input = document.createElement("input");
|
||||
let input = document.createElement("input");
|
||||
switch (element.type) {
|
||||
case 'text':
|
||||
input.type = "text";
|
||||
@@ -633,7 +600,7 @@ function contentselected() {
|
||||
const optionElement = document.createElement("option");
|
||||
optionElement.value = key;
|
||||
optionElement.text = element.options[key];
|
||||
if (element.options[key].substring(0,1)=="-") {
|
||||
if (element.options[key].substring(0, 1) == "-") {
|
||||
optionElement.text = element.options[key].substring(1);
|
||||
optionElement.selected = true;
|
||||
} else {
|
||||
@@ -646,7 +613,7 @@ function contentselected() {
|
||||
input.id = 'opt' + element.key;
|
||||
input.title = element.desc;
|
||||
if (obj[element.key]) input.value = obj[element.key];
|
||||
var p = document.createElement("p");
|
||||
let p = document.createElement("p");
|
||||
p.appendChild(label);
|
||||
p.appendChild(input);
|
||||
$('#customoptions').appendChild(p);
|
||||
@@ -657,14 +624,14 @@ function contentselected() {
|
||||
}
|
||||
|
||||
function populateSelectTag(hwtype, capabilities) {
|
||||
var selectTag = $("#cfgcontent");
|
||||
let selectTag = $("#cfgcontent");
|
||||
selectTag.innerHTML = "";
|
||||
var optionsAdded = false;
|
||||
var option;
|
||||
let optionsAdded = false;
|
||||
let option;
|
||||
cardconfig.forEach(item => {
|
||||
var capcheck = item.capabilities ?? 0;
|
||||
var hwtypeArray = item.hwtype;
|
||||
if (hwtypeArray.includes(hwtype) && (capabilities & capcheck || capcheck == 0)) {
|
||||
const capcheck = item.capabilities ?? 0;
|
||||
const hwtypeArray = item.hwtype ?? [];
|
||||
if ((hwtypeArray.includes(hwtype) || tagTypes[hwtype].contentids.includes(item.id)) && (capabilities & capcheck || capcheck == 0)) {
|
||||
option = document.createElement("option");
|
||||
option.value = item.id;
|
||||
option.text = item.name;
|
||||
@@ -673,11 +640,11 @@ function populateSelectTag(hwtype, capabilities) {
|
||||
}
|
||||
});
|
||||
|
||||
var rotateTag = $("#cfgrotate");
|
||||
let rotateTag = $("#cfgrotate");
|
||||
rotateTag.innerHTML = "";
|
||||
|
||||
for (let i = 0; i < 4; i++) {
|
||||
if (i == 0 || displaySizeLookup[hwtype][2] == 4 || (i == 2 && displaySizeLookup[hwtype][2] == 2)) {
|
||||
if (i == 0 || tagTypes[hwtype].width == tagTypes[hwtype].height || (i == 2)) {
|
||||
option = document.createElement("option");
|
||||
option.value = i;
|
||||
option.text = (i * 90) + " degrees";
|
||||
@@ -685,7 +652,7 @@ function populateSelectTag(hwtype, capabilities) {
|
||||
}
|
||||
}
|
||||
|
||||
var lutTag = $("#cfglut");
|
||||
let lutTag = $("#cfglut");
|
||||
lutTag.innerHTML = "";
|
||||
|
||||
option = document.createElement("option");
|
||||
@@ -705,14 +672,14 @@ function populateSelectTag(hwtype, capabilities) {
|
||||
|
||||
function getContentDefById(id) {
|
||||
if (id == null) return null;
|
||||
var obj = cardconfig.find(item => item.id == id);
|
||||
return obj ? obj : null;
|
||||
const obj = cardconfig.find(item => item.id == id);
|
||||
return obj || null;
|
||||
}
|
||||
|
||||
function showMessage(message, iserr) {
|
||||
const messages = $('#messages');
|
||||
var date = new Date(),
|
||||
time = date.toLocaleTimeString('nl-NL', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
||||
const date = new Date();
|
||||
const time = date.toLocaleTimeString('nl-NL', { hour12: false, hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
||||
if (iserr) {
|
||||
messages.insertAdjacentHTML("afterbegin", '<li class="new error">' + htmlEncode(time + ' ' + message) + '</li>');
|
||||
} else {
|
||||
@@ -740,31 +707,56 @@ function processQueue() {
|
||||
}
|
||||
isProcessing = true;
|
||||
const { id, imageSrc } = imageQueue.shift();
|
||||
const hwtype = $('#tag' + id).dataset.hwtype;
|
||||
if (tagTypes[hwtype]?.busy) {
|
||||
imageQueue.push({ id, imageSrc });
|
||||
setTimeout(processQueue, 50);
|
||||
return;
|
||||
};
|
||||
|
||||
const canvas = $('#tag' + id + ' .tagimg');
|
||||
canvas.style.display = 'block';
|
||||
const hwtype = $('#tag' + id).dataset.hwtype;
|
||||
|
||||
fetch(imageSrc, { cache: "force-cache" })
|
||||
.then(response => response.arrayBuffer())
|
||||
.then(buffer => {
|
||||
[canvas.width, canvas.height] = displaySizeLookup[hwtype] || [0, 0];
|
||||
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
|
||||
if (tagTypes[hwtype].rotatebuffer) [canvas.width, canvas.height] = [canvas.height, canvas.width];
|
||||
const ctx = canvas.getContext('2d');
|
||||
const imageData = ctx.createImageData(canvas.width, canvas.height);
|
||||
const data = new Uint8ClampedArray(buffer);
|
||||
const offsetRed = (data.length >= (canvas.width * canvas.height / 8) * 2) ? canvas.width * canvas.height / 8 : 0;
|
||||
var pixelValue = 0;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
const pixelIndex = i * 8 + j;
|
||||
if (offsetRed) {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0) | (((data[i + offsetRed] & (1 << (7 - j))) ? 1 : 0) << 1);
|
||||
} else {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0);
|
||||
if (data.length == 0) canvas.style.display = 'none';
|
||||
|
||||
if (tagTypes[hwtype].bpp == 16) {
|
||||
const is16Bit = data.length == tagTypes[hwtype].width * tagTypes[hwtype].height * 2;
|
||||
for (let i = 0; i < min(tagTypes[hwtype].width * tagTypes[hwtype].height, data.length); i++) {
|
||||
const dataIndex = is16Bit ? i * 2 : i;
|
||||
const rgb = is16Bit ? (data[dataIndex] << 8) | data[dataIndex + 1] : data[dataIndex];
|
||||
|
||||
imageData.data[i * 4] = is16Bit ? ((rgb >> 11) & 0x1F) << 3 : (((rgb >> 5) & 0x07) << 5) * 1.13;
|
||||
imageData.data[i * 4 + 1] = is16Bit ? ((rgb >> 5) & 0x3F) << 2 : (((rgb >> 2) & 0x07) << 5) * 1.13;
|
||||
imageData.data[i * 4 + 2] = is16Bit ? (rgb & 0x1F) << 3 : ((rgb & 0x03) << 6) * 1.3;
|
||||
imageData.data[i * 4 + 3] = 255;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
const offsetRed = (data.length >= (canvas.width * canvas.height / 8) * 2) ? canvas.width * canvas.height / 8 : 0;
|
||||
let pixelValue = 0;
|
||||
const colorTable = tagTypes[hwtype].colortable;
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
for (let j = 0; j < 8; j++) {
|
||||
const pixelIndex = i * 8 + j;
|
||||
if (offsetRed) {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0) | (((data[i + offsetRed] & (1 << (7 - j))) ? 1 : 0) << 1);
|
||||
} else {
|
||||
pixelValue = ((data[i] & (1 << (7 - j))) ? 1 : 0);
|
||||
}
|
||||
imageData.data[pixelIndex * 4] = colorTable[pixelValue][0];
|
||||
imageData.data[pixelIndex * 4 + 1] = colorTable[pixelValue][1];
|
||||
imageData.data[pixelIndex * 4 + 2] = colorTable[pixelValue][2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
}
|
||||
imageData.data[pixelIndex * 4] = colorTable[pixelValue][0];
|
||||
imageData.data[pixelIndex * 4 + 1] = colorTable[pixelValue][1];
|
||||
imageData.data[pixelIndex * 4 + 2] = colorTable[pixelValue][2];
|
||||
imageData.data[pixelIndex * 4 + 3] = 255;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,7 +816,7 @@ function GroupSortFilter() {
|
||||
gridItems.forEach(item => {
|
||||
|
||||
if (grouping) {
|
||||
const group = String(grouping).startsWith('data-') ? item.dataset[grouping.slice(5)] || '': item.querySelector('.' + grouping).textContent || '';
|
||||
const group = String(grouping).startsWith('data-') ? item.dataset[grouping.slice(5)] || '' : item.querySelector('.' + grouping).textContent || '';
|
||||
if (group !== currentGroup && group != '') {
|
||||
let header = document.getElementById('header' + group);
|
||||
if (!header) {
|
||||
@@ -855,7 +847,7 @@ function GroupSortFilter() {
|
||||
if ($('input[name="filter"][value="local"]').checked && item.dataset.isexternal == "true") show = false;
|
||||
if ($('input[name="filter"][value="inactive"]').checked && item.querySelector('.warningicon').style.display != 'inline-block') show = false;
|
||||
if ($('input[name="filter"][value="pending"]').checked && !item.classList.contains("tagpending")) show = false;
|
||||
if (show == false) item.style.display = 'none'; else item.style.display = 'block';
|
||||
if (!show) item.style.display = 'none'; else item.style.display = 'block';
|
||||
item.style.order = order++;
|
||||
});
|
||||
|
||||
@@ -875,3 +867,138 @@ $('#toggleFilters').addEventListener('click', () => {
|
||||
filterOptions.style.maxHeight = 0;
|
||||
}
|
||||
});
|
||||
|
||||
async function getTagtype(hwtype) {
|
||||
if (tagTypes[hwtype]?.busy) {
|
||||
await new Promise(resolve => {
|
||||
const checkBusy = setInterval(() => {
|
||||
if (!tagTypes[hwtype].busy) {
|
||||
clearInterval(checkBusy);
|
||||
resolve();
|
||||
}
|
||||
}, 10);
|
||||
});
|
||||
}
|
||||
|
||||
if (tagTypes[hwtype]) {
|
||||
return tagTypes[hwtype];
|
||||
}
|
||||
|
||||
try {
|
||||
tagTypes[hwtype] = { busy: true };
|
||||
const response = await fetch('/tagtypes/' + hwtype.toString(16).padStart(2, '0').toUpperCase() + '.json');
|
||||
if (!response.ok) {
|
||||
let data = { name: 'unknown id ' + hwtype, width: 0, height: 0, bpp: 0, rotatebuffer: 0, colortable: [], busy: false };
|
||||
tagTypes[hwtype] = data;
|
||||
return data;
|
||||
}
|
||||
const jsonData = await response.json();
|
||||
let data = {
|
||||
name: jsonData.name,
|
||||
width: parseInt(jsonData.width),
|
||||
height: parseInt(jsonData.height),
|
||||
bpp: parseInt(jsonData.bpp),
|
||||
rotatebuffer: jsonData.rotatebuffer,
|
||||
colortable: Object.values(jsonData.colortable),
|
||||
contentids: Object.values(jsonData.contentids ?? []),
|
||||
busy: false
|
||||
};
|
||||
tagTypes[hwtype] = data;
|
||||
return data;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching data:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function dropUpload() {
|
||||
const dropZone = $('#taglist');
|
||||
let timeoutId;
|
||||
|
||||
dropZone.addEventListener('dragenter', (event) => {
|
||||
const tagCard = event.target.closest('.tagcard');
|
||||
tagCard?.classList.add('drophighlight');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragover', (event) => {
|
||||
event.preventDefault();
|
||||
const tagCard = event.target.closest('.tagcard');
|
||||
tagCard?.classList.add('drophighlight');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('dragleave', (event) => {
|
||||
const tagCard = event.target.closest('.tagcard');
|
||||
tagCard?.classList.remove('drophighlight');
|
||||
});
|
||||
|
||||
dropZone.addEventListener('drop', (event) => {
|
||||
event.preventDefault();
|
||||
const file = event.dataTransfer.files[0];
|
||||
const tagCard = event.target.closest('.tagcard');
|
||||
if (tagCard && file && file.type.startsWith('image/')) {
|
||||
tagCard.classList.remove('drophighlight');
|
||||
const itemId = tagCard.id;
|
||||
const reader = new FileReader();
|
||||
|
||||
reader.onload = function (e) {
|
||||
const image = new Image();
|
||||
image.src = e.target.result;
|
||||
|
||||
image.onload = function () {
|
||||
const hwtype = tagCard.dataset.hwtype;
|
||||
const mac = tagCard.dataset.mac;
|
||||
const [width, height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
|
||||
const canvas = createCanvas(width, height);
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
const scaleFactor = Math.max(
|
||||
canvas.width / image.width,
|
||||
canvas.height / image.height
|
||||
);
|
||||
|
||||
const newWidth = image.width * scaleFactor;
|
||||
const newHeight = image.height * scaleFactor;
|
||||
|
||||
const x = (canvas.width - newWidth) / 2;
|
||||
const y = (canvas.height - newHeight) / 2;
|
||||
|
||||
ctx.drawImage(image, x, y, newWidth, newHeight);
|
||||
|
||||
canvas.toBlob(async (blob) => {
|
||||
const formData = new FormData();
|
||||
formData.append('mac', mac);
|
||||
formData.append('file', blob, 'image.jpg');
|
||||
|
||||
try {
|
||||
const response = await fetch('/imgupload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
console.log('Resized image uploaded successfully');
|
||||
} else {
|
||||
console.error('Image upload failed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Image upload failed', error);
|
||||
}
|
||||
}, 'image/jpeg'); };
|
||||
|
||||
image.onerror = function () {
|
||||
console.error('Failed to load image.');
|
||||
};
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
});
|
||||
|
||||
function createCanvas(width, height) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return canvas;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,14 @@ export async function initUpdate() {
|
||||
print("Update it manually one last time.");
|
||||
disableButtons(true);
|
||||
}
|
||||
return "{}";
|
||||
return {};
|
||||
} else {
|
||||
return response.json();
|
||||
}
|
||||
})
|
||||
.then(data => {
|
||||
if (data.env) {
|
||||
let matchtest='';
|
||||
let matchtest = '';
|
||||
if (data.buildversion != filesystemversion && filesystemversion != "custom" && data.buildversion != "custom") matchtest = " <- not matching!"
|
||||
print(`env: ${data.env}`);
|
||||
print(`build date: ${formatEpoch(data.buildtime)}`);
|
||||
@@ -45,7 +45,7 @@ export async function initUpdate() {
|
||||
print(`sha: ${data.sha}`);
|
||||
print(`psram size: ${data.psramsize}`);
|
||||
print(`flash size: ${data.flashsize}`);
|
||||
print("--------------------------","gray");
|
||||
print("--------------------------", "gray");
|
||||
env = data.env;
|
||||
currentVer = data.buildversion;
|
||||
currentBuildtime = data.buildtime;
|
||||
@@ -61,7 +61,6 @@ export async function initUpdate() {
|
||||
.then(data => {
|
||||
const releaseDetails = data.map(release => {
|
||||
const assets = release.assets;
|
||||
let fileUrl = null;
|
||||
const filesJsonAsset = assets.find(asset => asset.name === 'filesystem.json');
|
||||
const binariesJsonAsset = assets.find(asset => asset.name === 'binaries.json');
|
||||
if (filesJsonAsset && binariesJsonAsset) {
|
||||
@@ -82,7 +81,7 @@ export async function initUpdate() {
|
||||
easyupdate.innerHTML = ("No releases found.");
|
||||
} else {
|
||||
const release = releaseDetails[0];
|
||||
if (release && release.tag_name) {
|
||||
if (release?.tag_name) {
|
||||
if (release.tag_name == currentVer) {
|
||||
easyupdate.innerHTML = `Version ${currentVer}. You are up to date`;
|
||||
} else if (release.date < formatEpoch(currentBuildtime)) {
|
||||
@@ -100,7 +99,7 @@ export async function initUpdate() {
|
||||
table.appendChild(tableHeader);
|
||||
|
||||
releaseDetails.forEach(release => {
|
||||
if (release && release.html_url) {
|
||||
if (release?.html_url) {
|
||||
const tableRow = document.createElement('tr');
|
||||
let tablerow = `<td><a href="${release.html_url}" target="_new">${release.tag_name}</a></td><td>${release.date}</td><td>${release.name}</td><td><button onclick="otamodule.updateESP('${release.bin_url}', true)">ESP32</button></td><td><button onclick="otamodule.updateWebpage('${release.file_url}','${release.tag_name}', true)">Filesystem</button></td>`;
|
||||
if (release.tag_name == currentVer) {
|
||||
@@ -163,7 +162,6 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
|
||||
});
|
||||
|
||||
const checkfiles = async (files) => {
|
||||
|
||||
const updateactions = files.find(files => files.name === "update_actions.json");
|
||||
if (updateactions) {
|
||||
await fetchAndPost(updateactions.url, updateactions.name, updateactions.path);
|
||||
@@ -173,7 +171,7 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
|
||||
body: ''
|
||||
});
|
||||
if (response.ok) {
|
||||
const data = await response.text();
|
||||
await response.text();
|
||||
} else {
|
||||
print(`error performing update actions: ${response.status}`, "red");
|
||||
errors++;
|
||||
@@ -227,12 +225,12 @@ export async function updateWebpage(fileUrl, tagname, showReload) {
|
||||
consoleDiv.appendChild(newLine);
|
||||
consoleDiv.scrollTop = consoleDiv.scrollHeight;
|
||||
}
|
||||
};
|
||||
};
|
||||
} catch (error) {
|
||||
print('Error: ' + error, "red");
|
||||
errors++;
|
||||
reject(error);
|
||||
}
|
||||
reject(error);
|
||||
}
|
||||
})();
|
||||
});
|
||||
}
|
||||
@@ -259,17 +257,16 @@ export async function updateESP(fileUrl, showConfirm) {
|
||||
while (retryCount < maxRetries) {
|
||||
try {
|
||||
const response = await fetch("/getexturl?url=" + fileUrl);
|
||||
|
||||
const responseBody = await response.text();
|
||||
if (!response.ok) {
|
||||
throw new Error("Network response was not OK");
|
||||
throw new Error("Network response was not OK: " + responseBody);
|
||||
}
|
||||
|
||||
const responseBody = await response.text();
|
||||
if (responseBody.trim()[0] !== "[") {
|
||||
if (!responseBody.trim().startsWith("[")) {
|
||||
throw new Error("Failed to fetch the release info file");
|
||||
}
|
||||
|
||||
const data = JSON.parse(responseBody);
|
||||
|
||||
const file = data.find((entry) => entry.name == env + '.bin');
|
||||
if (file) {
|
||||
binurl = file.url;
|
||||
@@ -291,7 +288,7 @@ export async function updateESP(fileUrl, showConfirm) {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.text();
|
||||
await response.text();
|
||||
print('OTA update initiated.');
|
||||
} else {
|
||||
print('Failed to initiate OTA update: ' + response.status, "red");
|
||||
@@ -313,7 +310,7 @@ export async function updateESP(fileUrl, showConfirm) {
|
||||
|
||||
if (retryCount === maxRetries) {
|
||||
print("Reached maximum retry count. Failed to execute the update.", "red");
|
||||
}
|
||||
}
|
||||
|
||||
running = false;
|
||||
disableButtons(false);
|
||||
@@ -327,9 +324,9 @@ $('#rollbackBtn').onclick = function () {
|
||||
errors = 0;
|
||||
const consoleDiv = document.getElementById('updateconsole');
|
||||
consoleDiv.scrollTop = consoleDiv.scrollHeight;
|
||||
|
||||
|
||||
print("Rolling back...");
|
||||
|
||||
|
||||
fetch("/rollback", {
|
||||
method: "POST",
|
||||
body: ''
|
||||
@@ -337,7 +334,6 @@ $('#rollbackBtn').onclick = function () {
|
||||
|
||||
running = false;
|
||||
disableButtons(false);
|
||||
|
||||
}
|
||||
|
||||
export function print(line, color = "white") {
|
||||
@@ -360,7 +356,7 @@ export function print(line, color = "white") {
|
||||
|
||||
export function reboot() {
|
||||
print("Rebooting now... Reloading webpage in 5 seconds...", "yellow");
|
||||
fetch("/reboot",{method: "POST"});
|
||||
fetch("/reboot", { method: "POST" });
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 5000);
|
||||
|
||||
41
ESP32_AP-Flasher/wwwroot/variables-demo.html
Normal file
41
ESP32_AP-Flasher/wwwroot/variables-demo.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Variables upload Form</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h3>demo Json variables</h3>
|
||||
<p>You can use this as an example how to change variables to be uses in a json template. Look at the html source for the workings. You can use the variables in any json template, using <pre>{variablename}</pre>. As soon as a variable is changed, the tag is being refreshed with the new info.</p>
|
||||
<p>
|
||||
Change one variable:<br>
|
||||
<form method="POST" action="/set_var">
|
||||
key: <input type="text" name="key" value="testkey"><br>
|
||||
value: <input type="text" name="val" value="MyCoolValue"><br>
|
||||
<input type="submit" value="submit"><br>
|
||||
</form>
|
||||
</p>
|
||||
<p>
|
||||
Change multiple variables, using json:<br>
|
||||
<form method="POST" action="/set_vars">
|
||||
<p>
|
||||
<label for="vars">Place the json string here</label><br>
|
||||
<textarea id="vars" name="json" style="width:500px;height:80px;">
|
||||
{ "temperature": 28.5,
|
||||
"door": "open",
|
||||
"testkey": "MyCoolValue"
|
||||
}
|
||||
</textarea>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<input type="submit" value="submit json">
|
||||
</p>
|
||||
|
||||
</form>
|
||||
</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
Hardware/3D-Printed/2-9_Solum_shelf_holder_2cm.3dm
Normal file
BIN
Hardware/3D-Printed/2-9_Solum_shelf_holder_2cm.3dm
Normal file
Binary file not shown.
BIN
Hardware/3D-Printed/2-9_Solum_shelf_holder_2cm.stl
Normal file
BIN
Hardware/3D-Printed/2-9_Solum_shelf_holder_2cm.stl
Normal file
Binary file not shown.
@@ -5,3 +5,5 @@
|
||||
There are holder and stands for every tag. 1.54", 2.9" and 4.2".
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user