367 Commits

Author SHA1 Message Date
Nic Limper
ebd1adc0d5 gzipped www files 2024-02-28 01:20:37 +01:00
Nic Limper
f4cb642142 add Denmark to dayahead electricity prices; enable it also for 2.9" UC8151 2024-02-28 01:11:01 +01:00
Nic Limper
9b2d76a6b6 bugfix: idlereq should not be queued, and only sent when queue is empty 2024-02-28 01:09:00 +01:00
leXorNet
ac979a3c52 Added Swedish content language (#245) 2024-02-27 12:11:13 +01:00
Jan-Henrik Bruhn
a606c4c1aa Use relative paths for fetch calls and websocket (#243)
This allows the OEPL Frontend to be put behind a reverse proxy like Home
Assistant Ingress to proxy it behind a relative path.
2024-02-27 01:47:36 +01:00
Jelmer
c22fe0d91b Merge pull request #241 from TheRealMrSteel/patch-1
Update content_cards.json
2024-02-27 00:37:42 +01:00
Jelmer
b29907a725 Merge pull request #242 from VstudioLAB/M3_58-26-29FREEZER
M3 58 26 29 freezer
2024-02-27 00:36:03 +01:00
Jelmer
8da475901d Support for rotating generated images based on tagtype profile 2024-02-27 00:32:09 +01:00
Vstudio LAB
e4ed0b13db Delete ARM_Tag_FW/Newton_M3_nRF52811/$PROJECT_DIR directory 2024-02-26 22:55:48 +01:00
VstudioLAB
0ffd0fbf0e Update .gitignore 2024-02-26 22:49:03 +01:00
Steel
1cba70b9cc Update content_cards.json
typo in id19
2024-02-26 22:47:50 +01:00
VstudioLAB
6b67f6df2b updates 2024-02-26 22:24:48 +01:00
Nic Limper
b9fe72de5c small bugfixes 2024-02-26 20:58:46 +01:00
Nic Limper
c458c6b29c bugfix: config screen is not populated when alias is empty 2024-02-26 11:47:56 +01:00
jjwbruijn
d3b9abf56a M2 7.5" v0027 fw 2024-02-26 01:27:40 +01:00
Jelmer
d2b17b7a97 added M2 7.5" BW tag type 2024-02-25 23:10:40 +01:00
Nic Limper
7e3e73a064 bugfix: no flasher-only detection on tag-based AP 2024-02-25 21:39:28 +01:00
Jelmer
9ca9007a1c Update oepl-definitions.h 2024-02-25 19:57:20 +01:00
Nic Limper
b03ad07179 bugfix, AP always reported C6 present 2024-02-25 15:26:01 +01:00
Nic Limper
56537e46be dirty fix for zlib compression
The miniz is used for zlib compression. But because that library has some bugs related to a smal window sizes (we need 4096), I had to make some patches to the library. The miniz library happens to also be part of esp-idf. To distinguish between our version and the esp-idf version, I created a `namespace Miniz` around our version. But nevertheless, the esp-idf version is called when I'm calling Miniz::tdefl_init and Miniz::tdefl_compress . Why??
Anyway, renamed tdefl_init and tdefl_compress to tdefl_initOEPL and tdefl_compressOEPL to get it working. This is ugly. If somebody has a better solution, please let me know!
2024-02-25 14:45:03 +01:00
Nic Limper
bc06ea74e8 gzipped web files 2024-02-24 14:04:47 +01:00
Nic Limper
9137c5acb1 add BLE to all ESP32-S3 based AP's (default disabled; enable in the config screen if needed) 2024-02-24 14:01:27 +01:00
Nic Limper
c0e59dadb4 webflasher serial passthrough, work in progress, turned off for now 2024-02-24 12:46:27 +01:00
Nic Limper
0dd3a8459b fix for mini AP 2024-02-23 17:19:08 +01:00
Nic Limper
ebd6b5289c lot of small fixes
- adds tag serial debug in webflasher and power up/down buttons
- fixes bug where esp32-s3 connected via usb cdc slows down when no terminal connection is present
- fix: ghost tags reporting a different channel id than the AP are now ignored
- webflasher now ramps up/down power to prevent spikes
- bugfix: C6 doesn't get reset anoymore by the watchdog during flashing
- bugfix: C6 could go in flash mode unintended
- a failed connection during swd write blocks is now reported back instead of silently ignored
- added 4 areas of Sweden to day ahead price content
- new context menu option 'Delete all inactive tags' (only when right clicking on an inactive tag).
- adjusted some timings
2024-02-23 17:08:52 +01:00
atc1441
65558360ef Added offline lines to TLSR FW, If the AP is not found the display will draw 5 lines to notify the user 2024-02-20 18:12:44 +01:00
atc1441
dd69fa029a Added ATC_MiThermometer to the BLE part. This allows to receive the Advertising data from the Custom firmware running on the Thermometer via BLE 2024-02-16 18:12:13 +01:00
atc1441
9bbd30b783 Fixed TLSR No AP useless refresh 2024-02-16 16:04:49 +01:00
jjwbruijn
691b688f46 added magic numbers to M2 7.5" 2024-02-16 01:17:11 +01:00
Jelmer
3d125c415f mkfs.OEPL README.md 2024-02-15 23:36:35 +01:00
jjwbruijn
f2dc16953d beta v0027 M2-7.5" FW 2024-02-15 18:51:10 +01:00
jjwbruijn
f38e121c94 More OEPLFS stuff for 88MZ100 2024-02-15 18:34:22 +01:00
VstudioLAB
f83667bcce Added support for the 2.6 BWR 2024-02-15 13:25:58 +01:00
VstudioLAB
bee51a23b6 5.85" Initial support and general preparation for BW only compatibility. 2024-02-15 00:09:25 +01:00
VstudioLAB
a787ac6ddf M3 5.85" cleanning 2024-02-14 22:09:50 +01:00
VstudioLAB
5561f82bf6 Original commit (5.85" BWR only)
First commit of that branch.
At the moment, only the M3 5.85" is added, but not finished.
2024-02-14 21:39:36 +01:00
VstudioLAB
b07eeb31ce initial commit 2024-02-14 00:56:38 +01:00
jjwbruijn
57748d825b Added compression to M3, moved stuff around 2024-02-13 22:38:36 +01:00
Jelmer
d7f6fee31f Update oepl-definitions.h 2024-02-11 14:57:57 +01:00
Jelmer
1cb948e0b6 Update oepl-definitions.h 2024-02-11 14:57:20 +01:00
atc1441
aca1dfc7a3 Added Gicisky / PICKSMART BLE E-Paper Display support. Can be activated via the -D HAS_BLE_WRITER definition in the platformio.ini
This enables direct BLE Image upload from the Main ESP32 SoC via BLE and allows an OEPL usage without soldering/flashing or extra ZigBee interface.
Currently tested on the 2.9" BW and 4.2" BWR version, tagtypes need to be added for more versions

Demo video:
https://youtu.be/_efgMQUA1F4

Official description of the BLE Protocol here:
https://zhuanlan.zhihu.com/p/633113543

Thanks to these wonderful guys for such a good overview:
https://github.com/fpoli/gicisky-tag
https://github.com/Cabalist/gicisky_image_notes
2024-02-10 23:02:34 +01:00
Jelmer
edb874029e Merge pull request #226 from VstudioLAB/ST‐GM29MT1
Adding support to the ST‐GM29MT1 BW (UC8151)
2024-02-08 20:45:49 +01:00
VstudioLAB
a1eba95ce2 Create 27.json 2024-02-08 17:51:38 +01:00
VstudioLAB
4f1252d839 Original commit for this support 2024-02-08 17:36:48 +01:00
Nic Limper
b4836e81f3 tag flasher / timestamp content / bugfixes (#217)
- added webinterface for tag flasher
- added tcp transport for communicating with tag flasher (OTG USB also still works)
- added content 'timestamp', makes use of preloaded images and buttons on the 2.9" M3
- webinterface is now aware of C6 and flasher capabilities
- AP can run without ieee801.15.4 radio (i.e. flasher only) by shorting FLASHER_AP_TXD and FLASHER_AP_RXD
- added tcp transport option to OEPL-Flasher.py (serial also still works)
- added new environment OpenEPaperLink_Mini_AP_v4
- lots of finetuning and bug fixes
2024-02-04 20:30:52 +01:00
Nic Limper
472f148b0c typo 2024-02-02 16:36:27 +01:00
Nic Limper
107c85e3cf bugfix: too long pending filenames after a few hours of uptime 2024-02-02 16:22:19 +01:00
Nic Limper
1835b1cda7 gzipped wwwroot 2024-01-30 11:56:19 +01:00
Nic Limper
b71844eac0 imgupload performance / Norway dayahead codes 2024-01-30 11:23:58 +01:00
Nic Limper
72c1b7bf40 bugfix dayahead 2024-01-30 00:49:49 +01:00
Nic Limper
1c7d45865d new content type: day ahead prices (S3-based AP only) 2024-01-30 00:33:22 +01:00
Nic Limper
7fd04d1ae3 esp32 support for compressed images to tag 2024-01-29 02:50:39 +01:00
Nic Limper
6292e73135 Pending queue (#210)
Pretty complex change here: pending images/commands are now queued.

A command (like LED flasher) will not overwrite a pending image anymore. Also, sending multiple preloaded images is possible.
Also works (at least, as far as I could test) in combination with Multi AP and mirroring tags ('display a copy' content type).

It you want to test this: don't forget to upload the changed files in /www (the pending icon is now displaying the amount of queued messages). Timing improvements will follow later (only one message can be transmitted every checkin. If multiple messages are queued, at this moment, you have to wait until the next checkin which takes 40-60 sec).

This comes also with the advantage of better stability if you upload multiple images to the same tag in succession. Before queuing, if was possible to replace the image between sending the pending message and the image transfer to the tag, causing md5 mismatches and instability.

Solves #47
2024-01-29 00:49:52 +01:00
Nic Limper
8c4627007f removed simple_AP from build-test.yml 2024-01-28 23:08:33 +01:00
jjwbruijn
e563358370 Sorry bit much. Major rewrite of the 88MZ100 firmware, now with compression support. Added beta M2 2.7" (sleep current needs work) and 1.6"(200px). Probably broke M3 building, it's font files have moved to a new 'common' directory 2024-01-28 11:08:42 +01:00
Nic Limper
c2ab7d6057 crispy fonts / HS 3.5 BWY template fix / remove DATATYPE_IMG_RAW_1BPP_DIRECT 2024-01-27 23:49:14 +01:00
Jelmer
5e62b2de1b Update oepl-definitions.h 2024-01-26 22:29:07 +01:00
atc1441
62b87da8c2 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-26 16:41:06 +01:00
atc1441
9608c6e417 Allow for complete offline ESP32-C6 Updates 2024-01-26 16:41:03 +01:00
Jelmer
86a68cbba4 backlogged fixes 2024-01-26 16:10:00 +01:00
Jelmer
80298ed4a1 Update tag_md5_db.json 2024-01-25 14:41:19 +01:00
Jelmer
d6b1cc0eca added compressed datatypes 2024-01-25 12:10:00 +01:00
Jelmer
90284d0a81 Merge pull request #208 from Reletiv/dev
Added Skadis mounts for HS TLSR
2024-01-25 00:24:34 +01:00
Reletiv
f88c05b279 Added Skadis Solum mounts
Added Skadis Solum mounts 1.54" and 2.9"
Credits to: tdroza
2024-01-24 23:59:45 +01:00
Reletiv
d435d12c30 Added Skadis mounts for HS 2024-01-24 21:43:13 +01:00
Jelmer
af3b6c53c8 Merge pull request #206 from justinotherguy/master
add gerber file for combined flex pcb for nano ap
2024-01-21 14:34:45 +01:00
Justin Otherguy
6af250efbf add gerber file for combined flex pcb
this file for combined flex pcb: antenna and connection between ESP32 S2 mini and tag, so it can be produced in one flex pcb.
combined file has been kinldy provided by 123tztz321 - thank you :)
2024-01-21 14:24:45 +01:00
Nic Limper
83bd0ec177 stability improvements
- changed ESPAsyncWebServer and AsyncTCP (both not properly maintained for more than 5 years) to more recent fork with bugfixes
- fixed concurrency issues in /imgupload. Hurts the upload performance a lot, but probably that's not a real issue. Parallel uploads are now possible (still within the max 5 TCP connection limit)
2024-01-21 11:04:35 +01:00
atc1441
fd13cccdd9 Update README.md 2024-01-19 11:03:24 +01:00
Nic Limper
abc84e18ff change in ledflash http call + minor fixes 2024-01-18 22:25:11 +01:00
atc1441
4edba16674 Another flashing Bug fix
In case the flashing of the C6 is started before the full Boot sequence the AP will end in a failed state
2024-01-15 16:39:24 +01:00
atc1441
7703f6ce6c Fixed interrupted flashing bug
While the C6 would be flashed the recovery would trigger as no Ping was received from the RF-AP
2024-01-15 15:37:24 +01:00
Nic Limper
f00761db94 small improvements
- added short date format definition in language.json
- changed english date format to mm/dd
- added lightgrey (4)/darkgrey (5)/pink (6) colors in jsontemplate (uses pattern dither)
- fixed ntp init timing
2024-01-14 14:24:44 +01:00
atc1441
2655d6d065 Update README.md 2024-01-13 01:24:17 +01:00
Jonas Niesner
e734052697 Update build-test.yml 2024-01-12 17:20:17 +01:00
atc1441
f7b13d3dcb Added a "failsave" recovery to get the RF-AP back up running 2024-01-11 22:36:47 +01:00
Nic Limper
69a40e47aa localisation of date format; tag reverts back to previous content type after sending firmware. 2024-01-11 21:17:35 +01:00
atc1441
b737eb60ed Update TLSR_HS_35_ALPHA.bin 2024-01-11 17:52:50 +01:00
atc1441
1d0186fed0 Enabled cached uploads on the TLSR FW 2024-01-11 17:51:49 +01:00
Nic Limper
d01825a323 autosave tagDB in localstorage of the browser 2024-01-11 14:50:35 +01:00
atc1441
5abbead90b Better SubGHz ESP32-C6 Stability by doing housekeeping every 60 Seconds 2024-01-11 09:10:58 +01:00
Nic Limper
3b294be08a cache control for tagtypes; uptime display in statusbar 2024-01-10 00:53:13 +01:00
atc1441
59d08ea21e Update of the ESP32-C6 SubGHz handling, working Beta 2024-01-09 22:48:18 +01:00
Nic Limper
d2135a57bd bugfix 2024-01-09 21:35:42 +01:00
Jelmer
e77556ee9c Added M2 2.7 jig - updated Hanshow Jigs 2024-01-09 21:19:46 +01:00
Jonas Niesner
1aeea88696 Revert release file change 2024-01-09 20:33:51 +01:00
Nic Limper
837c5de1a8 minor fix in content 2024-01-09 17:58:29 +01:00
Jonas Niesner
d4f16f74e9 Update tagotaversions.json 2024-01-09 16:48:03 +01:00
Nic Limper
fdb4a3cbf1 weather forecast template 2.9" M3 and some minor fixes 2024-01-09 16:09:43 +01:00
Jelmer
5b7c96dcc0 Added 3 Hanshow Jigs 2024-01-09 13:25:16 +01:00
Jonas Niesner
c0a2bd01e5 CI cleanup (#195)
* Update release.yml

* Update platformio.ini

* Update build-test.yml
2024-01-09 08:59:06 +01:00
atc1441
bd8965174a Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-09 00:10:15 +01:00
atc1441
229962165a Added SubGHz Alpha 2024-01-09 00:10:11 +01:00
jjwbruijn
4dac6ab05c M2 v0026 firmware added 2024-01-08 21:59:51 +01:00
atc1441
f95e957361 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-08 08:09:50 +01:00
atc1441
b8161f21fa Arduino ino file renaming 2024-01-08 07:40:07 +01:00
Nic Limper
950931b9a6 smaller UI improvements
- got rid of gamma correction during dithering for quality reasons
- smaller UI improvements and textual edits
- tag grouping in the interface is now sticky across sessions
- tag auto update now shows before/after version number
2024-01-08 01:01:06 +01:00
atc1441
af5e917cb3 Arduino port of the ESP32-C6 AP Firmware added (Not PlatformIO) 2024-01-08 00:36:34 +01:00
atc1441
8005ae71fc Create TLSR_HS_35_ALPHA.bin 2024-01-07 20:10:05 +01:00
atc1441
4965c68516 Added Telink TLSR Alpha release 2024-01-07 20:07:59 +01:00
Nic Limper
96e8fe8660 geocoding and other small improvements
- separated content types for 'not configured', 'static image', 'uploaded image' and 'home assistant' (which is all the same internally, but it confused the users to always see 'static image'
- changed channel reported by the AP to the ieee801.15.4 channel instead of the WiFi channel
- added geocoding to the 'location' fields (e.g. weather forecast). Now you can choose an ambiguous location from a dropdown.
- added 'firmware update rejected' wakeup reason
2024-01-07 19:32:56 +01:00
jjwbruijn
fcff10412d added wakeup-reason for failed OTA 2024-01-07 19:23:36 +01:00
Nic Limper
23c3611872 button to restore tagDB file from backup; cleanup 2024-01-07 02:40:55 +01:00
Nic Limper
7cb7eddc22 removed u8g2 library/fonts (+ automatic substitution for compatibilty) 2024-01-07 00:03:51 +01:00
Jonas Niesner
b68cd22eb1 Updated tag OTA (#193) 2024-01-06 21:16:48 +01:00
Nic Limper
b0cfa1b2b4 new week calendar added 2024-01-06 21:09:08 +01:00
Nic Limper
29589bc5b0 content template redesign / textbox / various
- Added Signika-SB.ttf and some small bitmap fonts
- Removed calibrib50/60/80/100/120/150 bitmap fonts, as they can be better rendered using truetype. Fallback is in place to auto translate to Signika-SB.ttf with the right size in case it is still used in a json template
- Renamed confusing tag type names to 'M2 + size' and 'M3 + size'. Because the universal firmware, there is no need to tell every subtile type change apart anymore.
- added `textbox` to json templates (https://github.com/jjwbruijn/OpenEPaperLink/wiki/Json-template#paragraph-text)
- redesign of count days/hours
- redesign of RSS feed
- designed Buienradar for more tag sizes
- on a scheduled or user initiated reboot, 'REBOOTING' is sent to the error channel of the websockets just before the connection is dropped
- phased out "hwtype": [] in content_cards.json (new location is in the tagtype json, which contains a list of valid content types)

In case of problems using this commit: keep in mind the heavy caching of the tagtypes in the browser. You might still unknowingly use the old contents.
2024-01-05 13:59:31 +01:00
Nic Limper
00ce785158 use latest version 6 of ArduinoJson, not 7 for now. 2024-01-04 20:07:15 +01:00
Pablo Gonzalez
9da9ac9395 Make WebSocket connection protocol dependent (#191)
Currently, the connection to WebSockets is hardcoded to the protocol "ws://".

If the server is put behind a proxy server (like Nginx) to support "https", the connection to websockets will fail (at least in Firefox) due to insecure protocol.

This change checks the current protocol and connects to "wss" if loaded via "https", which makes it work when loaded via proxy.
2024-01-04 19:18:14 +01:00
Jonas Niesner
022f72eee7 Add simple tag ota (#190)
and renamed files
2024-01-04 17:30:42 +01:00
Nic Limper
1d03eedfd6 bugfix in WiFi connection setup; + reset wifi settings using gpio0
- in rare cases, an AP didn't connect to a WiFi network due to some tight timing
- bringing GPIO0 to LOW for more than 5 seconds now resets the wifi settings, in case you're stuck with e.g. a wrong static ip configuration
2024-01-03 15:34:09 +01:00
Nic Limper
4f7a226312 last small fixes before release 2024-01-01 13:25:42 +01:00
Nic Limper
43fd751d1e moved language strings to json file
(don't forget to place languages.json in the file partition)
2023-12-31 17:26:17 +01:00
jjwbruijn
ab8cb3955a Fixed M2 0024 issue->0025 2023-12-31 15:07:26 +01:00
Jelmer
2694a0936f added universal M3 flasher jig 2023-12-31 14:52:28 +01:00
Jelmer
547d27e256 Better EEPROM handling (9.7") 2023-12-31 12:37:40 +01:00
Nic Limper
12f91fb293 fixed 9.7" image wrapping 2023-12-31 02:17:26 +01:00
Nic Limper
5973607ad7 firmware version in webinterface (for now, both dec and hex...) 2023-12-30 22:56:04 +01:00
Jonas Niesner
c4fb629ed4 Move content cards to tag types (#188) 2023-12-30 22:54:09 +01:00
Nic Limper
e14ec92d48 optional previewtype and previewlut parameters for /imgupload call
- optional previewtype and previewlut parameters for /imgupload call
- new 35.json for M3 6.0" (no template yet; coming up next)
- updated upload-demo.html
2023-12-30 22:25:04 +01:00
atc1441
b3887b6874 Added content IDs for 3.5" 2023-12-30 17:41:29 +01:00
Nic Limper
424cf2faf6 webinterface changes
- add tag resolution
- weather forecast card: enabled modify lat/lon coordinates
2023-12-30 15:41:22 +01:00
Nic Limper
0621dda3cc autosize QR code 2023-12-30 14:04:25 +01:00
Nic Limper
9f55d72f97 various small fixes
- prevent using html file for tag firmware update
- removed excessive logging
- fallback to .bak on tagDB load error
- scheduled reboot once at night around 4:00
2023-12-30 12:30:07 +01:00
Jelmer
3621d4b6e1 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-12-30 11:50:42 +01:00
Jelmer
209f0f218a fixed M3 7.5 and 6.0 support in universal M3 fw 2023-12-30 11:50:30 +01:00
Nic Limper
9bb857329e re-rendered bitmap fonts for added languages 2023-12-30 00:38:45 +01:00
Miloš Krumpolc
b0d1e1da2c Add 4 new language: Czech, Slovak, Polish, Spanish (#162) 2023-12-29 23:57:55 +01:00
Nic Limper
d75a1d137f Fix automatic build for NRF 2023-12-29 23:42:22 +01:00
Vstudio LAB
19fc8c6594 Screen rotation in json (#173) 2023-12-29 23:35:47 +01:00
Nic Limper
bcd2a4618d bugfix deleting unknown tag / WIP locking
- bugfix: unable to delete unknown tag by right clicking
- work in progress: lock tag inventory, by rejecting new tags
2023-12-29 23:19:16 +01:00
Jelmer
a962828c4f Universal M3 binary 2023-12-29 19:32:40 +01:00
atc1441
45530085f9 Added S3_C6_NanoAP Gerbers 2023-12-28 09:15:57 +01:00
atc1441
ae4a5d5994 Added S3 C6 Nano AP 2023-12-27 23:09:06 +01:00
Jonas Niesner
bb11458167 M3 led control (#186)
Fixes led control for M3 based displays
2023-12-26 13:20:08 +01:00
atc1441
1f02a8288d Added 9.7" M3 Beta, still many bugs^^ 2023-12-23 13:53:43 +01:00
Jelmer
8065479557 Added 4.3" M3 definition 2023-12-22 00:30:37 +01:00
atc1441
ab65479917 Better Main Case for YellowAP 2023-12-20 18:38:54 +01:00
Jelmer
36596542c4 M3: Bugfix for buttons that would trigger multiple times on HA 2023-12-15 22:32:52 +01:00
Jelmer
eb66e4b7ec M3 v0024 - Slideshows and custom screens 2023-12-13 19:04:02 +01:00
Jelmer
8d15bb72fd Merge pull request #174 from VstudioLAB/M3_7.5BWR_support
Added M3 7.5" BWR EL075H3BRA tag to the AP
2023-12-13 15:10:29 +01:00
atc1441
4c43d76e09 Added YellowAP Case 2023-12-13 11:19:51 +01:00
Vstudio LAB
a1664daba4 Merge branch 'jjwbruijn:master' into M3_7.5BWR_support 2023-12-11 11:55:52 +01:00
jjwbruijn
60f9454bb2 M2 tag firmware v0024 2023-12-09 01:07:27 +01:00
VstudioLAB
db56860d26 Added M3 7.5" BWR EL075H3BRA tag to the AP 2023-12-09 00:54:17 +01:00
jjwbruijn
bb73069097 2.9 Slideshow builder 2023-12-09 00:31:03 +01:00
jjwbruijn
14e4d17b31 code cleanup, settings in eeprom, serial eeprom loader 2023-12-04 22:01:21 +01:00
Jelmer
a941cad902 Merge branch 'VstudioLAB-master' 2023-12-04 21:35:23 +01:00
Jelmer
80fc7997b7 remove content_cards.json.gz 2023-12-04 21:32:55 +01:00
Jelmer
ae0b44a424 Merge pull request #154 from skiphansen/master
Added scripts to build/use a local copy of sdcc version 4.2.0.
2023-12-04 19:56:35 +01:00
atc1441
372cb39c33 HS 3.5" BWY, BWR and BW Added 2023-12-02 13:43:52 +01:00
VstudioLAB
66c7ad6140 Added ST‐GM29XXF 2.9" Support
added ST‐GM29XXF 2.9" support
2023-11-29 00:26:15 +01:00
Skip Hansen
e95a1acae8 Merge branch 'jjwbruijn:master' into master 2023-11-26 18:41:35 -08:00
VstudioLAB
9410c47875 Added French
Added french langage as an option for tag content
2023-11-22 00:25:17 +01:00
Jelmer
220b4ae3e8 Restructured epd driver interface, support for UC-based tags 2023-11-12 10:24:36 +01:00
Skip Hansen
c64190709a Fix typos. 2023-11-04 09:48:40 -07:00
Skip Hansen
c446452b69 Added support for sdcc 4.0.7 used by https://dmitry.gr projects.
Make path's absolute, renamed scripts, added .gitignore
2023-11-04 08:20:51 -07:00
Skip Hansen
a24bccd1af Added scripts to build/use a local copy of sdcc version 4.2.0. 2023-11-03 16:21:02 -07:00
Nic Limper
246b234b22 small fix in follow redirects, and update of gzipped wwwroot 2023-10-29 22:07:58 +01:00
Milo Cesar
22c5bda4c5 Select currently configured files in tag editor (#152) 2023-10-29 22:04:18 +01:00
Sven-Ove Bjerkan
13f8dea68b Add support for Norwegian content (#149)
* Add support for Norwegian content
2023-10-23 19:06:00 +02:00
atc1441
696cb448fe Added Sub GHz YellowAP Gerber 2023-10-23 10:58:08 +02:00
Nic Limper
a4e19b19ab bugfixes: truetype rendering / fast luts / various
- no tag timeouts when tag is put to sleep
- small timing tweaks
- truetype render bugfix
- fix in fast lut setting
2023-10-22 13:20:54 +02:00
Sven-Ove Bjerkan
9d579e9515 Fix: Weather forecast showing yesterday as day 1 in some time zones (#146) (#148) 2023-10-19 16:27:15 +02:00
jjwbruijn
7faeb2eb54 slideshow builder for eeprom 2023-10-14 23:08:36 +02:00
Jelmer
5318f1fdc4 eeprom support OEPL-Flasher.py 2023-10-14 23:00:35 +02:00
Jelmer
4bf61c1dd0 added eeprom support for tag flasher 2023-10-14 22:59:11 +02:00
atc1441
c4beaa51c8 Model name typo 2023-10-13 11:07:31 +02:00
atc1441
26598fc408 Added NanoC6 Infos and Board definition 2023-10-12 17:20:42 +02:00
Nic Limper
06f3a5d524 small cosmetic changes 2023-10-12 17:06:57 +02:00
atc1441
0bed91ecc2 Update OpenEPaperLink_Yellow_AP_ESP32_C6_Gerber.zip 2023-10-12 13:26:40 +02:00
B0rax
1e76d690ec Add circle and rounded box to json template (#143) 2023-10-08 15:47:30 +02:00
Nic Limper
9c06cdf2d7 small fix for fw compile test 2023-10-08 15:44:02 +02:00
Nic Limper
7a0ca319e7 timing fix in getting version info for ota 2023-10-07 22:21:54 +02:00
Nic Limper
c095f4c881 created Python port for packagebinaries.php to create Tag_FW_Pack.bin 2023-10-06 22:30:09 +02:00
Nic Limper
c586c9f541 added negative sign to fonts; small improvements 2023-10-06 13:14:22 +02:00
Moritz Wirger
6c4f8ef35b Add ap_date and ap_time vars (#142)
* Add ap_date and ap_time vars
* Add convenience creation function for Timer
* Optimize timer
* Document timer
2023-10-04 21:43:28 +02:00
Nic Limper
c403c06b09 fix AP not responding + add more logs to investigate crashes 2023-10-04 15:33:22 +02:00
Nic Limper
ddd043f44f update esp32-C6 binaries 2023-10-02 15:09:29 +02:00
Nic Limper
81cc5ccc9a tiny oops 2023-10-02 13:51:11 +02:00
Nic Limper
be325b0e62 forgot to add gzipped files with previous commit 2023-10-02 13:45:03 +02:00
Nic Limper
3621c84cc4 various small fixes
- neopixel patterns optimized. The 'breathing' led state now is green colored if everything is okay, and blue if there are one or more tags timed out.
- time zone is now set before wifi connect to show correct time zone in the logs during startup
- concurrent image upload POST is now blocked. If an upload is in progress while you do a second http POST, http status 409 Conflict is returned.
- small synchronisation bug fix in web interface on loading tag type
- dialog window close bugfix in painter
- image upload is now logged in /log.txt
2023-10-02 13:43:53 +02:00
Nic Limper
ed82795e5f tweak timings 2023-10-02 11:54:36 +02:00
Marcel
5b9f8b324e New hardware profile: PoE AP (#141)
* New hardware profile: PoE AP

- added harware profiles for C6 firmware in menuconfig
- added free PSRAM stat in webinterface

* fix(fsfree): fixed var type of freesize of FS
2023-09-29 02:46:11 +02:00
Nic Limper
db80d23b52 several small improvements
- neopixel idle color now represents AP status
- option to invert colors (advanced options at tag card)
- filename dropdown in tag card when a filename is expected
- redrawing pending instead of raw, if previews are off and tag reboots
- tft brightness setting independent from neopixel brightness
2023-09-29 00:11:44 +02:00
jjwbruijn
125922f8e7 M2 2.2 - RFW for added RF Wake 2023-09-28 17:29:00 +02:00
Nic Limper
aa484575b8 update update screen to new design; ability to choose repo source for OTA 2023-09-28 11:40:29 +02:00
jjwbruijn
fa97daef3c M2 FW 2.2 - Preload and buttons 2023-09-28 01:03:29 +02:00
Jonas Niesner
0c591660bc Fix wrong domain
fixes #140
2023-09-27 20:33:54 +02:00
Jelmer
c8fb0ca4de ESP: Added feature to preload images 2023-09-27 14:04:48 +02:00
jjwbruijn
87ce823776 added new image type arguments for M3 2023-09-27 12:24:08 +02:00
Jonas Niesner
7fe4a1e6ad Rename bin files to the new standard (#139)
* Update release.yml
* Update genfilelist.py
* Rename files
* Create .gitignore
2023-09-27 08:33:32 +02:00
Nic Limper
29b8c9bc21 small fix in data parser 2023-09-26 22:53:59 +02:00
Moritz Wirger
2e44889b19 Add custom tag data parser (#132)
* Add formatString convenience function

* Use String& for wsLog, wsErr and wsSerial

* Add tag data parser and parse tag data

* Make logLine use String&

* Fix issue with formatString

* Reuse payloadLength in processTagReturnData

* Fix parsing of unsigned/signed inetegers and cleanup

* Use c++17 standard

* Cleanup logging
2023-09-26 22:51:57 +02:00
Nic Limper
4d08454fff Update README.md 2023-09-26 20:30:03 +02:00
Nic Limper
f131b5ce84 Update README.md 2023-09-26 20:29:23 +02:00
Nic Limper
33ba6a7aa7 updated web interface design 2023-09-26 10:27:57 +02:00
Nic Limper
75c6a6c0f9 previews now also show for tags connected to external AP; removed extra debug msg 2023-09-24 21:34:30 +02:00
Jonas Niesner
f7e2025487 M3 display led code fixes 2023-09-23 22:47:56 +02:00
Nic Limper
a91dd5c2a2 fix hangs on esp32-s2; refactor task runner; moved some json objects from the stack to the heap
temporary, there's some extra debug info on the terminal. Will be removed again in the near future.
2023-09-23 18:40:28 +02:00
Nic Limper
0ba287f734 mutex on file write; prevent other AP from stealing tag content; bigger heap for timeTask 2023-09-22 19:42:36 +02:00
Nic Limper
ad52c64b94 typo 2023-09-22 11:13:48 +02:00
Nic Limper
8c06bb04f3 typo 2023-09-22 11:13:15 +02:00
Nic Limper
07807afe08 add 4.2" mini stands design 2023-09-22 11:11:36 +02:00
onkelfunny
eb173e355f avoid loading *.raw files when preview is disabled (#136)
by @onkelfunny
2023-09-21 17:03:21 +02:00
onkelfunny
b792b71608 default configurable tag content (#134)
by @onkelfunny
2023-09-21 13:51:03 +02:00
Nic Limper
b0715fae97 cosmetic 2023-09-20 10:24:40 +02:00
Nic Limper
6e326009c3 finetuning C6 flashing, automatic retry on failing download 2023-09-20 10:15:55 +02:00
Jelmer
0a43c601fe M3 FW 0.1.6-beta3 2023-09-20 00:51:31 +02:00
Nic Limper
f92448992e remove debug info 2023-09-20 00:26:36 +02:00
Nic Limper
2d84583797 update button: download latest esp32-c6 firmware + flash from esp32-s3 2023-09-19 20:24:57 +02:00
atc1441
fac67eac7e Fixed Pull-up for C6 in YellowAP PCB for self flashing the C6 from ESP32-S3 2023-09-18 21:51:28 +02:00
Nic Limper
6cee005e92 esp32-c6 binaries for flashing by esp32-s3 2023-09-18 20:11:56 +02:00
Nic Limper
e68e549eaf bugfix, prevent duplicate dhcp hostnames 2023-09-15 09:50:56 +02:00
Jelmer
3eb4b94b06 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-09-14 12:38:03 +02:00
Jelmer
9951dc5ce5 added and updated M3 jigs 2023-09-14 12:37:47 +02:00
Nic Limper
c53f33f8ec bugfix calculating expected next checkin 2023-09-11 20:40:05 +02:00
Nic Limper
abbc636948 custom partition table (with 3MB littlefs) for C6 2023-09-11 14:01:42 +02:00
Nic Limper
7e32a1a197 remove unused preview files from /current folder at startup 2023-09-11 13:50:37 +02:00
Nic Limper
95d0cf6804 esp-serial-flasher library (altered from the original) 2023-09-11 00:57:19 +02:00
Nic Limper
a92e0eb5e6 flashing ESP32-C6 from ESP32 via serial connection from webinterface
To flash the C6, place bootloader.bin, partition-table.bin and OpenEPaperLink_esp32_C6.bin in the file system root.
APconfig -> update -> advanced options -> update ESP32-C6
This should also work with a previous unconfigured C6.
Compatible with Yellow-AP.
2023-09-11 00:48:08 +02:00
Jelmer
c6c3c4f9f6 Update README.md 2023-09-10 22:45:48 +02:00
Nic Limper
2e64ed2f16 set dhcp hostname 2023-09-09 19:01:18 +02:00
Nic Limper
2780b7ce36 only send fast lut to capable tags 2023-09-08 23:58:52 +02:00
Nic Limper
9af2bd2a92 tagReturnData for C6 AP. It compiles, but other than that, untested 2023-09-08 20:27:18 +02:00
Nic Limper
92ff939adc bugfix gethwtype 2023-09-08 17:23:19 +02:00
Nic Limper
83ff8564a7 'flash led' command in context menu of webinterface 2023-09-08 17:07:48 +02:00
Jelmer
dc33ff5854 ESP32 return-data support 2023-09-08 11:19:33 +02:00
jjwbruijn
4176252b51 ZBS Tag Return-data support 2023-09-08 11:16:16 +02:00
Moritz Wirger
36c3c45510 Json url file template (#128)
json template url + file implementation. 
The file contains the json template, and can contain variables that will be extracted from the json in the url. The url is fetched at regular intervals.
2023-09-08 11:06:15 +02:00
jjwbruijn
abb9b195d3 updated oepl-wide definitions 2023-09-08 00:10:26 +02:00
Jonas Niesner
a3e30c549e Multiple 2.2" and build script improvements + housekeeping (#127)
* Update build-test.yml

* Update build-test.yml

* Update release.yml

* Create hextobin.py

* Update preparefiles.py

* Delete ARM_Tag_FW/nrf52811_Platformio_2.9 directory

* Delete ARM_Tag_FW/nrf52811_Platformio_7.4 directory

* Update release.yml

* Delete binaries/Tag_FW_M3_7.5.hex

* Delete binaries/Tag_FW_M3_2.9.hex

* Fix mac for 2.2"

* Fix bug in the release script and add comment about future plans

* fix 2.2" mac again
2023-09-04 22:26:52 +02:00
Jonas Niesner
02cd65d383 Add 2.2" to content cards 2023-09-04 19:44:52 +02:00
Jelmer
bc394e0d26 Added MD5 verification for nRF-based tags 2023-09-04 15:22:22 +02:00
Jelmer
22d3001996 added 6.0 jig 2023-09-04 12:54:21 +02:00
Jelmer
efb5a3cb55 added OTA for M3 tags 2023-09-04 01:18:33 +02:00
Jonas Niesner
8055de91f3 Merge pull request #125 from jonasniesner/master
Add multiple 2.2" M3 tag files
2023-09-03 20:09:56 +02:00
Jonas Niesner
0226f01ddb Add 2.2" tag type 2023-09-03 20:08:38 +02:00
Jonas Niesner
9cfadf1670 Add M3 2.2" to release scripts 2023-09-03 19:34:15 +02:00
Jonas Niesner
a1d06a2d34 Merge branch 'jjwbruijn:master' into master 2023-09-03 19:33:01 +02:00
Jonas Niesner
27665174b7 Merge branch 'master' of github.com:jonasniesner/OpenEPaperLink 2023-09-03 19:32:13 +02:00
Jonas Niesner
c23c3049bf 2.2" M3 config added 2023-09-03 19:31:38 +02:00
atc1441
55fe95903a Added C6 flasher, The S3 can flash the connected ESP32-C6 via UART 2023-09-03 10:47:16 +02:00
Jelmer
ea39ea0fc8 Merge pull request #124 from milo526/master
extend patch_mac script
2023-09-02 22:24:38 +02:00
Milo Cesar
f966bee5af extend patch_mac script 2023-09-02 22:19:46 +02:00
Jonas Niesner
8f9a9e44c2 Merge pull request #6 from jjwbruijn/master
Add NRF firmware building to release scripts
2023-09-02 18:59:30 +02:00
Jonas Niesner
214ddbf4e0 Merge branch 'master' into master 2023-09-02 18:59:17 +02:00
Jonas Niesner
65431e587e Update release.yml 2023-09-02 18:57:55 +02:00
Jonas Niesner
52fd9f1232 Update main.cpp 2023-09-02 18:38:42 +02:00
Jonas Niesner
76345fa794 Update release.yml 2023-09-02 17:59:30 +02:00
Jonas Niesner
12f5add21b Add files via upload 2023-09-02 17:57:12 +02:00
Jonas Niesner
eccd309a61 Add NRF firmware building to release scripts 2023-09-02 16:17:17 +02:00
Jonas Niesner
6a58d0143c Update release.yml 2023-09-02 15:20:46 +02:00
Jonas Niesner
70b4bd197c Update release.yml 2023-09-02 15:18:16 +02:00
jjwbruijn
aad5fe71eb updated beta 7.5" fw 2023-09-02 12:26:40 +02:00
Jelmer
8f7ec46f68 Merge pull request #122 from jonasniesner/master
M3 firmware improvements
2023-09-02 11:46:34 +02:00
Jonas Niesner
733078147d Merge branch 'jjwbruijn:master' into master 2023-09-02 11:40:58 +02:00
Jonas Niesner
ae8bc98619 Merge branch 'master' of github.com:jonasniesner/OpenEPaperLink 2023-09-02 11:38:48 +02:00
Jonas Niesner
bbe903bf90 Led LUT for M3 2023-09-02 11:36:07 +02:00
Nic Limper
73ecdd09b4 tiny bugfixes 2023-09-02 11:17:42 +02:00
Jonas Niesner
2674b733db Merge branch 'jjwbruijn:master' into master 2023-09-01 20:17:06 +02:00
Nic Limper
b919445ecc highspeed communication between S3<>C6 2023-08-31 21:10:36 +02:00
Nic Limper
eba0ea8a89 simple http call to test the led flasher 2023-08-31 20:12:49 +02:00
Nic Limper
15719126b8 render raw preview files within the file editor 2023-08-31 12:19:04 +02:00
Nic Limper
e45693bfe0 new version of 88MZ100 7.4" tag firmware + patch_mac.py for easy mac change
No need for HxD anymore for this firmware. See https://github.com/jjwbruijn/OpenEPaperLink/wiki/88MZ100-Programming-and-interfacing
2023-08-31 02:44:34 +02:00
Nic Limper
ab83cb03cc improvements for yellow ap / esp32-c6
- Wifi connection progress is now visible on the TFT
- passthrough serial logging from the C6 to the S3 terminal for easier debugging
- no checks on force_flash and APtag-firmware version when C6 is used
2023-08-31 02:13:45 +02:00
Nic Limper
714f7fffae clean up
- removed the custom printf function (inherited from the zbs code, but easier to just use the native printf)
- led flash timer
- proper HW_TYPE set, now reported as 0xC6
2023-08-30 22:20:08 +02:00
Nic Limper
9929d1646f small fixes
- fixed context menu position
- fixed free space sometimes displays 0
- added 12 byte payload to sendCommand
2023-08-29 22:11:05 +02:00
Jonas Niesner
b423ed4163 Update build-test.yml 2023-08-29 18:45:22 +02:00
Jonas Niesner
71d8aba77a NFC + button wake and LED 2023-08-28 15:41:19 +02:00
Jonas Niesner
81f5345237 Improved M3 firmware try 6 2023-08-28 13:54:59 +02:00
Jonas Niesner
bfe3561553 Improved M3 firmware try 5 2023-08-28 13:04:11 +02:00
Jonas Niesner
66a6a204c1 Improved M3 firmware try 2 2023-08-28 12:49:29 +02:00
Jonas Niesner
a6af0deaab Improved M3 firmware 2023-08-28 12:43:40 +02:00
Nic Limper
c9cc33f3d6 Update README.md 2023-08-27 22:34:40 +02:00
Jelmer
57c9962a67 fixed an especially dumb mistake in the tag flashr 2023-08-26 22:32:29 +02:00
Jelmer
c1e53e7c4f Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-26 22:21:10 +02:00
Jelmer
505e3d38af improved nRF flashing 2023-08-26 22:21:03 +02:00
Jelmer
00432bd9b5 Merge pull request #118 from kquinsland/bug/c6-include-path-fix
Make path to `soc/lp_uart_reg.{c,h}` consistent
2023-08-26 21:34:30 +02:00
karl
3a1c34f3a6 Make path to soc/lp_uart_reg.{c,h} consistent
Using _just_ the `/` character makes the paths "universal".

On *nix, `/` is the path separator and windows has support for `/` internally.
2023-08-26 12:32:24 -07:00
Jelmer
51087fa400 Merge pull request #116 from kquinsland/feat/add-m3-2.2-jig
Add my 2.2 inch pogo jig
2023-08-26 21:19:59 +02:00
Karl Quinsalnd
073972875a Add my 2.2 inch pogo jig 2023-08-26 12:10:05 -07:00
Jelmer
de38662a2a New clamp design 2.9 2023-08-26 20:48:26 +02:00
Jelmer
69bf4fe036 M3-2.2 Jig 2023-08-26 13:09:11 +02:00
Jelmer
fcedb8256a Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-24 22:57:06 +02:00
Jelmer
6252f81888 Added some M2 7.5 stuff 2023-08-24 22:57:02 +02:00
Jelmer
3223d7c861 Another update on the readme for tag flasher 2023-08-24 22:20:43 +02:00
Jelmer
99a36c4eb8 Updated Tag-Flasher README.md 2023-08-24 22:10:35 +02:00
Jelmer
3c77e375d9 Added the tag-flasher 2023-08-24 21:37:32 +02:00
Jelmer
891b7a83be Tag_Flasher README.md 2023-08-24 21:16:30 +02:00
Nic Limper
09f6f7b4b1 small fix in ota.js 2023-08-24 12:59:31 +02:00
Jelmer
ec7bac1f34 Moved flasher script, added support for 88mz100 2023-08-23 12:52:58 +02:00
Nic Limper
0df91096c2 little oops 2023-08-23 01:35:48 +02:00
Nic Limper
79efe473bf various small fixes
- clean up webproxy getExtUrl
- bugfix init multicast on wifi reconnect
- add ip address of remote AP that's taken over a tag
- renamed button 'edit contentFS' to 'file system'
2023-08-23 01:29:52 +02:00
Nic Limper
034521682c get rid of using eps32 as web proxy 2023-08-22 17:05:23 +02:00
Nic Limper
9ad847eb53 Update content_cards.json.gz 2023-08-22 13:15:03 +02:00
Nic Limper
f268c48717 add wifi events to log.txt 2023-08-22 13:06:42 +02:00
Nic Limper
a0ebf0d255 weather values in fahrenheit/mph 2023-08-21 01:05:43 +02:00
Nic Limper
6fcfe02b28 updated .gz-files for www folder 2023-08-20 20:18:58 +02:00
Nic Limper
2edbf27033 various fixes / sleep at night / resend image at tag boot
- apconfig: configure night time, where the system is not updating tags, and the tags are sleeping
- fixed bug calculating expected checkin
- throttle down apinfo update to once per minute
- fixed too many concurrent requests getting tagtypes
- resend current image when a tag reboots and the content type is 'static image' (all other content types were already regenerating the content)
- fixed timing of main loop
2023-08-20 20:16:34 +02:00
Nic Limper
46fb23b70f drop json files to a tagcard + small fixes 2023-08-19 20:31:25 +02:00
Moritz Wirger
fce6c16153 Optimize tagDB and reduce RAM usage (#113)
* Reduce code size by removing nullptr assignments

* Optimize tagDB for loops

* More tagDB optimizations

* Remove static from language arrays reducing RAM by 5128b

- Reduces Flash by 13060b

* Add missing extern in tag_db.h

* Fix deprecation warning of sntp.h

* Remove static from contentmanager, reduces RAM by 184b

* Use string reference in prepareDataAvail

- Remove some unneeded buffers
- Remove some gotos
2023-08-17 10:06:21 +02:00
atc1441
a31e1453d0 Now resending the Pending data on Reset of the Connected AP 2023-08-15 13:49:09 +02:00
Nic Limper
d17502cb63 contextmenu: right-click on a tagcard 2023-08-15 12:42:59 +02:00
atc1441
828679b6f3 Update README.md 2023-08-14 23:43:23 +02:00
atc1441
bff6794303 Added Yellow AP Gerber files 2023-08-14 21:40:34 +02:00
atc1441
2f86ea54d0 Precompiled ESP32-C6 AP 2023-08-14 21:28:03 +02:00
atc1441
80e0d9e5dd Added ESP32-C6 AP Release :) 2023-08-14 21:25:38 +02:00
atc1441
4d8cfeae63 Added nRF52811 AP Port 2023-08-14 12:12:44 +02:00
atc1441
3271f399c9 Auto template for AP Display disabled as currently to many refreshes break and reset the AP 2023-08-14 12:02:32 +02:00
atc1441
862c08c00b Set AP Info screen as default template on boot again to know IP of AP 2023-08-13 22:43:59 +02:00
Nic Limper
77cbf92281 bugfix getlocation 2023-08-13 01:48:32 +02:00
Moritz Wirger
c4022e45f9 Fix weather icons exception (#114) 2023-08-13 01:00:47 +02:00
atc1441
a13c220565 Fixed countdown via negative count value 2023-08-12 21:43:37 +02:00
Nic Limper
3989ecc3a3 bugfix date display 2023-08-12 21:17:08 +02:00
Nic Limper
cb0f029900 Update build-test.yml
don't build all small variations. Just the minor platforms, the rest will work.
2023-08-12 21:11:33 +02:00
Nic Limper
443714e9dc build fixes 2023-08-12 20:58:25 +02:00
Nic Limper
f3f163fa00 Revert "Ziped web files"
This reverts commit 8848cfc0f8.
2023-08-12 20:19:01 +02:00
Bot
8848cfc0f8 Ziped web files 2023-08-12 17:16:45 +00:00
Moritz Wirger
6c91c78aa1 Refactor contentmanager (#112)
* Start contentmanager cleanup

- Make destination constant
- Remove unneeded asignments
- Improve loops
- Move printHeap function into util

* Refactor contentmanager::drawNew

* Optimize contentManager::replaceVariables

* Fix missing const in prepareCancelPending

* Refactor drawDate

* Refactor drawWeather, drawForecast & getLocation

- Generalize http get json function

* Add util function for printing largest free block

* Reuse weather icons for both drawWeather & drawForecast

* Make httpGetJson timeout const

* Reafctor more functions

* Add few more const

* Fix spelling mistake

* Add util for debugging streams

- Add util for checking if strings are empty or contain null
- Fix file and string checks

* Remove leftover debug print
2023-08-12 16:57:42 +02:00
Nic Limper
98baa020ff bugfix ap info screen 2023-08-12 16:17:06 +02:00
Nic Limper
56e1e9e6b6 small fixes
- build in led on esp32-s2 active low
- floyd steinberg dithering improved
- add tokyo time zone
2023-08-12 13:18:22 +02:00
jjwbruijn
2817aa7e38 Added 7.5 OTA img 2023-08-12 09:17:55 +02:00
jjwbruijn
2292aeaf7e another beta of the 88mz100 7.5 fw 2023-08-12 02:26:33 +02:00
Nic Limper
3472b5d4b6 drop image files to upload 2023-08-12 01:11:25 +02:00
Moritz Wirger
19f6a093d3 Cleanup ota files (#111)
- Constify everything
- Remove duplicate code
- Fix warnings in js
- Reduces bin size from 1283453 to 1283273 bytes
2023-08-12 00:37:26 +02:00
Nic Limper
d6734a7f79 bugfix database backup button 2023-08-11 22:42:02 +02:00
Nic Limper
da487fbc5f gzipped files in /www are now stored deterministic, without timestamp 2023-08-11 19:46:22 +02:00
Moritz Wirger
3b7fd7d1f6 Fix a few js warnings in main.js (#108)
* Fix indentation of content_cards json
* Fix multiple warnings in main.js
2023-08-11 19:39:20 +02:00
Nic Limper
f4273630ee rework of apinfo screen + variables in jsontemplate
- AP info screen content card. Can run on any tag.
- now, you can use {variables} in the 'text' entries in a json template. You can set variables via a http call. If you update a variable, all tags with a json template containing that variable get updated.
- font name in json template is more flexible. You can just use 'filename.ttf' or 'filename.vlw'. A full path is still possible.
- colors in the json template can now be set using #rrggbb color values, and using 'black', 'white' or 'red'.
- added direct output for the TFT display for the yellow esp32-s3. No file writes needed.
- added POST variable 'ttl' to json template upload and image upload, to set the next checkin time
- added /variables-demo.html to demonstrate the variables.
- json templates received from jsonupload are now saved in /current, and reused.
- known issue: 'backup db' button doesn't work due to some browser policy change. Fixing.
thanks to @steinwedel for the inspiration on the variables and some other fixes.
2023-08-11 18:46:46 +02:00
Jelmer
0cbb9e770e esp32 deep sleep support 2023-08-10 23:22:24 +02:00
jjwbruijn
9dfb37b376 Merge branch 'master' of github.com:jjwbruijn/OpenEPaperLink 2023-08-10 22:38:07 +02:00
jjwbruijn
e457475ea7 zbs243 tag FW 2.0 - added deepsleep 2023-08-10 22:26:50 +02:00
Jonas Niesner
806b2dc9e0 Merge pull request #107 from enwi/symlinks
Add batch for generating symlinks on windows
2023-08-10 22:18:48 +02:00
Jonas Niesner
2b7fc93043 Update release.yml 2023-08-10 22:16:27 +02:00
Moritz Wirger
6a711c99eb Add batch for generating symlinks 2023-08-10 21:49:55 +02:00
Nic Limper
ffd0acff72 tft driver for yellow board 2023-08-09 23:40:39 +02:00
Jelmer
a9c9812525 Merge pull request #104 from AndreKR/3dp-shelf-holder
Add 3D-printed shelf holder
2023-08-09 22:44:12 +02:00
André Hänsel
03ce036083 Accessories: Image of the shelf holder 2023-08-09 22:39:28 +02:00
André Hänsel
a98ad537ea Accessories: Source file for the shelf holder 2023-08-09 22:39:19 +02:00
André Hänsel
2726b4d2fe Accessories: Add a shelf holder
This adds a shelf holder for shelves with a thickness of 2 cm.
2023-08-09 22:38:03 +02:00
Jonas Niesner
fd5adb40f8 Typo fix 2023-08-09 21:32:45 +02:00
Jonas Niesner
89346b5d77 Update and rename esp32-build-test.yml to build-test.yml 2023-08-09 18:03:29 +02:00
Nic Limper
7ac57577df prelimary tagtype def for EL029H3WRA (M3 2.9")
I will finetune the content positions later
2023-08-08 17:31:30 +02:00
Nic Limper
09f7466f6f new flexible tagtype definition
- new: tagtypes are be defined via json in /tagtypes instead of hardcoded
- content template is moved to the tagtype definition
- optimalisation of spr2buffer (also uses psram now, if available)
- bugfixes in spiffseditor
- size fix in painter screen for large screens
2023-08-08 16:31:20 +02:00
atc1441
55e50b1920 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-08 16:00:25 +02:00
atc1441
7cb5e13a7f Added compiled version of 7.4" 2023-08-08 16:00:05 +02:00
Jonas Niesner
6f08af2c67 Create 32MB_partition table.csv 2023-08-07 17:30:07 +02:00
Jonas Niesner
e185ddd99b Add OutdoorAP 2023-08-07 16:59:47 +02:00
atc1441
3079101c48 Tag DB Size was only 8bit now 32bit, need to be fixed in further UDP usage later as well 2023-08-07 11:53:28 +02:00
atc1441
0b66a23ce4 Added Yellow AP basic parts, for now using Arduino GFX for simplicity 2023-08-06 23:35:30 +02:00
Nic Limper
41c7cb843f cleanup non-.gz files in www folder 2023-08-05 22:51:38 +02:00
Nic Limper
c43e71288d delete files carefully to not brick the thing if update fails 2023-08-05 22:11:45 +02:00
Nic Limper
66cc62339f fix aligning U8G2 fonts / improv protocol fix 2023-08-05 22:05:33 +02:00
atc1441
84bfb18261 Update cc2531_OEPL.c 2023-08-05 15:21:13 +02:00
Nic Limper
ab3cef8dda Update readme.md 2023-08-04 11:30:01 +02:00
Nic Limper
c831f07b6e group/sort/filter tag list 2023-08-03 23:15:05 +02:00
atc1441
ba39f60e69 Added Sonoff ZB Bridge-P as Board 2023-08-03 23:09:21 +02:00
atc1441
f409f493ec Added CC2531 EOPL Port plus the modded python station by foorschtbar 2023-08-03 18:53:30 +02:00
Nic Limper
df783c6f8f ability to mirror tags
mirrored tags don't take file system space (f they are local to the AP), and don't take time to generate. They share their buffer with the source tag.
2023-08-03 12:37:29 +02:00
Nic Limper
f0e4d25d36 use barcode scanner to select a tag 2023-08-02 20:04:55 +02:00
Nic Limper
b4bf060a51 json template is now streaming (both file and url)
'unlimited' size
2023-07-31 22:35:00 +02:00
Nic Limper
e3407468ea weather icons via truetype
Don't forget to update the file system: added .ttf font, deleted some .vlw fonts.
Saves about 144kB.
2023-07-31 20:25:31 +02:00
Nic Limper
8daff632ba truetype: more floats -> better rendering 2023-07-31 20:22:50 +02:00
Nic Limper
21a52e9b17 truetype fixes
- fixed curves using intermediate points
- now uses ascender to find baseline
- now uses unitsPerEm for font size calculations
rendering is not perfect yet, probably mainly due to rounding issues
2023-07-31 19:02:05 +02:00
Nic Limper
f9b4d163bc cleanup and gzip web files
- clean up unnecessary files
- fix ota update, maybe preventing timeouts
- new 'wwwroot' folder for the web source files, and python script to gzip the files to the /data/www folder
- run gzip_wwwfiles.py to compress the files in wwwroot into /data/www
2023-07-29 20:47:12 +02:00
Nic Limper
a78f2e3af5 added truetype fonts 2023-07-29 14:47:01 +02:00
29343 changed files with 6020312 additions and 2614277 deletions

54
.github/workflows/build-test.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: Firmware build test
on: [push,pull_request]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install intelhex
run: pip install --upgrade intelhex
# - name: Build Simple_AP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment Simple_AP
# pio run --target buildfs --environment Simple_AP
- name: Build OpenEPaperLink_Mini_AP
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_Mini_AP
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
- name: Build OpenEPaperLink_AP_and_Flasher
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_AP_and_Flasher
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
- name: Build ESP32_S3_16_8_YELLOW_AP
run: |
cd ESP32_AP-Flasher
pio run --environment ESP32_S3_16_8_YELLOW_AP
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
- name: OpenEPaperLink_Mini_AP_v4
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_Mini_AP_v4
pio run --target buildfs --environment OpenEPaperLink_Mini_AP_v4

View File

@@ -1,57 +0,0 @@
name: ESP32 firmware builf test
on: [push,pull_request]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Build Simple_AP
run: |
cd ESP32_AP-Flasher
pio run --environment Simple_AP
pio run --target buildfs --environment Simple_AP
- name: Build OpenEPaperLink_Mini_AP
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_Mini_AP
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
- name: Build OpenEPaperLink_Nano_AP
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_Nano_AP
pio run --target buildfs --environment OpenEPaperLink_Nano_AP
- name: Build OpenEPaperLink_AP_and_Flasher
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_AP_and_Flasher
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
- name: Build Wemos_d1_mini32_AP
run: |
cd ESP32_AP-Flasher
pio run --environment Wemos_d1_mini32_AP
pio run --target buildfs --environment Wemos_d1_mini32_AP
- name: Build M5Stack_Core_ONE_AP
run: |
cd ESP32_AP-Flasher
pio run --environment M5Stack_Core_ONE_AP
pio run --target buildfs --environment M5Stack_Core_ONE_AP

View File

@@ -21,69 +21,30 @@ jobs:
with:
python-version: '3.9'
# - name: Commit zipped files
# run: |
# git config --global user.name 'Bot'
# git config --global user.email "bot@openepaperlink.de"
# git commit -am "Zipped web files"
# git push origin HEAD:master
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install intelhex
run: pip install --upgrade intelhex
- name: Install esptool
run: pip install esptool
- name: create folders
run: |
mkdir espbinaries
- name: Build firmware for Simple_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment Simple_AP
pio run --target buildfs --environment Simple_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP/boot_app0.bin
cp .pio/build/Simple_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP/firmware.bin
cp .pio/build/Simple_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP/bootloader.bin
cp .pio/build/Simple_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP/partitions.bin
cp .pio/build/Simple_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/Simple_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp Simple_AP/firmware.bin espbinaries/Simple_AP.bin
cp Simple_AP/merged-firmware.bin espbinaries/Simple_AP_full.bin
- name: Build firmware for Wemos_d1_mini32_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment Wemos_d1_mini32_AP
pio run --target buildfs --environment Wemos_d1_mini32_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/boot_app0.bin
cp .pio/build/Wemos_d1_mini32_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/firmware.bin
cp .pio/build/Wemos_d1_mini32_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/bootloader.bin
cp .pio/build/Wemos_d1_mini32_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/partitions.bin
cp .pio/build/Wemos_d1_mini32_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp Wemos_d1_mini32_AP/firmware.bin espbinaries/Wemos_d1_mini32_AP.bin
cp Wemos_d1_mini32_AP/merged-firmware.bin espbinaries/Wemos_d1_mini32_AP_full.bin
- name: Build firmware for M5Stack_Core_ONE_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment M5Stack_Core_ONE_AP
pio run --target buildfs --environment M5Stack_Core_ONE_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/boot_app0.bin
cp .pio/build/M5Stack_Core_ONE_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/firmware.bin
cp .pio/build/M5Stack_Core_ONE_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/bootloader.bin
cp .pio/build/M5Stack_Core_ONE_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/partitions.bin
cp .pio/build/M5Stack_Core_ONE_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x2B0000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp M5Stack_Core_ONE_AP/firmware.bin espbinaries/M5Stack_Core_ONE_AP.bin
cp M5Stack_Core_ONE_AP/merged-firmware.bin espbinaries/M5Stack_Core_ONE_AP_full.bin
# - name: Zip web files
# run: |
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
# python gzip_wwwfiles.py
- name: Build firmware for OpenEPaperLink_Mini_AP
run: |
@@ -120,6 +81,10 @@ jobs:
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin
cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin
# - name: move files for big APs
# run: |
# cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/
- name: Build firmware for OpenEPaperLink_AP_and_Flasher
run: |
@@ -138,12 +103,84 @@ jobs:
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_AP_and_Flasher/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin
cp OpenEPaperLink_AP_and_Flasher/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin
- name: Build firmware for ESP32_S3_16_8_YELLOW_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_16_8_YELLOW_AP
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/boot_app0.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/firmware.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/bootloader.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/partitions.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_16_8_YELLOW_AP/firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP.bin
cp ESP32_S3_16_8_YELLOW_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP_full.bin
- name: Build firmware for ESP32_S3_C6_NANO_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_C6_NANO_AP
pio run --target buildfs --environment ESP32_S3_C6_NANO_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/boot_app0.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/firmware.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/bootloader.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/partitions.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_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_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 OpenEPaperLink_PoE_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_PoE_AP
pio run --target buildfs --environment OpenEPaperLink_PoE_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/boot_app0.bin
cp .pio/build/OpenEPaperLink_PoE_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/firmware.bin
cp .pio/build/OpenEPaperLink_PoE_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/bootloader.bin
cp .pio/build/OpenEPaperLink_PoE_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/partitions.bin
cp .pio/build/OpenEPaperLink_PoE_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode qio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xD000 boot_app0.bin 0x10000 firmware.bin 0x410000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_PoE_AP/firmware.bin espbinaries/OpenEPaperLink_PoE_AP.bin
cp OpenEPaperLink_PoE_AP/merged-firmware.bin espbinaries/OpenEPaperLink_PoE_AP_full.bin
- name: Build firmware for OpenEPaperLink_Mini_AP_v4
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Mini_AP_v4
pio run --target buildfs --environment OpenEPaperLink_Mini_AP_v4
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/boot_app0.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/firmware.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/bootloader.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/partitions.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4
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_Mini_AP_v4/firmware.bin espbinaries/OpenEPaperLink_Mini_AP_v4.bin
cp OpenEPaperLink_Mini_AP_v4/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_v4_full.bin
- name: generate release json file
run: |
mkdir jsonfiles
python genfilelist.py ${{ github.ref_name }} $GITHUB_REPOSITORY $GITHUB_SHA
- name: Add file lists to release
uses: svenstaro/upload-release-action@v2
with:
@@ -152,7 +189,27 @@ jobs:
tag: ${{ github.ref }}
file_glob: true
overwrite: true
# this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed)
- name: Build firmware for Tag_Flasher
run: |
cd Tag_Flasher/ESP32_Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment S2_Tag_Flasher
pio run --target buildfs --environment S2_Tag_Flasher
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/boot_app0.bin
cp .pio/build/S2_Tag_Flasher/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/firmware.bin
cp .pio/build/S2_Tag_Flasher/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/bootloader.bin
cp .pio/build/S2_Tag_Flasher/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/partitions.bin
cp .pio/build/S2_Tag_Flasher/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher
esptool.py --chip esp32-s2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp S2_Tag_Flasher/firmware.bin espbinaries/S2_Tag_Flasher.bin
cp S2_Tag_Flasher/merged-firmware.bin espbinaries/S2_Tag_Flasher_full.bin
- name: Add esp bins to release
uses: svenstaro/upload-release-action@v2
with:
@@ -161,36 +218,3 @@ jobs:
tag: ${{ github.ref }}
file_glob: true
overwrite: true
- name: Add tag bins to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: binaries/*
tag: ${{ github.ref }}
file_glob: true
overwrite: true
# - name: Add www folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/www/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add fonts folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/fonts/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add data folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/*
# tag: ${{ github.ref }}
# file_glob: true

4
.gitignore vendored
View File

@@ -23,3 +23,7 @@
*.bin
*.lk
*.o
sdcc/sdcc
ESP32_AP-Flasher/.vscode/extensions.json
ARM_Tag_FW\Newton_M3_nRF52811\$PROJECT_DIR

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "ARM_Tag_FW/common/uzlib"]
path = ARM_Tag_FW/common/uzlib
url = https://github.com/pfalcon/uzlib.git
[submodule "ARM_Tag_FW/common/QRCode"]
path = ARM_Tag_FW/common/QRCode
url = https://github.com/ricmoo/QRCode

View File

@@ -1,2 +1,4 @@
build
*.axf
# Allow
#!*.bin

View File

@@ -1,72 +1,114 @@
MZ_FLASHER=python ../88MZ100_Flasher/88MZ100_Uart_flasher.py
ARMGCC=armgcc/bin/
ARMGCC=/usr/bin/
CC=$(ARMGCC)arm-none-eabi-gcc
GPLUSPLUS=$(ARMGCC)arm-none-eabi-g++
AS=$(ARMGCC)arm-none-eabi-as
OBJCOPY=$(ARMGCC)arm-none-eabi-objcopy
#-Wall
#-Wall
CC_WARNING_FLAGS=-Wall -Wformat=0 -Wattributes -Wstrict-aliasing=0
CC_FlAGS=-mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c99
CC_END_FLAGS=-lc -lnosys -L. -T mz100.ld -fPIE --specs=nosys.specs -mcpu=cortex-m3 -mthumb -Wl,--gc-sections -O0 -flto -ffunction-sections -fdata-sections -DARM_GNU
CPP_FLAGS=-lstdc++ -mcpu=cortex-m3 -g -O3 -mthumb -fdata-sections -ffunction-sections -std=c++98 -std=gnu++0x
CPP0_FLAGS=-lstdc++ -mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c++98 -std=gnu++0x
CC_FLAGS=-mcpu=cortex-m3 -g -O0 -mthumb -fdata-sections -ffunction-sections -std=c99
CC3_FLAGS=-mcpu=cortex-m3 -g -O3 -mthumb -fdata-sections -ffunction-sections -std=c99
CC_END_FLAGS=-lstdc++ -lc -lnosys -L. -T mz100/mz100.ld -fPIE --specs=nosys.specs -mcpu=cortex-m3 -mthumb -Wl,--gc-sections -O0 -flto -ffunction-sections -fdata-sections -DARM_GNU
C_SOURCES :=$(wildcard *.c)
C_EXECUTABLE :=$(C_SOURCES:.c=)
COMPORT = COM12
build: clean compile create_ota_img flash_uart_flash
build: compile
only: clean compile create_ota_img
uart: clean compile flash_uart
compile:
@mkdir -p build
@$(AS) -mcpu=cortex-m3 --gdwarf-2 -mthumb-interwork -o build/startup.o startup.S
#build: clean compile create_ota_img flash_uart_flash
#only: clean compile create_ota_img
#uart: clean compile flash_uart
@$(CC) $(CC_FlAGS) -c core_cm3.c -o build/core_cm3.o
@$(CC) $(CC_FlAGS) -c mz100_ssp.c -o build/mz100_ssp.o
@$(CC) $(CC_FlAGS) -c mz100_wdt.c -o build/mz100_wdt.o
@$(CC) $(CC_FlAGS) -c mz100_gpio.c -o build/mz100_gpio.o
@$(CC) $(CC_FlAGS) -c mz100_driver.c -o build/mz100_driver.o
@$(CC) $(CC_FlAGS) -c mz100_adc.c -o build/mz100_adc.o
@$(CC) $(CC_FlAGS) -c mz100_flash.c -o build/mz100_flash.o
@$(CC) $(CC_FlAGS) -c mz100_clock.c -o build/mz100_clock.o
@$(CC) $(CC_FlAGS) -c mz100_rtc.c -o build/mz100_rtc.o
@$(CC) $(CC_FlAGS) -c mz100_pinmux.c -o build/mz100_pinmux.o
@$(CC) $(CC_FlAGS) -c mz100_pmu.c -o build/mz100_pmu.o
@$(CC) $(CC_FlAGS) -c mz100_qspi.c -o build/mz100_qspi.o
@$(CC) $(CC_FlAGS) -c mz100_aes.c -o build/mz100_aes.o
@$(CC) $(CC_FlAGS) -c mz100_gpt.c -o build/mz100_gpt.o
@$(CC) $(CC_FlAGS) -c mz100_sleep.c -o build/mz100_sleep.o
@$(CC) $(CC_FlAGS) -c mz100_uart.c -o build/mz100_uart.o
# UZLIB
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/adler32.c -o build/adler32.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/crc32.c -o build/crc32.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/defl_static.c -o build/defl_static.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/genlz77.c -o build/genlz77.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfgzip.c -o build/tinfgzip.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinflate.c -o build/tinflate.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c uzlib/src/tinfzlib.c -o build/tinfzlib.o
# UZLIB END
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c compression.c -o build/compression.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c zigbee.c -o build/zigbee.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c ccm.c -o build/ccm.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c chars.c -o build/chars.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c drawing.c -o build/drawing.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c powermgt.c -o build/powermgt.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c syncedproto.c -o build/syncedproto.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c comms.c -o build/comms.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c settings.c -o build/settings.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c timer.c -o build/timer.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c util.c -o build/util.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c gpio.c -o build/gpio.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c nfc.c -o build/nfc.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c epd.c -o build/epd.o
@$(CC) $(CC_FlAGS) $(CC_WARNING_FLAGS) -c main.c -o build/main.o
@$(CC) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) build/main.o build/adler32.o build/crc32.o build/defl_static.o build/genlz77.o build/tinfgzip.o build/tinflate.o build/tinfzlib.o build/compression.o build/zigbee.o build/ccm.o build/chars.o build/drawing.o build/powermgt.o build/syncedproto.o build/comms.o build/settings.o build/timer.o build/util.o build/gpio.o build/nfc.o build/epd.o build/mz100_sleep.o build/core_cm3.o build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o build/startup.o -o main.axf
compile:
# @mkdir -p build
@$(AS) -mcpu=cortex-m3 --gdwarf-2 -mthumb-interwork -o build/startup.o startup.S
@$(CC) $(CC3_FLAGS) -c mz100/core_cm3.c -o build/core_cm3.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_ssp.c -o build/mz100_ssp.o
@$(CC) $(CC_FLAGS) -c mz100/mz100_wdt.c -o build/mz100_wdt.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_gpio.c -o build/mz100_gpio.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_driver.c -o build/mz100_driver.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_adc.c -o build/mz100_adc.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_flash.c -o build/mz100_flash.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_clock.c -o build/mz100_clock.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_rtc.c -o build/mz100_rtc.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_pinmux.c -o build/mz100_pinmux.o
@$(CC) $(CC_FLAGS) -c mz100/mz100_pmu.c -o build/mz100_pmu.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_qspi.c -o build/mz100_qspi.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_aes.c -o build/mz100_aes.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_gpt.c -o build/mz100_gpt.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_sleep.c -o build/mz100_sleep.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_uart.c -o build/mz100_uart.o
@$(CC) $(CC3_FLAGS) -c mz100/mz100_aon_ram.c -o build/mz100_aon_ram.o
@$(CC) $(CC3_FLAGS) -c mz100/printf.c -o build/printf.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c zigbee.c -o build/zigbee.o
# @$(CC) $(CC_FLAGS) $(CC_WARNING_FLAGS) -c ccm.c -o build/ccm.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/adler32.c -o build/uz-adler32.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/crc32.c -o build/uz-crc32.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/defl_static.c -o build/uz-defl_static.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/genlz77.c -o build/uz-genlz77.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/tinfgzip.c -o build/uz-tinfgzip.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/tinflate.c -o build/uz-tinflate.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/uzlib/src/tinfzlib.c -o build/uz-tinfzlib.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -Wno-unknown-pragmas -c ../common/QRCode/src/qrcode.c -o build/qrcode.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c compression.cpp -o build/compression.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c drawing.cpp -o build/drawing.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c epd_interface.cpp -o build/epd_interface.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c powermgt.cpp -o build/powermgt.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLASGS) -c oepl-protocol.cpp -o build/oepl-protocol.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c comms.c -o build/comms.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c ../common/md5.c -o build/md5.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c settings.cpp -o build/settings.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c mz100/timer.c -o build/timer.o
@$(CC) $(CC3_FLAGS) $(CC_WARNING_FLAGS) -c mz100/util.c -o build/util.o
@$(CC) $(CC_FLAGS) $(CC_WARNING_FLAGS) -c mz100/gpio.c -o build/gpio.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c uc8159-var-m2.cpp -o build/uc8159-var-m2.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c uc8176-var-m2.cpp -o build/uc8176-var-m2.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c userinterface.cpp -o build/userinterface.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c main.cpp -o build/main.o
@$(GPLUSPLUS) $(CPP_FLAGS) $(CC_WARNING_FLAGS) -c oepl_fs.cpp -o build/oepl_fs.o
@$(GPLUSPLUS) $(CC_END_FLAGS) $(CC_WARNING_FLAGS) \
build/main.o \
build/epd_interface.o \
build/oepl_fs.o\
build/userinterface.o \
build/printf.o \
build/mz100_aon_ram.o \
build/zigbee.o \
build/compression.o \
build/drawing.o \
build/powermgt.o \
build/oepl-protocol.o \
build/comms.o \
build/settings.o \
build/timer.o \
build/util.o \
build/md5.o \
build/gpio.o \
build/uc8176-var-m2.o \
build/uc8159-var-m2.o \
build/mz100_sleep.o \
build/core_cm3.o \
build/qrcode.o \
build/uz-adler32.o build/uz-crc32.o build/uz-defl_static.o build/uz-genlz77.o build/uz-tinfgzip.o build/uz-tinflate.o build/uz-tinfzlib.o \
build/mz100_ssp.o build/mz100_wdt.o build/mz100_gpio.o build/mz100_driver.o build/mz100_adc.o build/mz100_flash.o build/mz100_clock.o build/mz100_rtc.o build/mz100_pinmux.o build/mz100_pmu.o build/mz100_qspi.o build/mz100_aes.o build/mz100_gpt.o build/mz100_uart.o \
build/startup.o -o main.axf
@$(OBJCOPY) -v -O binary main.axf main.bin
@cat build/fs.img >> main.bin
clean:
@rm -rf build/*
@@ -83,4 +125,4 @@ flash_dump:
@$(MZ_FLASHER) $(COMPORT) read dump.bin
create_ota_img:
@$(MZ_FLASHER) img main.bin UPDT0028.BIN
@$(MZ_FLASHER) img main.bin UPDT0028.BIN

View File

@@ -4,7 +4,7 @@
#include <stdint.h>
#include "proto.h"
#include "main.h"
#include "gpio.h"
#include "mz100/gpio.h"
#define eepromByte spiByte
#define eepromPrvSelect() do { /*digitalWrite(FLASH_CS,LOW);*/ } while(0)

View File

@@ -1,96 +0,0 @@
#include <string.h>
#include "mz100.h"
#include "mz100_aes.h"
#include "mz100_driver.h"
#include "ccm.h"
static bool aesCcmOp(void* dst, const void *src, uint16_t authSrcLen, uint16_t encSrcLen, const void *key, const void *nonce, bool dec)
{
uint32_t tempB, nBytesNoMic = authSrcLen + encSrcLen, nBytesIn, nBytesOut;
const uint32_t *inD = (const uint32_t*)src;
uint32_t *outD = (uint32_t*)dst;
uint_fast8_t i;
bool success;
if (dec) {
nBytesIn = nBytesNoMic + AES_CCM_MIC_SIZE;
nBytesOut = nBytesNoMic;
}
else {
nBytesIn = nBytesNoMic;
nBytesOut = nBytesNoMic + AES_CCM_MIC_SIZE;
}
do{
AES->CTRL1.WORDVAL |= 2;
} while (!(AES->STATUS.WORDVAL & 2));
AES->CTRL2.WORDVAL |= 1;
(void)AES->CTRL2.WORDVAL;
AES->CTRL2.WORDVAL &=~ 1;
AES->CTRL1.WORDVAL = 0x0005501e + (dec ? 0x8000 : 0);
AES->IMR.WORDVAL = 0xffffffff;
for(i = 0; i < 4; i++)
AES->KEY[7 - i].WORDVAL = ((uint32_t*)key)[i];
AES->MSTR_LEN.WORDVAL = encSrcLen;
AES->ASTR_LEN.WORDVAL = authSrcLen;
for(i = 0; i < 3; i++)
AES->IV[i].WORDVAL = ((uint32_t*)nonce)[i];
AES->IV[3].WORDVAL = ((uint8_t*)nonce)[12] + 0x200; //2 byte lengths
AES->CTRL1.WORDVAL |= 1;
while (nBytesIn || nBytesOut) {
if (!(AES->STATUS.WORDVAL & 0x10) && nBytesIn) {
if (nBytesIn >= 4) {
AES->STR_IN.WORDVAL = *inD++;
nBytesIn -= 4;
}
else {
memcpy(&tempB, inD, nBytesIn);
AES->STR_IN.WORDVAL = tempB;
nBytesIn = 0;
}
}
if ((AES->STATUS.WORDVAL & 0x40) && nBytesOut) {
if (nBytesOut >= 4) {
*outD++ = AES->STR_OUT.WORDVAL;
nBytesOut -= 4;
}
else {
tempB = AES->STR_OUT.WORDVAL;
memcpy(outD, &tempB, nBytesOut);
nBytesOut = 0;
}
}
}
success = !((AES->STATUS.WORDVAL >> 11) & 7);
AES->CTRL1.WORDVAL = 0;
return success;
}
void aesCcmEnc(void* dst, const void *src, uint16_t authSrcLen, uint16_t encSrcLen, const void *key, const void *nonce)
{
aesCcmOp(dst, src, authSrcLen, encSrcLen, key, nonce, false);
}
bool aesCcmDec(void* dst, const void *src, uint16_t authSrcLen, uint16_t encSrcLen, const void *key, const void *nonce)
{
return aesCcmOp(dst, src, authSrcLen, encSrcLen, key, nonce, true);
}

View File

@@ -1,20 +0,0 @@
#ifndef _CCM_H_
#define _CCM_H_
//CCM defined for T = 4 (mic is 4 bytes), Q = 2 (max data len 65536), N = 13( nonse is 13 bytes), 128-bit AES (16 bytes of key)
//no more than 0xff00 auth data bytes allowed
#include <stdbool.h>
#include <stdint.h>
#define AES_CCM_MIC_SIZE 4
#define AES_CCM_NONCE_SIZE 13
//encrypted data follows auth data. both in and out. 4 bytes of MIC appended on the encrypt path, checke don the decrypt path
void aesCcmEnc(void* dst, const void *src, uint16_t authSrcLen, uint16_t encSrcLen, const void *key, const void *nonce);
bool aesCcmDec(void* dst, const void *src, uint16_t authSrcLen, uint16_t encSrcLen, const void *key, const void *nonce);
#endif

View File

@@ -1,410 +0,0 @@
#include "eeprom.h"
#include "chars.h"
#include "mz100_flash.h"
#include "epd.h"
#define NUM_CHARS 256
#define CANVAS_FLIP_H 1
#define CANVAS_MSB_FIRST 1
const static uint8_t mCharsImgs[];
extern uint8_t mScreenRow[];
static void charsPrvDrawCharRow(uint8_t ch, int16_t x, uint8_t imgRow, uint8_t foreColor, uint8_t backColor, uint8_t mag)
{
uint8_t c, mc, charRow = imgRow / mag, bitMask = (1 << 4) - 1;
for (c = 0; c < CHAR_WIDTH; c++)
{ // iterate over the char's columns for this row
uint8_t imgCol = ((uint8_t)((uint8_t)CHAR_WIDTH * (uint8_t)ch) & 7) + c; // sort out where in the row our data begins
uint8_t color = ((mCharsImgs[(((CHAR_WIDTH * NUM_CHARS + 7) / 8 * charRow) + (CHAR_WIDTH * ch) / 8) + (imgCol >> 3)] >> (7 - (imgCol % 8))) & 1) ? foreColor : backColor; // get the color
if (color == CHAR_COLOR_TRANSPARENT)
continue;
for (mc = 0; mc < mag; mc++, x++)
{ // set the pixel
uint8_t *dst = mScreenRow;
uint8_t bitOfst;
uint16_t c = x;
if (x < 0)
continue;
if (x >= DISPLAY_WIDTH)
break;
#if CANVAS_FLIP_H
c = DISPLAY_WIDTH - c - 1;
#endif
dst += (c * 4) / 8;
bitOfst = (c * 4) % 8;
#if CANVAS_MSB_FIRST
bitOfst = 8 - bitOfst - 4;
#endif
*dst = ((*dst) & ~(bitMask << bitOfst)) | ((color & bitMask) << bitOfst);
}
}
}
void charsDrawString(const struct CharDrawingParams *params)
{
const char *s = params->str;
int16_t x = params->x;
uint8_t ch;
while ((ch = *s++) != 0)
{
charsPrvDrawCharRow(ch, x, params->imgRow, params->foreColor, params->backColor, params->magnify);
x += (uint16_t)(uint8_t)(CHAR_WIDTH * params->magnify);
}
}
const static uint8_t mCharsImgs[] = {
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0xf0, 0x0f, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x7e, 0x36,
0x3c, 0xd8, 0x38, 0x1c, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x1e, 0x0c, 0x3c, 0x3c, 0x30, 0x7e, 0x1c, 0x7e, 0x3c, 0x3c, 0x00, 0x00,
0x06, 0x00, 0x60, 0x3c, 0x7e, 0x18, 0x7c, 0x3c, 0x78, 0x7e, 0x7e, 0x3c,
0x66, 0x3c, 0x06, 0x66, 0x60, 0x63, 0x63, 0x3c, 0x7c, 0x3c, 0x7c, 0x3c,
0x7e, 0x66, 0x66, 0x63, 0x66, 0x66, 0x7e, 0x3c, 0x60, 0x3c, 0x66, 0x00,
0x0c, 0x00, 0x60, 0x00, 0x06, 0x00, 0x1e, 0x00, 0x60, 0x18, 0x0c, 0x60,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x30, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x7e, 0x36, 0x66, 0xda, 0x6c, 0x1c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x33, 0x1c, 0x66, 0x66, 0x30, 0x60, 0x18, 0x06,
0x66, 0x66, 0x00, 0x00, 0x0c, 0x00, 0x30, 0x66, 0xc3, 0x3c, 0x66, 0x66,
0x6c, 0x60, 0x60, 0x66, 0x66, 0x18, 0x06, 0x66, 0x60, 0x63, 0x63, 0x66,
0x66, 0x66, 0x66, 0x66, 0x18, 0x66, 0x66, 0x63, 0x66, 0x66, 0x06, 0x30,
0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x30, 0x00,
0x60, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0xdb, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x40,
0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0x7f, 0x60, 0x76, 0x6c, 0x0c,
0x18, 0x18, 0x36, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x37, 0x7c, 0x66, 0x66,
0x36, 0x60, 0x30, 0x0c, 0x66, 0x66, 0x1c, 0x1c, 0x18, 0x00, 0x18, 0x66,
0xc3, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x66, 0x66, 0x18, 0x06, 0x6c,
0x60, 0x77, 0x73, 0x66, 0x66, 0x66, 0x66, 0x60, 0x18, 0x66, 0x66, 0x63,
0x34, 0x66, 0x06, 0x30, 0x30, 0x0c, 0x00, 0x00, 0x00, 0x3c, 0x7c, 0x3c,
0x3e, 0x3c, 0x30, 0x3e, 0x7c, 0x78, 0x3c, 0x66, 0x18, 0x7e, 0x7c, 0x3c,
0x7c, 0x3e, 0x66, 0x3e, 0x7e, 0x66, 0x66, 0x63, 0x66, 0x66, 0x7e, 0x18,
0x18, 0x18, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x87, 0xe1, 0x86, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x7e, 0x36,
0x30, 0x0c, 0x38, 0x18, 0x30, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x0c,
0x37, 0x0c, 0x06, 0x06, 0x36, 0x60, 0x7c, 0x0c, 0x76, 0x66, 0x1c, 0x1c,
0x30, 0x7e, 0x0c, 0x0c, 0xcf, 0x66, 0x66, 0x60, 0x66, 0x60, 0x60, 0x60,
0x66, 0x18, 0x06, 0x6c, 0x60, 0x6b, 0x7b, 0x66, 0x66, 0x66, 0x66, 0x30,
0x18, 0x66, 0x66, 0x6b, 0x18, 0x66, 0x0c, 0x30, 0x30, 0x0c, 0x00, 0x00,
0x00, 0x06, 0x66, 0x66, 0x66, 0x66, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x66,
0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x6e, 0x60, 0x30, 0x66, 0x66, 0x6b,
0x66, 0x66, 0x06, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x19, 0xd8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x7e, 0x36, 0x18, 0x18, 0x60, 0x00, 0x30, 0x0c, 0x7f, 0x7e,
0x00, 0x7e, 0x00, 0x18, 0x33, 0x0c, 0x0c, 0x1c, 0x36, 0x7c, 0x66, 0x18,
0x3c, 0x66, 0x00, 0x00, 0x60, 0x00, 0x06, 0x18, 0xdb, 0x66, 0x7c, 0x60,
0x66, 0x7c, 0x7c, 0x60, 0x7e, 0x18, 0x06, 0x78, 0x60, 0x6b, 0x6f, 0x66,
0x7c, 0x66, 0x7c, 0x18, 0x18, 0x66, 0x66, 0x6b, 0x18, 0x3c, 0x18, 0x30,
0x18, 0x0c, 0x00, 0x00, 0x00, 0x06, 0x66, 0x60, 0x66, 0x66, 0x7e, 0x66,
0x66, 0x18, 0x0c, 0x6c, 0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x70, 0x60,
0x30, 0x66, 0x66, 0x6b, 0x3c, 0x66, 0x0c, 0x30, 0x18, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x23,
0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x7e, 0x36, 0x0c, 0x30, 0x6f, 0x00,
0x30, 0x0c, 0x1c, 0x18, 0x00, 0x00, 0x00, 0x18, 0x3b, 0x0c, 0x18, 0x06,
0x66, 0x06, 0x66, 0x18, 0x6e, 0x3e, 0x00, 0x00, 0x30, 0x7e, 0x0c, 0x18,
0xdb, 0x7e, 0x66, 0x60, 0x66, 0x60, 0x60, 0x6e, 0x66, 0x18, 0x06, 0x6c,
0x60, 0x6b, 0x67, 0x66, 0x60, 0x66, 0x6c, 0x0c, 0x18, 0x66, 0x66, 0x6b,
0x2c, 0x18, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x3e, 0x66, 0x60,
0x66, 0x7e, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x78, 0x18, 0x6b, 0x66, 0x66,
0x66, 0x66, 0x60, 0x3c, 0x30, 0x66, 0x66, 0x6b, 0x18, 0x66, 0x18, 0x60,
0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x41, 0x82, 0x47, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
0x06, 0x6e, 0x66, 0x00, 0x30, 0x0c, 0x36, 0x18, 0x00, 0x00, 0x00, 0x30,
0x3b, 0x0c, 0x30, 0x66, 0x7f, 0x06, 0x66, 0x30, 0x66, 0x0c, 0x00, 0x00,
0x18, 0x00, 0x18, 0x00, 0xcf, 0x66, 0x66, 0x66, 0x66, 0x60, 0x60, 0x66,
0x66, 0x18, 0x66, 0x6c, 0x60, 0x63, 0x63, 0x66, 0x60, 0x66, 0x66, 0x06,
0x18, 0x66, 0x66, 0x36, 0x66, 0x18, 0x60, 0x30, 0x0c, 0x0c, 0x00, 0x00,
0x00, 0x66, 0x66, 0x60, 0x66, 0x60, 0x30, 0x66, 0x66, 0x18, 0x0c, 0x6c,
0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x60, 0x06, 0x30, 0x66, 0x66, 0x6b,
0x3c, 0x66, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x61, 0x8e, 0x61, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x7e, 0x36, 0x66, 0x5b, 0x66, 0x00, 0x30, 0x0c, 0x00, 0x00,
0x1c, 0x00, 0x1c, 0x30, 0x33, 0x0c, 0x60, 0x66, 0x06, 0x0c, 0x66, 0x30,
0x66, 0x18, 0x1c, 0x1c, 0x0c, 0x00, 0x30, 0x18, 0xc0, 0x66, 0x66, 0x66,
0x6c, 0x60, 0x60, 0x66, 0x66, 0x18, 0x66, 0x66, 0x60, 0x63, 0x63, 0x66,
0x60, 0x66, 0x66, 0x66, 0x18, 0x66, 0x3c, 0x36, 0x66, 0x18, 0x60, 0x30,
0x0c, 0x0c, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x60, 0x30, 0x66,
0x66, 0x18, 0x0c, 0x66, 0x18, 0x6b, 0x66, 0x66, 0x66, 0x66, 0x60, 0x06,
0x30, 0x66, 0x3c, 0x36, 0x66, 0x66, 0x60, 0x18, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x11, 0x9c,
0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x7e, 0x36, 0x3c, 0x1b, 0x3b, 0x00,
0x18, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x1c, 0x60, 0x1e, 0x0c, 0x7e, 0x3c,
0x06, 0x78, 0x3c, 0x30, 0x3c, 0x38, 0x1c, 0x1c, 0x06, 0x00, 0x60, 0x18,
0x7f, 0x66, 0x7c, 0x3c, 0x78, 0x7e, 0x60, 0x3e, 0x66, 0x3c, 0x3c, 0x66,
0x7e, 0x63, 0x63, 0x3c, 0x60, 0x3c, 0x66, 0x3c, 0x18, 0x3c, 0x18, 0x36,
0x66, 0x18, 0x7e, 0x30, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x3e, 0x7c, 0x3c,
0x3e, 0x3c, 0x30, 0x3e, 0x66, 0x7e, 0x0c, 0x66, 0x7e, 0x63, 0x66, 0x3c,
0x7c, 0x3e, 0x60, 0x7c, 0x1e, 0x3e, 0x18, 0x36, 0x66, 0x3c, 0x7e, 0x18,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x08, 0x38, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x0e, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x60,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x0c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x00, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x88, 0x71, 0x88, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0xe3,
0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xc0, 0x43, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};

View File

@@ -1,31 +0,0 @@
#ifndef _CHARS_H_
#define _CHARS_H_
#include <stdbool.h>
#include <stdint.h>
#define CHAR_WIDTH 8
#define CHAR_HEIGHT 16
#define CHAR_COLOR_TRANSPARENT (0xff)
#define CHAR_SIGNAL_PT1 (1)
#define CHAR_SIGNAL_PT2 (2)
#define CHAR_NO_SIGNAL_PT1 (3)
#define CHAR_NO_SIGNAL_PT2 (4)
struct CharDrawingParams
{
const char *str;
int16_t x;
uint8_t imgRow;
uint8_t foreColor;
uint8_t backColor;
uint8_t magnify;
};
void charsDrawString(const struct CharDrawingParams *params);
#endif

188
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.c Normal file → Executable file
View File

@@ -1,96 +1,30 @@
#include <stdio.h>
#include "comms.h"
#include <stdint.h>
#include <string.h>
#include "comms.h"
#include <stdbool.h>
#include "proto.h"
#include "ccm.h"
extern uint8_t Zigbee_tx_buffer(uint8_t tx_buffer[], int len);
static uint8_t packet[128];
static uint8_t mSeq = 0;
uint8_t mLastLqi = 0;
int8_t mLastRSSI = 0;
uint8_t commsGetLastPacketLQI(void)
{
return mLastLqi;
uint8_t commsGetLastPacketLQI(void) {
return mLastLqi;
}
int8_t commsGetLastPacketRSSI(void)
{
return mLastRSSI;
int8_t commsGetLastPacketRSSI(void) {
return mLastRSSI;
}
static inline void __attribute__((always_inline)) macCopy(uint8_t *restrict dst, const uint8_t *restrict src)
{
((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
static inline void __attribute__((always_inline)) macCopy(uint8_t* dst, const uint8_t* src) {
((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
}
static inline bool __attribute__((always_inline)) macIsEq(const uint8_t *restrict dst, const uint8_t *restrict src)
{
return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1];
}
bool commsTx(struct CommsInfo *info, bool bcast, const void *packet_in, uint32_t len)
{
uint8_t nonce[AES_CCM_NONCE_SIZE] = {};
struct MacFrameNormal *mfn;
struct MacFrameBcast *mfb;
uint32_t hdrSz;
char *payload;
static const struct MacFcs normalFcs = {
.frameType = FRAME_TYPE_DATA,
.panIdCompressed = 1,
.destAddrType = ADDR_MODE_LONG,
.srcAddrType = ADDR_MODE_LONG,
};
static const struct MacFcs broadcastFcs = {
.frameType = FRAME_TYPE_DATA,
.destAddrType = ADDR_MODE_SHORT,
.srcAddrType = ADDR_MODE_LONG,
};
if (len > COMMS_MAX_PACKET_SZ)
return false;
if (bcast)
{
mfb = (struct MacFrameBcast *)packet;
hdrSz = sizeof(struct MacFrameBcast);
payload = (char *)(mfb + 1);
mfb->fcs = broadcastFcs;
mfb->seq = mSeq++;
mfb->dstPan = 0xffff;
mfb->dstAddr = 0xffff;
mfb->srcPan = PROTO_PAN_ID;
macCopy(mfb->src, info->myMac);
}
else
{
mfn = (struct MacFrameNormal *)packet;
hdrSz = sizeof(struct MacFrameNormal);
payload = (char *)(mfn + 1);
mfn->fcs = normalFcs;
mfn->seq = mSeq++;
mfn->pan = PROTO_PAN_ID;
macCopy(mfn->dst, info->masterMac);
macCopy(mfn->src, info->myMac);
}
*(uint32_t *)nonce = (*info->nextIV)++;
macCopy(nonce + sizeof(uint32_t), info->myMac);
memcpy(payload, packet_in, len);
aesCcmEnc((void *)packet, (void *)packet, hdrSz, len, info->encrKey, nonce);
*(uint32_t *)(payload + len + AES_CCM_MIC_SIZE) = *(uint32_t *)nonce; // send nonce
len += hdrSz;
len += AES_CCM_MIC_SIZE;
len += sizeof(uint32_t);
return !Zigbee_tx_buffer((uint8_t *)&packet, len);
static inline bool __attribute__((always_inline)) macIsEq(const uint8_t* dst, const uint8_t* src) {
return ((uint32_t *)dst)[0] == ((const uint32_t *)src)[0] && ((uint32_t *)dst)[1] == ((const uint32_t *)src)[1];
}
extern volatile uint8_t rx_buffer[0x400];
@@ -98,94 +32,16 @@ extern volatile uint8_t new_rx;
extern volatile uint8_t new_rssi;
extern volatile int rx_len;
int32_t __attribute__((noinline)) commsRx(struct CommsInfo *info, void *data, uint8_t *fromMacP)
{
uint8_t *buf = packet, nonce[13] = {}, fromMac[8] = {0, 0, 0, 0, 0, 0, 0, 0};
uint32_t len, minNeedLen, hdrLen = 0;
struct MacFrameFromMaster *mfm;
struct MacFrameNormal *mfn;
// sort out how many bytes minimum are a valid packet
minNeedLen = sizeof(struct MacFrameFromMaster); // mac header
minNeedLen += sizeof(uint8_t); // packet type
minNeedLen += AES_CCM_MIC_SIZE; // MIC
minNeedLen += sizeof(uint32_t); // nonce counter
minNeedLen += 2 * sizeof(uint8_t); // RSSI/LQI
if (!new_rx)
return COMMS_RX_ERR_NO_PACKETS;
// some basic checks
mfm = (struct MacFrameFromMaster *)rx_buffer;
if (rx_len >= sizeof(packet) || rx_len < minNeedLen || mfm->fcs.frameType != FRAME_TYPE_DATA ||
mfm->fcs.secure || mfm->fcs.frameVer || mfm->fcs.destAddrType != ADDR_MODE_LONG || !mfm->fcs.panIdCompressed ||
(mfm->fcs.srcAddrType != ADDR_MODE_LONG && mfm->fcs.srcAddrType != ADDR_MODE_SHORT) ||
mfm->pan != PROTO_PAN_ID || !macIsEq(mfm->dst, info->myMac))
{
new_rx = 0;
return COMMS_RX_ERR_INVALID_PACKET;
}
// copy out and release buffer
memcpy(buf, &rx_buffer, len = rx_len - 2 * sizeof(uint8_t));
mLastLqi = rx_buffer[len + 0];
mLastRSSI = rx_buffer[len + 1];
mfm = (struct MacFrameFromMaster *)buf;
mfn = (struct MacFrameNormal *)buf;
new_rx = 0;
// sort out header len, copy mac into nonce
if (mfm->fcs.srcAddrType == ADDR_MODE_LONG)
{
macCopy(fromMac, mfn->src);
hdrLen = sizeof(struct MacFrameNormal);
// re-verify needed length
minNeedLen -= sizeof(struct MacFrameFromMaster);
minNeedLen += sizeof(struct MacFrameNormal);
if (rx_len < minNeedLen)
return COMMS_RX_ERR_INVALID_PACKET;
}
else if (mfm->fcs.srcAddrType == ADDR_MODE_SHORT)
{
macCopy(fromMac, info->masterMac);
hdrLen = sizeof(struct MacFrameFromMaster);
}
// sort out the nonce
macCopy(nonce + sizeof(uint32_t), fromMac);
*(uint32_t *)nonce = *(uint32_t *)(buf + len - sizeof(uint32_t));
// decrypt and auth
len -= hdrLen + AES_CCM_MIC_SIZE + sizeof(uint32_t);
if (!aesCcmDec(buf, buf, hdrLen, len, info->encrKey, nonce))
return COMMS_RX_ERR_MIC_FAIL;
if (fromMacP)
macCopy(fromMacP, fromMac);
memcpy(data, buf + hdrLen, len);
return len;
int32_t __attribute__((noinline)) commsRxUnenc(void *data) {
if (!new_rx)
return COMMS_RX_ERR_NO_PACKETS;
memcpy(data, (uint8_t*)&rx_buffer, rx_len);
mLastLqi = 255 - new_rssi;
mLastRSSI = new_rssi;
new_rx = 0;
return rx_len;
}
int32_t __attribute__((noinline)) commsRxUnenc(void *data)
{
if (!new_rx)
return COMMS_RX_ERR_NO_PACKETS;
memcpy(data, &rx_buffer, rx_len);
mLastLqi = 255 - new_rssi;
mLastRSSI = new_rssi;
new_rx = 0;
return rx_len;
}
void commsTxNoCpy(uint8_t *packetp)
{
Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2));
void commsTxNoCpy(uint8_t *packetp) {
Zigbee_tx_buffer((uint8_t *)&packetp[1], (packetp[0] - 2));
}

19
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/comms.h Normal file → Executable file
View File

@@ -2,36 +2,17 @@
#define _COMMS_H_
#include <stdint.h>
#include "ccm.h"
struct CommsInfo {
const uint8_t *myMac;
const uint8_t *masterMac;
const void *encrKey;
uint32_t *nextIV;
};
extern uint8_t mLastLqi;
extern int8_t mLastRSSI;
#define COMMS_MAX_RADIO_WAIT_MSEC 100
#define COMMS_IV_SIZE (4) //zeroes except these 4 counter bytes
#define COMMS_RX_ERR_NO_PACKETS (-1)
#define COMMS_RX_ERR_INVALID_PACKET (-2)
#define COMMS_RX_ERR_MIC_FAIL (-3)
#define COMMS_MAX_PACKET_SZ (127 /* max phy len */ - 21 /* max mac frame with panID compression */ - 2 /* FCS len */ - AES_CCM_MIC_SIZE - COMMS_IV_SIZE)
bool commsTx(struct CommsInfo *info, bool bcast, const void *packet, uint32_t len);
int32_t commsRx(struct CommsInfo *info, void *data, uint8_t *fromMac); //returns length or COMMS_RX_ERR_*
uint8_t commsGetLastPacketLQI(void);
int8_t commsGetLastPacketRSSI(void);
int32_t commsRxUnenc(void *data);
void commsTxNoCpy(uint8_t *packetp);
#endif

View File

@@ -1,116 +0,0 @@
#include "compression.h"
#include "uzlib/src/uzlib.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "mz100_flash.h"
#include "mz100_wdt.h"
#include "util.h"
#include "eeprom.h"
#define OUT_CHUNK_SIZE 0x100
struct EepromImageHeader backup_header;
uint8_t out_buffer[OUT_CHUNK_SIZE];
uint8_t dict_buffer[32768];
uint32_t current_in_pos = 0;
int callback_read_more_data(TINF_DATA *d)
{
return FLASH_ByteRead(FLASH_NORMAL_READ, current_in_pos++);
}
uint32_t decompress_file(uint32_t address_in, uint32_t size_compressed, uint32_t address_temp, uint32_t max_len_temp, char error_reason[100])
{
FLASH_Read(0, address_in - sizeof(struct EepromImageHeader), (uint8_t *)&backup_header, sizeof(struct EepromImageHeader)); // Save the image header to write it back later
int res;
struct uzlib_uncomp d;
uint32_t decomp_len;
uint32_t decomp_left;
uint32_t current_out_pos = 0;
current_in_pos = address_in;
FLASH_Read(0, address_in + size_compressed - 4, (uint8_t *)&decomp_len, 4); // Read the expected decompressed len
printf("Compressed size is: %i\r\n", size_compressed);
printf("Decompressed size is: %i\r\n", decomp_len);
if (decomp_len + 1 > max_len_temp)
{
printf("Error decompiled file will get too big\r\n");
sprintf(error_reason, "Out too big %i of max %i bytes", decomp_len, max_len_temp);
return 0;
}
decomp_left = decomp_len + 1;
uzlib_init();
uzlib_uncompress_init(&d, dict_buffer, 32768);
d.source = NULL;
d.source_limit = 0;
d.source_read_cb = callback_read_more_data; // Read each byte in the callback to save RAM
res = uzlib_gzip_parse_header(&d);
if (res != TINF_OK)
{
printf("Error parsing header: %d\r\n", res);
sprintf(error_reason, "Error parsing header %i", res);
return 0;
}
printf("Header parsed !\r\n");
qspiEraseRange(address_temp, max_len_temp);
printf("OTA Area erased\r\n");
while (decomp_left)
{
WDT_RestartCounter();
unsigned int chunk_len = decomp_left < OUT_CHUNK_SIZE ? decomp_left : OUT_CHUNK_SIZE;
d.dest = out_buffer;
d.dest_start = d.dest;
d.dest_limit = d.dest + sizeof(out_buffer);
// printf("One round: %i\r\n", decomp_left);
// printf("chunk_len: %i\r\n", chunk_len);
res = uzlib_uncompress_chksum(&d);
// printf("res: %i\r\n", res);
decomp_left -= chunk_len;
FLASH_Write(false, address_temp + current_out_pos, out_buffer, chunk_len);
current_out_pos += chunk_len;
if (res == TINF_DONE)
{
break;
}
if (res != TINF_OK)
{
printf("Some error inner decomp %i\r\n", res);
sprintf(error_reason, "Inner decomp error %i", res);
return 0;
}
}
if (res != TINF_DONE)
{
printf("Some error in decomp %i\r\n", res);
sprintf(error_reason, "Decomp error %i", res);
return 0;
}
printf("Decompression done\r\n");
printf("Writing image to correct position\r\n");
qspiEraseRange(address_in, EEPROM_IMG_EACH);
uint32_t copy_left = decomp_len;
current_out_pos = 0;
while (copy_left)
{
WDT_RestartCounter();
unsigned int chunk_len = copy_left < OUT_CHUNK_SIZE ? copy_left : OUT_CHUNK_SIZE;
FLASH_Read(0, address_temp + current_out_pos, (uint8_t *)&out_buffer, chunk_len);
FLASH_Write(false, address_in + current_out_pos, out_buffer, chunk_len);
current_out_pos += chunk_len;
copy_left -= chunk_len;
}
backup_header.size = decomp_len;
// Writing back the header of an uncompressed image
FLASH_Write(false, address_in - sizeof(struct EepromImageHeader), (uint8_t *)&backup_header, sizeof(struct EepromImageHeader));
printf("Everything done\r\n");
return decomp_len;
}

View File

@@ -0,0 +1,38 @@
#include "drawing.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "epd_interface.h"
#include "mz100/printf.h"
#include "mz100/eeprom.h"
#include "oepl_fs.h"
#include "compression.h"
#include "../../oepl-definitions.h"
#include "../../oepl-proto.h"
#include "settings.h"
extern "C" {
extern void dump(const uint8_t *a, const uint16_t l);
#include "mz100/util.h"
#include "mz100/mz100_flash.h"
#include "../common/uzlib/src/uzlib.h"
}
#define MAX_WINDOW_SIZE 8192
#define ZLIB_CACHE_SIZE 512
uint32_t __attribute__((always_inline)) inline HAL_flashRead(uint32_t address, uint8_t *buffer, uint32_t num){
return FLASH_Read(FLASH_FAST_READ_QUAD_OUT, address, buffer, num);
}
#include "../common/compression.cpp"

View File

@@ -1,9 +1,9 @@
#pragma once
#include "uzlib/src/uzlib.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#define ENABLE_OEPLFS
uint32_t decompress_file(uint32_t address_in, uint32_t size_compressed, uint32_t address_temp, uint32_t max_len_temp, char error_reason[100]);
#ifdef ENABLE_OEPLFS
#include "oepl_fs.h"
#endif
#include "../common/compression.h"

View File

@@ -1,467 +0,0 @@
#include "drawing.h"
#include <stdbool.h>
#include <stdbool.h>
#include "board.h"
#include "eeprom.h"
#include "proto.h"
#include "timer.h"
#include "screen.h"
#include "util.h"
#include "epd.h"
#define COMPRESSION_BITPACKED_3x5_to_7 0x62700357 // 3 pixels of 5 possible colors in 7 bits
#define COMPRESSION_BITPACKED_5x3_to_8 0x62700538 // 5 pixels of 3 possible colors in 8 bits
#define COMPRESSION_BITPACKED_3x6_to_8 0x62700368 // 3 pixels of 6 possible colors in 8 bits
struct BitmapFileHeader
{
uint8_t sig[2];
uint32_t fileSz;
uint8_t rfu[4];
uint32_t dataOfst;
uint32_t headerSz; // 40
int32_t width;
int32_t height;
uint16_t colorplanes; // must be one
uint16_t bpp;
uint32_t compression;
uint32_t dataLen; // may be 0
uint32_t pixelsPerMeterX;
uint32_t pixelsPerMeterY;
uint32_t numColors; // if zero, assume 2^bpp
uint32_t numImportantColors;
};
struct BitmapClutEntry
{
uint8_t b, g, r, x;
};
struct BitmapDrawInfo
{
// dimensions
uint16_t w, h, effectiveW, effectiveH, stride /* 0 -> 1, 5 - >7, 255 -> 256 */;
uint8_t numColorsM1;
// data start
uint32_t dataAddr;
// compression state
uint8_t packetPixelDivVal;
uint8_t packetNumPixels;
uint8_t packetBitSz;
uint8_t packetBitMask; // derived from the above
// flags
uint8_t bpp : 4;
uint8_t bottomUp : 1;
};
uint8_t mPassNo = 0;
static const uint8_t mColorMap[][6] = {
// colors are: B, DG, G, LG, W, R
// phase 0 (LUTS: B:W:R:G, purpose: BWR, prepare greys)
{1, 1, 1, 1, 0, 0}, // lo plane (B)
{0, 0, 0, 0, 0, 1} // hi plane (R)
};
static uint8_t mClutMap[256];
static uint8_t mClutMapRed[256];
static struct BitmapDrawInfo mDrawInfo;
static uint32_t drawPrvParseHeader(uint32_t addr) // return clut addr or zero on error
{
/*struct BitmapFileHeader bmph;
uint16_t packetsPerRow;
addr += sizeof(struct EepromImageHeader);
eepromRead(addr, &bmph, sizeof(bmph));
if (bmph.sig[0] != 'B' || bmph.sig[1] != 'M')
goto fail;
if (bmph.colorplanes != 1)
goto fail;
if ((&bmph.headerSz - 40)) // < 40
goto fail;
if (bmph.bpp > 8)
goto fail;
mDrawInfo.bpp = bmph.bpp;
if (!(&bmph.headerSz - 257)) // >= 257
goto fail;
if ((&bmph.numColors))
mDrawInfo.numColorsM1 = (uint8_t)bmph.numColors - (uint8_t)1;
else
mDrawInfo.numColorsM1 = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp) - (uint8_t)1;
if (!(&bmph.height))
goto fail;
if ((&bmph.width - 1) || !(&bmph.width - 0xffff))
goto fail;
mDrawInfo.w = bmph.width;
if ((&bmph.height) < 0)
{
if ((&bmph.height + 0xffff)) // carries if val too negative
goto fail;
mDrawInfo.h = -bmph.height;
mDrawInfo.bottomUp = false;
}
else
{
if (!(&bmph.headerSz - 0xffff)) // no carry if val too big
goto fail;
mDrawInfo.h = bmph.height;
mDrawInfo.bottomUp = true;
}
if (bmph.compression)
{
printf("compression is not supported ;(");
goto fail;
}
mDrawInfo.packetPixelDivVal = 0;
mDrawInfo.packetNumPixels = 1;
if (mDrawInfo.bpp > 1)
{
mDrawInfo.packetBitSz = 2;
}
else
{
mDrawInfo.packetBitSz = 1; // mDrawInfo.bpp;
}
// mDrawInfo.stride = mathPrvDiv32x8(mathPrvMul16x8((mDrawInfo.w + mDrawInfo.packetNumPixels - 1), mDrawInfo.packetBitSz) + 31, 32) * 4UL;
// mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1;
packetsPerRow = (mDrawInfo.w + mDrawInfo.packetNumPixels - 1) / (mDrawInfo.packetNumPixels);
mDrawInfo.stride = (((packetsPerRow * mDrawInfo.packetBitSz) + 31) / 32) * 4UL;
mDrawInfo.packetBitMask = (uint8_t)(((uint8_t)1) << (uint8_t)mDrawInfo.packetBitSz) - (uint8_t)1;
// calc effective size
mDrawInfo.effectiveH = (mDrawInfo.h > SCREEN_HEIGHT) ? SCREEN_HEIGHT : mDrawInfo.h;
mDrawInfo.effectiveW = (mDrawInfo.w > SCREEN_WIDTH) ? SCREEN_WIDTH : mDrawInfo.w;
// calc addrs
mDrawInfo.dataAddr = addr + bmph.dataOfst;
return addr + bmph.dataOfst - sizeof(struct BitmapClutEntry) * (1 + mDrawInfo.numColorsM1);
fail:
printf("Tried to parse the bmp header, didn't work...");*/
return 0;
}
static void drawPrvLoadAndMapClut(uint32_t clutAddr)
{
/*struct BitmapClutEntry clut;
uint8_t i;
// convert clut to our understanding of color
i = 0;
do
{
uint8_t entry;
eepromRead(clutAddr, &clut, sizeof(clut));
clutAddr += sizeof(struct BitmapClutEntry);
if (SCREEN_EXTRA_COLOR_INDEX >= 0 && clut.r == 0xff && (clut.g == 0xff || clut.g == 0) && clut.b == 0) // yellow/red
entry = SCREEN_EXTRA_COLOR_INDEX;
else
{
uint16_t intensity = 0;
intensity += (0x37 * clut.r);
intensity += (0xB7 * clut.g);
intensity += (0x12 * clut.b);
// adds up to 0xff00 -> fix it
intensity += (uint8_t)(intensity >> 8);
entry = (intensity * SCREEN_NUM_GREYS) >> 16;
entry += SCREEN_FIRST_GREY_IDX;
}
// printf("mapped clut %u (%d %d %d) -> %d\n", i, clut.r, clut.g, clut.b, entry);
mClutMap[i] = entry;
} while (i++ != mDrawInfo.numColorsM1);
// replicate clut down if not a full 256-entry clut
if (mDrawInfo.bpp != 8)
{
uint8_t num = (uint8_t)((uint8_t)1 << (uint8_t)mDrawInfo.bpp);
// we can use the fact that our memcpy always copies forward
memcpy(mClutMap + num, mClutMap, (uint8_t)256 - (uint8_t)num);
}*/
}
static void drawPrvDecodeImageOnce(void)
{
/*uint8_t rowBuf[SCREEN_WIDTH];
uint16_t er, c;
if (mDrawInfo.bottomUp)
er = mDrawInfo.effectiveH - 1;
else
er = 0;
while (1)
{ // we account differently for loop gets compiled worse
uint8_t inIdx = 0, bitpoolInUsed = 0, bitpoolIn = 0;
uint16_t nBytesOut = 0;
#if SCREEN_TX_BPP == 4
uint8_t txPrev = 0;
bool emit = false;
#else
uint8_t bitpoolOutUsedUsed = 0;
uint16_t bitpoolOut = 0;
#endif
// get a row
epdDeselect();
eepromRead((er * mDrawInfo.stride) + mDrawInfo.dataAddr, rowBuf, mDrawInfo.stride);
epdSelect();
// convert to our format
c = mDrawInfo.effectiveW;
do
{
// uartTx('.');
uint8_t packet, packetIdx, packetMembers = mDrawInfo.packetNumPixels;
if (bitpoolInUsed >= mDrawInfo.packetBitSz)
{
bitpoolInUsed -= mDrawInfo.packetBitSz;
packet = bitpoolIn >> bitpoolInUsed;
}
else
{
uint8_t packetBitSz = mDrawInfo.packetBitSz;
uint8_t t = rowBuf[inIdx++];
packet = (bitpoolIn << (packetBitSz - bitpoolInUsed)) | (t >> (8 - (packetBitSz - bitpoolInUsed)));
bitpoolInUsed += 8 - packetBitSz;
bitpoolIn = t;
}
packet &= mDrawInfo.packetBitMask;
// val is now a packet - unpack it
if (packetMembers > c)
packetMembers = c;
for (packetIdx = 0; packetIdx < packetMembers; packetIdx++)
{
uint8_t val;
// extract
if (mDrawInfo.packetPixelDivVal)
{
val = packet % mDrawInfo.packetPixelDivVal;
packet /= mDrawInfo.packetPixelDivVal;
}
else
val = packet;
// map
val = mClutMap[val];
// get bits out
#if SCREEN_TX_BPP == 4
if (emit)
{
emit = false;
ByteDecode(txPrev | val);
nBytesOut++;
txPrev = 0;
}
else
{
emit = true;
txPrev = val << 4;
}
#else
bitpoolOut <<= SCREEN_TX_BPP;
bitpoolOut |= val;
bitpoolOutUsedUsed += SCREEN_TX_BPP;
if (bitpoolOutUsedUsed >= 8)
{
ByteDecode(bitpoolOut >> (bitpoolOutUsedUsed -= 8));
bitpoolOut &= (1 << bitpoolOutUsedUsed) - 1;
nBytesOut++;
}
#endif
}
c -= packetMembers;
} while (c);
#if SCREEN_TX_BPP == 4
if (emit)
{
ByteDecode(txPrev);
nBytesOut++;
}
#else
if (bitpoolOutUsedUsed)
{
ByteDecode(bitpoolOut);
nBytesOut++;
}
#endif
// if we did not produce enough bytes, do so
nBytesOut = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8 - nBytesOut;
while (nBytesOut--)
ByteDecode(SCREEN_BYTE_FILL);
// update row
if (mDrawInfo.bottomUp)
{
if (er)
er--;
else
break;
}
else
{
er++;
if (er == mDrawInfo.effectiveH)
break;
}
}
// fill the rest of the screen
for (er = mDrawInfo.effectiveH - SCREEN_HEIGHT; er; er--)
{
for (c = ((long)SCREEN_WIDTH * SCREEN_TX_BPP + 7) / 8; c; c--)
{
ByteDecode(SCREEN_BYTE_FILL);
}
}*/
}
static uint8_t prev, step = 0;
void ByteDecode(uint8_t byte)
{
/*prev <<= 2;
prev |= (mColorMap[mPassNo][byte >> 4] << 1) | mColorMap[mPassNo][byte & 0x0f];
if (++step == 4)
{
step = 0;
Display_Write_byte(prev);
}*/
}
void drawImageAtAddress(uint32_t addr, uint8_t lut)
{
struct EepromImageHeader *eih = (struct EepromImageHeader *)mClutMap;
eepromRead(addr, mClutMap, sizeof(struct EepromImageHeader));
uint8_t prevVal = 0;
switch (eih->dataType)
{
case DATATYPE_IMG_RAW_1BPP:
printf("Doing raw 1bpp\n");
init_epd();
display_send_start(1);
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
if (c % 256 == 0)
{
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
}
uint8_t curr_byte = mClutMap[c % 256]; // this one holds 8 pixel, we will translate them to 4 sendings
for (int pixI = 0; pixI < 4; pixI++)
{
uint8_t pixel1 = (curr_byte & 0x80) ? 0 : 3;
curr_byte <<= 1;
uint8_t pixel2 = (curr_byte & 0x80) ? 0 : 3;
curr_byte <<= 1;
display_tx_byte((pixel1 << 4) | pixel2);
}
}
display_send_stop();
epd_refresh_and_sleep();
break;
case DATATYPE_IMG_RAW_2BPP:
printf("Doing raw 2bpp\n");
init_epd();
display_send_start(1);
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
if (c % 256 == 0)
{
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
eepromRead(addr + sizeof(struct EepromImageHeader) + (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)) + c, mClutMapRed, 256);
}
uint8_t curr_byte = mClutMap[c % 256]; // this one holds 8 pixel, we will translate them to 4 sendings
uint8_t curr_byteRed = mClutMapRed[c % 256]; // this one holds 8 pixel, we will translate them to 4 sendings
for (int pixI = 0; pixI < 4; pixI++)
{
uint8_t pixel1 = (curr_byte & 0x80) ? 0 : 3;
pixel1 = (curr_byteRed & 0x80) ? 4 : pixel1;
curr_byte <<= 1;
curr_byteRed <<= 1;
uint8_t pixel2 = (curr_byte & 0x80) ? 0 : 3;
pixel2 = (curr_byteRed & 0x80) ? 4 : pixel1;
curr_byte <<= 1;
curr_byteRed <<= 1;
display_tx_byte((pixel1 << 4) | pixel2);
}
}
display_send_stop();
epd_refresh_and_sleep();
break;
case DATATYPE_IMG_BMP:;
uint32_t clutAddr;
printf("sending BMP to EPD - ");
/*clutAddr = drawPrvParseHeader(addr);
if (!clutAddr)
return;
drawPrvLoadAndMapClut(clutAddr);
epdSetup();
if (lut)
selectLUT(lut);
mPassNo = 0;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_BLACK);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();
mPassNo++;
beginFullscreenImage();
beginWriteFramebuffer(EPD_COLOR_RED);
prev = 0;
step = 0;
drawPrvDecodeImageOnce();
endWriteFramebuffer();*/
printf(" complete.\n");
break;
default: // prevent drawing from an unknown file image type
printf("Image with type 0x%02X was requested, but we don't know what to do with that currently...\n", eih->dataType);
return;
}
// addOverlay();
// drawWithSleep();
}

View File

@@ -0,0 +1,40 @@
// #pragma pack(1)
#include "drawing.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "epd_interface.h"
#include "mz100/printf.h"
#include "mz100/eeprom.h"
#include "compression.h"
#include "oepl_fs.h"
#include "../common/QRCode/src/qrcode.h"
#include "../../oepl-definitions.h"
#include "../../oepl-proto.h"
extern "C" {
extern void dump(const uint8_t *a, const uint16_t l);
#include "mz100/util.h"
#include "mz100/mz100_flash.h"
#include "../common/QRCode/src/qrcode.h"
}
#include "userinterface.h"
#include "epd_interface.h"
uint32_t __attribute__((always_inline)) inline HAL_flashRead(uint32_t address, uint8_t *buffer, uint32_t num){
return FLASH_Read(FLASH_FAST_READ_QUAD_OUT, address, buffer, num);
}
#include "../common/drawing.cpp"

View File

@@ -2,12 +2,13 @@
#define _DRAWING_H_
#include <stdint.h>
#include <stdbool.h>
#define DRAWING_MIN_BITMAP_SIZE (128) //minimum size we'll consider
void set_offline(bool state);
void drawImageAtAddress(uint32_t addr, uint8_t lut);
void drawImageFromBuffer(uint8_t* buffer, const uint8_t lut);
#define ENABLE_OEPLFS
#ifdef ENABLE_OEPLFS
#include "oepl_fs.h"
#endif
#include "../common/drawing.h"
#endif

View File

@@ -1,60 +0,0 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdint.h>
#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment
#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment
//pages are 4K in size
//an update can be stored in any 2 image slots
#define EEPROM_UPDATA_AREA_START (0x17000UL)
#define EEPROM_UPDATE_AREA_LEN (0x10000UL)
#define EEPROM_PAGE_SIZE (0x01000UL)
#define EEPROM_OS_START (0x00000UL)
#define EEPROM_OS_LEN (0x13FFFUL) //0xE820 of image, rounded up to 4K
#define EEPROM_IMG_START (0x17000UL)
#define EEPROM_IMG_EACH (0x1F000UL)
#define EEPROM_IMG_LEN (EEPROM_IMG_START + 0x13FFFUL)
#define EEPROM_UPDATE_START (0x17000UL) //same header as images
#define EEPROM_UPDATE_LEN (0x13FFFUL)
#define EEPROM_SETTINGS_AREA_START (0x14000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
#define EEPROM_MAC_INFO_START (0x6c000UL) //not same as stock
#define EEPROM_MAC_INFO_LEN (0x01000UL)
#define EEPROM_IMG_INPROGRESS (0x7fffffff)
#define EEPROM_IMG_VALID (0x494d4721)
#define EEPROM_PIECE_SZ (88)
struct EepromImageHeaderOld {
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint32_t rfu[8]; //zero-filled for now
uint8_t piecesMissing[256]; //each bit represents a 64-byte piece
//image data here
//os update here possibly (EEPROM_OS_UPDATE_SZ_PER_IMG bytes each piece)
//we pre-erase so progress can be calculated by finding the first non-0xff byte
};
struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint8_t dataType;
uint32_t id;
//image data here
//we pre-erase so progress can be calculated by finding the first non-0xff byte
};
#endif

View File

@@ -1,431 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "core_cm3.h"
#include "main.h"
#include "epd.h"
#include "mz100_gpio.h"
#include "mz100_ssp.h"
#include "mz100_pinmux.h"
#include "mz100_clock.h"
#include "mz100_wdt.h"
#include "util.h"
#include "gpio.h"
void epd_reset()
{
uint8_t v0 = 5;
while (1)
{
GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH);
delay(100);
GPIO_WritePinOutput(EPD_RESET, GPIO_IO_LOW);
delay(3000);
GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH);
delay(3000);
if (GPIO_ReadPinLevel(EPD_BUSY))
break;
v0--;
if (!v0)
{
printf("EPD reset failure\r\n");
break;
}
}
delay(5000);
}
void EPD_cmd(char a1)
{
unsigned int v1 = 0;
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW);
do
{
if ((a1 & 0x80) != 0)
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
else
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
a1 *= 2;
v1++;
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
} while (v1 < 8);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
delay(1000);
}
void EPD_data(char a1)
{
unsigned int v1 = 0;
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
do
{
if ((a1 & 0x80) != 0)
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
else
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
a1 *= 2;
v1++;
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
} while (v1 < 8);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
delay(1000);
}
void spi_soft_send_byte(char a1)
{
uint8_t v2 = 0;
do
{
if ((a1 & 0x80) != 0)
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
else
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
a1 *= 2;
v2++;
} while (v2 < 8);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
}
void BUSY_wait(unsigned int a1)
{
unsigned int v2 = 0;
while (GPIO_ReadPinLevel(EPD_BUSY) == GPIO_IO_LOW)
{
delay(10000);
v2++;
if (v2 > a1)
break;
if (!(20 * (v2 % 1000 / 10)))
WDT_RestartCounter();
}
}
void spi_soft_read_buffer(char a1, uint16_t a2, uint8_t *a3, unsigned int a4)
{
char v9;
unsigned int v10;
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW);
spi_soft_send_byte(3);
spi_soft_send_byte(a1);
spi_soft_send_byte(a2 >> 8);
spi_soft_send_byte(a2);
delay_us(10);
for (int i = 0; i < a4; i = (uint8_t)(i + 1))
{
v9 = 0;
v10 = 0;
do
{
v9 *= 2;
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
delay_us(5);
if (GPIO_ReadPinLevel(EPD_MISO))
v9 |= 1u;
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(5);
v10++;
} while (v10 < 8);
delay_us(5);
*a3++ = v9;
}
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH);
}
int spi_soft_read_byte()
{
int v0;
unsigned int v1;
v0 = 0;
GPIO_WritePinOutput(EPD_BS, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
delay_us(1);
GPIO_SetPinDir(EPD_MOSI, GPIO_INPUT);
GPIO_PinMuxFun(EPD_MOSI, 0);
delay_us(3);
v1 = 0;
do
{
v0 = (uint8_t)(2 * v0);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
if (GPIO_ReadPinLevel(EPD_MOSI))
v0 |= 1u;
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
delay_us(1);
v1++;
} while (v1 < 8);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_MOSI, 0);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW);
return v0;
}
void epd_read_write_30()
{
uint8_t v0;
uint8_t v1;
uint8_t v4;
uint8_t v5[12];
uint8_t v6[12];
uint8_t v7[40];
EPD_cmd(101);
EPD_data(1);
delay_us(1000);
spi_soft_read_buffer(0, 25002, v7, 10);
delay_us(1000);
spi_soft_read_buffer(0, 25039, v6, 10);
delay_us(1000);
EPD_cmd(101);
EPD_data(0);
EPD_cmd(64);
BUSY_wait(0xAu);
v0 = spi_soft_read_byte();
v1 = (uint8_t)(2 * v0) + ((uint8_t)spi_soft_read_byte() >> 7);
for (int i = 0; i < 9; i++)
v5[i] = (((char)v1 - (uint8_t)v7[i]) & 0x80) != 0;
for (int j = 0; j < 9; j++)
{
v4 = v6[j];
if (v5[j] == 1)
break;
}
EPD_cmd(0x30);
EPD_data(v4);
}
void epd_read_write_82()
{
uint8_t v0;
int v1;
uint8_t v4;
uint8_t v5[12];
uint8_t v6[12];
uint8_t v7[32];
EPD_cmd(101);
EPD_data(1);
delay_us(1000);
spi_soft_read_buffer(0, 25002, v7, 10);
spi_soft_read_buffer(0, 25049, v6, 10);
delay_us(1000);
EPD_cmd(101);
EPD_data(0);
EPD_cmd(0x40);
BUSY_wait(0xAu);
v0 = spi_soft_read_byte();
v1 = (char)(2 * v0 + ((unsigned int)spi_soft_read_byte() >> 7));
for (int i = 0; i < 9; i++)
v5[i] = ((v1 - (uint8_t)v7[i]) & 0x80) != 0;
for (int j = 0; j < 9; j++)
{
v4 = v6[j];
if (v5[j] == 1)
break;
}
EPD_cmd(0x82);
EPD_data(v4);
}
void epd_send_init()
{
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
delay(1000);
EPD_cmd(4);
BUSY_wait(0x32u);
EPD_cmd(1);
EPD_data(55);
EPD_data(0);
EPD_data(5);
EPD_data(5);
EPD_cmd(0);
EPD_data(203);
EPD_data(8);
EPD_cmd(229);
EPD_data(3);
EPD_cmd(3);
EPD_data(0);
EPD_cmd(6);
EPD_data(199);
EPD_data(204);
EPD_data(45);
EPD_cmd(48);
EPD_data(60);
EPD_cmd(65);
EPD_data(0);
EPD_cmd(80);
EPD_data(119);
EPD_cmd(96);
EPD_data(34);
EPD_cmd(97);
EPD_data(2);
EPD_data(128);
EPD_data(1);
EPD_data(128);
epd_read_write_82();
EPD_cmd(2);
BUSY_wait(0x32u);
}
void init_GPIO_EPD()
{
SSP_CFG_Type v0;
SPI_Param_Type spiParaStruct;
GPIO_PinMuxFun(EPD_MOSI, 0);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CLK, 0);
GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CS, 0);
GPIO_SetPinDir(EPD_CS, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_BUSY, 0);
GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT);
GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP);
GPIO_PinMuxFun(EPD_RESET, 0);
GPIO_SetPinDir(EPD_RESET, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_DC, 0);
GPIO_SetPinDir(EPD_DC, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_BS, 0);
GPIO_SetPinDir(EPD_BS, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW);
GPIO_PinMuxFun(EPD_HLT_CTRL, 0);
GPIO_SetPinDir(EPD_HLT_CTRL, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_MISO, 0);
GPIO_SetPinDir(EPD_MISO, GPIO_INPUT);
GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT);
memset(&v0, 0, 9);
v0.timeOutVal = 0;
SSP_Init(SSP2_ID, &v0);
spiParaStruct.spiClkPhase = SPI_SCPHA_1;
spiParaStruct.spiClkPolarity = SPI_SCPOL_LOW;
SPI_Config(SSP2_ID, &spiParaStruct);
CLK_I2SClkSrc(CLK_I2S_XTAL32M);
CLK_SSPClkSrc(CLK_SSP_ID_2, CLK_SSP_I2S);
CLK_I2SClkDivider(1, 1);
}
void epd_refresh_and_sleep()
{
EPD_cmd(0x12);
delay(100000);
do_sleeped_epd_refresh();
init_GPIO_EPD();
epd_reset();
epd_reset();
EPD_cmd(1);
EPD_data(2);
EPD_data(0);
EPD_data(0);
EPD_data(0);
delay_us(500000);
EPD_cmd(2);
delay_us(1000000);
BUSY_wait(0x32u);
EPD_cmd(0x65);
EPD_data(1);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW);
spi_soft_send_byte(0xB9);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH);
EPD_cmd(0x65);
EPD_data(0);
EPD_cmd(7);
EPD_data(0xA5);
}
void epd_pin_enable(int a1)
{
if (a1)
{
GPIO_PinMuxFun(EPD_CLK, GPIO22_SSP2_SCK);
GPIO_PinMuxFun(EPD_MOSI, GPIO12_SSP2_TXD);
GPIO_PinMuxFun(EPD_MISO, GPIO13_SSP2_RXD);
SSP_Enable(SSP2_ID);
}
else
{
SSP_Disable(SSP2_ID);
GPIO_PinMuxFun(EPD_MOSI, 0);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CLK, 0);
GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_MISO, 0);
GPIO_SetPinDir(EPD_MISO, GPIO_INPUT);
GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT);
}
}
void display_tx_byte(uint8_t data)
{
SSP_SendData(SSP2_ID, data);
for (int i = 0; i < 0xF; ++i)
__ISB();
}
void display_send_start(uint8_t inverted)
{
EPD_cmd(0);
if(inverted)
EPD_data(207);
else
EPD_data(203);
EPD_cmd(0x10);
epd_pin_enable(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
}
void display_send_stop()
{
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
epd_pin_enable(0);
}
void init_epd(void)
{
init_GPIO_EPD();
epd_reset();
epd_reset();
EPD_cmd(0x65);
EPD_data(1);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_LOW);
spi_soft_send_byte(0xAB);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH);
EPD_cmd(0x65);
EPD_data(0);
delay(1000);
epd_send_init();
delay(1000);
EPD_cmd(4);
BUSY_wait(0x32u);
epd_read_write_30();
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define DISPLAY_WIDTH (640)
#define DISPLAY_HEIGHT (384)
#define DISPLAY_WIDTH_MM (164)
#define DISPLAY_HEIGHT_MM (97)
#define MAGNIFY1 3
#define MAGNIFY2 2
#define MAGNIFY3 1
#define BACK_COLOR 3
#define FORE_COLOR_1 0
#define FORE_COLOR_2 4
#define FORE_COLOR_3 0
void init_GPIO_EPD();
void display_send_buffer();
void epd_refresh_and_sleep();
void display_tx_byte(uint8_t data);
void display_send_start(uint8_t inverted);
void display_send_stop();
void init_epd();
void refresh_epd();

View File

@@ -0,0 +1,278 @@
#include "drawing.h"
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "epd_interface.h"
#include "uc8159-var-m2.h"
#include "uc8176-var-m2.h"
#include "mz100/printf.h"
#include "mz100/eeprom.h"
#include "main.h"
extern "C" {
#include "mz100/mz100_clock.h"
#include "mz100/mz100_gpio.h"
#include "mz100/mz100_pinmux.h"
#include "mz100/mz100_ssp.h"
#include "mz100/mz100_wdt.h"
#include "mz100/util.h"
}
#include "settings.h"
#include "../../oepl-definitions.h"
#include "../../oepl-proto.h"
__attribute__((section(".aonshadow"))) epdInterface *epd;
__attribute__((section(".aonshadow"))) tagSpecs tag;
epdInterface::~epdInterface() {
}
void epdSetup() {
switch (tagProfile.controllerType) {
case 0:
epd = new uc8159;
break;
case 1:
epd = new uc8176;
break;
}
epd->effectiveXRes = tagProfile.xRes;
epd->effectiveYRes = tagProfile.yRes;
epd->Xres = tagProfile.xRes;
epd->Yres = tagProfile.yRes;
epd->bpp = tagProfile.bpp;
epd->epdSetup();
}
void epdEnterSleep() {
epd->epdEnterSleep();
delete epd;
}
void draw() {
epd->draw();
}
void drawNoWait() {
epd->drawNoWait();
}
void epdWaitRdy() {
epd->epdWaitRdy();
}
void selectLUT(uint8_t sel) {
epd->selectLUT(sel);
}
static void busyWaitUntilHigh(uint32_t timeout) {
uint32_t v2 = 0;
while (GPIO_ReadPinLevel(EPD_BUSY) == GPIO_IO_LOW) {
delay(50);
v2++;
if (v2 > timeout)
break;
if (((v2 % 1000) / 10) == 0)
WDT_RestartCounter();
}
}
static void busyWaitUntilLow(uint32_t timeout) {
uint32_t v2 = 0;
while (GPIO_ReadPinLevel(EPD_BUSY) == GPIO_IO_HIGH) {
delay(50);
v2++;
if (v2 > timeout)
break;
if (((v2 % 1000) / 10) == 0)
WDT_RestartCounter();
}
}
void busyWaitUntil(bool high, uint32_t timeout) {
if (high)
busyWaitUntilHigh(timeout);
else
busyWaitUntilLow(timeout);
}
void softSPIWriteByte(char byteOut) {
uint8_t loopCount = 0;
do {
if ((byteOut & 0x80) != 0)
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
else
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
byteOut *= 2;
loopCount++;
delay_us(1);
} while (loopCount < 8);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
}
uint8_t softSPIReadByte() {
uint8_t readByte = 0;
uint8_t loopCount = 0;
GPIO_WritePinOutput(EPD_BS, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_HIGH);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
delay_us(1);
GPIO_SetPinDir(EPD_MOSI, GPIO_INPUT);
GPIO_PinMuxFun(EPD_MOSI, PINMUX_FUNCTION_0);
delay_us(3);
do {
readByte *= 2;
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_HIGH);
if (GPIO_ReadPinLevel(EPD_MOSI))
readByte |= 1u;
GPIO_WritePinOutput(EPD_CLK, GPIO_IO_LOW);
delay_us(1);
// delay(1);
loopCount++;
} while (loopCount < 8);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_MOSI, PINMUX_FUNCTION_0);
GPIO_WritePinOutput(EPD_MOSI, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW);
// delay(1);
delay_us(1);
return readByte;
}
void enableHardSPI(bool enable) {
if (enable) {
GPIO_PinMuxFun(EPD_CLK, GPIO22_SSP2_SCK);
GPIO_PinMuxFun(EPD_MOSI, GPIO12_SSP2_TXD);
GPIO_PinMuxFun(EPD_MISO, GPIO13_SSP2_RXD);
SSP_Enable(SSP2_ID);
} else {
SSP_Disable(SSP2_ID);
GPIO_PinMuxFun(EPD_MOSI, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CLK, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_MISO, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_MISO, GPIO_INPUT);
GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT);
}
}
void initEPDGPIO() {
SSP_CFG_Type v0;
SPI_Param_Type spiParaStruct;
GPIO_PinMuxFun(EPD_MOSI, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_MOSI, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CLK, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_CLK, GPIO_OUTPUT);
GPIO_PinMuxFun(EPD_CS, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_CS, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_BUSY, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT);
GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP);
GPIO_PinMuxFun(EPD_RESET, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_RESET, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_RESET, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_DC, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_DC, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_BS, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_BS, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_BS, GPIO_IO_LOW);
GPIO_PinMuxFun(EPD_HLT_CTRL, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_HLT_CTRL, GPIO_OUTPUT);
GPIO_WritePinOutput(EPD_HLT_CTRL, GPIO_IO_HIGH);
GPIO_PinMuxFun(EPD_MISO, PINMUX_FUNCTION_0);
GPIO_SetPinDir(EPD_MISO, GPIO_INPUT);
GPIO_PinModeConfig(EPD_MISO, PINMODE_DEFAULT);
memset(&v0, 0, 9);
v0.timeOutVal = 0;
SSP_Init(SSP2_ID, &v0);
spiParaStruct.spiClkPhase = SPI_SCPHA_1;
spiParaStruct.spiClkPolarity = SPI_SCPOL_LOW;
SPI_Config(SSP2_ID, &spiParaStruct);
CLK_I2SClkSrc(CLK_I2S_XTAL32M);
CLK_SSPClkSrc(CLK_SSP_ID_2, CLK_SSP_I2S);
CLK_I2SClkDivider(1, 1);
}
void epdWrite(uint8_t reg, uint8_t len, ...) {
va_list valist;
va_start(valist, len);
enableHardSPI(true);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW);
SSP_SendData(SSP2_ID, reg);
while (SSP_GetTxFifoLevel(SSP2_ID))
;
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
for (uint8_t i = 0; i < len; i++) {
SSP_SendData(SSP2_ID, va_arg(valist, int));
}
while (SSP_GetTxFifoLevel(SSP2_ID))
;
delay_us(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
enableHardSPI(false);
va_end(valist);
}
void epdBlockWrite(uint8_t reg, uint8_t *buffer, uint16_t len) {
enableHardSPI(true);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_LOW);
SSP_SendData(SSP2_ID, reg);
while (SSP_GetTxFifoLevel(SSP2_ID))
;
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
for (uint16_t i = 0; i < len; i++) {
SSP_SendData(SSP2_ID, buffer[i]);
while (SSP_GetTxFifoLevel(SSP2_ID) > 8)
;
}
while (SSP_GetTxFifoLevel(SSP2_ID))
;
delay_us(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
enableHardSPI(false);
}
void epdBlockWrite(uint8_t *buffer, uint16_t len) {
enableHardSPI(true);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_LOW);
GPIO_WritePinOutput(EPD_DC, GPIO_IO_HIGH);
for (uint16_t i = 0; i < len; i++) {
SSP_SendData(SSP2_ID, buffer[i]);
while (SSP_GetTxFifoLevel(SSP2_ID) > 8)
;
}
while (SSP_GetTxFifoLevel(SSP2_ID))
;
delay_us(1);
GPIO_WritePinOutput(EPD_CS, GPIO_IO_HIGH);
enableHardSPI(false);
}

View File

@@ -0,0 +1,68 @@
#pragma once
// #include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
class epdInterface {
public:
virtual ~epdInterface() = 0;
virtual void epdSetup() = 0;
virtual void epdEnterSleep() = 0;
virtual void draw() = 0;
virtual void drawNoWait() = 0;
virtual void epdWaitRdy() = 0;
virtual void selectLUT(uint8_t lut) = 0;
uint8_t controllerType = 0;
uint16_t Xres;
uint16_t Yres;
uint16_t effectiveXRes;
uint16_t effectiveYRes;
uint16_t XOffset = 0;
uint16_t YOffset = 0;
uint8_t bpp = 0;
bool drawDirectionRight = false;
bool epdMirrorV = false;
bool epdMirrorH = false;
};
struct tagSpecs {
uint8_t buttonCount = 0;
bool hasNFC = false;
bool hasLED = false;
uint16_t macSuffix = 0x0000;
uint8_t OEPLtype = 0;
uint8_t solumType = 0;
uint32_t imageSize = 0;
} __attribute__((packed));
extern __attribute__((section(".aonshadow"))) tagSpecs tag;
//__attribute__((section(".aonshadow")))
extern epdInterface *epd;
void epdSetup();
void epdEnterSleep();
void draw();
void drawNoWait();
void drawWithSleep();
void epdWaitRdy();
#define EPD_LUT_DEFAULT 0
#define EPD_LUT_NO_REPEATS 1
#define EPD_LUT_FAST_NO_REDS 2
#define EPD_LUT_FAST 3
void selectLUT(uint8_t lut);
void initEPDGPIO();
void busyWaitUntil(bool high, uint32_t timeout);
void softSPIWriteByte(char byteOut);
uint8_t softSPIReadByte();
void enableHardSPI(bool enable);
void epdWrite(uint8_t reg, uint8_t len, ...);
void epdBlockWrite(uint8_t reg, uint8_t *buffer, uint16_t len);
void epdBlockWrite(uint8_t *buffer, uint16_t len);

View File

@@ -1,260 +0,0 @@
#pragma once
#include <stdint.h>
static const uint8_t font[256][20]={ // https://raw.githubusercontent.com/basti79/LCD-fonts/master/10x16_vertikal_MSB_1.h
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
{0xE0,0x01,0x30,0x03,0x50,0x02,0x28,0x05,0x28,0x04,0x28,0x04,0x28,0x05,0x50,0x02,0x30,0x03,0xE0,0x01}, // 0x01
{0xE0,0x01,0xF0,0x03,0xB0,0x03,0xD8,0x06,0xD8,0x07,0xD8,0x07,0xD8,0x06,0xB0,0x03,0xF0,0x03,0xE0,0x01}, // 0x02
{0x00,0x3E,0x80,0x7F,0xE0,0x7F,0xF0,0x7F,0xF8,0x3F,0xF8,0x3F,0xF0,0x7F,0xE0,0x7F,0x80,0x7F,0x00,0x3E}, // 0x03
{0x00,0x01,0x80,0x03,0xC0,0x0F,0xE0,0x1F,0xF8,0x7F,0xF0,0x1F,0xE0,0x0F,0xC0,0x07,0x80,0x03,0x00,0x01}, // 0x04
{0x80,0x03,0xC0,0x07,0xC0,0x07,0xC0,0x3F,0xF8,0x7F,0xB8,0x7F,0xC0,0x3F,0xC0,0x07,0xC0,0x07,0x80,0x03}, // 0x05
{0x80,0x03,0xC0,0x07,0xC0,0x0F,0xC0,0x1F,0xF8,0x3F,0xB8,0x7F,0xC0,0x1F,0xC0,0x0F,0xC0,0x07,0x80,0x03}, // 0x06
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
{0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x2E,0xE0,0x71,0x00,0x70,0x00,0x18}, // 0x0B
{0x00,0x00,0x00,0x1E,0x20,0x21,0xA0,0x40,0xF8,0x40,0xA0,0x40,0xA0,0x41,0x00,0x21,0x00,0x1E,0x00,0x00}, // 0x0C
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
{0x06,0x00,0x0E,0x00,0x0E,0x00,0xFC,0x1F,0x00,0x18,0x30,0x10,0x70,0x30,0x70,0x20,0xE0,0x7F,0x00,0x00}, // 0x0E
{0x00,0x01,0xC0,0x0F,0xC0,0x04,0x40,0x08,0x60,0x18,0x40,0x08,0x40,0x04,0xC0,0x0C,0xC0,0x0B,0x00,0x01}, // 0x0F
{0xF8,0x0F,0xF0,0x07,0xF0,0x07,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xC0,0x01,0xC0,0x01,0x80,0x00,0x80,0x00}, // 0x10
{0x80,0x00,0x80,0x00,0xC0,0x01,0xC0,0x01,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xF0,0x07,0xF0,0x07,0xF8,0x0F}, // 0x11
{0x00,0x00,0x00,0x00,0x08,0x10,0x04,0x20,0xFE,0x7F,0x04,0x20,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x12
{0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x13
{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0x14
{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0x15
{0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00}, // 0x16
{0x00,0x00,0x00,0x00,0x11,0x10,0x09,0x20,0xFD,0x7F,0x09,0x20,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x17
{0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x20,0xFE,0x7F,0x00,0x20,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x18
{0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0xFE,0x7F,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x19
{0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1A
{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00}, // 0x1B
{0x00,0x00,0xF8,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00}, // 0x1C
{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1D
{0x08,0x00,0x18,0x00,0x78,0x00,0xF8,0x01,0xF8,0x03,0xF8,0x0F,0xF8,0x03,0xF8,0x00,0x38,0x00,0x08,0x00}, // 0x1E
{0x00,0x08,0x00,0x0C,0x00,0x0F,0xC0,0x0F,0xE0,0x0F,0xF8,0x0F,0xE0,0x0F,0x80,0x0F,0x00,0x0E,0x00,0x08}, // 0x1F
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21
{0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
{0x80,0x00,0x98,0x04,0xE0,0x05,0x80,0x1E,0x98,0x64,0xE0,0x05,0x80,0x1E,0x80,0x64,0x80,0x04,0x00,0x00}, // 0x23
{0x00,0x00,0x00,0x00,0x18,0x38,0x08,0x64,0x08,0x42,0xFC,0xFF,0x88,0x41,0xF0,0x40,0x00,0x00,0x00,0x00}, // 0x24
{0x08,0x38,0x10,0x44,0x20,0x44,0xC0,0x44,0x00,0x39,0x70,0x02,0x88,0x0C,0x88,0x10,0x88,0x20,0x70,0x40}, // 0x25
{0xE0,0x00,0x10,0x01,0x08,0x3A,0x08,0x46,0x88,0x45,0xC8,0x4C,0x38,0x38,0x18,0x00,0x68,0x00,0x80,0x01}, // 0x26
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x18,0x18,0x0C,0x30,0x04,0x20,0x02,0x40,0x02,0x40,0x00,0x00}, // 0x28
{0x00,0x00,0x02,0x40,0x02,0x40,0x04,0x20,0x0C,0x30,0x18,0x18,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x29
{0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x0F,0x00,0x72,0x00,0x0F,0x00,0x18,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x2A
{0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xF8,0x07,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0x2B
{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2C
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x2D
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E
{0x00,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00}, // 0x2F
{0x00,0x00,0xC0,0x0F,0x30,0x30,0x08,0x40,0x08,0x40,0x08,0x40,0x30,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00}, // 0x30
{0x00,0x00,0x08,0x20,0x08,0x20,0x08,0x20,0xF8,0x7F,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x31
{0x00,0x00,0x18,0x60,0x28,0x40,0x48,0x40,0x88,0x40,0x08,0x43,0x08,0x3C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32
{0x00,0x00,0x00,0x00,0x08,0x40,0x08,0x42,0x08,0x42,0x08,0x42,0xF0,0x3D,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33
{0xC0,0x00,0x40,0x03,0x40,0x04,0x40,0x18,0x40,0x20,0xF8,0x7F,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00}, // 0x34
{0x00,0x00,0x00,0x00,0x08,0x7C,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x41,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35
{0x00,0x00,0xE0,0x0F,0x10,0x32,0x08,0x44,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x36
{0x00,0x00,0x00,0x40,0x18,0x40,0xE0,0x40,0x00,0x43,0x00,0x4C,0x00,0x50,0x00,0x60,0x00,0x00,0x00,0x00}, // 0x37
{0x00,0x00,0xF0,0x38,0x08,0x45,0x08,0x42,0x08,0x42,0x08,0x45,0x90,0x45,0x60,0x38,0x00,0x00,0x00,0x00}, // 0x38
{0x00,0x00,0x00,0x1E,0x08,0x21,0x88,0x40,0x88,0x40,0x88,0x40,0x30,0x21,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0x39
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x18,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A
{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x06,0x1E,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3B
{0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x20,0x01,0x20,0x01,0x10,0x02,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x3C
{0x00,0x00,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x00,0x00}, // 0x3D
{0x00,0x00,0x08,0x04,0x10,0x02,0x10,0x02,0x20,0x01,0x20,0x01,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00}, // 0x3E
{0x00,0x00,0x00,0x70,0x00,0x40,0xD8,0x40,0x00,0x41,0x00,0x42,0x00,0x64,0x00,0x38,0x00,0x00,0x00,0x00}, // 0x3F
{0xC0,0x0F,0x30,0x18,0x18,0x20,0xC8,0x47,0x28,0x48,0x68,0x50,0xD8,0x51,0xE0,0x3F,0x20,0x00,0x20,0x00}, // 0x40
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x41
{0x00,0x00,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x88,0x12,0x70,0x0C,0x00,0x00,0x00,0x00}, // 0x42
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x18,0x00,0x00,0x00,0x00}, // 0x43
{0x00,0x00,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0x44
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x45
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x46
{0x00,0x00,0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x88,0x10,0x88,0x10,0xF8,0x18,0x00,0x00}, // 0x47
{0x00,0x00,0xF8,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x48
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x49
{0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A
{0x00,0x00,0xF8,0x1F,0x00,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x20,0x08,0x10,0x10,0x08,0x00,0x00,0x00}, // 0x4B
{0x00,0x00,0xF8,0x1F,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x4C
{0xF8,0x1F,0x00,0x1C,0x80,0x07,0xE0,0x00,0x60,0x00,0x80,0x03,0x00,0x1C,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4D
{0x00,0x00,0xF8,0x1F,0x00,0x08,0x00,0x06,0x80,0x01,0x60,0x00,0x10,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4E
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x4F
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0x50
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x0C,0x10,0x12,0x08,0xE2,0x07,0x00,0x00}, // 0x51
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0xC0,0x10,0x20,0x11,0x10,0x0E,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x52
{0x00,0x00,0x18,0x0E,0x08,0x12,0x08,0x11,0x08,0x11,0x88,0x10,0x90,0x10,0x70,0x18,0x00,0x00,0x00,0x00}, // 0x53
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xF8,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00}, // 0x54
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x55
{0x00,0x10,0x00,0x0C,0x80,0x03,0x60,0x00,0x18,0x00,0x18,0x00,0xE0,0x00,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0x56
{0x00,0x18,0xC0,0x07,0x38,0x00,0xF0,0x00,0x00,0x07,0x80,0x03,0x70,0x00,0x38,0x00,0xC0,0x07,0x00,0x18}, // 0x57
{0x08,0x10,0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10}, // 0x58
{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0x59
{0x00,0x00,0x18,0x10,0x28,0x10,0x48,0x10,0x88,0x10,0x08,0x11,0x08,0x12,0x08,0x14,0x08,0x18,0x00,0x00}, // 0x5A
{0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x5B
{0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0xC0,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x00,0x00}, // 0x5C
{0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5D
{0x00,0x00,0x20,0x00,0xC0,0x00,0x00,0x07,0x00,0x1C,0x00,0x70,0x00,0x0E,0xC0,0x01,0x20,0x00,0x00,0x00}, // 0x5E
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00}, // 0x5F
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x61
{0x00,0x00,0xF8,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x62
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x63
{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xF8,0x7F,0x00,0x00,0x00,0x00}, // 0x64
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x65
{0x00,0x00,0x00,0x04,0x00,0x04,0xF8,0x3F,0x00,0x24,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x00}, // 0x66
{0x00,0x00,0xE0,0x01,0x19,0x02,0x09,0x04,0x09,0x04,0x09,0x04,0x12,0x02,0xFC,0x07,0x00,0x00,0x00,0x00}, // 0x67
{0x00,0x00,0xF8,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x68
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x64,0xF8,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69
{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0x01,0x64,0xFE,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6A
{0x00,0x00,0xF8,0x7F,0x80,0x00,0xC0,0x00,0x20,0x01,0x20,0x02,0x10,0x02,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x6B
{0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0xF8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C
{0xF8,0x07,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00}, // 0x6D
{0x00,0x00,0xF8,0x07,0x00,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x6E
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x6F
{0x00,0x00,0xFF,0x07,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x70
{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xFF,0x07,0x00,0x00,0x00,0x00}, // 0x71
{0x00,0x00,0x00,0x00,0xF8,0x07,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x00}, // 0x72
{0x00,0x00,0x18,0x03,0x88,0x04,0x88,0x04,0x48,0x04,0x48,0x04,0x30,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73
{0x00,0x00,0x00,0x04,0x00,0x04,0xF0,0x1F,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x74
{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75
{0x00,0x04,0x80,0x03,0x60,0x00,0x18,0x00,0x08,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x04,0x00,0x00}, // 0x76
{0x00,0x06,0xE0,0x01,0x18,0x00,0x70,0x00,0x80,0x03,0x80,0x01,0x70,0x00,0x18,0x00,0xE0,0x01,0x00,0x06}, // 0x77
{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x78
{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x00,0x18,0x00,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x79
{0x00,0x00,0x08,0x04,0x18,0x04,0x28,0x04,0x48,0x04,0x88,0x04,0x08,0x05,0x08,0x06,0x08,0x04,0x00,0x00}, // 0x7A
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x7C,0x3F,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x7B
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7C
{0x00,0x00,0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x7C,0x3F,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x7D
{0xC0,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x80,0x01}, // 0x7E
{0x00,0x00,0xF8,0x01,0x08,0x03,0x08,0x04,0x08,0x08,0x08,0x04,0x08,0x03,0xF8,0x01,0x00,0x00,0x00,0x00}, // 0x7F
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x09,0x10,0x0D,0x10,0x0B,0x18,0x00,0x00,0x00,0x00}, // 0x80
{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x00,0x08,0x00,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x81
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x24,0x88,0x44,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x82
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x44,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x83
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x04,0x88,0x04,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x84
{0x00,0x00,0x30,0x00,0x48,0x44,0x88,0x24,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x85
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x44,0x88,0xA4,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x86
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x09,0x04,0x0D,0x04,0x0B,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x87
{0x00,0x00,0xE0,0x01,0x90,0x22,0x88,0x44,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x88
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x24,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x89
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x8A
{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x04,0xF8,0x07,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8B
{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x44,0xF8,0x47,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8C
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x44,0xF8,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8D
{0x08,0x00,0x70,0x00,0xC0,0x81,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x8E
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0xB0,0x40,0xB8,0x40,0x4F,0xC0,0x01,0x70,0x00,0x08,0x00}, // 0x8F
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x90
{0x70,0x04,0xC8,0x04,0x88,0x04,0x88,0x04,0xF0,0x03,0x98,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00}, // 0x91
{0x08,0x00,0x30,0x00,0xE0,0x01,0x20,0x06,0x20,0x18,0xF8,0x1F,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00}, // 0x92
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x44,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x93
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x94
{0x00,0x00,0xE0,0x01,0x10,0x42,0x08,0x24,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x95
{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x40,0x08,0x40,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x96
{0x00,0x00,0xF0,0x07,0x08,0x40,0x08,0x20,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x97
{0x01,0x04,0x01,0x03,0xC1,0x20,0x62,0x00,0x1C,0x00,0x18,0x20,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x98
{0x00,0x00,0xE0,0x07,0x10,0x88,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x99
{0x00,0x00,0xE0,0x1F,0x18,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x80,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x9A
{0x00,0x00,0xE8,0x01,0x10,0x02,0x28,0x04,0xC8,0x04,0x08,0x05,0x10,0x02,0xE0,0x05,0x00,0x00,0x00,0x00}, // 0x9B
{0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x02,0xE8,0x3F,0x08,0x42,0x08,0x42,0x08,0x40,0x00,0x00,0x00,0x00}, // 0x9C
{0x00,0x00,0xE8,0x07,0x30,0x08,0x68,0x10,0x88,0x10,0x08,0x11,0x08,0x16,0x10,0x0C,0xE0,0x17,0x00,0x00}, // 0x9D
{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x9E
{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0xFE,0x7F,0x00,0x84,0x00,0x84,0x00,0x80,0x00,0x00,0x00,0x00}, // 0x9F
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x24,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xA0
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x27,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA1
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x24,0x08,0x44,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xA2
{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x20,0x10,0x40,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA3
{0x00,0x00,0xF8,0x07,0x00,0x23,0x00,0x42,0x00,0x24,0x00,0x24,0x00,0x44,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0xA4
{0x00,0x00,0xF8,0x1F,0x00,0x48,0x00,0x86,0x80,0xC1,0x60,0x40,0x10,0x80,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0xA5
{0x00,0x00,0x00,0x00,0x00,0x4C,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x3E,0x00,0x02,0x00,0x00,0x00,0x00}, // 0xA6
{0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00}, // 0xA7
{0x00,0x00,0x0E,0x00,0x13,0x00,0x11,0x00,0x21,0x00,0xC1,0x06,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00}, // 0xA8
{0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x5D,0x00,0x55,0x00,0x5D,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00}, // 0xA9
{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xE0,0x01,0x00,0x00}, // 0xAA
{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x00,0x08,0x08,0x31,0x38,0x41,0x28,0x01,0xC8,0x00}, // 0xAB
{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x60,0x08,0xA0,0x30,0x20,0x41,0xF8,0x01,0x20,0x00}, // 0xAC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xAD
{0x00,0x00,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x00,0x00}, // 0xAE
{0x00,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x00,0x00}, // 0xAF
{0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x00,0x00}, // 0xB0
{0xDB,0x36,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0x36,0xDB}, // 0xB1
{0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0x36,0xDB}, // 0xB2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB3
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB4
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x58,0x40,0x8C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB5
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0x98,0x40,0x8C,0x40,0x43,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB6
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x8E,0x40,0x58,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB7
{0xC0,0x0F,0x30,0x30,0x98,0x67,0xC8,0x4C,0x48,0x48,0x48,0x48,0x58,0x68,0x30,0x30,0xC0,0x0F,0x00,0x00}, // 0xB8
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB9
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBA
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBB
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBC
{0x00,0x00,0xC0,0x0F,0x20,0x10,0x30,0x20,0x10,0x20,0xF8,0x7F,0x10,0x20,0x10,0x20,0x00,0x00,0x00,0x00}, // 0xBD
{0x00,0x40,0x00,0x20,0x20,0x19,0x20,0x05,0xF8,0x03,0x20,0x05,0x20,0x09,0x00,0x10,0x00,0x20,0x00,0x40}, // 0xBE
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBF
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC0
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC1
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC3
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC4
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC5
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x24,0x90,0x24,0xF8,0x43,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xC6
{0x08,0x00,0x70,0x00,0xC0,0x41,0x40,0x8E,0x40,0xD8,0x40,0x4C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xC7
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC8
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC9
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCA
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCB
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCC
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCD
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCE
{0x00,0x00,0x20,0x10,0xC0,0x0F,0x40,0x08,0x40,0x08,0x40,0x08,0x40,0x08,0xC0,0x0F,0x20,0x10,0x00,0x00}, // 0xCF
{0x00,0x00,0xE0,0x41,0x10,0x52,0x08,0x74,0x08,0x24,0x08,0x54,0x10,0x0E,0xE0,0x03,0x00,0x00,0x00,0x00}, // 0xD0
{0x00,0x01,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0xD1
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x90,0x88,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD2
{0x00,0x00,0xF8,0x1F,0x88,0x90,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD3
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x90,0x88,0x50,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD4
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD5
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x5F,0x08,0x90,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD6
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x50,0xF8,0x9F,0x08,0x90,0x08,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD7
{0x00,0x00,0x08,0x10,0x08,0x90,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD8
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xDA
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB
{0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00}, // 0xDC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xDD
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x90,0xF8,0x5F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xDE
{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, // 0xDF
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x50,0x08,0x90,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE0
{0x00,0x00,0xF8,0x3F,0x00,0x40,0x00,0x40,0x08,0x47,0x88,0x38,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00}, // 0xE1
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x50,0x08,0x90,0x08,0x90,0x08,0x50,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE2
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x90,0x08,0x50,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE3
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x24,0x08,0x24,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE4
{0x00,0x00,0xE0,0x07,0x10,0x48,0x08,0x90,0x08,0xD0,0x08,0x50,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE5
{0x00,0x00,0xFF,0x07,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xE6
{0x00,0x00,0xFF,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE7
{0x00,0x00,0xF8,0x1F,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x40,0x04,0x80,0x03,0x00,0x00,0x00,0x00}, // 0xE8
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x40,0x08,0x80,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xE9
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x40,0x08,0x80,0x08,0x80,0x10,0x40,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEA
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x80,0x08,0x40,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEB
{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x20,0x18,0x40,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0xEC
{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x40,0x00,0x81,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0xED
{0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80}, // 0xEE
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0xF0
{0x00,0x00,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0xC8,0x07,0x08,0x01,0x08,0x01,0x08,0x01,0x00,0x00}, // 0xF1
{0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00}, // 0xF2
{0x08,0x42,0x10,0x52,0x20,0x5A,0xC0,0x6C,0x00,0x01,0x60,0x02,0xA0,0x0C,0x20,0x11,0xF8,0x21,0x20,0x40}, // 0xF3
{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0xF4
{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0xF5
{0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x58,0x06,0x58,0x06,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0xF6
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF7
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF8
{0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFA
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFB
{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x6C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFC
{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x46,0x00,0x4A,0x00,0x4A,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFD
{0x00,0x00,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0x00,0x00}, // 0xFE
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
};

View File

@@ -1,195 +0,0 @@
#include "nfc.h"
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
#include "main.h"
#include "mz100_rtc.h"
#include "mz100_wdt.h"
#include "mz100_pmu.h"
#include "mz100_pinmux.h"
#include "mz100_gpio.h"
#include "util.h"
void NVIC_some_IRQ1(unsigned int a1)
{
*(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1E80) = 1 << (a1 & 0x1F);
}
void NIVC_some_IRQ(unsigned int a1)
{
*(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1D80) = 1 << (a1 & 0x1F);
}
void Pin_pad_set_Low(int pin)
{
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD);
}
void Pin_pad_set_High(int pin)
{
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_HIGH);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD);
}
void Pin_pad_set_Normal(int pin)
{
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
}
void init_GPIO_boot()
{
Pin_pad_set_Normal(NFC_POWER);
Pin_pad_set_Normal(NFC_IRQ);
Pin_pad_set_Normal(EPD_MOSI);
Pin_pad_set_Normal(EPD_MISO);
Pin_pad_set_Normal(EPD_CLK);
Pin_pad_set_Normal(EPD_DC);
Pin_pad_set_Normal(NFC_SCL);
Pin_pad_set_Normal(NFC_SDA);
Pin_pad_set_Normal(EPD_BS);
Pin_pad_set_Normal(EPD_CS);
Pin_pad_set_Normal(EPD_RESET);
Pin_pad_set_Normal(EPD_HLT_CTRL);
}
void init_GPIO_sleep()
{
Pin_pad_set_Low(NFC_POWER);
//Pin_pad_set_Low(NFC_IRQ);
Pin_pad_set_Low(EPD_MOSI);
Pin_pad_set_Low(EPD_MISO);
Pin_pad_set_Low(EPD_CLK);
Pin_pad_set_Low(EPD_DC);
Pin_pad_set_Low(NFC_SCL);
Pin_pad_set_Low(NFC_SDA);
Pin_pad_set_High(EPD_BS);
Pin_pad_set_High(EPD_CS);
Pin_pad_set_High(EPD_RESET);
Pin_pad_set_High(EPD_HLT_CTRL);
}
uint8_t WAKEUP_RF = 0;
void __attribute__((interrupt)) ExtPin5_IRQHandler(void)
{
if (!WAKEUP_RF)
{
NVIC_ClearPendingIRQ(ExtPin5_IRQn);
GPIO_IntMask(RF_WAKEUP_PIN, MASK);
NVIC_some_IRQ1(ExtPin5_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO5_INT);
NVIC_ClearPendingIRQ(ExtPin5_IRQn);
WAKEUP_RF = 1;
}
}
uint32_t gSleepRtcCounter = 0;
uint8_t Ext_Pin27_triggered = 0;
void __attribute__((interrupt)) ExtPin27_IRQHandler(void)
{
WDT_RestartCounter();
printf(">>PIN_27_IRQHandler\r\n");
NVIC_ClearPendingIRQ(ExtPin27_IRQn);
GPIO_IntMask(EPD_BUSY, MASK);
NVIC_some_IRQ1(ExtPin27_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO27_INT);
NVIC_ClearPendingIRQ(ExtPin27_IRQn);
Ext_Pin27_triggered = 1;
}
void enable_irq_for_pin(int a1, unsigned int a2)
{
PMU_WakeupPinSrc_Type v4; // r0
PMU_WakeupPinSrc_Type v5; // r5
char v6; // r7
PMU_WakeupTrigMode_Type v7; // r1
GPIO_PinMuxFun(a2, 7);
if (a2 > 7)
{
if (a2 - 26 > 5)
return;
v4 = a2 - 19;
}
else
{
v4 = a2 - 1;
}
v5 = v4;
v6 = a2 + 31;
if (a1 == 1)
{
GPIO_PinModeConfig(a2, PINMODE_PULLDOWN);
v7 = PMU_WAKEUP_EDGE_RISING;
}
else
{
if (a1 != 2)
goto LABEL_11;
GPIO_PinModeConfig(a2, PINMODE_PULLUP);
v7 = PMU_WAKEUP_EDGE_FALLING;
}
PMU_ConfigWakeupPin(v5, v7);
LABEL_11:
PMU_ClearWakeupExtpin(v5);
GPIO_IntClr((GPIO_NO_Type)a2);
NVIC_ClearPendingIRQ((IRQn_Type)v6);
NVIC_EnableIRQ(v6);
}
void wait_busy_sleep(int a1)
{
unsigned int v1 = 0;
gSleepRtcCounter = 0;
printf("=> EPD_BUSYN_PIN : %d\r\n", 27);
while (1)
{
RTC_CounterReset();
RTC_IntClr(RTC_INT_CNT_UPP);
NIVC_some_IRQ(0);
RTC_IntMask(RTC_INT_CNT_UPP, UNMASK);
(*(volatile unsigned int *)0xE000E100) = 1;
RTC_SetCounterUppVal(0x7FFF * a1 / 0x3E8u);
RTC_Start();
enable_irq_for_pin(1, 27);
__WFI();
if (Ext_Pin27_triggered == 1)
break;
v1++;
delay(2000);
printf("busypin:%d,SCNT:%d\r\n", GPIO_ReadPinLevel(EPD_BUSY), v1);
if (v1 >= 0x5A)
{
printf("DRF BUSY CHECK FAIL\r\n");
break;
}
}
RTC_Stop();
RTC_IntClr(RTC_INT_CNT_UPP);
NIVC_some_IRQ(0);
(*(volatile unsigned int *)0xE000E180) = 1;
gSleepRtcCounter = 1000 * RTC_GetCounterVal() / 0x7FFFu + a1 * v1;
printf("RTC_GetCounterVal(): %d, gSleepRtcCounter:%d(ms)\r\n", RTC_GetCounterVal(), gSleepRtcCounter);
RTC_CounterReset();
Ext_Pin27_triggered = 0;
GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT);
GPIO_PinMuxFun(EPD_BUSY, 0);
GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP);
}
void do_sleeped_epd_refresh()
{
printf("PM2 MODE START!\r\n");
PMU->PMIP_BRN.BF.BRNDET_EN = 0;
PMU->PWR_MODE.BF.CAU_ON = 0;
PMU->PMIP_CHP_CTRL.BF.CHP_ON_OFF = 1;
PMU_SetSleepMode(PMU_PM2);
PMU_ClearWakeupExtpin(PMU_GPIO5_INT);
wait_busy_sleep(2000);
printf("uDisTime : %d ms\r\n", gSleepRtcCounter);
}

View File

@@ -1,9 +0,0 @@
#pragma once
void NVIC_some_IRQ1(unsigned int a1);
void NIVC_some_IRQ(unsigned int a1);
void init_GPIO_boot();
void init_GPIO_sleep();
void enable_irq_for_pin(int a1, unsigned int a2);
void wait_busy_sleep(int a1);
void do_sleeped_epd_refresh();

View File

@@ -1,756 +0,0 @@
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
#include "main.h"
#include "mz100_pinmux.h"
#include "mz100_gpio.h"
#include "mz100_uart.h"
#include "mz100_clock.h"
#include "mz100_sleep.h"
#include "mz100_flash.h"
#include "epd.h"
#include "mz100_ssp.h"
#include "mz100_pmu.h"
#include "core_cminstr.h"
#include "zigbee.h"
#include "util.h"
#include "settings.h"
#include "eeprom.h"
#include "proto.h"
#include "comms.h"
#include "chars.h"
#include "mz100.h"
#include "timer.h"
#include "util.h"
#include "ccm.h"
#include "nfc.h"
#include "gpio.h"
#include "compression.h"
#include "syncedproto.h"
#include "proto.h"
#include "powermgt.h"
#define SW_VER_CURRENT (0x0000011300000000ull) // top 16 bits are off limits, xxxx.VV.tt.vvvv.mmmm means version V.t.v.m
#define SW_DEFAULT_MAC (0x0000000000000014ull)
uint64_t __attribute__((section(".ver"))) mCurVersionExport = SW_VER_CURRENT;
uint64_t __attribute__((section(".default_mac"))) default_mac = SW_DEFAULT_MAC;
char macStr[32];
char macStr1[32];
uint8_t mSelfMac[8];
void prvApplyUpdateIfNeeded()
{
uint32_t ofst, now, size, pieceSz = 0x2000;
uint8_t chunkStore[0x2000];
(*(volatile unsigned int *)0x130000) = 0; // Invalidate RAM in any case so the next boot will be a full one
(*(volatile unsigned int *)0x130400) = 0;
printf("Applying update\r\n");
qspiEraseRange(EEPROM_OS_START, EEPROM_OS_LEN);
size = EEPROM_OS_LEN;
for (ofst = 0; ofst < size; ofst += now)
{
now = size - ofst;
if (now > pieceSz)
now = pieceSz;
printf("Cpy 0x%06x + 0x%04x to 0x%06x\r\n", EEPROM_UPDATE_START + ofst, now, EEPROM_OS_START + ofst);
FLASH_Read(0, EEPROM_UPDATE_START + ofst, chunkStore, now);
FLASH_Write(false, EEPROM_OS_START + ofst, chunkStore, now);
WDT_RestartCounter();
}
printf("Erz IMAGES\r\n");
qspiEraseRange(EEPROM_IMG_START, EEPROM_IMG_LEN);
printf("Erz update\r\n");
qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN);
sleep_with_with_wakeup(1000);
}
static const char *fwVerString(void)
{
static char fwVer[64] = {};
sprintf(fwVer, "FW v%u.%u.%u.%u Batt: %imV Temp: %iC",
(uint8_t)(mCurVersionExport >> 40),
(uint8_t)(mCurVersionExport >> 32),
(uint16_t)(mCurVersionExport >> 16),
(uint16_t)(mCurVersionExport),
measureBattery(),
measureTemp());
return fwVer;
}
uint8_t mScreenRow[DISPLAY_WIDTH / 2];
void uiPrvFullscreenMsg(const char *str, const char *line2, const char *line3)
{
struct CharDrawingParams cdp;
uint16_t i, r, textRow, textRowEnd;
static const char zero = 0;
uint8_t rowIdx;
const char *strA[] = {str ? str : "", line2 ? line2 : "", line3 ? line3 : ""};
printf("MESSAGE: '%s', '%s', '%s'\r\n", strA[0], strA[1], strA[2]);
if (NO_GUI == 1)
return; // Make everything faster for debugging.!!!!
init_epd();
display_send_start(false);
rowIdx = 0;
cdp.magnify = MAGNIFY1;
cdp.str = strA[0];
cdp.x = 1;
cdp.foreColor = FORE_COLOR_1;
cdp.backColor = BACK_COLOR;
textRow = 10;
textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify;
for (r = 0; r < DISPLAY_HEIGHT; r++)
{
// clear the row
for (i = 0; i < sizeof(mScreenRow); i++)
mScreenRow[i] = 0x33;
if (r >= textRowEnd)
{
switch (rowIdx)
{
case 0:
rowIdx = 1;
textRow = textRowEnd + 20;
cdp.magnify = MAGNIFY2;
cdp.foreColor = FORE_COLOR_2;
cdp.str = strA[1];
cdp.x = 1;
textRowEnd = textRow + CHAR_HEIGHT * cdp.magnify;
break;
case 1:
rowIdx = 2;
textRow = DISPLAY_HEIGHT - CHAR_HEIGHT;
cdp.magnify = MAGNIFY3;
cdp.foreColor = FORE_COLOR_3;
cdp.str = strA[2];
cdp.x = 1;
textRowEnd = textRow + CHAR_HEIGHT;
break;
case 2:
cdp.str = (const char *)&zero;
break;
}
}
else if (r > textRow)
{
cdp.imgRow = r - textRow;
charsDrawString(&cdp);
}
for (i = 0; i < sizeof(mScreenRow); i++)
display_tx_byte(mScreenRow[i]);
}
WDT_RestartCounter();
display_send_stop();
epd_refresh_and_sleep();
}
void prvEepromIndex(struct EepromContentsInfo *eci)
{
struct EepromImageHeader eih;
uint32_t addr;
for (addr = EEPROM_IMG_START; addr - EEPROM_IMG_START < EEPROM_IMG_LEN; addr += EEPROM_IMG_EACH)
{
uint32_t *addrP, *szP = NULL;
uint64_t *verP = NULL;
FLASH_Read(0, addr, (uint8_t *)&eih, sizeof(struct EepromImageHeader));
printf("DATA slot 0x%06x: type 0x%08x ver 0x%08x%08x\r\n", addr, eih.validMarker, (uint32_t)(eih.version >> 32), (uint32_t)eih.version);
switch (eih.validMarker)
{
case EEPROM_IMG_INPROGRESS:
verP = &eci->latestInprogressImgVer;
addrP = &eci->latestInprogressImgAddr;
break;
case EEPROM_IMG_VALID:
verP = &eci->latestCompleteImgVer;
addrP = &eci->latestCompleteImgAddr;
szP = &eci->latestCompleteImgSize;
break;
}
if (verP && eih.version >= *verP)
{
*verP = eih.version;
*addrP = addr;
if (szP)
*szP = eih.size;
}
}
}
void prvWriteNewHeader(struct EepromImageHeaderOld *eih, uint32_t addr, uint32_t eeSize, uint64_t ver, uint32_t size)
{
qspiEraseRange(addr, eeSize);
bzero(eih, sizeof(struct EepromImageHeaderOld));
eih->version = ver;
eih->validMarker = EEPROM_IMG_INPROGRESS;
eih->size = size;
memset(eih->piecesMissing, 0xff, sizeof(eih->piecesMissing));
FLASH_Write(false, addr, (uint8_t *)eih, sizeof(struct EepromImageHeaderOld));
}
static void uiPrvDrawImageAtAddress(uint32_t addr, uint32_t size)
{
printf("Drawing image now\r\n");
if (size < 6) // we need enough size to even sort out what this is, that needs 6 bytes
return;
// uiPrvDrawBitmap(addr + sizeof(struct EepromImageHeader), size);
}
void uiPrvDrawLatestImage(const struct EepromContentsInfo *eci)
{
if (eci->latestCompleteImgAddr)
uiPrvDrawImageAtAddress(eci->latestCompleteImgAddr, eci->latestCompleteImgSize);
}
static void prvGetSelfMac(void)
{
FLASH_Read(0, EEPROM_MAC_INFO_START, mSelfMac, 8);
if ((((uint32_t *)mSelfMac)[0] | ((uint32_t *)mSelfMac)[1]) == 0 || (((uint32_t *)mSelfMac)[0] & ((uint32_t *)mSelfMac)[1]) == 0xffffffff)
{ // fastest way to check for all ones or all zeroes
printf("mac unknown\r\n");
// Write a blank mac to have something to work with.
memcpy(&mSelfMac, (uint8_t *)&default_mac, 8);
FLASH_Write(0, EEPROM_MAC_INFO_START, mSelfMac, 8);
// sleep_with_with_wakeup(0);
}
}
static void showVersionAndVerifyMatch(void)
{
// the &mCurVersionExport access is necessary to make sure mCurVersionExport is referenced
/* printf("Booting FW ver 0x%08x%08x (at 0x%08x)\r\n",
(unsigned)(mCurVersionExport >> 32), (unsigned)mCurVersionExport, &mCurVersionExport);
if (((uint32_t)&mCurVersionExport) - 0x100000 != HW_TYPE_74_INCH_BWR_ROM_VER_OFST - 0x20)
{
printf("ver loc mismatch\r\n");
sleep_with_with_wakeup(0);
}
if (mCurVersionExport & ~VERSION_SIGNIFICANT_MASK)
{
printf("ver num @ red zone\r\n");
sleep_with_with_wakeup(0);
}*/
}
uint8_t showChannelSelect()
{ // returns 0 if no accesspoints were found
uint8_t result[sizeof(channelList)];
memset(result, 0, sizeof(result));
powerUp(INIT_RADIO);
// uiPrvFullscreenMsg("Scanning", NULL, NULL);
for (uint8_t i = 0; i < 4; i++)
{
for (uint8_t c = 0; c < sizeof(channelList); c++)
{
if (detectAP(channelList[c]))
{
if (mLastLqi > result[c])
result[c] = mLastLqi;
printf("Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI);
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++)
{
if (result[c] > highestLqi)
{
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
uint8_t channelSelect()
{ // returns 0 if no accesspoints were found
uint8_t result[16];
memset(result, 0, sizeof(result));
for (uint8_t i = 0; i < 2; i++)
{
for (uint8_t c = 0; c < sizeof(channelList); c++)
{
if (detectAP(channelList[c]))
{
if (mLastLqi > result[c])
result[c] = mLastLqi;
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++)
{
if (result[c] > highestLqi)
{
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
void __attribute__((interrupt)) NMIException(void)
{
printf("-----------> NMIException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) HardFaultException(void)
{
printf("-----------> HardFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) MemManageException(void)
{
printf("-----------> MemManageException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) BusFaultException(void)
{
printf("-----------> BusFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) UsageFaultException(void)
{
printf("-----------> UsageFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) SVCHandler(void)
{
}
void __attribute__((interrupt)) DebugMonitor(void)
{
}
void __attribute__((interrupt)) PendSVC(void)
{
}
extern struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send
extern struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received from the AP
extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not
int main(void)
{
uint8_t currentChannel = 0;
struct Settings settings;
uint32_t sleepDuration = 5000;
struct CommsInfo ci;
uint32_t reset_reason = PMU_GetLastResetCause();
uint8_t pwr_mode_at_boot = PMU->PWR_MODE.BF.PWR_MODE;
(*(volatile unsigned int *)0x20124000) = 0x100004; // On WARM RESET: Goto this address. -> entry
(*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000
(*(volatile unsigned int *)0xE000E41A) = 0x40;
CLK_SystemClkInit(CLK_SYS_XTAL64M, CLK_SYS_64M);
CLK_Xtal32MEnable(CLK_OSC_INTERN);
while (CLK_GetClkStatus(CLK_OUT_XTAL64M) != 1)
;
// UART 1 DEBUG OUT
GPIO_PinModeConfig(UART_TX, PINMODE_DEFAULT);
GPIO_PinModeConfig(UART_RX, PINMODE_DEFAULT);
GPIO_PinMuxFun(UART_TX, GPIO4_UART2_TXD); // UART
GPIO_PinMuxFun(UART_RX, GPIO6_UART2_RXD); // UART
UART_CFG_Type uartcfg;
uartcfg.baudRate = 115200;
uartcfg.dataBits = UART_DATABITS_8;
uartcfg.stopBits = 1;
uartcfg.parity = UART_PARITY_NONE;
uartcfg.autoFlowControl = DISABLE;
UART_Init(1, &uartcfg);
UART_FIFO_Type uartFifo;
uartFifo.FIFO_ResetRx = 1;
uartFifo.FIFO_ResetTx = 1;
uartFifo.FIFO_Function = 1;
uartFifo.FIFO_RcvrTrigger = 2;
uartFifo.FIFO_TxEmptyTrigger = 3;
UART_FIFOConfig(1, &uartFifo);
// UART 1 DEBUG OUT
if (!(~(*(volatile unsigned int *)0x4A080000) << 30))
{
NVIC_EnableIRQ(ExtPin5_IRQn);
NVIC_EnableIRQ(RTC_IRQn);
}
(*(volatile unsigned int *)0x4A070004) = ((*(volatile unsigned int *)0x4A070004) & 0xFFFFFFE0) + 2;
PMU->PWR_MODE.BF.PWR_MODE = 2;
uint32_t v0 = FLASH_WordRead(FLASH_NORMAL_READ, 4u);
char v1;
if (!(~v0 << 25))
{
CLK_RC32MEnable();
while (CLK_GetClkStatus(CLK_OUT_RC32M) != 1)
;
v1 = CLK_RC32MCalibration(CLK_AUTO_CAL, 0);
FLASH_WordWrite(FLASH_PROGRAM_NORMAL, 4u, (v0 & 0xFFFFFF00) | (v1 & 0x7F));
}
//** WATCHDOG
CLK_ModuleClkEnable(CLK_WDT);
WDT_SetMode(WDT_MODE_RESET);
WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256);
WDT_SetTimeoutVal(30);
WDT_RestartCounter();
WDT_Enable();
//** WATCHDOG
//** GPIOS
init_GPIO_boot();
// NFC POWER Should be on if NFC is wanted to be used
GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_POWER, 0);
GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_POWER, 1); // Better power NFC up so IRQ will work unpowered later
//** GPIOS
//** RTC
CLK_Xtal32MEnable(CLK_OSC_INTERN);
while (!CLK_GetClkStatus(CLK_OUT_XTAL64M))
;
RC32K_CalClk_Div(63, 31);
CLK_ModuleClkEnable(CLK_RC32K_CAL);
CLK_RC32KEnable();
while (!CLK_GetClkStatus(CLK_OUT_RC32K))
;
PMU->RC32K_CAL_CNTL.BF.RC32K_CAL_DIV = 0;
CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_AUTO_CAL, 0);
CLK_ModuleClkEnable(CLK_RTC);
CLK_RTCClkSrc(CLK_RTC_RC32K);
RTC_Stop();
RTC_Config_Type rtc_conf;
rtc_conf.CntValUpdateMode = RTC_CNT_VAL_UPDATE_AUTO;
rtc_conf.clockDivider = 0;
rtc_conf.uppVal = 0xffffffff;
RTC_Init(&rtc_conf);
RTC_IntClr(RTC_INT_CNT_UPP);
NVIC_ClearPendingIRQ(RTC_IRQn);
RTC_IntMask(RTC_INT_CNT_UPP, UNMASK);
NVIC_EnableIRQ(RTC_IRQn);
//*** RTC
//** Get the real wakeup reason
printf("Rst reason: %i\r\n", reset_reason);
uint32_t real_reason = 0;
if ((*(volatile unsigned int *)0x130400) != 0x11223344)
{
(*(volatile unsigned int *)0x130400) = 0x11223344;
currentChannel = 0;
(*(volatile unsigned int *)0x130404) = currentChannel;
nfc_i2c_init(); // This is only needed on a complete reboot
if (reset_reason == 5)
{
if (pwr_mode_at_boot)
{
real_reason = 1; // POR Reset
}
else
{
real_reason = 3; // WDT Reset
}
}
else
{
if (reset_reason != 4)
{
if (real_reason == 1 && !pwr_mode_at_boot)
{
real_reason = 2; // System Reset
}
else
{
real_reason = 1; // POR Reset
}
}
else if (pwr_mode_at_boot != 1)
{
real_reason = 1; // POR Reset
}
}
}
else
{
currentChannel = (*(volatile unsigned int *)0x130404);
memcpy((uint8_t *)&curBlock, (uint8_t *)&(*(volatile unsigned int *)0x130500), sizeof(struct blockRequest));
memcpy((uint8_t *)&curDataInfo, (uint8_t *)&(*(volatile unsigned int *)0x130600), sizeof(struct AvailDataInfo));
memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES);
requestPartialBlock = false;
}
showVersionAndVerifyMatch();
timerInit();
WDT_RestartCounter();
prvGetSelfMac();
initializeProto();
printf("Booot OpenEPaperLink\r\n");
if (real_reason == 1)
{
printf("Erz data\r\n");
qspiEraseRange(EEPROM_IMG_START, EEPROM_IMG_LEN);
qspiEraseRange(EEPROM_UPDATE_START, EEPROM_UPDATE_LEN);
qspiEraseRange(EEPROM_SETTINGS_AREA_START, EEPROM_SETTINGS_AREA_LEN);
sprintf(macStr, "(" MACFMT ")", MACCVT(mSelfMac));
// uiPrvFullscreenMsg("HELLO OTA", macStr, fwVerString());
currentChannel = showChannelSelect();
(*(volatile unsigned int *)0x130404) = currentChannel;
WDT_RestartCounter();
if (currentChannel)
{
printf("AP Found\r\n");
sprintf(macStr1, "OpenEPaperLink Ch: %i", currentChannel);
uiPrvFullscreenMsg("AP Found", macStr1, macStr);
timerDelay(TIMER_TICKS_PER_MSEC * 1000);
}
else
{
printf("No AP found\r\n");
uiPrvFullscreenMsg("No AP Found", "OpenEPaperLink", macStr);
sleep_with_with_wakeup(120000UL);
}
}
if (nfc_handle()) // If an image was uploaded via NFC lets display it.
{
struct EepromContentsInfo eci;
memset(&eci, 0x00, sizeof(eci));
prvEepromIndex(&eci);
uiPrvDrawLatestImage(&eci);
sleep_with_with_wakeup(30 * 1000);
}
while (1 == 1)
{
wdt10s();
if (currentChannel)
{
// associated
struct AvailDataInfo *avail;
// Is there any reason why we should do a long (full) get data request (including reason, status)?
if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED)
{
// check if we should do a voltage measurement (those are pretty expensive)
/*if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL)
{
powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading
powerUp(INIT_TEMPREADING | INIT_EPD_VOLTREADING);
powerDown(INIT_RADIO);
voltageCheckCounter = 0;
}
else
{
powerUp(INIT_TEMPREADING);
}
voltageCheckCounter++;*/
// check if the battery level is below minimum, and force a redraw of the screen
/*if ((lowBattery && !lowBatteryShown) || (noAPShown))
{
// Check if we were already displaying an image
if (curImgSlot != 0xFF)
{
powerUp(INIT_EEPROM | INIT_EPD);
wdt60s();
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EEPROM | INIT_EPD);
}
else
{
powerUp(INIT_EPD);
showAPFound();
powerDown(INIT_EPD);
}
}*/
powerUp(INIT_RADIO);
avail = getAvailDataInfo();
powerDown(INIT_RADIO);
if (avail != NULL)
{
// we got some data!
longDataReqCounter = 0;
// since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status
wakeUpReason = WAKEUP_REASON_TIMED;
}
}
else
{
powerUp(INIT_RADIO);
avail = getShortAvailDataInfo();
powerDown(INIT_RADIO);
}
addAverageValue();
if (avail == NULL)
{
// no data :(
sleep_with_with_wakeup(60 * 1000UL);
nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period
}
else
{
nextCheckInFromAP = avail->nextCheckIn;
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE)
{
// data transfer
if (processAvailDataInfo(avail))
{
// succesful transfer, next wake time is determined by the NextCheckin;
}
else
{
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
}
else
{
// no data transfer, just sleep.
}
}
uint16_t nextCheckin = getNextSleep();
longDataReqCounter += nextCheckin;
if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS)
{
// disconnected, obviously...
currentChannel = 0;
(*(volatile unsigned int *)0x130404) = currentChannel;
}
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP)
{
sleep_with_with_wakeup(nextCheckInFromAP * 60000UL);
}
else
{
sleep_with_with_wakeup(getNextSleep() * 1000UL);
}
}
else
{
// not associated
if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS)))
{
powerUp(INIT_RADIO); // load down the battery using the radio to get a good reading
powerUp(INIT_EPD_VOLTREADING);
powerDown(INIT_RADIO);
}
// try to find a working channel
powerUp(INIT_RADIO);
currentChannel = channelSelect();
(*(volatile unsigned int *)0x130404) = currentChannel;
powerDown(INIT_RADIO);
/*if ((!currentChannel && !noAPShown) || (lowBattery && !lowBatteryShown) || (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1)))
{
powerUp(INIT_EPD);
wdt60s();
if (curImgSlot != 0xFF)
{
powerUp(INIT_EEPROM);
drawImageFromEeprom(curImgSlot);
powerDown(INIT_EEPROM);
}
else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1)))
{
showLongTermSleep();
}
else
{
showNoAP();
}
powerDown(INIT_EPD);
}*/
// did we find a working channel?
if (currentChannel)
{
// now associated!
scanAttempts = 0;
wakeUpReason = WAKEUP_REASON_NETWORK_SCAN;
initPowerSaving(INTERVAL_BASE);
sleep_with_with_wakeup(getNextSleep() * 1000UL);
}
else
{
// still not associated
//sleep_with_with_wakeup(getNextScanSleep(true) * 1000UL);
sleep_with_with_wakeup(10 * 60 * 1000UL);
}
}
}
printf("sleep: %u\r\n", sleepDuration);
if (sleepDuration == 0)
sleepDuration = 60 * 1000 * 15; // never sleep forever!
sleep_with_with_wakeup(sleepDuration);
return 0;
}
int _write(int file, char *ptr, int len)
{
UART_SendBytes(1, ptr, len);
return len;
}

View File

@@ -0,0 +1,594 @@
// #include "main.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "epd_interface.h"
#include "powermgt.h"
#include "main.h"
#include "settings.h"
extern "C" {
#include "comms.h"
#include "mz100/core_cm3.h"
#include "mz100/eeprom.h"
#include "mz100/gpio.h"
#include "mz100/mz100.h"
#include "mz100/mz100_aon_ram.h"
#include "mz100/mz100_clock.h"
#include "mz100/mz100_flash.h"
#include "mz100/mz100_gpio.h"
#include "mz100/mz100_pinmux.h"
#include "mz100/mz100_pmu.h"
#include "mz100/mz100_sleep.h"
#include "mz100/mz100_ssp.h"
#include "mz100/mz100_uart.h"
#include "mz100/printf.h"
#include "proto.h"
#include "mz100/timer.h"
#include "mz100/util.h"
#include "zigbee.h"
extern void dump(const uint8_t *a, const uint16_t l);
}
#include "oepl-protocol.h"
#include "compression.h"
#include "userinterface.h"
#include "oepl_fs.h"
#define SW_VER_CURRENT (0x0000011300000000ull) // top 16 bits are off limits, xxxx.VV.tt.vvvv.mmmm means version V.t.v.m
#define FW_MAGIC (0x14AFEEBCDC14AE5Aull)
uint64_t __attribute__((section(".ver"))) mCurVersionExport = SW_VER_CURRENT;
uint64_t __attribute__((section(".fwmagic"))) magic = FW_MAGIC;
#define TAG_MODE_CHANSEARCH 0
#define TAG_MODE_ASSOCIATED 1
__attribute__((section(".aon"))) uint8_t currentTagMode = TAG_MODE_CHANSEARCH;
__attribute__((section(".aon"))) volatile struct zigbeeCalibDataStruct zigbeeCalibData;
bool protectedFlashWrite(uint32_t address, uint8_t *buffer, uint32_t num) {
uint8_t attempt = 3;
uint8_t *buf2 = (uint8_t *)malloc(num);
while (attempt--) {
qspiEraseRange(address, num);
delay(50);
FLASH_Write((FLASH_ProgramMode_Type) false, address, buffer, num);
FLASH_Read((FLASH_ReadMode_Type)0, address, buf2, num);
if (memcmp(buffer, buf2, num) == 0) {
printf("Flash block at %06X written successfully\n", address);
free(buf2);
return true;
}
printf("Failed attempt to write flash block at %lu\n", address);
}
free(buf2);
printf("Giving up on writing block at %lu\n", address);
return false;
}
static void initTagProfile() {
for (uint8_t c = 0; c < 8; c++) {
mSelfMac[c] = tagProfile.macAddress[7 - c];
}
if ((((uint32_t *)mSelfMac)[0] | ((uint32_t *)mSelfMac)[1]) == 0 || (((uint32_t *)mSelfMac)[0] & ((uint32_t *)mSelfMac)[1]) == 0xffffffff) { // fastest way to check for all ones or all zeroes
printf("MAC: mac unknown, taking random Flash ID\n");
*((uint64_t *)&tagProfile.macAddress) = FLASH_GetUniqueID();
}
tag.imageSize = flashRoundUp(sizeof(struct EepromImageHeader) + (tagProfile.xRes * tagProfile.yRes * tagProfile.bpp) / 8);
tag.OEPLtype = tagProfile.OEPLType;
}
uint8_t showChannelSelect() { // returns 0 if no accesspoints were found
uint8_t result[sizeof(channelList)];
memset(result, 0, sizeof(result));
powerUp(INIT_RADIO);
// uiPrvFullscreenMsg("Scanning", NULL, NULL);
for (uint8_t i = 0; i < 4; i++) {
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (detectAP(channelList[c])) {
if (mLastLqi > result[c])
result[c] = mLastLqi;
#ifdef DEBUG_MAIN
printf("MAIN: Channel: %d - LQI: %d RSSI %d\n", channelList[c], mLastLqi, mLastRSSI);
#endif
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++) {
if (result[c] > highestLqi) {
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
uint8_t channelSelect() { // returns 0 if no accesspoints were found
printf("Doing chansearch...\n");
uint8_t result[16];
memset(result, 0, sizeof(result));
for (uint8_t i = 0; i < 2; i++) {
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (detectAP(channelList[c])) {
if (mLastLqi > result[c])
result[c] = mLastLqi;
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++) {
if (result[c] > highestLqi) {
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
void __attribute__((interrupt)) NMIException(void) {
printf("-----------> NMIException\r\n");
delay(1000);
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) HardFaultException(void) {
printf("-----------> HardFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) MemManageException(void) {
printf("-----------> MemManageException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) BusFaultException(void) {
printf("-----------> BusFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) UsageFaultException(void) {
printf("-----------> UsageFaultException\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) SVCHandler(void) {
printf("-----------> SVCHandler\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) DebugMonitor(void) {
printf("-----------> DebugMonitor\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
void __attribute__((interrupt)) PendSVC(void) {
printf("-----------> PendSVC\r\n");
PMU->CLK_SRC.BF.MAIN_CLK_SOURCE = 1;
PMU->PWR_MODE.BF.PWR_MODE = 0;
NVIC_SystemReset();
}
int32_t setupRTC(uint32_t calibrate) {
// CLK_Xtal32MEnable(CLK_OSC_INTERN);
// while (!CLK_GetClkStatus(CLK_OUT_XTAL64M))
// ;
RC32K_CalClk_Div(63, 31);
CLK_ModuleClkEnable(CLK_RC32K_CAL);
CLK_RC32KEnable();
while (!CLK_GetClkStatus(CLK_OUT_RC32K))
;
PMU->RC32K_CAL_CNTL.BF.RC32K_CAL_DIV = 0;
int32_t calres;
if (!calibrate) {
calres = CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_AUTO_CAL, 0);
} else {
calres = CLK_RC32KCalibration(CLK_RC32KCAL_XTAL64M, CLK_MANUAL_CAL, calibrate);
}
CLK_ModuleClkEnable(CLK_RTC);
CLK_RTCClkSrc(CLK_RTC_RC32K);
RTC_Stop();
RTC_Config_Type rtc_conf;
rtc_conf.CntValUpdateMode = RTC_CNT_VAL_UPDATE_AUTO;
rtc_conf.clockDivider = 0;
rtc_conf.uppVal = 0xffffffff;
RTC_Init(&rtc_conf);
RTC_IntClr(RTC_INT_CNT_UPP);
NVIC_ClearPendingIRQ(RTC_IRQn);
RTC_IntMask(RTC_INT_CNT_UPP, UNMASK);
NVIC_EnableIRQ(RTC_IRQn);
return calres;
}
void setupUART() {
// UART 1 DEBUG OUT
GPIO_PinModeConfig(UART_TX, PINMODE_DEFAULT);
GPIO_PinModeConfig(UART_RX, PINMODE_DEFAULT);
GPIO_PinMuxFun(UART_TX, GPIO4_UART2_TXD); // UART
GPIO_PinMuxFun(UART_RX, GPIO6_UART2_RXD); // UART
UART_CFG_Type uartcfg;
uartcfg.baudRate = 115200;
uartcfg.dataBits = UART_DATABITS_8;
uartcfg.stopBits = (UART_StopBits_Type)1;
uartcfg.parity = UART_PARITY_NONE;
uartcfg.autoFlowControl = DISABLE;
UART_Init((UART_ID_Type)1, &uartcfg);
UART_FIFO_Type uartFifo;
uartFifo.FIFO_ResetRx = (FunctionalState)1;
uartFifo.FIFO_ResetTx = (FunctionalState)1;
uartFifo.FIFO_Function = (FunctionalState)1;
uartFifo.FIFO_RcvrTrigger = (UART_RxFIFOLevel_Type)2;
uartFifo.FIFO_TxEmptyTrigger = (UART_TxFIFOLevel_Type)3;
UART_FIFOConfig((UART_ID_Type)1, &uartFifo);
// UART 1 DEBUG OUT
}
void setupGPIO() {
//** GPIOS
init_GPIO_boot();
// NFC POWER Should be on if NFC is wanted to be used
GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_POWER, (GPIO_PinMuxFunc_Type)0);
GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_POWER, (GPIO_IO_Type)1); // Better power NFC up so IRQ will work unpowered later
//** GPIOS
if (!(~(*(volatile unsigned int *)0x4A080000) << 30)) {
NVIC_EnableIRQ(ExtPin5_IRQn);
NVIC_EnableIRQ(RTC_IRQn);
}
}
int32_t setupCLKCalib() {
(*(volatile unsigned int *)0x4A070004) = ((*(volatile unsigned int *)0x4A070004) & 0xFFFFFFE0) + 2;
// PMU->PWR_MODE.BF.PWR_MODE = 2; // hmmm
uint32_t v0 = FLASH_WordRead(FLASH_NORMAL_READ, 4u);
char v1;
if (!(~v0 << 25)) {
CLK_RC32MEnable();
while (CLK_GetClkStatus(CLK_OUT_RC32M) != 1)
;
v1 = CLK_RC32MCalibration(CLK_AUTO_CAL, 0);
FLASH_WordWrite(FLASH_PROGRAM_NORMAL, 4u, (v0 & 0xFFFFFF00) | (v1 & 0x7F));
return v1;
}
return -1;
}
void checkWDT() {
uint32_t val1 = WDT_GetCounterVal();
delay(10000);
uint32_t val2 = WDT_GetCounterVal();
if (val1 == val2) {
printf("WDT: Not running!\n");
} else {
printf("WDT: 1: %lu 2: %lu divider is now %lu\n", val1, val2, (val2 - val1) / 10000);
}
}
void TagAssociated() {
// associated
struct AvailDataInfo *avail;
// Is there any reason why we should do a long (full) get data request (including reason, status)?
if ((longDataReqCounter > LONG_DATAREQ_INTERVAL) || wakeUpReason != WAKEUP_REASON_TIMED) {
// check if we should do a voltage measurement (those are pretty expensive)
if (voltageCheckCounter == VOLTAGE_CHECK_INTERVAL) {
doVoltageReading();
voltageCheckCounter = 0;
} else {
powerUp(INIT_TEMPREADING);
}
voltageCheckCounter++;
// check if the battery level is below minimum, and force a redraw of the screen
if ((lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) ||
(!lowBattery && lowBatteryShown) ||
(noAPShown && tagSettings.enableNoRFSymbol)) {
// Check if we were already displaying an image
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM | INIT_EPD);
wdt60s();
drawImageFromEeprom(curImgSlot, 0);
powerDown(INIT_EEPROM | INIT_EPD);
} else {
wdt60s();
showAPFound();
wdt60s();
}
}
powerUp(INIT_RADIO);
#ifdef DEBUG_MAIN
printf("MAIN: full request\n");
#endif
avail = getAvailDataInfo();
avail = getAvailDataInfo();
powerDown(INIT_RADIO);
if (avail != NULL) {
// we got some data!
longDataReqCounter = 0;
// since we've had succesful contact, and communicated the wakeup reason succesfully, we can now reset to the 'normal' status
wakeUpReason = WAKEUP_REASON_TIMED;
}
if (tagSettings.enableTagRoaming) {
uint8_t roamChannel = channelSelect();
if (roamChannel) currentChannel = roamChannel;
}
} else {
powerUp(INIT_RADIO);
avail = getShortAvailDataInfo();
powerDown(INIT_RADIO);
}
addAverageValue();
if (avail == NULL) {
// no data :( this means no reply from AP
nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period
} else {
nextCheckInFromAP = avail->nextCheckIn;
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE) {
// data transfer
if (processAvailDataInfo(avail)) {
// succesful transfer, next wake time is determined by the NextCheckin;
} else {
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
} else {
// no data transfer, just sleep.
}
}
uint16_t nextCheckin = getNextSleep();
longDataReqCounter += nextCheckin;
if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS) {
// We've averaged up to the maximum interval, this means the tag hasn't been in contact with an AP for some time.
if (tagSettings.enableScanForAPAfterTimeout) {
currentTagMode = TAG_MODE_CHANSEARCH;
return;
}
}
// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP) {
sleep_with_with_wakeup(nextCheckInFromAP * 60000UL);
} else {
sleep_with_with_wakeup(getNextSleep() * 1000UL);
}
}
void TagChanSearch() {
// not associated
if (((scanAttempts != 0) && (scanAttempts % VOLTAGEREADING_DURING_SCAN_INTERVAL == 0)) || (scanAttempts > (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))) {
doVoltageReading();
}
// try to find a working channel
currentChannel = channelSelect();
// Check if we should redraw the screen with icons, info screen or screensaver
if ((!currentChannel && !noAPShown && tagSettings.enableNoRFSymbol) ||
(lowBattery && !lowBatteryShown && tagSettings.enableLowBatSymbol) ||
(!lowBattery && lowBatteryShown) ||
(scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) {
powerUp(INIT_EPD);
wdt60s();
if (curImgSlot != 0xFF) {
powerUp(INIT_EEPROM);
drawImageFromEeprom(curImgSlot, 0);
powerDown(INIT_EEPROM);
} else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1))) {
showLongTermSleep();
} else {
showNoAP();
}
powerDown(INIT_EPD);
}
// did we find a working channel?
if (currentChannel) {
#ifdef DEBUG_PROTO
printf("PROTO: Found a working channel from the TagChanSearch loop\n");
#endif
// now associated! set up and bail out of this loop.
scanAttempts = 0;
wakeUpReason = WAKEUP_REASON_NETWORK_SCAN;
initPowerSaving(INTERVAL_BASE);
currentTagMode = TAG_MODE_ASSOCIATED;
sleep_with_with_wakeup(getNextSleep() * 1000UL);
return;
} else {
// still not associated
sleep_with_with_wakeup(getNextScanSleep(true) * 1000UL);
}
}
int main(void) {
(*(volatile unsigned int *)0x20124000) = 0x100004; // On WARM RESET: Goto this address. -> entry
(*(volatile unsigned int *)0xE000ED08) = 0x20100000; // Vector table in RAM and offset 0x4000
(*(volatile unsigned int *)0xE000E41A) = 0x40; // ??
CLK_SystemClkInit(CLK_SYS_XTAL64M, CLK_SYS_64M);
CLK_Xtal32MEnable(CLK_OSC_INTERN);
while (CLK_GetClkStatus(CLK_OUT_XTAL64M) != 1)
;
setupUART();
setupCLKCalib();
if (!loadValidateAonRam() || PMU_GetLastResetCause()) {
// cold boot!
printf("BOOT: Cold boot!\n");
// calibrate the 32K RC oscillator (autocal), we'll store the result to flash later
uint32_t rtccal = setupRTC(0);
setupGPIO();
timerInit();
setupWDT();
clearAonRam();
// all variables are set to 0 now. This might not be appropriate for all variables, such as:
curImgSlot = 0xFF;
// try to load settings
if (!loadSettings()) {
// if we couldn't load settings, we'll try to get it from the tagprofile file. Useful during development
fs->init();
if (!loadProfileFromFile((char *)"tagprofile.bin")) {
// whoops. Empty profile, that shouldn't really ever happen, ever.
printf("We don't know the type of this tag. That's kinda bad, I guess...\n");
} else {
fs->deleteFile((char *)"tagprofile.bin");
}
} else {
printf("BOOT: Loaded tag settings from EEPROM\n");
}
printf("BOOT: MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", tagProfile.macAddress[0], tagProfile.macAddress[1], tagProfile.macAddress[2], tagProfile.macAddress[3], tagProfile.macAddress[4], tagProfile.macAddress[5], tagProfile.macAddress[6], tagProfile.macAddress[7]);
tagProfile.RC32Kcal = rtccal;
printf("BOOT: Rst reason: %i\r\n", PMU_GetLastResetCause());
initTagProfile();
wdt10s();
showSplashScreen();
delay(10000);
currentChannel = 0;
zigbeeCalibData.isValid = false;
wakeUpReason = WAKEUP_REASON_FIRSTBOOT;
initializeProto();
initPowerSaving(INTERVAL_BASE);
doVoltageReading();
currentChannel = showChannelSelect();
radioShutdown();
if (currentChannel) {
printf("BOOT: AP Found\n");
wdt10s();
delay(10000);
showAPFound();
wdt10s();
timerDelay(TIMER_TICKS_PER_MSEC * 1000);
currentTagMode = TAG_MODE_ASSOCIATED;
} else {
printf("BOOT: No AP found\n");
wdt10s();
delay(10000);
showNoAP();
wdt10s();
timerDelay(TIMER_TICKS_PER_MSEC * 1000);
currentTagMode = TAG_MODE_CHANSEARCH;
}
writeSettings();
printf("BOOT: Cold boot complete\n");
sleep_with_with_wakeup(5 * 1000UL);
} else {
setupRTC(tagProfile.RC32Kcal);
setupWDT();
setupGPIO();
timerInit();
}
while (1) {
wdt10s();
switch (currentTagMode) {
case TAG_MODE_ASSOCIATED:
TagAssociated();
break;
case TAG_MODE_CHANSEARCH:
TagChanSearch();
break;
}
}
return 0;
}
int _write(int file, char *ptr, int len) {
UART_SendBytes((UART_ID_Type)1, ptr, len);
return len;
}
void _putchar(char c) {
_write(0, &c, 1);
}
void applyUpdate(uint32_t size) {
uint32_t ofst, now, pieceSz = 0x2000;
uint8_t chunkStore[0x2000];
printf("Applying update\r\n");
// apparently, the flash process is more reliable if we do these two first
setupCLKCalib();
setupRTC(0);
uint64_t test;
FLASH_Read((FLASH_ReadMode_Type)0, fsEnd + 0x0168, (uint8_t *)&test, 8);
if (test != magic) {
printf("Update didn't have the correct magic number!\n");
printf("got %llu\n", test);
delay(1000);
return;
}
showApplyUpdate();
printf("Applying update\r\n");
// qspiEraseRange(EEPROM_OS_START, EEPROM_OS_LEN);
for (ofst = 0; ofst < size; ofst += now) {
now = size - ofst;
if (now > pieceSz)
now = pieceSz;
printf("Cpy 0x%06x + 0x%04x to 0x%06x\r\n", fsEnd + ofst, now, ofst);
FLASH_Read((FLASH_ReadMode_Type)0, fsEnd + ofst, chunkStore, now);
// qspiEraseRange(ofst, now);
protectedFlashWrite(ofst, chunkStore, now);
WDT_RestartCounter();
}
printf("Resetting!\n");
delay(1000);
NVIC_SystemReset();
while (1)
;
}

47
ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4/main.h Normal file → Executable file
View File

@@ -1,38 +1,33 @@
#pragma once
#include <stdio.h>
//#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
//#include "core_cm3.h"
#define NO_GUI 0 // Set this to one for faster developing, not Refresh on the E-Paper while showing Full screen messages
#define TEST_PIN 3
#define RF_WAKEUP_PIN 5
#define TEST_PIN GPIO_3
#define RF_WAKEUP_PIN GPIO_5
#define UART_TX 4
#define UART_RX 6
#define UART_TX GPIO_4
#define UART_RX GPIO_6
#define NFC_POWER 1
#define NFC_IRQ 7
#define NFC_SCL 28
#define NFC_SDA 29
#define NFC_POWER GPIO_1
#define NFC_IRQ GPIO_7
#define NFC_SCL GPIO_28
#define NFC_SDA GPIO_29
#define EPD_BS GPIO_2
#define EPD_MOSI GPIO_12
#define EPD_MISO GPIO_13
#define EPD_CLK GPIO_22
#define EPD_CS GPIO_23
#define EPD_RESET GPIO_24
#define EPD_DC GPIO_26
#define EPD_BUSY GPIO_27
#define EPD_HLT_CTRL GPIO_25
#define EPD_BS 2
#define EPD_MOSI 12
#define EPD_MISO 13
#define EPD_CLK 22
#define EPD_CS 23
#define EPD_RESET 24
#define EPD_DC 26
#define EPD_BUSY 27
#define EPD_HLT_CTRL 25
#define RADIO_FIRST_CHANNEL (11) //2.4-GHz channels start at 11
struct EepromContentsInfo
{
uint32_t latestCompleteImgAddr, latestInprogressImgAddr, latestCompleteImgSize;
uint64_t latestCompleteImgVer, latestInprogressImgVer;
};
void uiPrvFullscreenMsg(const char *str, const char *line2, const char *line3);
void prvApplyUpdateIfNeeded();
void applyUpdate(uint32_t len);

View File

@@ -0,0 +1,16 @@
## 'Filesystem' tools for 88MZ100 ##
- compile_fs_tools.sh
- Compiles 'genprofile.cpp' and and 'mkfs.oepl.cpp' utilities. Expects g++ in paths
- mkfs.oepl.sh
- Converts relevant images to binaries, generates a tag profile, and assembles a binary filesystem
- genprofile
- Generates a binary tag profile from 'tagprofile.json'
- mkbinaryimage.py
- Generates OEPL-compatible binary image file
- mkfs.oepl
- Optionally compresses files and fonts and assembles them into a filesystem
- tagprofile.json
- Tag profile. Used if the serial flasher is used to flash/program a tag. Contains type and mac address
![image](https://github.com/jjwbruijn/OpenEPaperLink/assets/2544995/adb53e40-0b8a-4130-9f28-6ac8f008d54b)

View File

@@ -0,0 +1,7 @@
rm mkfs.oepl genprofile
g++ mkfs.oepl.cpp -lz -o mkfs.oepl
g++ genprofile.cpp -o genprofile
chmod +x mkfs.oepl
chmod +x genprofile

View File

@@ -0,0 +1,61 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
// #include <iostream>
#include <vector>
#include <string.h>
#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
#include "../tagprofile_struct.h"
struct tagHardwareProfile* getProfileFromJson();
int main() {
struct tagHardwareProfile* thwp = getProfileFromJson();
printf("MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X, xRes: %d\n", thwp->macAddress[0],thwp->macAddress[1],thwp->macAddress[2],thwp->macAddress[3],thwp->macAddress[4],thwp->macAddress[5],thwp->macAddress[6],thwp->macAddress[7], thwp->xRes);
FILE* wptr = fopen("tagprofile.bin", "wb");
fwrite((uint8_t*)thwp, sizeof(struct tagHardwareProfile), 1, wptr);
fclose(wptr);
}
struct tagHardwareProfile* getProfileFromJson() {
struct tagHardwareProfile* thwp = new struct tagHardwareProfile;
std::ifstream f("tagprofile.json");
json jsonData = json::parse(f);
// Check if the 'mac' key exists in the JSON object
if (jsonData.find("mac") != jsonData.end()) {
std::string macString = jsonData["mac"];
thwp->xRes = jsonData["xRes"];
thwp->yRes = jsonData["yRes"];
thwp->bpp = jsonData["bpp"];
thwp->controllerType = jsonData["controllerType"];
thwp->OEPLType = jsonData["OEPLType"];
// Attempt to parse the MAC address with ":" separators
int resultWithColons = sscanf(macString.c_str(), "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
&thwp->macAddress[0], &thwp->macAddress[1], &thwp->macAddress[2], &thwp->macAddress[3],
&thwp->macAddress[4], &thwp->macAddress[5], &thwp->macAddress[6], &thwp->macAddress[7]);
if (resultWithColons != 8) {
int resultWithoutColons = sscanf(macString.c_str(), "%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
&thwp->macAddress[0], &thwp->macAddress[1], &thwp->macAddress[2], &thwp->macAddress[3],
&thwp->macAddress[4], &thwp->macAddress[5], &thwp->macAddress[6], &thwp->macAddress[7]);
// Check if either format successfully parsed the MAC address
if (resultWithoutColons != 8) {
std::cerr << "Error parsing MAC address from JSON string." << std::endl;
delete thwp;
return nullptr;
}
}
return thwp;
} else {
std::cerr << "Error: 'mac' key not found in JSON." << std::endl;
delete thwp;
return nullptr;
}
}

View File

@@ -0,0 +1 @@
MAC_BEGINS_HERE>

View File

@@ -0,0 +1,95 @@
import sys
from PIL import Image
import struct
import math
def convert_image_to_binary(input_image_path, output_file_path):
# Open the image
img = Image.open(input_image_path)
# Calculate the padded X size
new_x_size = math.ceil(img.size[0] / 8) * 8
# Create a new image with the padded X size
img_padded = Image.new("RGB", (new_x_size, img.size[1]), (255, 255, 255))
img_padded.paste(img, (0, 0))
# Convert the padded image to grayscale and invert
img_bw = img_padded.convert('L').point(lambda x: 255 - x)
# Check if the image has a red channel
has_red_channel = 'R' in img.getbands()
pixel_data_red = img_padded.split()[0].point(lambda x: 255 - x).tobytes()
if any(pixel_data_red):
has_red_channel = 1;
else:
has_red_channel = 0;
# Calculate unpadded resolution
unpadded_resolution = (img.size[0], img.size[1])
# Create binary file
with open(output_file_path, "wb") as binary_file:
# Write header: 0x06, unpadded X size, Y size, bits-per-pixel
binary_file.write(b'\x06')
binary_file.write(unpadded_resolution[0].to_bytes(2, byteorder='little'))
binary_file.write(unpadded_resolution[1].to_bytes(2, byteorder='little'))
# Determine bits-per-pixel
bits_per_pixel = 2 if has_red_channel else 1
binary_file.write(bits_per_pixel.to_bytes(1, byteorder='big'))
# Extract pixel data
pixel_data_bw = img_bw.tobytes()
# If there's a red channel, extract red pixels
if has_red_channel:
pixel_data_red = img_padded.split()[0].point(lambda x: 255 - x).tobytes()
# Process pixel data in chunks of 8 and pack into bytes for black/white
packed_data_bw = bytearray()
packed_data_red = bytearray()
for i in range(0, len(pixel_data_bw), 8):
chunk_bw = pixel_data_bw[i:i + 8]
packed_byte_bw = 0
for j, pixel_value in enumerate(chunk_bw):
packed_byte_bw |= (pixel_value >> j) & 1 << (7 - j)
packed_data_bw.append(packed_byte_bw)
chunk_red = pixel_data_red[i:i + 8]
packed_byte_red = 0
for j, pixel_value in enumerate(chunk_red):
packed_byte_red |= (pixel_value >> j) & 1 << (7 - j)
packed_byte_red = packed_byte_red ^ packed_byte_bw
packed_data_red.append(packed_byte_red)
# Write packed pixel data to binary file
binary_file.write(bytes(packed_data_bw))
binary_file.write(bytes(packed_data_red))
else:
# Process pixel data in chunks of 8 and pack into bytes for black/white
packed_data_bw = bytearray()
for i in range(0, len(pixel_data_bw), 8):
chunk_bw = pixel_data_bw[i:i + 8]
packed_byte_bw = 0
for j, pixel_value in enumerate(chunk_bw):
packed_byte_bw |= (pixel_value >> j) & 1 << (7 - j)
packed_data_bw.append(packed_byte_bw)
# Write packed pixel data to binary file
binary_file.write(bytes(packed_data_bw))
print(f"Conversion completed. Output saved to {output_file_path}")
if __name__ == "__main__":
if len(sys.argv) != 3:
print("Usage: python script_name.py input_image_path output_file_path")
else:
input_image_path = sys.argv[1]
output_file_path = sys.argv[2]
convert_image_to_binary(input_image_path, output_file_path)

View File

@@ -0,0 +1,258 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
//#include <iostream>
#include <vector>
#include <string.h>
#include <zlib.h>
#pragma pack(1)
/*
This prepares a FS binary for use with the 88mz100-based OEPL Tag Firmware
Jelmer Bruijn 2024
*/
#define PROGMEM
//#define WINDOW_SIZE 12 // 4096 bytes
#define WINDOW_SIZE 10 // 1024 bytes
#define FILENAME_LENGTH 32
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
uint16_t first; ///< ASCII extents (first char)
uint16_t last; ///< ASCII extents (last char)
uint8_t yAdvance; ///< Newline distance (y axis)
} GFXfont;
typedef struct {
uint16_t first;
uint16_t last;
uint8_t yAdvance;
char glyphFile[FILENAME_LENGTH];
char bitmapFile[FILENAME_LENGTH];
} GFXFontOEPL;
typedef struct {
char name[FILENAME_LENGTH];
uint32_t offset;
uint32_t len;
} OEPLFile;
std::vector<OEPLFile*> files;
uint8_t* buffer = nullptr; // temporary holds the entire FS
uint32_t curOffset = 0;
char OEPLHeader[12] = "---OEPL_FS!";
FILE *wptr;
void dump(const uint8_t *a, const uint16_t l) {
printf("\n ");
#define ROWS 16
for (uint8_t c = 0; c < ROWS; c++) {
printf(" %02X", c);
}
printf("\n--------");
for (uint8_t c = 0; c < ROWS; c++) {
printf("---");
}
for (uint16_t c = 0; c < l; c++) {
if ((c % ROWS) == 0) {
printf("\n0x%04X | ", c);
}
printf("%02X ", a[c]);
}
printf("\n--------");
for (uint8_t c = 0; c < ROWS; c++) {
printf("---");
}
printf("\n");
}
unsigned long doCompress(uint8_t* in, uint32_t in_len, uint8_t* out) {
*((uint32_t*)out) = in_len;
z_stream stream;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.avail_in = (uInt)in_len;
stream.next_in = (Bytef*)in;
stream.avail_out = (uInt)(in_len+1337);
stream.next_out = (Bytef*)(out+4);
*((uint32_t*)out) = in_len;
if (deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, WINDOW_SIZE, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
fprintf(stderr, "Error initializing zlib for compression\n");
return 1;
}
if (deflate(&stream, Z_FINISH) != Z_STREAM_END) {
fprintf(stderr, "Error compressing data\n");
deflateEnd(&stream);
return 1;
}
if (deflateEnd(&stream) != Z_OK) {
fprintf(stderr, "Error finalizing compression\n");
return 1;
}
//dump(out, 16);
return stream.total_out+4;
}
void addFile(uint8_t* filedata, uint16_t len, char* filename, bool compress){
char newfilename[FILENAME_LENGTH];
if(compress){
if(strlen(filename)>(FILENAME_LENGTH-3)){
printf("Filename '%s' is too long\n", filename);
return;
}
uint8_t* tmpbuffer = (uint8_t*)malloc(len + 1337);
unsigned long out_len = doCompress(filedata, len, tmpbuffer);
if(out_len==1){
printf("Compression of %s failed\n", filename);
return;
}
filedata = tmpbuffer;
uint8_t rounded = (uint8_t)((float)100*out_len/len);
printf("Compressed %s \033[50D\033[40C: %u \033[50D\033[47C -> %lu \033[70D\033[58C(%d%%)\n", filename, len, out_len, rounded);
len = out_len;
uint8_t flen = strlen(filename);
strncpy(newfilename,filename,FILENAME_LENGTH-3);
strcpy(newfilename + flen, ".z");
filename = newfilename;
}
if(strlen(filename)>(FILENAME_LENGTH-1)){
printf("Filename '%s' is too long\n", filename);
return;
}
if(!buffer){
buffer = (uint8_t*)malloc(len);
} else {
buffer = (uint8_t*)realloc((void*)buffer, curOffset + len);
}
memcpy(buffer+curOffset, filedata, len);
if(compress)free(filedata);
OEPLFile* file = new OEPLFile;
strcpy(file->name,filename);
file->offset = curOffset;
file->len = len;
files.push_back(file);
curOffset+=len;
}
void addFileFromFS(const char* filename, bool compress){
FILE* file = fopen(filename, "rb");
if (file == NULL) {
fprintf(stderr, "Error opening file: %s\n", filename);
return;
}
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
rewind(file);
char* fileContent = (char*)malloc(fileSize);
if (fileContent == NULL) {
fprintf(stderr, "Error allocating memory for file content\n");
fclose(file);
return;
}
size_t bytesRead = fread(fileContent, 1, fileSize, file);
addFile((uint8_t*)fileContent, fileSize, (char*)filename, compress);
}
void printFAT(){
printf("OEPL Filesystem Summary:\n");
uint16_t tableSize = files.size() * sizeof(OEPLFile);
tableSize += sizeof(OEPLHeader)-1;
fwrite(OEPLHeader,sizeof(OEPLHeader)-1,1,wptr);
uint32_t fssize = 0;
for(OEPLFile* file : files){
file->offset += tableSize;
fwrite((uint8_t*)file,sizeof(OEPLFile),1,wptr);
printf("file: %s \033[50D\033[37C size=%u \033[50D\033[51C offset=0x%04X\n",file->name, file->len, file->offset);
fssize = file->len + file->offset;
}
printf("Total FS size: %u\n", fssize);
}
void saveFontData(const GFXfont* font, char* name){
if(strlen(name)>(FILENAME_LENGTH-7)){
printf("Font filename '%s' is too long\n", name);
return;
}
GFXFontOEPL fontdata;
fontdata.first = font->first;
fontdata.last = font->last;
fontdata.yAdvance = font->yAdvance;
strcpy(fontdata.glyphFile, name);
strcpy(fontdata.bitmapFile, name);
uint8_t len = strlen(fontdata.glyphFile);
strcpy(fontdata.glyphFile + len, ".glyph");
strcpy(fontdata.bitmapFile + len, ".bmp");
addFile((uint8_t*)&fontdata, sizeof(GFXFontOEPL), name, false);
uint16_t glyphLen = font->last - font->first;
uint16_t lastOffset = font->glyph[glyphLen].bitmapOffset;
uint16_t lastBitmapSize = font->glyph[glyphLen].width * font->glyph[glyphLen].height;
uint8_t lastBitmapBytes = lastBitmapSize/8;
if(lastBitmapSize%8)lastBitmapBytes++;
uint16_t bitmapSize = lastOffset + lastBitmapBytes;
int16_t glyphSize = (glyphLen + 1) * sizeof(GFXglyph);
addFile((uint8_t*)font->glyph, glyphSize, fontdata.glyphFile, false);
addFile((uint8_t*)font->bitmap, bitmapSize, fontdata.bitmapFile, false);
}
#include "../../common/fonts/FreeSans9pt7b.h"
#include "../../common/fonts/FreeSansBold18pt7b.h"
#include "../../common/fonts/FreeSansBold24pt7b.h"
int main(){
wptr = fopen("../build/fs.img","wb"); // w for write, b for binary
/* FONTS */
saveFontData(&FreeSansBold24pt7b, (char*)"font/FreeSansBold24pt7b");
saveFontData(&FreeSansBold18pt7b, (char*)"font/FreeSansBold18pt7b");
saveFontData(&FreeSans9pt7b, (char*)"font/FreeSans9pt7b");
/* OTHER STUFF */
addFileFromFS("marker.txt", false);
addFileFromFS("tagprofile.bin", false);
addFileFromFS("norf.bin", true);
addFileFromFS("lowbat.bin", true);
addFileFromFS("sadpanda.bin", true);
addFileFromFS("tbird2.bin", true);
addFileFromFS("jet.bin", true);
printFAT();
fwrite(buffer,curOffset,1,wptr);
fclose(wptr);
return 0;
}

View File

@@ -0,0 +1,8 @@
python3 mkbinaryimage.py ../../common/assets/norf48.png norf.bin
python3 mkbinaryimage.py ../../common/assets/lowbat48.png lowbat.bin
python3 mkbinaryimage.py ../../common/assets/sadpanda.png sadpanda.bin
python3 mkbinaryimage.py ../../common/assets/tbird2.png tbird2.bin
python3 mkbinaryimage.py ../../common/assets/jet.png jet.bin
./genprofile
./mkfs.oepl

View File

@@ -0,0 +1,8 @@
{
"mac":"00000130C8754110",
"xRes":400,
"yRes":300,
"bpp":2,
"controllerType":1,
"OEPLType":36
}

View File

@@ -0,0 +1,8 @@
{
"mac":"0000021ECA8C743F",
"xRes":640,
"yRes":384,
"bpp":2,
"controllerType":0,
"OEPLType":5
}

View File

@@ -0,0 +1,8 @@
{
"mac":"000001EF0ED27336",
"xRes":640,
"yRes":384,
"bpp":1,
"controllerType":0,
"OEPLType":38
}

View File

@@ -0,0 +1,8 @@
{
"mac":"000001EF0ED27336",
"xRes":640,
"yRes":384,
"bpp":1,
"controllerType":0,
"OEPLType":38
}

View File

@@ -0,0 +1,25 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdint.h>
#define EEPROM_WRITE_PAGE_SZ 256 //max write size & alignment
#define EEPROM_ERZ_SECTOR_SZ 4096 //erase size and alignment
//pages are 4K in size
//an update can be stored in any 2 image slots
#define EEPROM_SETTINGS_AREA_START (0x7F000UL)
#define EEPROM_SETTINGS_SIZE (0x01000UL)
#define EEPROM_TOTAL_SIZE (0x80000UL)
#define EEPROM_MAC_INFO_START (0x6c000UL) //not same as stock
#define EEPROM_MAC_INFO_LEN (0x01000UL)
#define EEPROM_IMG_VALID (0x494d4721)
//#define EEPROM_PIECE_SZ (88)
#include "../../common/eeprom_struct.h"
#endif

View File

@@ -0,0 +1,198 @@
#include "nfc.h"
// #include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
#include "../main.h"
#include "mz100_rtc.h"
#include "mz100_wdt.h"
#include "mz100_pmu.h"
#include "mz100_pinmux.h"
#include "mz100_gpio.h"
#include "util.h"
#include "printf.h"
#include "mz100_clock.h"
volatile bool RTCintFired = false;
void setupWDT() {
//** WATCHDOG
CLK_ModuleClkEnable(CLK_WDT);
WDT_SetMode(WDT_MODE_RESET);
WDT_SetResetPulseLen(WDT_RESET_PULSE_LEN_256);
WDT_SetTimeoutVal(0x0B);
WDT_RestartCounter();
WDT_Enable();
//** WATCHDOG
}
void NVIC_some_IRQ1(unsigned int a1) {
*(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1E80) = 1 << (a1 & 0x1F);
}
void NIVC_some_IRQ(unsigned int a1) {
*(uint32_t *)(4 * (a1 >> 5) - 0x1FFF1D80) = 1 << (a1 & 0x1F);
}
void Pin_pad_set_Low(int pin) {
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD);
}
void Pin_pad_set_High(int pin) {
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_HIGH);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_PAD);
}
void Pin_pad_set_Normal(int pin) {
GPIO_PinPadOutputEnable(pin);
GPIO_PinPadOutputLevel(pin, PIN_PAD_OUTPUT_LOW);
GPIO_PinOutputModeConfig(pin, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
}
void init_GPIO_boot() {
Pin_pad_set_Normal(NFC_POWER);
Pin_pad_set_Normal(NFC_IRQ);
Pin_pad_set_Normal(EPD_MOSI);
Pin_pad_set_Normal(EPD_MISO);
Pin_pad_set_Normal(EPD_CLK);
Pin_pad_set_Normal(EPD_DC);
Pin_pad_set_Normal(NFC_SCL);
Pin_pad_set_Normal(NFC_SDA);
Pin_pad_set_Normal(EPD_BS);
Pin_pad_set_Normal(EPD_CS);
Pin_pad_set_Normal(EPD_RESET);
Pin_pad_set_Normal(EPD_HLT_CTRL);
}
void init_GPIO_sleep() {
Pin_pad_set_Low(NFC_POWER);
// Pin_pad_set_Low(NFC_IRQ);
Pin_pad_set_Low(EPD_MOSI);
Pin_pad_set_Low(EPD_MISO);
Pin_pad_set_Low(EPD_CLK);
Pin_pad_set_Low(EPD_DC);
Pin_pad_set_Low(NFC_SCL);
Pin_pad_set_Low(NFC_SDA);
Pin_pad_set_High(EPD_BS);
Pin_pad_set_High(EPD_CS);
Pin_pad_set_High(EPD_RESET);
Pin_pad_set_High(EPD_HLT_CTRL);
}
uint8_t WAKEUP_RF = 0;
void __attribute__((interrupt)) ExtPin5_IRQHandler(void) {
if (!WAKEUP_RF) {
NVIC_ClearPendingIRQ(ExtPin5_IRQn);
GPIO_IntMask(RF_WAKEUP_PIN, MASK);
NVIC_some_IRQ1(ExtPin5_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO5_INT);
NVIC_ClearPendingIRQ(ExtPin5_IRQn);
WAKEUP_RF = 1;
}
}
void __attribute__((interrupt)) ExtPin7_IRQHandler(void) {
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
GPIO_IntMask(NFC_IRQ, MASK);
NVIC_some_IRQ1(ExtPin7_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO7_INT);
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
}
volatile uint32_t gSleepRtcCounter = 0;
volatile uint8_t Ext_Pin27_triggered = 0;
void __attribute__((interrupt)) ExtPin27_IRQHandler(void) {
WDT_RestartCounter();
printf(">>PIN_27_IRQHandler\r\n");
NVIC_ClearPendingIRQ(ExtPin27_IRQn);
GPIO_IntMask(EPD_BUSY, MASK);
NVIC_some_IRQ1(ExtPin27_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO27_INT);
NVIC_ClearPendingIRQ(ExtPin27_IRQn);
Ext_Pin27_triggered = 1;
}
void enable_irq_for_pin(int a1, unsigned int a2) {
PMU_WakeupPinSrc_Type v4; // r0
PMU_WakeupPinSrc_Type v5; // r5
char v6; // r7
PMU_WakeupTrigMode_Type v7; // r1
GPIO_PinMuxFun(a2, 7);
if (a2 > 7) {
if (a2 - 26 > 5)
return;
v4 = a2 - 19;
} else {
v4 = a2 - 1;
}
v5 = v4;
v6 = a2 + 31;
if (a1 == 1) {
GPIO_PinModeConfig(a2, PINMODE_PULLDOWN);
v7 = PMU_WAKEUP_EDGE_RISING;
} else {
if (a1 != 2)
goto LABEL_11;
GPIO_PinModeConfig(a2, PINMODE_PULLUP);
v7 = PMU_WAKEUP_EDGE_FALLING;
}
PMU_ConfigWakeupPin(v5, v7);
LABEL_11:
PMU_ClearWakeupExtpin(v5);
GPIO_IntClr((GPIO_NO_Type)a2);
NVIC_ClearPendingIRQ((IRQn_Type)v6);
NVIC_EnableIRQ(v6);
}
void wait_busy_sleep(int a1) {
unsigned int v1 = 0;
gSleepRtcCounter = 0;
// printf("=> EPD_BUSYN_PIN : %d\r\n", 27);
delay(1);
while (1) {
RTC_CounterReset();
RTC_IntClr(RTC_INT_CNT_UPP);
NIVC_some_IRQ(0);
RTC_IntMask(RTC_INT_CNT_UPP, UNMASK);
(*(volatile unsigned int *)0xE000E100) = 1;
RTC_SetCounterUppVal(0x7FFF * a1 / 0x3E8u);
RTC_Start();
enable_irq_for_pin(1, 27);
__WFI();
if (Ext_Pin27_triggered == 1)
break;
v1++;
if (v1 >= 0x5A) {
printf("DRF BUSY CHECK FAIL\r\n");
break;
}
}
RTC_Stop();
RTC_IntClr(RTC_INT_CNT_UPP);
NIVC_some_IRQ(0);
(*(volatile unsigned int *)0xE000E180) = 1;
gSleepRtcCounter = 1000 * RTC_GetCounterVal() / 0x7FFFu + a1 * v1;
// printf("RTC_GetCounterVal(): %d, gSleepRtcCounter:%d(ms)\r\n", RTC_GetCounterVal(), gSleepRtcCounter);
RTC_CounterReset();
Ext_Pin27_triggered = 0;
GPIO_SetPinDir(EPD_BUSY, GPIO_INPUT);
GPIO_PinMuxFun(EPD_BUSY, 0);
GPIO_PinModeConfig(EPD_BUSY, PINMODE_PULLUP);
}
void do_sleeped_epd_refresh() {
printf("PM2 MODE START!\r\n");
PMU->PMIP_BRN.BF.BRNDET_EN = 0;
PMU->PWR_MODE.BF.CAU_ON = 0;
PMU->PMIP_CHP_CTRL.BF.CHP_ON_OFF = 1;
PMU_SetSleepMode(PMU_PM2);
PMU_ClearWakeupExtpin(PMU_GPIO5_INT);
wait_busy_sleep(500);
printf("uDisTime : %d ms\r\n", gSleepRtcCounter);
}

View File

@@ -0,0 +1,11 @@
#pragma once
void setupWDT();
void NVIC_some_IRQ1(unsigned int a1);
void NIVC_some_IRQ(unsigned int a1);
void init_GPIO_boot();
void init_GPIO_sleep();
void enable_irq_for_pin(int a1, unsigned int a2);
void wait_busy_sleep(int a1);
void do_sleeped_epd_refresh();

View File

@@ -3,9 +3,10 @@ GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x100000, LENGTH = 80k
RAM (rwx) : ORIGIN = 0x20100000 + 80k, LENGTH = 160k - 80k - 16k
RAM1 (rwx) : ORIGIN = 0x20124000 , LENGTH = 16k
FLASH (rx) : ORIGIN = 0x100000, LENGTH = 90k
RAM (rwx) : ORIGIN = 0x20100000 + 90k, LENGTH = 160k - 90k - 2k
AONSHADOW (rwx) : ORIGIN = 0x20128000 - 2k, LENGTH = 2k
AON (rwx) : ORIGIN = 0x20130000 , LENGTH = 4k
}
ENTRY(Reset_Handler)
@@ -16,7 +17,7 @@ SECTIONS
{
KEEP(*(.isr_vector))
KEEP(*(.ver))
KEEP(*(.default_mac))
KEEP(*(.fwmagic))
*(.text*)
KEEP(*(.init))
@@ -123,6 +124,27 @@ SECTIONS
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
.aon (NOLOAD):
{
. = ALIGN(4);
_start_of_aon = .;
*(.aon)
*(.aon.*)
. = ALIGN(4);
_end_of_aon = .;
} > AON
.aonshadow (NOLOAD):
{
. = ALIGN(4);
_start_of_aonshadow = .;
*(.aonshadow)
*(.aonshadow.*)
. = ALIGN(4);
_end_of_aonshadow = .;
} > AONSHADOW
}

View File

@@ -0,0 +1,44 @@
#include "mz100_aon_ram.h"
#include <string.h>
#include "stdint.h"
__attribute__((section(".aon"))) volatile uint32_t aonChecksum;
__attribute__((section(".aon"))) volatile uint8_t aonShadow[AONSHADOW_SIZE];
bool aonRamValid = false;
void clearAonRam() {
memset((void *)0x130000, 0, 4096);
//memcpy((void *)(0x128000 - AONSHADOW_SIZE), (uint8_t *)aonShadow, AONSHADOW_SIZE);
}
bool loadValidateAonRam() {
uint32_t testchecksum = aonChecksum;
aonChecksum = 0x00000000;
uint32_t checksum = 0xABBA5FF7;
for (uint32_t c = 0x130000; c < 0x131000; c += 4) {
checksum += *(uint32_t *)c;
}
if (checksum == testchecksum) {
// immediately invalidate the checksum; if we reboot, we want a clean reboot
aonChecksum = 0x5445A00A;
memcpy((void *)(0x128000 - AONSHADOW_SIZE), (uint8_t *)aonShadow, AONSHADOW_SIZE);
return true;
} else {
clearAonRam();
memset((void *)(0x128000 - AONSHADOW_SIZE), 0, AONSHADOW_SIZE);
return false;
}
}
void saveAonRam() {
memcpy((uint8_t *)aonShadow, (void *)(0x128000 - AONSHADOW_SIZE), AONSHADOW_SIZE);
aonChecksum = 0x00000000;
uint32_t checksum = 0xABBA5FF7;
for (uint32_t c = 0x130000; c < 0x131000; c += 4) {
checksum += *(uint32_t *)c;
}
aonChecksum = checksum;
}

View File

@@ -0,0 +1,11 @@
#include "stdint.h"
#include "stdbool.h"
#define AONSHADOW_SIZE 2048
extern bool aonRamValid;
bool loadValidateAonRam();
void saveAonRam();
void clearAonRam();

View File

@@ -1,4 +1,4 @@
#include <stdio.h>
//#include <stdio.h>
#include <stdint.h>
#include "core_cm3.h"
#include "mz100_gpio.h"
@@ -12,8 +12,11 @@
#include "mz100_sleep.h"
#include "util.h"
#include "gpio.h"
#include "main.h"
#include "proto.h"
#include "../main.h"
//#include "proto.h"
#include "printf.h"
extern void saveAonRam();
void AON_level_VDD(int state)
{
@@ -85,14 +88,16 @@ void Set_Wakeup_pin_nfc()
NVIC_EnableIRQ(ExtPin7_IRQn);
}
extern struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send
extern struct AvailDataInfo curDataInfo; // last 'AvailDataInfo' we received from the AP
extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not
//extern struct blockRequest curBlock; // used by the block-requester, contains the next request that we'll send
//extern struct AvailDataInfo xferDataInfo; // last 'AvailDataInfo' we received from the AP
//extern bool requestPartialBlock; // if we should ask the AP to get this block from the host or not
void sleep_with_with_wakeup(uint32_t sleep_time_ms)
{
memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest));
memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo));
printf("sleep: %u\r\n", sleep_time_ms);
saveAonRam();
//memcpy((uint8_t *)&(*(volatile unsigned int *)0x130500), (uint8_t *)&curBlock, sizeof(struct blockRequest));
//memcpy((uint8_t *)&(*(volatile unsigned int *)0x130600), (uint8_t *)&curDataInfo, sizeof(struct AvailDataInfo));
//sleep_time_ms = 10000;
//printf("sleep! %u\n", sleep_time_ms);
uint32_t sleep_time_ms_1;
AON_level_VDD(7);
AON_level_VAA(0);
@@ -117,4 +122,4 @@ void sleep_with_with_wakeup(uint32_t sleep_time_ms)
Set_Wakeup_pin_rf(1);
Set_Wakeup_pin_nfc();
__WFI();
}
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <stdio.h>
//#include <stdio.h>
#include <stdint.h>
#include "core_cm3.h"
#include "mz100_gpio.h"

View File

@@ -129,6 +129,7 @@ void WDT_SetMode(WDT_Mode_Type mode)
void WDT_SetTimeoutVal(uint32_t timeoutVal)
{
/* set WDT timeout value */
// This value can be anything between 0x00 and 0x0F; this configures the WDT to reset at 2^(16+value) cycles (2^16 - 2^31)
WDT->TORR.BF.TOP = timeoutVal;
}

View File

@@ -0,0 +1,682 @@
#include "nfc.h"
//#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
#include "main.h"
#include "mz100_pinmux.h"
#include "mz100_gpio.h"
#include "mz100_wdt.h"
#include "mz100_clock.h"
#include "gpio.h"
#include "mz100_pmu.h"
#include "mz100_flash.h"
#include "eeprom.h"
#include "util.h"
#include "timer.h"
#include "epd.h"
#include "proto.h"
#include "printf.h"
#define WHO_AM_I 0x04
uint8_t i2c_address = 0xAA;
uint8_t nfc_available = 0;
void i2c_pins_init()
{
GPIO_PinOutputModeConfig(NFC_SCL, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_SCL, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_SCL, 0);
GPIO_SetPinDir(NFC_SCL, GPIO_OUTPUT);
GPIO_PinOutputModeConfig(NFC_SDA, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_SDA, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_SDA, 0);
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_POWER, 0);
GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_POWER, GPIO_IO_LOW);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_HIGH);
delay(500);
GPIO_WritePinOutput(NFC_POWER, GPIO_IO_HIGH);
delay(100);
}
void i2c_pins_sleep()
{
delay(500);
GPIO_PinOutputModeConfig(NFC_POWER, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_POWER, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_POWER, 0);
GPIO_SetPinDir(NFC_POWER, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_POWER, GPIO_IO_LOW);
GPIO_PinOutputModeConfig(NFC_SCL, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_SCL, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_SCL, 0);
GPIO_SetPinDir(NFC_SCL, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
GPIO_PinOutputModeConfig(NFC_SDA, PIN_OUTPUT_MODE_NORMAL_FUNCTION);
GPIO_PinModeConfig(NFC_SDA, PINMODE_DEFAULT);
GPIO_PinMuxFun(NFC_SDA, 0);
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
}
void i2c_start()
{
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
delay_us(1);
}
void i2c_stop()
{
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_HIGH);
delay_us(1);
}
void i2c_send_byte(char a1)
{
uint8_t v2 = 0;
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
do
{
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
delay_us(1);
if ((a1 & 0x80) != 0)
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_HIGH);
else
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
delay_us(1);
a1 *= 2;
v2++;
} while (v2 < 8);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
GPIO_SetPinDir(NFC_SDA, GPIO_INPUT);
delay_us(1);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
delay_us(1);
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
}
uint8_t i2c_receive_byte(int a1)
{
uint8_t v2 = 0;
uint8_t v3 = 0;
GPIO_SetPinDir(NFC_SDA, GPIO_INPUT);
GPIO_PinMuxFun(NFC_SDA, 0);
GPIO_PinModeConfig(NFC_SDA, PINMODE_PULLUP);
do
{
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
delay_us(1);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
delay_us(1);
v2 *= 2;
if (GPIO_ReadPinLevel(NFC_SDA))
v2 |= 1u;
v3++;
} while (v3 < 8);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
GPIO_SetPinDir(NFC_SDA, GPIO_OUTPUT);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
delay_us(1);
if (a1)
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
else
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_HIGH);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_HIGH);
delay_us(1);
GPIO_WritePinOutput(NFC_SCL, GPIO_IO_LOW);
GPIO_WritePinOutput(NFC_SDA, GPIO_IO_LOW);
GPIO_SetPinDir(NFC_SDA, GPIO_INPUT);
GPIO_PinMuxFun(NFC_SDA, 0);
GPIO_PinModeConfig(NFC_SDA, PINMODE_PULLUP);
return v2;
}
void i2c_send_buffer(uint8_t buffer[], uint8_t addr, uint8_t reg, int empty)
{
unsigned int v7 = 0;
delay_us(1);
i2c_start();
i2c_send_byte(addr);
i2c_send_byte(reg);
if (empty == 1)
{
i2c_send_byte(0);
i2c_send_byte(0);
i2c_send_byte(0);
}
else
{
do
{
i2c_send_byte(buffer[v7]);
v7++;
} while (v7 < 16);
}
i2c_stop();
}
void i2c_receive_buffer(uint8_t buffer[], uint8_t addr, uint8_t reg, uint32_t len, int a5)
{
uint32_t v8 = 0;
delay_us(1);
i2c_start();
i2c_send_byte(addr);
i2c_send_byte(reg);
if (a5 == 1)
i2c_send_byte(0);
i2c_stop();
i2c_start();
i2c_send_byte(addr + 1);
while (v8 < len)
{
buffer[v8++] = i2c_receive_byte(1);
}
i2c_stop();
}
void i2c_send_one_buffer(uint8_t new_address, int a1)
{
uint8_t v1[16] = {0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x10, 0xE1, 0x00};
if (a1 == 1)
{
v1[10] = 0xFF;
v1[11] = 0xFF;
}
i2c_send_buffer(v1, new_address, 0, 0);
delay(1560);
}
void i2c_receive_one_byte(uint8_t *test_byte, uint8_t addr, uint8_t reg, int a4, int a5)
{
i2c_start();
i2c_send_byte(addr);
i2c_send_byte(reg);
if (a5 == 1)
i2c_send_byte(0);
i2c_stop();
i2c_start();
i2c_send_byte(addr + 1);
*test_byte = i2c_receive_byte(1);
i2c_stop();
}
void nfc_send_16_byte_blocks(uint8_t buffer[], uint32_t len)
{
uint32_t v2 = 0;
uint16_t v5 = 1;
uint32_t v6 = 0;
i2c_pins_init();
if (len << 28)
v6 = (len >> 4) + 1;
else
v6 = len >> 4;
while (v2 < v6)
{
i2c_send_buffer(&buffer[16 * v2], i2c_address, v5++, 0);
v2++;
}
i2c_pins_sleep();
}
void nfc_erase()
{
uint8_t dowrite = 0;
uint8_t count_erased = 0;
uint8_t empty_buffer[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t read_temp_buffer[16];
for (int i = 0x01; i < 0x37; i++)
{
i2c_receive_buffer(read_temp_buffer, i2c_address, i, 16, 0);
for (int b = 0; b < 16; b++)
{
if (read_temp_buffer[b] != 0x00)
{
dowrite = 1;
break;
}
}
if (dowrite)
{
dowrite = 0;
count_erased++;
i2c_send_buffer(empty_buffer, i2c_address, i, 0);
}
}
printf("NFC Erase counter: %i\r\n", count_erased);
}
void nfc_set_default_config()
{
// Set default Config
uint8_t temp_config[8];
uint8_t expected_config[16] = {0x19, 0x00, 0xF8, 0x48, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
i2c_receive_buffer(temp_config, i2c_address, 0x3A, 8, 0);
if (memcmp(temp_config, expected_config, 8) != 0)
{
printf("Config rewriting\r\n");
i2c_send_buffer(expected_config, i2c_address, 0x3A, 0);
delay(1560);
}
// Set default Config END
}
/*
void nfc_dump_register()
{
uint8_t temp_dump[16];
printf("NFC:\r\n");
for (int i = 0; i < 0xff; i++)
{
if (i != 0x39 && (i < 0x3B || i > 0xF7) && i != 0xFC && i != 0xFD && i != 0xFE)
{
i2c_receive_buffer(temp_dump, i2c_address, i, 16, 0);
printf("REG 0x%02X :", i);
for (int i = 0; i < 16; i++)
{
printf(" %02X", temp_dump[i]);
}
printf("\r\n");
}
}
}
*/
void nfc_write_session(uint8_t index, uint8_t mask, uint8_t data)
{
i2c_start();
i2c_send_byte(i2c_address);
i2c_send_byte(0xFE);
i2c_send_byte(index);
i2c_send_byte(mask);
i2c_send_byte(data);
i2c_stop();
}
uint8_t nfc_read_session(uint8_t index)
{
uint8_t read_data = 0;
i2c_start();
i2c_send_byte(i2c_address);
i2c_send_byte(0xFE);
i2c_send_byte(index);
i2c_stop();
i2c_start();
i2c_send_byte(i2c_address + 1);
read_data = i2c_receive_byte(1);
i2c_stop();
return read_data;
}
/*
volatile uint8_t gpio7_triggered = 0;
void irq_gpio7(void)
{
// printf("GPIO_IRQ\r\n");
if ((nfc_read_session(0) & 0x40) != 1)
nfc_write_session(0, 0b01000001, 0b01000001);
gpio7_triggered = 1;
}
*/
void __attribute__((interrupt)) ExtPin7_IRQHandler(void)
{
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
GPIO_IntMask(NFC_IRQ, MASK);
NVIC_some_IRQ1(ExtPin7_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO7_INT);
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
}
void nfc_i2c_init()
{
uint8_t test_byte = 0;
i2c_pins_init();
i2c_receive_one_byte(&test_byte, i2c_address, 0, 1, 0);
if (test_byte != WHO_AM_I)
{
// printf("NFC device was not found at: %02X restoring now.\r\n", i2c_address);
for (int i = 0; i < 127; i++)
{
i2c_receive_one_byte(&test_byte, i << 1, 0, 1, 0);
if (test_byte == WHO_AM_I)
{
// printf("Found NFC device at: %02X restoring default now.\r\n", i << 1);
delay(50);
i2c_send_one_buffer(i << 1, 0);
break;
}
}
}
i2c_receive_one_byte(&test_byte, i2c_address, 0, 1, 0);
nfc_available = test_byte == WHO_AM_I;
if (nfc_available)
{
nfc_erase();
nfc_set_default_config();
}
// printf("I2C_CheckForNfcConnection = %d test_buffer = 0x%x \r\n", nfc_available, test_byte);
/*if (0) // Test SRAM HERE
{
printf("Writing now to SRAM of the NFC Chip\r\n");
// GPIO Interrupt
GPIO_IntConfig_Type gpio7_intConfg;
gpio7_intConfg.gpioIntFunc = ENABLE;
gpio7_intConfg.intLevel = GPIO_INT_EDGE_SENS;
gpio7_intConfg.intPol = GPIO_INT_ACTIVE_LOW;
GPIO_PinModeConfig(NFC_IRQ, PINMODE_PULLUP);
GPIO_PinMuxFun(NFC_IRQ, GPIO7_GPIO7);
GPIO_SetPinDir(NFC_IRQ, GPIO_INPUT);
GPIO_IntConfig(NFC_IRQ, &gpio7_intConfg);
GPIO_IntMask(NFC_IRQ, UNMASK);
GPIO_IntClr(NFC_IRQ);
install_int_callback(INT_GPIO, NFC_IRQ, irq_gpio7);
NVIC_ClearPendingIRQ(GPIO_IRQn);
NVIC_EnableIRQ(GPIO_IRQn);
// GPIO Interrupt END
nfc_dump_register();
printf("Enabling Pass-through mode now\r\n");
for (int i = 0; i < 8; i++)
{
printf(" %02X", nfc_read_session(i));
}
printf("\r\n");
printf("Writing now to SRAM of the NFC Chip\r\n");
uint8_t s_buffer[64];
for (int i = 0; i < sizeof(s_buffer); i++)
{
s_buffer[i] = i;
}
i2c_send_buffer(&s_buffer[0], i2c_address, 0xF8, 0);
i2c_send_buffer(&s_buffer[16], i2c_address, 0xF9, 0);
i2c_send_buffer(&s_buffer[32], i2c_address, 0xFA, 0);
i2c_send_buffer(&s_buffer[48], i2c_address, 0xFB, 0);
while (0)
{
if (gpio7_triggered)
{
gpio7_triggered = 0;
printf("Received the following data via NFC:\r\n");
for (int i = 0; i < sizeof(s_buffer); i++)
{
s_buffer[i] = i;
}
i2c_send_buffer(&s_buffer[0], i2c_address, 0xF8, 0);
i2c_send_buffer(&s_buffer[16], i2c_address, 0xF9, 0);
i2c_send_buffer(&s_buffer[32], i2c_address, 0xFA, 0);
i2c_send_buffer(&s_buffer[48], i2c_address, 0xFB, 0);
i2c_receive_buffer(s_buffer, i2c_address, 0xF8, 16, 0);
for (int i = 0; i < 16; i++)
{
printf(" %02X", s_buffer[i]);
}
printf("\r\n");
}
WDT_RestartCounter();
}
}*/
i2c_pins_sleep();
}
extern void uiPrvDrawLatestImage(const struct EepromContentsInfo *eci);
extern void prvWriteNewHeader(struct EepromImageHeader *eih, uint32_t addr, uint32_t eeSize, uint64_t ver, uint32_t size);
extern void prvEepromIndex(struct EepromContentsInfo *eci);
// This will get allready checked cmds buffer and can directly being used
/*
CMD 0x01:
Get infos of the E-Paper Display like screen size etc.
29 bytes of answer available TO BE DEFINED :)
CMD 0x10:
Erase IMAGE AREA. EEPROM_IMG_START to EEPROM_IMG_EACH
expected_size = (buff_int[5] << 16) | (buff_int[6] << 8) | buff_int[7]
CMD 0x11:
Write to IMAGE AREA. EEPROM_IMG_START + address
address (buff[1] << 16) |(buff[2] << 8) | buff[3]
data buff[4] up to len
CMD 0x12:
Read from IMAGE AREA. EEPROM_IMG_START + address
address (buff[1] << 16) |(buff[2] << 8) | buff[3]
len buff[4], MAX 32-5
CMD 0x13:
Finish upload and display image
*/
void reply_nfc_cmd(uint8_t buff_out[], int len_out)
{
uint8_t buffer_out[32];
uint16_t crc_checked = 0x0000;
for (uint32_t i = 0; i < sizeof(buffer_out) - 2; i++)
{
if (i < len_out)
buffer_out[i] = buff_out[i];
else
buff_out[i] = 0x00;
crc_checked = crc16(crc_checked, buffer_out[i]);
}
buffer_out[sizeof(buffer_out) - 2] = crc_checked >> 8;
buffer_out[sizeof(buffer_out) - 1] = crc_checked & 0xff;
/*printf("BUFFER_OUT_DUMP:\r\n");
for (int i = 0; i < sizeof(buffer_out); i++)
{
printf(" %02X", buffer_out[i]);
}
printf("\r\n");*/
nfc_write_session(0, 0b00000001, 0b00000000);
i2c_send_buffer(&buffer_out[0], i2c_address, 0xF8, 0);
i2c_send_buffer(&buffer_out[16], i2c_address, 0xF9, 0);
nfc_write_session(0, 0b00000001, 0b00000001);
}
uint8_t should_finish_it = 0;
void handle_nfc_cmd(uint8_t buff_int[], int len_in)
{
uint8_t buff_out[30];
uint8_t cmd = buff_int[0];
uint32_t address = (buff_int[1] << 16) | (buff_int[2] << 8) | buff_int[3];
uint8_t len = buff_int[4];
uint8_t *data_buff = &buff_int[5];
buff_out[0] = 0xFE; // NACK 0xFA = ACK
if (len > (len_in - 5))
{
printf("len to big %i\r\n", len);
reply_nfc_cmd(buff_out, 1);
return;
}
switch (cmd)
{
case 0x01:
{
memset(buff_out, 0x00, sizeof(buff_out));
uint16_t temperature_c = measureTemp();
uint16_t battery_voltage = measureBattery();
buff_out[0] = 0xFA;
buff_out[1] = ((uint16_t)DISPLAY_WIDTH) >> 8;
buff_out[2] = ((uint8_t)DISPLAY_WIDTH);
buff_out[3] = ((uint16_t)DISPLAY_HEIGHT) >> 8;
buff_out[4] = ((uint8_t)DISPLAY_HEIGHT);
buff_out[5] = ((uint16_t)DISPLAY_WIDTH_MM) >> 8;
buff_out[6] = ((uint8_t)DISPLAY_WIDTH_MM);
buff_out[7] = ((uint16_t)DISPLAY_HEIGHT_MM) >> 8;
buff_out[8] = ((uint8_t)DISPLAY_HEIGHT_MM);
buff_out[9] = HW_TYPE_74_INCH_BWR;
buff_out[10] = temperature_c >> 8;
buff_out[11] = temperature_c;
buff_out[12] = battery_voltage >> 8;
buff_out[13] = battery_voltage;
reply_nfc_cmd(buff_out, 30);
break;
}
case 0x10:
{
buff_out[0] = 0xFA;
reply_nfc_cmd(buff_out, 1);
// Here lets write a new header into the image area. lets set the current version plus one so RF can upload a new one
uint32_t expected_size = (data_buff[0] << 16) | (data_buff[1] << 8) | data_buff[2];
printf("Expected size: %i\r\n", expected_size);
if (expected_size > EEPROM_IMG_EACH)
{
reply_nfc_cmd(buff_out, 1);
return;
}
struct EepromImageHeader eih;
FLASH_Read(0, EEPROM_IMG_START, (uint8_t *)&eih, sizeof(struct EepromImageHeader));
prvWriteNewHeader(&eih, EEPROM_IMG_START, EEPROM_IMG_EACH, eih.version + 1, expected_size);
break;
}
case 0x11:
{
if ((address + len) < (EEPROM_IMG_EACH - sizeof(struct EepromImageHeader)))
{
buff_out[0] = 0xFA;
reply_nfc_cmd(buff_out, 1);
printf("Wrinting at: %08X len %i\r\n", EEPROM_IMG_START + address + sizeof(struct EepromImageHeader), len);
FLASH_Write(false, EEPROM_IMG_START + address + sizeof(struct EepromImageHeader), data_buff, len);
}
break;
}
case 0x12:
{
if (address + len < EEPROM_IMG_EACH)
{
if (len < (sizeof(buff_out) - 1))
{
buff_out[0] = 0xFA;
reply_nfc_cmd(buff_out, 1);
FLASH_Read(false, EEPROM_IMG_START + address, &buff_out[1], len);
}
}
break;
}
case 0x13:
{
buff_out[0] = 0xFA;
reply_nfc_cmd(buff_out, 1);
struct EepromImageHeader eih;
FLASH_Read(0, EEPROM_IMG_START, (uint8_t *)&eih, sizeof(struct EepromImageHeader));
eih.validMarker = EEPROM_IMG_VALID;
FLASH_Write(false, EEPROM_IMG_START + offsetof(struct EepromImageHeader, validMarker), (uint8_t *)&eih.validMarker, sizeof(eih.validMarker));
should_finish_it = 1;
break;
}
default:
{
reply_nfc_cmd(buff_out, 1);
break;
}
}
}
uint8_t nfc_handle()
{
NVIC_DisableIRQ(ExtPin7_IRQn);
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
GPIO_IntMask(NFC_IRQ, MASK);
NVIC_some_IRQ1(ExtPin7_IRQn);
PMU_ClearWakeupExtpin(PMU_GPIO7_INT);
NVIC_ClearPendingIRQ(ExtPin7_IRQn);
GPIO_PinModeConfig(NFC_IRQ, PINMODE_PULLUP);
GPIO_PinMuxFun(NFC_IRQ, GPIO7_GPIO7);
GPIO_SetPinDir(NFC_IRQ, GPIO_INPUT);
if (GPIO_ReadPinLevel(NFC_IRQ) == 1) // Do nothing no NFC connection notified
return 0;
i2c_pins_init();
uint32_t last_comms = 0;
uint8_t temp_pinstate = 0;
while (1)
{
if (GPIO_ReadPinLevel(NFC_IRQ) == 0)
{
if (temp_pinstate == 0)
{
temp_pinstate = 1;
uint8_t sess_reg0 = nfc_read_session(0);
if ((sess_reg0 & 0x40) != 1)
nfc_write_session(0, 0b01000001, 0b01000001);
}
}
else
{
temp_pinstate = 0;
}
uint8_t ns_reg = nfc_read_session(6);
if (ns_reg == 0x51)
{
last_comms = timerGet();
// printf("NS_REG %i %i %i %i %i %i %i %i : ", (ns_reg >> 7) & 1, (ns_reg >> 6) & 1, (ns_reg >> 5) & 1, (ns_reg >> 4) & 1, (ns_reg >> 3) & 1, (ns_reg >> 2) & 1, (ns_reg >> 1) & 1, ns_reg & 1);
uint8_t buffer_in[64];
i2c_receive_buffer(&buffer_in[0], i2c_address, 0xF8, 16, 0);
i2c_receive_buffer(&buffer_in[16], i2c_address, 0xF9, 16, 0);
i2c_receive_buffer(&buffer_in[32], i2c_address, 0xFA, 16, 0);
i2c_receive_buffer(&buffer_in[48], i2c_address, 0xFB, 16, 0);
uint16_t crc_checked = 0x0000;
uint16_t crc_in = (buffer_in[sizeof(buffer_in) - 2] << 8) | buffer_in[sizeof(buffer_in) - 1];
for (uint32_t i = 0; i < sizeof(buffer_in) - 2; i++)
{
crc_checked = crc16(crc_checked, buffer_in[i]);
}
if (crc_checked == crc_in)
{
handle_nfc_cmd(buffer_in, 62);
}
/*for (int i = 0; i < 64; i++)
{
printf(" %02X", buffer_in[i]);
}
printf("\r\n");*/
}
if (timerGet() - last_comms > TIMER_TICKS_PER_MSEC * 6000)
{
printf("NFCout\r\n");
break;
}
if (should_finish_it && timerGet() - last_comms > TIMER_TICKS_PER_MSEC * 500)
break;
WDT_RestartCounter();
}
i2c_pins_sleep();
if (should_finish_it)
{
should_finish_it = 0;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,25 @@
#pragma once
//#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "core_cm3.h"
#include "mz100_pinmux.h"
#include "mz100_gpio.h"
#include "gpio.h"
#include "util.h"
void i2c_pins_init();
void i2c_pins_sleep();
void i2c_start();
void i2c_stop();
void i2c_send_byte(char a1);
uint8_t i2c_receive_byte(int a1);
void i2c_send_buffer(uint8_t buffer[], uint8_t addr, uint8_t reg, int empty);
void i2c_receive_buffer(uint8_t buffer[], uint8_t addr, uint8_t reg, uint32_t len, int a5);
void i2c_send_one_buffer(uint8_t new_address, int a1);
void i2c_receive_one_byte(uint8_t *test_byte, uint8_t addr, uint8_t reg, int a4, int a5);
void nfc_send_16_byte_blocks(uint8_t buffer[], uint32_t len);
void nfc_i2c_init();
uint8_t nfc_handle();
void nfc_erase();

View File

@@ -0,0 +1,914 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and (v)snprintf implementation, optimized for speed on
// embedded systems with a very limited resources. These routines are thread
// safe and reentrant!
// Use this instead of the bloated standard/newlib printf cause these use
// malloc for printf (and may not be thread safe).
//
///////////////////////////////////////////////////////////////////////////////
#include <stdbool.h>
#include <stdint.h>
#include "printf.h"
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
// printf_config.h header file
// default: undefined
#ifdef PRINTF_INCLUDE_CONFIG_H
#include "printf_config.h"
#endif
// 'ntoa' conversion buffer size, this must be big enough to hold one converted
// numeric number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif
// 'ftoa' conversion buffer size, this must be big enough to hold one converted
// float number including padded zeros (dynamically created on stack)
// default: 32 byte
#ifndef PRINTF_FTOA_BUFFER_SIZE
#define PRINTF_FTOA_BUFFER_SIZE 32U
#endif
// support for the floating point type (%f)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
#define PRINTF_SUPPORT_FLOAT
#endif
// support for exponential floating point notation (%e/%g)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
#define PRINTF_SUPPORT_EXPONENTIAL
#endif
// define the default floating point precision
// default: 6 digits
#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
#define PRINTF_DEFAULT_FLOAT_PRECISION 6U
#endif
// define the largest float suitable to print with %f
// default: 1e9
#ifndef PRINTF_MAX_FLOAT
#define PRINTF_MAX_FLOAT 1e9
#endif
// support for the long long types (%llu or %p)
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
#define PRINTF_SUPPORT_LONG_LONG
#endif
// support for the ptrdiff_t type (%t)
// ptrdiff_t is normally defined in <stddef.h> as long or long long type
// default: activated
#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
#define PRINTF_SUPPORT_PTRDIFF_T
#endif
///////////////////////////////////////////////////////////////////////////////
// internal flag definitions
#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)
// import float.h for DBL_MAX
#if defined(PRINTF_SUPPORT_FLOAT)
#include <float.h>
#endif
// output function type
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);
// wrapper (used as buffer) for output function type
typedef struct {
void (*fct)(char character, void* arg);
void* arg;
} out_fct_wrap_type;
// internal buffer output
static inline void _out_buffer(char character, void* buffer, size_t idx, size_t maxlen)
{
if (idx < maxlen) {
((char*)buffer)[idx] = character;
}
}
// internal null output
static inline void _out_null(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)character; (void)buffer; (void)idx; (void)maxlen;
}
// internal _putchar wrapper
static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)buffer; (void)idx; (void)maxlen;
if (character) {
_putchar(character);
}
}
// internal output function wrapper
static inline void _out_fct(char character, void* buffer, size_t idx, size_t maxlen)
{
(void)idx; (void)maxlen;
if (character) {
// buffer is the output fct pointer
((out_fct_wrap_type*)buffer)->fct(character, ((out_fct_wrap_type*)buffer)->arg);
}
}
// internal secure strlen
// \return The length of the string (excluding the terminating 0) limited by 'maxsize'
static inline unsigned int _strnlen_s(const char* str, size_t maxsize)
{
const char* s;
for (s = str; *s && maxsize--; ++s);
return (unsigned int)(s - str);
}
// internal test if char is a digit (0-9)
// \return true if char is a digit
static inline bool _is_digit(char ch)
{
return (ch >= '0') && (ch <= '9');
}
// internal ASCII string to unsigned int conversion
static unsigned int _atoi(const char** str)
{
unsigned int i = 0U;
while (_is_digit(**str)) {
i = i * 10U + (unsigned int)(*((*str)++) - '0');
}
return i;
}
// output the specified string in reverse, taking care of any zero-padding
static size_t _out_rev(out_fct_type out, char* buffer, size_t idx, size_t maxlen, const char* buf, size_t len, unsigned int width, unsigned int flags)
{
const size_t start_idx = idx;
// pad spaces up to given width
if (!(flags & FLAGS_LEFT) && !(flags & FLAGS_ZEROPAD)) {
for (size_t i = len; i < width; i++) {
out(' ', buffer, idx++, maxlen);
}
}
// reverse string
while (len) {
out(buf[--len], buffer, idx++, maxlen);
}
// append pad spaces up to given width
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) {
out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
// internal itoa format
static size_t _ntoa_format(out_fct_type out, char* buffer, size_t idx, size_t maxlen, char* buf, size_t len, bool negative, unsigned int base, unsigned int prec, unsigned int width, unsigned int flags)
{
// pad leading zeros
if (!(flags & FLAGS_LEFT)) {
if (width && (flags & FLAGS_ZEROPAD) && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
while ((flags & FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
// handle hash
if (flags & FLAGS_HASH) {
if (!(flags & FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
len--;
if (len && (base == 16U)) {
len--;
}
}
if ((base == 16U) && !(flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'x';
}
else if ((base == 16U) && (flags & FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'X';
}
else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
buf[len++] = 'b';
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
buf[len++] = '0';
}
}
if (len < PRINTF_NTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal itoa for 'long' type
static size_t _ntoa_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long value, bool negative, unsigned long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
// internal itoa for 'long long' type
#if defined(PRINTF_SUPPORT_LONG_LONG)
static size_t _ntoa_long_long(out_fct_type out, char* buffer, size_t idx, size_t maxlen, unsigned long long value, bool negative, unsigned long long base, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_NTOA_BUFFER_SIZE];
size_t len = 0U;
// no hash for 0 values
if (!value) {
flags &= ~FLAGS_HASH;
}
// write if precision != 0 and value is != 0
if (!(flags & FLAGS_PRECISION) || value) {
do {
const char digit = (char)(value % base);
buf[len++] = digit < 10 ? '0' + digit : (flags & FLAGS_UPPERCASE ? 'A' : 'a') + digit - 10;
value /= base;
} while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
}
return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (unsigned int)base, prec, width, flags);
}
#endif // PRINTF_SUPPORT_LONG_LONG
#if defined(PRINTF_SUPPORT_FLOAT)
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// forward declaration so that _ftoa can switch to exp notation for values > PRINTF_MAX_FLOAT
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags);
#endif
// internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
char buf[PRINTF_FTOA_BUFFER_SIZE];
size_t len = 0U;
double diff = 0.0;
// powers of 10
static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
// test for special values
if (value != value)
return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
if (value < -DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
if (value > DBL_MAX)
return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
// test for very large values
// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
return 0U;
#endif
}
// test for negative
bool negative = false;
if (value < 0) {
negative = true;
value = 0 - value;
}
// set default precision, if not set explicitly
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
buf[len++] = '0';
prec--;
}
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
unsigned long frac = (unsigned long)tmp;
diff = tmp - frac;
if (diff > 0.5) {
++frac;
// handle rollover, e.g. case 0.99 with prec 1 is 1.0
if (frac >= pow10[prec]) {
frac = 0;
++whole;
}
}
else if (diff < 0.5) {
}
else if ((frac == 0U) || (frac & 1U)) {
// if halfway, round up if odd OR if last digit is 0
++frac;
}
if (prec == 0U) {
diff = value - (double)whole;
if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
// exactly 0.5 and ODD, then round up
// 1.5 -> 2, but 2.5 -> 2
++whole;
}
}
else {
unsigned int count = prec;
// now do fractional part, as an unsigned number
while (len < PRINTF_FTOA_BUFFER_SIZE) {
--count;
buf[len++] = (char)(48U + (frac % 10U));
if (!(frac /= 10U)) {
break;
}
}
// add extra 0s
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
buf[len++] = '0';
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
// add decimal
buf[len++] = '.';
}
}
// do whole part, number is reversed
while (len < PRINTF_FTOA_BUFFER_SIZE) {
buf[len++] = (char)(48 + (whole % 10));
if (!(whole /= 10)) {
break;
}
}
// pad leading zeros
if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD)) {
if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE)))) {
width--;
}
while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
buf[len++] = '0';
}
}
if (len < PRINTF_FTOA_BUFFER_SIZE) {
if (negative) {
buf[len++] = '-';
}
else if (flags & FLAGS_PLUS) {
buf[len++] = '+'; // ignore the space if the '+' exists
}
else if (flags & FLAGS_SPACE) {
buf[len++] = ' ';
}
}
return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
// internal ftoa variant for exponential floating-point type, contributed by Martijn Jasperse <m.jasperse@gmail.com>
static size_t _etoa(out_fct_type out, char* buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
// check for NaN and special values
if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
}
// determine the sign
const bool negative = value < 0;
if (negative) {
value = -value;
}
// default precision
if (!(flags & FLAGS_PRECISION)) {
prec = PRINTF_DEFAULT_FLOAT_PRECISION;
}
// determine the decimal exponent
// based on the algorithm by David Gay (https://www.ampl.com/netlib/fp/dtoa.c)
union {
uint64_t U;
double F;
} conv;
conv.F = value;
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U); // drop the exponent so conv.F is now in [1,2)
// now approximate log10 from the log2 integer part and an expansion of ln around 1.5
int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
// now we want to compute 10^expval but we want to be sure it won't overflow
exp2 = (int)(expval * 3.321928094887362 + 0.5);
const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
const double z2 = z * z;
conv.U = (uint64_t)(exp2 + 1023) << 52U;
// compute exp(z) using continued fractions, see https://en.wikipedia.org/wiki/Exponential_function#Continued_fractions_for_ex
conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
// correct for rounding errors
if (value < conv.F) {
expval--;
conv.F /= 10;
}
// the exponent format is "%+03d" and largest value is "307", so set aside 4-5 characters
unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
// in "%g" mode, "prec" is the number of *significant figures* not decimals
if (flags & FLAGS_ADAPT_EXP) {
// do we want to fall-back to "%f" mode?
if ((value >= 1e-4) && (value < 1e6)) {
if ((int)prec > expval) {
prec = (unsigned)((int)prec - expval - 1);
}
else {
prec = 0;
}
flags |= FLAGS_PRECISION; // make sure _ftoa respects precision
// no characters in exponent
minwidth = 0U;
expval = 0;
}
else {
// we use one sigfig for the whole part
if ((prec > 0) && (flags & FLAGS_PRECISION)) {
--prec;
}
}
}
// will everything fit?
unsigned int fwidth = width;
if (width > minwidth) {
// we didn't fall-back so subtract the characters required for the exponent
fwidth -= minwidth;
} else {
// not enough characters, so go back to default sizing
fwidth = 0U;
}
if ((flags & FLAGS_LEFT) && minwidth) {
// if we're padding on the right, DON'T pad the floating part
fwidth = 0U;
}
// rescale the float value
if (expval) {
value /= conv.F;
}
// output the floating part
const size_t start_idx = idx;
idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~FLAGS_ADAPT_EXP);
// output the exponent part
if (minwidth) {
// output the exponential symbol
out((flags & FLAGS_UPPERCASE) ? 'E' : 'e', buffer, idx++, maxlen);
// output the exponent value
idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1, FLAGS_ZEROPAD | FLAGS_PLUS);
// might need to right-pad spaces
if (flags & FLAGS_LEFT) {
while (idx - start_idx < width) out(' ', buffer, idx++, maxlen);
}
}
return idx;
}
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
// internal vsnprintf
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
{
unsigned int flags, width, precision, n;
size_t idx = 0U;
if (!buffer) {
// use null output function
out = _out_null;
}
while (*format)
{
// format specifier? %[flags][width][.precision][length]
if (*format != '%') {
// no
out(*format, buffer, idx++, maxlen);
format++;
continue;
}
else {
// yes, evaluate it
format++;
}
// evaluate flags
flags = 0U;
do {
switch (*format) {
case '0': flags |= FLAGS_ZEROPAD; format++; n = 1U; break;
case '-': flags |= FLAGS_LEFT; format++; n = 1U; break;
case '+': flags |= FLAGS_PLUS; format++; n = 1U; break;
case ' ': flags |= FLAGS_SPACE; format++; n = 1U; break;
case '#': flags |= FLAGS_HASH; format++; n = 1U; break;
default : n = 0U; break;
}
} while (n);
// evaluate width field
width = 0U;
if (_is_digit(*format)) {
width = _atoi(&format);
}
else if (*format == '*') {
const int w = va_arg(va, int);
if (w < 0) {
flags |= FLAGS_LEFT; // reverse padding
width = (unsigned int)-w;
}
else {
width = (unsigned int)w;
}
format++;
}
// evaluate precision field
precision = 0U;
if (*format == '.') {
flags |= FLAGS_PRECISION;
format++;
if (_is_digit(*format)) {
precision = _atoi(&format);
}
else if (*format == '*') {
const int prec = (int)va_arg(va, int);
precision = prec > 0 ? (unsigned int)prec : 0U;
format++;
}
}
// evaluate length field
switch (*format) {
case 'l' :
flags |= FLAGS_LONG;
format++;
if (*format == 'l') {
flags |= FLAGS_LONG_LONG;
format++;
}
break;
case 'h' :
flags |= FLAGS_SHORT;
format++;
if (*format == 'h') {
flags |= FLAGS_CHAR;
format++;
}
break;
#if defined(PRINTF_SUPPORT_PTRDIFF_T)
case 't' :
flags |= (sizeof(ptrdiff_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
#endif
case 'j' :
flags |= (sizeof(intmax_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
case 'z' :
flags |= (sizeof(size_t) == sizeof(long) ? FLAGS_LONG : FLAGS_LONG_LONG);
format++;
break;
default :
break;
}
// evaluate specifier
switch (*format) {
case 'd' :
case 'i' :
case 'u' :
case 'x' :
case 'X' :
case 'o' :
case 'b' : {
// set the base
unsigned int base;
if (*format == 'x' || *format == 'X') {
base = 16U;
}
else if (*format == 'o') {
base = 8U;
}
else if (*format == 'b') {
base = 2U;
}
else {
base = 10U;
flags &= ~FLAGS_HASH; // no hash for dec format
}
// uppercase
if (*format == 'X') {
flags |= FLAGS_UPPERCASE;
}
// no plus or space flag for u, x, X, o, b
if ((*format != 'i') && (*format != 'd')) {
flags &= ~(FLAGS_PLUS | FLAGS_SPACE);
}
// ignore '0' flag when precision is given
if (flags & FLAGS_PRECISION) {
flags &= ~FLAGS_ZEROPAD;
}
// convert the integer
if ((*format == 'i') || (*format == 'd')) {
// signed
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
const long long value = va_arg(va, long long);
idx = _ntoa_long_long(out, buffer, idx, maxlen, (unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
const long value = va_arg(va, long);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
else {
const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
}
}
else {
// unsigned
if (flags & FLAGS_LONG_LONG) {
#if defined(PRINTF_SUPPORT_LONG_LONG)
idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va, unsigned long long), false, base, precision, width, flags);
#endif
}
else if (flags & FLAGS_LONG) {
idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va, unsigned long), false, base, precision, width, flags);
}
else {
const unsigned int value = (flags & FLAGS_CHAR) ? (unsigned char)va_arg(va, unsigned int) : (flags & FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
idx = _ntoa_long(out, buffer, idx, maxlen, value, false, base, precision, width, flags);
}
}
format++;
break;
}
#if defined(PRINTF_SUPPORT_FLOAT)
case 'f' :
case 'F' :
if (*format == 'F') flags |= FLAGS_UPPERCASE;
idx = _ftoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
case 'e':
case 'E':
case 'g':
case 'G':
if ((*format == 'g')||(*format == 'G')) flags |= FLAGS_ADAPT_EXP;
if ((*format == 'E')||(*format == 'G')) flags |= FLAGS_UPPERCASE;
idx = _etoa(out, buffer, idx, maxlen, va_arg(va, double), precision, width, flags);
format++;
break;
#endif // PRINTF_SUPPORT_EXPONENTIAL
#endif // PRINTF_SUPPORT_FLOAT
case 'c' : {
unsigned int l = 1U;
// pre padding
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// char output
out((char)va_arg(va, int), buffer, idx++, maxlen);
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 's' : {
const char* p = va_arg(va, char*);
unsigned int l = _strnlen_s(p, precision ? precision : (size_t)-1);
// pre padding
if (flags & FLAGS_PRECISION) {
l = (l < precision ? l : precision);
}
if (!(flags & FLAGS_LEFT)) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
// string output
while ((*p != 0) && (!(flags & FLAGS_PRECISION) || precision--)) {
out(*(p++), buffer, idx++, maxlen);
}
// post padding
if (flags & FLAGS_LEFT) {
while (l++ < width) {
out(' ', buffer, idx++, maxlen);
}
}
format++;
break;
}
case 'p' : {
width = sizeof(void*) * 2U;
flags |= FLAGS_ZEROPAD | FLAGS_UPPERCASE;
#if defined(PRINTF_SUPPORT_LONG_LONG)
const bool is_ll = sizeof(uintptr_t) == sizeof(long long);
if (is_ll) {
idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va, void*), false, 16U, precision, width, flags);
}
else {
#endif
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)((uintptr_t)va_arg(va, void*)), false, 16U, precision, width, flags);
#if defined(PRINTF_SUPPORT_LONG_LONG)
}
#endif
format++;
break;
}
case '%' :
out('%', buffer, idx++, maxlen);
format++;
break;
default :
out(*format, buffer, idx++, maxlen);
format++;
break;
}
}
// termination
out((char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
// return written chars without terminating \0
return (int)idx;
}
///////////////////////////////////////////////////////////////////////////////
int printf_(const char* format, ...)
{
va_list va;
va_start(va, format);
char buffer[1];
const int ret = _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int sprintf_(char* buffer, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, (size_t)-1, format, va);
va_end(va);
return ret;
}
int snprintf_(char* buffer, size_t count, const char* format, ...)
{
va_list va;
va_start(va, format);
const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
va_end(va);
return ret;
}
int vprintf_(const char* format, va_list va)
{
char buffer[1];
return _vsnprintf(_out_char, buffer, (size_t)-1, format, va);
}
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va)
{
return _vsnprintf(_out_buffer, buffer, count, format, va);
}
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...)
{
va_list va;
va_start(va, format);
const out_fct_wrap_type out_fct_wrap = { out, arg };
const int ret = _vsnprintf(_out_fct, (char*)(uintptr_t)&out_fct_wrap, (size_t)-1, format, va);
va_end(va);
return ret;
}

View File

@@ -0,0 +1,116 @@
///////////////////////////////////////////////////////////////////////////////
// \author (c) Marco Paland (info@paland.com)
// 2014-2019, PALANDesign Hannover, Germany
//
// \license The MIT License (MIT)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// \brief Tiny printf, sprintf and snprintf implementation, optimized for speed on
// embedded systems with a very limited resources.
// Use this instead of bloated standard/newlib printf.
// These routines are thread safe and reentrant.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef _PRINTF_H_
#define _PRINTF_H_
#include <stdarg.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Output a character to a custom device like UART, used by the printf() function
* This function is declared here only. You have to write your custom implementation somewhere
* \param character Character to output
*/
void _putchar(char character);
/**
* Tiny printf implementation
* You have to implement _putchar if you use printf()
* To avoid conflicts with the regular printf() API it is overridden by macro defines
* and internal underscore-appended functions like printf_() are used
* \param format A string that specifies the format of the output
* \return The number of characters that are written into the array, not counting the terminating null character
*/
#define printf printf_
int printf_(const char* format, ...);
/**
* Tiny sprintf implementation
* Due to security reasons (buffer overflow) YOU SHOULD CONSIDER USING (V)SNPRINTF INSTEAD!
* \param buffer A pointer to the buffer where to store the formatted string. MUST be big enough to store the output!
* \param format A string that specifies the format of the output
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define sprintf sprintf_
int sprintf_(char* buffer, const char* format, ...);
/**
* Tiny snprintf/vsnprintf implementation
* \param buffer A pointer to the buffer where to store the formatted string
* \param count The maximum number of characters to store in the buffer, including a terminating null character
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that COULD have been written into the buffer, not counting the terminating
* null character. A value equal or larger than count indicates truncation. Only when the returned value
* is non-negative and less than count, the string has been completely written.
*/
#define snprintf snprintf_
#define vsnprintf vsnprintf_
int snprintf_(char* buffer, size_t count, const char* format, ...);
int vsnprintf_(char* buffer, size_t count, const char* format, va_list va);
/**
* Tiny vprintf implementation
* \param format A string that specifies the format of the output
* \param va A value identifying a variable arguments list
* \return The number of characters that are WRITTEN into the buffer, not counting the terminating null character
*/
#define vprintf vprintf_
int vprintf_(const char* format, va_list va);
/**
* printf with output function
* You may use this as dynamic alternative to printf() with its fixed _putchar() output
* \param out An output function which takes one character and an argument pointer
* \param arg An argument pointer for user data passed to output function
* \param format A string that specifies the format of the output
* \return The number of characters that are sent to the output function, not counting the terminating null character
*/
int fctprintf(void (*out)(char character, void* arg), void* arg, const char* format, ...);
#ifdef __cplusplus
}
#endif
#endif // _PRINTF_H_

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