72 Commits
2.60 ... 2.70

Author SHA1 Message Date
mhwlng
c1738936a9 change endianness lilygo t-panel in Arduino_ESP32RGBPanel to get rid of looping over all pixels (#388) 2024-11-03 19:33:29 +01:00
Nic Limper
4813f062f7 nightly reboot config option fix 2024-11-03 15:08:25 +01:00
Nic Limper
1052102032 improved AP status indicator 2024-11-03 13:33:30 +01:00
Jonas Niesner
61eb19dfe8 Enable S2 based APs in release scripts 2024-11-03 13:06:58 +01:00
Nic Limper
9eb0b303f3 breaking change for ESP32-S2 based AP's
- turn off Buienradar and Google Calendar content on ESP32-S2 based AP's because the firmware doesn't fit the flash memory anymore. If you need this and you use e.g. the mini AP v2, don't update. ESP32-S3 based AP's are not affected.
- On the update tab, the list of available versions now only shows the versions that are actually available for the build environment in use, so when we leave out S2-based builds in future releases, they won't show the new version.
2024-11-03 02:04:04 +01:00
Nic Limper
7abd5d9a84 painter now uses the color table of the tag instead of hardcoded black/red/white 2024-11-03 00:22:38 +01:00
Jonny Bergdahl
d4ccaf6027 Add option for AP discovery type (#351) 2024-11-02 23:10:00 +01:00
Nic Limper
a57c797542 various improvements, see desc
- nightly reboot is now optional (and rescheduled to 3:56 daily)
- lowbatt count in sys websocket messages (once a minute)
- new preview window, showing pending image on 1:1 size, great for debugging json template or other custom content. Right click tag and choose 'Tag preview'
2024-11-02 19:35:28 +01:00
Nic Limper
0cd76eebf0 smaller improvements
- dayahead Fixed surcharge now takes either one value (old behaviour) or an array with 24 elements for each hour, to add a surcharge depending on the time of day (as apparently they use in Denmark). The array should be entered like `[n,n,...,n]`
- added 1.54" template for dayahead prices
- in dayahead content, added option to only display the graph, without the current time/price/arrow. With this, the display only has to refresh one a day, which will save battery
- added the number of timedout tags to the 'sys' websocket message. The timeoutcount key/value is only present once a minute.
`{"sys":{"currtime":1730133055,"heap":194124,"recordcount":27,"dbsize":5488,"littlefsfree":5246976,"psfree":8350371,"apstate":1,"runstate":2,"rssi":-70,"wifistatus":3,"wifissid":"sensors","uptime":72,"timeoutcount":0}}`
- cosmetic: tagtype update now doesn't give an error when it tries to process readme.md
2024-10-28 17:40:40 +01:00
Nic Limper
d9a3bf8aac restrict fastled library version because of breaking change 2024-10-28 12:48:52 +01:00
Nic Limper
5e9238835e /save_cfg call: fixed crash by making all parameters optional 2024-10-28 11:58:50 +01:00
Nic Limper
dd5d96d1ee add dayahead prices to 4.2" displays; add custom interval to weather
don't forget to reboot the AP and clear browser cache after updating (or to open your browser developer tools and check 'disable cache' the first time you reload the UI)
2024-10-25 16:20:38 +02:00
atc1441
3f613407fe Update 03.json 2024-10-21 23:32:03 +02:00
atc1441
36f6705083 Update 03.json 2024-10-21 12:08:26 +02:00
atc1441
261aef13b4 Added 2 M2 Types 2024-10-21 09:13:01 +02:00
Skip Hansen
4c75234fa1 Enabled SubGhz support for ESP32_S3_C6_NANO_AP (thanks to discord user Ficu). 2024-10-10 11:42:29 -04:00
Magnus Erler
20e2106658 Update README.md (#381) 2024-10-08 12:36:03 +02:00
mhwlng
30bcd3b176 display brightness adjustment dropdown for lilygo panel now works gfx library now also supports t-panel LITE. fixed possible memory leak? (#378)
* display brightness adjustment dropdown now works

* add GFX library files for t-panel lite display controller

* add deleteSprilte after draw16bitRGBBitmap

* better handle t-panel LITE display

* file missing in last commit?
2024-10-06 13:07:23 +02:00
Jonas Niesner
8986967a4d Move Hardware directory to new separate repo (#377)
* Delete Hardware directory

* Create readme.md
2024-10-03 22:26:26 +02:00
Jonas Niesner
32072a3b25 Fix T-Panel AP builds (#373)
* Update release.yml

* Update conditional-build-test.yml

* fix builds for linux

* Update platformio.ini
2024-09-29 18:49:30 +02:00
mhwlng
8ff9826b3d add support for lilygo t-panel (#370)
* add support for lilygo t-panel

add support for lilygo t-panel (the rs485 version with an ESP32-S3 and ESP32-G2)
https://www.lilygo.cc/products/t-panel-s3

* refactor

* moved gfx library to lib2 folder and removed examples

* removed lib2\Arduino_GFX-1.3.7 and switch to moononournation/GFX Library for Arduino@^1.4.9

* added lilygo lib2\Arduino_GFX-1.3.7 back and removed all unused files. went from 166 files to 15 files!
2024-09-27 17:49:56 +02:00
atc1441
6a02f719da Added Gicisky TFT 2.13 Custom Firmware 2024-09-08 15:23:50 +02:00
atc1441
2a0c763ba0 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-09-05 19:59:11 +02:00
atc1441
e1f4384813 Added one tagtype and 7,5" TLSR Firmware update 2024-09-05 19:59:08 +02:00
Reletiv
c96f380346 Add skadis mount for nebular (#344)
Added universal mount for Hanshow Nebular models.
be aware of up/down click mechanism.
Use combined with t clip
2024-09-05 10:57:41 +02:00
atc1441
b3978fb3cf Create 68.json 2024-09-02 16:36:59 +02:00
atc1441
80a75d7df2 Added new AP types, TLSR and C6 Nano 2024-08-23 14:16:07 +02:00
atc1441
b5d8852bd5 Added 12" Stand 2024-08-21 20:27:55 +02:00
atc1441
41fef2834c Merge pull request #357 from quack3d/master
Remix of jjwbruijn's Yellow AP Case
2024-08-12 19:49:18 +02:00
sepodele
a7929010e8 Remix of jjwbruijn's Yellow AP Case
Remixed to support the size of a Spaghetti AP
2024-08-12 19:38:51 +02:00
atc1441
b3a34beaae Added HS BWY 20 Type and Firmware 2024-08-11 11:45:38 +02:00
atc1441
af04d39ecb Added new TLSR Type 2024-08-11 02:29:15 +02:00
atc1441
f8e6dea9ce Added types M3 OTA Version increase 2024-08-05 16:31:18 +02:00
atc1441
3eaa59cc18 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-08-04 19:42:54 +02:00
atc1441
169a2f5d5d Create 44.json 2024-08-04 19:42:34 +02:00
Skip Hansen
80cb4dc472 Added Chroma29 Flashing Jig by mindstormer7. 2024-08-04 10:37:08 -07:00
Skip Hansen
00d3e2b11c Added cc_interface.* files missed in earlier commit. 2024-07-30 09:54:21 -07:00
atc1441
90dd623d5b Create TLSR_Gicisky_BWR_29_ALPHA.bin 2024-07-30 16:41:02 +02:00
atc1441
acaa193093 Create TLSR_HS_BW_35_ALPHA.bin 2024-07-29 15:58:15 +02:00
atc1441
1f3962fbc9 Added CMD sending for 2 Tagtypes 2024-07-29 00:07:13 +02:00
atc1441
f9e73526df Increased thickness of YellowAP Printable Case because of new Ebyte module variant 2024-07-28 10:42:01 +02:00
Skip Hansen
73e472ec21 Added support for TI CCxxxx chips to Tag_Flasher, AP_and_Flasher and Mini_AP_v4. 2024-07-27 10:37:01 -07:00
atc1441
d0ccd8ff09 Added 3D Printable stand for 9.7" 2024-07-27 19:12:23 +02:00
atc1441
701f3a6429 Added Big AP 2024-07-26 12:27:19 +02:00
Skip Hansen
4276799777 Added chroma74y_ota_0007.bin missed in last commit. 2024-07-21 11:54:21 -07:00
Skip Hansen
cb4f3bdff0 Added v0007 chroma29r, chroma42 and chroma74y firmware images. 2024-07-20 07:02:51 -07:00
Skip Hansen
500f35f286 Modified auto update code to support chroma hardware variants. 2024-07-20 07:00:01 -07:00
Skip Hansen
be8ece2413 Remove "Ch" from SugGhz channel to fix LCD truncation on mini V4 AP. 2024-07-17 09:51:07 -07:00
atc1441
9fbafaf23e Changed repo to new repo organization in source 2024-07-17 00:07:45 +02:00
Skip Hansen
5c421648d1 Accept CC1101 chip version 4 was well as 20. Fixes Yellow APs
built with modules with older CC1101 chips.  Version 4 and 20
should cover all chips made from 2007 to 2021.
2024-07-16 13:48:04 -07:00
atc1441
fddf6169f1 Added 9.7" Case by Viktor Knall 2024-07-15 17:45:18 +02:00
atc1441
bf80cbff3e Create 2D.json 2024-07-13 20:36:51 +02:00
atc1441
76b6cc6d4c Update of release ESP32-C6 With SubGhz and Version increase 2024-07-11 20:04:23 +02:00
atc1441
ca657fd68c Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-07-11 00:07:06 +02:00
atc1441
309b76061d Fixed Position of GUI Text in CC Firmware 2024-07-11 00:07:00 +02:00
atc1441
cc6c0cb8f2 Fixed non working Zigbee and SubGhz 2024-07-10 10:15:05 -07:00
atc1441
8ba87800c1 Fixes some bugs in CC Display firmware 2024-07-10 14:05:03 +02:00
atc1441
2c04db25ec New Display cover for M2 4.2 2024-07-08 21:35:11 +02:00
Steven Cooreman
54bad5a08a Merge pull request #348 from stevew817/master
Add tag type for HD150 w/ modchip
2024-07-05 00:07:28 +02:00
Steven
2576043456 Add tag type 50 2024-07-04 23:06:06 +02:00
Jonas Niesner
468f6b77a1 Delete Hardware/9.7"_case directory 2024-07-01 22:56:18 +02:00
Jonas Niesner
0adf81ab79 Add 9.7" case 2024-06-30 17:53:56 +02:00
Skip Hansen
99fe067ba8 Another frequency error correction fix, FreqErr uint8_t -> uint8_t. 2024-06-26 09:21:59 -04:00
atc1441
79e3633e85 Addded 4.2" 3D Printed front made by Corwin 2024-06-24 23:40:31 +02:00
Stefan Krupop
8d0bd95288 Implement "erase" command to unprotect NRF52 based tags (#332) 2024-06-20 12:09:31 +02:00
Stefan Krupop
e22c40d097 Add small delay after powering on tag before accessing uC to allow voltage to stabilize (#331) 2024-06-20 12:07:51 +02:00
atc1441
f11f8e31fc Update syncedproto.c 2024-06-19 16:40:34 +02:00
Skip Hansen
564cd655fc Merge pull request #337 from mnyhlen/bugfix_calculating_nextcheckin
Bugfix: Update variable minutesUntilNextUpdate to 32-bit integer because of integer overflow
2024-06-15 09:02:56 -04:00
mnyhlen
6981171a6e Bugfix: Update variable minutesUntilNextUpdate to 32-bit integer because of integer overflow 2024-06-12 20:59:19 +02:00
Skip Hansen
1d1845580b Merge pull request #329 from skiphansen/oepl_pr_13
Change Fahrenheit/ mph /mm Units option to Fahrenheit / mph / in.
2024-06-04 08:23:18 -07:00
Skip Hansen
eca64ee3c3 Change Fahrenheit/ mph /mm Units option to Fahrenheit / mph / in. 2024-06-03 16:05:03 -07:00
Stefan Krupop
6a636b5b54 - ESP32_Flasher: Return new status "2" when connected, but nRF is locked (#327)
- OEPL-Flasher: Print "locked" message when flasher returns status 2
- ESP32_Flasher: Initialize idCode to zero as failed read attempts will not set it
- ESP32_Flasher: Print returned idCode when showDebug is enabled
2024-05-27 23:11:44 +02:00
379 changed files with 15077 additions and 183276 deletions

View File

@@ -66,8 +66,8 @@ jobs:
strategy:
matrix:
environment:
- OpenEPaperLink_Mini_AP
- OpenEPaperLink_AP_and_Flasher
#- OpenEPaperLink_Mini_AP
#- OpenEPaperLink_AP_and_Flasher
- ESP32_S3_16_8_YELLOW_AP
- OpenEPaperLink_Mini_AP_v4
runs-on: ubuntu-22.04

View File

@@ -41,16 +41,31 @@ jobs:
run: |
mkdir espbinaries
- name: esp-idf build
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: latest
target: esp32c6
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
#- name: esp-idf build
# uses: espressif/esp-idf-ci-action@v1
# with:
# esp_idf_version: latest
# target: esp32c6
# path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
# - name: esp-idf build
# uses: espressif/esp-idf-ci-action@v1
# with:
# esp_idf_version: latest
# target: esp32h2
# path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/'
#- name: Add C6 files to release
# run: |
# cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
#- name: Add H2 files to release
# run: |
# cd ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/
# dir build
# esptool.py --chip esp32h2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_size 4MB --flash_freq 48m 0x0 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0x10000 build/OpenEPaperLink_esp32_C6.bin
# cp merged-firmware.bin ../../espbinaries/OpenEPaperLink_esp32_H2.bin
- name: Add C6 files to release
run: |
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
# - name: Zip web files
# run: |
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
@@ -150,6 +165,42 @@ jobs:
cp ESP32_S3_C6_NANO_AP/firmware.bin espbinaries/ESP32_S3_C6_NANO_AP.bin
cp ESP32_S3_C6_NANO_AP/merged-firmware.bin espbinaries/ESP32_S3_C6_NANO_AP_full.bin
- name: Build firmware for ESP32_S3_16_8_LILYGO_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_16_8_LILYGO_AP
pio run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/boot_app0.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/firmware.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/bootloader.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/partitions.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_16_8_LILYGO_AP/firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP.bin
cp ESP32_S3_16_8_LILYGO_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP_full.bin
- name: Build firmware for OpenEPaperLink_Nano_TLSR
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Nano_TLSR
pio run --target buildfs --environment OpenEPaperLink_Nano_TLSR
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/boot_app0.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/firmware.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/bootloader.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/partitions.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Nano_TLSR/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR.bin
cp OpenEPaperLink_Nano_TLSR/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_full.bin
- name: Build firmware for OpenEPaperLink_PoE_AP
run: |
cd ESP32_AP-Flasher

3
.gitignore vendored
View File

@@ -31,3 +31,6 @@ $PROJECT_DIR/
# OS generated files
.DS_Store
# Jetbrains IDE
.idea/

View File

@@ -306,7 +306,7 @@ static bool blockRxLoop(const uint32_t timeout)
bool success = false;
// radioRxEnable(true);
uint32_t t = clock_time();
while (!clock_time_exceed(t, 2000 * 1000))
while (!clock_time_exceed(t, timeout * 1000)) // 300 ms is enough here
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
@@ -611,7 +611,7 @@ static bool getDataBlock(const uint16_t blockSize)
{
// immediately start with the reception of the block data
}
blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed
blockRxLoop(300); // BLOCK RX LOOP - receive a block, until the timeout has passed
#ifdef DEBUGBLOCKS
printf("RX %d[", curBlock.blockId);

View File

@@ -0,0 +1,42 @@
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
idf.py fullclean
idf.py build
#python -m esptool -p COM8 -b 460800 --before default_reset --after hard_reset --chip esp32c6 write_flash --flash_mode dio --flash_size detect --flash_freq 80m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_C6.bin
#idf.py -p COM8 flash
#esptool.py v4.7.0
#Serial port COM8
#Connecting...
#Chip is ESP32-C6 (QFN40) (revision v0.0)
#Features: WiFi 6, BT 5, IEEE802.15.4
#Crystal is 40MHz
#MAC: 40:4c:ca:ff:fe:47:b4:f0
#BASE MAC: 40:4c:ca:47:b4:f0
#MAC_EXT: ff:fe
#Uploading stub...
#Running stub...
#Stub running...
#Changing baud rate to 460800
#Changed.
#Configuring flash size...
#Auto-detected Flash size: 4MB
#Flash will be erased from 0x00000000 to 0x00005fff...
#Flash will be erased from 0x00008000 to 0x00008fff...
#Flash will be erased from 0x00010000 to 0x00051fff...
#Compressed 22336 bytes to 13474...
#Wrote 22336 bytes (13474 compressed) at 0x00000000 in 0.3 seconds (effective 624.9 kbit/s)...
#Hash of data verified.
#Compressed 3072 bytes to 104...
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 361.3 kbit/s)...
#Hash of data verified.
#Compressed 268624 bytes to 140956...
#Wrote 268624 bytes (140956 compressed) at 0x00010000 in 1.2 seconds (effective 1725.6 kbit/s)...
#Hash of data verified.
#Leaving...
#Hard resetting via RTS pin...

View File

@@ -627,7 +627,7 @@ int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
uint8_t Rssi;
uint8_t Lqi;
int Ret;
uint8_t FreqErr;
int8_t FreqErr;
int8_t FreqCorrection;
// Any data waiting to be read and no overflow?
@@ -672,22 +672,19 @@ int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
if(pLqi != NULL) {
*pLqi = Lqi & CC1101_LQI_MASK;
}
FreqErr = CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
if(FreqErr != 0) {
FreqErr += gFreqCorrection;
if(gFreqErrSumCount < 255) {
gFreqErrSum += FreqErr;
gFreqErrSumCount++;
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
if(gFreqCorrection != FreqCorrection) {
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
gFreqCorrection = FreqCorrection;
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
}
if(gFreqErrSumCount == 255) {
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
}
}
FreqErr = (int8_t) CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
if(FreqErr != 0 && gFreqErrSumCount < 255) {
gFreqErrSum += FreqErr + gFreqCorrection;
gFreqErrSumCount++;
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
if(gFreqCorrection != FreqCorrection) {
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
gFreqCorrection = FreqCorrection;
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
}
if(gFreqErrSumCount == 255) {
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
}
}
} while(false);
@@ -704,10 +701,18 @@ bool CC1101_Present()
uint8_t PartNum = CC1101_readReg(CC1101_PARTNUM, CC1101_STATUS_REGISTER);
uint8_t ChipVersion = CC1101_readReg(CC1101_VERSION, CC1101_STATUS_REGISTER);
if(PartNum == 0 && ChipVersion == 20) {
if(PartNum == 0 && (ChipVersion == 20 || ChipVersion == 4)) {
LOGA("CC1101 detected\n");
Ret = true;
}
else {
if(PartNum != 0) {
LOGA("Invalid PartNum 0x%x\n",PartNum);
}
else {
LOGA("Invalid or unsupported ChipVersion 0x%x\n",ChipVersion);
}
}
return Ret;
}

View File

@@ -42,7 +42,7 @@ const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
struct pendingData pendingDataArr[MAX_PENDING_MACS];
// VERSION GOES HERE!
uint16_t version = 0x0019;
uint16_t version = 0x001d;
#define RAW_PKT_PADDING 2

View File

@@ -32,7 +32,6 @@ static const char *TAG = "RADIO";
uint8_t mSelfMac[8];
volatile uint8_t isInTransmit = 0;
QueueHandle_t packet_buffer = NULL;
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
ESP_EARLY_LOGI(TAG, "RX %d", frame[0]);
BaseType_t xHigherPriorityTaskWoken;
@@ -40,6 +39,7 @@ void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *fr
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
esp_ieee802154_receive_sfd_done();
}
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
@@ -50,12 +50,19 @@ void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_erro
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
isInTransmit = 0;
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
esp_ieee802154_receive_sfd_done();
}
static bool zigbee_is_enabled = false;
void radio_init(uint8_t ch) {
if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130);
// this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works
if(zigbee_is_enabled)
{
zigbee_is_enabled = false;
esp_ieee802154_disable();
}
zigbee_is_enabled = true;
esp_ieee802154_enable();
esp_ieee802154_set_channel(ch);
// esp_ieee802154_set_txpower(int8_t power);
@@ -101,8 +108,6 @@ bool radioTx(uint8_t *packet) {
static uint8_t txPKT[130];
#endif
led_flash(1);
while (isInTransmit) {
}
// while (getMillis() - lastZbTx < 6) {
// }
// lastZbTx = getMillis();
@@ -114,6 +119,8 @@ bool radioTx(uint8_t *packet) {
return SubGig_radioTx(packet);
}
#endif
while (isInTransmit) {
}
isInTransmit = 1;
esp_ieee802154_transmit(txPKT, false);
return true;

View File

@@ -0,0 +1,8 @@
build
*.axf
# Allow
!*.bin
.vscode
sdkconfig
sdkconfig.old

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(OpenEPaperLink_esp32_C6)

View File

@@ -0,0 +1,45 @@
#| Function | ESP32H2 Pin | ESP32S3 Pin
#| :--------------------------------: | :-------------------: | :------------------
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
&(Join-Path $env:USERPROFILE '\esp\esp-idf\export.ps1')
idf.py fullclean
idf.py build
#python -m esptool -p COM11 -b 460800 --before default_reset --after hard_reset --chip esp32h2 write_flash --flash_mode dio --flash_size detect --flash_freq 48m 0x0 build\bootloader\bootloader.bin 0x8000 build\partition_table\partition-table.bin 0x10000 build\OpenEPaperLink_esp32_H2.bin
#idf.py -p COM8 flash
#Chip is ESP32-H2 (revision v0.1)
#Features: BLE, IEEE802.15.4
#Crystal is 32MHz
#MAC: 74:4d:bd:ff:fe:63:84:e8
#BASE MAC: 74:4d:bd:63:84:e8
#MAC_EXT: ff:fe
#Uploading stub...
#Running stub...
#Stub running...
#Changing baud rate to 460800
#Changed.
#Configuring flash size...
#Auto-detected Flash size: 4MB
#Flash will be erased from 0x00000000 to 0x00005fff...
#Flash will be erased from 0x00008000 to 0x00008fff...
#Flash will be erased from 0x00010000 to 0x0004dfff...
#Compressed 22080 bytes to 13385...
#Wrote 22080 bytes (13385 compressed) at 0x00000000 in 0.3 seconds (effective 511.5 kbit/s)...
#Hash of data verified.
#Compressed 3072 bytes to 104...
#Wrote 3072 bytes (104 compressed) at 0x00008000 in 0.1 seconds (effective 309.1 kbit/s)...
#Hash of data verified.
#Compressed 253952 bytes to 133359...
#Wrote 253952 bytes (133359 compressed) at 0x00010000 in 1.9 seconds (effective 1098.1 kbit/s)...
#Hash of data verified.

View File

@@ -0,0 +1,9 @@
idf_component_register( SRCS
SRCS "utils.c"
SRCS "second_uart.c"
SRCS "radio.c"
SRCS "SubGigRadio.c"
SRCS "cc1101_radio.c"
SRCS "led.c"
SRCS "main.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,104 @@
menu "OEPL Hardware config"
choice OEPL_HARDWARE_PROFILE
prompt "Hardware profile"
default OEPL_HARDWARE_PROFILE_DEFAULT
config OEPL_HARDWARE_PROFILE_DEFAULT
bool "Default"
config OEPL_HARDWARE_PROFILE_POE_AP
bool "PoE-AP"
config OEPL_HARDWARE_PROFILE_CUSTOM
bool "Custom"
endchoice
config OEPL_HARDWARE_UART_TX
depends on OEPL_HARDWARE_PROFILE_CUSTOM
int "GPIO - UART TX"
default 3
config OEPL_HARDWARE_UART_RX
depends on OEPL_HARDWARE_PROFILE_CUSTOM
int "GPIO - UART RX"
default 2
config OEPL_SUBGIG_SUPPORT
bool "Enable SubGhz Support"
default "n"
menu "CC1101 Configuration"
depends on OEPL_SUBGIG_SUPPORT
config GPIO_RANGE_MAX
int
default 33 if IDF_TARGET_ESP32
default 46 if IDF_TARGET_ESP32S2
default 48 if IDF_TARGET_ESP32S3
default 18 if IDF_TARGET_ESP32C2
default 19 if IDF_TARGET_ESP32C3
default 30 if IDF_TARGET_ESP32C6
default 30 if IDF_TARGET_ESP32H2
config MISO_GPIO
int "CC1101 MISO GPIO"
range 0 GPIO_RANGE_MAX
default 7
help
Pin Number to be used as the MISO SPI signal.
config SCK_GPIO
int "CC1101 SCK GPIO"
range 0 GPIO_RANGE_MAX
default 0
help
Pin Number to be used as the SCK SPI signal.
config MOSI_GPIO
int "CC1101 MOSI GPIO"
default 1
help
Pin Number to be used as the MOSI SPI signal.
config CSN_GPIO
int "CC1101 CSN GPIO"
range 0 GPIO_RANGE_MAX
default 4
help
Pin Number to be used as the CSN SPI signal.
config GDO0_GPIO
int "CC1101 GDO0 GPIO"
range 0 GPIO_RANGE_MAX
default 5
help
Pin Number to be used as the GDO0 signal.
config GDO2_GPIO
int "CC1101 GDO2 GPIO"
range 0 GPIO_RANGE_MAX
default 6
help
Pin Number to be used as the GDO2 signal.
choice SPI_HOST
prompt "SPI peripheral that controls this bus"
default SPI2_HOST
help
Select SPI peripheral that controls this bus.
config SPI2_HOST
bool "SPI2_HOST"
help
Use SPI2_HOST. This is also called HSPI_HOST.
config SPI3_HOST
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
bool "SPI3_HOST"
help
USE SPI3_HOST. This is also called VSPI_HOST
endchoice
endmenu
endmenu

View File

@@ -0,0 +1,562 @@
#include "sdkconfig.h"
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include "esp_log.h"
#include "radio.h"
#include "proto.h"
#include "cc1101_radio.h"
#include "SubGigRadio.h"
void DumpHex(void *AdrIn,int Len);
#define LOGE(format, ... ) \
printf("%s#%d: " format,__FUNCTION__,__LINE__,## __VA_ARGS__)
#if 0
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
#define LOG_HEX(x,y) DumpHex(x,y)
#else
#define LOG(format, ... )
#define LOG_RAW(format, ... )
#define LOG_HEX(x,y)
#endif
// SPI Stuff
#if CONFIG_SPI2_HOST
#define HOST_ID SPI2_HOST
#elif CONFIG_SPI3_HOST
#define HOST_ID SPI3_HOST
#endif
// Address Config = No address check
// Base Frequency = xxx.xxx
// CRC Enable = false
// Carrier Frequency = 915.000000
// Channel Number = 0
// Channel Spacing = 199.951172
// Data Rate = 1.19948
// Deviation = 5.157471
// Device Address = 0
// Manchester Enable = false
// Modulated = false
// Modulation Format = ASK/OOK
// PA Ramping = false
// Packet Length = 255
// Packet Length Mode = Reserved
// Preamble Count = 4
// RX Filter BW = 58.035714
// Sync Word Qualifier Mode = No preamble/sync
// TX Power = 10
// Whitening = false
// Rf settings for CC1110
const RfSetting gCW[] = {
{CC1101_PKTCTRL0,0x22}, // PKTCTRL0: Packet Automation Control
{CC1101_FSCTRL1,0x06}, // FSCTRL1: Frequency Synthesizer Control
{CC1101_MDMCFG4,0xF5}, // MDMCFG4: Modem configuration
{CC1101_MDMCFG3,0x83}, // MDMCFG3: Modem Configuration
{CC1101_MDMCFG2,0xb0}, // MDMCFG2: Modem Configuration
{CC1101_DEVIATN,0x15}, // DEVIATN: Modem Deviation Setting
{CC1101_MCSM0,0x18}, // MCSM0: Main Radio Control State Machine Configuration
{CC1101_FOCCFG,0x17}, // FOCCFG: Frequency Offset Compensation Configuration
{CC1101_FSCAL3,0xE9}, // FSCAL3: Frequency Synthesizer Calibration
{CC1101_FSCAL2,0x2A}, // FSCAL2: Frequency Synthesizer Calibration
{CC1101_FSCAL1,0x00}, // FSCAL1: Frequency Synthesizer Calibration
{CC1101_FSCAL0,0x1F}, // FSCAL0: Frequency Synthesizer Calibration
{CC1101_TEST1,0x31}, // TEST1: Various Test Settings
{CC1101_TEST0,0x09}, // TEST0: Various Test Settings
{0xff,0} // end of table
};
// Set Base Frequency to 865.999634
const RfSetting g866Mhz[] = {
{CC1101_FREQ2,0x21}, // FREQ2: Frequency Control Word, High Byte
{CC1101_FREQ1,0x4e}, // FREQ1: Frequency Control Word, Middle Byte
{CC1101_FREQ0,0xc4}, // FREQ0: Frequency Control Word, Low Byte
{0xff,0} // end of table
};
// Set Base Frequency to 863.999756
const RfSetting g864Mhz[] = {
{CC1101_FREQ2,0x21}, // FREQ2: Frequency Control Word, High Byte
{CC1101_FREQ1,0x3b}, // FREQ1: Frequency Control Word, Middle Byte
{CC1101_FREQ0,0x13}, // FREQ0: Frequency Control Word, Low Byte
{0xff,0} // end of table
};
// Set Base Frequency to 902.999756
const RfSetting g903Mhz[] = {
{CC1101_FREQ2,0x22}, // FREQ2: Frequency Control Word, High Byte
{CC1101_FREQ1,0xbb}, // FREQ1: Frequency Control Word, Middle Byte
{CC1101_FREQ0,0x13}, // FREQ0: Frequency Control Word, Low Byte
{0xff,0} // end of table
};
// Seet Base Frequency to 915.000000
const RfSetting g915Mhz[] = {
{CC1101_FREQ2,0x23}, // FREQ2: Frequency Control Word, High Byte
{CC1101_FREQ1,0x31}, // FREQ1: Frequency Control Word, Middle Byte
{CC1101_FREQ0,0x3B}, // FREQ0: Frequency Control Word, Low Byte
{0xff,0} // end of table
};
// Address Config = No address check
// Base Frequency = 901.934937 (adjusted to compensate for the crappy crystal on the CC1101 board)
// CRC Enable = true
// Carrier Frequency = 901.934937
// Channel Number = 0
// Channel Spacing = 199.951172
// Data Rate = 38.3835
// Deviation = 20.629883
// Device Address = ff
// Manchester Enable = false
// Modulated = true
// Modulation Format = GFSK
// PA Ramping = false
// Packet Length = 61
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
// Preamble Count = 4
// RX Filter BW = 101.562500
// Sync Word Qualifier Mode = 30/32 sync word bits detected
// TX Power = 10
// Whitening = false
// The following was generated by setting the spec for Register to "{CC1101_@RN@,0x@VH@},"
const RfSetting gIDF_Basic[] = {
{CC1101_SYNC1,0xC7},
{CC1101_SYNC0,0x0A},
{CC1101_PKTLEN,0x3D},
{CC1101_PKTCTRL0,0x05},
{CC1101_ADDR,0xFF},
{CC1101_FSCTRL1,0x08},
{CC1101_FREQ2,0x22},
{CC1101_FREQ1,0xB1},
{CC1101_FREQ0,0x3B},
{CC1101_MDMCFG4,0xCA},
{CC1101_MDMCFG3,0x83},
{CC1101_MDMCFG2,0x93},
{CC1101_DEVIATN,0x35},
// {CC1101_MCSM0,0x18}, FS_AUTOCAL = 1, PO_TIMEOUT = 2
{CC1101_MCSM0,0x18},
{CC1101_FOCCFG,0x16},
{CC1101_AGCCTRL2,0x43},
{CC1101_FSCAL3,0xEF},
{CC1101_FSCAL2,0x2D},
{CC1101_FSCAL1,0x25},
{CC1101_FSCAL0,0x1F},
{CC1101_TEST2,0x81},
{CC1101_TEST1,0x35},
{CC1101_TEST0,0x09},
{0xff,0} // end of table
};
// RF configuration from Dimitry's orginal code
// Address Config = No address check
// Base Frequency = 902.999756
// CRC Autoflush = false
// CRC Enable = true
// Carrier Frequency = 902.999756
// Channel Number = 0
// Channel Spacing = 335.632324
// Data Format = Normal mode
// Data Rate = 249.939
// Deviation = 165.039063
// Device Address = 22
// Manchester Enable = false
// Modulated = true
// Modulation Format = GFSK
// PA Ramping = false
// Packet Length = 255
// Packet Length Mode = Variable packet length mode. Packet length configured by the first byte after sync word
// Preamble Count = 24
// RX Filter BW = 650.000000
// Sync Word Qualifier Mode = 30/32 sync word bits detected
// TX Power = 0
// Whitening = true
// Rf settings for CC1101
// The following was generated by setting the spec for Register to "{CC1101_@RN@,0x@VH@},"
const RfSetting gDmitry915[] = {
{CC1101_FREQ2,0x22},
{CC1101_FREQ1,0xBB},
{CC1101_FREQ0,0x13},
{CC1101_MDMCFG4,0x1D},
{CC1101_MDMCFG3,0x3B},
{CC1101_MDMCFG2,0x13},
{CC1101_MDMCFG1,0x73},
{CC1101_MDMCFG0,0xA7},
{CC1101_DEVIATN,0x65},
{CC1101_MCSM0,0x18},
{CC1101_FOCCFG,0x1E},
{CC1101_BSCFG,0x1C},
{CC1101_AGCCTRL2,0xC7},
{CC1101_AGCCTRL1,0x00},
{CC1101_AGCCTRL0,0xB0},
{CC1101_FREND1,0xB6},
{CC1101_FSCAL3,0xEA},
{CC1101_FSCAL2,0x2A},
{CC1101_FSCAL1,0x00},
{CC1101_FSCAL0,0x1F},
{CC1101_TEST0,0x09},
{0xff,0} // end of table
};
SubGigData gSubGigData;
int CheckSubGigState(void);
void SubGig_CC1101_reset(void);
void SubGig_CC1101_SetConfig(const RfSetting *pConfig);
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
gSubGigData.RxAvailable = true;
}
// return SUBGIG_ERR_NONE aka ESP_OK aka 0 if CC1101 is detected and all is good
SubGigErr SubGig_radio_init(uint8_t ch)
{
esp_err_t Err;
spi_device_interface_config_t devcfg = {
.clock_speed_hz = 5000000, // SPI clock is 5 MHz!
.queue_size = 7,
.mode = 0, // SPI mode 0
.spics_io_num = -1, // we will use manual CS control
.flags = SPI_DEVICE_NO_DUMMY
};
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_NEGEDGE, // GPIO interrupt type : falling edge
//bit mask of the pins
.pin_bit_mask = 1ULL<<CONFIG_GDO0_GPIO,
//set as input mode
.mode = GPIO_MODE_INPUT,
//enable pull-up mode
.pull_up_en = 1,
.pull_down_en = 0
};
int ErrLine = 0;
SubGigErr Ret = SUBGIG_ERR_NONE;
do {
gpio_reset_pin(CONFIG_CSN_GPIO);
gpio_set_direction(CONFIG_CSN_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(CONFIG_CSN_GPIO, 1);
spi_bus_config_t buscfg = {
.sclk_io_num = CONFIG_SCK_GPIO,
.mosi_io_num = CONFIG_MOSI_GPIO,
.miso_io_num = CONFIG_MISO_GPIO,
.quadwp_io_num = -1,
.quadhd_io_num = -1
};
if((Err = spi_bus_initialize(HOST_ID,&buscfg,SPI_DMA_CH_AUTO)) != 0) {
ErrLine = __LINE__;
break;
}
if((Err = spi_bus_add_device(HOST_ID,&devcfg,&gSpiHndl)) != 0) {
ErrLine = __LINE__;
break;
}
// Configure GDO0, interrupt on falling edge
if((Err = gpio_config(&io_conf)) != 0) {
ErrLine = __LINE__;
break;
}
// Configure GDO2, interrupts disabled
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.pin_bit_mask = 1ULL<<CONFIG_GDO2_GPIO;
if((Err = gpio_config(&io_conf)) != 0) {
ErrLine = __LINE__;
break;
}
// install gpio isr service
if((Err = gpio_install_isr_service(0)) != 0) {
ErrLine = __LINE__;
break;
}
//hook isr handler for specific gpio pin
Err = gpio_isr_handler_add(CONFIG_GDO0_GPIO,gpio_isr_handler,
(void*) CONFIG_GDO0_GPIO);
if(Err != 0) {
ErrLine = __LINE__;
break;
}
// Check Chip ID
if(!CC1101_Present()) {
Ret = SUBGIG_CC1101_NOT_FOUND;
break;
}
gSubGigData.Present = true;
SubGig_CC1101_reset();
CC1101_SetConfig(NULL);
SubGig_CC1101_SetConfig(gDmitry915);
#if 0
CC1101_DumpRegs();
#endif
if(ch != 0) {
SubGig_radioSetChannel(ch);
}
// good to go!
} while(false);
if(ErrLine != 0) {
LOG("%s#%d: failed %d\n",__FUNCTION__,ErrLine,Err);
if(Err == 0) {
Ret = ESP_FAIL;
}
}
return Ret;
}
SubGigErr SubGig_radioSetChannel(uint8_t ch)
{
SubGigErr Ret = SUBGIG_ERR_NONE;
RfSetting SetChannr[2] = {
{CC1101_CHANNR,0},
{0xff,0} // end of table
};
do {
if(!gSubGigData.Enabled && gSubGigData.Present && ch != 0) {
gSubGigData.Enabled = true;
LOG("SubGhz enabled\n");
}
if((Ret = CheckSubGigState()) != SUBGIG_ERR_NONE) {
break;
}
if(ch == 0) {
// Disable SubGhz
LOG("SubGhz disabled\n");
gSubGigData.Enabled = false;
break;
}
LOG("Set channel %d\n",ch);
if(ch >= FIRST_866_CHAN && ch < FIRST_866_CHAN + NUM_866_CHANNELS) {
// Base Frequency = 863.999756
// total channels 6 (0 -> 5) (CHANNR 0 -> 15)
// Channel 100 / CHANNR 0: 863.999756
// Channel 101 / CHANNR 3: 865.006 Mhz
// Channel 102 / CHANNR 6: 866.014 Mhz
// Channel 103 / CHANNR 9: 867.020 Mhz
// Channel 104 / CHANNR 12: 868.027 Mhz
// Channel 105 / CHANNR 15: 869.034 Mhz
SubGig_CC1101_SetConfig(g864Mhz);
SetChannr[0].Value = (ch - FIRST_866_CHAN) * 3;
}
else {
// Base Frequency = 902.999756
// Dmitry's orginal code used 25 channels in 915 Mhz
// We don't want to have to scan that many so for OEPL we'll just use 6
// to match 866.
// Channel 200 / CHANNR 0: 903.000 Mhz
// Channel 201 / CHANNR 12: 907.027 Mhz
// Channel 202 / CHANNR 24: 911.054 Mhz
// Channel 203 / CHANNR 24: 915.083 Mhz
// Channel 204 / CHANNR 48: 919.110 Mhz
// Channel 205 / CHANNR 60: 923.138 Mhz
SubGig_CC1101_SetConfig(g903Mhz);
if(ch >= FIRST_915_CHAN && ch < FIRST_915_CHAN + NUM_915_CHANNELS) {
SetChannr[0].Value = (ch - FIRST_915_CHAN) * 12;
}
else {
Ret = SUBGIG_INVALID_CHANNEL;
SetChannr[0].Value = 0; // default to the first channel on 915
}
}
SubGig_CC1101_SetConfig(SetChannr);
CC1101_setRxState();
} while(false);
return Ret;
}
SubGigErr SubGig_radioTx(uint8_t *packet)
{
SubGigErr Ret = SUBGIG_ERR_NONE;
do {
if(gSubGigData.FreqTest) {
break;
}
if((Ret = CheckSubGigState()) != SUBGIG_ERR_NONE) {
break;
}
if(packet[0] < 3 || packet[0] > RADIO_MAX_PACKET_LEN + RAW_PKT_PADDING) {
Ret = SUBGIG_TX_BAD_LEN;
break;
}
// All packets seem to be padded by RAW_PKT_PADDING (2 bytes)
// Remove the padding before sending so the length is correct when received
packet[0] -= RAW_PKT_PADDING;
LOG("Sending %d byte subgig frame:\n",packet[0]);
LOG_HEX(&packet[1],packet[0]);
if(CC1101_Tx(packet)) {
Ret = SUBGIG_TX_FAILED;
}
// Clear RxAvailable, in TX GDO0 deasserts on TX FIFO underflows
gSubGigData.RxAvailable = false;
// restore original len just in case anyone cares
packet[0] += RAW_PKT_PADDING;
} while(false);
return Ret;
}
// returns packet size in bytes data in data
int8_t SubGig_commsRxUnencrypted(uint8_t *data)
{
int RxBytes;
int8_t Ret = 0;
do {
if(CheckSubGigState() != SUBGIG_ERR_NONE) {
break;
}
if(gSubGigData.FreqTest) {
break;
}
CC1101_logState();
if(!gSubGigData.RxAvailable && gpio_get_level(CONFIG_GDO0_GPIO) == 1) {
// Did we miss an interrupt?
if(gpio_get_level(CONFIG_GDO0_GPIO) == 1) {
// Yup!
LOGE("SubGhz lost interrupt\n");
gSubGigData.RxAvailable = true;
}
}
if(gSubGigData.RxAvailable){
gSubGigData.RxAvailable = false;
RxBytes = CC1101_Rx(data,128,NULL,NULL);
if(RxBytes >= 2) {
// NB: RxBytes includes the CRC, deduct it
Ret = (uint8_t) RxBytes - 2;
LOG("Received %d byte subgig frame:\n",Ret);
LOG_HEX(data,Ret);
}
}
} while(false);
return Ret;
}
int CheckSubGigState()
{
int Err = SUBGIG_ERR_NONE;
if(!gSubGigData.Present) {
Err = SUBGIG_CC1101_NOT_FOUND;
}
else if(!gSubGigData.Initialized) {
Err = SUBGIG_NOT_INITIALIZED;
}
else if(!gSubGigData.Enabled) {
Err = SUBGIG_NOT_ENABLED;
}
if(Err != SUBGIG_ERR_NONE) {
LOG("CheckSubGigState: returing %d\n",Err);
}
return Err;
}
SubGigErr SubGig_FreqTest(bool b866Mhz,bool bStart)
{
SubGigErr Err = SUBGIG_ERR_NONE;
#if 0
uint8_t TxData = 0; // len = 0
do {
if((Err = CheckSubGigState()) != SUBGIG_ERR_NONE) {
break;
}
if(bStart) {
LOG_RAW("Starting %sMhz Freq test\n",b866Mhz ? "866" : "915");
SubGig_CC1101_reset();
SubGig_CC1101_SetConfig(gCW);
SubGig_CC1101_SetConfig(b866Mhz ? g866Mhz : g915Mhz);
CC1101_cmdStrobe(CC1101_SIDLE);
CC1101_cmdStrobe(CC1101_SFTX); // flush Tx Fifo
CC1101_cmdStrobe(CC1101_STX);
gRfState = RFSTATE_TX;
gSubGigData.FreqTest = true;
}
else {
LOG_RAW("Ending Freq test\n");
gSubGigData.FreqTest = false;
SubGig_CC1101_reset();
SubGig_CC1101_SetConfig(gSubGigData.pConfig);
}
} while(false);
#endif
return Err;
}
void SubGig_CC1101_reset()
{
gSubGigData.Initialized = false;
gSubGigData.FixedRegsSet = false;
CC1101_reset();
}
void SubGig_CC1101_SetConfig(const RfSetting *pConfig)
{
CC1101_SetConfig(pConfig);
gSubGigData.Initialized = true;
}
void DumpHex(void *AdrIn,int Len)
{
unsigned char *Adr = (unsigned char *) AdrIn;
int i = 0;
int j;
while(i < Len) {
for(j = 0; j < 16; j++) {
if((i + j) == Len) {
break;
}
LOG_RAW("%02x ",Adr[i+j]);
}
LOG_RAW(" ");
for(j = 0; j < 16; j++) {
if((i + j) == Len) {
break;
}
if(isprint(Adr[i+j])) {
LOG_RAW("%c",Adr[i+j]);
}
else {
LOG_RAW(".");
}
}
i += 16;
LOG_RAW("\n");
}
}
#endif // CONFIG_OEPL_SUBGIG_SUPPORT

View File

@@ -0,0 +1,40 @@
#ifndef _SUBGIG_RADIO_H_
#define _SUBGIG_RADIO_H_
//sub-GHz 866 Mhz channels start at 100
#define FIRST_866_CHAN (100)
#define NUM_866_CHANNELS (6)
//sub-GHz 915 Mhz channels start at 200
#define FIRST_915_CHAN (200)
#define NUM_915_CHANNELS (6)
typedef enum {
SUBGIG_ERR_NONE,
SUBGIG_CC1101_NOT_FOUND,
SUBGIG_NOT_INITIALIZED,
SUBGIG_NOT_ENABLED,
SUBGIG_TX_FAILED,
SUBGIG_TX_BAD_LEN,
SUBGIG_INVALID_CHANNEL,
} SubGigErr;
typedef struct {
uint8_t Present:1;
uint8_t Enabled:1;
uint8_t FreqTest:1;
uint8_t RxAvailable:1;
uint8_t Initialized:1;
uint8_t FixedRegsSet:1;
} SubGigData;
extern SubGigData gSubGigData;
SubGigErr SubGig_radio_init(uint8_t ch);
SubGigErr SubGig_radioTx(uint8_t *packet);
SubGigErr SubGig_radioSetChannel(uint8_t ch);
int8_t SubGig_commsRxUnencrypted(uint8_t *data);
SubGigErr SubGig_FreqTest(bool b866Mhz,bool bStart);
#endif // _SUBGIG_RADIO_H_

View File

@@ -0,0 +1,790 @@
// Large portions of this code was copied from:
// https://github.com/nopnop2002/esp-idf-cc1101 with the following copyright
/*
* Copyright (c) 2011 panStamp <contact@panstamp.com>
* Copyright (c) 2016 Tyler Sommer <contact@tylersommer.pro>
*
* This file is part of the CC1101 project.
*
* CC1101 is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* CC1101 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CC1101; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*
* Author: Daniel Berenguer
* Creation date: 03/03/2011
*/
#include "sdkconfig.h"
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <driver/spi_master.h>
#include "proto.h"
#include "cc1101_radio.h"
#include "radio.h"
#define ENABLE_LOGGING 0
// LOGA - generic logging, always enabled
#define LOGA(format, ... ) printf(format,## __VA_ARGS__)
// LOGE - error logging, always enabled
#define LOGE(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
#if ENABLE_LOGGING
#define LOG(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
#define LOG_RAW(format, ... ) printf(format,## __VA_ARGS__)
#else
#define LOG(format, ... )
#define LOG_RAW(format, ... )
#endif
#define ENABLE_VERBOSE_LOGGING 0
#if ENABLE_VERBOSE_LOGGING
#define LOGV(format, ... ) printf("%s: " format,__FUNCTION__,## __VA_ARGS__)
#define LOGV_RAW(format, ... ) printf(format,## __VA_ARGS__)
#else
#define LOGV(format, ... )
#define LOGB_RAW(format, ... )
#endif
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include "esp_log.h"
#include "sdkconfig.h"
/**
* RF STATES
*/
enum RFSTATE {
RFSTATE_IDLE = 0,
RFSTATE_RX,
RFSTATE_TX
};
/**
* Type of transfers
*/
#define WRITE_BURST 0x40
#define READ_SINGLE 0x80
#define READ_BURST 0xC0
/**
* Type of register
*/
#define CC1101_CONFIG_REGISTER READ_SINGLE
#define CC1101_STATUS_REGISTER READ_BURST
/**
* PATABLE & FIFO's
*/
#define CC1101_PATABLE 0x3E // PATABLE address
#define CC1101_TXFIFO 0x3F // TX FIFO address
#define CC1101_RXFIFO 0x3F // RX FIFO address
/**
* Command strobes
*/
#define CC1101_SRES 0x30 // Reset CC1101 chip
#define CC1101_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA):
// Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround).
#define CC1101_SXOFF 0x32 // Turn off crystal oscillator
#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without
// setting manual calibration mode (MCSM0.FS_AUTOCAL=0)
#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1
#define CC1101_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1.
// If in RX state and CCA is enabled: Only go to TX if channel is clear
#define CC1101_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable
#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if
// WORCTRL.RC_PD=0
#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high
#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states
#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states
#define CC1101_SWORRST 0x3C // Reset real time clock to Event1 value
#define CC1101_SNOP 0x3D // No operation. May be used to get access to the chip status byte
#define CC1101_STATE_SLEEP 0x00
#define CC1101_STATE_IDLE 0x01
#define CC1101_STATE_XOFF 0x02
#define CC1101_STATE_VCOON_MC 0x03
#define CC1101_STATE_REGON_MC 0x04
#define CC1101_STATE_MANCAL 0x05
#define CC1101_STATE_VCOON 0x06
#define CC1101_STATE_REGON 0x07
#define CC1101_STATE_STARTCAL 0x08
#define CC1101_STATE_BWBOOST 0x09
#define CC1101_STATE_FS_LOCK 0x0A
#define CC1101_STATE_IFADCON 0x0B
#define CC1101_STATE_ENDCAL 0x0C
#define CC1101_STATE_RX 0x0D
#define CC1101_STATE_RX_END 0x0E
#define CC1101_STATE_RX_RST 0x0F
#define CC1101_STATE_TXRX_SWITCH 0x10
#define CC1101_STATE_RXFIFO_OVERFLOW 0x11
#define CC1101_STATE_FSTXON 0x12
#define CC1101_STATE_TX 0x13
#define CC1101_STATE_TX_END 0x14
#define CC1101_STATE_RXTX_SWITCH 0x15
#define CC1101_STATE_TXFIFO_UNDERFLOW 0x16
// Masks for first byte read from RXFIFO
#define CC1101_NUM_RXBYTES_MASK 0x7f
#define CC1101_RXFIFO_OVERFLOW_MASK 0x80
// Masks for last byte read from RXFIFO
#define CC1101_LQI_MASK 0x7f
#define CC1101_CRC_OK_MASK 0x80
// IOCFG2 GDO2: high when TX FIFO at or above the TX FIFO threshold
#define CC1101_DEFVAL_IOCFG2 0x02
// IOCFG1 GDO1: High impedance (3-state)
#define CC1101_DEFVAL_IOCFG1 0x2E
// GDO0 goes high when sync word has been sent / received, and
// goes low at the end of the packet.
// In TX mode the pin will go low if the TX FIFO underflows.
#define CC1101_DEFVAL_IOCFG0 0x06
// Threshold = 32 bytes (1/2 of FIFO len)
#define CC1101_DEFVAL_FIFOTHR 0x07
#define CC1101_DEFVAL_RCCTRL1 0x41
#define CC1101_DEFVAL_RCCTRL0 0x00
#define CC1101_DEFVAL_AGCTEST 0x3F
#define CC1101_DEFVAL_MCSM1 0x20
#define CC1101_DEFVAL_WORCTRL 0xFB
#define CC1101_DEFVAL_FSCTRL0 0
#define CC1101_DEFVAL_PATABLE 0xc0 // full power
RfSetting gFixedConfig[] = {
{CC1101_IOCFG2,CC1101_DEFVAL_IOCFG2},
{CC1101_IOCFG1,CC1101_DEFVAL_IOCFG1},
{CC1101_IOCFG0,CC1101_DEFVAL_IOCFG0},
{CC1101_FIFOTHR,CC1101_DEFVAL_FIFOTHR},
{CC1101_FSCTRL0,CC1101_DEFVAL_FSCTRL0},
{CC1101_RCCTRL1,CC1101_DEFVAL_RCCTRL1},
{CC1101_RCCTRL0,CC1101_DEFVAL_RCCTRL0},
{CC1101_MCSM1,CC1101_DEFVAL_MCSM1},
{CC1101_WORCTRL,CC1101_DEFVAL_WORCTRL},
{0xff,0},
};
void CC1101_readBurstReg(uint8_t *buffer,uint8_t regAddr,uint8_t len);
void CC1101_cmdStrobe(uint8_t cmd);
void CC1101_wakeUp(void);
uint8_t CC1101_readReg(uint8_t regAddr, uint8_t regType);
void CC1101_writeReg(uint8_t regAddr, uint8_t value);
void CC1101_setTxState(void);
void setIdleState(void);
spi_device_handle_t gSpiHndl;
#define readConfigReg(regAddr) CC1101_readReg(regAddr, CC1101_CONFIG_REGISTER)
#define readStatusReg(regAddr) CC1101_readReg(regAddr, CC1101_STATUS_REGISTER)
#define flushRxFifo() CC1101_cmdStrobe(CC1101_SFRX)
#define flushTxFifo() CC1101_cmdStrobe(CC1101_SFTX)
const char *RegNamesCC1101[] = {
"IOCFG2", // 0x00 GDO2 output pin configuration
"IOCFG1", // 0x01 GDO1 output pin configuration
"IOCFG0", // 0x02 GDO0 output pin configuration
"FIFOTHR", // 0x03 RX FIFO and TX FIFO thresholds
"SYNC1", // 0x04 Sync word, high INT8U
"SYNC0", // 0x05 Sync word, low INT8U
"PKTLEN", // 0x06 Packet length
"PKTCTRL1", // 0x07 Packet automation control
"PKTCTRL0", // 0x08 Packet automation control
"ADDR", // 0x09 Device address
"CHANNR", // 0x0A Channel number
"FSCTRL1", // 0x0B Frequency synthesizer control
"FSCTRL0", // 0x0C Frequency synthesizer control
"FREQ2", // 0x0D Frequency control word, high INT8U
"FREQ1", // 0x0E Frequency control word, middle INT8U
"FREQ0", // 0x0F Frequency control word, low INT8U
"MDMCFG4", // 0x10 Modem configuration
"MDMCFG3", // 0x11 Modem configuration
"MDMCFG2", // 0x12 Modem configuration
"MDMCFG1", // 0x13 Modem configuration
"MDMCFG0", // 0x14 Modem configuration
"DEVIATN", // 0x15 Modem deviation setting
"MCSM2", // 0x16 Main Radio Control State Machine configuration
"MCSM1", // 0x17 Main Radio Control State Machine configuration
"MCSM0", // 0x18 Main Radio Control State Machine configuration
"FOCCFG", // 0x19 Frequency Offset Compensation configuration
"BSCFG", // 0x1A Bit Synchronization configuration
"AGCCTRL2", // 0x1B AGC control
"AGCCTRL1", // 0x1C AGC control
"AGCCTRL0", // 0x1D AGC control
"WOREVT1", // 0x1E High INT8U Event 0 timeout
"WOREVT0", // 0x1F Low INT8U Event 0 timeout
"WORCTRL", // 0x20 Wake On Radio control
"FREND1", // 0x21 Front end RX configuration
"FREND0", // 0x22 Front end TX configuration
"FSCAL3", // 0x23 Frequency synthesizer calibration
"FSCAL2", // 0x24 Frequency synthesizer calibration
"FSCAL1", // 0x25 Frequency synthesizer calibration
"FSCAL0", // 0x26 Frequency synthesizer calibration
"RCCTRL1", // 0x27 RC oscillator configuration
"RCCTRL0", // 0x28 RC oscillator configuration
"FSTEST", // 0x29 Frequency synthesizer calibration control
"PTEST", // 0x2A Production test
"AGCTEST", // 0x2B AGC test
"TEST2", // 0x2C Various test settings
"TEST1", // 0x2D Various test settings
"TEST0", // 0x2E Various test settings
"0x2f", // 0x2f
//CC1101 Strobe commands
"SRES", // 0x30 Reset chip.
"SFSTXON", // 0x31 Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
"SXOFF", // 0x32 Turn off crystal oscillator.
"SCAL", // 0x33 Calibrate frequency synthesizer and turn it off
"SRX", // 0x34 Enable RX. Perform calibration first if coming from IDLE and
"STX", // 0x35 In IDLE state: Enable TX. Perform calibration first if
"SIDLE", // 0x36 Exit RX / TX, turn off frequency synthesizer and exit
"SAFC", // 0x37 Perform AFC adjustment of the frequency synthesizer
"SWOR", // 0x38 Start automatic RX polling sequence (Wake-on-Radio)
"SPWD", // 0x39 Enter power down mode when CSn goes high.
"SFRX", // 0x3A Flush the RX FIFO buffer.
"SFTX", // 0x3B Flush the TX FIFO buffer.
"SWORRST", // 0x3C Reset real time clock.
"SNOP", // 0x3D No operation. May be used to pad strobe commands to two
"PATABLE" // 0x3E
};
// SPI Stuff
#if CONFIG_SPI2_HOST
#define HOST_ID SPI2_HOST
#elif CONFIG_SPI3_HOST
#define HOST_ID SPI3_HOST
#endif
/*
* RF state
*/
static uint8_t gRfState;
#define cc1101_Select() gpio_set_level(CONFIG_CSN_GPIO, LOW)
#define cc1101_Deselect() gpio_set_level(CONFIG_CSN_GPIO, HIGH)
#define wait_Miso() while(gpio_get_level(CONFIG_MISO_GPIO)>0)
#define getGDO0state() gpio_get_level(CONFIG_GDO0_GPIO)
#define wait_GDO0_high() while(!getGDO0state())
#define wait_GDO0_low() while(getGDO0state())
#define getGDO2state() gpio_get_level(CONFIG_GDO2_GPIO)
#define wait_GDO2_low() while(getGDO2state())
/**
* Arduino Macros
*/
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
#define delayMicroseconds(us) esp_rom_delay_us(us)
#define LOW 0
#define HIGH 1
int32_t gFreqErrSum;
uint8_t gFreqErrSumCount;
int8_t gFreqCorrection;
bool spi_write_byte(uint8_t* Dataout,size_t DataLength)
{
spi_transaction_t SPITransaction;
if(DataLength > 0) {
memset(&SPITransaction,0,sizeof(spi_transaction_t));
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = Dataout;
SPITransaction.rx_buffer = NULL;
spi_device_transmit(gSpiHndl,&SPITransaction);
}
return true;
}
bool spi_read_byte(uint8_t* Datain,uint8_t* Dataout,size_t DataLength)
{
spi_transaction_t SPITransaction;
if(DataLength > 0) {
memset(&SPITransaction,0,sizeof(spi_transaction_t));
SPITransaction.length = DataLength * 8;
SPITransaction.tx_buffer = Dataout;
SPITransaction.rx_buffer = Datain;
spi_device_transmit(gSpiHndl,&SPITransaction);
}
return true;
}
uint8_t spi_transfer(uint8_t address)
{
uint8_t datain[1];
uint8_t dataout[1];
dataout[0] = address;
//spi_write_byte(dev, dataout, 1 );
//spi_read_byte(datain, dataout, 1 );
spi_transaction_t SPITransaction;
memset(&SPITransaction,0,sizeof(spi_transaction_t));
SPITransaction.length = 8;
SPITransaction.tx_buffer = dataout;
SPITransaction.rx_buffer = datain;
spi_device_transmit(gSpiHndl,&SPITransaction);
return datain[0];
}
/**
* CC1101_wakeUp
*
* Wake up CC1101 from Power Down state
*/
void CC1101_wakeUp(void)
{
cc1101_Select();
wait_Miso();
cc1101_Deselect();
}
/**
* CC1101_writeReg
*
* Write single register into the CC1101 IC via SPI
*
* @param regAddr Register address
* @param value Value to be writen
*/
void CC1101_writeReg(uint8_t regAddr, uint8_t value)
{
if(regAddr < 0x3f) {
LOGV("0x%x -> %s(0x%x)\n",value,RegNamesCC1101[regAddr],regAddr);
}
else {
LOGV("0x%x -> 0x%x\n",value,regAddr);
}
cc1101_Select(); // Select CC1101
wait_Miso(); // Wait until MISO goes low
spi_transfer(regAddr); // Send register address
spi_transfer(value); // Send value
cc1101_Deselect(); // Deselect CC1101
}
/**
* CC1101_cmdStrobe
*
* Send command strobe to the CC1101 IC via SPI
*
* @param cmd Command strobe
*/
void CC1101_cmdStrobe(uint8_t cmd)
{
cc1101_Select();
wait_Miso();
spi_transfer(cmd);
cc1101_Deselect();
}
/**
* CC1101_readReg
*
* Read CC1101 register via SPI
*
* @param regAddr Register address
* @param regType Type of register: CONFIG_REGISTER or STATUS_REGISTER
*
* Return:
* Data uint8_t returned by the CC1101 IC
*/
uint8_t CC1101_readReg(uint8_t regAddr,uint8_t regType)
{
uint8_t addr, val;
addr = regAddr | regType;
cc1101_Select();
wait_Miso();
spi_transfer(addr);
val = spi_transfer(0x00); // Read result
cc1101_Deselect();
return val;
}
/**
* CC1101_readBurstReg
*
* Read burst data from CC1101 via SPI
*
* @param buffer Buffer where to copy the result to
* @param regAddr Register address
* @param len Data length
*/
void CC1101_readBurstReg(uint8_t *buffer,uint8_t regAddr,uint8_t len)
{
uint8_t addr, i;
addr = regAddr | READ_BURST;
cc1101_Select();
wait_Miso();
spi_transfer(addr); // Send register address
for(i = 0; i < len; i++) {
buffer[i] = spi_transfer(0x00); // Read result uint8_t by uint8_t
}
cc1101_Deselect();
}
/**
* reset
*
* Reset CC1101
*/
void CC1101_reset(void)
{
// See sectin 19.1.2 of the CC1101 spec sheet for reasons for the following
cc1101_Deselect();
delayMicroseconds(5);
cc1101_Select();
delayMicroseconds(10);
cc1101_Deselect();
delayMicroseconds(41);
cc1101_Select();
// Wait until MISO goes low indicating XOSC stable
wait_Miso();
spi_transfer(CC1101_SRES); // Send reset command strobe
wait_Miso();
cc1101_Deselect();
}
/**
* CC1101_setRxState
*
* Enter Rx state
*/
void CC1101_setRxState(void)
{
CC1101_cmdStrobe(CC1101_SRX);
gRfState = RFSTATE_RX;
}
/**
* CC1101_setTxState
*
* Enter Tx state
*/
void CC1101_setTxState(void)
{
CC1101_cmdStrobe(CC1101_STX);
gRfState = RFSTATE_TX;
}
void CC1101_DumpRegs()
{
#if ENABLE_LOGGING
uint8_t regAddr;
uint8_t value;
LOG("\n");
for(regAddr = 0; regAddr < 0x2f; regAddr++) {
value = CC1101_readReg(regAddr,READ_SINGLE);
LOG("%02x %s: 0x%02X\n",regAddr,RegNamesCC1101[regAddr],value);
}
#if 0
for(regAddr = 0; regAddr < 0x2f; regAddr++) {
value = CC1101_readReg(regAddr,READ_SINGLE);
LOG("<Register><Name>%s</Name><Value>0x%02X</Value></Register>\n",RegNamesCC1101[regAddr],value);
}
#endif
#endif
}
bool CC1101_Tx(uint8_t *TxData)
{
bool Ret = false;
int ErrLine = 0;
spi_transaction_t SPITransaction;
uint8_t BytesSent = 0;
uint8_t Bytes2Send;
uint8_t len;
uint8_t CanSend;
esp_err_t Err;
do {
// The first byte in the buffer is the number of data bytes to send,
// we also need to send the first byte
len = 1 + *TxData;
memset(&SPITransaction,0,sizeof(spi_transaction_t));
SPITransaction.tx_buffer = TxData;
setIdleState();
flushTxFifo();
while(BytesSent < len) {
Bytes2Send = len - BytesSent;
if(BytesSent == 0) {
// First chunk, the FIFO is empty and can take 64 bytes
if(Bytes2Send > 64) {
Bytes2Send = 64;
}
}
else {
// Not the first chunk, we can only send FIFO_THRESHOLD bytes
// and only when GDO2 says we can
if(getGDO2state()) {
wait_GDO2_low();
}
CanSend = readStatusReg(CC1101_TXBYTES);
if(CanSend & 0x80) {
LOGE("TX FIFO underflow, BytesSent %d\n",BytesSent);
ErrLine = __LINE__;
break;
}
CanSend = 64 - CanSend;
if(CanSend == 0) {
LOGE("CanSend == 0, GDO2 problem\n");
ErrLine = __LINE__;
break;
}
if(Bytes2Send > CanSend) {
Bytes2Send = CanSend;
}
}
SPITransaction.length = Bytes2Send * 8;
SPITransaction.rxlength = 0;
cc1101_Select();
wait_Miso();
spi_transfer(CC1101_TXFIFO | WRITE_BURST);
if((Err = spi_device_transmit(gSpiHndl,&SPITransaction)) != ESP_OK) {
ErrLine = __LINE__;
LOGE("spi_device_transmit failed %d\n",Err);
break;
}
cc1101_Deselect();
// LOG("Sending %d bytes\n",Bytes2Send);
if(BytesSent == 0) {
// some or all of the tx data has been written to the FIFO,
// start transmitting
// LOG("Start tx\n");
CC1101_setTxState();
// Wait for the sync word to be transmitted
wait_GDO0_high();
}
SPITransaction.tx_buffer += Bytes2Send;
BytesSent += Bytes2Send;
}
// Wait until the end of the TxData transmission
wait_GDO0_low();
Ret = true;
} while(false);
setIdleState();
CC1101_setRxState();
if(ErrLine != 0) {
LOGE("%s#%d: failure\n",__FUNCTION__,ErrLine);
}
return Ret;
}
// Called when GDO0 goes low, i.e. end of packet.
// Everything has been received.
// NB: this means the entire packet must fit in the FIFO so maximum
// message length is 64 bytes.
int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi)
{
uint8_t rxBytes = readStatusReg(CC1101_RXBYTES);
uint8_t Rssi;
uint8_t Lqi;
int Ret;
int8_t FreqErr;
int8_t FreqCorrection;
// Any data waiting to be read and no overflow?
do {
if(rxBytes & CC1101_RXFIFO_OVERFLOW_MASK) {
LOGE("RxFifo overflow\n");
Ret = -2;
break;
}
if(rxBytes < 2) {
// should have at least 2 bytes, packet len and one byte of data
LOGE("Internal error, rxBytes = %d\n",rxBytes);
Ret = -2;
break;
}
// Get packet length
Ret = readConfigReg(CC1101_RXFIFO);
if(Ret > RxBufLen) {
// Toss the data
LOGE("RxBuf too small %d < %d\n",RxBufLen,Ret);
Ret = -1;
break;
}
// Read the data
CC1101_readBurstReg(RxBuf,CC1101_RXFIFO,Ret);
// Read RSSI
Rssi = readConfigReg(CC1101_RXFIFO);
// Read LQI and CRC_OK
Lqi = readConfigReg(CC1101_RXFIFO);
if(!(Lqi & CC1101_CRC_OK_MASK)) {
// Crc error, ignore the packet
LOG("Ignoring %d byte packet, CRC error\n",Ret);
Ret = 0;
break;
}
// CRC is valid
if(pRssi != NULL) {
*pRssi = Rssi;
}
if(pLqi != NULL) {
*pLqi = Lqi & CC1101_LQI_MASK;
}
FreqErr = (int8_t) CC1101_readReg(CC1101_FREQEST,CC1101_STATUS_REGISTER);
if(FreqErr != 0 && gFreqErrSumCount < 255) {
gFreqErrSum += FreqErr + gFreqCorrection;
gFreqErrSumCount++;
FreqCorrection = (int8_t) (gFreqErrSum / gFreqErrSumCount);
if(gFreqCorrection != FreqCorrection) {
LOGA("FreqCorrection %d -> %d\n",gFreqCorrection,FreqCorrection);
gFreqCorrection = FreqCorrection;
CC1101_writeReg(CC1101_FSCTRL0,gFreqCorrection);
}
if(gFreqErrSumCount == 255) {
LOGA("Final FreqCorrection %d\n",gFreqCorrection);
}
}
} while(false);
setIdleState();
flushRxFifo();
CC1101_setRxState();
return Ret;
}
bool CC1101_Present()
{
bool Ret = false;
uint8_t PartNum = CC1101_readReg(CC1101_PARTNUM, CC1101_STATUS_REGISTER);
uint8_t ChipVersion = CC1101_readReg(CC1101_VERSION, CC1101_STATUS_REGISTER);
if(PartNum == 0 && (ChipVersion == 20 || ChipVersion == 4)) {
LOGA("CC1101 detected\n");
Ret = true;
}
else {
if(PartNum != 0) {
LOGA("Invalid PartNum 0x%x\n",PartNum);
}
else {
LOGA("Invalid or unsupported ChipVersion 0x%x\n",ChipVersion);
}
}
return Ret;
}
void CC1101_SetConfig(const RfSetting *pConfig)
{
int i;
uint8_t RegWasSet[CC1101_TEST0 + 1];
uint8_t Reg;
memset(RegWasSet,0,sizeof(RegWasSet));
setIdleState();
if(pConfig == NULL) {
// Just set the fixed registers
LOG("Setting fixed registers\n");
for(i = 0; (Reg = gFixedConfig[i].Reg) != 0xff; i++) {
CC1101_writeReg(Reg,gFixedConfig[i].Value);
}
// Set TX power
CC1101_writeReg(CC1101_PATABLE,CC1101_DEFVAL_PATABLE);
}
else {
for(i = 0; (Reg = gFixedConfig[i].Reg) != 0xff; i++) {
RegWasSet[Reg] = 1;
}
while((Reg = pConfig->Reg) != 0xff) {
if(RegWasSet[Reg] == 1) {
LOG("%s value ignored\n",RegNamesCC1101[Reg]);
}
else {
if(RegWasSet[Reg] == 2) {
LOG("%s value set before\n",RegNamesCC1101[Reg]);
}
CC1101_writeReg(pConfig->Reg,pConfig->Value);
RegWasSet[Reg] = 2;
}
pConfig++;
}
#if 0
for(Reg = 0; Reg <= CC1101_TEST0; Reg++) {
if(RegWasSet[Reg] == 0) {
LOG("%s value not set\n",RegNamesCC1101[Reg]);
}
}
#endif
}
}
void setIdleState()
{
uint8_t MarcState;
CC1101_cmdStrobe(CC1101_SIDLE);
// Wait for it
do {
MarcState = readStatusReg(CC1101_MARCSTATE);
} while(MarcState != CC1101_STATE_IDLE);
}
void CC1101_logState()
{
static uint8_t LastMarcState = 0xff;
uint8_t MarcState;
MarcState = readStatusReg(CC1101_MARCSTATE);
if(LastMarcState != MarcState) {
LOG("MarcState 0x%x -> 0x%x\n",LastMarcState,MarcState);
LastMarcState = MarcState;
}
}
#endif // CONFIG_OEPL_SUBGIG_SUPPORT

View File

@@ -0,0 +1,118 @@
// Large portions of this code was copied from:
// https://github.com/nopnop2002/esp-idf-cc1101 with the following copyright
/*
* Copyright (c) 2011 panStamp <contact@panstamp.com>
* Copyright (c) 2016 Tyler Sommer <contact@tylersommer.pro>
*
* This file is part of the CC1101 project.
*
* CC1101 is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* any later version.
*
* CC1101 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CC1101; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*
* Author: Daniel Berenguer
* Creation date: 03/03/2011
*/
#ifndef __CC1101_RADIO_H_
#define __CC1101_RADIO_H_
/**
* CC1101 configuration registers
*/
#define CC1101_IOCFG2 0x00 // GDO2 Output Pin Configuration
#define CC1101_IOCFG1 0x01 // GDO1 Output Pin Configuration
#define CC1101_IOCFG0 0x02 // GDO0 Output Pin Configuration
#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO Thresholds
#define CC1101_SYNC1 0x04 // Sync Word, High Byte
#define CC1101_SYNC0 0x05 // Sync Word, Low Byte
#define CC1101_PKTLEN 0x06 // Packet Length
#define CC1101_PKTCTRL1 0x07 // Packet Automation Control
#define CC1101_PKTCTRL0 0x08 // Packet Automation Control
#define CC1101_ADDR 0x09 // Device Address
#define CC1101_CHANNR 0x0A // Channel Number
#define CC1101_FSCTRL1 0x0B // Frequency Synthesizer Control
#define CC1101_FSCTRL0 0x0C // Frequency Synthesizer Control
#define CC1101_FREQ2 0x0D // Frequency Control Word, High Byte
#define CC1101_FREQ1 0x0E // Frequency Control Word, Middle Byte
#define CC1101_FREQ0 0x0F // Frequency Control Word, Low Byte
#define CC1101_MDMCFG4 0x10 // Modem Configuration
#define CC1101_MDMCFG3 0x11 // Modem Configuration
#define CC1101_MDMCFG2 0x12 // Modem Configuration
#define CC1101_MDMCFG1 0x13 // Modem Configuration
#define CC1101_MDMCFG0 0x14 // Modem Configuration
#define CC1101_DEVIATN 0x15 // Modem Deviation Setting
#define CC1101_MCSM2 0x16 // Main Radio Control State Machine Configuration
#define CC1101_MCSM1 0x17 // Main Radio Control State Machine Configuration
#define CC1101_MCSM0 0x18 // Main Radio Control State Machine Configuration
#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation Configuration
#define CC1101_BSCFG 0x1A // Bit Synchronization Configuration
#define CC1101_AGCCTRL2 0x1B // AGC Control
#define CC1101_AGCCTRL1 0x1C // AGC Control
#define CC1101_AGCCTRL0 0x1D // AGC Control
#define CC1101_WOREVT1 0x1E // High Byte Event0 Timeout
#define CC1101_WOREVT0 0x1F // Low Byte Event0 Timeout
#define CC1101_WORCTRL 0x20 // Wake On Radio Control
#define CC1101_FREND1 0x21 // Front End RX Configuration
#define CC1101_FREND0 0x22 // Front End TX Configuration
#define CC1101_FSCAL3 0x23 // Frequency Synthesizer Calibration
#define CC1101_FSCAL2 0x24 // Frequency Synthesizer Calibration
#define CC1101_FSCAL1 0x25 // Frequency Synthesizer Calibration
#define CC1101_FSCAL0 0x26 // Frequency Synthesizer Calibration
#define CC1101_RCCTRL1 0x27 // RC Oscillator Configuration
#define CC1101_RCCTRL0 0x28 // RC Oscillator Configuration
#define CC1101_FSTEST 0x29 // Frequency Synthesizer Calibration Control
#define CC1101_PTEST 0x2A // Production Test
#define CC1101_AGCTEST 0x2B // AGC Test
#define CC1101_TEST2 0x2C // Various Test Settings
#define CC1101_TEST1 0x2D // Various Test Settings
#define CC1101_TEST0 0x2E // Various Test Settings
/**
* Status registers
*/
#define CC1101_PARTNUM 0x30 // Chip ID
#define CC1101_VERSION 0x31 // Chip ID
#define CC1101_FREQEST 0x32 // Frequency Offset Estimate from Demodulator
#define CC1101_LQI 0x33 // Demodulator Estimate for Link Quality
#define CC1101_RSSI 0x34 // Received Signal Strength Indication
#define CC1101_MARCSTATE 0x35 // Main Radio Control State Machine State
#define CC1101_WORTIME1 0x36 // High Byte of WOR Time
#define CC1101_WORTIME0 0x37 // Low Byte of WOR Time
#define CC1101_PKTSTATUS 0x38 // Current GDOx Status and Packet Status
#define CC1101_VCO_VC_DAC 0x39 // Current Setting from PLL Calibration Module
#define CC1101_TXBYTES 0x3A // Underflow and Number of Bytes
#define CC1101_RXBYTES 0x3B // Overflow and Number of Bytes
#define CC1101_RCCTRL1_STATUS 0x3C // Last RC Oscillator Calibration Result
#define CC1101_RCCTRL0_STATUS 0x3D // Last RC Oscillator Calibration Result
typedef struct {
uint16_t Reg;
uint8_t Value;
} RfSetting;
extern spi_device_handle_t gSpiHndl;
void CC1101_SetConfig(const RfSetting *pConfig);
int CC1101_Rx(uint8_t *RxBuf,size_t RxBufLen,uint8_t *pRssi,uint8_t *pLqi);
bool CC1101_Tx(uint8_t *TxData);
bool CC1101_Present(void);
void CC1101_DumpRegs(void);
void CC1101_reset(void);
void CC1101_logState(void);
void CC1101_setRxState(void);
#endif // __CC1101_RADIO_H_

View File

@@ -0,0 +1,48 @@
#include "led.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LEDS 2
const gpio_num_t led_pins[NUM_LEDS] = {LED1, LED2};
TimerHandle_t led_timers[NUM_LEDS] = {0};
void led_timer_callback(TimerHandle_t xTimer) {
int led_index = (int)pvTimerGetTimerID(xTimer);
if (led_index >= 0 && led_index < NUM_LEDS) {
gpio_set_level(led_pins[led_index], 0);
}
}
void init_led() {
gpio_config_t led1 = {};
led1.intr_type = GPIO_INTR_DISABLE;
led1.mode = GPIO_MODE_OUTPUT;
led1.pin_bit_mask = ((1ULL << LED1) | (1ULL << LED2));
led1.pull_down_en = 0;
led1.pull_up_en = 0;
gpio_config(&led1);
for (int i = 0; i < NUM_LEDS; i++) {
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
}
}
void led_flash(int nr) {
gpio_set_level(led_pins[nr], 1);
if (nr >= 0 && nr < NUM_LEDS) {
xTimerStart(led_timers[nr], 0);
}
}
void led_set(int nr, bool state) {
gpio_set_level(nr, state);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
void init_led();
void led_set(int nr, bool state);
void led_flash(int nr);

View File

@@ -0,0 +1,833 @@
// Ported to ESP32-H2 By ATC1441(ATCnetz.de) for OpenEPaperLink at ~08.2023
#include "main.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_log.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "led.h"
#include "proto.h"
#include "radio.h"
#include "sdkconfig.h"
#include "second_uart.h"
//#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include "utils.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "SubGigRadio.h"
static const char *TAG = "MAIN";
const uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
#define DATATYPE_NOUPDATE 0
#define HW_TYPE 0xC6
#define MAX_PENDING_MACS 250
#define HOUSEKEEPING_INTERVAL 60UL
struct pendingData pendingDataArr[MAX_PENDING_MACS];
// VERSION GOES HERE!
uint16_t version = 0x001d;
#define RAW_PKT_PADDING 2
uint8_t radiotxbuffer[128];
uint8_t radiorxbuffer[128];
static uint32_t housekeepingTimer;
struct blockRequest requestedData = {0}; // holds which data was requested by the tag
uint8_t dstMac[8]; // target for the block transfer
uint16_t dstPan; //
static uint32_t blockStartTimer = 0; // reference that holds when the AP sends the next block
uint32_t nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32
uint8_t seq = 0; // holds current sequence number for transmission
uint8_t blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
uint8_t lastAckMac[8] = {0};
// these variables hold the current mac were talking to
#define CONCURRENT_REQUEST_DELAY 1200UL
uint32_t lastBlockRequest = 0;
uint8_t lastBlockMac[8];
uint8_t lastTagReturn[8];
#define NO_SUBGHZ_CHANNEL 255
uint8_t curSubGhzChannel;
uint8_t curChannel = 25;
uint8_t curPower = 10;
uint8_t curPendingData = 0;
uint8_t curNoUpdate = 0;
bool highspeedSerial = false;
void sendXferCompleteAck(uint8_t *dst);
void sendCancelXfer(uint8_t *dst);
void espNotifyAPInfo();
// tools
void addCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *) p)[c];
}
((uint8_t *) p)[0] = total;
}
bool checkCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *) p)[c];
}
return ((uint8_t *) p)[0] == total;
}
uint8_t getPacketType(void *buffer) {
struct MacFcs *fcs = buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
// broadcast frame
uint8_t type = ((uint8_t *) buffer)[sizeof(struct MacFrameBcast)];
return type;
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
// normal frame
uint8_t type = ((uint8_t *) buffer)[sizeof(struct MacFrameNormal)];
return type;
}
return 0;
}
uint8_t getBlockDataLength() {
uint8_t partNo = 0;
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
partNo++;
}
}
return partNo;
}
// pendingdata slot stuff
int8_t findSlotForMac(const uint8_t *mac) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(mac, ((uint8_t *) &(pendingDataArr[c].targetMac)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) {
return c;
}
}
}
return -1;
}
int8_t findFreeSlot() {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft == 0) {
return c;
}
}
return -1;
}
int8_t findSlotForVer(const uint8_t *ver) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(ver, ((uint8_t *) &(pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) return c;
}
}
return -1;
}
void deleteAllPendingDataForVer(const uint8_t *ver) {
int8_t slot = -1;
do {
slot = findSlotForVer(ver);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void deleteAllPendingDataForMac(const uint8_t *mac) {
int8_t slot = -1;
do {
slot = findSlotForMac(mac);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void countSlots() {
curPendingData = 0;
curNoUpdate = 0;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft != 0) {
if (pendingDataArr[c].availdatainfo.dataType != 0) {
curPendingData++;
} else {
curNoUpdate++;
}
}
}
}
// processing serial data
#define ZBS_RX_WAIT_HEADER 0
#define ZBS_RX_WAIT_SDA 1 // send data avail
#define ZBS_RX_WAIT_CANCEL 2 // cancel traffic for mac
#define ZBS_RX_WAIT_SCP 3 // set channel power
#define ZBS_RX_WAIT_BLOCKDATA 4
bool isSame(uint8_t *in1, char *in2, int len) {
bool flag = 1;
for (int i = 0; i < len; i++) {
if (in1[i] != in2[i]) flag = 0;
}
return flag;
}
int blockPosition = 0;
void processSerial(uint8_t lastchar) {
static uint8_t cmdbuffer[4];
static uint8_t RXState = 0;
static uint8_t serialbuffer[48];
static uint8_t *serialbufferp;
static uint8_t bytesRemain = 0;
static uint32_t lastSerial = 0;
static uint32_t blockStartTime = 0;
if ((RXState != ZBS_RX_WAIT_HEADER) && ((getMillis() - lastSerial) > 1000)) {
RXState = ZBS_RX_WAIT_HEADER;
ESP_LOGI(TAG, "UART Timeout");
}
lastSerial = getMillis();
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
// shift characters in
for (uint8_t c = 0; c < 3; c++) {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if (isSame(cmdbuffer + 1, ">D>", 3)) {
pr("ACK>");
blockStartTime = getMillis();
ESP_LOGI(TAG, "Starting BlkData, %lu ms after request", blockStartTime - nextBlockAttempt );
blockPosition = 0;
RXState = ZBS_RX_WAIT_BLOCKDATA;
}
if (isSame(cmdbuffer, "SDA>", 4)) {
ESP_LOGI(TAG, "SDA In");
RXState = ZBS_RX_WAIT_SDA;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "CXD>", 4)) {
ESP_LOGI(TAG, "CXD In");
RXState = ZBS_RX_WAIT_CANCEL;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "SCP>", 4)) {
ESP_LOGI(TAG, "SCP In");
RXState = ZBS_RX_WAIT_SCP;
bytesRemain = sizeof(struct espSetChannelPower);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "NFO?", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "NFO? In");
espNotifyAPInfo();
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RDY?", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "RDY? In");
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RSET", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "RSET In");
delay(100);
// TODO RESET US HERE
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "HSPD", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "HSPD In, switching to 2000000");
delay(100);
uart_switch_speed(2000000);
delay(100);
highspeedSerial = true;
pr("ACK>");
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_BLOCKDATA:
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
if (blockPosition >= 4100) {
ESP_LOGI(TAG, "Blockdata fully received in %lu ms, %lu ms after the request", getMillis() - blockStartTime, getMillis() - nextBlockAttempt);
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SDA:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *) serialbuffer;
int8_t slot = findSlotForMac(pd->targetMac);
if (slot == -1) slot = findFreeSlot();
if (slot != -1) {
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
pr("ACK>");
} else {
pr("NOQ>");
}
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_CANCEL:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *) serialbuffer;
deleteAllPendingDataForMac((uint8_t *) &pd->targetMac);
pr("ACK>");
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SCP:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct espSetChannelPower))) {
struct espSetChannelPower *scp = (struct espSetChannelPower *) serialbuffer;
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
if(curSubGhzChannel != scp->subghzchannel
&& curSubGhzChannel != NO_SUBGHZ_CHANNEL)
{
curSubGhzChannel = scp->subghzchannel;
ESP_LOGI(TAG,"Set SubGhz channel: %d",curSubGhzChannel);
SubGig_radioSetChannel(scp->subghzchannel);
if(scp->channel == 0) {
// Not setting 802.15.4 channel
goto SCPchannelFound;
}
}
#endif
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (channelList[c] == scp->channel) goto SCPchannelFound;
}
goto SCPfailed;
SCPchannelFound:
pr("ACK>");
if (curChannel != scp->channel) {
radioSetChannel(scp->channel);
curChannel = scp->channel;
}
curPower = scp->power;
radioSetTxPower(scp->power);
ESP_LOGI(TAG, "Set channel: %d power: %d", curChannel, curPower);
} else {
SCPfailed:
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
}
}
// sending data to the ESP
void espBlockRequest(const struct blockRequest *br, uint8_t *src) {
struct espBlockRequest *ebr = (struct espBlockRequest *) blockbuffer;
uartTx('R');
uartTx('Q');
uartTx('B');
uartTx('>');
memcpy(&(ebr->ver), &(br->ver), 8);
memcpy(&(ebr->src), src, 8);
ebr->blockId = br->blockId;
addCRC(ebr, sizeof(struct espBlockRequest));
for (uint8_t c = 0; c < sizeof(struct espBlockRequest); c++) {
uartTx(((uint8_t *) ebr)[c]);
}
}
void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src) {
uartTx('A');
uartTx('D');
uartTx('R');
uartTx('>');
struct espAvailDataReq eadr = {0};
memcpy((void *) eadr.src, (void *) src, 8);
memcpy((void *) &eadr.adr, (void *) adr, sizeof(struct AvailDataReq));
addCRC(&eadr, sizeof(struct espAvailDataReq));
for (uint8_t c = 0; c < sizeof(struct espAvailDataReq); c++) {
uartTx(((uint8_t *) &eadr)[c]);
}
}
void espNotifyXferComplete(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('F');
uartTx('C');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *) &exfc)[c]);
}
}
void espNotifyTimeOut(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('T');
uartTx('O');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *) &exfc)[c]);
}
}
void espNotifyAPInfo() {
pr("TYP>%02X", HW_TYPE);
pr("VER>%04X", version);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
pr("ZCH>%02X", curChannel);
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
pr("SCH>%03d",curSubGhzChannel);
#endif
pr("ZPW>%02X", curPower);
countSlots();
pr("PEN>%02X", curPendingData);
pr("NOP>%02X", curNoUpdate);
}
void espNotifyTagReturnData(uint8_t *src, uint8_t len) {
struct tagReturnData *trd = (struct tagReturnData *)(radiorxbuffer + sizeof(struct MacFrameBcast) + 1); // oh how I'd love to pass this as an argument, but sdcc won't let me
struct espTagReturnData *etrd = (struct espTagReturnData *)radiotxbuffer;
if (memcmp((void *) & trd->dataVer, lastTagReturn, 8) == 0) {
return;
} else {
memcpy(lastTagReturn, &trd->dataVer, 8);
}
memcpy(etrd->src, src, 8);
etrd->len = len;
memcpy(&etrd->returnData, trd, len);
addCRC(etrd, len + 10);
uartTx('T');
uartTx('R');
uartTx('D');
uartTx('>');
for (uint8_t c = 0; c < len + 10; c++) {
uartTx(((uint8_t *)etrd)[c]);
}
}
// process data from tag
void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *) buffer;
struct blockRequest *blockReq = (struct blockRequest *) (buffer + sizeof(struct MacFrameNormal) + 1);
if (!checkCRC(blockReq, sizeof(struct blockRequest))) return;
// check if we're already talking to this mac
if (memcmp(rxHeader->src, lastBlockMac, 8) == 0) {
lastBlockRequest = getMillis();
} else {
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
if ((getMillis() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
// mark this mac as the new current mac we're talking to
memcpy((void *) lastBlockMac, (void *) rxHeader->src, 8);
lastBlockRequest = getMillis();
} else {
// we're talking to another mac, let this mac know we can't accomodate another request right now
pr("BUSY!\n");
sendCancelXfer(rxHeader->src);
return;
}
}
// check if we have data for this mac
if (findSlotForMac(rxHeader->src) == -1) {
// no data for this mac, politely tell it to fuck off
sendCancelXfer(rxHeader->src);
return;
}
bool requestDataDownload = false;
if ((blockReq->blockId != requestedData.blockId) || (blockReq->ver != requestedData.ver)) {
// requested block isn't already in the buffer
requestDataDownload = true;
} else {
// requested block is already in the buffer
if (forceBlockDownload) {
if ((getMillis() - nextBlockAttempt) > 380) {
requestDataDownload = true;
pr("FORCED\n");
} else {
pr("IGNORED\n");
}
}
}
// copy blockrequest into requested data
memcpy(&requestedData, blockReq, sizeof(struct blockRequest));
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
struct blockRequestAck *blockRequestAck = (struct blockRequestAck *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct blockRequestAck) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST_ACK;
if (blockStartTimer == 0) {
if (requestDataDownload) {
if (highspeedSerial == true) {
blockRequestAck->pleaseWaitMs = 140;
} else {
blockRequestAck->pleaseWaitMs = 550;
}
} else {
// block is already in buffer
blockRequestAck->pleaseWaitMs = 30;
}
} else {
blockRequestAck->pleaseWaitMs = 30;
}
blockStartTimer = getMillis() + blockRequestAck->pleaseWaitMs;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->pan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC((void *) blockRequestAck, sizeof(struct blockRequestAck));
radioTx(radiotxbuffer);
// save the target for the blockdata
memcpy(dstMac, rxHeader->src, 8);
dstPan = rxHeader->pan;
if (requestDataDownload) {
blockPosition = 0;
espBlockRequest(&requestedData, rxHeader->src);
nextBlockAttempt = getMillis();
}
}
void processAvailDataReq(uint8_t *buffer) {
struct MacFrameBcast *rxHeader = (struct MacFrameBcast *) buffer;
struct AvailDataReq *availDataReq = (struct AvailDataReq *) (buffer + sizeof(struct MacFrameBcast) + 1);
if (!checkCRC(availDataReq, sizeof(struct AvailDataReq))) return;
// prepare tx buffer to send a response
memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120);
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_AVAIL_DATA_INFO;
// check to see if we have data available for this mac
bool haveData = false;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft) {
if (memcmp(pendingDataArr[c].targetMac, rxHeader->src, 8) == 0) {
haveData = true;
memcpy((void *) availDataInfo, &(pendingDataArr[c].availdatainfo), sizeof(struct AvailDataInfo));
break;
}
}
}
// couldn't find data for this mac
if (!haveData) availDataInfo->dataType = DATATYPE_NOUPDATE;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->dstPan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC(availDataInfo, sizeof(struct AvailDataInfo));
radioTx(radiotxbuffer);
memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet
espNotifyAvailDataReq(availDataReq, rxHeader->src);
}
void processXferComplete(uint8_t *buffer) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *) buffer;
sendXferCompleteAck(rxHeader->src);
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
memcpy((void *) lastAckMac, (void *) rxHeader->src, 8);
espNotifyXferComplete(rxHeader->src);
int8_t slot = findSlotForMac(rxHeader->src);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
}
}
void processTagReturnData(uint8_t *buffer, uint8_t len) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buffer;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
if (!checkCRC((buffer + sizeof(struct MacFrameBcast) + 1), len - (sizeof(struct MacFrameBcast) + 1))) {
return;
}
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_TAG_RETURN_DATA_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer);
espNotifyTagReturnData(rxframe->src, len - (sizeof(struct MacFrameBcast) + 1));
}
// send block data to the tag
void sendPart(uint8_t partNo) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
struct blockPart *blockPart = (struct blockPart *) (radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PART;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dstMac, 8);
blockPart->blockId = requestedData.blockId;
blockPart->blockPart = partNo;
memcpy(&(blockPart->data), blockbuffer + (partNo * BLOCK_PART_DATA_SIZE), BLOCK_PART_DATA_SIZE);
addCRC(blockPart, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendBlockData() {
if (getBlockDataLength() == 0) {
pr("Invalid block request received, 0 parts..\n");
requestedData.requestedParts[0] |= 0x01;
}
pr("Sending parts:");
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS); c++) {
if (c % 10 == 0) pr(" ");
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
pr("X");
} else {
pr(".");
}
}
pr("\n");
uint8_t partNo = 0;
while (partNo < BLOCK_MAX_PARTS) {
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS) && (partNo < BLOCK_MAX_PARTS); c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
sendPart(c);
partNo++;
}
}
if(dstPan == PROTO_PAN_ID_SUBGHZ) {
// Don't send BLOCK_MAX_PARTS for subgig, it requests what it
// can handle with its limited RAM
break;
}
}
}
void sendXferCompleteAck(uint8_t *dst) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendCancelXfer(uint8_t *dst) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendPong(void *buf) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *) buf;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *) (radiotxbuffer + 1);
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG;
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
if(rxframe->srcPan == PROTO_PAN_ID_SUBGHZ) {
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curSubGhzChannel;
}
else
#endif
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curChannel;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer);
}
void app_main(void) {
esp_event_loop_create_default();
init_nvs();
init_led();
init_second_uart();
requestedData.blockId = 0xFF;
// clear the array with pending information
memset(pendingDataArr, 0, sizeof(pendingDataArr));
radio_init(curChannel);
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
if(SubGig_radio_init(curSubGhzChannel)) {
// Ether we don't have a cc1101 or it's not working
curSubGhzChannel = NO_SUBGHZ_CHANNEL;
ESP_LOGI(TAG,"CC1101 NOT detected.");
}
else {
ESP_LOGI(TAG,"CC1101 detected.");
}
#endif
radioSetTxPower(10);
pr("RES>");
pr("RDY>");
ESP_LOGI(TAG, "H2 ready!");
housekeepingTimer = getMillis();
while (1) {
while ((getMillis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
int8_t ret = commsRxUnencrypted(radiorxbuffer);
if (ret > 1) {
led_flash(0);
// received a packet, lets see what it is
switch (getPacketType(radiorxbuffer)) {
case PKT_AVAIL_DATA_REQ:
if (ret == 28) {
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
processAvailDataReq(radiorxbuffer);
} else if (ret == 40) {
// new version of the AvailDataReq struct
processAvailDataReq(radiorxbuffer);
}
break;
case PKT_BLOCK_REQUEST:
processBlockRequest(radiorxbuffer, 1);
break;
case PKT_BLOCK_PARTIAL_REQUEST:
processBlockRequest(radiorxbuffer, 0);
break;
case PKT_XFER_COMPLETE:
processXferComplete(radiorxbuffer);
break;
case PKT_PING:
sendPong(radiorxbuffer);
break;
case PKT_AVAIL_DATA_SHORTREQ:
// a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal
// battery use bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is
// sent
if (ret == 18) {
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq) + 2);
processAvailDataReq(radiorxbuffer);
}
break;
case PKT_TAG_RETURN_DATA:
processTagReturnData(radiorxbuffer, ret);
break;
default:
ESP_LOGI(TAG, "t=%02X" , getPacketType(radiorxbuffer));
break;
}
} else if (blockStartTimer == 0) {
vTaskDelay(10 / portTICK_PERIOD_MS);
}
uint8_t curr_char;
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
if (blockStartTimer) {
if (getMillis() > blockStartTimer) {
sendBlockData();
blockStartTimer = 0;
}
}
}
memset(&lastTagReturn, 0, 8);
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
if (pendingDataArr[cCount].attemptsLeft == 1) {
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
espNotifyTimeOut(pendingDataArr[cCount].targetMac);
}
pendingDataArr[cCount].attemptsLeft = 0;
} else if (pendingDataArr[cCount].attemptsLeft > 1) {
pendingDataArr[cCount].attemptsLeft--;
if (pendingDataArr[cCount].availdatainfo.nextCheckIn) pendingDataArr[cCount].availdatainfo.nextCheckIn--;
}
}
housekeepingTimer = getMillis();
}
}

View File

@@ -0,0 +1 @@
#pragma once

View File

@@ -0,0 +1,194 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdint.h>
#define LED1 22
#define LED2 25
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
#define PROTO_PAN_ID_SUBGHZ (0x1337) // PAN ID compression shall be used
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
struct MacFcs {
uint8_t frameType : 3;
uint8_t secure : 1;
uint8_t framePending : 1;
uint8_t ackReqd : 1;
uint8_t panIdCompressed : 1;
uint8_t rfu1 : 1;
uint8_t rfu2 : 2;
uint8_t destAddrType : 2;
uint8_t frameVer : 2;
uint8_t srcAddrType : 2;
} __attribute__((packed, aligned(1)));
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
} __attribute__((packed, aligned(1)));
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
#define PKT_TAG_RETURN_DATA 0xE1
#define PKT_TAG_RETURN_DATA_ACK 0xE2
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
#define PKT_BLOCK_REQUEST_ACK 0xE9
#define PKT_BLOCK_REQUEST 0xE4
#define PKT_BLOCK_PART 0xE8
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_COMPLETE_ACK 0xEB
#define PKT_CANCEL_XFER 0xEC
#define PKT_PING 0xED
#define PKT_PONG 0xEE
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
uint16_t tagSoftwareVersion;
uint8_t currentChannel;
uint8_t customMode;
uint8_t reserved[8];
} __attribute__((packed, aligned(1)));
struct oldAvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
} __attribute__((packed, aligned(1)));
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
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, aligned(1)));
struct pendingData {
struct AvailDataInfo availdatainfo;
uint16_t attemptsLeft;
uint8_t targetMac[8];
} __attribute__((packed, aligned(1)));
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} __attribute__((packed, aligned(1)));
struct blockData {
uint16_t size;
uint16_t checksum;
uint8_t data[];
} __attribute__((packed, aligned(1)));
#define TAG_RETURN_DATA_SIZE 90
struct tagReturnData {
uint8_t checksum;
uint8_t partId;
uint64_t dataVer;
uint8_t dataType;
uint8_t data[TAG_RETURN_DATA_SIZE];
} __attribute__((packed, aligned(1)));
#define BLOCK_PART_DATA_SIZE 99
#define BLOCK_MAX_PARTS 42
#define BLOCK_DATA_SIZE 4096UL
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
#define BLOCK_REQ_PARTS_BYTES 6
struct blockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t type;
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
} __attribute__((packed, aligned(1)));
struct blockRequestAck {
uint8_t checksum;
uint16_t pleaseWaitMs;
} __attribute__((packed, aligned(1)));
struct espBlockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espXferComplete {
uint8_t checksum;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espAvailDataReq {
uint8_t checksum;
uint8_t src[8];
struct AvailDataReq adr;
} __attribute__((packed, aligned(1)));
struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
uint8_t subghzchannel;
#endif
} __attribute__((packed, aligned(1)));
struct espTagReturnData {
uint8_t checksum;
uint8_t src[8];
uint8_t len;
struct tagReturnData returnData;
} __attribute__((packed, aligned(1)));
#endif

View File

@@ -0,0 +1,150 @@
#include <stddef.h>
#include "radio.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_log.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "led.h"
#include "main.h"
#include "proto.h"
#include "sdkconfig.h"
// if you get an error about soc/lp_uart_reg.h not being found,
// you didn't choose the right build target. :-)
//#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include "utils.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include "SubGigRadio.h"
static const char *TAG = "RADIO";
uint8_t mSelfMac[8];
volatile uint8_t isInTransmit = 0;
QueueHandle_t packet_buffer = NULL;
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
ESP_EARLY_LOGI(TAG, "RX %d", frame[0]);
BaseType_t xHigherPriorityTaskWoken;
static uint8_t inner_rxPKT[130];
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
esp_ieee802154_receive_sfd_done();
}
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
isInTransmit = 0;
ESP_EARLY_LOGE(TAG, "TX Err: %d", error);
}
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
isInTransmit = 0;
ESP_EARLY_LOGI(TAG, "TX %d", frame[0]);
esp_ieee802154_receive_sfd_done();
}
static bool zigbee_is_enabled = false;
void radio_init(uint8_t ch) {
if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130);
// this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works
if(zigbee_is_enabled)
{
zigbee_is_enabled = false;
esp_ieee802154_disable();
}
zigbee_is_enabled = true;
esp_ieee802154_enable();
esp_ieee802154_set_channel(ch);
// esp_ieee802154_set_txpower(int8_t power);
esp_ieee802154_set_panid(PROTO_PAN_ID);
esp_ieee802154_set_promiscuous(false);
esp_ieee802154_set_coordinator(false);
esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ZIGBEE);
// esp_ieee802154_set_extended_address needs the MAC in reversed byte order
esp_read_mac(mSelfMac, ESP_MAC_IEEE802154);
uint8_t eui64_rev[8] = {0};
for (int i = 0; i < 8; i++) {
eui64_rev[7 - i] = mSelfMac[i];
}
esp_ieee802154_set_extended_address(eui64_rev);
esp_ieee802154_get_extended_address(mSelfMac);
esp_ieee802154_set_short_address(0xFFFE);
esp_ieee802154_set_rx_when_idle(true);
esp_ieee802154_receive();
led_flash(1);
vTaskDelay(100 / portTICK_PERIOD_MS);
led_flash(0);
vTaskDelay(100 / portTICK_PERIOD_MS);
led_flash(1);
vTaskDelay(100 / portTICK_PERIOD_MS);
led_flash(0);
ESP_LOGI(TAG, "Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x",
esp_ieee802154_get_panid(), esp_ieee802154_get_channel(),
mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3],
mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7],
esp_ieee802154_get_short_address());
}
// uint32_t lastZbTx = 0;
bool radioTx(uint8_t *packet) {
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
// The subghz driver uses DMA
static DMA_ATTR uint8_t txPKT[130];
#else
static uint8_t txPKT[130];
#endif
led_flash(1);
// while (getMillis() - lastZbTx < 6) {
// }
// lastZbTx = getMillis();
memcpy(txPKT, packet, packet[0]);
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
struct MacFrameNormal *txHeader = (struct MacFrameNormal *) (packet + 1);
if(txHeader->pan == PROTO_PAN_ID_SUBGHZ) {
return SubGig_radioTx(packet);
}
#endif
while (isInTransmit) {
}
isInTransmit = 1;
esp_ieee802154_transmit(txPKT, false);
return true;
}
void radioSetChannel(uint8_t ch) {
radio_init(ch);
}
void radioSetTxPower(uint8_t power) {}
int8_t commsRxUnencrypted(uint8_t *data) {
static uint8_t inner_rxPKT_out[130];
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
return inner_rxPKT_out[0] - 2;
}
#ifdef CONFIG_OEPL_SUBGIG_SUPPORT
if(gSubGigData.Enabled) {
int8_t Ret = SubGig_commsRxUnencrypted(data);
if(Ret > 0) {
return Ret;
}
}
#endif
return 0;
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#define RAW_PKT_PADDING 2
extern uint8_t mSelfMac[8];
void radio_init(uint8_t ch);
bool radioTx(uint8_t *packet);
void radioSetChannel(uint8_t ch);
void radioSetTxPower(uint8_t power);
int8_t commsRxUnencrypted(uint8_t *data);
#ifdef SUBGIG_SUPPORT
void SubGig_radio_init(uint8_t ch);
bool SubGig_radioTx(uint8_t *packet);
void SubGig_radioSetChannel(uint8_t ch);
void SubGig_radioSetTxPower(uint8_t power);
int8_t SubGig_commsRxUnencrypted(uint8_t *data);
#endif

View File

@@ -0,0 +1,116 @@
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_log.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "main.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
//#include "soc/lp_uart_reg.h"
#include "second_uart.h"
//static const char *TAG = "SECOND_UART";
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
#define MAX_BUFF_POS 8000
volatile int curr_buff_pos = 0;
volatile int worked_buff_pos = 0;
volatile uint8_t buff_pos[MAX_BUFF_POS + 5];
static void uart_event_task(void *pvParameters);
void init_second_uart() {
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0));
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(1, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
}
void uart_switch_speed(int baudrate) {
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
}
void uartTx(uint8_t data) { uart_write_bytes(1, (const char *) &data, 1); }
bool getRxCharSecond(uint8_t *newChar) {
if (curr_buff_pos != worked_buff_pos) {
*newChar = buff_pos[worked_buff_pos];
worked_buff_pos++;
worked_buff_pos %= MAX_BUFF_POS;
return true;
}
return false;
}
static void uart_event_task(void *pvParameters) {
uart_event_t event;
uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);
for (;;) {
if (xQueueReceive(uart0_queue, (void *) &event, (TickType_t) portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
switch (event.type) {
case UART_DATA:
uart_read_bytes(1, dtmp, event.size, portMAX_DELAY);
for (int i = 0; i < event.size; i++) {
buff_pos[curr_buff_pos] = dtmp[i];
curr_buff_pos++;
curr_buff_pos %= MAX_BUFF_POS;
}
break;
default:
// ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
void uart_printf(const char *format, ...) {
va_list args;
va_start(args, format);
char buffer[128];
int len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len > 0) {
uart_write_bytes(1, buffer, len);
}
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include <inttypes.h>
void init_second_uart();
void uart_switch_speed(int baudrate);
void uartTx(uint8_t data);
bool getRxCharSecond(uint8_t *newChar);
void uart_printf(const char *format, ...);
#define pr uart_printf
#define CONFIG_OEPL_HARDWARE_UART_TX 24
#define CONFIG_OEPL_HARDWARE_UART_RX 23

View File

@@ -0,0 +1,36 @@
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_log.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "main.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
//#include "soc/lp_uart_reg.h"
#include "nvs_flash.h"
void delay(int ms) { vTaskDelay(pdMS_TO_TICKS(ms)); }
uint32_t getMillis() { return (uint32_t) (esp_timer_get_time() / 1000); }
void init_nvs()
{
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );
}

View File

@@ -0,0 +1,5 @@
#pragma once
void delay(int ms);
uint32_t getMillis();
void init_nvs();

View File

@@ -0,0 +1,5 @@
# ESP-IDF Partition Table
# Name, Type, SubType, Offset, Size, Flags
nvs,data,nvs,0x9000,0x6000,,
factory,app,factory,0x10000,1M,,
littlefs,data,spiffs,,3008K,,
1 # ESP-IDF Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs,data,nvs,0x9000,0x6000,,
4 factory,app,factory,0x10000,1M,,
5 littlefs,data,spiffs,,3008K,,

View File

@@ -0,0 +1,8 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_IDF_TARGET="esp32h2"
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y
CONFIG_PARTITION_TABLE_CUSTOM=y

View File

@@ -0,0 +1,76 @@
#| Function | ESP32H2 Pin | ESP32S3 Pin
#| :--------------------------------: | :-------------------: | :------------------
#| Activate The BOOT Mode Of ESP32H2 | ESP32H2_IO9 | ESP32S3_IO33
#| Reset ESP32H2 | ESP32H2_Pin Number 8 | ESP32S3_IO34
#| Uart | ESP32H2_TX_IO24 | ESP32S3_RX_IO48
#| Uart | ESP32H2_RX_IO23 | ESP32S3_TX_IO47
# cd ESP32_AP-Flasher
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
python gzip_wwwfiles.py
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_LILYGO_AP
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
# mkdir ESP32_S3_16_8_LILYGO_AP
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_LILYGO_AP\boot_app0.bin
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\firmware.bin ESP32_S3_16_8_LILYGO_AP\firmware.bin
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\bootloader.bin ESP32_S3_16_8_LILYGO_AP\bootloader.bin
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\partitions.bin ESP32_S3_16_8_LILYGO_AP\partitions.bin
copy .pio\build\ESP32_S3_16_8_LILYGO_AP\littlefs.bin ESP32_S3_16_8_LILYGO_AP\littlefs.bin
copy ESP32_S3_16_8_LILYGO_AP\firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP.bin
copy ESP32_S3_16_8_LILYGO_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_LILYGO_AP_full.bin
cd ESP32_S3_16_8_LILYGO_AP
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
#python -m esptool -p COM12 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd ..
#esptool.py v4.7.0
#Serial port COM12
#Connecting...
#Chip is ESP32-S3 (QFN56) (revision v0.2)
#Features: WiFi, BLE
#Crystal is 40MHz
#MAC: f4:12:fa:af:5b:9c
#Uploading stub...
#Running stub...
#Stub running...
#Changing baud rate to 460800
#Changed.
#Configuring flash size...
#Auto-detected Flash size: 16MB
#Flash will be erased from 0x00000000 to 0x00003fff...
#Flash will be erased from 0x00008000 to 0x00008fff...
#Flash will be erased from 0x0000e000 to 0x0000ffff...
#Flash will be erased from 0x00010000 to 0x00203fff...
#Flash will be erased from 0x00910000 to 0x00feffff...
#Compressed 15104 bytes to 10401...
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.3 seconds (effective 375.1 kbit/s)...
#Hash of data verified.
#Compressed 3072 bytes to 146...
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 272.1 kbit/s)...
#Hash of data verified.
#Compressed 8192 bytes to 47...
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 447.3 kbit/s)...
#Hash of data verified.
#Compressed 2047040 bytes to 1259376...
#Wrote 2047040 bytes (1259376 compressed) at 0x00010000 in 18.7 seconds (effective 876.9 kbit/s)...
#Hash of data verified.
#Compressed 7208960 bytes to 302805...
#Wrote 7208960 bytes (302805 compressed) at 0x00910000 in 47.0 seconds (effective 1227.2 kbit/s)...
#Hash of data verified.

View File

@@ -0,0 +1,69 @@
# cd ESP32_AP-Flasher
# export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
python gzip_wwwfiles.py
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --environment ESP32_S3_16_8_YELLOW_AP
&(Join-Path $env:USERPROFILE '\.platformio\penv\Scripts\pio') run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
# mkdir ESP32_S3_16_8_YELLOW_AP
copy "$env:USERPROFILE\.platformio\packages\framework-arduinoespressif32\tools\partitions\boot_app0.bin" ESP32_S3_16_8_YELLOW_AP\boot_app0.bin
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\firmware.bin ESP32_S3_16_8_YELLOW_AP\firmware.bin
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\bootloader.bin ESP32_S3_16_8_YELLOW_AP\bootloader.bin
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\partitions.bin ESP32_S3_16_8_YELLOW_AP\partitions.bin
copy .pio\build\ESP32_S3_16_8_YELLOW_AP\littlefs.bin ESP32_S3_16_8_YELLOW_AP\littlefs.bin
copy ESP32_S3_16_8_YELLOW_AP\firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP.bin
copy ESP32_S3_16_8_YELLOW_AP\merged-firmware.bin espbinaries\ESP32_S3_16_8_YELLOW_AP_full.bin
cd ESP32_S3_16_8_YELLOW_AP
#python -m esptool --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
#python -m esptool -p COM4 -b 460800 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_size detect 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd ..
#esptool.py v4.7.0
#Serial port COM4
#Connecting...
#Chip is ESP32-S3 (QFN56) (revision v0.2)
#Features: WiFi, BLE, Embedded PSRAM 8MB (AP_3v3)
#Crystal is 40MHz
#MAC: dc:da:0c:16:cf:4c
#Uploading stub...
#Running stub...
#Stub running...
#Changing baud rate to 460800
#Changed.
#Configuring flash size...
#Auto-detected Flash size: 16MB
#Flash will be erased from 0x00000000 to 0x00003fff...
#Flash will be erased from 0x00008000 to 0x00008fff...
#Flash will be erased from 0x0000e000 to 0x0000ffff...
#Flash will be erased from 0x00010000 to 0x001dbfff...
#Flash will be erased from 0x00910000 to 0x00feffff...
#Compressed 15104 bytes to 10401...
#Wrote 15104 bytes (10401 compressed) at 0x00000000 in 0.4 seconds (effective 277.3 kbit/s)...
#Hash of data verified.
#Compressed 3072 bytes to 146...
#Wrote 3072 bytes (146 compressed) at 0x00008000 in 0.1 seconds (effective 425.0 kbit/s)...
#Hash of data verified.
#Compressed 8192 bytes to 47...
#Wrote 8192 bytes (47 compressed) at 0x0000e000 in 0.1 seconds (effective 632.5 kbit/s)...
#Hash of data verified.
#Compressed 1881424 bytes to 1196500...
#Wrote 1881424 bytes (1196500 compressed) at 0x00010000 in 27.6 seconds (effective 544.8 kbit/s)...
#Hash of data verified.
#Compressed 7208960 bytes to 302804...
#Wrote 7208960 bytes (302804 compressed) at 0x00910000 in 35.0 seconds (effective 1648.8 kbit/s)...
#Hash of data verified.

View File

@@ -0,0 +1,64 @@
{
"version": 1,
"name": "LILYGO TPANEL 4\"",
"width": 480,
"height": 480,
"rotatebuffer": 0,
"bpp": 16,
"colortable": {
"white": [ 255, 255, 255 ],
"black": [ 0, 0, 0 ],
"red": [ 255, 0, 0 ]
},
"shortlut": 0,
"options": [ ],
"contentids": [ 22, 1, 2, 3, 4, 8, 7, 19, 10, 11, 21 ],
"template": {
"21": [
{ "box": [ 0, 0, 480, 480, 1 ] },
{ "text": [ 10, 15, "OpenEpaperLink AP", "calibrib30", 2, 0, 0, 1 ] },
{ "text": [ 10, 70, "IP address:", "bahnschrift30", "#888888", 0, 0, 1 ] },
{ "text": [ 180, 70, "{ap_ip}", "bahnschrift30", 0, 0, 0, 1 ] },
{ "text": [ 10, 110, "Channel:", "bahnschrift30", "#888888", 0, 0, 1 ] },
{ "text": [ 180, 110, "{ap_ch}", "bahnschrift30", 0, 0, 0, "1" ] },
{ "text": [ 10, 150, "Tag count:", "bahnschrift30", "#888888", 0, 0, 1 ] },
{ "text": [ 180, 150, "{ap_tagcount}", "bahnschrift30", 0, 0, 0, "1" ] }
],
"1": {
"weekday": [ 240, 30, "Signika-SB.ttf", 90 ],
"month": [ 240, 330, "Signika-SB.ttf", 90 ],
"day": [ 240, 80, "Signika-SB.ttf", 250 ]
},
"4": {
"location": [ 20, 20, "fonts/calibrib30" ],
"wind": [ 90, 95, "fonts/calibrib50" ],
"temp": [ 20, 200, "fonts/calibrib100" ],
"icon": [ 400, 30, 150, 2 ],
"dir": [ 40, 70, 80 ],
"umbrella": [ 325, 250, 150 ]
},
"2": {
"fonts": [ "Signika-SB.ttf", 150, 150, 110, 80, 60, 50 ],
"xy": [ 240, 240 ]
},
"8": {
"location": [ 10, 20, "fonts/calibrib50" ],
"column": [ 6, 80 ],
"day": [ 40, 100, "fonts/bahnschrift30", 144, 270 ],
"rain": [ 40, 320 ],
"icon": [ 40, 180, 50 ],
"wind": [ 17, 120 ],
"line": [ 100, 340 ]
},
"10": {
"title": [ 240, 10, "fonts/bahnschrift20" ],
"pos": [ 240, 35 ]
},
"11": {
"rotate": 0,
"mode": 1,
"days": 4,
"gridparam": [ 5, 17, 20, "calibrib16.vlw", "tahoma9.vlw", 14 ]
}
}
}

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,58 @@
#pragma once
#include <Arduino.h>
typedef void (*callbackPtr)(uint8_t percent);
class CC_interface
{
public:
uint16_t begin(uint8_t CC, uint8_t DD, uint8_t RESET);
void set_callback(callbackPtr callBack = nullptr);
uint8_t set_lock_byte(uint8_t lock_byte);
uint8_t erase_chip();
void read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
void read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
void write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[]);
void set_pc(uint16_t address);
uint8_t clock_init();
uint8_t write_code_memory(uint16_t address, uint8_t buffer[], int len);
uint8_t verify_code_memory(uint16_t address, uint8_t buffer[], int len);
uint8_t opcode(uint8_t opCode);
uint8_t opcode(uint8_t opCode, uint8_t opCode1);
uint8_t opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2);
uint8_t WR_CONFIG(uint8_t config);
uint8_t WD_CONFIG();
/* Send one byte and return one byte as answer */
uint8_t send_cc_cmdS(uint8_t cmd);
/* Send one byte and returns two bytes as answer */
uint16_t send_cc_cmd(uint8_t cmd);
void cc_send_byte(uint8_t in_byte);
uint8_t cc_receive_byte();
void enable_cc_debug();
void reset_cc();
private:
boolean dd_direction = 0; // 0=OUT 1=IN
uint8_t _CC_PIN = -1;
uint8_t _DD_PIN = -1;
uint8_t _RESET_PIN = -1;
uint8_t flash_opcode[30] = {
0x75, 0xAD, 0x00, // Set Flash Address HIGH
0x75, 0xAC, 0x00, // Set Flash Address LOW
0x90, 0xF0, 0x00, // Set RAM Address to 0xF000
0x75, 0xAE, 0x02, // Enable Flash Writing
0x7D, 0x08, // Set Loop value to Half size as we write 2bytes at once 0x100
0xE0, // Put DPTR to A
0xF5, 0xAF, // Put A to FWDATA
0xA3, // Increase DPTR;
0xE0, // Put DPTR to A
0xF5, 0xAF, // Put A to FWDATA
0xA3, // Increase DPTR
0xE5, 0xAE, // Wait till writing is done
0x20, 0xE6, 0xFB,
0xDD, 0xF1, // Loop trough all bytes
0xA5 // Breakpoint
};
callbackPtr _callback = nullptr;
};

View File

@@ -1,6 +1,98 @@
#pragma once
#include <Arduino.h>
#include <TFT_eSPI.h>
#ifdef HAS_LILYGO_TPANEL
#define LV_ATTRIBUTE_TICK_INC IRAM_ATTR
#define TOUCH_MODULES_CST_MUTUAL
// SD
#define SD_CS 38
#define SD_SCLK 36
#define SD_MOSI 35
#define SD_MISO 37
// IIC
#define IIC_SDA 17
#define IIC_SCL 18
// ESP32H2
#define ESP32H2_TX 48
#define ESP32H2_RX 47
// #define T_Panel_V1_0_RS485
#define T_Panel_V1_2_RS485
// #define T_Panel_V1_2_CAN
#if defined T_Panel_V1_0_RS485
#define RS485_TX 15
#define RS485_RX 16
#endif
#if defined T_Panel_V1_2_RS485
#define RS485_TX 16
#define RS485_RX 15
#endif
#if defined T_Panel_V1_2_CAN
#define CAN_TX 16
#define CAN_RX 15
#endif
// YDP395BT001-V2
#define LCD_WIDTH 480
#define LCD_HEIGHT 480
#define LCD_VSYNC 40
#define LCD_HSYNC 39
#define LCD_PCLK 41
#define LCD_B0 1
#define LCD_B1 2
#define LCD_B2 3
#define LCD_B3 4
#define LCD_B4 5
#define LCD_G0 6
#define LCD_G1 7
#define LCD_G2 8
#define LCD_G3 9
#define LCD_G4 10
#define LCD_G5 11
#define LCD_R0 12
#define LCD_R1 13
#define LCD_R2 42
#define LCD_R3 46
#define LCD_R4 45
#define LCD_BL 14
// CST3240
#define CST3240_ADDRESS 0x5A
#define TOUCH_SDA 17
#define TOUCH_SCL 18
#define TOUCH_INT 21
#define TOUCH_RST 4
// XL95x5
#define XL95X5_CS 17
#define XL95X5_SCLK 15
#define XL95X5_MOSI 16
#define XL95X5_TOUCH_RST 4
#define XL95X5_RS485_CON 7
#define XL95X5_LCD_RST 5
#define XL95X5_ESP32H2_IO12 1
#define XL95X5_ESP32H2_IO4 2
#define XL95X5_ESP32H2_IO5 3
// ESP32H2
#define ESP32H2_EN 34
#define ESP32H2_BOOT 33
#include "Arduino_GFX_Library.h"
extern Arduino_RGB_Display *gfx;
#endif
#ifdef HAS_TFT
extern TFT_eSPI tft2;

View File

@@ -66,12 +66,14 @@ struct Config {
uint8_t stopsleep;
uint8_t runStatus;
uint8_t preview;
uint8_t nightlyreboot;
uint8_t lock;
uint8_t wifiPower;
char timeZone[52];
uint8_t sleepTime1;
uint8_t sleepTime2;
uint8_t ble;
uint8_t discovery;
String repo;
String env;
};
@@ -111,7 +113,7 @@ extern void saveDB(const String& filename);
extern bool loadDB(const String& filename);
extern void destroyDB();
extern uint32_t getTagCount();
extern uint32_t getTagCount(uint32_t& timeoutcount);
extern uint32_t getTagCount(uint32_t& timeoutcount, uint32_t& lowbattcount);
extern void mac2hex(const uint8_t* mac, char* hexBuffer);
extern bool hex2mac(const String& hexString, uint8_t* mac);
extern void clearPending(tagRecord* taginfo);

View File

@@ -1,24 +1,28 @@
#include <Arduino.h>
#include "AsyncUDP.h"
#include "tag_db.h"
#ifndef defudpcomm
#define defudpcomm
extern Config config;
class UDPcomm {
public:
UDPcomm();
~UDPcomm();
void init();
void getAPList();
void netProcessDataReq(struct espAvailDataReq* eadr);
void netProcessXferComplete(struct espXferComplete* xfc);
void netProcessXferTimeout(struct espXferComplete* xfc);
void netSendDataAvail(struct pendingData* pending);
void netTaginfo(struct TagInfo* taginfoitem);
private:
AsyncUDP udp;
void processPacket(AsyncUDPPacket packet);
public:
UDPcomm();
~UDPcomm();
void init();
void getAPList();
void netProcessDataReq(struct espAvailDataReq* eadr);
void netProcessXferComplete(struct espXferComplete* xfc);
void netProcessXferTimeout(struct espXferComplete* xfc);
void netSendDataAvail(struct pendingData* pending);
void netTaginfo(struct TagInfo* taginfoitem);
private:
AsyncUDP udp;
void processPacket(AsyncUDPPacket packet);
void writeUdpPacket(uint8_t* buffer, uint16_t len, IPAddress senderIP);
};
#endif

View File

@@ -0,0 +1,163 @@
/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#include "Arduino_DataBus.h"
Arduino_DataBus::Arduino_DataBus() {}
void Arduino_DataBus::writeC8D8(uint8_t c, uint8_t d)
{
writeCommand(c);
write(d);
}
void Arduino_DataBus::writeC8D16(uint8_t c, uint16_t d)
{
writeCommand(c);
write16(d);
}
void Arduino_DataBus::writeC16D16(uint16_t c, uint16_t d)
{
writeCommand16(c);
write16(d);
}
void Arduino_DataBus::writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2)
{
writeCommand(c);
write16(d1);
write16(d2);
}
void Arduino_DataBus::writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2)
{
writeCommand(c);
_data16.value = d1;
write(_data16.msb);
write(_data16.lsb);
_data16.value = d2;
write(_data16.msb);
write(_data16.lsb);
}
void Arduino_DataBus::sendCommand(uint8_t c)
{
beginWrite();
writeCommand(c);
endWrite();
}
void Arduino_DataBus::sendCommand16(uint16_t c)
{
beginWrite();
writeCommand16(c);
endWrite();
}
void Arduino_DataBus::sendData(uint8_t d)
{
beginWrite();
write(d);
endWrite();
}
void Arduino_DataBus::sendData16(uint16_t d)
{
beginWrite();
write16(d);
endWrite();
}
void Arduino_DataBus::batchOperation(const uint8_t *operations, size_t len)
{
for (size_t i = 0; i < len; ++i)
{
uint8_t l = 0;
switch (operations[i])
{
case BEGIN_WRITE:
beginWrite();
break;
case WRITE_C8_D16:
writeCommand(operations[++i]);
l = 2;
break;
case WRITE_C8_D8:
writeC8D8(operations[++i], operations[++i]);
break;
case WRITE_COMMAND_8:
writeCommand(operations[++i]);
break;
case WRITE_C16_D16:
break;
case WRITE_COMMAND_16:
break;
case WRITE_DATA_8:
l = 1;
break;
case WRITE_DATA_16:
l = 2;
break;
case WRITE_BYTES:
l = operations[++i];
break;
case END_WRITE:
endWrite();
break;
case DELAY:
delay(operations[++i]);
break;
default:
printf("Unknown operation id at %d: %d", i, operations[i]);
break;
}
while (l--)
{
write(operations[++i]);
}
}
}
#if !defined(LITTLE_FOOT_PRINT)
void Arduino_DataBus::writePattern(uint8_t *data, uint8_t len, uint32_t repeat)
{
while (repeat--)
{
writeBytes(data, len);
}
}
void Arduino_DataBus::writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len)
{
while (len--)
{
write16(idx[*(data++)]);
}
}
void Arduino_DataBus::writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len)
{
uint8_t *d = data;
while (len--)
{
_data16.value = idx[*(d++)];
write(_data16.msb);
write(_data16.lsb);
write(_data16.msb);
write(_data16.lsb);
}
}
#endif // !defined(LITTLE_FOOT_PRINT)
void Arduino_DataBus::digitalWrite(uint8_t pin, uint8_t val)
{
}
int Arduino_DataBus::digitalRead(uint8_t pin)
{
}

View File

@@ -0,0 +1,292 @@
/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#ifndef _ARDUINO_DATABUS_H_
#define _ARDUINO_DATABUS_H_
#include <Arduino.h>
#define GFX_SKIP_OUTPUT_BEGIN -2
#define GFX_NOT_DEFINED -1
#define GFX_STR_HELPER(x) #x
#define GFX_STR(x) GFX_STR_HELPER(x)
#if defined(__AVR__)
#define LITTLE_FOOT_PRINT // reduce program size for limited flash MCU
#define USE_FAST_PINIO ///< Use direct PORT register access
typedef uint8_t ARDUINOGFX_PORT_t;
#elif defined(ARDUINO_ARCH_NRF52840)
#define USE_FAST_PINIO ///< Use direct PORT register access
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(TARGET_RP2040)
#define USE_FAST_PINIO ///< Use direct PORT register access
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(ESP32)
#define USE_FAST_PINIO ///< Use direct PORT register access
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(ESP8266)
#define ESP8266SAFEBATCHBITSIZE (2048 * 8 * 9)
#define USE_FAST_PINIO ///< Use direct PORT register access
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(ARDUINO_ARCH_STM32)
#define USE_FAST_PINIO ///< Use direct PORT register access
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(__arm__)
#if defined(ARDUINO_ARCH_SAMD)
// Adafruit M0, M4
#define USE_FAST_PINIO ///< Use direct PORT register access
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(CONFIG_ARCH_CHIP_CXD56XX) // Sony Spresense
#define USE_FAST_PINIO ///< Use direct PORT register access
typedef uint8_t ARDUINOGFX_PORT_t;
#elif defined(RTL8722DM)
#define USE_FAST_PINIO ///< Use direct PORT register access
typedef uint32_t ARDUINOGFX_PORT_t;
#elif defined(CORE_TEENSY)
#define USE_FAST_PINIO ///< Use direct PORT register access
#define HAS_PORT_SET_CLR ///< PORTs have set & clear registers
#if defined(__IMXRT1052__) || defined(__IMXRT1062__)
// PJRC Teensy 4.x
typedef uint32_t ARDUINOGFX_PORT_t;
#else
// PJRC Teensy 3.x
typedef uint8_t ARDUINOGFX_PORT_t;
#endif
#else
// Arduino Due?
// USE_FAST_PINIO not available here (yet)...Due has a totally different
// GPIO register set and will require some changes elsewhere (e.g. in
// constructors especially).
#endif
#else // !ARM
// Unknow architecture, USE_FAST_PINIO is not available here (yet)
// but don't worry about it too much...the digitalWrite() implementation
// on these platforms is reasonably efficient and already RAM-resident,
// only gotcha then is no parallel connection support for now.
#endif // !ARM
#ifdef USE_FAST_PINIO
typedef volatile ARDUINOGFX_PORT_t *PORTreg_t;
#endif
#if defined(ARDUINO_ARCH_ARC32) || defined(ARDUINO_MAXIM)
#define SPI_DEFAULT_FREQ 16000000
// Teensy 3.0, 3.1/3.2, 3.5, 3.6
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#define SPI_DEFAULT_FREQ 40000000
// Teensy 4.x
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
#define SPI_DEFAULT_FREQ 40000000
#elif defined(__AVR__) || defined(TEENSYDUINO)
#define SPI_DEFAULT_FREQ 8000000
#elif defined(ARDUINO_ARCH_NRF52840)
#define SPI_DEFAULT_FREQ 8000000
#elif defined(ESP8266) || defined(ESP32)
#define SPI_DEFAULT_FREQ 40000000
#elif defined(RTL8722DM)
#define SPI_DEFAULT_FREQ 20000000
#elif defined(RASPI)
#define SPI_DEFAULT_FREQ 80000000
#elif defined(ARDUINO_ARCH_STM32F1)
#define SPI_DEFAULT_FREQ 36000000
#elif defined(ARDUINO_BLACKPILL_F411CE)
#define SPI_DEFAULT_FREQ 50000000
#elif defined(F_CPU)
#define SPI_DEFAULT_FREQ (F_CPU / 4)
#else
#define SPI_DEFAULT_FREQ 24000000 ///< Default SPI data clock frequency
#endif
#ifndef UNUSED
#define UNUSED(x) (void)(x)
#endif
#define ATTR_UNUSED __attribute__((unused))
#define MSB_16(val) (((val)&0xFF00) >> 8) | (((val)&0xFF) << 8)
#define MSB_16_SET(var, val) \
{ \
(var) = MSB_16(val); \
}
#define MSB_32_SET(var, val) \
{ \
uint8_t *v = (uint8_t *)&(val); \
(var) = v[3] | (v[2] << 8) | (v[1] << 16) | (v[0] << 24); \
}
#define MSB_32_16_16_SET(var, v1, v2) \
{ \
(var) = (((uint32_t)v2 & 0xff00) << 8) | (((uint32_t)v2 & 0xff) << 24) | ((v1 & 0xff00) >> 8) | ((v1 & 0xff) << 8); \
}
#define MSB_32_8_ARRAY_SET(var, a) \
{ \
(var) = ((uint32_t)a[0] << 8 | a[1] | a[2] << 24 | a[3] << 16); \
}
#if defined(ESP32)
#define INLINE __attribute__((always_inline)) inline
#else
#define INLINE inline
#endif
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
#include <esp_lcd_panel_io.h>
#include <esp_lcd_panel_io_interface.h>
#include <esp_pm.h>
#include <esp_private/gdma.h>
#include <hal/dma_types.h>
#include <hal/lcd_hal.h>
#include <soc/dport_reg.h>
#include <soc/gpio_sig_map.h>
#include <soc/lcd_cam_reg.h>
#include <soc/lcd_cam_struct.h>
typedef struct esp_lcd_i80_bus_t esp_lcd_i80_bus_t;
typedef struct lcd_panel_io_i80_t lcd_panel_io_i80_t;
typedef struct lcd_i80_trans_descriptor_t lcd_i80_trans_descriptor_t;
struct esp_lcd_i80_bus_t
{
int bus_id; // Bus ID, index from 0
portMUX_TYPE spinlock; // spinlock used to protect i80 bus members(hal, device_list, cur_trans)
lcd_hal_context_t hal; // Hal object
size_t bus_width; // Number of data lines
intr_handle_t intr; // LCD peripheral interrupt handle
esp_pm_lock_handle_t pm_lock; // Power management lock
size_t num_dma_nodes; // Number of DMA descriptors
uint8_t *format_buffer; // The driver allocates an internal buffer for DMA to do data format transformer
size_t resolution_hz; // LCD_CLK resolution, determined by selected clock source
gdma_channel_handle_t dma_chan; // DMA channel handle
size_t psram_trans_align; // DMA transfer alignment for data allocated from PSRAM
size_t sram_trans_align; // DMA transfer alignment for data allocated from SRAM
lcd_i80_trans_descriptor_t *cur_trans; // Current transaction
lcd_panel_io_i80_t *cur_device; // Current working device
LIST_HEAD(i80_device_list, lcd_panel_io_i80_t)
device_list; // Head of i80 device list
struct
{
unsigned int exclusive : 1; // Indicate whether the I80 bus is owned by one device (whose CS GPIO is not assigned) exclusively
} flags;
dma_descriptor_t dma_nodes[]; // DMA descriptor pool, the descriptors are shared by all i80 devices
};
struct lcd_i80_trans_descriptor_t
{
lcd_panel_io_i80_t *i80_device; // i80 device issuing this transaction
int cmd_value; // Command value
uint32_t cmd_cycles; // Command cycles
const void *data; // Data buffer
uint32_t data_length; // Data buffer size
void *user_ctx; // private data used by trans_done_cb
esp_lcd_panel_io_color_trans_done_cb_t trans_done_cb; // transaction done callback
};
struct lcd_panel_io_i80_t
{
esp_lcd_panel_io_t base; // Base class of generic lcd panel io
esp_lcd_i80_bus_t *bus; // Which bus the device is attached to
int cs_gpio_num; // GPIO used for CS line
unsigned int pclk_hz; // PCLK clock frequency
size_t clock_prescale; // Prescaler coefficient, determined by user's configured PCLK frequency
QueueHandle_t trans_queue; // Transaction queue, transactions in this queue are pending for scheduler to dispatch
QueueHandle_t done_queue; // Transaction done queue, transactions in this queue are finished but not recycled by the caller
size_t queue_size; // Size of transaction queue
size_t num_trans_inflight; // Number of transactions that are undergoing (the descriptor not recycled yet)
int lcd_cmd_bits; // Bit width of LCD command
int lcd_param_bits; // Bit width of LCD parameter
void *user_ctx; // private data used when transfer color data
esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done; // color data trans done callback
LIST_ENTRY(lcd_panel_io_i80_t)
device_list_entry; // Entry of i80 device list
struct
{
unsigned int dc_idle_level : 1; // Level of DC line in IDLE phase
unsigned int dc_cmd_level : 1; // Level of DC line in CMD phase
unsigned int dc_dummy_level : 1; // Level of DC line in DUMMY phase
unsigned int dc_data_level : 1; // Level of DC line in DATA phase
} dc_levels;
struct
{
unsigned int cs_active_high : 1; // Whether the CS line is active on high level
unsigned int reverse_color_bits : 1; // Reverse the data bits, D[N:0] -> D[0:N]
unsigned int swap_color_bytes : 1; // Swap adjacent two data bytes before sending out
unsigned int pclk_active_neg : 1; // The display will write data lines when there's a falling edge on WR line
unsigned int pclk_idle_low : 1; // The WR line keeps at low level in IDLE phase
} flags;
lcd_i80_trans_descriptor_t trans_pool[]; // Transaction pool
};
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
typedef enum
{
BEGIN_WRITE,
WRITE_COMMAND_8,
WRITE_COMMAND_16,
WRITE_DATA_8,
WRITE_DATA_16,
WRITE_BYTES,
WRITE_C8_D8,
WRITE_C8_D16,
WRITE_C16_D16,
END_WRITE,
DELAY,
} spi_operation_type_t;
union
{
uint16_t value;
struct
{
uint8_t lsb;
uint8_t msb;
};
} _data16;
class Arduino_DataBus
{
public:
Arduino_DataBus();
void unused() { UNUSED(_data16); } // avoid compiler warning
virtual bool begin(int32_t speed = SPI_DEFAULT_FREQ, int8_t dataMode = GFX_NOT_DEFINED) = 0;
virtual void beginWrite() = 0;
virtual void endWrite() = 0;
virtual void writeCommand(uint8_t c) = 0;
virtual void writeCommand16(uint16_t c) = 0;
virtual void write(uint8_t) = 0;
virtual void write16(uint16_t) = 0;
virtual void writeC8D8(uint8_t c, uint8_t d);
virtual void writeC16D16(uint16_t c, uint16_t d);
virtual void writeC8D16(uint8_t c, uint16_t d);
virtual void writeC8D16D16(uint8_t c, uint16_t d1, uint16_t d2);
virtual void writeC8D16D16Split(uint8_t c, uint16_t d1, uint16_t d2);
virtual void writeRepeat(uint16_t p, uint32_t len) = 0;
virtual void writePixels(uint16_t *data, uint32_t len) = 0;
void sendCommand(uint8_t c);
void sendCommand16(uint16_t c);
void sendData(uint8_t d);
void sendData16(uint16_t d);
void batchOperation(const uint8_t *operations, size_t len);
#if !defined(LITTLE_FOOT_PRINT)
virtual void writeBytes(uint8_t *data, uint32_t len) = 0;
virtual void writePattern(uint8_t *data, uint8_t len, uint32_t repeat);
virtual void writeIndexedPixels(uint8_t *data, uint16_t *idx, uint32_t len);
virtual void writeIndexedPixelsDouble(uint8_t *data, uint16_t *idx, uint32_t len);
#endif // !defined(LITTLE_FOOT_PRINT)
virtual void digitalWrite(uint8_t pin, uint8_t val);
virtual int digitalRead(uint8_t pin);
protected:
int32_t _speed;
int8_t _dataMode;
};
#endif // _ARDUINO_DATABUS_H_

View File

@@ -0,0 +1,279 @@
#if !defined(LITTLE_FOOT_PRINT)
#include "Arduino_G.h"
/**************************************************************************/
/*!
@brief Instatiate a GFX context for graphics! Can only be done by a superclass
@param w Display width, in pixels
@param h Display height, in pixels
*/
/**************************************************************************/
Arduino_G::Arduino_G(int16_t w, int16_t h) : WIDTH(w), HEIGHT(h)
{
}
// utility functions
bool gfx_draw_bitmap_to_framebuffer(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
{
int16_t max_X = framebuffer_w - 1;
int16_t max_Y = framebuffer_h - 1;
if (
((x + bitmap_w - 1) < 0) || // Outside left
((y + bitmap_h - 1) < 0) || // Outside top
(x > max_X) || // Outside right
(y > max_Y) // Outside bottom
)
{
return false;
}
else
{
int16_t xskip = 0;
if ((y + bitmap_h - 1) > max_Y)
{
bitmap_h -= (y + bitmap_h - 1) - max_Y;
}
if (y < 0)
{
from_bitmap -= y * bitmap_w;
bitmap_h += y;
y = 0;
}
if ((x + bitmap_w - 1) > max_X)
{
xskip = (x + bitmap_w - 1) - max_X;
bitmap_w -= xskip;
}
if (x < 0)
{
from_bitmap -= x;
xskip -= x;
bitmap_w += x;
x = 0;
}
uint16_t *row = framebuffer;
row += y * framebuffer_w; // shift framebuffer to y offset
row += x; // shift framebuffer to x offset
if (((framebuffer_w & 1) == 0) && ((xskip & 1) == 0) && ((bitmap_w & 1) == 0))
{
uint32_t *row2 = (uint32_t *)row;
uint32_t *from_bitmap2 = (uint32_t *)from_bitmap;
int16_t framebuffer_w2 = framebuffer_w >> 1;
int16_t xskip2 = xskip >> 1;
int16_t w2 = bitmap_w >> 1;
int16_t j = bitmap_h;
while (j--)
{
for (int16_t i = 0; i < w2; ++i)
{
row2[i] = *from_bitmap2++;
}
from_bitmap2 += xskip2;
row2 += framebuffer_w2;
}
}
else
{
int16_t j = bitmap_h;
while (j--)
{
for (int i = 0; i < bitmap_w; ++i)
{
row[i] = *from_bitmap++;
}
from_bitmap += xskip;
row += framebuffer_w;
}
}
return true;
}
}
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
{
int16_t max_X = framebuffer_w - 1;
int16_t max_Y = framebuffer_h - 1;
if (
((x + bitmap_w - 1) < 0) || // Outside left
((y + bitmap_h - 1) < 0) || // Outside top
(x > max_X) || // Outside right
(y > max_Y) // Outside bottom
)
{
return false;
}
else
{
int16_t xskip = 0;
if ((y + bitmap_h - 1) > max_Y)
{
bitmap_h -= (y + bitmap_h - 1) - max_Y;
}
if (y < 0)
{
from_bitmap -= y * bitmap_w;
bitmap_h += y;
y = 0;
}
if ((x + bitmap_w - 1) > max_X)
{
xskip = (x + bitmap_w - 1) - max_X;
bitmap_w -= xskip;
}
if (x < 0)
{
from_bitmap -= x;
xskip -= x;
bitmap_w += x;
x = 0;
}
uint16_t *p;
int16_t i;
for (int16_t j = 0; j < bitmap_h; j++)
{
p = framebuffer;
p += (x * framebuffer_h); // shift framebuffer to y offset
p += (framebuffer_h - y - j); // shift framebuffer to x offset
i = bitmap_w;
while (i--)
{
*p = *from_bitmap++;
p += framebuffer_h;
}
from_bitmap += xskip;
}
return true;
}
}
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
{
int16_t max_X = framebuffer_w - 1;
int16_t max_Y = framebuffer_h - 1;
if (
((x + bitmap_w - 1) < 0) || // Outside left
((y + bitmap_h - 1) < 0) || // Outside top
(x > max_X) || // Outside right
(y > max_Y) // Outside bottom
)
{
return false;
}
else
{
int16_t xskip = 0;
if ((y + bitmap_h - 1) > max_Y)
{
bitmap_h -= (y + bitmap_h - 1) - max_Y;
}
if (y < 0)
{
from_bitmap -= y * bitmap_w;
bitmap_h += y;
y = 0;
}
if ((x + bitmap_w - 1) > max_X)
{
xskip = (x + bitmap_w - 1) - max_X;
bitmap_w -= xskip;
}
if (x < 0)
{
from_bitmap -= x;
xskip -= x;
bitmap_w += x;
x = 0;
}
uint16_t *row = framebuffer;
row += (max_Y - y) * framebuffer_w; // shift framebuffer to y offset
row += framebuffer_w - x - bitmap_w; // shift framebuffer to x offset
int16_t i;
int16_t j = bitmap_h;
while (j--)
{
i = bitmap_w;
while (i--)
{
row[i] = *from_bitmap++;
}
from_bitmap += xskip;
row -= framebuffer_w;
}
return true;
}
}
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h)
{
int16_t max_X = framebuffer_w - 1;
int16_t max_Y = framebuffer_h - 1;
if (
((x + bitmap_w - 1) < 0) || // Outside left
((y + bitmap_h - 1) < 0) || // Outside top
(x > max_X) || // Outside right
(y > max_Y) // Outside bottom
)
{
return false;
}
else
{
int16_t xskip = 0;
if ((y + bitmap_h - 1) > max_Y)
{
bitmap_h -= (y + bitmap_h - 1) - max_Y;
}
if (y < 0)
{
from_bitmap -= y * bitmap_w;
bitmap_h += y;
y = 0;
}
if ((x + bitmap_w - 1) > max_X)
{
xskip = (x + bitmap_w - 1) - max_X;
bitmap_w -= xskip;
}
if (x < 0)
{
from_bitmap -= x;
xskip -= x;
bitmap_w += x;
x = 0;
}
uint16_t *p;
int16_t i;
for (int16_t j = 0; j < bitmap_h; j++)
{
p = framebuffer;
p += ((max_X - x) * framebuffer_h); // shift framebuffer to y offset
p += y + j; // shift framebuffer to x offset
i = bitmap_w;
while (i--)
{
*p = *from_bitmap++;
p -= framebuffer_h;
}
from_bitmap += xskip;
}
return true;
}
}
#endif // !defined(LITTLE_FOOT_PRINT)

View File

@@ -0,0 +1,50 @@
#if !defined(LITTLE_FOOT_PRINT)
#ifndef _ARDUINO_G_H_
#define _ARDUINO_G_H_
#include <Arduino.h>
#include "Arduino_DataBus.h"
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
class Arduino_G
{
public:
Arduino_G(int16_t w, int16_t h); // Constructor
// This MUST be defined by the subclass:
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg) = 0;
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) = 0;
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) = 0;
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h) = 0;
protected:
int16_t
WIDTH, ///< This is the 'raw' display width - never changes
HEIGHT; ///< This is the 'raw' display height - never changes
};
#endif // _ARDUINO_G_H_
// utility functions
bool gfx_draw_bitmap_to_framebuffer(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
bool gfx_draw_bitmap_to_framebuffer_rotate_1(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
bool gfx_draw_bitmap_to_framebuffer_rotate_2(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
bool gfx_draw_bitmap_to_framebuffer_rotate_3(
uint16_t *from_bitmap, int16_t bitmap_w, int16_t bitmap_h,
uint16_t *framebuffer, int16_t x, int16_t y, int16_t framebuffer_w, int16_t framebuffer_h);
#endif // !defined(LITTLE_FOOT_PRINT)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,447 @@
/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#ifndef _ARDUINO_GFX_H_
#define _ARDUINO_GFX_H_
#include <Arduino.h>
#include <Print.h>
#include "Arduino_G.h"
#include "Arduino_DataBus.h"
#if !defined(ATTINY_CORE)
#include "gfxfont.h"
#endif // !defined(ATTINY_CORE)
#ifndef DEGTORAD
#define DEGTORAD 0.017453292519943295769236907684886F
#endif
#define RGB565(r, g, b) ((((r)&0xF8) << 8) | (((g)&0xFC) << 3) | ((b) >> 3))
#define RGB16TO24(c) ((((uint32_t)c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x1F) << 3))
#define RGB565_BLACK RGB565(0, 0, 0)
#define RGB565_NAVY RGB565(0, 0, 123)
#define RGB565_DARKGREEN RGB565(0, 125, 0)
#define RGB565_DARKCYAN RGB565(0, 125, 123)
#define RGB565_MAROON RGB565(123, 0, 0)
#define RGB565_PURPLE RGB565(123, 0, 123)
#define RGB565_OLIVE RGB565(123, 125, 0)
#define RGB565_LIGHTGREY RGB565(198, 195, 198)
#define RGB565_DARKGREY RGB565(123, 125, 123)
#define RGB565_BLUE RGB565(0, 0, 255)
#define RGB565_GREEN RGB565(0, 255, 0)
#define RGB565_CYAN RGB565(0, 255, 255)
#define RGB565_RED RGB565(255, 0, 0)
#define RGB565_MAGENTA RGB565(255, 0, 255)
#define RGB565_YELLOW RGB565(255, 255, 0)
#define RGB565_WHITE RGB565(255, 255, 255)
#define RGB565_ORANGE RGB565(255, 165, 0)
#define RGB565_GREENYELLOW RGB565(173, 255, 41)
#define RGB565_PINK RGB565(255, 130, 198)
// Color definitions
#ifndef DISABLE_COLOR_DEFINES
#define BLACK RGB565_BLACK
#define NAVY RGB565_NAVY
#define DARKGREEN RGB565_DARKGREEN
#define DARKCYAN RGB565_DARKCYAN
#define MAROON RGB565_MAROON
#define PURPLE RGB565_PURPLE
#define OLIVE RGB565_OLIVE
#define LIGHTGREY RGB565_LIGHTGREY
#define DARKGREY RGB565_DARKGREY
#define BLUE RGB565_BLUE
#define GREEN RGB565_GREEN
#define CYAN RGB565_CYAN
#define RED RGB565_RED
#define MAGENTA RGB565_MAGENTA
#define YELLOW RGB565_YELLOW
#define WHITE RGB565_WHITE
#define ORANGE RGB565_ORANGE
#define GREENYELLOW RGB565_GREENYELLOW
#define PINK RGB565_PINK
#endif
// Many (but maybe not all) non-AVR board installs define macros
// for compatibility with existing PROGMEM-reading AVR code.
// Do our own checks and defines here for good measure...
#ifndef pgm_read_byte
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#endif
#ifndef pgm_read_word
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
#ifndef pgm_read_dword
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
#endif
// workaround of a15 asm compile error
#ifdef ESP8266
#undef pgm_read_word
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
#endif
// Pointers are a peculiar case...typically 16-bit on AVR boards,
// 32 bits elsewhere. Try to accommodate both...
#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF)
#define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr))
#else
#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
#endif
#ifndef _swap_uint8_t
#define _swap_uint8_t(a, b) \
{ \
uint8_t t = a; \
a = b; \
b = t; \
}
#endif
#ifndef _swap_int16_t
#define _swap_int16_t(a, b) \
{ \
int16_t t = a; \
a = b; \
b = t; \
}
#endif
#ifndef _diff
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
#endif
#ifndef _ordered_in_range
#define _ordered_in_range(v, a, b) ((a <= v) && (v <= b))
#endif
#ifndef _in_range
#define _in_range(v, a, b) ((a > b) ? _ordered_in_range(v, b, a) : _ordered_in_range(v, a, b))
#endif
#if !defined(ATTINY_CORE)
INLINE GFXglyph *pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c)
{
#ifdef __AVR__
return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
#else
// expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
// So expression may be simplified
return gfxFont->glyph + c;
#endif //__AVR__
}
INLINE uint8_t *pgm_read_bitmap_ptr(const GFXfont *gfxFont)
{
#ifdef __AVR__
return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap);
#else
// expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning
// In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way
// So expression may be simplified
return gfxFont->bitmap;
#endif //__AVR__
}
#endif // !defined(ATTINY_CORE)
/// A generic graphics superclass that can handle all sorts of drawing. At a minimum you can subclass and provide drawPixel(). At a maximum you can do a ton of overriding to optimize. Used for any/all Adafruit displays!
#if defined(LITTLE_FOOT_PRINT)
class Arduino_GFX : public Print
#else
class Arduino_GFX : public Print, public Arduino_G
#endif // !defined(LITTLE_FOOT_PRINT)
{
public:
Arduino_GFX(int16_t w, int16_t h); // Constructor
// This MUST be defined by the subclass:
virtual bool begin(int32_t speed = GFX_NOT_DEFINED) = 0;
virtual void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) = 0;
// TRANSACTION API / CORE DRAW API
// These MAY be overridden by the subclass to provide device-specific
// optimized code. Otherwise 'generic' versions are used.
virtual void startWrite();
virtual void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
virtual void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
virtual void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
virtual void writeLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
virtual void endWrite(void);
// CONTROL API
// These MAY be overridden by the subclass to provide device-specific
// optimized code. Otherwise 'generic' versions are used.
virtual void setRotation(uint8_t r);
virtual void invertDisplay(bool i);
virtual void displayOn();
virtual void displayOff();
// BASIC DRAW API
// These MAY be overridden by the subclass to provide device-specific
// optimized code. Otherwise 'generic' versions are used.
// It's good to implement those, even if using transaction API
void writePixel(int16_t x, int16_t y, uint16_t color);
void drawPixel(int16_t x, int16_t y, uint16_t color);
void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color);
void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color);
void writeFillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void fillScreen(uint16_t color);
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color);
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint16_t color);
void drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h, int16_t radius, uint16_t color);
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color);
void drawXBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color);
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], const uint8_t mask[], int16_t w, int16_t h);
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
void getTextBounds(const char *string, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const __FlashStringHelper *s, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void getTextBounds(const String &str, int16_t x, int16_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h);
void setTextSize(uint8_t s);
void setTextSize(uint8_t sx, uint8_t sy);
void setTextSize(uint8_t sx, uint8_t sy, uint8_t pixel_margin);
#if !defined(ATTINY_CORE)
void setFont(const GFXfont *f = NULL);
#if defined(U8G2_FONT_SUPPORT)
void setFont(const uint8_t *font);
void setUTF8Print(bool isEnable);
uint16_t u8g2_font_get_word(const uint8_t *font, uint8_t offset);
uint8_t u8g2_font_decode_get_unsigned_bits(uint8_t cnt);
int8_t u8g2_font_decode_get_signed_bits(uint8_t cnt);
void u8g2_font_decode_len(uint8_t len, uint8_t is_foreground, uint16_t color, uint16_t bg);
#endif // defined(U8G2_FONT_SUPPORT)
virtual void flush(void);
#endif // !defined(ATTINY_CORE)
// adopt from LovyanGFX
void drawEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
void drawEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, uint16_t color);
void fillEllipse(int16_t x, int16_t y, int16_t rx, int16_t ry, uint16_t color);
void fillEllipseHelper(int32_t x, int32_t y, int32_t rx, int32_t ry, uint8_t cornername, int16_t delta, uint16_t color);
void drawArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
void fillArc(int16_t x, int16_t y, int16_t r1, int16_t r2, float start, float end, uint16_t color);
void fillArcHelper(int16_t cx, int16_t cy, int16_t oradius, int16_t iradius, float start, float end, uint16_t color);
// TFT optimization code, too big for ATMEL family
#if defined(LITTLE_FOOT_PRINT)
void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
#else // !defined(LITTLE_FOOT_PRINT)
virtual void writeSlashLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color);
virtual void drawBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h, uint16_t color, uint16_t bg);
virtual void drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bg);
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
virtual void drawGrayscaleBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0);
virtual void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, uint8_t chroma_key, int16_t w, int16_t h, int16_t x_skip = 0);
virtual void draw3bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint8_t *mask, int16_t w, int16_t h);
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, const uint16_t bitmap[], int16_t w, int16_t h);
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
virtual void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, uint16_t transparent_color, int16_t w, int16_t h);
virtual void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h);
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, const uint8_t bitmap[], int16_t w, int16_t h);
virtual void draw24bitRGBBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h);
virtual void drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg);
#endif // !defined(LITTLE_FOOT_PRINT)
/**********************************************************************/
/*!
@brief Set text cursor location
@param x X coordinate in pixels
@param y Y coordinate in pixels
*/
/**********************************************************************/
void setCursor(int16_t x, int16_t y)
{
cursor_x = x;
cursor_y = y;
}
/**********************************************************************/
/*!
@brief Set text font color with transparant background
@param c 16-bit 5-6-5 Color to draw text with
@note For 'transparent' background, background and foreground
are set to same color rather than using a separate flag.
*/
/**********************************************************************/
void setTextColor(uint16_t c) { textcolor = textbgcolor = c; }
/**********************************************************************/
/*!
@brief Set text font color with custom background color
@param c 16-bit 5-6-5 Color to draw text with
@param bg 16-bit 5-6-5 Color to draw background/fill with
*/
/**********************************************************************/
void setTextColor(uint16_t c, uint16_t bg)
{
textcolor = c;
textbgcolor = bg;
}
/**********************************************************************/
/*!
@brief Set whether text that is too long for the screen width should
automatically wrap around to the next line (else clip right).
@param w true for wrapping, false for clipping
*/
/**********************************************************************/
void setTextWrap(bool w) { wrap = w; }
virtual size_t write(uint8_t);
/************************************************************************/
/*!
@brief Get width of the display, accounting for current rotation
@returns Width in pixels
*/
/************************************************************************/
int16_t width(void) const { return _width; };
/************************************************************************/
/*!
@brief Get height of the display, accounting for current rotation
@returns Height in pixels
*/
/************************************************************************/
int16_t height(void) const { return _height; }
/************************************************************************/
/*!
@brief Get rotation setting for display
@returns 0 thru 3 corresponding to 4 cardinal rotations
*/
/************************************************************************/
uint8_t getRotation(void) const { return _rotation; }
// get current cursor position (get rotation safe maximum values,
// using: width() for x, height() for y)
/************************************************************************/
/*!
@brief Get text cursor X location
@returns X coordinate in pixels
*/
/************************************************************************/
int16_t getCursorX(void) const { return cursor_x; }
/************************************************************************/
/*!
@brief Get text cursor Y location
@returns Y coordinate in pixels
*/
/************************************************************************/
int16_t getCursorY(void) const { return cursor_y; };
/*!
@brief Given 8-bit red, green and blue values, return a 'packed'
16-bit color value in '565' RGB format (5 bits red, 6 bits
green, 5 bits blue). This is just a mathematical operation,
no hardware is touched.
@param red 8-bit red brightnesss (0 = off, 255 = max).
@param green 8-bit green brightnesss (0 = off, 255 = max).
@param blue 8-bit blue brightnesss (0 = off, 255 = max).
@return 'Packed' 16-bit color value (565 format).
*/
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue)
{
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
}
protected:
void charBounds(char c, int16_t *x, int16_t *y, int16_t *minx, int16_t *miny, int16_t *maxx, int16_t *maxy);
int16_t
_width, ///< Display width as modified by current rotation
_height, ///< Display height as modified by current rotation
_max_x, ///< x zero base bound (_width - 1)
_max_y, ///< y zero base bound (_height - 1)
cursor_x, ///< x location to start print()ing text
cursor_y; ///< y location to start print()ing text
uint16_t
textcolor, ///< 16-bit background color for print()
textbgcolor; ///< 16-bit text color for print()
uint8_t
textsize_x, ///< Desired magnification in X-axis of text to print()
textsize_y, ///< Desired magnification in Y-axis of text to print()
text_pixel_margin, ///< Margin for each text pixel
_rotation; ///< Display rotation (0 thru 3)
bool
wrap; ///< If set, 'wrap' text at right edge of display
#if !defined(ATTINY_CORE)
GFXfont *gfxFont; ///< Pointer to special font
#endif // !defined(ATTINY_CORE)
#if defined(U8G2_FONT_SUPPORT)
uint8_t *u8g2Font;
bool _enableUTF8Print = false;
uint8_t _utf8_state = 0;
uint16_t _encoding;
uint8_t _u8g2_glyph_cnt;
uint8_t _u8g2_bits_per_0;
uint8_t _u8g2_bits_per_1;
uint8_t _u8g2_bits_per_char_width;
uint8_t _u8g2_bits_per_char_height;
uint8_t _u8g2_bits_per_char_x;
uint8_t _u8g2_bits_per_char_y;
uint8_t _u8g2_bits_per_delta_x;
int8_t _u8g2_max_char_width;
int8_t _u8g2_max_char_height;
uint16_t _u8g2_start_pos_upper_A;
uint16_t _u8g2_start_pos_lower_a;
uint16_t _u8g2_start_pos_unicode;
uint8_t _u8g2_first_char;
uint8_t _u8g2_char_width;
uint8_t _u8g2_char_height;
int8_t _u8g2_char_x;
int8_t _u8g2_char_y;
int8_t _u8g2_delta_x;
int8_t _u8g2_dx;
int8_t _u8g2_dy;
uint16_t _u8g2_target_x;
uint16_t _u8g2_target_y;
const uint8_t *_u8g2_decode_ptr;
uint8_t _u8g2_decode_bit_pos;
#endif // defined(U8G2_FONT_SUPPORT)
#if defined(LITTLE_FOOT_PRINT)
int16_t
WIDTH, ///< This is the 'raw' display width - never changes
HEIGHT; ///< This is the 'raw' display height - never changes
#endif // defined(LITTLE_FOOT_PRINT)
};
#endif // _ARDUINO_GFX_H_

View File

@@ -0,0 +1,209 @@
#ifndef _ARDUINO_GFX_LIBRARIES_H_
#define _ARDUINO_GFX_LIBRARIES_H_
#include "Arduino_DataBus.h"
#include "databus/Arduino_ESP32RGBPanel.h"
#include "databus/Arduino_SWSPI.h"
#include "databus/Arduino_XL9535SWSPI.h"
#include "Arduino_GFX.h" // Core graphics library
#include "display/Arduino_RGB_Display.h"
#if defined(ARDUINO_ARCH_SAMD) && defined(SEEED_GROVE_UI_WIRELESS)
#define DISPLAY_DEV_KIT
#define WIO_TERMINAL
#define DF_GFX_CS LCD_SS_PIN
#define DF_GFX_DC LCD_DC
#define DF_GFX_RST GFX_NOT_DEFINED
#define DF_GFX_BL LCD_BACKLIGHT
#elif defined(ARDUINO_ESP32_S3_BOX)
#define DISPLAY_DEV_KIT
#define ESP32_S3_BOX
#define DF_GFX_SCK TFT_CLK
#define DF_GFX_MOSI TFT_MOSI
#define DF_GFX_MISO TFT_MISO
#define DF_GFX_CS TFT_CS
#define DF_GFX_DC TFT_DC
#define DF_GFX_RST TFT_RST
#define DF_GFX_BL TFT_BL
#elif defined(ARDUINO_M5Stack_Core_ESP32) || defined(ARDUINO_M5STACK_FIRE)
#define DISPLAY_DEV_KIT
#define M5STACK_CORE
#define DF_GFX_SCK 18
#define DF_GFX_MOSI 23
#define DF_GFX_MISO 19
#define DF_GFX_CS 14
#define DF_GFX_DC 27
#define DF_GFX_RST 33
#define DF_GFX_BL 32
#elif defined(ARDUINO_M5Stack_ATOMS3)
#define DISPLAY_DEV_KIT
#define M5STACK_ATOMS3
#define DF_GFX_SCK 17
#define DF_GFX_MOSI 21
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 15
#define DF_GFX_DC 33
#define DF_GFX_RST 34
#define DF_GFX_BL 16
#elif defined(ARDUINO_ODROID_ESP32)
#define DISPLAY_DEV_KIT
#define ODROID_GO
#define DF_GFX_SCK 18
#define DF_GFX_MOSI 23
#define DF_GFX_MISO 19
#define DF_GFX_CS 5
#define DF_GFX_DC 21
#define DF_GFX_RST GFX_NOT_DEFINED
#define DF_GFX_BL 14
/* TTGO T-Watch */
#elif defined(ARDUINO_T) || defined(ARDUINO_TWATCH_BASE) || defined(ARDUINO_TWATCH_2020_V1) || defined(ARDUINO_TWATCH_2020_V2)
#define DISPLAY_DEV_KIT
#define TTGO_T_WATCH
#define DF_GFX_SCK 18
#define DF_GFX_MOSI 19
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 5
#define DF_GFX_DC 27
#define DF_GFX_RST GFX_NOT_DEFINED
#define DF_GFX_BL 12
/* Waveshare RP2040-LCD-1.28 */
#elif defined(ARDUINO_WAVESHARE_RP2040_LCD_1_28)
#define DISPLAY_DEV_KIT
#define WAVESHARE_RP2040_LCD_1_28
#define DF_GFX_SCK 10
#define DF_GFX_MOSI 11
#define DF_GFX_MISO 12
#define DF_GFX_CS 9
#define DF_GFX_DC 8
#define DF_GFX_RST 12
#define DF_GFX_BL 25
#define DF_GFX_SPI spi1
#elif defined(ARDUINO_ARCH_NRF52840)
#define DF_GFX_SCK 13
#define DF_GFX_MOSI 11
#define DF_GFX_MISO 12
#define DF_GFX_CS 9
#define DF_GFX_DC 8
#define DF_GFX_RST 7
#define DF_GFX_BL 6
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
// PJRC Teensy 4.x
#define DF_GFX_SCK 13
#define DF_GFX_MOSI 11
#define DF_GFX_MISO 12
#define DF_GFX_CS 39 // GFX_NOT_DEFINED for display without CS pin
#define DF_GFX_DC 41
#define DF_GFX_RST 40
#define DF_GFX_BL 22
#elif defined(ARDUINO_BLACKPILL_F411CE)
#define DF_GFX_SCK 5
#define DF_GFX_MOSI 7
#define DF_GFX_MISO 6
#define DF_GFX_CS 4
#define DF_GFX_DC 3
#define DF_GFX_RST 2
#define DF_GFX_BL 1
#elif defined(TARGET_RP2040)
#define DF_GFX_SCK 18
#define DF_GFX_MOSI 19
#define DF_GFX_MISO 16
#define DF_GFX_CS 17
#define DF_GFX_DC 27
#define DF_GFX_RST 26
#define DF_GFX_BL 28
#define DF_GFX_SPI spi0
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32)
#define DF_GFX_SCK 18
#define DF_GFX_MOSI 23
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 5
#define DF_GFX_DC 27
#define DF_GFX_RST 33
#define DF_GFX_BL 22
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S2)
#define DF_GFX_SCK 36
#define DF_GFX_MOSI 35
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 34
#define DF_GFX_DC 38
#define DF_GFX_RST 33
#define DF_GFX_BL 21
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
#define DF_GFX_SCK 36
#define DF_GFX_MOSI 35
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 40
#define DF_GFX_DC 41
#define DF_GFX_RST 42
#define DF_GFX_BL 48
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
#define DF_GFX_SCK 4
#define DF_GFX_MOSI 6
#define DF_GFX_MISO GFX_NOT_DEFINED
#define DF_GFX_CS 7
#define DF_GFX_DC 2
#define DF_GFX_RST 1
#define DF_GFX_BL 3
#elif defined(ESP8266)
#define DF_GFX_SCK 14
#define DF_GFX_MOSI 13
#define DF_GFX_MISO 12
#define DF_GFX_CS 15
#define DF_GFX_DC 4
#define DF_GFX_RST 2
#define DF_GFX_BL 5
#elif defined(RTL8722DM)
#if defined(BOARD_RTL8720DN_BW16)
#define DF_GFX_SCK 10
#define DF_GFX_MOSI 12
#define DF_GFX_MISO 11
#define DF_GFX_CS 9
#define DF_GFX_DC 8
#define DF_GFX_RST 6
#define DF_GFX_BL 3
#elif defined(BOARD_RTL8722DM)
#define DF_GFX_SCK 13
#define DF_GFX_MOSI 11
#define DF_GFX_MISO 12
#define DF_GFX_CS 18
#define DF_GFX_DC 17
#define DF_GFX_RST 22
#define DF_GFX_BL 23
#elif defined(BOARD_RTL8722DM_MINI)
#define DF_GFX_SCK 11
#define DF_GFX_MOSI 9
#define DF_GFX_MISO 10
#define DF_GFX_CS 12
#define DF_GFX_DC 14
#define DF_GFX_RST 15
#define DF_GFX_BL 13
#else // old version
#define DF_GFX_SCK 19
#define DF_GFX_MOSI 21
#define DF_GFX_MISO 20
#define DF_GFX_CS 18 // GFX_NOT_DEFINED for display without CS pin
#define DF_GFX_DC 17
#define DF_GFX_RST 2
#define DF_GFX_BL 23
#endif
#elif defined(SEEED_XIAO_M0)
#define DF_GFX_SCK 8
#define DF_GFX_MOSI 10
#define DF_GFX_MISO 9
#define DF_GFX_CS 3 // GFX_NOT_DEFINED for display without CS pin
#define DF_GFX_DC 2
#define DF_GFX_RST 1
#define DF_GFX_BL 0
#else // default pins for Arduino Nano, Mini, Micro and more
#define DF_GFX_SCK 13
#define DF_GFX_MOSI 11
#define DF_GFX_MISO 12
#define DF_GFX_CS 9
#define DF_GFX_DC 8
#define DF_GFX_RST 7
#define DF_GFX_BL 6
#endif
#endif // _ARDUINO_GFX_LIBRARIES_H_

View File

@@ -0,0 +1,129 @@
#include "Arduino_ESP32RGBPanel.h"
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
Arduino_ESP32RGBPanel::Arduino_ESP32RGBPanel(
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
uint16_t pclk_active_neg, int32_t prefer_speed, bool useBigEndian,
uint16_t de_idle_high, uint16_t pclk_idle_high)
: _de(de), _vsync(vsync), _hsync(hsync), _pclk(pclk),
_r0(r0), _r1(r1), _r2(r2), _r3(r3), _r4(r4),
_g0(g0), _g1(g1), _g2(g2), _g3(g3), _g4(g4), _g5(g5),
_b0(b0), _b1(b1), _b2(b2), _b3(b3), _b4(b4),
_hsync_polarity(hsync_polarity), _hsync_front_porch(hsync_front_porch), _hsync_pulse_width(hsync_pulse_width), _hsync_back_porch(hsync_back_porch),
_vsync_polarity(vsync_polarity), _vsync_front_porch(vsync_front_porch), _vsync_pulse_width(vsync_pulse_width), _vsync_back_porch(vsync_back_porch),
_pclk_active_neg(pclk_active_neg), _prefer_speed(prefer_speed), _useBigEndian(useBigEndian),
_de_idle_high(de_idle_high), _pclk_idle_high(pclk_idle_high)
{
}
bool Arduino_ESP32RGBPanel::begin(int32_t speed)
{
if (speed == GFX_NOT_DEFINED)
{
#ifdef CONFIG_SPIRAM_MODE_QUAD
_speed = 6000000L;
#else
_speed = 12000000L;
#endif
}
else
{
_speed = speed;
}
return true;
}
uint16_t *Arduino_ESP32RGBPanel::getFrameBuffer(int16_t w, int16_t h)
{
esp_lcd_rgb_panel_config_t *_panel_config = (esp_lcd_rgb_panel_config_t *)heap_caps_calloc(1, sizeof(esp_lcd_rgb_panel_config_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
_panel_config->clk_src = LCD_CLK_SRC_PLL160M;
_panel_config->timings.pclk_hz = (_prefer_speed == GFX_NOT_DEFINED) ? _speed : _prefer_speed;
_panel_config->timings.h_res = w;
_panel_config->timings.v_res = h;
// The following parameters should refer to LCD spec
_panel_config->timings.hsync_pulse_width = _hsync_pulse_width;
_panel_config->timings.hsync_back_porch = _hsync_back_porch;
_panel_config->timings.hsync_front_porch = _hsync_front_porch;
_panel_config->timings.vsync_pulse_width = _vsync_pulse_width;
_panel_config->timings.vsync_back_porch = _vsync_back_porch;
_panel_config->timings.vsync_front_porch = _vsync_front_porch;
_panel_config->timings.flags.hsync_idle_low = (_hsync_polarity == 0) ? 1 : 0;
_panel_config->timings.flags.vsync_idle_low = (_vsync_polarity == 0) ? 1 : 0;
_panel_config->timings.flags.de_idle_high = _de_idle_high;
_panel_config->timings.flags.pclk_active_neg = _pclk_active_neg;
_panel_config->timings.flags.pclk_idle_high = _pclk_idle_high;
_panel_config->data_width = 16; // RGB565 in parallel mode, thus 16bit in width
_panel_config->sram_trans_align = 8;
_panel_config->psram_trans_align = 64;
_panel_config->hsync_gpio_num = _hsync;
_panel_config->vsync_gpio_num = _vsync;
_panel_config->de_gpio_num = _de;
_panel_config->pclk_gpio_num = _pclk;
if (_useBigEndian)
{
_panel_config->data_gpio_nums[0] = _g3;
_panel_config->data_gpio_nums[1] = _g4;
_panel_config->data_gpio_nums[2] = _g5;
_panel_config->data_gpio_nums[3] = _r0;
_panel_config->data_gpio_nums[4] = _r1;
_panel_config->data_gpio_nums[5] = _r2;
_panel_config->data_gpio_nums[6] = _r3;
_panel_config->data_gpio_nums[7] = _r4;
_panel_config->data_gpio_nums[8] = _b0;
_panel_config->data_gpio_nums[9] = _b1;
_panel_config->data_gpio_nums[10] = _b2;
_panel_config->data_gpio_nums[11] = _b3;
_panel_config->data_gpio_nums[12] = _b4;
_panel_config->data_gpio_nums[13] = _g0;
_panel_config->data_gpio_nums[14] = _g1;
_panel_config->data_gpio_nums[15] = _g2;
}
else
{
_panel_config->data_gpio_nums[0] = _b0;
_panel_config->data_gpio_nums[1] = _b1;
_panel_config->data_gpio_nums[2] = _b2;
_panel_config->data_gpio_nums[3] = _b3;
_panel_config->data_gpio_nums[4] = _b4;
_panel_config->data_gpio_nums[5] = _g0;
_panel_config->data_gpio_nums[6] = _g1;
_panel_config->data_gpio_nums[7] = _g2;
_panel_config->data_gpio_nums[8] = _g3;
_panel_config->data_gpio_nums[9] = _g4;
_panel_config->data_gpio_nums[10] = _g5;
_panel_config->data_gpio_nums[11] = _r0;
_panel_config->data_gpio_nums[12] = _r1;
_panel_config->data_gpio_nums[13] = _r2;
_panel_config->data_gpio_nums[14] = _r3;
_panel_config->data_gpio_nums[15] = _r4;
}
_panel_config->disp_gpio_num = GPIO_NUM_NC;
_panel_config->flags.disp_active_low = 0;
_panel_config->flags.relax_on_idle = 0;
_panel_config->flags.fb_in_psram = 1; // allocate frame buffer in PSRAM
ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(_panel_config, &_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_reset(_panel_handle));
ESP_ERROR_CHECK(esp_lcd_panel_init(_panel_handle));
uint16_t color = random(0xffff);
ESP_ERROR_CHECK(_panel_handle->draw_bitmap(_panel_handle, 0, 0, 1, 1, &color));
_rgb_panel = __containerof(_panel_handle, esp_rgb_panel_t, base);
return (uint16_t *)_rgb_panel->fb;
}
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)

View File

@@ -0,0 +1,100 @@
#include "Arduino_DataBus.h"
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
#ifndef _ARDUINO_ESP32RGBPANEL_H_
#define _ARDUINO_ESP32RGBPANEL_H_
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_rgb.h"
#include "esp_lcd_panel_vendor.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_interface.h"
#include "esp_private/gdma.h"
#include "esp_pm.h"
#include "hal/dma_types.h"
#include "hal/lcd_hal.h"
#include "hal/lcd_ll.h"
#include "esp32s3/rom/cache.h"
// This function is located in ROM (also see esp_rom/${target}/ld/${target}.rom.ld)
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
// extract from esp-idf esp_lcd_rgb_panel.c
struct esp_rgb_panel_t
{
esp_lcd_panel_t base; // Base class of generic lcd panel
int panel_id; // LCD panel ID
lcd_hal_context_t hal; // Hal layer object
size_t data_width; // Number of data lines (e.g. for RGB565, the data width is 16)
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
intr_handle_t intr; // LCD peripheral interrupt handle
esp_pm_lock_handle_t pm_lock; // Power management lock
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
uint8_t *fb; // Frame buffer
size_t fb_size; // Size of frame buffer
int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
size_t resolution_hz; // Peripheral clock resolution
esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
gdma_channel_handle_t dma_chan; // DMA channel handle
esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done
void *user_ctx; // Reserved user's data of callback functions
int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window
int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window
struct
{
unsigned int disp_en_level : 1; // The level which can turn on the screen by `disp_gpio_num`
unsigned int stream_mode : 1; // If set, the LCD transfers data continuously, otherwise, it stops refreshing the LCD when transaction done
unsigned int fb_in_psram : 1; // Whether the frame buffer is in PSRAM
} flags;
dma_descriptor_t dma_nodes[]; // DMA descriptor pool of size `num_dma_nodes`
};
class Arduino_ESP32RGBPanel
{
public:
Arduino_ESP32RGBPanel(
int8_t de, int8_t vsync, int8_t hsync, int8_t pclk,
int8_t r0, int8_t r1, int8_t r2, int8_t r3, int8_t r4,
int8_t g0, int8_t g1, int8_t g2, int8_t g3, int8_t g4, int8_t g5,
int8_t b0, int8_t b1, int8_t b2, int8_t b3, int8_t b4,
uint16_t hsync_polarity, uint16_t hsync_front_porch, uint16_t hsync_pulse_width, uint16_t hsync_back_porch,
uint16_t vsync_polarity, uint16_t vsync_front_porch, uint16_t vsync_pulse_width, uint16_t vsync_back_porch,
uint16_t pclk_active_neg = 0, int32_t prefer_speed = GFX_NOT_DEFINED, bool useBigEndian = false,
uint16_t de_idle_high = 0, uint16_t pclk_idle_high = 0);
bool begin(int32_t speed = GFX_NOT_DEFINED);
uint16_t *getFrameBuffer(int16_t w, int16_t h);
protected:
private:
int32_t _speed;
int8_t _de, _vsync, _hsync, _pclk;
int8_t _r0, _r1, _r2, _r3, _r4;
int8_t _g0, _g1, _g2, _g3, _g4, _g5;
int8_t _b0, _b1, _b2, _b3, _b4;
uint16_t _hsync_polarity;
uint16_t _hsync_front_porch;
uint16_t _hsync_pulse_width;
uint16_t _hsync_back_porch;
uint16_t _vsync_polarity;
uint16_t _vsync_front_porch;
uint16_t _vsync_pulse_width;
uint16_t _vsync_back_porch;
uint16_t _pclk_active_neg;
int32_t _prefer_speed;
bool _useBigEndian;
uint16_t _de_idle_high;
uint16_t _pclk_idle_high;
esp_lcd_panel_handle_t _panel_handle = NULL;
esp_rgb_panel_t *_rgb_panel;
};
#endif // _ARDUINO_ESP32RGBPANEL_H_
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)

View File

@@ -0,0 +1,696 @@
/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#include "Arduino_SWSPI.h"
Arduino_SWSPI::Arduino_SWSPI(int8_t dc, int8_t cs, int8_t sck, int8_t mosi, int8_t miso /* = GFX_NOT_DEFINED */)
: _dc(dc), _cs(cs), _sck(sck), _mosi(mosi), _miso(miso)
{
}
bool Arduino_SWSPI::begin(int32_t speed, int8_t dataMode)
{
UNUSED(speed);
UNUSED(dataMode);
if (_dc != GFX_NOT_DEFINED)
{
pinMode(_dc, OUTPUT);
digitalWrite(_dc, HIGH); // Data mode
}
if (_cs != GFX_NOT_DEFINED)
{
pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH); // Deselect
}
pinMode(_sck, OUTPUT);
digitalWrite(_sck, LOW);
pinMode(_mosi, OUTPUT);
digitalWrite(_mosi, LOW);
if (_miso != GFX_NOT_DEFINED)
{
pinMode(_miso, INPUT);
}
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(ARDUINO_ARCH_NRF52840)
uint32_t pin;
NRF_GPIO_Type *reg;
if (_dc != GFX_NOT_DEFINED)
{
pin = digitalPinToPinName((pin_size_t)_dc);
reg = nrf_gpio_pin_port_decode(&pin);
_dcPinMask = 1UL << pin;
_dcPortSet = &reg->OUTSET;
_dcPortClr = &reg->OUTCLR;
}
if (_cs != GFX_NOT_DEFINED)
{
pin = digitalPinToPinName((pin_size_t)_cs);
NRF_GPIO_Type *reg = nrf_gpio_pin_port_decode(&pin);
_csPinMask = 1UL << pin;
_csPortSet = &reg->OUTSET;
_csPortClr = &reg->OUTCLR;
}
pin = digitalPinToPinName((pin_size_t)_sck);
reg = nrf_gpio_pin_port_decode(&pin);
_sckPinMask = 1UL << pin;
_sckPortSet = &reg->OUTSET;
_sckPortClr = &reg->OUTCLR;
pin = digitalPinToPinName((pin_size_t)_mosi);
reg = nrf_gpio_pin_port_decode(&pin);
_mosiPinMask = 1UL << pin;
_mosiPortSet = &reg->OUTSET;
_mosiPortClr = &reg->OUTCLR;
if (_miso != GFX_NOT_DEFINED)
{
pin = digitalPinToPinName((pin_size_t)_miso);
reg = nrf_gpio_pin_port_decode(&pin);
_misoPinMask = 1UL << pin;
_misoPort = &reg->IN;
}
#elif defined(TARGET_RP2040)
if (_dc != GFX_NOT_DEFINED)
{
_dcPinMask = digitalPinToBitMask(_dc);
_dcPortSet = (PORTreg_t)&sio_hw->gpio_set;
_dcPortClr = (PORTreg_t)&sio_hw->gpio_clr;
}
if (_cs != GFX_NOT_DEFINED)
{
_csPinMask = digitalPinToBitMask(_cs);
_csPortSet = (PORTreg_t)&sio_hw->gpio_set;
_csPortClr = (PORTreg_t)&sio_hw->gpio_clr;
}
_sckPinMask = digitalPinToBitMask(_sck);
_sckPortSet = (PORTreg_t)&sio_hw->gpio_set;
_sckPortClr = (PORTreg_t)&sio_hw->gpio_clr;
_mosiPinMask = digitalPinToBitMask(_mosi);
_mosiPortSet = (PORTreg_t)&sio_hw->gpio_set;
_mosiPortClr = (PORTreg_t)&sio_hw->gpio_clr;
if (_miso != GFX_NOT_DEFINED)
{
_misoPinMask = digitalPinToBitMask(_miso);
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
}
#elif defined(ESP32) && (CONFIG_IDF_TARGET_ESP32C3)
_dcPinMask = digitalPinToBitMask(_dc);
_dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
_dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
if (_cs != GFX_NOT_DEFINED)
{
_csPinMask = digitalPinToBitMask(_cs);
_csPortSet = (PORTreg_t)&GPIO.out_w1ts;
_csPortClr = (PORTreg_t)&GPIO.out_w1tc;
}
_sckPinMask = digitalPinToBitMask(_sck);
_sckPortSet = (PORTreg_t)&GPIO.out_w1ts;
_sckPortClr = (PORTreg_t)&GPIO.out_w1tc;
_mosiPinMask = digitalPinToBitMask(_mosi);
_mosiPortSet = (PORTreg_t)&GPIO.out_w1ts;
_mosiPortClr = (PORTreg_t)&GPIO.out_w1tc;
if (_miso != GFX_NOT_DEFINED)
{
_misoPinMask = digitalPinToBitMask(_miso);
_misoPort = (PORTreg_t)GPIO_IN_REG;
}
#elif defined(ESP32)
_dcPinMask = digitalPinToBitMask(_dc);
if (_dc >= 32)
{
_dcPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
_dcPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
}
else if (_dc != GFX_NOT_DEFINED)
{
_dcPortSet = (PORTreg_t)&GPIO.out_w1ts;
_dcPortClr = (PORTreg_t)&GPIO.out_w1tc;
}
if (_cs >= 32)
{
_csPinMask = digitalPinToBitMask(_cs);
_csPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
_csPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
}
else if (_cs != GFX_NOT_DEFINED)
{
_csPinMask = digitalPinToBitMask(_cs);
_csPortSet = (PORTreg_t)&GPIO.out_w1ts;
_csPortClr = (PORTreg_t)&GPIO.out_w1tc;
}
_sckPinMask = digitalPinToBitMask(_sck);
_mosiPinMask = digitalPinToBitMask(_mosi);
if (_sck >= 32)
{
_sckPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
_sckPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
}
else
{
_sckPortSet = (PORTreg_t)&GPIO.out_w1ts;
_sckPortClr = (PORTreg_t)&GPIO.out_w1tc;
}
if (_mosi >= 32)
{
_mosiPortSet = (PORTreg_t)&GPIO.out1_w1ts.val;
_mosiPortClr = (PORTreg_t)&GPIO.out1_w1tc.val;
}
else
{
_mosiPortSet = (PORTreg_t)&GPIO.out_w1ts;
_mosiPortClr = (PORTreg_t)&GPIO.out_w1tc;
}
if (_miso != GFX_NOT_DEFINED)
{
_misoPinMask = digitalPinToBitMask(_miso);
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
}
#elif defined(CORE_TEENSY)
if (_dc != GFX_NOT_DEFINED)
{
#if !defined(KINETISK)
_dcPinMask = digitalPinToBitMask(_dc);
#endif
_dcPortSet = portSetRegister(_dc);
_dcPortClr = portClearRegister(_dc);
}
if (_cs != GFX_NOT_DEFINED)
{
#if !defined(KINETISK)
_csPinMask = digitalPinToBitMask(_cs);
#endif
_csPortSet = portSetRegister(_cs);
_csPortClr = portClearRegister(_cs);
}
#if !defined(KINETISK)
_sckPinMask = digitalPinToBitMask(_sck);
#endif
_sckPortSet = portSetRegister(_sck);
_sckPortClr = portClearRegister(_sck);
#if !defined(KINETISK)
_mosiPinMask = digitalPinToBitMask(_mosi);
#endif
_mosiPortSet = portSetRegister(_mosi);
_mosiPortClr = portClearRegister(_mosi);
if (_miso != GFX_NOT_DEFINED)
{
#if !defined(KINETISK)
_misoPinMask = digitalPinToBitMask(_miso);
#endif
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
}
#else // !CORE_TEENSY
if (_dc != GFX_NOT_DEFINED)
{
_dcPinMask = digitalPinToBitMask(_dc);
_dcPortSet = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTSET.reg);
_dcPortClr = &(PORT->Group[g_APinDescription[_dc].ulPort].OUTCLR.reg);
}
if (_cs != GFX_NOT_DEFINED)
{
_csPinMask = digitalPinToBitMask(_cs);
_csPortSet = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTSET.reg);
_csPortClr = &(PORT->Group[g_APinDescription[_cs].ulPort].OUTCLR.reg);
}
_sckPinMask = digitalPinToBitMask(_sck);
_sckPortSet = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTSET.reg);
_sckPortClr = &(PORT->Group[g_APinDescription[_sck].ulPort].OUTCLR.reg);
_mosiPinMask = digitalPinToBitMask(_mosi);
_mosiPortSet = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTSET.reg);
_mosiPortClr = &(PORT->Group[g_APinDescription[_mosi].ulPort].OUTCLR.reg);
if (_miso != GFX_NOT_DEFINED)
{
_misoPinMask = digitalPinToBitMask(_miso);
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
}
#endif // end !CORE_TEENSY
#else // !HAS_PORT_SET_CLR
if (_dc != GFX_NOT_DEFINED)
{
_dcPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_dc));
_dcPinMaskSet = digitalPinToBitMask(_dc);
_dcPinMaskClr = ~_dcPinMaskSet;
}
if (_cs != GFX_NOT_DEFINED)
{
_csPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_cs));
_csPinMaskSet = digitalPinToBitMask(_cs);
_csPinMaskClr = ~_csPinMaskSet;
}
_sckPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_sck));
_sckPinMaskSet = digitalPinToBitMask(_sck);
_sckPinMaskClr = ~_sckPinMaskSet;
_mosiPort = (PORTreg_t)portOutputRegister(digitalPinToPort(_mosi));
_mosiPinMaskSet = digitalPinToBitMask(_mosi);
_mosiPinMaskClr = ~_mosiPinMaskSet;
if (_miso != GFX_NOT_DEFINED)
{
_misoPort = (PORTreg_t)portInputRegister(digitalPinToPort(_miso));
_misoPinMask = digitalPinToBitMask(_miso);
}
#endif // !HAS_PORT_SET_CLR
#endif // USE_FAST_PINIO
return true;
}
void Arduino_SWSPI::beginWrite()
{
if (_dc != GFX_NOT_DEFINED)
{
DC_HIGH();
}
CS_LOW();
}
void Arduino_SWSPI::endWrite()
{
CS_HIGH();
}
void Arduino_SWSPI::writeCommand(uint8_t c)
{
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
{
WRITE9BITCOMMAND(c);
}
else
{
DC_LOW();
WRITE(c);
DC_HIGH();
}
}
void Arduino_SWSPI::writeCommand16(uint16_t c)
{
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
{
_data16.value = c;
WRITE9BITCOMMAND(_data16.msb);
WRITE9BITCOMMAND(_data16.lsb);
}
else
{
DC_LOW();
WRITE16(c);
DC_HIGH();
}
}
void Arduino_SWSPI::write(uint8_t d)
{
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
{
WRITE9BITDATA(d);
}
else
{
WRITE(d);
}
}
void Arduino_SWSPI::write16(uint16_t d)
{
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
{
_data16.value = d;
WRITE9BITDATA(_data16.msb);
WRITE9BITDATA(_data16.lsb);
}
else
{
WRITE16(d);
}
}
void Arduino_SWSPI::writeRepeat(uint16_t p, uint32_t len)
{
if (_dc == GFX_NOT_DEFINED) // 9-bit SPI
{
// ESP8266 avoid trigger watchdog
#if defined(ESP8266)
while (len > (ESP8266SAFEBATCHBITSIZE / 9))
{
WRITE9BITREPEAT(p, ESP8266SAFEBATCHBITSIZE / 9);
len -= ESP8266SAFEBATCHBITSIZE / 9;
yield();
}
WRITE9BITREPEAT(p, len);
#else
WRITE9BITREPEAT(p, len);
#endif
}
else
{
#if defined(ESP8266)
while (len > (ESP8266SAFEBATCHBITSIZE / 8))
{
WRITEREPEAT(p, ESP8266SAFEBATCHBITSIZE / 8);
len -= ESP8266SAFEBATCHBITSIZE / 8;
yield();
}
WRITEREPEAT(p, len);
#else
WRITEREPEAT(p, len);
#endif
}
}
void Arduino_SWSPI::writePixels(uint16_t *data, uint32_t len)
{
while (len--)
{
WRITE16(*data++);
}
}
#if !defined(LITTLE_FOOT_PRINT)
void Arduino_SWSPI::writeBytes(uint8_t *data, uint32_t len)
{
while (len--)
{
WRITE(*data++);
}
}
#endif // !defined(LITTLE_FOOT_PRINT)
INLINE void Arduino_SWSPI::WRITE9BITCOMMAND(uint8_t c)
{
// D/C bit, command
SPI_MOSI_LOW();
SPI_SCK_HIGH();
SPI_SCK_LOW();
uint8_t bit = 0x80;
while (bit)
{
if (c & bit)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
SPI_SCK_HIGH();
bit >>= 1;
SPI_SCK_LOW();
}
}
INLINE void Arduino_SWSPI::WRITE9BITDATA(uint8_t d)
{
// D/C bit, data
SPI_MOSI_HIGH();
SPI_SCK_HIGH();
SPI_SCK_LOW();
uint8_t bit = 0x80;
while (bit)
{
if (d & bit)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
SPI_SCK_HIGH();
bit >>= 1;
SPI_SCK_LOW();
}
}
INLINE void Arduino_SWSPI::WRITE(uint8_t d)
{
uint8_t bit = 0x80;
while (bit)
{
if (d & bit)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
SPI_SCK_HIGH();
bit >>= 1;
SPI_SCK_LOW();
}
}
INLINE void Arduino_SWSPI::WRITE16(uint16_t d)
{
uint16_t bit = 0x8000;
while (bit)
{
if (d & bit)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
SPI_SCK_HIGH();
bit >>= 1;
SPI_SCK_LOW();
}
}
INLINE void Arduino_SWSPI::WRITE9BITREPEAT(uint16_t p, uint32_t len)
{
if (p == 0xffff) // no need to set MOSI level while filling white
{
SPI_MOSI_HIGH();
len *= 18; // 9-bit * 2
while (len--)
{
SPI_SCK_HIGH();
SPI_SCK_LOW();
}
}
else
{
_data16.value = p;
while (len--)
{
WRITE9BITDATA(_data16.msb);
WRITE9BITDATA(_data16.lsb);
}
}
}
INLINE void Arduino_SWSPI::WRITEREPEAT(uint16_t p, uint32_t len)
{
if ((p == 0x0000) || (p == 0xffff)) // no need to set MOSI level while filling black or white
{
if (p)
{
SPI_MOSI_HIGH();
}
else
{
SPI_MOSI_LOW();
}
len *= 16;
while (len--)
{
SPI_SCK_HIGH();
SPI_SCK_LOW();
}
}
else
{
while (len--)
{
WRITE16(p);
}
}
}
/******** low level bit twiddling **********/
INLINE void Arduino_SWSPI::DC_HIGH(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_dcPortSet = 1;
#else // !KINETISK
*_dcPortSet = _dcPinMask;
#endif // end !KINETISK
#else // !HAS_PORT_SET_CLR
*_dcPort |= _dcPinMaskSet;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_dc, HIGH);
#endif // end !USE_FAST_PINIO
}
INLINE void Arduino_SWSPI::DC_LOW(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_dcPortClr = 1;
#else // !KINETISK
*_dcPortClr = _dcPinMask;
#endif // end !KINETISK
#else // !HAS_PORT_SET_CLR
*_dcPort &= _dcPinMaskClr;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_dc, LOW);
#endif // end !USE_FAST_PINIO
}
INLINE void Arduino_SWSPI::CS_HIGH(void)
{
if (_cs != GFX_NOT_DEFINED)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_csPortSet = 1;
#else // !KINETISK
*_csPortSet = _csPinMask;
#endif // end !KINETISK
#else // !HAS_PORT_SET_CLR
*_csPort |= _csPinMaskSet;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_cs, HIGH);
#endif // end !USE_FAST_PINIO
}
}
INLINE void Arduino_SWSPI::CS_LOW(void)
{
if (_cs != GFX_NOT_DEFINED)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_csPortClr = 1;
#else // !KINETISK
*_csPortClr = _csPinMask;
#endif // end !KINETISK
#else // !HAS_PORT_SET_CLR
*_csPort &= _csPinMaskClr;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_cs, LOW);
#endif // end !USE_FAST_PINIO
}
}
/*!
@brief Set the software (bitbang) SPI MOSI line HIGH.
*/
INLINE void Arduino_SWSPI::SPI_MOSI_HIGH(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_mosiPortSet = 1;
#else // !KINETISK
*_mosiPortSet = _mosiPinMask;
#endif
#else // !HAS_PORT_SET_CLR
*_mosiPort |= _mosiPinMaskSet;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_mosi, HIGH);
#endif // end !USE_FAST_PINIO
}
/*!
@brief Set the software (bitbang) SPI MOSI line LOW.
*/
INLINE void Arduino_SWSPI::SPI_MOSI_LOW(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_mosiPortClr = 1;
#else // !KINETISK
*_mosiPortClr = _mosiPinMask;
#endif
#else // !HAS_PORT_SET_CLR
*_mosiPort &= _mosiPinMaskClr;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_mosi, LOW);
#endif // end !USE_FAST_PINIO
}
/*!
@brief Set the software (bitbang) SPI SCK line HIGH.
*/
INLINE void Arduino_SWSPI::SPI_SCK_HIGH(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_sckPortSet = 1;
#else // !KINETISK
*_sckPortSet = _sckPinMask;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
for (volatile uint8_t i = 0; i < 1; i++)
;
#endif
#endif
#else // !HAS_PORT_SET_CLR
*_sckPort |= _sckPinMaskSet;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_sck, HIGH);
#endif // end !USE_FAST_PINIO
}
/*!
@brief Set the software (bitbang) SPI SCK line LOW.
*/
INLINE void Arduino_SWSPI::SPI_SCK_LOW(void)
{
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
#if defined(KINETISK)
*_sckPortClr = 1;
#else // !KINETISK
*_sckPortClr = _sckPinMask;
#if defined(__IMXRT1052__) || defined(__IMXRT1062__) // Teensy 4.x
for (volatile uint8_t i = 0; i < 1; i++)
;
#endif
#endif
#else // !HAS_PORT_SET_CLR
*_sckPort &= _sckPinMaskClr;
#endif // end !HAS_PORT_SET_CLR
#else // !USE_FAST_PINIO
digitalWrite(_sck, LOW);
#endif // end !USE_FAST_PINIO
}
/*!
@brief Read the state of the software (bitbang) SPI MISO line.
@return true if HIGH, false if LOW.
*/
INLINE bool Arduino_SWSPI::SPI_MISO_READ(void)
{
#if defined(USE_FAST_PINIO)
#if defined(KINETISK)
return *_misoPort;
#else // !KINETISK
return *_misoPort & _misoPinMask;
#endif // end !KINETISK
#else // !USE_FAST_PINIO
return digitalRead(_miso);
#endif // end !USE_FAST_PINIO
}

View File

@@ -0,0 +1,94 @@
/*
* start rewrite from:
* https://github.com/adafruit/Adafruit-GFX-Library.git
*/
#ifndef _ARDUINO_SWSPI_H_
#define _ARDUINO_SWSPI_H_
#include "Arduino_DataBus.h"
class Arduino_SWSPI : public Arduino_DataBus
{
public:
Arduino_SWSPI(int8_t dc, int8_t cs, int8_t _sck, int8_t _mosi, int8_t _miso = GFX_NOT_DEFINED); // Constructor
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
void beginWrite() override;
void endWrite() override;
void writeCommand(uint8_t) override;
void writeCommand16(uint16_t) override;
void write(uint8_t) override;
void write16(uint16_t) override;
void writeRepeat(uint16_t p, uint32_t len) override;
void writePixels(uint16_t *data, uint32_t len) override;
#if !defined(LITTLE_FOOT_PRINT)
void writeBytes(uint8_t *data, uint32_t len) override;
#endif // !defined(LITTLE_FOOT_PRINT)
private:
INLINE void WRITE9BITCOMMAND(uint8_t c);
INLINE void WRITE9BITDATA(uint8_t d);
INLINE void WRITE(uint8_t d);
INLINE void WRITE16(uint16_t d);
INLINE void WRITE9BITREPEAT(uint16_t p, uint32_t len);
INLINE void WRITEREPEAT(uint16_t p, uint32_t len);
INLINE void DC_HIGH(void);
INLINE void DC_LOW(void);
INLINE void CS_HIGH(void);
INLINE void CS_LOW(void);
INLINE void SPI_MOSI_HIGH(void);
INLINE void SPI_MOSI_LOW(void);
INLINE void SPI_SCK_HIGH(void);
INLINE void SPI_SCK_LOW(void);
INLINE bool SPI_MISO_READ(void);
int8_t _dc, _cs;
int8_t _sck, _mosi, _miso;
// CLASS INSTANCE VARIABLES --------------------------------------------
// Here be dragons! There's a big union of three structures here --
// one each for hardware SPI, software (bitbang) SPI, and parallel
// interfaces. This is to save some memory, since a display's connection
// will be only one of these. The order of some things is a little weird
// in an attempt to get values to align and pack better in RAM.
#if defined(USE_FAST_PINIO)
#if defined(HAS_PORT_SET_CLR)
PORTreg_t _csPortSet; ///< PORT register for chip select SET
PORTreg_t _csPortClr; ///< PORT register for chip select CLEAR
PORTreg_t _dcPortSet; ///< PORT register for data/command SET
PORTreg_t _dcPortClr; ///< PORT register for data/command CLEAR
PORTreg_t _mosiPortSet; ///< PORT register for MOSI SET
PORTreg_t _mosiPortClr; ///< PORT register for MOSI CLEAR
PORTreg_t _sckPortSet; ///< PORT register for SCK SET
PORTreg_t _sckPortClr; ///< PORT register for SCK CLEAR
#if !defined(KINETISK)
ARDUINOGFX_PORT_t _csPinMask; ///< Bitmask for chip select
ARDUINOGFX_PORT_t _dcPinMask; ///< Bitmask for data/command
ARDUINOGFX_PORT_t _mosiPinMask; ///< Bitmask for MOSI
ARDUINOGFX_PORT_t _sckPinMask; ///< Bitmask for SCK
#endif // !KINETISK
#else // !HAS_PORT_SET_CLR
PORTreg_t _mosiPort; ///< PORT register for MOSI
PORTreg_t _sckPort; ///< PORT register for SCK
PORTreg_t _csPort; ///< PORT register for chip select
PORTreg_t _dcPort; ///< PORT register for data/command
ARDUINOGFX_PORT_t _csPinMaskSet; ///< Bitmask for chip select SET (OR)
ARDUINOGFX_PORT_t _csPinMaskClr; ///< Bitmask for chip select CLEAR (AND)
ARDUINOGFX_PORT_t _dcPinMaskSet; ///< Bitmask for data/command SET (OR)
ARDUINOGFX_PORT_t _dcPinMaskClr; ///< Bitmask for data/command CLEAR (AND)
ARDUINOGFX_PORT_t _mosiPinMaskSet; ///< Bitmask for MOSI SET (OR)
ARDUINOGFX_PORT_t _mosiPinMaskClr; ///< Bitmask for MOSI CLEAR (AND)
ARDUINOGFX_PORT_t _sckPinMaskSet; ///< Bitmask for SCK SET (OR bitmask)
ARDUINOGFX_PORT_t _sckPinMaskClr; ///< Bitmask for SCK CLEAR (AND)
#endif // HAS_PORT_SET_CLR
PORTreg_t _misoPort; ///< PORT (PIN) register for MISO
#if !defined(KINETISK)
ARDUINOGFX_PORT_t _misoPinMask; ///< Bitmask for MISO
#endif // !KINETISK
#endif // defined(USE_FAST_PINIO)
};
#endif // _ARDUINO_SWSPI_H_

View File

@@ -0,0 +1,276 @@
#include "Arduino_XL9535SWSPI.h"
Arduino_XL9535SWSPI::Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire)
: _sda(sda), _scl(scl), _pwd(pwd), _cs(cs), _sck(sck), _mosi(mosi), _wire(wire)
{
}
bool Arduino_XL9535SWSPI::begin(int32_t speed, int8_t dataMode)
{
UNUSED(speed);
UNUSED(dataMode);
_address = XL9535_IIC_ADDRESS;
_wire->beginTransmission(_address);
if (!_wire->endTransmission())
{
Serial.println("Found xl9535");
is_found = true;
if (_pwd != GFX_NOT_DEFINED)
{
this->pinMode(_pwd, OUTPUT);
}
this->pinMode(_cs, OUTPUT);
this->pinMode(_sck, OUTPUT);
this->pinMode(_mosi, OUTPUT);
if (_pwd != GFX_NOT_DEFINED)
{
this->digitalWrite(_pwd, 1);
}
this->digitalWrite(_cs, 1);
this->digitalWrite(_sck, 1);
this->digitalWrite(_mosi, 1);
// while(1)
// {
// this->digitalWrite(4, 0);
// delay(1000);
// this->digitalWrite(4, 1);
// delay(1000);
// }
// this->digitalWrite(_cs, 0);
// this->digitalWrite(5, 1);
// delay(100);
// this->digitalWrite(5, 0);
// delay(800);
// this->digitalWrite(5, 1);
// delay(800);
// this->digitalWrite(_cs, 1);
}
else
{
Serial.println("xl9535 not found");
is_found = false;
}
return true;
}
void Arduino_XL9535SWSPI::beginWrite()
{
this->digitalWrite(_cs, 0);
}
void Arduino_XL9535SWSPI::endWrite()
{
this->digitalWrite(_cs, 1);
}
void Arduino_XL9535SWSPI::writeCommand(uint8_t c)
{
// D/C bit, command
this->digitalWrite(_mosi, 0);
this->digitalWrite(_sck, 0);
this->digitalWrite(_sck, 1);
uint8_t bit = 0x80;
while (bit)
{
if (c & bit)
{
this->digitalWrite(_mosi, 1);
}
else
{
this->digitalWrite(_mosi, 0);
}
this->digitalWrite(_sck, 0);
bit >>= 1;
this->digitalWrite(_sck, 1);
}
}
void Arduino_XL9535SWSPI::writeCommand16(uint16_t)
{
}
void Arduino_XL9535SWSPI::write(uint8_t d)
{
// D/C bit, data
this->digitalWrite(_mosi, 1);
this->digitalWrite(_sck, 0);
this->digitalWrite(_sck, 1);
uint8_t bit = 0x80;
while (bit)
{
if (d & bit)
{
this->digitalWrite(_mosi, 1);
}
else
{
this->digitalWrite(_mosi, 0);
}
this->digitalWrite(_sck, 0);
bit >>= 1;
this->digitalWrite(_sck, 1);
}
}
void Arduino_XL9535SWSPI::write16(uint16_t)
{
// not implemented
}
void Arduino_XL9535SWSPI::writeRepeat(uint16_t p, uint32_t len)
{
// not implemented
}
void Arduino_XL9535SWSPI::writePixels(uint16_t *data, uint32_t len)
{
// not implemented
}
#if !defined(LITTLE_FOOT_PRINT)
void Arduino_XL9535SWSPI::writeBytes(uint8_t *data, uint32_t len)
{
// not implemented
}
#endif // !defined(LITTLE_FOOT_PRINT)
void Arduino_XL9535SWSPI::writeRegister(uint8_t reg, uint8_t *data, size_t len)
{
_wire->beginTransmission(_address);
_wire->write(reg);
for (size_t i = 0; i < len; i++)
{
_wire->write(data[i]);
}
_wire->endTransmission();
}
uint8_t Arduino_XL9535SWSPI::readRegister(uint8_t reg, uint8_t *data, size_t len)
{
_wire->beginTransmission(_address);
_wire->write(reg);
_wire->endTransmission();
_wire->requestFrom(_address, len);
size_t index = 0;
while (index < len)
data[index++] = _wire->read();
return 0;
}
void Arduino_XL9535SWSPI::pinMode(uint8_t pin, uint8_t mode)
{
if (is_found)
{
uint8_t port = 0;
if (pin > 7)
{
this->readRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
if (mode == OUTPUT)
{
port = port & (~(1 << (pin - 10)));
}
else
{
port = port | (1 << (pin - 10));
}
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &port, 1);
}
else
{
this->readRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
if (mode == OUTPUT)
{
port = port & (~(1 << pin));
}
else
{
port = port | (1 << pin);
}
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &port, 1);
}
}
else
{
Serial.println("xl9535 not found");
}
}
void Arduino_XL9535SWSPI::pinMode8(uint8_t port, uint8_t pin, uint8_t mode)
{
if (is_found)
{
uint8_t _pin = (mode != OUTPUT) ? pin : ~pin;
if (port)
{
this->writeRegister(XL9535_CONFIG_PORT_1_REG, &_pin, 1);
}
else
{
this->writeRegister(XL9535_CONFIG_PORT_0_REG, &_pin, 1);
}
}
else
{
Serial.println("xl9535 not found");
}
}
void Arduino_XL9535SWSPI::digitalWrite(uint8_t pin, uint8_t val)
{
if (is_found)
{
uint8_t port = 0;
uint8_t reg_data = 0;
if (pin > 7)
{
this->readRegister(XL9535_OUTPUT_PORT_1_REG, &reg_data, 1);
reg_data = reg_data & (~(1 << (pin - 10)));
port = reg_data | val << (pin - 10);
this->writeRegister(XL9535_OUTPUT_PORT_1_REG, &port, 1);
}
else
{
this->readRegister(XL9535_OUTPUT_PORT_0_REG, &reg_data, 1);
reg_data = reg_data & (~(1 << pin));
port = reg_data | val << pin;
this->writeRegister(XL9535_OUTPUT_PORT_0_REG, &port, 1);
}
}
else
{
Serial.println("xl9535 not found");
}
}
int Arduino_XL9535SWSPI::digitalRead(uint8_t pin)
{
if (is_found)
{
int state = 0;
uint8_t port = 0;
if (pin > 7)
{
this->readRegister(XL9535_INPUT_PORT_1_REG, &port, 1);
state = port >> (pin - 10) & 0x01 ? 1 : 0;
}
else
{
this->readRegister(XL9535_INPUT_PORT_0_REG, &port, 1);
state = port >> pin & 0x01 ? 1 : 0;
}
return state;
}
else
{
Serial.println("xl9535 not found");
}
return 0;
}

View File

@@ -0,0 +1,57 @@
#ifndef _ARDUINO_XL9535SWSPI_H_
#define _ARDUINO_XL9535SWSPI_H_
#include <Wire.h>
#include "Arduino_DataBus.h"
#define XL9535_IIC_ADDRESS 0X20
#define XL9535_INPUT_PORT_0_REG 0X00
#define XL9535_INPUT_PORT_1_REG 0X01
#define XL9535_OUTPUT_PORT_0_REG 0X02
#define XL9535_OUTPUT_PORT_1_REG 0X03
#define XL9535_INVERSION_PORT_0_REG 0X04
#define XL9535_INVERSION_PORT_1_REG 0X05
#define XL9535_CONFIG_PORT_0_REG 0X06
#define XL9535_CONFIG_PORT_1_REG 0X07
class Arduino_XL9535SWSPI : public Arduino_DataBus
{
public:
Arduino_XL9535SWSPI(int8_t sda, int8_t scl, int8_t pwd, int8_t cs, int8_t sck, int8_t mosi, TwoWire *wire = &Wire);
bool begin(int32_t speed = GFX_NOT_DEFINED, int8_t dataMode = GFX_NOT_DEFINED) override;
void beginWrite() override;
void endWrite() override;
void writeCommand(uint8_t) override;
void writeCommand16(uint16_t) override;
void write(uint8_t) override;
void write16(uint16_t) override;
void writeRepeat(uint16_t p, uint32_t len) override;
void writePixels(uint16_t *data, uint32_t len) override;
#if !defined(LITTLE_FOOT_PRINT)
void writeBytes(uint8_t *data, uint32_t len) override;
#endif // !defined(LITTLE_FOOT_PRINT)
void pinMode(uint8_t pin, uint8_t mode);
void pinMode8(uint8_t port, uint8_t pin, uint8_t mode);
void digitalWrite(uint8_t pin, uint8_t val) override;
int digitalRead(uint8_t pin) override;
protected:
void writeRegister(uint8_t reg, uint8_t *data, size_t len);
uint8_t readRegister(uint8_t reg, uint8_t *data, size_t len);
uint8_t _address;
bool is_found;
int8_t _sda, _scl, _pwd, _cs, _sck, _mosi;
TwoWire *_wire;
private:
};
#endif // _ARDUINO_XL9535SWSPI_H_

View File

@@ -0,0 +1,493 @@
#include "../Arduino_DataBus.h"
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
#include "../Arduino_GFX.h"
#include "Arduino_RGB_Display.h"
Arduino_RGB_Display::Arduino_RGB_Display(
int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r, bool auto_flush,
Arduino_DataBus *bus, int8_t rst, const uint8_t *init_operations, size_t init_operations_len)
: Arduino_GFX(w, h), _rgbpanel(rgbpanel), _auto_flush(auto_flush),
_bus(bus), _rst(rst), _init_operations(init_operations), _init_operations_len(init_operations_len)
{
_framebuffer_size = w * h * 2;
MAX_X = WIDTH - 1;
MAX_Y = HEIGHT - 1;
setRotation(r);
}
bool Arduino_RGB_Display::begin(int32_t speed)
{
if (_bus)
{
if (!_bus->begin())
{
return false;
}
}
if (_rst != GFX_NOT_DEFINED)
{
pinMode(_rst, OUTPUT);
digitalWrite(_rst, HIGH);
delay(100);
digitalWrite(_rst, LOW);
delay(120);
digitalWrite(_rst, HIGH);
delay(120);
}
else
{
if (_bus)
{
// Software Rest
_bus->sendCommand(0x01);
delay(120);
}
}
if (_bus)
{
if (_init_operations_len > 0)
{
_bus->batchOperation((uint8_t *)_init_operations, _init_operations_len);
}
}
_rgbpanel->begin(speed);
_framebuffer = _rgbpanel->getFrameBuffer(WIDTH, HEIGHT);
if (!_framebuffer)
{
return false;
}
return true;
}
void Arduino_RGB_Display::writePixelPreclipped(int16_t x, int16_t y, uint16_t color)
{
uint16_t *fb = _framebuffer;
switch (_rotation)
{
case 1:
fb += (int32_t)x * _height;
fb += _max_y - y;
*fb = color;
if (_auto_flush)
{
Cache_WriteBack_Addr((uint32_t)fb, 2);
}
break;
case 2:
fb += (int32_t)(_max_y - y) * _width;
fb += _max_x - x;
*fb = color;
if (_auto_flush)
{
Cache_WriteBack_Addr((uint32_t)fb, 2);
}
break;
case 3:
fb += (int32_t)(_max_x - x) * _height;
fb += y;
*fb = color;
if (_auto_flush)
{
Cache_WriteBack_Addr((uint32_t)fb, 2);
}
break;
default: // case 0:
fb += (int32_t)y * _width;
fb += x;
*fb = color;
if (_auto_flush)
{
Cache_WriteBack_Addr((uint32_t)fb, 2);
}
}
}
void Arduino_RGB_Display::writeFastVLine(int16_t x, int16_t y,
int16_t h, uint16_t color)
{
// log_i("writeFastVLine(x: %d, y: %d, h: %d)", x, y, h);
switch (_rotation)
{
case 1:
writeFastHLineCore(_height - y - h, x, h, color);
break;
case 2:
writeFastVLineCore(_max_x - x, _height - y - h, h, color);
break;
case 3:
writeFastHLineCore(y, _max_x - x, h, color);
break;
default: // case 0:
writeFastVLineCore(x, y, h, color);
}
}
void Arduino_RGB_Display::writeFastVLineCore(int16_t x, int16_t y,
int16_t h, uint16_t color)
{
// log_i("writeFastVLineCore(x: %d, y: %d, h: %d)", x, y, h);
if (_ordered_in_range(x, 0, MAX_X) && h)
{ // X on screen, nonzero height
if (h < 0)
{ // If negative height...
y += h + 1; // Move Y to top edge
h = -h; // Use positive height
}
if (y <= MAX_Y)
{ // Not off bottom
int16_t y2 = y + h - 1;
if (y2 >= 0)
{ // Not off top
// Line partly or fully overlaps screen
if (y < 0)
{
y = 0;
h = y2 + 1;
} // Clip top
if (y2 > MAX_Y)
{
h = MAX_Y - y + 1;
} // Clip bottom
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
if (_auto_flush)
{
while (h--)
{
*fb = color;
Cache_WriteBack_Addr((uint32_t)fb, 2);
fb += WIDTH;
}
}
else
{
while (h--)
{
*fb = color;
fb += WIDTH;
}
}
}
}
}
}
void Arduino_RGB_Display::writeFastHLine(int16_t x, int16_t y,
int16_t w, uint16_t color)
{
// log_i("writeFastHLine(x: %d, y: %d, w: %d)", x, y, w);
switch (_rotation)
{
case 1:
writeFastVLineCore(_max_y - y, x, w, color);
break;
case 2:
writeFastHLineCore(_width - x - w, _max_y - y, w, color);
break;
case 3:
writeFastVLineCore(y, _width - x - w, w, color);
break;
default: // case 0:
writeFastHLineCore(x, y, w, color);
}
}
void Arduino_RGB_Display::writeFastHLineCore(int16_t x, int16_t y,
int16_t w, uint16_t color)
{
// log_i("writeFastHLineCore(x: %d, y: %d, w: %d)", x, y, w);
if (_ordered_in_range(y, 0, MAX_Y) && w)
{ // Y on screen, nonzero width
if (w < 0)
{ // If negative width...
x += w + 1; // Move X to left edge
w = -w; // Use positive width
}
if (x <= MAX_X)
{ // Not off right
int16_t x2 = x + w - 1;
if (x2 >= 0)
{ // Not off left
// Line partly or fully overlaps screen
if (x < 0)
{
x = 0;
w = x2 + 1;
} // Clip left
if (x2 > MAX_X)
{
w = MAX_X - x + 1;
} // Clip right
uint16_t *fb = _framebuffer + ((int32_t)y * WIDTH) + x;
uint32_t cachePos = (uint32_t)fb;
int16_t writeSize = w * 2;
while (w--)
{
*(fb++) = color;
}
if (_auto_flush)
{
Cache_WriteBack_Addr(cachePos, writeSize);
}
}
}
}
}
void Arduino_RGB_Display::writeFillRectPreclipped(int16_t x, int16_t y,
int16_t w, int16_t h, uint16_t color)
{
// log_i("writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
if (_rotation > 0)
{
int16_t t = x;
switch (_rotation)
{
case 1:
x = WIDTH - y - h;
y = t;
t = w;
w = h;
h = t;
break;
case 2:
x = WIDTH - x - w;
y = HEIGHT - y - h;
break;
case 3:
x = y;
y = HEIGHT - t - w;
t = w;
w = h;
h = t;
break;
}
}
// log_i("adjusted writeFillRectPreclipped(x: %d, y: %d, w: %d, h: %d)", x, y, w, h);
uint16_t *row = _framebuffer;
row += y * WIDTH;
uint32_t cachePos = (uint32_t)row;
row += x;
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
row[i] = color;
}
row += WIDTH;
}
if (_auto_flush)
{
Cache_WriteBack_Addr(cachePos, WIDTH * h * 2);
}
}
void Arduino_RGB_Display::drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else
{
if (_rotation > 0)
{
Arduino_GFX::drawIndexedBitmap(x, y, bitmap, color_index, w, h, x_skip);
}
else
{
if ((y + h - 1) > _max_y)
{
h -= (y + h - 1) - _max_y;
}
if (y < 0)
{
bitmap -= y * w;
h += y;
y = 0;
}
if ((x + w - 1) > _max_x)
{
x_skip += (x + w - 1) - _max_x;
w -= (x + w - 1) - _max_x;
}
if (x < 0)
{
bitmap -= x;
x_skip -= x;
w += x;
x = 0;
}
uint16_t *row = _framebuffer;
row += y * _width;
uint32_t cachePos = (uint32_t)row;
row += x;
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
row[i] = color_index[*bitmap++];
}
bitmap += x_skip;
row += _width;
}
if (_auto_flush)
{
Cache_WriteBack_Addr(cachePos, _width * h * 2);
}
}
}
}
void Arduino_RGB_Display::draw16bitRGBBitmap(int16_t x, int16_t y,
uint16_t *bitmap, int16_t w, int16_t h)
{
bool result;
switch (_rotation)
{
case 1:
result = gfx_draw_bitmap_to_framebuffer_rotate_1(bitmap, w, h, _framebuffer, x, y, _width, _height);
break;
case 2:
result = gfx_draw_bitmap_to_framebuffer_rotate_2(bitmap, w, h, _framebuffer, x, y, _width, _height);
break;
case 3:
result = gfx_draw_bitmap_to_framebuffer_rotate_3(bitmap, w, h, _framebuffer, x, y, _width, _height);
break;
default: // case 0:
result = gfx_draw_bitmap_to_framebuffer(bitmap, w, h, _framebuffer, x, y, _width, _height);
}
if (result)
{
if (_auto_flush)
{
uint32_t cachePos;
size_t cache_size;
switch (_rotation)
{
case 1:
cachePos = (uint32_t)(_framebuffer + (x * WIDTH));
cache_size = HEIGHT * w * 2;
break;
case 2:
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - y) * WIDTH));
cache_size = HEIGHT * h * 2;
break;
case 3:
cachePos = (uint32_t)(_framebuffer + ((MAX_Y - x) * WIDTH));
cache_size = HEIGHT * w * 2;
break;
default: // case 0:
cachePos = (uint32_t)(_framebuffer + (y * WIDTH) + x);
cache_size = (WIDTH * (h - 1) + w) * 2;
}
Cache_WriteBack_Addr(cachePos, cache_size);
}
}
}
void Arduino_RGB_Display::draw16bitBeRGBBitmap(int16_t x, int16_t y,
uint16_t *bitmap, int16_t w, int16_t h)
{
if (
((x + w - 1) < 0) || // Outside left
((y + h - 1) < 0) || // Outside top
(x > _max_x) || // Outside right
(y > _max_y) // Outside bottom
)
{
return;
}
else
{
if (_rotation > 0)
{
Arduino_GFX::draw16bitBeRGBBitmap(x, y, bitmap, w, h);
}
else
{
int16_t xskip = 0;
if ((y + h - 1) > _max_y)
{
h -= (y + h - 1) - _max_y;
}
if (y < 0)
{
bitmap -= y * w;
h += y;
y = 0;
}
if ((x + w - 1) > _max_x)
{
xskip = (x + w - 1) - _max_x;
w -= xskip;
}
if (x < 0)
{
bitmap -= x;
xskip -= x;
w += x;
x = 0;
}
uint16_t *row = _framebuffer;
row += y * _width;
uint32_t cachePos = (uint32_t)row;
row += x;
uint16_t color;
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
color = *bitmap++;
MSB_16_SET(row[i], color);
}
bitmap += xskip;
row += _width;
}
if (_auto_flush)
{
Cache_WriteBack_Addr(cachePos, _width * h * 2);
}
}
}
}
void Arduino_RGB_Display::flush(void)
{
if (!_auto_flush)
{
Cache_WriteBack_Addr((uint32_t)_framebuffer, _framebuffer_size);
}
}
uint16_t *Arduino_RGB_Display::getFramebuffer()
{
return _framebuffer;
}
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
void Arduino_RGB_Display::XL_digitalWrite(uint8_t pin, uint8_t val)
{
_bus->digitalWrite(pin, val);
}
int Arduino_RGB_Display::XL_digitalRead(uint8_t pin)
{
return _bus->digitalRead(pin);
}

View File

@@ -0,0 +1,52 @@
#include "../Arduino_DataBus.h"
#if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)
#ifndef _ARDUINO_RGB_DISPLAY_H_
#define _ARDUINO_RGB_DISPLAY_H_
#include "../Arduino_GFX.h"
#include "../databus/Arduino_ESP32RGBPanel.h"
class Arduino_RGB_Display : public Arduino_GFX
{
public:
Arduino_RGB_Display(
int16_t w, int16_t h, Arduino_ESP32RGBPanel *rgbpanel, uint8_t r = 0, bool auto_flush = true,
Arduino_DataBus *bus = NULL, int8_t rst = GFX_NOT_DEFINED, const uint8_t *init_operations = NULL, size_t init_operations_len = GFX_NOT_DEFINED);
bool begin(int32_t speed = GFX_NOT_DEFINED) override;
void writePixelPreclipped(int16_t x, int16_t y, uint16_t color) override;
void writeFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color) override;
void writeFastVLineCore(int16_t x, int16_t y, int16_t h, uint16_t color);
void writeFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color) override;
void writeFastHLineCore(int16_t x, int16_t y, int16_t w, uint16_t color);
void writeFillRectPreclipped(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color) override;
void drawIndexedBitmap(int16_t x, int16_t y, uint8_t *bitmap, uint16_t *color_index, int16_t w, int16_t h, int16_t x_skip = 0) override;
void draw16bitRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
void draw16bitBeRGBBitmap(int16_t x, int16_t y, uint16_t *bitmap, int16_t w, int16_t h) override;
void flush(void) override;
uint16_t *getFramebuffer();
void XL_digitalWrite(uint8_t pin, uint8_t val);
int XL_digitalRead(uint8_t pin);
protected:
uint16_t *_framebuffer;
size_t _framebuffer_size;
Arduino_ESP32RGBPanel *_rgbpanel;
bool _auto_flush;
Arduino_DataBus *_bus;
int8_t _rst;
const uint8_t *_init_operations;
size_t _init_operations_len;
int16_t MAX_X, MAX_Y;
private:
};
#endif // _ARDUINO_RGB_DISPLAY_H_
#endif // #if defined(ESP32) && (CONFIG_IDF_TARGET_ESP32S3)

View File

@@ -0,0 +1,280 @@
// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0.
// See gfxfont.h for newer custom bitmap font info.
#ifndef FONT5X7_H
#define FONT5X7_H
#ifdef __AVR__
#include <avr/io.h>
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
// PROGMEM is defefind for T4 to place data in specific memory section
#undef PROGMEM
#define PROGMEM
#else
#define PROGMEM
#endif
// Standard ASCII 5x7 font
static const unsigned char font[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x00, 0x06, 0x09, 0x09, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
};
#endif // FONT5X7_H

View File

@@ -0,0 +1,31 @@
// Font structures for newer Adafruit_GFX (1.1 and later).
// Example fonts are included in 'Fonts' directory.
// To use a font in your Arduino sketch, #include the corresponding .h
// file and pass address of GFXfont struct to setFont(). Pass NULL to
// revert to 'classic' fixed-space bitmap font.
#ifndef _GFXFONT_H_
#define _GFXFONT_H_
/// Font data stored PER GLYPH
typedef struct
{
uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
uint8_t width; ///< Bitmap dimensions in pixels
uint8_t height; ///< Bitmap dimensions in pixels
uint8_t xAdvance; ///< Distance to advance cursor (x axis)
int8_t xOffset; ///< X dist from cursor pos to UL corner
int8_t yOffset; ///< Y dist from cursor pos to UL corner
} GFXglyph;
/// Data stored for FONT AS A WHOLE
typedef struct
{
uint8_t *bitmap; ///< Glyph bitmaps, concatenated
GFXglyph *glyph; ///< Glyph array
uint8_t first; ///< ASCII extents (first char)
uint8_t last; ///< ASCII extents (last char)
uint8_t yAdvance; ///< Newline distance (y axis)
} GFXfont;
#endif // _GFXFONT_H_

View File

@@ -12,7 +12,7 @@ lib_deps =
https://github.com/Bodmer/TJpg_Decoder.git
https://github.com/nlimper/shoddyxml2
https://github.com/nlimper/QRCodeGenerator
fastled/FastLED
fastled/FastLED@3.7.8
https://github.com/MajenkoLibraries/SoftSPI
platform_packages =
platformio/framework-arduinoespressif32 @ 3.20014.231204
@@ -30,8 +30,8 @@ build_flags =
-D DISABLE_ALL_LIBRARY_WARNINGS
-D ILI9341_DRIVER
-D SMOOTH_FONT
;upload_port = COM11
;monitor_port = COM11
upload_port = COM26
monitor_port = COM26
; ----------------------------------------------------------------------------------------
; !!! this configuration expects the Mini_AP
; ----------------------------------------------------------------------------------------
@@ -263,6 +263,110 @@ board_upload.flash_size = 16MB
; ----------------------------------------------------------------------------------------
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------
[env:ESP32_S3_16_8_LILYGO_AP]
board = esp32-s3-devkitc-1
board_build.partitions = large_spiffs_16MB.csv
monitor_dtr = 0
monitor_rts = 0
build_unflags =
-std=gnu++11
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
;-D ILI9341_DRIVER
lib_deps = ${env.lib_deps}
lib_extra_dirs = lib2/Arduino_GFX-1.3.7
build_flags =
-std=gnu++17
${env.build_flags}
-D HAS_TFT
-D HAS_LILYGO_TPANEL
-D CORE_DEBUG_LEVEL=1
-D ARDUINO_USB_CDC_ON_BOOT=1
-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 HAS_BLE_WRITER
-D FLASHER_AP_SS=-1
-D FLASHER_AP_CLK=-1
-D FLASHER_AP_MOSI=-1
-D FLASHER_AP_MISO=-1
-D FLASHER_AP_RESET=34
-D FLASHER_AP_POWER={-1}
-D FLASHER_AP_TEST=-1
-D FLASHER_AP_TXD=48
-D FLASHER_AP_RXD=47
-D FLASHER_DEBUG_TXD=43
-D FLASHER_DEBUG_RXD=44
-D FLASHER_DEBUG_PROG=33
-D FLASHER_LED=-1
-D TFT_HEIGHT=480
-D USE_HSPI_PORT
-D LOAD_FONT2
-D MD5_ENABLED=1
-D SERIAL_FLASHER_INTERFACE_UART=1
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
build_src_filter =
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
board_build.flash_mode=qio
board_build.arduino.memory_type = qio_qspi ;Enable external PSRAM
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 ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------
[env:ESP32_S3_C6_BIG_AP]
board = esp32-s3-devkitc-1
board_build.partitions = large_spiffs_16MB.csv
build_unflags =
-std=gnu++11
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
lib_deps =
${env.lib_deps}
build_flags =
-std=gnu++17
${env.build_flags}
-D HAS_BLE_WRITER
-D CORE_DEBUG_LEVEL=0
-D ARDUINO_USB_CDC_ON_BOOT
-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=13
-D FLASHER_AP_RXD=14
-D FLASHER_DEBUG_SWS=21
-D FLASHER_DEBUG_TXD=15
-D FLASHER_DEBUG_RXD=16
-D FLASHER_DEBUG_PROG=7
-D FLASHER_LED=38
-D MD5_ENABLED=1
-D SERIAL_FLASHER_INTERFACE_UART=1
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
-D C6_OTA_FLASHING
build_src_filter =
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.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 ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------
[env:ESP32_S3_C6_NANO_AP]
board = esp32-s3-devkitc-1
board_build.partitions = large_spiffs_16MB.csv
@@ -300,6 +404,7 @@ build_flags =
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
-D C6_OTA_FLASHING
-D HAS_SUBGHZ
build_src_filter =
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.cpp>
board_build.flash_mode=qio
@@ -309,6 +414,144 @@ board_upload.maximum_size = 16777216
board_upload.maximum_ram_size = 327680
board_upload.flash_size = 16MB
; ----------------------------------------------------------------------------------------
; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------
[env:OpenEPaperLink_Nano_TLSR]
board = esp32-s3-devkitc-1
board_build.partitions = large_spiffs_16MB.csv
build_unflags =
-std=gnu++11
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
-D ILI9341_DRIVER
lib_deps =
${env.lib_deps}
build_flags =
-std=gnu++17
${env.build_flags}
-D HAS_TFT
-D CORE_DEBUG_LEVEL=1
-D ARDUINO_USB_CDC_ON_BOOT=1
-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 HAS_BLE_WRITER
-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_DEBUG_SWS=21
-D FLASHER_DEBUG_TXD=15
-D FLASHER_DEBUG_RXD=7
-D FLASHER_DEBUG_PROG=6
-D FLASHER_LED=16
-D ST7735_NANO_TLSR
-D ST7735_DRIVER
-D ST7735_GREENTAB160x80
-D TFT_INVERSION_ON
-D TFT_WIDTH=80
-D TFT_HEIGHT=160
-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
-D LOAD_FONT4
-D LOAD_GLCD
-D MD5_ENABLED=1
-D SERIAL_FLASHER_INTERFACE_UART=1
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
-D C6_OTA_FLASHING
-D HAS_SUBGHZ
build_src_filter =
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.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 ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------
[env:OpenEPaperLink_Nano_TLSR_C6]
board = esp32-s3-devkitc-1
board_build.partitions = large_spiffs_16MB.csv
build_unflags =
-std=gnu++11
-D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
-D ILI9341_DRIVER
lib_deps =
${env.lib_deps}
build_flags =
-std=gnu++17
${env.build_flags}
-D HAS_TFT
-D CORE_DEBUG_LEVEL=1
-D ARDUINO_USB_CDC_ON_BOOT=1
-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 HAS_BLE_WRITER
-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=15
-D FLASHER_AP_RXD=7
-D FLASHER_DEBUG_SWS=21
-D FLASHER_DEBUG_TXD=18
-D FLASHER_DEBUG_RXD=17
-D FLASHER_DEBUG_PROG=6
-D FLASHER_LED=16
-D ST7735_NANO_TLSR
-D ST7735_DRIVER
-D ST7735_GREENTAB160x80
-D TFT_INVERSION_ON
-D TFT_WIDTH=80
-D TFT_HEIGHT=160
-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
-D LOAD_FONT4
-D LOAD_GLCD
-D MD5_ENABLED=1
-D SERIAL_FLASHER_INTERFACE_UART=1
-D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=200
-D SERIAL_FLASHER_RESET_HOLD_TIME_MS=200
-D C6_OTA_FLASHING
-D HAS_SUBGHZ
build_src_filter =
+<*>-<usbflasher.cpp>-<swd.cpp>-<webflasher.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 ESP32-S3 16MB Flash 8MB RAM
; ----------------------------------------------------------------------------------------

View File

@@ -0,0 +1,397 @@
#include <Arduino.h>
#include "cc_interface.h"
uint16_t CC_interface::begin(uint8_t CC, uint8_t DD, uint8_t RESET)
{
_CC_PIN = CC;
_DD_PIN = DD;
_RESET_PIN = RESET;
pinMode(_CC_PIN, OUTPUT);
pinMode(_DD_PIN, OUTPUT);
pinMode(_RESET_PIN, OUTPUT);
digitalWrite(_CC_PIN, LOW);
digitalWrite(_DD_PIN, HIGH);
digitalWrite(_RESET_PIN, HIGH);
enable_cc_debug();
uint16_t device_id_answer = send_cc_cmd(0x68);
opcode(0x00); // NOP
clock_init(); // Even with failed clock init return the device id, because if the device is locked setting clock will fail
return device_id_answer;
}
void CC_interface::set_callback(callbackPtr callBack)
{
_callback = callBack;
}
uint8_t CC_interface::set_lock_byte(uint8_t lock_byte)
{
lock_byte = lock_byte & 0x1f; // Max lock byte value
WR_CONFIG(0x01); // Select flash info Page
opcode(0x00); // NOP
opcode(0xE5, 0x92);
opcode(0x75, 0x92, 0x00);
opcode(0xE5, 0x83);
opcode(0xE5, 0x82);
opcode(0x90, 0xF0, 0x00);
opcode(0x74, 0xFF);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, lock_byte); // Transmit the set lock byte
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x90, 0x00, 0x00);
opcode(0x75, 0x92, 0x00);
opcode(0x74, 0x00);
opcode(0x00); // NOP
opcode(0xE5, 0x92);
opcode(0x75, 0x92, 0x00);
opcode(0xE5, 0x83);
opcode(0xE5, 0x82);
opcode(0x90, 0xF8, 0x00);
opcode(0x74, 0xF0);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0x00);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0xDF);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0xAF);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0x00);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0x02);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0x12);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x74, 0x4A);
opcode(0xF0);
opcode(0xA3); // Increase Pointer
opcode(0x90, 0x00, 0x00);
opcode(0x75, 0x92, 0x00);
opcode(0x74, 0x00);
opcode(0x00); // NOP
opcode(0xE5, 0xC6);
opcode(0x74, 0x00);
opcode(0x75, 0xAB, 0x23);
opcode(0x75, 0xD5, 0xF8);
opcode(0x75, 0xD4, 0x00);
opcode(0x75, 0xD6, 0x01);
opcode(0x75, 0xAD, 0x00);
opcode(0x75, 0xAC, 0x00);
opcode(0x75, 0xAE, 0x02);
opcode(0x00); // NOP
opcode(0xE5, 0xAE);
opcode(0x74, 0x00);
return WR_CONFIG(0x00); // Select normal flash page
}
uint8_t CC_interface::erase_chip()
{
opcode(0x00); // NOP
send_cc_cmdS(0x14);
int timeout = millis() + 100;
while (!(send_cc_cmdS(0x34) & 0x80))
{
if (millis() > timeout)
{
return 1;
}
}
return 0;
}
void CC_interface::read_code_memory(uint16_t address, uint16_t len, uint8_t buffer[])
{
int last_callback = 0;
opcode(0x75, 0xc7, 0x01);
opcode(0x90, address >> 8, address);
for (int i = 0; i < len; i++)
{
opcode(0xe4);
buffer[i] = opcode(0x93);
opcode(0xa3);
if (i - last_callback > 100)
{
last_callback = i;
if (_callback != nullptr)
{
uint8_t percent = ((float)((float)i / (float)len) * 100.0);
if (percent < 0)
percent = 0;
if (percent > 100)
percent = 100;
_callback(percent);
}
}
}
if (_callback != nullptr)
_callback(100);
}
void CC_interface::read_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[])
{
opcode(0x90, address >> 8, address);
for (int i = 0; i < len; i++)
{
buffer[i] = opcode(0xe0);
opcode(0xa3);
}
}
void CC_interface::write_xdata_memory(uint16_t address, uint16_t len, uint8_t buffer[])
{
opcode(0x90, address >> 8, address);
for (int i = 0; i < len; i++)
{
opcode(0x74, buffer[i]);
opcode(0xf0);
opcode(0xa3);
}
}
void CC_interface::set_pc(uint16_t address)
{
opcode(0x02, address >> 8, address);
}
uint8_t CC_interface::clock_init()
{
opcode(0x75, 0xc6, 0x00);
int timeout = millis() + 100;
while (!(opcode(0xe5, 0xbe) & 0x40))
{
if (millis() > timeout)
{
return 1;
}
}
return 0;
}
uint8_t CC_interface::write_code_memory(uint16_t address, uint8_t buffer[], int len)
{
int entry_len = len;
if (len % 2 != 0)
len++;
int position = 0;
int len_per_transfer = 64;
address = address / 2;
while (len)
{
flash_opcode[2] = (address >> 8) & 0xff;
flash_opcode[5] = address & 0xff;
flash_opcode[13] = (len > len_per_transfer) ? (len_per_transfer / 2) : (len / 2);
write_xdata_memory(0xf000, len_per_transfer, &buffer[position]);
write_xdata_memory(0xf100, sizeof(flash_opcode), flash_opcode);
opcode(0x75, 0xC7, 0x51);
set_pc(0xf100);
send_cc_cmdS(0x4c);
int timeout = millis() + 500;
while (!(send_cc_cmdS(0x34) & 0x08))
{
if (millis() > timeout)
{
if (_callback != nullptr)
_callback(0);
return 1;
}
}
if (_callback != nullptr)
{
uint8_t percent = 100 - ((float)((float)len / (float)entry_len) * 100.0);
if (percent < 0)
percent = 0;
if (percent > 100)
percent = 100;
_callback(percent);
}
len -= flash_opcode[13] * 2;
position += flash_opcode[13] * 2;
address += flash_opcode[13];
}
if (_callback != nullptr)
_callback(100);
return 0;
}
uint8_t CC_interface::verify_code_memory(uint16_t address, uint8_t buffer[], int len)
{
int last_callback = 0;
opcode(0x75, 0xc7, 0x01);
opcode(0x90, address >> 8, address);
for (int i = 0; i < len; i++)
{
opcode(0xe4);
if (buffer[i] != opcode(0x93))
{
if (_callback != nullptr)
_callback(0);
return 1;
}
opcode(0xa3);
if (i - last_callback > 100)
{
last_callback = i;
if (_callback != nullptr)
{
uint8_t percent = ((float)((float)i / (float)len) * 100.0);
if (percent < 0)
percent = 0;
if (percent > 100)
percent = 100;
_callback(percent);
}
}
}
if (_callback != nullptr)
_callback(100);
return 0;
}
uint8_t CC_interface::opcode(uint8_t opCode)
{
cc_send_byte(0x55);
cc_send_byte(opCode);
return cc_receive_byte();
}
uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1)
{
cc_send_byte(0x56);
cc_send_byte(opCode);
cc_send_byte(opCode1);
return cc_receive_byte();
}
uint8_t CC_interface::opcode(uint8_t opCode, uint8_t opCode1, uint8_t opCode2)
{
cc_send_byte(0x57);
cc_send_byte(opCode);
cc_send_byte(opCode1);
cc_send_byte(opCode2);
return cc_receive_byte();
}
uint8_t CC_interface::WR_CONFIG(uint8_t config)
{
cc_send_byte(0x1d);
cc_send_byte(config);
return cc_receive_byte();
}
uint8_t CC_interface::WD_CONFIG()
{
cc_send_byte(0x24);
return cc_receive_byte();
}
uint8_t CC_interface::send_cc_cmdS(uint8_t cmd)
{
cc_send_byte(cmd);
return cc_receive_byte();
}
uint16_t CC_interface::send_cc_cmd(uint8_t cmd)
{
cc_send_byte(cmd);
return (cc_receive_byte() << 8) + cc_receive_byte();
}
void CC_interface::cc_send_byte(uint8_t in_byte)
{
if (dd_direction == 1)
{
dd_direction = 0;
pinMode(_DD_PIN, OUTPUT);
digitalWrite(_DD_PIN, LOW);
}
for (int i = 8; i; i--)
{
if (in_byte & 0x80)
digitalWrite(_DD_PIN, HIGH);
else
digitalWrite(_DD_PIN, LOW);
digitalWrite(_CC_PIN, HIGH);
in_byte <<= 1;
delayMicroseconds(5);
digitalWrite(_CC_PIN, LOW);
}
}
uint8_t CC_interface::cc_receive_byte()
{
uint8_t out_byte = 0x00;
if (dd_direction == 0)
{
dd_direction = 1;
pinMode(_DD_PIN, INPUT);
digitalWrite(_DD_PIN, LOW);
}
for (int i = 8; i; i--)
{
digitalWrite(_CC_PIN, HIGH);
delayMicroseconds(5);
out_byte <<= 1;
if (digitalRead(_DD_PIN))
out_byte |= 0x01;
digitalWrite(_CC_PIN, LOW);
delayMicroseconds(5);
}
return out_byte;
}
void CC_interface::enable_cc_debug()
{
if (dd_direction == 0)
{
dd_direction = 1;
pinMode(_DD_PIN, INPUT);
digitalWrite(_DD_PIN, HIGH);
}
delay(5);
digitalWrite(_RESET_PIN, LOW);
delay(2);
digitalWrite(_CC_PIN, HIGH);
delayMicroseconds(5);
digitalWrite(_CC_PIN, LOW);
delayMicroseconds(5);
digitalWrite(_CC_PIN, HIGH);
delayMicroseconds(5);
digitalWrite(_CC_PIN, LOW);
delay(2);
digitalWrite(_RESET_PIN, HIGH);
delay(2);
}
void CC_interface::reset_cc()
{
if (dd_direction == 0)
{
dd_direction = 1;
pinMode(_DD_PIN, INPUT);
digitalWrite(_DD_PIN, HIGH);
}
delay(5);
digitalWrite(_RESET_PIN, LOW);
delay(5);
digitalWrite(_RESET_PIN, HIGH);
delay(2);
}

View File

@@ -8,9 +8,9 @@
#define CONTENT_NFCLUT
#define CONTENT_DAYAHEAD
#define CONTENT_TIMESTAMP
#endif
#define CONTENT_CAL
#define CONTENT_BUIENRADAR
#define CONTENT_CAL
#endif
#define CONTENT_TAGCFG
#include <Arduino.h>
@@ -64,7 +64,7 @@ void contentRunner() {
}
if (taginfo->expectedNextCheckin > now - 10 && taginfo->expectedNextCheckin < now + 30 && taginfo->pendingIdle == 0 && taginfo->pendingCount == 0) {
int16_t minutesUntilNextUpdate = (taginfo->nextupdate - now) / 60;
int32_t minutesUntilNextUpdate = (taginfo->nextupdate - now) / 60;
if (minutesUntilNextUpdate > config.maxsleep) {
minutesUntilNextUpdate = config.maxsleep;
}
@@ -336,8 +336,8 @@ void drawNew(const uint8_t mac[8], tagRecord *&taginfo) {
// https://github.com/erikflowers/weather-icons
drawWeather(filename, cfgobj, taginfo, imageParams);
taginfo->nextupdate = now + 1800;
updateTagImage(filename, mac, 15, taginfo, imageParams);
taginfo->nextupdate = now + interval;
updateTagImage(filename, mac, interval / 60, taginfo, imageParams);
break;
case 8: // Forecast
@@ -855,7 +855,7 @@ void drawWeather(String &filename, JsonObject &cfgobj, const tagRecord *taginfo,
const String tz = cfgobj["#tz"];
String units = "";
if (cfgobj["units"] == "1") {
units += "&temperature_unit=fahrenheit&windspeed_unit=mph";
units += "&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch";
}
DynamicJsonDocument doc(1000);
@@ -940,7 +940,7 @@ void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo
String tz = cfgobj["#tz"];
String units = "";
if (cfgobj["units"] == "1") {
units += "&temperature_unit=fahrenheit&windspeed_unit=mph";
units += "&temperature_unit=fahrenheit&windspeed_unit=mph&precipitation_unit=inch";
}
DynamicJsonDocument doc(2000);
@@ -990,10 +990,19 @@ void drawForecast(String &filename, JsonObject &cfgobj, const tagRecord *taginfo
}
if (loc["rain"]) {
const int8_t rain = round(daily["precipitation_sum"][dag].as<double>());
if (rain > 0) {
drawString(spr, String(rain) + "mm", dag * column1 + loc["rain"][0].as<int>(), loc["rain"][1], day[2], TC_DATUM, (rain > 10 ? imageParams.highlightColor : TFT_BLACK));
}
if (cfgobj["units"] == "0") {
const int8_t rain = round(daily["precipitation_sum"][dag].as<double>());
if (rain > 0) {
drawString(spr, String(rain) + "mm", dag * column1 + loc["rain"][0].as<int>(), loc["rain"][1], day[2], TC_DATUM, (rain > 10 ? imageParams.highlightColor : TFT_BLACK));
}
} else {
double fRain = daily["precipitation_sum"][dag].as<double>();
fRain = round(fRain*100.0) / 100.0;
if (fRain > 0.0) {
// inch, display if > .01 inches
drawString(spr, String(fRain) + "in", dag * column1 + loc["rain"][0].as<int>(), loc["rain"][1], day[2], TC_DATUM, (fRain > 0.5 ? imageParams.highlightColor : TFT_BLACK));
}
}
}
drawString(spr, String(tmin) + " ", dag * column1 + day[0].as<int>(), day[4], day[2], TR_DATUM, (tmin < 0 ? imageParams.highlightColor : TFT_BLACK));
@@ -1162,7 +1171,7 @@ char *epoch_to_display(time_t utc) {
#ifdef CONTENT_CAL
bool getCalFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo, imgParam &imageParams) {
// google apps scripts method to retrieve calendar
// see https://github.com/jjwbruijn/OpenEPaperLink/wiki/Google-Apps-Scripts for description
// see https://github.com/OpenEPaperLink/OpenEPaperLink/wiki/Google-Apps-Scripts for description
wsLog("get calendar");
@@ -1532,18 +1541,37 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
int units = cfgobj["units"].as<int>();
if (units == 0) units = 1;
double tarifkwh = cfgobj["tariffkwh"].as<double>();
double tarifkwh;
double tariftax = cfgobj["tarifftax"].as<double>();
double minPrice = (doc[0]["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
double maxPrice = minPrice;
double minPrice = std::numeric_limits<double>::max();
double maxPrice = std::numeric_limits<double>::lowest();
double prices[n];
DynamicJsonDocument doc2(500);
JsonArray tariffArray;
std::string tariffString = cfgobj["tariffkwh"].as<std::string>();
if (tariffString.front() == '[') {
if (deserializeJson(doc2, tariffString) == DeserializationError::Ok) {
tariffArray = doc2.as<JsonArray>();
} else {
Serial.println("Error in tariffkwh array");
}
}
for (int i = 0; i < n; i++) {
const JsonObject &obj = doc[i];
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
minPrice = min(minPrice, price);
maxPrice = max(maxPrice, price);
prices[i] = price;
if (tariffArray.size() == 24) {
const time_t item_time = obj["time"];
struct tm item_timeinfo;
localtime_r(&item_time, &item_timeinfo);
tarifkwh = tariffArray[item_timeinfo.tm_hour].as<double>();
} else {
tarifkwh = cfgobj["tariffkwh"].as<double>();
}
prices[i] = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
minPrice = std::min(minPrice, prices[i]);
maxPrice = std::max(maxPrice, prices[i]);
}
std::sort(prices, prices + n);
@@ -1556,14 +1584,17 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
for (double i = minPrice; i <= maxPrice; i += yAxisScale.step) {
int y = mapDouble(i, minPrice, maxPrice, spr.height() - barBottom, spr.height() - barBottom - loc["bars"][2].as<int>());
spr.drawLine(0, y, spr.width(), y, TFT_BLACK);
drawString(spr, String(int(i * units)), yAxisX, y - 9, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
if (loc["yaxis"][0]) drawString(spr, String(int(i * units)), yAxisX, y - 9, loc["yaxis"][0], TL_DATUM, TFT_BLACK);
}
uint16_t barwidth = loc["bars"][1].as<int>() / n;
uint16_t barheight = loc["bars"][2].as<int>() / (maxPrice - minPrice);
uint16_t arrowY = 0;
if (loc["bars"].size() >= 5) arrowY = loc["bars"][4].as<int>();
uint16_t barX = loc["bars"][0].as<int>();
double pricenow = std::numeric_limits<double>::quiet_NaN();
bool showcurrent = true;
if (cfgobj["showcurr"] && cfgobj["showcurr"] == "0") showcurrent = false;
for (int i = 0; i < n; i++) {
const JsonObject &obj = doc[i];
@@ -1571,27 +1602,40 @@ bool getDayAheadFeed(String &filename, JsonObject &cfgobj, tagRecord *&taginfo,
struct tm item_timeinfo;
localtime_r(&item_time, &item_timeinfo);
if (tariffArray.size() == 24) {
tarifkwh = tariffArray[item_timeinfo.tm_hour].as<double>();
} else {
tarifkwh = cfgobj["tariffkwh"].as<double>();
}
const double price = (obj["price"].as<double>() / 10 + tarifkwh) * (1 + tariftax / 100) / units;
uint16_t barcolor = getPercentileColor(prices, n, price, imageParams.hwdata);
uint16_t thisbarh = mapDouble(price, minPrice, maxPrice, 0, loc["bars"][2].as<int>());
spr.fillRect(barX + i * barwidth, spr.height() - barBottom - thisbarh, barwidth - 1, thisbarh, barcolor);
if (i % 2 == 0) {
if (i % 2 == 0 && loc["time"][0]) {
drawString(spr, String(item_timeinfo.tm_hour), barX + i * barwidth + barwidth / 3 + 1, spr.height() - barBottom + 3, loc["time"][0], TC_DATUM, TFT_BLACK);
}
if (now - item_time < 3600 && std::isnan(pricenow)) {
spr.fillRect(barX + i * barwidth + 3, 5, barwidth - 6, 10, imageParams.highlightColor);
spr.fillTriangle(barX + i * barwidth, 15,
barX + i * barwidth + barwidth - 1, 15,
barX + i * barwidth + (barwidth - 1) / 2, 15 + barwidth, imageParams.highlightColor);
spr.drawLine(barX + i * barwidth + (barwidth - 1) / 2, 20 + barwidth, barX + i * barwidth + (barwidth - 1) / 2, spr.height(), getColor("pink"));
if (now - item_time < 3600 && std::isnan(pricenow) && showcurrent) {
spr.fillRect(barX + i * barwidth + (barwidth > 6 ? 3 : 1), 5 + arrowY, (barwidth > 6 ? barwidth - 6 : barwidth - 2), 10, imageParams.highlightColor);
spr.fillTriangle(barX + i * barwidth, 15 + arrowY,
barX + i * barwidth + barwidth - 1, 15 + arrowY,
barX + i * barwidth + (barwidth - 1) / 2, 15 + barwidth + arrowY, imageParams.highlightColor);
spr.drawLine(barX + i * barwidth + (barwidth - 1) / 2, 20 + barwidth + arrowY, barX + i * barwidth + (barwidth - 1) / 2, spr.height(), getColor("pink"));
pricenow = price;
}
}
drawString(spr, String(timeinfo.tm_hour) + ":00", barX, 5, loc["head"][0], TL_DATUM, TFT_BLACK, 30);
drawString(spr, String(pricenow) + "/kWh", spr.width() - barX, 5, loc["head"][0], TR_DATUM, TFT_BLACK, 30);
if (showcurrent) {
if (barwidth < 5) {
drawString(spr, String(timeinfo.tm_hour) + ":00", spr.width() / 2, 5, "calibrib16.vlw", TC_DATUM, TFT_BLACK, 30);
drawString(spr, String(pricenow) + "/kWh", spr.width() / 2, 25, loc["head"][0], TC_DATUM, TFT_BLACK, 30);
} else {
drawString(spr, String(timeinfo.tm_hour) + ":00", barX, 5, loc["head"][0], TL_DATUM, TFT_BLACK, 30);
drawString(spr, String(pricenow) + "/kWh", spr.width() - barX, 5, loc["head"][0], TR_DATUM, TFT_BLACK, 30);
}
}
spr2buffer(spr, filename, imageParams);
spr.deleteSprite();

View File

@@ -19,7 +19,174 @@ uint8_t YellowSense = 0;
bool tftLogscreen = true;
bool tftOverride = false;
#ifdef HAS_LILYGO_TPANEL
static const uint8_t st7701_type9_init_operations_lilygo[] = {
BEGIN_WRITE,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x13,
WRITE_C8_D8, 0xEF, 0x08,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x10,
WRITE_C8_D16, 0xC0, 0x3B, 0x00,
WRITE_C8_D16, 0xC1, 0x0B, 0x02,
WRITE_COMMAND_8, 0xC2,
WRITE_BYTES, 3, 0x30, 0x02, 0x37,
WRITE_C8_D8, 0xCC, 0x10,
WRITE_COMMAND_8, 0xB0, // Positive Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x0F, 0x16, 0x0E,
0x11, 0x07, 0x09, 0x09,
0x08, 0x23, 0x05, 0x11,
0x0F, 0x28, 0x2D, 0x18,
WRITE_COMMAND_8, 0xB1, // Negative Voltage Gamma Control
WRITE_BYTES, 16,
0x00, 0x0F, 0x16, 0x0E,
0x11, 0x07, 0x09, 0x08,
0x09, 0x23, 0x05, 0x11,
0x0F, 0x28, 0x2D, 0x18,
WRITE_COMMAND_8, 0xFF,
WRITE_BYTES, 5, 0x77, 0x01, 0x00, 0x00, 0x11,
WRITE_C8_D8, 0xB0, 0x4D,
WRITE_C8_D8, 0xB1, 0x33,
WRITE_C8_D8, 0xB2, 0x87,
WRITE_C8_D8, 0xB5, 0x4B,
WRITE_C8_D8, 0xB7, 0x8C,
WRITE_C8_D8, 0xB8, 0x20,
WRITE_C8_D8, 0xC1, 0x78,
WRITE_C8_D8, 0xC2, 0x78,
WRITE_C8_D8, 0xD0, 0x88,
WRITE_COMMAND_8, 0xE0,
WRITE_BYTES, 3, 0x00, 0x00, 0x02,
WRITE_COMMAND_8, 0xE1,
WRITE_BYTES, 11,
0x02, 0xF0, 0x00, 0x00,
0x03, 0xF0, 0x00, 0x00,
0x00, 0x44, 0x44,
WRITE_COMMAND_8, 0xE2,
WRITE_BYTES, 12,
0x10, 0x10, 0x40, 0x40,
0xF2, 0xF0, 0x00, 0x00,
0xF2, 0xF0, 0x00, 0x00,
WRITE_COMMAND_8, 0xE3,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE4, 0x44, 0x44,
WRITE_COMMAND_8, 0xE5,
WRITE_BYTES, 16,
0x07, 0xEF, 0xF0, 0xF0,
0x09, 0xF1, 0xF0, 0xF0,
0x03, 0xF3, 0xF0, 0xF0,
0x05, 0xED, 0xF0, 0xF0,
WRITE_COMMAND_8, 0xE6,
WRITE_BYTES, 4, 0x00, 0x00, 0x11, 0x11,
WRITE_C8_D16, 0xE7, 0x44, 0x44,
WRITE_COMMAND_8, 0xE8,
WRITE_BYTES, 16,
0x08, 0xF0, 0xF0, 0xF0,
0x0A, 0xF2, 0xF0, 0xF0,
0x04, 0xF4, 0xF0, 0xF0,
0x06, 0xEE, 0xF0, 0xF0,
WRITE_COMMAND_8, 0xEB,
WRITE_BYTES, 7,
0x00, 0x00, 0xE4, 0xE4,
0x44, 0x88, 0x40,
WRITE_C8_D16, 0xEC, 0x78, 0x00,
WRITE_COMMAND_8, 0xED,
WRITE_BYTES, 16,
0x20, 0xF9, 0x87, 0x76,
0x65, 0x54, 0x4F, 0xFF,
0xFF, 0xF4, 0x45, 0x56,
0x67, 0x78, 0x9F, 0x02,
WRITE_COMMAND_8, 0xEF,
WRITE_BYTES, 6,
0x10, 0x0D, 0x04, 0x08,
0x3F, 0x1F,
// WRITE_C8_D8, 0xCD, 0x05,//Test
WRITE_C8_D8, 0x3A, 0x55,
WRITE_C8_D8, 0x36, 0x08,
WRITE_COMMAND_8, 0x11,
// WRITE_COMMAND_8, 0xFF,//Test
// WRITE_BYTES, 5,
// 0x77, 0x01, 0x00, 0x00,
// 0x12,
// WRITE_C8_D8, 0xD1, 0x81,//Test
// WRITE_C8_D8, 0xD2, 0x08,//Test
WRITE_COMMAND_8, 0x29, // Display On
// WRITE_C8_D8, 0x35, 0x00,//Test
// WRITE_C8_D8, 0xCE, 0x04,//Test
// WRITE_COMMAND_8, 0xF2,//Test
// WRITE_BYTES, 4,
// 0xF0, 0xA3, 0xA3, 0x71,
END_WRITE};
Arduino_DataBus *bus = new Arduino_XL9535SWSPI(IIC_SDA /* SDA */, IIC_SCL /* SCL */, -1 /* XL PWD */,
XL95X5_CS /* XL CS */, XL95X5_SCLK /* XL SCK */, XL95X5_MOSI /* XL MOSI */);
Arduino_ESP32RGBPanel *rgbpanel = new Arduino_ESP32RGBPanel(
-1 /* DE */, LCD_VSYNC /* VSYNC */, LCD_HSYNC /* HSYNC */, LCD_PCLK /* PCLK */,
LCD_B0 /* B0 */, LCD_B1 /* B1 */, LCD_B2 /* B2 */, LCD_B3 /* B3 */, LCD_B4 /* B4 */,
LCD_G0 /* G0 */, LCD_G1 /* G1 */, LCD_G2 /* G2 */, LCD_G3 /* G3 */, LCD_G4 /* G4 */, LCD_G5 /* G5 */,
LCD_R0 /* R0 */, LCD_R1 /* R1 */, LCD_R2 /* R2 */, LCD_R3 /* R3 */, LCD_R4 /* R4 */,
1 /* hsync_polarity */, 20 /* hsync_front_porch */, 2 /* hsync_pulse_width */, 0 /* hsync_back_porch */,
1 /* vsync_polarity */, 30 /* vsync_front_porch */, 8 /* vsync_pulse_width */, 1 /* vsync_back_porch */,
10 /* pclk_active_neg */, 6000000L /* prefer_speed */, true /* useBigEndian */,
0 /* de_idle_high*/, 0 /* pclk_idle_high */);
Arduino_RGB_Display *gfx = new Arduino_RGB_Display(
LCD_WIDTH /* width */, LCD_HEIGHT /* height */, rgbpanel, 0 /* rotation */, true /* auto_flush */,
bus, -1 /* RST */, st7701_type9_init_operations_lilygo, sizeof(st7701_type9_init_operations_lilygo));
#endif
void TFTLog(String text) {
#ifdef HAS_LILYGO_TPANEL
gfx->setTextSize(2);
if (tftLogscreen == false) {
gfx->fillScreen(BLACK);
gfx->setCursor(0, 0);
tftLogscreen = true;
}
if (text.isEmpty()) return;
gfx->setTextColor(WHITE);
gfx->println(text);
#else
if (tftLogscreen == false) {
tft2.fillScreen(TFT_BLACK);
tft2.setCursor(0, 0, (tft2.width() == 160 ? 1 : 2));
@@ -53,6 +220,7 @@ void TFTLog(String text) {
tft2.setTextColor(TFT_GREEN);
}
tft2.println(text);
#endif
}
int32_t findId(uint8_t mac[8]) {
@@ -72,7 +240,11 @@ void sendAvail(uint8_t wakeupReason) {
memcpy(&eadr.src, mac, 6);
eadr.adr.lastPacketRSSI = WiFi.RSSI();
eadr.adr.currentChannel = config.channel;
#ifdef HAS_LILYGO_TPANEL
eadr.adr.hwType = 0xE2;
#else
eadr.adr.hwType = (tft2.width() == 160 ? 0xE1 : 0xE0);
#endif
eadr.adr.wakeupReason = wakeupReason;
eadr.adr.capabilities = 0;
eadr.adr.tagSoftwareVersion = 0;
@@ -81,6 +253,25 @@ void sendAvail(uint8_t wakeupReason) {
}
void yellow_ap_display_init(void) {
#ifdef HAS_LILYGO_TPANEL
tftLogscreen = true;
pinMode(LCD_BL, OUTPUT);
digitalWrite(LCD_BL, HIGH);
ledcAttachPin(LCD_BL, 1);
ledcSetup(1, 1000, 8);
ledcWrite(1, config.tft); // brightness
Wire.begin(IIC_SDA, IIC_SCL);
gfx->begin();
gfx->fillScreen(BLACK);
#else
pinMode(YELLOW_SENSE, INPUT_PULLDOWN);
vTaskDelay(100 / portTICK_PERIOD_MS);
if (digitalRead(YELLOW_SENSE) == HIGH) YellowSense = 1;
@@ -88,7 +279,12 @@ void yellow_ap_display_init(void) {
digitalWrite(TFT_BACKLIGHT, LOW);
tft2.init();
#ifdef ST7735_NANO_TLSR
YellowSense = 0;
tft2.setRotation(1);
#else
tft2.setRotation(YellowSense == 1 ? 1 : 3);
#endif
tft2.fillScreen(TFT_BLACK);
tft2.setCursor(12, 0, (tft2.width() == 160 ? 1 : 2));
tft2.setTextColor(TFT_WHITE);
@@ -100,6 +296,7 @@ void yellow_ap_display_init(void) {
GPIO.func_out_sel_cfg[TFT_BACKLIGHT].inv_sel = 1;
}
ledcWrite(6, config.tft);
#endif
}
void yellow_ap_display_loop(void) {
@@ -141,7 +338,19 @@ void yellow_ap_display_loop(void) {
void* spriteData = spr.getPointer();
size_t bytesRead = file.readBytes((char*)spriteData, spr.width() * spr.height() * 2);
file.close();
#ifdef HAS_LILYGO_TPANEL
long dy = spr.height();
long dx = spr.width();
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData));
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData, dx, dy);
spr.deleteSprite();
#else
spr.pushSprite(0, 0);
#endif
tftLogscreen = false;
struct espXferComplete xfc = {0};

View File

@@ -132,8 +132,13 @@ void rgbIdleStep() {
void setBrightness(int brightness) {
maxledbrightness = brightness;
#ifdef HAS_TFT
#ifdef HAS_LILYGO_TPANEL
ledcWrite(1, config.tft);
#else
#ifdef HAS_TFT
ledcWrite(6, config.tft);
#endif
#endif
#ifdef HAS_RGB_LED
FastLED.setBrightness(maxledbrightness);
@@ -145,8 +150,12 @@ void updateBrightnessFromConfig() {
if (newbrightness != maxledbrightness) {
setBrightness(newbrightness);
}
#ifdef HAS_TFT
#ifdef HAS_LILYGO_TPANEL
ledcWrite(1, config.tft);
#else
#ifdef HAS_TFT
ledcWrite(6, config.tft);
#endif
#endif
if (apInfo.state == AP_STATE_NORADIO) addFadeMono(config.led);
}

View File

@@ -26,7 +26,9 @@
#include "udp.h"
#include "util.h"
#include "web.h"
#ifdef HAS_BLE_WRITER
#include "ble_writer.h"
#endif
util::Timer intervalContentRunner(seconds(1));
util::Timer intervalSysinfo(seconds(5));

View File

@@ -80,6 +80,7 @@ uint32_t colorDistance(Color &c1, Color &c2, Error &e1) {
}
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();
@@ -273,7 +274,11 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
if (fileout == "direct") {
if (tftOverride == false) {
TFT_eSprite spr2 = TFT_eSprite(&tft2);
#ifdef ST7735_NANO_TLSR
tft2.setRotation(1);
#else
tft2.setRotation(YellowSense == 1 ? 1 : 3);
#endif
spr2.createSprite(spr.width(), spr.height());
spr2.setColorDepth(spr.getColorDepth());
@@ -282,7 +287,20 @@ void spr2buffer(TFT_eSprite &spr, String &fileout, imgParam &imageParams) {
size_t dataSize = spr.width() * spr.height() * (spr.getColorDepth() / 8);
memcpy(spriteData2, spriteData, dataSize);
#ifdef HAS_LILYGO_TPANEL
if (spr.getColorDepth() == 16)
{
long dy = spr.height();
long dx = spr.width();
uint16_t* data = static_cast<uint16_t*>(const_cast<void*>(spriteData2));
gfx->draw16bitRGBBitmap(0, 0, (uint16_t *)spriteData2, dx, dy);
spr2.deleteSprite();
}
#else
spr2.pushSprite(0, 0);
#endif
}
return;
}

View File

@@ -268,10 +268,10 @@ void destroyDB() {
uint32_t getTagCount() {
uint32_t temp = 0;
return getTagCount(temp);
return getTagCount(temp, temp);
}
uint32_t getTagCount(uint32_t& timeoutcount) {
uint32_t getTagCount(uint32_t& timeoutcount, uint32_t& lowbattcount) {
uint32_t tagcount = 0;
time_t now;
time(&now);
@@ -285,6 +285,7 @@ uint32_t getTagCount(uint32_t& timeoutcount) {
// expected checkin is behind, timeout if not seen last 10 minutes
if (timeout > 600) timeoutcount++;
}
if (taginfo->batteryMv < 2400 && taginfo->batteryMv != 0 && taginfo->batteryMv != 1337) lowbattcount++;
}
return tagcount;
}
@@ -307,7 +308,7 @@ void clearPending(tagRecord* taginfo) {
}
void initAPconfig() {
DynamicJsonDocument APconfig(500);
DynamicJsonDocument APconfig(768);
File configFile = contentFS->open("/current/apconfig.json", "r");
if (configFile) {
DeserializationError error = deserializeJson(APconfig, configFile);
@@ -327,17 +328,19 @@ void initAPconfig() {
config.maxsleep = APconfig.containsKey("maxsleep") ? APconfig["maxsleep"] : 10;
config.stopsleep = APconfig.containsKey("stopsleep") ? APconfig["stopsleep"] : 1;
config.preview = APconfig.containsKey("preview") ? APconfig["preview"] : 1;
config.nightlyreboot = APconfig.containsKey("nightlyreboot") ? APconfig["nightlyreboot"] : 1;
config.lock = APconfig.containsKey("lock") ? APconfig["lock"] : 0;
config.sleepTime1 = APconfig.containsKey("sleeptime1") ? APconfig["sleeptime1"] : 0;
config.sleepTime2 = APconfig.containsKey("sleeptime2") ? APconfig["sleeptime2"] : 0;
config.ble = APconfig.containsKey("ble") ? APconfig["ble"] : 0;
config.discovery = APconfig.containsKey("discovery") ? APconfig["discovery"] : 0;
#ifdef BLE_ONLY
config.ble = true;
#endif
// default wifi power 8.5 dbM
// see https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiGeneric.h#L111
config.wifiPower = APconfig.containsKey("wifipower") ? APconfig["wifipower"] : 34;
config.repo = APconfig.containsKey("repo") ? APconfig["repo"].as<String>() : String("jjwbruijn/OpenEPaperLink");
config.repo = APconfig.containsKey("repo") ? APconfig["repo"].as<String>() : String("OpenEPaperLink/OpenEPaperLink");
config.env = APconfig.containsKey("env") ? APconfig["env"].as<String>() : String(STR(BUILD_ENV_NAME));
if (APconfig["timezone"]) {
strlcpy(config.timeZone, APconfig["timezone"], sizeof(config.timeZone));
@@ -359,6 +362,7 @@ void saveAPconfig() {
APconfig["maxsleep"] = config.maxsleep;
APconfig["stopsleep"] = config.stopsleep;
APconfig["preview"] = config.preview;
APconfig["nightlyreboot"] = config.nightlyreboot;
APconfig["lock"] = config.lock;
APconfig["wifipower"] = config.wifiPower;
APconfig["timezone"] = config.timeZone;
@@ -367,6 +371,7 @@ void saveAPconfig() {
APconfig["ble"] = config.ble;
APconfig["repo"] = config.repo;
APconfig["env"] = config.env;
APconfig["discovery"] = config.discovery;
serializeJsonPretty(APconfig, configFile);
configFile.close();
xSemaphoreGive(fsMutex);

View File

@@ -31,12 +31,22 @@ UDPcomm::~UDPcomm() {
}
void UDPcomm::init() {
if (udp.listenMulticast(UDPIP, UDPPORT)) {
udp.onPacket([this](AsyncUDPPacket packet) {
if (packet.remoteIP() != WiFi.localIP()) {
this->processPacket(packet);
}
});
if (config.discovery == 0) {
if (udp.listenMulticast(UDPIP, UDPPORT)) {
udp.onPacket([this](AsyncUDPPacket packet) {
if (packet.remoteIP() != WiFi.localIP()) {
this->processPacket(packet);
}
});
}
} else {
if (udp.listen(UDPPORT)) {
udp.onPacket([this](AsyncUDPPacket packet) {
if (packet.isBroadcast() && packet.remoteIP() != WiFi.localIP()) {
this->processPacket(packet);
}
});
}
}
setAPchannel();
}
@@ -87,7 +97,7 @@ void UDPcomm::processPacket(AsyncUDPPacket packet) {
uint8_t buffer[sizeof(struct APlist) + 1];
buffer[0] = PKT_APLIST_REPLY;
memcpy(buffer + 1, &APitem, sizeof(struct APlist));
udp.writeTo(buffer, sizeof(buffer), senderIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), senderIP);
break;
}
case PKT_APLIST_REPLY: {
@@ -158,40 +168,48 @@ void UDPcomm::getAPList() {
uint8_t buffer[sizeof(struct APlist) + 1];
buffer[0] = PKT_APLIST_REQ;
memcpy(buffer + 1, &APitem, sizeof(struct APlist));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::netProcessDataReq(struct espAvailDataReq* eadr) {
uint8_t buffer[sizeof(struct espAvailDataReq) + 1];
buffer[0] = PKT_AVAIL_DATA_INFO;
memcpy(buffer + 1, eadr, sizeof(struct espAvailDataReq));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::netProcessXferComplete(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_COMPLETE;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::netProcessXferTimeout(struct espXferComplete* xfc) {
uint8_t buffer[sizeof(struct espXferComplete) + 1];
buffer[0] = PKT_XFER_TIMEOUT;
memcpy(buffer + 1, xfc, sizeof(struct espXferComplete));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::netSendDataAvail(struct pendingData* pending) {
uint8_t buffer[sizeof(struct pendingData) + 1];
buffer[0] = PKT_AVAIL_DATA_REQ;
memcpy(buffer + 1, pending, sizeof(struct pendingData));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::netTaginfo(struct TagInfo* taginfoitem) {
uint8_t buffer[sizeof(struct TagInfo) + 1];
buffer[0] = PKT_TAGINFO;
memcpy(buffer + 1, taginfoitem, sizeof(struct TagInfo));
udp.writeTo(buffer, sizeof(buffer), UDPIP, UDPPORT);
writeUdpPacket(buffer, sizeof(buffer), UDPIP);
}
void UDPcomm::writeUdpPacket(uint8_t *buffer, uint16_t len, IPAddress senderIP) {
if (config.discovery == 0) {
udp.writeTo(buffer, len, senderIP, UDPPORT);
} else {
udp.broadcastTo(buffer, len, UDPPORT);
}
}

View File

@@ -20,6 +20,7 @@ USBCDC USBSerial;
#include "web.h"
#include "webflasher.h"
#include "zbs_interface.h"
#include "cc_interface.h"
QueueHandle_t flasherCmdQueue;
@@ -310,6 +311,7 @@ typedef enum {
CMD_SELECT_ZBS243 = 60,
CMD_SELECT_NRF82511 = 61,
CMD_SELECT_CC = 62,
CMD_SELECT_PORT = 70,
@@ -323,15 +325,17 @@ typedef enum {
CMD_WRITE_ERROR = 99,
} ZBS_UART_PROTO;
uint32_t FLASHER_VERSION = 0x00000031;
uint32_t FLASHER_VERSION = 0x00000032;
#define CONTROLLER_ZBS243 0
#define CONTROLLER_NRF82511 1
#define CONTROLLER_CC 2
uint8_t selectedController = 0;
uint8_t selectedFlasherPort;
uint32_t currentFlasherOffset;
flasher* zbsflasherp = nullptr;
nrfswd* nrfflasherp = nullptr;
CC_interface *ccflasherp = nullptr;
void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
uint8_t* tempbuffer;
@@ -400,6 +404,9 @@ void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
} else if (selectedController == CONTROLLER_ZBS243) {
if (zbsflasherp == nullptr) return;
zbsflasherp->zbs->erase_flash();
} else if (selectedController == CONTROLLER_CC) {
if (ccflasherp == nullptr) return;
ccflasherp->erase_chip();
}
sendFlasherAnswer(CMD_ERASE_FLASH, NULL, 0, transportType);
break;
@@ -451,6 +458,14 @@ void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
currentFlasherOffset = 0;
selectedController = CONTROLLER_NRF82511;
break;
case CMD_SELECT_CC:
ccflasherp = new CC_interface;
ccflasherp->begin(FLASHER_EXT_CLK,FLASHER_EXT_MISO,FLASHER_EXT_RESET);
temp_buff[0] = 1;
sendFlasherAnswer(CMD_SELECT_CC, temp_buff, 1,transportType);
currentFlasherOffset = 0;
selectedController = CONTROLLER_CC;
break;
case CMD_READ_FLASH:
wsSerial("> read flash");
uint8_t* bufferp;
@@ -481,6 +496,19 @@ void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
sendFlasherAnswer(CMD_READ_FLASH, bufferp, cur_len, transportType);
if (bufferp != nullptr) free(bufferp);
}
} else if (selectedController == CONTROLLER_CC) {
if (ccflasherp == nullptr) return;
if (currentFlasherOffset >= 32768) {
sendFlasherAnswer(CMD_COMPLETE, temp_buff, 1,transportType);
} else {
bufferp = (uint8_t*)malloc(1024);
if (bufferp == nullptr) return;
cur_len = (32768 - currentFlasherOffset >= 1024) ? 1024 : 32768 - currentFlasherOffset;
ccflasherp->read_code_memory(currentFlasherOffset,cur_len,bufferp);
currentFlasherOffset += cur_len;
sendFlasherAnswer(CMD_READ_FLASH, bufferp, cur_len,transportType);
free(bufferp);
}
}
break;
case CMD_READ_INFOPAGE:
@@ -550,6 +578,15 @@ void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
currentFlasherOffset += cmd->len;
sendFlasherAnswer(CMD_WRITE_FLASH, NULL, 0, transportType);
}
} else if (selectedController == CONTROLLER_CC) {
if (currentFlasherOffset >= 32768) {
sendFlasherAnswer(CMD_COMPLETE, temp_buff, 1, transportType);
} else {
if (ccflasherp == nullptr) return;
ccflasherp->write_code_memory(currentFlasherOffset, cmd->data, cmd->len);
currentFlasherOffset += cmd->len;
sendFlasherAnswer(CMD_WRITE_FLASH, NULL, 0, transportType);
}
}
break;
case CMD_WRITE_INFOPAGE:
@@ -603,6 +640,10 @@ void processFlasherCommand(struct flasherCommand* cmd, uint8_t transportType) {
cmdSerial.println("Not yet implemented!");
}
break;
default:
cmdSerial.printf("Ignored flasher command 0x%x.\r\n",cmd->command);
break;
}
}
@@ -618,6 +659,10 @@ void flasherCommandTimeout() {
delete nrfflasherp;
nrfflasherp = nullptr;
}
if (ccflasherp != nullptr) {
delete ccflasherp;
ccflasherp = nullptr;
}
lastCmdTimeStamp = 0;
}

View File

@@ -68,7 +68,7 @@ size_t dbSize() {
}
void wsSendSysteminfo() {
DynamicJsonDocument doc(250);
DynamicJsonDocument doc(300);
JsonObject sys = doc.createNestedObject("sys");
time_t now;
time(&now);
@@ -119,7 +119,7 @@ void wsSendSysteminfo() {
ApChanString += "disabled";
}
else {
ApChanString += "Ch " + String(apInfo.SubGhzChannel);
ApChanString += String(apInfo.SubGhzChannel);
}
}
setVarDB("ap_ch", ApChanString);
@@ -128,7 +128,7 @@ void wsSendSysteminfo() {
#endif
// reboot once at night
if (timeinfo.tm_hour == 4 && timeinfo.tm_min == 0 && millis() > 2 * 3600 * 1000) {
if (timeinfo.tm_hour == 3 && timeinfo.tm_min == 56 && millis() > 2 * 3600 * 1000 && config.nightlyreboot == 1) {
logLine("Nightly reboot");
wsErr("REBOOTING");
config.runStatus = RUNSTATUS_STOP;
@@ -143,8 +143,10 @@ void wsSendSysteminfo() {
static uint32_t tagcounttimer = 0;
if (millis() - tagcounttimer > 60000 || tagcounttimer == 0) {
uint32_t timeoutcount = 0;
uint32_t tagcount = getTagCount(timeoutcount);
uint32_t timeoutcount = 0, lowbattcount = 0;
uint32_t tagcount = getTagCount(timeoutcount, lowbattcount);
sys["lowbattcount"] = lowbattcount;
sys["timeoutcount"] = timeoutcount;
char result[40];
if (timeoutcount > 0) {
snprintf(result, sizeof(result), "%lu/%lu, %lu timeout", tagcount, tagDB.size(), timeoutcount);
@@ -352,14 +354,20 @@ void init_web() {
if (hex2mac(dst, mac)) {
tagRecord *taginfo = tagRecord::findByMAC(mac);
if (taginfo != nullptr) {
uint16_t newContentMode = atoi(request->getParam("contentmode", true)->value().c_str());
if (newContentMode != taginfo->contentMode && (newContentMode == 5 || newContentMode == 17 || newContentMode == 18)) {
// temporary content, restore after sending
pushTagInfo(taginfo);
if (request->hasParam("contentmode", true)) {
uint16_t newContentMode = atoi(request->getParam("contentmode", true)->value().c_str());
if (newContentMode != taginfo->contentMode && (newContentMode == 5 || newContentMode == 17 || newContentMode == 18)) {
// temporary content, restore after sending
pushTagInfo(taginfo);
}
taginfo->contentMode = newContentMode;
}
if (request->hasParam("alias", true)) {
taginfo->alias = request->getParam("alias", true)->value();
}
if (request->hasParam("modecfgjson", true)) {
taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value();
}
taginfo->alias = request->getParam("alias", true)->value();
taginfo->modeConfigJson = request->getParam("modecfgjson", true)->value();
taginfo->contentMode = newContentMode;
taginfo->nextupdate = 0;
if (request->hasParam("rotate", true)) {
taginfo->rotate = atoi(request->getParam("rotate", true)->value().c_str());
@@ -478,7 +486,7 @@ void init_web() {
server.on("/led_flash", HTTP_GET, [](AsyncWebServerRequest *request) {
// color picker: https://roger-random.github.io/RGB332_color_wheel_three.js/
// http GET to /led_flash?mac=000000000000&pattern=000000000000000000000000
// see https://github.com/jjwbruijn/OpenEPaperLink/wiki/Led-control
// see https://github.com/OpenEPaperLink/OpenEPaperLink/wiki/Led-control
if (request->hasParam("mac")) {
String dst = request->getParam("mac")->value();
uint8_t mac[8];
@@ -594,6 +602,9 @@ void init_web() {
if (request->hasParam("preview", true)) {
config.preview = static_cast<uint8_t>(request->getParam("preview", true)->value().toInt());
}
if (request->hasParam("nightlyreboot", true)) {
config.nightlyreboot = static_cast<uint8_t>(request->getParam("nightlyreboot", true)->value().toInt());
}
if (request->hasParam("lock", true)) {
config.lock = static_cast<uint8_t>(request->getParam("lock", true)->value().toInt());
}
@@ -614,6 +625,9 @@ void init_web() {
setenv("TZ", config.timeZone, 1);
tzset();
}
if (request->hasParam("discovery", true)) {
config.discovery = static_cast<uint8_t>(request->getParam("discovery", true)->value().toInt());
}
if (request->hasParam("repo", true)) {
config.repo = request->getParam("repo", true)->value();
}

View File

@@ -103,7 +103,18 @@
"type": "select",
"options": {
"0": "-Celcius / Beaufort / millimeters",
"1": "Fahrenheit / mph / millimeters"
"1": "Fahrenheit / mph / inches"
}
},
{
"key": "interval",
"name": "Interval",
"desc": "How often the info is being refreshed.",
"type": "select",
"options": {
"30": "-Every 30 minutes",
"60": "Every hour",
"180": "Every three hours"
}
},
{
@@ -144,7 +155,7 @@
"type": "select",
"options": {
"0": "-Celcius / Beaufort / millimeters",
"1": "Fahrenheit / mph / millimeters"
"1": "Fahrenheit / mph / inches"
}
},
{
@@ -392,7 +403,7 @@
{
"key": "tariffkwh",
"name": "Fixed surcharge",
"desc": "Fixed surcharge per kWh, in 1/100 units (cents/öre/øre)",
"desc": "Fixed surcharge per kWh, in 1/100 units (cents/öre/øre). Enter one value, or an array of exactly 24 elements for each hour in the form of '[n,n,...,n]'",
"type": "text"
},
{
@@ -410,6 +421,16 @@
"100": "1/1 units (EUR/NOK/DKK)",
"1": "1/100 units (cents/öre/øre)"
}
},
{
"key": "showcurr",
"name": "Show current",
"desc": "Hourly refresh to show current price (less battery friendly)",
"type": "select",
"options": {
"0": "No",
"1": "-Yes"
}
}
]
},

View File

@@ -154,7 +154,7 @@ async function checkTagFW() {
print(`File ${fwfile} found`, "green");
} else {
print(`File ${fwfile} not found. Downloading...`, "red");
await fetchAndPost("https://raw.githubusercontent.com/jjwbruijn/OpenEPaperLink/master/binaries/Tag/Tag_FW_Pack.bin", "Tag_FW_Pack.bin", fwfile);
await fetchAndPost("https://raw.githubusercontent.com/OpenEPaperLink/OpenEPaperLink/master/binaries/Tag/Tag_FW_Pack.bin", "Tag_FW_Pack.bin", fwfile);
}
} else {
print(`error checking file ${file.path}: ${response.status}`, "red");

View File

@@ -32,7 +32,7 @@
</div>
<!-- /tabs -->
<div><span id="runstate"></div>
<div><span id="apstatecolor">&#11044;</span> <span id="apstate">loading</span></div>
<div><span id="apstatecolor" style="font-size: 18px; vertical-align: bottom;" class="material-symbols-outlined">hourglass</span> <span id="apstate">loading</span></div>
<div><a href="/edit" target="littlefs" class="filebutton material-symbols-outlined">folder_open</a>
</div>
</div>
@@ -46,10 +46,10 @@
<div id="hometab" class="tabcontent">
<table>
<tr onclick="setFilterAndShow('')">
<td class="material-symbols-outlined" style="color:#239f26" id="dashboardStatusIcon">
check_circle
<td class="material-symbols-outlined" id="dashboardStatusIcon">
hourglass
</td>
<td id="dashboardStatus" style="color:#239f26" colspan="2">
<td id="dashboardStatus" colspan="2">
initialising...
</td>
</tr>
@@ -238,7 +238,7 @@
It sets the mac automatically, tries to recognize the type, and starts flashing. Currently, Solum M2 tags only.
<br><br>
<button class="button" id="doUSBflash">Command line</button><br><br>
Using <a href="https://github.com/jjwbruijn/OpenEPaperLink/tree/master/Tag_Flasher#oepl-flasherpy" target="_blank">OEPL-Flasher.py</a>, you have full control over the flashing of the tag.<br>
Using <a href="https://github.com/OpenEPaperLink/OpenEPaperLink/tree/master/Tag_Flasher#oepl-flasherpy" target="_blank">OEPL-Flasher.py</a>, you have full control over the flashing of the tag.<br>
Use the --ip argument to connect to the flasher.<br>
<br>
Usage:<br>
@@ -382,6 +382,13 @@ options:
<span style="align-self:center;">and</span>
<select id="apcnight2"></select>
</p>
<p title="Reboots every night at 3:56 for stability">
<label for="apcnightlyreboot">Nightly reboot</label>
<select id="apcnightlyreboot">
<option value="0">no</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>
@@ -464,6 +471,13 @@ options:
</optgroup>
</select>
</p>
<p title="Set to Broadcast if using a multi WiFi AP setup that does not support IGMP sniffing">
<label for="apcdiscovery">AP discovery method</label>
<select id="apcdiscovery">
<option value="0" selected>Multicast</option>
<option value="1">Broadcast</option>
</select>
</p>
<p>
<input type="button" value="Save" id="apcfgsave"><span id="apcfgmsg"></span>
</p>
@@ -486,8 +500,8 @@ options:
</p>
<p>
<br>
<a href="https://github.com/jjwbruijn/OpenEPaperLink" target="_new">Github OpenEPaperLink</a><br>
<a href="https://github.com/jjwbruijn/OpenEPaperLink/wiki" target="_new">OpenEPaperLink Wiki</a><br>
<a href="https://github.com/OpenEPaperLink/OpenEPaperLink" target="_new">Github OpenEPaperLink</a><br>
<a href="https://github.com/OpenEPaperLink/OpenEPaperLink/wiki" target="_new">OpenEPaperLink Wiki</a><br>
</p>
</div>

View File

@@ -9,7 +9,7 @@
<body>
<h3>demo Json template form</h3>
<p>You can use this as an example how to push json templates to a tag by an external server/script. Make sure your json is valid. Check the syntax on <a href="https://jsonlint.com/" target="_blank">https://jsonlint.com/</a>.<br>
Documentation: <a href="https://github.com/jjwbruijn/OpenEPaperLink/wiki/Json-template">https://github.com/jjwbruijn/OpenEPaperLink/wiki/Json-template</a></p>
Documentation: <a href="https://github.com/OpenEPaperLink/OpenEPaperLink/wiki/Json-template">https://github.com/OpenEPaperLink/OpenEPaperLink/wiki/Json-template</a></p>
<p>
<form method="POST" action="/jsonupload">

View File

@@ -14,16 +14,17 @@ const WAKEUP_REASON_WDT_RESET = 0xFE;
let tagTypes = {};
let apConfig = {};
let tagDB = {};
const previewWindows = [];
const apstate = [
{ state: "offline", color: "red" },
{ state: "online", color: "green" },
{ state: "flashing", color: "orange" },
{ state: "wait for reset", color: "blue" },
{ state: "requires power cycle", color: "purple" },
{ state: "failed", color: "red" },
{ state: "coming online", color: "yellow" },
{ state: "AP without radio", color: "green" }
{ state: "offline, please wait...", color: "orange", icon: "warning" },
{ state: "online", color: "green", icon: "check_circle" },
{ state: "flashing", color: "orange", icon: "flash_on" },
{ state: "wait for reset", color: "blue", icon: "hourglass" },
{ state: "AP requires power cycle", color: "purple", icon: "refresh" },
{ state: "failed", color: "red", icon: "error" },
{ state: "coming online...", color: "orange", icon: "hourglass" },
{ state: "AP without radio", color: "green", icon: "wifi_off" }
];
const runstate = [
{ state: "⏹︎ stopped" },
@@ -70,9 +71,13 @@ window.addEventListener("loadConfig", function () {
if (data.savespace) {
}
if (data.apstate) {
$("#apstatecolor").innerHTML = apstate[data.apstate].icon;
$("#apstatecolor").style.color = apstate[data.apstate].color;
$("#apstate").innerHTML = apstate[data.apstate].state;
$('#dashboardStatus').innerHTML = apstate[data.apstate].state;
$('#dashboardStatus').style.color = apstate[data.apstate].color;
$('#dashboardStatusIcon').innerHTML = apstate[data.apstate].icon;
$('#dashboardStatusIcon').style.color = apstate[data.apstate].color;
}
});
});
@@ -214,10 +219,14 @@ function connect() {
$("#sysinfo").innerHTML = str;
if (msg.sys.apstate) {
$("#runstate").innerHTML = runstate[msg.sys.runstate].state;
$("#apstatecolor").innerHTML = apstate[msg.sys.apstate].icon;
$("#apstatecolor").style.color = apstate[msg.sys.apstate].color;
$("#apstate").innerHTML = apstate[msg.sys.apstate].state;
$("#runstate").innerHTML = runstate[msg.sys.runstate].state;
$('#dashboardStatus').innerHTML = apstate[msg.sys.apstate].state;
$('#dashboardStatus').style.color = apstate[msg.sys.apstate].color;
$('#dashboardStatusIcon').innerHTML = apstate[msg.sys.apstate].icon;
$('#dashboardStatusIcon').style.color = apstate[msg.sys.apstate].color;
}
servertimediff = (Date.now() / 1000) - msg.sys.currtime;
}
@@ -288,12 +297,12 @@ function processTags(tagArray) {
if (!alias) {
alias = tagmac.replace(/^0{1,4}/, '');
if (alias.match(/^4467/)) {
let macdigit = Number.parseInt(alias.substr(4,2),16) & 0x1f;
let macdigit = Number.parseInt(alias.substr(4, 2), 16) & 0x1f;
let model = String.fromCharCode(macdigit + 65);
if (model == 'J' || model == 'M') {
macdigit = Number.parseInt(alias.substr(6,2),16) & 0x1f;
if (model == 'J' || model == 'M') {
macdigit = Number.parseInt(alias.substr(6, 2), 16) & 0x1f;
model += String.fromCharCode(macdigit + 65);
alias = model + alias.substr(8,8) + 'x'
alias = model + alias.substr(8, 8) + 'x'
}
}
}
@@ -424,6 +433,16 @@ function processTags(tagArray) {
setTimeout(function () { $('#tag' + tagmac).classList.remove("tagflash"); }, 1400);
})(tagmac);
if (element.pending) div.classList.add("tagpending");
previewWindows.forEach((previewWindow, index) => {
if (previewWindow && !previewWindow.closed) {
if (previewWindow.mac === tagmac) {
previewWindow.updateMessage(element);
}
} else {
previewWindows.splice(index, 1);
}
});
}
GroupSortFilter();
}
@@ -656,7 +675,7 @@ $('#cfgautoupdate').onclick = async function () {
formData.append("mac", mac);
formData.append("alias", $('#cfgalias').value);
var repo = apConfig.repo || 'jjwbruijn/OpenEPaperLink';
var repo = apConfig.repo || 'OpenEPaperLink/OpenEPaperLink';
var infourl = "https://raw.githubusercontent.com/" + repo + "/master/binaries/Tag/tagotaversions.json";
var info = "";
await fetch(infourl, { method: 'GET' }).then(await function (response) { return response.json(); }).then(await function (json) { info = json; });
@@ -667,10 +686,20 @@ $('#cfgautoupdate').onclick = async function () {
return false;
}
var version = info[0][tagtype]["version"];
var md5 = info[0][tagtype]["md5"];
if (name.substr(0, 6) == "chroma") {
var variation = (Number.parseInt(mac.substr(4, 2), 16) >> 5).toString();
if (variation != '0') {
var name = info[0][tagtype]["type_" + variation];
version = info[0][tagtype]['version_' + variation];
md5 = info[0][tagtype]['md5_' + variation];
}
}
var currentversion = $('#tag' + mac).dataset.ver | 0;
if (confirm(`Current version: ${currentversion} 0x${currentversion.toString(16)}\nPending version: ${parseInt(version, 16)} 0x${parseInt(version, 16).toString(16)}\n\nNOTE: Every OTA update comes with a risk of bricking the tag, if it is bricked, it only can be recoverd with a tag flasher. Please only update if you need the new features.\n\nPress Cancel if you want to get out of here, or press OK if you want to proceed with the update.`)) {
var md5 = info[0][tagtype]["md5"];
var fullFilename = name + "_" + version + ".bin";
var filepath = "/" + fullFilename;
var binurl = "https://raw.githubusercontent.com/" + repo + "/master/binaries/Tag/" + fullFilename;
@@ -749,7 +778,7 @@ document.addEventListener("loadTab", function (event) {
apConfig = data;
$('#apcfgalias').value = data.alias;
$('#apcfgchid').value = data.channel;
$('#apcfgsubgigchid').value = data.subghzchannel;
$('#apcfgsubgigchid').value = data.subghzchannel;
$('#apcfgble').value = data.ble;
$("#apcfgledbrightness").value = data.led;
$("#apcfgtftbrightness").value = data.tft;
@@ -757,11 +786,13 @@ document.addEventListener("loadTab", function (event) {
$("#apclatency").value = data.maxsleep;
$("#apcpreventsleep").value = data.stopsleep;
$("#apcpreview").value = data.preview;
$("#apcnightlyreboot").value = data.nightlyreboot;
$("#apclock").value = data.lock;
$("#apcwifipower").value = data.wifipower;
$("#apctimezone").value = data.timezone;
$("#apcnight1").value = data.sleeptime1;
$("#apcnight2").value = data.sleeptime2;
$("#apcdiscovery").value = data.discovery;
}
})
$('#apcfgmsg').innerHTML = '';
@@ -785,7 +816,7 @@ $('#apcfgsave').onclick = function () {
let formData = new FormData();
formData.append("alias", $('#apcfgalias').value);
formData.append("channel", $('#apcfgchid').value);
formData.append("subghzchannel", $('#apcfgsubgigchid').value);
formData.append("subghzchannel", $('#apcfgsubgigchid').value);
formData.append('ble', $('#apcfgble').value);
formData.append('led', $('#apcfgledbrightness').value);
formData.append('tft', $('#apcfgtftbrightness').value);
@@ -793,12 +824,13 @@ $('#apcfgsave').onclick = function () {
formData.append('maxsleep', $('#apclatency').value);
formData.append('stopsleep', $('#apcpreventsleep').value);
formData.append('preview', $('#apcpreview').value);
formData.append('nightlyreboot', $('#apcnightlyreboot').value);
formData.append('lock', $('#apclock').value);
formData.append('wifipower', $('#apcwifipower').value);
formData.append('timezone', $('#apctimezone').value);
formData.append('sleeptime1', $('#apcnight1').value);
formData.append('sleeptime2', $('#apcnight2').value);
formData.append('discovery', $('#apcdiscovery').value)
fetch("save_apcfg", {
method: "POST",
body: formData
@@ -900,10 +932,10 @@ $('#paintbutton').onclick = function () {
const hwtype = $('#tag' + mac).dataset.hwtype;
const [width, height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
if (paintLoaded) {
startPainter(mac, width, height);
startPainter(mac, width, height, tagTypes[hwtype]);
} else {
loadScript('painter.js', function () {
startPainter(mac, width, height);
startPainter(mac, width, height, tagTypes[hwtype]);
});
}
}
@@ -985,8 +1017,8 @@ function contentselected() {
case 'chanselect':
input = document.createElement("select");
let options;
if(element.type == 'chanselect') {
if($('#cfgmac').dataset.ch < 100) {
if (element.type == 'chanselect') {
if ($('#cfgmac').dataset.ch < 100) {
options = element.chans;
}
else {
@@ -1161,54 +1193,7 @@ function processQueue() {
.then(response => response.arrayBuffer())
.then(buffer => {
data = new Uint8ClampedArray(buffer);
if (data.length > 0 && tagTypes[hwtype].zlib > 0 && $('#tag' + id).dataset.ver >= tagTypes[hwtype].zlib) {
data = processZlib(data);
}
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
if (tagTypes[hwtype].rotatebuffer%2) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer>=2) canvas.style.transform='rotate(180deg)';
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
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;
}
}
}
ctx.putImageData(imageData, 0, 0);
drawCanvas(buffer, canvas, hwtype, id, true);
processQueue();
})
.catch(error => {
@@ -1217,6 +1202,71 @@ function processQueue() {
});
}
function drawCanvas(buffer, canvas, hwtype, tagmac, doRotate) {
data = new Uint8ClampedArray(buffer);
if (data.length > 0 && tagTypes[hwtype].zlib > 0 && $('#tag' + tagmac).dataset.ver >= tagTypes[hwtype].zlib) {
data = processZlib(data);
}
[canvas.width, canvas.height] = [tagTypes[hwtype].width, tagTypes[hwtype].height] || [0, 0];
if (tagTypes[hwtype].rotatebuffer % 2) [canvas.width, canvas.height] = [canvas.height, canvas.width];
if (tagTypes[hwtype].rotatebuffer >= 2) canvas.style.transform = 'rotate(180deg)';
if (doRotate == false && tagTypes[hwtype].rotatebuffer == 1) {
canvas.style.transform = 'rotate(90deg)';
canvas.style.transformOrigin = 'top left';
canvas.style.position = 'absolute';
canvas.style.left = canvas.height + 15;
canvas.style.top = 15;
}
if (doRotate == false && tagTypes[hwtype].rotatebuffer == 3) {
canvas.style.transform = 'rotate(270deg)';
canvas.style.transformOrigin = 'top left';
canvas.style.position = 'absolute';
canvas.style.top = (canvas.width + 15) + 'px';
canvas.style.left = 15;
}
const ctx = canvas.getContext('2d');
const imageData = ctx.createImageData(canvas.width, canvas.height);
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;
}
}
}
ctx.putImageData(imageData, 0, 0);
}
function processZlib(data) {
const subBuffer = data.subarray(4);
try {
@@ -1352,7 +1402,7 @@ $('#activefilter').addEventListener('click', (event) => {
const downloadTagtype = async (hwtype) => {
try {
console.log("download tagtype " + hwtype);
let repo = apConfig.repo || 'jjwbruijn/OpenEPaperLink';
let repo = apConfig.repo || 'OpenEPaperLink/OpenEPaperLink';
let url = "https://raw.githubusercontent.com/" + repo + "/master/resources/tagtypes/" + hwtype + ".json";
console.log(url);
@@ -1451,7 +1501,7 @@ async function getTagtype(hwtype) {
zlib: parseInt(jsonData.zlib_compression || "0", 16),
shortlut: parseInt(jsonData.shortlut),
busy: false,
usetemplate:parseInt(jsonData.usetemplate || "0",10)
usetemplate: parseInt(jsonData.usetemplate || "0", 10)
};
tagTypes[hwtype] = data;
localStorage.setItem("tagTypes", JSON.stringify(tagTypes));
@@ -1622,6 +1672,16 @@ $('#taglist').addEventListener('contextmenu', (e) => {
);
}
contextMenu.innerHTML = '';
const li = document.createElement('li');
li.textContent = "Tag preview";
li.addEventListener('click', (e) => {
e.preventDefault();
openPreview(mac, tagTypes[hwtype].width, tagTypes[hwtype].height);
contextMenu.style.display = 'none';
});
contextMenu.appendChild(li);
contextMenuOptions.forEach(option => {
const li = document.createElement('li');
li.textContent = option.label;
@@ -1632,6 +1692,7 @@ $('#taglist').addEventListener('contextmenu', (e) => {
});
contextMenu.appendChild(li);
});
const contextMenuPosition = {
left: e.clientX + window.scrollX,
top: e.clientY + window.scrollY
@@ -1794,3 +1855,73 @@ function backupTagDB() {
localStorage.setItem("tagDB", JSON.stringify(tagDB));
}
function openPreview(mac, w, h) {
const previewWindow = window.open("", `PreviewWindow_${mac}`, `width=${w + 30},height=${h + 30},menubar=no,toolbar=no,location=no,status=no,resizable=no,scrollbars=no`);
if (previewWindow) {
previewWindow.mac = mac;
previewWindows.push(previewWindow);
const element = tagDB[mac];
previewWindow.hash = "";
previewWindow.pending = 0;
previewWindow.focus();
console.log(element);
console.log(tagTypes[element.hwType]);
previewWindow.document.head.innerHTML = `<title>${tagTypes[element.hwType].name + ' ' + mac}</title>`;
previewWindow.document.body.style.backgroundColor = "#dddddd";
previewWindow.document.body.style.margin = "15px";
previewWindow.document.body.style.overflow = "hidden";
previewWindow.document.body.innerHTML = `<canvas id="preview" style="border:1px solid #888888;"></canvas>`;
showPreview(previewWindow, element);
previewWindow.updateMessage = function (data) {
//const messageDisplay = previewWindow.document.getElementById('messageDisplay');
showPreview(previewWindow, data);
};
} else {
console.error("Failed to open preview window.");
}
}
function showPreview(previewWindow, element) {
let imageSrc = "";
const canvas = previewWindow.document.getElementById('preview');
if (element.pending != previewWindow.pending && element.pending != 0) {
console.log('refresh ' + element.mac);
previewWindow.pending = element.pending;
previewWindow.hash = "";
if (element.isexternal && element.contentMode == 12) {
imageSrc = 'http://' + tagDB[element.mac].apip + '/getdata?mac=' + element.mac + '&md5=0000000000000000';
} else {
imageSrc = '/getdata?mac=' + element.mac + '&md5=0000000000000000';
}
} else if (element.hash != previewWindow.hash) {
let cachetag = element.hash;
previewWindow.hash = cachetag;
previewWindow.pending = 0;
if (element.isexternal && element.contentMode == 12) {
imageSrc = 'http://' + tagDB[element.mac].apip + '/current/' + element.mac + '.raw?' + cachetag;
} else {
imageSrc = 'current/' + element.mac + '.raw?' + cachetag;
}
}
if (imageSrc) {
fetch(imageSrc)
.then(response => response.arrayBuffer())
.then(buffer => {
drawCanvas(buffer, canvas, element.hwType, element.mac, false);
})
.catch(error => {
console.error('fetch preview image error:', error);
});
}
}

View File

@@ -1,4 +1,4 @@
var repo = apConfig.repo || 'jjwbruijn/OpenEPaperLink';
var repo = apConfig.repo || 'OpenEPaperLink/OpenEPaperLink';
var repoUrl = 'https://api.github.com/repos/' + repo + '/releases';
const $ = document.querySelector.bind(document);
@@ -76,7 +76,8 @@ export async function initUpdate() {
const assets = release.assets;
const filesJsonAsset = assets.find(asset => asset.name === 'filesystem.json');
const binariesJsonAsset = assets.find(asset => asset.name === 'binaries.json');
if (filesJsonAsset && binariesJsonAsset) {
const containsEnv = assets.find(asset => asset.name === env + '.bin');
if (filesJsonAsset && binariesJsonAsset && containsEnv) {
return {
html_url: release.html_url,
tag_name: release.tag_name,
@@ -594,13 +595,12 @@ async function fetchAndCheckTagtypes(cleanup) {
for (const file of fileList) {
const filename = file.name;
print(filename, "green");
let check = true;
let check = filename.endsWith('.json');
let hwtype = parseInt(filename, 16);
if (cleanup) {
if (check && cleanup) {
let isInUse = Array.from(gridItems).some(element => element.dataset.hwtype == hwtype);
if (!isInUse) {
isInUse = Array.from(gridItems).some(element => element.dataset.usetemplate == hwtype);
}
if (!isInUse) {

View File

@@ -1,4 +1,4 @@
function startPainter(mac, width, height) {
function startPainter(mac, width, height, tagtype) {
let isDrawing = false;
let lastX = 0;
let lastY = 0;
@@ -46,29 +46,36 @@ function startPainter(mac, width, height) {
txtButton.style.fontStyle = 'italic';
txtButton.addEventListener('click', addText);
const blackButton = document.createElement('button');
blackButton.innerHTML = '&#65103;&#128396';
blackButton.style.color = 'black';
blackButton.addEventListener('click', () => {
color = 'black';
linewidth = 3;
cursor = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><circle cx=\'2\' cy=\'2\' r=\'2\' opacity=\'0.5\'/></svg>") 2 2, auto';
blackButton.classList.add('active');
redButton.classList.remove('active');
whiteButton.classList.remove('active');
});
blackButton.classList.add('active');
console.log(tagtype.colortable);
const rgbToCSSColor = (rgbArray) => `rgb(${rgbArray[0]}, ${rgbArray[1]}, ${rgbArray[2]})`;
const redButton = document.createElement('button');
redButton.innerHTML = '&#65103;&#128396';
redButton.style.color = 'red';
redButton.addEventListener('click', () => {
color = 'red';
linewidth = 3;
cursor = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><circle cx=\'2\' cy=\'2\' r=\'2\' opacity=\'0.5\'/></svg>") 2 2, auto';
blackButton.classList.remove('active');
redButton.classList.add('active');
whiteButton.classList.remove('active');
let activeButton = null;
tagtype.colortable.forEach((thiscolor, index) => {
if (thiscolor[0] === 255 && thiscolor[1] === 255 && thiscolor[2] === 255) return;
const colorButton = document.createElement('button');
colorButton.innerHTML = '&#65103;&#128396';
colorButton.style.color = rgbToCSSColor(thiscolor);
colorButton.classList.add('colorbutton');
colorButton.addEventListener('click', () => {
color = rgbToCSSColor(thiscolor);
linewidth = 3;
cursor = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><circle cx=\'2\' cy=\'2\' r=\'2\' opacity=\'0.5\'/></svg>") 2 2, auto';
if (activeButton) activeButton.classList.remove('active');
colorButton.classList.add('active');
activeButton = colorButton;
});
if (!activeButton) {
colorButton.classList.add('active');
activeButton = colorButton;
color = rgbToCSSColor(thiscolor);
}
$("#buttonbar").appendChild(colorButton);
});
const whiteButton = document.createElement('button');
@@ -78,9 +85,9 @@ function startPainter(mac, width, height) {
color = 'white';
linewidth = 20;
cursor = 'url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><circle cx=\'10\' cy=\'10\' r=\'10\' opacity=\'0.5\'/></svg>") 10 10, auto';
blackButton.classList.remove('active');
redButton.classList.remove('active');
if (activeButton) activeButton.classList.remove('active');
whiteButton.classList.add('active');
activeButton = whiteButton;
});
const clearButton = document.createElement('button');
@@ -110,8 +117,6 @@ function startPainter(mac, width, height) {
$('#configbox').close();
});
$("#buttonbar").appendChild(blackButton);
$("#buttonbar").appendChild(redButton);
$("#buttonbar").appendChild(whiteButton);
$("#buttonbar").appendChild(txtButton);
$("#buttonbar").appendChild(clearButton);
@@ -258,13 +263,12 @@ function startPainter(mac, width, height) {
input.focus();
isAddingText = true;
//cursor = 'move';
blackButton.innerHTML = 'aA'
redButton.innerHTML = 'aA'
const colorButtons = document.querySelectorAll('.colorbutton');
colorButtons.forEach(button => {
button.innerHTML = 'aA';
});
if (color=='white') {
whiteButton.classList.remove('active');
blackButton.classList.add('active');
color='black';
document.querySelector('.colorbutton').click();
}
}
@@ -283,8 +287,10 @@ function startPainter(mac, width, height) {
showCursor = false;
if (apply) drawText(input.value, textX, textY);
txtButton.classList.remove('active');
blackButton.innerHTML = '&#65103;&#128396'
redButton.innerHTML = '&#65103;&#128396'
const colorButtons = document.querySelectorAll('.colorbutton');
colorButtons.forEach(button => {
button.innerHTML = '&#65103;&#128396';
});
}
function drawText(text, x, y) {

View File

@@ -1,2 +0,0 @@
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
)

View File

@@ -1,64 +0,0 @@
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
(symbol "ESL-connector" (in_bom yes) (on_board yes)
(property "Reference" "U" (id 0) (at 0 11.43 0)
(effects (font (size 1.27 1.27)))
)
(property "Value" "ESL-connector" (id 1) (at 0 -11.43 0)
(effects (font (size 1.27 1.27)))
)
(property "Footprint" "" (id 2) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(property "Datasheet" "" (id 3) (at 0 0 0)
(effects (font (size 1.27 1.27)) hide)
)
(symbol "ESL-connector_0_1"
(rectangle (start -6.35 10.16) (end 6.35 -10.16)
(stroke (width 0.1524) (type default) (color 0 0 0 0))
(fill (type none))
)
)
(symbol "ESL-connector_1_1"
(pin power_in line (at -8.89 7.62 0) (length 2.54)
(name "VCC" (effects (font (size 1.27 1.27))))
(number "1" (effects (font (size 1.27 1.27))))
)
(pin bidirectional line (at 8.89 -7.62 180) (length 2.54)
(name "P1.0" (effects (font (size 1.27 1.27))))
(number "10" (effects (font (size 1.27 1.27))))
)
(pin input line (at -8.89 3.81 0) (length 2.54)
(name "MoSi" (effects (font (size 1.27 1.27))))
(number "2" (effects (font (size 1.27 1.27))))
)
(pin input line (at -8.89 0 0) (length 2.54)
(name "SS" (effects (font (size 1.27 1.27))))
(number "3" (effects (font (size 1.27 1.27))))
)
(pin output line (at -8.89 -3.81 0) (length 2.54)
(name "TXD" (effects (font (size 1.27 1.27))))
(number "4" (effects (font (size 1.27 1.27))))
)
(pin input line (at -8.89 -7.62 0) (length 2.54)
(name "CLK" (effects (font (size 1.27 1.27))))
(number "5" (effects (font (size 1.27 1.27))))
)
(pin output line (at 8.89 7.62 180) (length 2.54)
(name "MiSo" (effects (font (size 1.27 1.27))))
(number "6" (effects (font (size 1.27 1.27))))
)
(pin power_in line (at 8.89 3.81 180) (length 2.54)
(name "GND" (effects (font (size 1.27 1.27))))
(number "7" (effects (font (size 1.27 1.27))))
)
(pin input line (at 8.89 0 180) (length 2.54)
(name "RST" (effects (font (size 1.27 1.27))))
(number "8" (effects (font (size 1.27 1.27))))
)
(pin input line (at 8.89 -3.81 180) (length 2.54)
(name "RXD" (effects (font (size 1.27 1.27))))
(number "9" (effects (font (size 1.27 1.27))))
)
)
)
)

View File

@@ -1,26 +0,0 @@
# Alternative PCB for 2.9" flashing #
This is an alternative PCB for flashing 2.9" ESLs
<img width="600" alt="pcb" src="pcb.png">
<img width="600" alt="bot" src="jig_bot.jpg">
<img width="600" alt="top" src="jig_top.jpg">
### Parts (per board) ###
* 10x 1mm pogo pin
* 3x Switches
* 3x 3mm LEDs
* 3x 0805 SMD resistor (47 ohm or so, depending on LED color, personal taste, whatever)
* ESP32-DevKit-Lipo form Olimex
* please check the PCB for the rest
### Errata ###
The ESP32 board needs to be solder upside down
## Getting PCB's ##
You can order the boards from your favorite boardhouse, using the zip file in this repository.
## Disclaimer ##
There is no guarantee or warranty whatsoever, nor is there any promise or insinuation that this board fill fullfill any particular purpose. This board may very well not work for you, set your hair and/or, but not limited to, pants on fire, incite violance or persuade other countries to invade your country. You're on your own, chief!

View File

@@ -1,40 +0,0 @@
(footprint "SOLUM_ZBS_DEBUG" (version 20211014) (generator pcbnew)
(layer "F.Cu")
(tedit 0)
(descr "<h3>Solum Debug header pinout for 1mm pogo pins</h3>")
(fp_text reference "J19" (at 0 0) (layer "F.SilkS") hide
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp 82ec8fc7-4947-43e8-a28a-f87f8d8a424a)
)
(fp_text value "" (at 0 0) (layer "F.Fab") hide
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp 9be777ad-9f8e-434c-9925-b4f3cbcf667d)
)
(fp_line (start -3.745 -2.506) (end -3.745 2.494) (layer "F.SilkS") (width 0.127) (tstamp 230f73ed-7388-4311-bd67-896af89b3fcb))
(fp_line (start -3.345 0.044) (end -2.745 -0.356) (layer "F.SilkS") (width 0.127) (tstamp 25b0ffe5-9f43-42b5-ad90-4a164f170e55))
(fp_line (start 3.755 -2.506) (end 3.755 2.494) (layer "F.SilkS") (width 0.127) (tstamp 53faed3a-63cc-4487-8883-b5c4197265c2))
(fp_line (start -3.345 0.044) (end -2.745 0.444) (layer "F.SilkS") (width 0.127) (tstamp 5a223cb8-3c61-4d1f-a412-d9c7d77f66b9))
(fp_line (start -3.745 -2.506) (end 3.755 -2.506) (layer "F.SilkS") (width 0.127) (tstamp 85c102fc-8b65-4d83-a6fe-e043723d82a4))
(fp_line (start -3.745 2.494) (end 3.755 2.494) (layer "F.SilkS") (width 0.127) (tstamp a1645c22-11d6-485a-92a9-3621b643513c))
(fp_line (start -3.345 0.044) (end -1.495 0.044) (layer "F.SilkS") (width 0.127) (tstamp dab4d2de-3395-4723-9799-d0bb3a191c1b))
(pad "1" thru_hole circle (at -2.995 1.744) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 71343d1a-b887-4c75-8f6e-3783c4cee9df))
(pad "2" thru_hole circle (at -0.995 1.744) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp a5bba08a-0aac-4518-8a18-8e86b2e9784c))
(pad "3" thru_hole circle (at 1.005 1.744) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 64903969-f443-47c1-a03d-9412f3950a7f))
(pad "4" thru_hole circle (at 3.005 1.794) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 53ec6283-c57d-491a-9c98-1df814704014))
(pad "5" thru_hole circle (at 0.005 -0.006) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 6b11af81-f064-49d0-8c15-50a5af3bdce8))
(pad "6" thru_hole circle (at 2.005 -0.006) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 048099e4-1d18-4e68-a98e-c376a592cc1d))
(pad "7" thru_hole circle (at -2.995 -1.756) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 323c1c33-7532-46f9-b99c-f77f2344710a))
(pad "8" thru_hole circle (at -0.995 -1.756) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp e067c309-8b30-4efa-b5e6-088c3f57692f))
(pad "9" thru_hole circle (at 1.005 -1.756) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp f4cd57db-f82c-479a-9526-cfebc536273b))
(pad "10" thru_hole circle (at 3.005 -1.756) (size 1.27 1.27) (drill 1) (layers *.Cu *.Mask)
(solder_mask_margin 0.0508) (tstamp 2700ab94-06e0-45e2-9edc-3815ba09c9d6))
)

View File

@@ -1,3 +0,0 @@
(fp_lib_table
(lib (name "esl")(type "KiCad")(uri "${KIPRJMOD}/esl.pretty")(options "")(descr ""))
)

View File

@@ -1,252 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:56+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L2,Bot*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:56*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 #@! TA.AperFunction,ComponentPad*
%ADD10C,2.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD11R,1.700000X1.700000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD12O,1.700000X1.700000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD13R,1.800000X1.800000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD14C,1.800000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD15C,1.270000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ViaPad*
%ADD16C,0.600000*%
G04 #@! TD*
G04 #@! TA.AperFunction,Conductor*
%ADD17C,1.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,Conductor*
%ADD18C,0.500000*%
G04 #@! TD*
G04 APERTURE END LIST*
D10*
X9250000Y-4765564D03*
X2750000Y-4765564D03*
X2750000Y-9265564D03*
X9250000Y-9265564D03*
D11*
X7620000Y-35560000D03*
D12*
X7620000Y-38100000D03*
X7620000Y-40640000D03*
X7620000Y-43180000D03*
X7620000Y-45720000D03*
X7620000Y-48260000D03*
X7620000Y-50800000D03*
X7620000Y-53340000D03*
X7620000Y-55880000D03*
X7620000Y-58420000D03*
X7620000Y-60960000D03*
X7620000Y-63500000D03*
X7620000Y-66040000D03*
X7620000Y-68580000D03*
X7620000Y-71120000D03*
X7620000Y-73660000D03*
X7620000Y-76200000D03*
X7620000Y-78740000D03*
X7620000Y-81280000D03*
D13*
X23290000Y-5080000D03*
D14*
X25830000Y-5080000D03*
D11*
X32975000Y-35570000D03*
D12*
X32975000Y-38110000D03*
X32975000Y-40650000D03*
X32975000Y-43190000D03*
X32975000Y-45730000D03*
X32975000Y-48270000D03*
X32975000Y-50810000D03*
X32975000Y-53350000D03*
X32975000Y-55890000D03*
X32975000Y-58430000D03*
X32975000Y-60970000D03*
X32975000Y-63510000D03*
X32975000Y-66050000D03*
X32975000Y-68590000D03*
X32975000Y-71130000D03*
X32975000Y-73670000D03*
X32975000Y-76210000D03*
X32975000Y-78750000D03*
X32975000Y-81290000D03*
D15*
X28256000Y-17005000D03*
X28256000Y-19005000D03*
X28256000Y-21005000D03*
X28206000Y-23005000D03*
X30006000Y-20005000D03*
X30006000Y-22005000D03*
X31756000Y-17005000D03*
X31756000Y-19005000D03*
X31756000Y-21005000D03*
X31756000Y-23005000D03*
D13*
X28830000Y-5080000D03*
D14*
X31370000Y-5080000D03*
D10*
X19250000Y-4765564D03*
X12750000Y-4765564D03*
X19250000Y-9265564D03*
X12750000Y-9265564D03*
D13*
X34370000Y-5080000D03*
D14*
X36910000Y-5080000D03*
D10*
X14750000Y-20820000D03*
X21250000Y-20820000D03*
X14750000Y-25320000D03*
X21250000Y-25320000D03*
D16*
X23000000Y-35500000D03*
X24000000Y-39700000D03*
X11000000Y-29750000D03*
X11500000Y-15000000D03*
X14440000Y-79310000D03*
X7620000Y-21620000D03*
X20500000Y-17000000D03*
X20500000Y-15250000D03*
X21000000Y-13750000D03*
X26750000Y-38250000D03*
D17*
X23000000Y-37093502D02*
X23000000Y-35500000D01*
X24828249Y-38921751D02*
X24050000Y-39700000D01*
X25606498Y-39700000D02*
X24828249Y-38921751D01*
X24828249Y-38921751D02*
X23000000Y-37093502D01*
X32975000Y-35570000D02*
X28845000Y-39700000D01*
X24050000Y-39700000D02*
X24000000Y-39700000D01*
D18*
X11000000Y-15500000D02*
X11500000Y-15000000D01*
D17*
X28845000Y-39700000D02*
X25606498Y-39700000D01*
D18*
X11000000Y-29750000D02*
X11000000Y-15500000D01*
X32975000Y-40650000D02*
X23150000Y-40650000D01*
X19250000Y-36750000D02*
X19250000Y-9265564D01*
X23150000Y-40650000D02*
X19250000Y-36750000D01*
X21940000Y-43190000D02*
X16750000Y-38000000D01*
X32975000Y-43190000D02*
X21940000Y-43190000D01*
X16750000Y-38000000D02*
X16750000Y-16765564D01*
X16750000Y-16765564D02*
X9250000Y-9265564D01*
X14750000Y-40250000D02*
X14750000Y-25320000D01*
X20230000Y-45730000D02*
X14750000Y-40250000D01*
X32975000Y-45730000D02*
X20230000Y-45730000D01*
D17*
X9200000Y-50800000D02*
X10750000Y-49250000D01*
X10750000Y-49250000D02*
X10750000Y-37250000D01*
D18*
X25410000Y-68590000D02*
X25160000Y-68590000D01*
X6820000Y-20820000D02*
X7620000Y-21620000D01*
D17*
X33505000Y-17005000D02*
X31756000Y-17005000D01*
X9060000Y-35560000D02*
X7620000Y-35560000D01*
X7620000Y-50800000D02*
X9200000Y-50800000D01*
D18*
X4200000Y-6215564D02*
X2750000Y-4765564D01*
D17*
X34525000Y-18025000D02*
X33505000Y-17005000D01*
X10750000Y-37250000D02*
X9060000Y-35560000D01*
X32975000Y-68590000D02*
X25410000Y-68590000D01*
D18*
X25160000Y-68590000D02*
X14440000Y-79310000D01*
X6820000Y-20820000D02*
X4200000Y-18200000D01*
D17*
X34525000Y-67040000D02*
X34525000Y-18025000D01*
X7620000Y-50800000D02*
X25410000Y-68590000D01*
D18*
X7620000Y-21620000D02*
X7620000Y-35560000D01*
D17*
X32975000Y-68590000D02*
X34525000Y-67040000D01*
D18*
X4200000Y-18200000D02*
X4200000Y-6215564D01*
X29239950Y-7750000D02*
X20500000Y-16489950D01*
X31700000Y-7750000D02*
X29239950Y-7750000D01*
X34370000Y-5080000D02*
X31700000Y-7750000D01*
X20500000Y-16489950D02*
X20500000Y-16750000D01*
X20500000Y-16750000D02*
X20500000Y-17000000D01*
X28830000Y-7170000D02*
X20750000Y-15250000D01*
X20750000Y-15250000D02*
X20500000Y-15250000D01*
X28830000Y-5080000D02*
X28830000Y-7170000D01*
X23290000Y-5080000D02*
X23290000Y-11460000D01*
X23290000Y-11460000D02*
X21000000Y-13750000D01*
D17*
X25250000Y-18250000D02*
X26495000Y-17005000D01*
X26495000Y-17005000D02*
X28256000Y-17005000D01*
X26750000Y-26250000D02*
X25250000Y-24750000D01*
X26750000Y-38250000D02*
X26750000Y-26250000D01*
X25250000Y-24750000D02*
X25250000Y-18250000D01*
M02*

View File

@@ -1,101 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Soldermask,Bot*
G04 #@! TF.FilePolarity,Negative*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,2.000000*%
%ADD11R,1.700000X1.700000*%
%ADD12O,1.700000X1.700000*%
%ADD13R,1.800000X1.800000*%
%ADD14C,1.800000*%
%ADD15C,1.371600*%
G04 APERTURE END LIST*
D10*
X9250000Y-4765564D03*
X2750000Y-4765564D03*
X2750000Y-9265564D03*
X9250000Y-9265564D03*
D11*
X7620000Y-35560000D03*
D12*
X7620000Y-38100000D03*
X7620000Y-40640000D03*
X7620000Y-43180000D03*
X7620000Y-45720000D03*
X7620000Y-48260000D03*
X7620000Y-50800000D03*
X7620000Y-53340000D03*
X7620000Y-55880000D03*
X7620000Y-58420000D03*
X7620000Y-60960000D03*
X7620000Y-63500000D03*
X7620000Y-66040000D03*
X7620000Y-68580000D03*
X7620000Y-71120000D03*
X7620000Y-73660000D03*
X7620000Y-76200000D03*
X7620000Y-78740000D03*
X7620000Y-81280000D03*
D13*
X23290000Y-5080000D03*
D14*
X25830000Y-5080000D03*
D11*
X32975000Y-35570000D03*
D12*
X32975000Y-38110000D03*
X32975000Y-40650000D03*
X32975000Y-43190000D03*
X32975000Y-45730000D03*
X32975000Y-48270000D03*
X32975000Y-50810000D03*
X32975000Y-53350000D03*
X32975000Y-55890000D03*
X32975000Y-58430000D03*
X32975000Y-60970000D03*
X32975000Y-63510000D03*
X32975000Y-66050000D03*
X32975000Y-68590000D03*
X32975000Y-71130000D03*
X32975000Y-73670000D03*
X32975000Y-76210000D03*
X32975000Y-78750000D03*
X32975000Y-81290000D03*
D15*
X28256000Y-17005000D03*
X28256000Y-19005000D03*
X28256000Y-21005000D03*
X28206000Y-23005000D03*
X30006000Y-20005000D03*
X30006000Y-22005000D03*
X31756000Y-17005000D03*
X31756000Y-19005000D03*
X31756000Y-21005000D03*
X31756000Y-23005000D03*
D13*
X28830000Y-5080000D03*
D14*
X31370000Y-5080000D03*
D10*
X19250000Y-4765564D03*
X12750000Y-4765564D03*
X19250000Y-9265564D03*
X12750000Y-9265564D03*
D13*
X34370000Y-5080000D03*
D14*
X36910000Y-5080000D03*
D10*
X14750000Y-20820000D03*
X21250000Y-20820000D03*
X14750000Y-25320000D03*
X21250000Y-25320000D03*
M02*

View File

@@ -1,15 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Paste,Bot*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 APERTURE END LIST*
M02*

View File

@@ -1,153 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Legend,Bot*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,0.150000*%
%ADD11C,0.120000*%
%ADD12C,2.000000*%
%ADD13R,1.700000X1.700000*%
%ADD14O,1.700000X1.700000*%
%ADD15R,1.800000X1.800000*%
%ADD16C,1.800000*%
%ADD17C,1.371600*%
G04 APERTURE END LIST*
D10*
X19333333Y-19224761D02*
X19190476Y-19272380D01*
X18952380Y-19272380D01*
X18857142Y-19224761D01*
X18809523Y-19177142D01*
X18761904Y-19081904D01*
X18761904Y-18986666D01*
X18809523Y-18891428D01*
X18857142Y-18843809D01*
X18952380Y-18796190D01*
X19142857Y-18748571D01*
X19238095Y-18700952D01*
X19285714Y-18653333D01*
X19333333Y-18558095D01*
X19333333Y-18462857D01*
X19285714Y-18367619D01*
X19238095Y-18320000D01*
X19142857Y-18272380D01*
X18904761Y-18272380D01*
X18761904Y-18320000D01*
X18428571Y-18272380D02*
X18190476Y-19272380D01*
X18000000Y-18558095D01*
X17809523Y-19272380D01*
X17571428Y-18272380D01*
X17285714Y-18272380D02*
X16666666Y-18272380D01*
X17000000Y-18653333D01*
X16857142Y-18653333D01*
X16761904Y-18700952D01*
X16714285Y-18748571D01*
X16666666Y-18843809D01*
X16666666Y-19081904D01*
X16714285Y-19177142D01*
X16761904Y-19224761D01*
X16857142Y-19272380D01*
X17142857Y-19272380D01*
X17238095Y-19224761D01*
X17285714Y-19177142D01*
D11*
X14500000Y-23820000D02*
X14500000Y-22320000D01*
X20250000Y-26320000D02*
X15750000Y-26320000D01*
X21500000Y-22320000D02*
X21500000Y-23820000D01*
X15750000Y-19820000D02*
X20250000Y-19820000D01*
%LPC*%
D12*
X9250000Y-4765564D03*
X2750000Y-4765564D03*
X2750000Y-9265564D03*
X9250000Y-9265564D03*
D13*
X7620000Y-35560000D03*
D14*
X7620000Y-38100000D03*
X7620000Y-40640000D03*
X7620000Y-43180000D03*
X7620000Y-45720000D03*
X7620000Y-48260000D03*
X7620000Y-50800000D03*
X7620000Y-53340000D03*
X7620000Y-55880000D03*
X7620000Y-58420000D03*
X7620000Y-60960000D03*
X7620000Y-63500000D03*
X7620000Y-66040000D03*
X7620000Y-68580000D03*
X7620000Y-71120000D03*
X7620000Y-73660000D03*
X7620000Y-76200000D03*
X7620000Y-78740000D03*
X7620000Y-81280000D03*
D15*
X23290000Y-5080000D03*
D16*
X25830000Y-5080000D03*
D13*
X32975000Y-35570000D03*
D14*
X32975000Y-38110000D03*
X32975000Y-40650000D03*
X32975000Y-43190000D03*
X32975000Y-45730000D03*
X32975000Y-48270000D03*
X32975000Y-50810000D03*
X32975000Y-53350000D03*
X32975000Y-55890000D03*
X32975000Y-58430000D03*
X32975000Y-60970000D03*
X32975000Y-63510000D03*
X32975000Y-66050000D03*
X32975000Y-68590000D03*
X32975000Y-71130000D03*
X32975000Y-73670000D03*
X32975000Y-76210000D03*
X32975000Y-78750000D03*
X32975000Y-81290000D03*
D17*
X28256000Y-17005000D03*
X28256000Y-19005000D03*
X28256000Y-21005000D03*
X28206000Y-23005000D03*
X30006000Y-20005000D03*
X30006000Y-22005000D03*
X31756000Y-17005000D03*
X31756000Y-19005000D03*
X31756000Y-21005000D03*
X31756000Y-23005000D03*
D15*
X28830000Y-5080000D03*
D16*
X31370000Y-5080000D03*
D12*
X19250000Y-4765564D03*
X12750000Y-4765564D03*
X19250000Y-9265564D03*
X12750000Y-9265564D03*
D15*
X34370000Y-5080000D03*
D16*
X36910000Y-5080000D03*
D12*
X14750000Y-20820000D03*
X21250000Y-20820000D03*
X14750000Y-25320000D03*
X21250000Y-25320000D03*
M02*

View File

@@ -1,26 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Profile,NP*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 #@! TA.AperFunction,Profile*
%ADD10C,0.100000*%
G04 #@! TD*
G04 APERTURE END LIST*
D10*
X0Y-85000000D02*
X0Y0D01*
X40000000Y-85000000D02*
X0Y-85000000D01*
X40000000Y0D02*
X40000000Y-85000000D01*
X0Y0D02*
X40000000Y0D01*
M02*

View File

@@ -1,528 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:56+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Copper,L1,Top*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:56*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 Aperture macros list*
%AMRoundRect*
0 Rectangle with rounded corners*
0 $1 Rounding radius*
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
0 Add a 4 corners polygon primitive as box body*
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
0 Add four circle primitives for the rounded corners*
1,1,$1+$1,$2,$3*
1,1,$1+$1,$4,$5*
1,1,$1+$1,$6,$7*
1,1,$1+$1,$8,$9*
0 Add four rect primitives between the rounded corners*
20,1,$1+$1,$2,$3,$4,$5,0*
20,1,$1+$1,$4,$5,$6,$7,0*
20,1,$1+$1,$6,$7,$8,$9,0*
20,1,$1+$1,$8,$9,$2,$3,0*%
%AMFreePoly0*
4,1,22,0.500000,-0.750000,0.000000,-0.750000,0.000000,-0.745033,-0.079941,-0.743568,-0.215256,-0.701293,-0.333266,-0.622738,-0.424486,-0.514219,-0.481581,-0.384460,-0.499164,-0.250000,-0.500000,-0.250000,-0.500000,0.250000,-0.499164,0.250000,-0.499963,0.256109,-0.478152,0.396186,-0.417904,0.524511,-0.324060,0.630769,-0.204165,0.706417,-0.067858,0.745374,0.000000,0.744959,0.000000,0.750000,
0.500000,0.750000,0.500000,-0.750000,0.500000,-0.750000,$1*%
%AMFreePoly1*
4,1,20,0.000000,0.744959,0.073905,0.744508,0.209726,0.703889,0.328688,0.626782,0.421226,0.519385,0.479903,0.390333,0.500000,0.250000,0.500000,-0.250000,0.499851,-0.262216,0.476331,-0.402017,0.414519,-0.529596,0.319384,-0.634700,0.198574,-0.708877,0.061801,-0.746166,0.000000,-0.745033,0.000000,-0.750000,-0.500000,-0.750000,-0.500000,0.750000,0.000000,0.750000,0.000000,0.744959,
0.000000,0.744959,$1*%
G04 Aperture macros list end*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD10FreePoly0,180.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD11FreePoly1,180.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD12RoundRect,0.250000X0.350000X0.450000X-0.350000X0.450000X-0.350000X-0.450000X0.350000X-0.450000X0*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD13RoundRect,0.250000X-0.450000X0.350000X-0.450000X-0.350000X0.450000X-0.350000X0.450000X0.350000X0*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD14C,2.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD15R,1.700000X1.700000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD16O,1.700000X1.700000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD17R,0.800000X1.900000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD18R,1.800000X1.800000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD19C,1.800000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD20RoundRect,0.250000X-0.350000X-0.450000X0.350000X-0.450000X0.350000X0.450000X-0.350000X0.450000X0*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD21R,1.900000X0.800000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD22FreePoly0,90.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD23FreePoly1,90.000000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ComponentPad*
%ADD24C,1.270000*%
G04 #@! TD*
G04 #@! TA.AperFunction,SMDPad,CuDef*
%ADD25C,2.500000*%
G04 #@! TD*
G04 #@! TA.AperFunction,ViaPad*
%ADD26C,0.600000*%
G04 #@! TD*
G04 #@! TA.AperFunction,Conductor*
%ADD27C,0.500000*%
G04 #@! TD*
G04 #@! TA.AperFunction,Conductor*
%ADD28C,1.000000*%
G04 #@! TD*
G04 APERTURE END LIST*
G36*
X25250000Y-81350000D02*
G01*
X24750000Y-81350000D01*
X24750000Y-80950000D01*
X25250000Y-80950000D01*
X25250000Y-81350000D01*
G37*
G36*
X25250000Y-80550000D02*
G01*
X24750000Y-80550000D01*
X24750000Y-80150000D01*
X25250000Y-80150000D01*
X25250000Y-80550000D01*
G37*
D10*
X25650000Y-80750000D03*
D11*
X24350000Y-80750000D03*
D12*
X18250000Y-81120000D03*
X16250000Y-81120000D03*
D13*
X6000000Y-13000000D03*
X6000000Y-15000000D03*
D14*
X9250000Y-4765564D03*
X2750000Y-4765564D03*
X2750000Y-9265564D03*
X9250000Y-9265564D03*
D15*
X7620000Y-35560000D03*
D16*
X7620000Y-38100000D03*
X7620000Y-40640000D03*
X7620000Y-43180000D03*
X7620000Y-45720000D03*
X7620000Y-48260000D03*
X7620000Y-50800000D03*
X7620000Y-53340000D03*
X7620000Y-55880000D03*
X7620000Y-58420000D03*
X7620000Y-60960000D03*
X7620000Y-63500000D03*
X7620000Y-66040000D03*
X7620000Y-68580000D03*
X7620000Y-71120000D03*
X7620000Y-73660000D03*
X7620000Y-76200000D03*
X7620000Y-78740000D03*
X7620000Y-81280000D03*
D17*
X23380000Y-75120000D03*
X21480000Y-75120000D03*
X22430000Y-78120000D03*
D13*
X35500000Y-10000000D03*
X35500000Y-12000000D03*
X30500000Y-10000000D03*
X30500000Y-12000000D03*
X16000000Y-13000000D03*
X16000000Y-15000000D03*
D18*
X23290000Y-5080000D03*
D19*
X25830000Y-5080000D03*
D20*
X21250000Y-71120000D03*
X23250000Y-71120000D03*
D15*
X32975000Y-35570000D03*
D16*
X32975000Y-38110000D03*
X32975000Y-40650000D03*
X32975000Y-43190000D03*
X32975000Y-45730000D03*
X32975000Y-48270000D03*
X32975000Y-50810000D03*
X32975000Y-53350000D03*
X32975000Y-55890000D03*
X32975000Y-58430000D03*
X32975000Y-60970000D03*
X32975000Y-63510000D03*
X32975000Y-66050000D03*
X32975000Y-68590000D03*
X32975000Y-71130000D03*
X32975000Y-73670000D03*
X32975000Y-76210000D03*
X32975000Y-78750000D03*
X32975000Y-81290000D03*
D21*
X13400000Y-74470000D03*
X13400000Y-76370000D03*
X16400000Y-75420000D03*
D13*
X24500000Y-10000000D03*
X24500000Y-12000000D03*
D22*
X26250000Y-72650000D03*
D23*
X26250000Y-71350000D03*
D24*
X28256000Y-17005000D03*
X28256000Y-19005000D03*
X28256000Y-21005000D03*
X28206000Y-23005000D03*
X30006000Y-20005000D03*
X30006000Y-22005000D03*
X31756000Y-17005000D03*
X31756000Y-19005000D03*
X31756000Y-21005000D03*
X31756000Y-23005000D03*
D25*
X28500000Y-77500000D03*
D18*
X28830000Y-5080000D03*
D19*
X31370000Y-5080000D03*
D13*
X10750000Y-25500000D03*
X10750000Y-27500000D03*
D14*
X19250000Y-4765564D03*
X12750000Y-4765564D03*
X19250000Y-9265564D03*
X12750000Y-9265564D03*
D18*
X34370000Y-5080000D03*
D19*
X36910000Y-5080000D03*
D12*
X18750000Y-71120000D03*
X16750000Y-71120000D03*
D14*
X14750000Y-20820000D03*
X21250000Y-20820000D03*
X14750000Y-25320000D03*
X21250000Y-25320000D03*
D26*
X23000000Y-35500000D03*
X24000000Y-39700000D03*
X11000000Y-29750000D03*
X11500000Y-15000000D03*
X14440000Y-79310000D03*
X7620000Y-21620000D03*
X20500000Y-17000000D03*
X20500000Y-15250000D03*
X21000000Y-13750000D03*
X26750000Y-38250000D03*
D27*
X34975000Y-20225000D02*
X33755000Y-19005000D01*
X33755000Y-19005000D02*
X31756000Y-19005000D01*
X34975000Y-58970000D02*
X34975000Y-20225000D01*
X32975000Y-60970000D02*
X34975000Y-58970000D01*
X25830000Y-8670000D02*
X24500000Y-10000000D01*
X25830000Y-5080000D02*
X25830000Y-8670000D01*
X30671000Y-24090000D02*
X31756000Y-23005000D01*
X29050000Y-49200000D02*
X29050000Y-25700000D01*
X30660000Y-24090000D02*
X30671000Y-24090000D01*
X29000000Y-49250000D02*
X29050000Y-49200000D01*
X29050000Y-25700000D02*
X30660000Y-24090000D01*
X32975000Y-50810000D02*
X30560000Y-50810000D01*
X30560000Y-50810000D02*
X29000000Y-49250000D01*
X31370000Y-9130000D02*
X30500000Y-10000000D01*
X31370000Y-5080000D02*
X31370000Y-9130000D01*
X28300000Y-24450000D02*
X29300000Y-24450000D01*
X32975000Y-53350000D02*
X29350000Y-53350000D01*
X30006000Y-23244000D02*
X30006000Y-22005000D01*
X29300000Y-24450000D02*
X30000000Y-23750000D01*
X30000000Y-23250000D02*
X30006000Y-23244000D01*
X29350000Y-53350000D02*
X28300000Y-52300000D01*
X28300000Y-52300000D02*
X28300000Y-24450000D01*
X30000000Y-23750000D02*
X30000000Y-23250000D01*
X36910000Y-8590000D02*
X35500000Y-10000000D01*
X36910000Y-5080000D02*
X36910000Y-8590000D01*
X17500000Y-15000000D02*
X16000000Y-15000000D01*
D28*
X21480000Y-75120000D02*
X21480000Y-71350000D01*
X26250000Y-69750000D02*
X26250000Y-71350000D01*
X21250000Y-68500000D02*
X25000000Y-68500000D01*
D27*
X24500000Y-12000000D02*
X20500000Y-12000000D01*
X10750000Y-27500000D02*
X10750000Y-29500000D01*
X20500000Y-12000000D02*
X17500000Y-15000000D01*
X11000000Y-29750000D02*
X17250000Y-29750000D01*
D28*
X21480000Y-71350000D02*
X21250000Y-71120000D01*
D27*
X17250000Y-29750000D02*
X23000000Y-35500000D01*
X35500000Y-12000000D02*
X30500000Y-12000000D01*
D28*
X25000000Y-68500000D02*
X26250000Y-69750000D01*
X21250000Y-42450000D02*
X21250000Y-68500000D01*
X21250000Y-71120000D02*
X18750000Y-71120000D01*
D27*
X6000000Y-15000000D02*
X11500000Y-15000000D01*
D28*
X24000000Y-39700000D02*
X21250000Y-42450000D01*
D27*
X10750000Y-29500000D02*
X11000000Y-29750000D01*
D28*
X21250000Y-68500000D02*
X21250000Y-71120000D01*
D27*
X13000000Y-15000000D02*
X16000000Y-15000000D01*
X30500000Y-12000000D02*
X24500000Y-12000000D01*
X11500000Y-15000000D02*
X13000000Y-15000000D01*
X16000000Y-12515564D02*
X16000000Y-13000000D01*
X12750000Y-9265564D02*
X16000000Y-12515564D01*
X19250000Y-9265564D02*
X16000000Y-12515564D01*
X6000000Y-12515564D02*
X6000000Y-13000000D01*
X2750000Y-9265564D02*
X6000000Y-12515564D01*
X9250000Y-9265564D02*
X6000000Y-12515564D01*
X14750000Y-25320000D02*
X11320000Y-25320000D01*
X21250000Y-25320000D02*
X14750000Y-25320000D01*
X28206000Y-23005000D02*
X28206000Y-23544000D01*
X27600000Y-55100000D02*
X28390000Y-55890000D01*
X28390000Y-55890000D02*
X32975000Y-55890000D01*
X27600000Y-24150000D02*
X27600000Y-55100000D01*
X28206000Y-23544000D02*
X27600000Y-24150000D01*
X34275000Y-57130000D02*
X34275000Y-23524000D01*
X32975000Y-58430000D02*
X34275000Y-57130000D01*
X34275000Y-23524000D02*
X31756000Y-21005000D01*
X13400000Y-78270000D02*
X13400000Y-76370000D01*
X8420000Y-20820000D02*
X7620000Y-21620000D01*
X9250000Y-4765564D02*
X2750000Y-4765564D01*
X16250000Y-81120000D02*
X14440000Y-79310000D01*
X14750000Y-20820000D02*
X8420000Y-20820000D01*
X12750000Y-4765564D02*
X9250000Y-4765564D01*
X14440000Y-79310000D02*
X13400000Y-78270000D01*
X14750000Y-20820000D02*
X21250000Y-20820000D01*
X19250000Y-4765564D02*
X12750000Y-4765564D01*
X30006000Y-20005000D02*
X30006000Y-15744000D01*
X35675000Y-16425000D02*
X35675000Y-68430000D01*
X34250000Y-15000000D02*
X35675000Y-16425000D01*
X30006000Y-15744000D02*
X30750000Y-15000000D01*
X35675000Y-68430000D02*
X32975000Y-71130000D01*
X30750000Y-15000000D02*
X34250000Y-15000000D01*
X26200000Y-34800000D02*
X26200000Y-19550000D01*
X26745000Y-19005000D02*
X28256000Y-19005000D01*
X26200000Y-19550000D02*
X26745000Y-19005000D01*
X22900000Y-38100000D02*
X26200000Y-34800000D01*
X7620000Y-38100000D02*
X22900000Y-38100000D01*
X9460000Y-38800000D02*
X7620000Y-40640000D01*
X26900000Y-35100000D02*
X23200000Y-38800000D01*
X27245000Y-21005000D02*
X26900000Y-21350000D01*
X28256000Y-21005000D02*
X27245000Y-21005000D01*
X26900000Y-21350000D02*
X26900000Y-35100000D01*
X23200000Y-38800000D02*
X9460000Y-38800000D01*
X3400000Y-19089950D02*
X3400000Y-46400000D01*
X4169975Y-18319975D02*
X3400000Y-19089950D01*
X3400000Y-46400000D02*
X5260000Y-48260000D01*
X20500000Y-17000000D02*
X19180025Y-18319975D01*
X5260000Y-48260000D02*
X7620000Y-48260000D01*
X19180025Y-18319975D02*
X4169975Y-18319975D01*
X2700000Y-51700000D02*
X4340000Y-53340000D01*
X2700000Y-18800000D02*
X2700000Y-51700000D01*
X18130025Y-17619975D02*
X18010050Y-17500000D01*
X20500000Y-15250000D02*
X18130025Y-17619975D01*
X4000000Y-17500000D02*
X2700000Y-18800000D01*
X18010050Y-17500000D02*
X4000000Y-17500000D01*
X4340000Y-53340000D02*
X7620000Y-53340000D01*
X3380000Y-55880000D02*
X7620000Y-55880000D01*
X17519390Y-16000000D02*
X16769390Y-16750000D01*
X20939339Y-13750000D02*
X18689339Y-16000000D01*
X16769390Y-16750000D02*
X3250000Y-16750000D01*
X3250000Y-16750000D02*
X2000000Y-18000000D01*
X21000000Y-13750000D02*
X20939339Y-13750000D01*
X2000000Y-18000000D02*
X2000000Y-54500000D01*
X2000000Y-54500000D02*
X3380000Y-55880000D01*
X18689339Y-16000000D02*
X17519390Y-16000000D01*
X15060000Y-70310000D02*
X10790000Y-66040000D01*
X10790000Y-66040000D02*
X7620000Y-66040000D01*
X16750000Y-71120000D02*
X15060000Y-72810000D01*
X15060000Y-72810000D02*
X13400000Y-74470000D01*
X15060000Y-72810000D02*
X15060000Y-70310000D01*
X23380000Y-75120000D02*
X23380000Y-71250000D01*
X23380000Y-75120000D02*
X23380000Y-75470000D01*
X23380000Y-71250000D02*
X23250000Y-71120000D01*
X22330000Y-76520000D02*
X17500000Y-76520000D01*
X23380000Y-75470000D02*
X22330000Y-76520000D01*
X17500000Y-76520000D02*
X16400000Y-75420000D01*
D28*
X26000000Y-55250000D02*
X26000000Y-38750000D01*
X28500000Y-77500000D02*
X28500000Y-57750000D01*
X25650000Y-80350000D02*
X28500000Y-77500000D01*
X28500000Y-57750000D02*
X26000000Y-55250000D01*
X26000000Y-38750000D02*
X26500000Y-38250000D01*
X25650000Y-80750000D02*
X25650000Y-80350000D01*
X26500000Y-38250000D02*
X26650000Y-38250000D01*
X21250000Y-78120000D02*
X18250000Y-81120000D01*
X23380000Y-78120000D02*
X22430000Y-78120000D01*
X26250000Y-72650000D02*
X26250000Y-75250000D01*
X22430000Y-78830000D02*
X24350000Y-80750000D01*
X22430000Y-78120000D02*
X21250000Y-78120000D01*
X22430000Y-78120000D02*
X22430000Y-78830000D01*
X26250000Y-75250000D02*
X23380000Y-78120000D01*
M02*

View File

@@ -1,178 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Soldermask,Top*
G04 #@! TF.FilePolarity,Negative*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 Aperture macros list*
%AMRoundRect*
0 Rectangle with rounded corners*
0 $1 Rounding radius*
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
0 Add a 4 corners polygon primitive as box body*
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
0 Add four circle primitives for the rounded corners*
1,1,$1+$1,$2,$3*
1,1,$1+$1,$4,$5*
1,1,$1+$1,$6,$7*
1,1,$1+$1,$8,$9*
0 Add four rect primitives between the rounded corners*
20,1,$1+$1,$2,$3,$4,$5,0*
20,1,$1+$1,$4,$5,$6,$7,0*
20,1,$1+$1,$6,$7,$8,$9,0*
20,1,$1+$1,$8,$9,$2,$3,0*%
%AMFreePoly0*
4,1,22,0.500000,-0.750000,0.000000,-0.750000,0.000000,-0.745033,-0.079941,-0.743568,-0.215256,-0.701293,-0.333266,-0.622738,-0.424486,-0.514219,-0.481581,-0.384460,-0.499164,-0.250000,-0.500000,-0.250000,-0.500000,0.250000,-0.499164,0.250000,-0.499963,0.256109,-0.478152,0.396186,-0.417904,0.524511,-0.324060,0.630769,-0.204165,0.706417,-0.067858,0.745374,0.000000,0.744959,0.000000,0.750000,
0.500000,0.750000,0.500000,-0.750000,0.500000,-0.750000,$1*%
%AMFreePoly1*
4,1,20,0.000000,0.744959,0.073905,0.744508,0.209726,0.703889,0.328688,0.626782,0.421226,0.519385,0.479903,0.390333,0.500000,0.250000,0.500000,-0.250000,0.499851,-0.262216,0.476331,-0.402017,0.414519,-0.529596,0.319384,-0.634700,0.198574,-0.708877,0.061801,-0.746166,0.000000,-0.745033,0.000000,-0.750000,-0.500000,-0.750000,-0.500000,0.750000,0.000000,0.750000,0.000000,0.744959,
0.000000,0.744959,$1*%
G04 Aperture macros list end*
%ADD10FreePoly0,180.000000*%
%ADD11FreePoly1,180.000000*%
%ADD12RoundRect,0.250000X0.350000X0.450000X-0.350000X0.450000X-0.350000X-0.450000X0.350000X-0.450000X0*%
%ADD13RoundRect,0.250000X-0.450000X0.350000X-0.450000X-0.350000X0.450000X-0.350000X0.450000X0.350000X0*%
%ADD14C,2.000000*%
%ADD15R,1.700000X1.700000*%
%ADD16O,1.700000X1.700000*%
%ADD17R,0.800000X1.900000*%
%ADD18R,1.800000X1.800000*%
%ADD19C,1.800000*%
%ADD20RoundRect,0.250000X-0.350000X-0.450000X0.350000X-0.450000X0.350000X0.450000X-0.350000X0.450000X0*%
%ADD21R,1.900000X0.800000*%
%ADD22FreePoly0,90.000000*%
%ADD23FreePoly1,90.000000*%
%ADD24C,1.371600*%
%ADD25C,2.500000*%
G04 APERTURE END LIST*
D10*
X25650000Y-80750000D03*
D11*
X24350000Y-80750000D03*
D12*
X18250000Y-81120000D03*
X16250000Y-81120000D03*
D13*
X6000000Y-13000000D03*
X6000000Y-15000000D03*
D14*
X9250000Y-4765564D03*
X2750000Y-4765564D03*
X2750000Y-9265564D03*
X9250000Y-9265564D03*
D15*
X7620000Y-35560000D03*
D16*
X7620000Y-38100000D03*
X7620000Y-40640000D03*
X7620000Y-43180000D03*
X7620000Y-45720000D03*
X7620000Y-48260000D03*
X7620000Y-50800000D03*
X7620000Y-53340000D03*
X7620000Y-55880000D03*
X7620000Y-58420000D03*
X7620000Y-60960000D03*
X7620000Y-63500000D03*
X7620000Y-66040000D03*
X7620000Y-68580000D03*
X7620000Y-71120000D03*
X7620000Y-73660000D03*
X7620000Y-76200000D03*
X7620000Y-78740000D03*
X7620000Y-81280000D03*
D17*
X23380000Y-75120000D03*
X21480000Y-75120000D03*
X22430000Y-78120000D03*
D13*
X35500000Y-10000000D03*
X35500000Y-12000000D03*
X30500000Y-10000000D03*
X30500000Y-12000000D03*
X16000000Y-13000000D03*
X16000000Y-15000000D03*
D18*
X23290000Y-5080000D03*
D19*
X25830000Y-5080000D03*
D20*
X21250000Y-71120000D03*
X23250000Y-71120000D03*
D15*
X32975000Y-35570000D03*
D16*
X32975000Y-38110000D03*
X32975000Y-40650000D03*
X32975000Y-43190000D03*
X32975000Y-45730000D03*
X32975000Y-48270000D03*
X32975000Y-50810000D03*
X32975000Y-53350000D03*
X32975000Y-55890000D03*
X32975000Y-58430000D03*
X32975000Y-60970000D03*
X32975000Y-63510000D03*
X32975000Y-66050000D03*
X32975000Y-68590000D03*
X32975000Y-71130000D03*
X32975000Y-73670000D03*
X32975000Y-76210000D03*
X32975000Y-78750000D03*
X32975000Y-81290000D03*
D21*
X13400000Y-74470000D03*
X13400000Y-76370000D03*
X16400000Y-75420000D03*
D13*
X24500000Y-10000000D03*
X24500000Y-12000000D03*
D22*
X26250000Y-72650000D03*
D23*
X26250000Y-71350000D03*
D24*
X28256000Y-17005000D03*
X28256000Y-19005000D03*
X28256000Y-21005000D03*
X28206000Y-23005000D03*
X30006000Y-20005000D03*
X30006000Y-22005000D03*
X31756000Y-17005000D03*
X31756000Y-19005000D03*
X31756000Y-21005000D03*
X31756000Y-23005000D03*
D25*
X28500000Y-77500000D03*
D18*
X28830000Y-5080000D03*
D19*
X31370000Y-5080000D03*
D13*
X10750000Y-25500000D03*
X10750000Y-27500000D03*
D14*
X19250000Y-4765564D03*
X12750000Y-4765564D03*
X19250000Y-9265564D03*
X12750000Y-9265564D03*
D18*
X34370000Y-5080000D03*
D19*
X36910000Y-5080000D03*
D12*
X18750000Y-71120000D03*
X16750000Y-71120000D03*
D14*
X14750000Y-20820000D03*
X21250000Y-20820000D03*
X14750000Y-25320000D03*
X21250000Y-25320000D03*
M02*

View File

@@ -1,173 +0,0 @@
G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*
G04 #@! TF.CreationDate,2023-03-04T17:24:57+01:00*
G04 #@! TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*
G04 #@! TF.SameCoordinates,Original*
G04 #@! TF.FileFunction,Paste,Top*
G04 #@! TF.FilePolarity,Positive*
%FSLAX46Y46*%
G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:24:57*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
G04 Aperture macros list*
%AMRoundRect*
0 Rectangle with rounded corners*
0 $1 Rounding radius*
0 $2 $3 $4 $5 $6 $7 $8 $9 X,Y pos of 4 corners*
0 Add a 4 corners polygon primitive as box body*
4,1,4,$2,$3,$4,$5,$6,$7,$8,$9,$2,$3,0*
0 Add four circle primitives for the rounded corners*
1,1,$1+$1,$2,$3*
1,1,$1+$1,$4,$5*
1,1,$1+$1,$6,$7*
1,1,$1+$1,$8,$9*
0 Add four rect primitives between the rounded corners*
20,1,$1+$1,$2,$3,$4,$5,0*
20,1,$1+$1,$4,$5,$6,$7,0*
20,1,$1+$1,$6,$7,$8,$9,0*
20,1,$1+$1,$8,$9,$2,$3,0*%
G04 Aperture macros list end*
%ADD10C,0.150000*%
%ADD11RoundRect,0.250000X0.350000X0.450000X-0.350000X0.450000X-0.350000X-0.450000X0.350000X-0.450000X0*%
%ADD12RoundRect,0.250000X-0.450000X0.350000X-0.450000X-0.350000X0.450000X-0.350000X0.450000X0.350000X0*%
%ADD13R,0.800000X1.900000*%
%ADD14RoundRect,0.250000X-0.350000X-0.450000X0.350000X-0.450000X0.350000X0.450000X-0.350000X0.450000X0*%
%ADD15R,1.900000X0.800000*%
G04 APERTURE END LIST*
D10*
X13511904Y-49702380D02*
X13321428Y-49702380D01*
X13226190Y-49750000D01*
X13178571Y-49797619D01*
X13083333Y-49940476D01*
X13035714Y-50130952D01*
X13035714Y-50511904D01*
X13083333Y-50607142D01*
X13130952Y-50654761D01*
X13226190Y-50702380D01*
X13416666Y-50702380D01*
X13511904Y-50654761D01*
X13559523Y-50607142D01*
X13607142Y-50511904D01*
X13607142Y-50273809D01*
X13559523Y-50178571D01*
X13511904Y-50130952D01*
X13416666Y-50083333D01*
X13226190Y-50083333D01*
X13130952Y-50130952D01*
X13083333Y-50178571D01*
X13035714Y-50273809D01*
X14464285Y-50035714D02*
X14464285Y-50702380D01*
X14226190Y-49654761D02*
X13988095Y-50369047D01*
X14607142Y-50369047D01*
X15369047Y-50654761D02*
X15273809Y-50702380D01*
X15083333Y-50702380D01*
X14988095Y-50654761D01*
X14940476Y-50559523D01*
X14940476Y-50178571D01*
X14988095Y-50083333D01*
X15083333Y-50035714D01*
X15273809Y-50035714D01*
X15369047Y-50083333D01*
X15416666Y-50178571D01*
X15416666Y-50273809D01*
X14940476Y-50369047D01*
X15845238Y-50035714D02*
X15845238Y-50702380D01*
X15845238Y-50130952D02*
X15892857Y-50083333D01*
X15988095Y-50035714D01*
X16130952Y-50035714D01*
X16226190Y-50083333D01*
X16273809Y-50178571D01*
X16273809Y-50702380D01*
X17178571Y-50035714D02*
X17178571Y-50845238D01*
X17130952Y-50940476D01*
X17083333Y-50988095D01*
X16988095Y-51035714D01*
X16845238Y-51035714D01*
X16750000Y-50988095D01*
X17178571Y-50654761D02*
X17083333Y-50702380D01*
X16892857Y-50702380D01*
X16797619Y-50654761D01*
X16750000Y-50607142D01*
X16702380Y-50511904D01*
X16702380Y-50226190D01*
X16750000Y-50130952D01*
X16797619Y-50083333D01*
X16892857Y-50035714D01*
X17083333Y-50035714D01*
X17178571Y-50083333D01*
X17654761Y-50607142D02*
X17702380Y-50654761D01*
X17654761Y-50702380D01*
X17607142Y-50654761D01*
X17654761Y-50607142D01*
X17654761Y-50702380D01*
X18559523Y-50702380D02*
X18559523Y-49702380D01*
X18559523Y-50654761D02*
X18464285Y-50702380D01*
X18273809Y-50702380D01*
X18178571Y-50654761D01*
X18130952Y-50607142D01*
X18083333Y-50511904D01*
X18083333Y-50226190D01*
X18130952Y-50130952D01*
X18178571Y-50083333D01*
X18273809Y-50035714D01*
X18464285Y-50035714D01*
X18559523Y-50083333D01*
X19416666Y-50654761D02*
X19321428Y-50702380D01*
X19130952Y-50702380D01*
X19035714Y-50654761D01*
X18988095Y-50559523D01*
X18988095Y-50178571D01*
X19035714Y-50083333D01*
X19130952Y-50035714D01*
X19321428Y-50035714D01*
X19416666Y-50083333D01*
X19464285Y-50178571D01*
X19464285Y-50273809D01*
X18988095Y-50369047D01*
D11*
X18250000Y-81120000D03*
X16250000Y-81120000D03*
D12*
X6000000Y-13000000D03*
X6000000Y-15000000D03*
D13*
X23380000Y-75120000D03*
X21480000Y-75120000D03*
X22430000Y-78120000D03*
D12*
X35500000Y-10000000D03*
X35500000Y-12000000D03*
X30500000Y-10000000D03*
X30500000Y-12000000D03*
X16000000Y-13000000D03*
X16000000Y-15000000D03*
D14*
X21250000Y-71120000D03*
X23250000Y-71120000D03*
D15*
X13400000Y-74470000D03*
X13400000Y-76370000D03*
X16400000Y-75420000D03*
D12*
X24500000Y-10000000D03*
X24500000Y-12000000D03*
X10750000Y-25500000D03*
X10750000Y-27500000D03*
D11*
X18750000Y-71120000D03*
X16750000Y-71120000D03*
M02*

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +0,0 @@
%TF.GenerationSoftware,KiCad,Pcbnew,(6.0.11)*%
%TF.CreationDate,2023-03-04T17:25:38+01:00*%
%TF.ProjectId,jig2,6a696732-2e6b-4696-9361-645f70636258,rev?*%
%TF.SameCoordinates,Original*%
%TF.FileFunction,Drillmap*%
%TF.FilePolarity,Positive*%
%FSLAX45Y45*%
G04 Gerber Fmt 4.5, Leading zero omitted, Abs format (unit mm)*
G04 Created by KiCad (PCBNEW (6.0.11)) date 2023-03-04 17:25:38*
%MOMM*%
%LPD*%
G01*
G04 APERTURE LIST*
%ADD10C,0.100000*%
%ADD11C,0.200000*%
G04 APERTURE END LIST*
D10*
X0Y-8500000D02*
X0Y0D01*
X4000000Y-8500000D02*
X0Y-8500000D01*
X4000000Y0D02*
X4000000Y-8500000D01*
X0Y0D02*
X4000000Y0D01*
D11*
X252619Y-8815476D02*
X252619Y-8615476D01*
X300238Y-8615476D01*
X328810Y-8625000D01*
X347857Y-8644048D01*
X357381Y-8663095D01*
X366905Y-8701190D01*
X366905Y-8729762D01*
X357381Y-8767857D01*
X347857Y-8786905D01*
X328810Y-8805952D01*
X300238Y-8815476D01*
X252619Y-8815476D01*
X452619Y-8815476D02*
X452619Y-8682143D01*
X452619Y-8720238D02*
X462143Y-8701190D01*
X471667Y-8691667D01*
X490714Y-8682143D01*
X509762Y-8682143D01*
X576429Y-8815476D02*
X576429Y-8682143D01*
X576429Y-8615476D02*
X566905Y-8625000D01*
X576429Y-8634524D01*
X585952Y-8625000D01*
X576429Y-8615476D01*
X576429Y-8634524D01*
X700238Y-8815476D02*
X681190Y-8805952D01*
X671667Y-8786905D01*
X671667Y-8615476D01*
X805000Y-8815476D02*
X785952Y-8805952D01*
X776428Y-8786905D01*
X776428Y-8615476D01*
X1033571Y-8815476D02*
X1033571Y-8615476D01*
X1100238Y-8758333D01*
X1166905Y-8615476D01*
X1166905Y-8815476D01*
X1347857Y-8815476D02*
X1347857Y-8710714D01*
X1338333Y-8691667D01*
X1319286Y-8682143D01*
X1281190Y-8682143D01*
X1262143Y-8691667D01*
X1347857Y-8805952D02*
X1328810Y-8815476D01*
X1281190Y-8815476D01*
X1262143Y-8805952D01*
X1252619Y-8786905D01*
X1252619Y-8767857D01*
X1262143Y-8748810D01*
X1281190Y-8739286D01*
X1328810Y-8739286D01*
X1347857Y-8729762D01*
X1443095Y-8682143D02*
X1443095Y-8882143D01*
X1443095Y-8691667D02*
X1462143Y-8682143D01*
X1500238Y-8682143D01*
X1519286Y-8691667D01*
X1528809Y-8701190D01*
X1538333Y-8720238D01*
X1538333Y-8777381D01*
X1528809Y-8796429D01*
X1519286Y-8805952D01*
X1500238Y-8815476D01*
X1462143Y-8815476D01*
X1443095Y-8805952D01*
X1624048Y-8796429D02*
X1633571Y-8805952D01*
X1624048Y-8815476D01*
X1614524Y-8805952D01*
X1624048Y-8796429D01*
X1624048Y-8815476D01*
X1624048Y-8691667D02*
X1633571Y-8701190D01*
X1624048Y-8710714D01*
X1614524Y-8701190D01*
X1624048Y-8691667D01*
X1624048Y-8710714D01*
M02*

View File

@@ -1,13 +0,0 @@
M48
; DRILL file {KiCad (6.0.11)} date Sa 04 Mär 2023 17:25:31 CET
; FORMAT={-:-/ absolute / metric / decimal}
; #@! TF.CreationDate,2023-03-04T17:25:31+01:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(6.0.11)
; #@! TF.FileFunction,NonPlated,1,2,NPTH
FMAT,2
METRIC
%
G90
G05
T0
M30

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +0,0 @@
M48
; DRILL file {KiCad (6.0.11)} date Sa 04 Mär 2023 17:25:31 CET
; FORMAT={-:-/ absolute / metric / decimal}
; #@! TF.CreationDate,2023-03-04T17:25:31+01:00
; #@! TF.GenerationSoftware,Kicad,Pcbnew,(6.0.11)
; #@! TF.FileFunction,Plated,1,2,PTH
FMAT,2
METRIC
; #@! TA.AperFunction,Plated,PTH,ViaDrill
T1C0.400
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T2C0.900
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T3C1.000
; #@! TA.AperFunction,Plated,PTH,ComponentDrill
T4C1.100
%
G90
G05
T1
X7.62Y-21.62
X11.0Y-29.75
X11.5Y-15.0
X14.44Y-79.31
X20.5Y-15.25
X20.5Y-17.0
X21.0Y-13.75
X23.0Y-35.5
X24.0Y-39.7
X26.75Y-38.25
T2
X23.29Y-5.08
X25.83Y-5.08
X28.83Y-5.08
X31.37Y-5.08
X34.37Y-5.08
X36.91Y-5.08
T3
X7.62Y-35.56
X7.62Y-38.1
X7.62Y-40.64
X7.62Y-43.18
X7.62Y-45.72
X7.62Y-48.26
X7.62Y-50.8
X7.62Y-53.34
X7.62Y-55.88
X7.62Y-58.42
X7.62Y-60.96
X7.62Y-63.5
X7.62Y-66.04
X7.62Y-68.58
X7.62Y-71.12
X7.62Y-73.66
X7.62Y-76.2
X7.62Y-78.74
X7.62Y-81.28
X28.206Y-23.005
X28.256Y-17.005
X28.256Y-19.005
X28.256Y-21.005
X30.006Y-20.005
X30.006Y-22.005
X31.756Y-17.005
X31.756Y-19.005
X31.756Y-21.005
X31.756Y-23.005
X32.975Y-35.57
X32.975Y-38.11
X32.975Y-40.65
X32.975Y-43.19
X32.975Y-45.73
X32.975Y-48.27
X32.975Y-50.81
X32.975Y-53.35
X32.975Y-55.89
X32.975Y-58.43
X32.975Y-60.97
X32.975Y-63.51
X32.975Y-66.05
X32.975Y-68.59
X32.975Y-71.13
X32.975Y-73.67
X32.975Y-76.21
X32.975Y-78.75
X32.975Y-81.29
T4
X2.75Y-4.766
X2.75Y-9.266
X9.25Y-4.766
X9.25Y-9.266
X12.75Y-4.766
X12.75Y-9.266
X14.75Y-20.82
X14.75Y-25.32
X19.25Y-4.766
X19.25Y-9.266
X21.25Y-20.82
X21.25Y-25.32
T0
M30

File diff suppressed because it is too large Load Diff

View File

@@ -1,75 +0,0 @@
{
"board": {
"active_layer": 35,
"active_layer_preset": "All Layers",
"auto_track_width": true,
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"pads": 1.0,
"tracks": 1.0,
"vias": 1.0,
"zones": 0.6
},
"ratsnest_display_mode": 0,
"selection_filter": {
"dimensions": true,
"footprints": true,
"graphics": true,
"keepouts": true,
"lockedItems": true,
"otherItems": true,
"pads": true,
"text": true,
"tracks": true,
"vias": true,
"zones": true
},
"visible_items": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
32,
33,
34,
35,
36
],
"visible_layers": "fffffff_ffffffff",
"zone_display_mode": 0
},
"meta": {
"filename": "jig2.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

Some files were not shown because too many files have changed in this diff Show More