diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9928f2fb..b89bf0276 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,8 @@ All notable changes to this project will be documented in this file.
### Breaking Changed
### Changed
+- ESP32 Platform from 2025.07.31 to 2025.08.30, Framework (Arduino Core) from v3.1.3.250712 to v3.1.3.250808 and IDF from v5.3.3.250707 to v5.3.3.250801 (#23778)
+- Epdiy library from v1.0.0 to v2.0.0
### Fixed
- Syslog RFC5424 compliance (#23509)
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index b6db3c06d..613810fda 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -132,8 +132,9 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
### Breaking Changed
### Changed
-- ESP32 Platform from 2025.05.30 to 2025.07.31, Framework (Arduino Core) from v3.1.3.250504 to v3.1.3.250712 and IDF from v5.3.3.250501 to v5.3.3.250707 [#23685](https://github.com/arendst/Tasmota/issues/23685)
- ESP8266 platform update from 2025.05.00 to 2025.07.00 [#23700](https://github.com/arendst/Tasmota/issues/23700)
+- ESP32 Platform from 2025.05.30 to 2025.08.30, Framework (Arduino Core) from v3.1.3.250504 to v3.1.3.250808 and IDF from v5.3.3.250501 to v5.3.3.250801 [#23778](https://github.com/arendst/Tasmota/issues/23778)
+- Epdiy library from v1.0.0 to v2.0.0
- OpenTherm library from v0.9.0 to v1.1.5 [#23704](https://github.com/arendst/Tasmota/issues/23704)
- Library names [#23560](https://github.com/arendst/Tasmota/issues/23560)
- CSS uses named colors variables [#23597](https://github.com/arendst/Tasmota/issues/23597)
diff --git a/lib/libesp32_eink/epdiy/.clang-format b/lib/libesp32_eink/epdiy/.clang-format
new file mode 100644
index 000000000..a05539ca4
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/.clang-format
@@ -0,0 +1,11 @@
+BasedOnStyle: chromium
+IndentWidth: 4
+ColumnLimit: 100
+AlignAfterOpenBracket: BlockIndent
+IncludeBlocks: Preserve
+BreakBeforeBinaryOperators: All
+Cpp11BracedListStyle: false
+AllowAllParametersOfDeclarationOnNextLine: true
+BinPackArguments: false
+BinPackParameters: false
+SortIncludes: false
diff --git a/lib/libesp32_eink/epdiy/.gitignore b/lib/libesp32_eink/epdiy/.gitignore
index b7b2db4a8..5ab771df7 100755
--- a/lib/libesp32_eink/epdiy/.gitignore
+++ b/lib/libesp32_eink/epdiy/.gitignore
@@ -1,6 +1,9 @@
.pio
+.vscode
build/
+build.clang
sdkconfig.old
+sdkconfig
**/build/
.ccls-cache
doc/source/xml/
@@ -16,3 +19,10 @@ fp-info-cache
__pycache__
examples/weather/components
sdkconfig
+managed_components/
+epaper-breakout-backups/
+dependencies.lock
+ED*.h
+ES*.h
+examples/private_*/
+*.code-workspace
diff --git a/lib/libesp32_eink/epdiy/.gitmodules b/lib/libesp32_eink/epdiy/.gitmodules
deleted file mode 100755
index c7efb9205..000000000
--- a/lib/libesp32_eink/epdiy/.gitmodules
+++ /dev/null
@@ -1,6 +0,0 @@
-[submodule "hardware/epaper-breakout/esp32-wrover-kicad"]
- path = hardware/epaper-breakout/esp32-wrover-kicad
- url = https://github.com/aliafshar/esp32-wrover-kicad
-[submodule "hardware/epaper-breakout/tp4056"]
- path = hardware/epaper-breakout/tp4056
- url = https://github.com/alltheworld/tp4056/
diff --git a/lib/libesp32_eink/epdiy/.readthedocs.yml b/lib/libesp32_eink/epdiy/.readthedocs.yml
index 4d21d9b40..e7c2b25d5 100755
--- a/lib/libesp32_eink/epdiy/.readthedocs.yml
+++ b/lib/libesp32_eink/epdiy/.readthedocs.yml
@@ -12,8 +12,12 @@ sphinx:
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
+build:
+ os: ubuntu-22.04
+ tools:
+ python: "3.11"
+
# Optionally set the version of Python and requirements required to build your docs
python:
- version: 3.7
install:
- requirements: doc/requirements.txt
diff --git a/lib/libesp32_eink/epdiy/LICENSE b/lib/libesp32_eink/epdiy/LICENSE
new file mode 100644
index 000000000..0a041280b
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/LICENSE
@@ -0,0 +1,165 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+ This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+ 0. Additional Definitions.
+
+ As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+ "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+ An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+ A "Combined Work" is a work produced by combining or linking an
+Application with the Library. The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+ The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+ The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+ 1. Exception to Section 3 of the GNU GPL.
+
+ You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+ 2. Conveying Modified Versions.
+
+ If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+ a) under this License, provided that you make a good faith effort to
+ ensure that, in the event an Application does not supply the
+ function or data, the facility still operates, and performs
+ whatever part of its purpose remains meaningful, or
+
+ b) under the GNU GPL, with none of the additional permissions of
+ this License applicable to that copy.
+
+ 3. Object Code Incorporating Material from Library Header Files.
+
+ The object code form of an Application may incorporate material from
+a header file that is part of the Library. You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+ a) Give prominent notice with each copy of the object code that the
+ Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the object code with a copy of the GNU GPL and this license
+ document.
+
+ 4. Combined Works.
+
+ You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+ a) Give prominent notice with each copy of the Combined Work that
+ the Library is used in it and that the Library and its use are
+ covered by this License.
+
+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
+ document.
+
+ c) For a Combined Work that displays copyright notices during
+ execution, include the copyright notice for the Library among
+ these notices, as well as a reference directing the user to the
+ copies of the GNU GPL and this license document.
+
+ d) Do one of the following:
+
+ 0) Convey the Minimal Corresponding Source under the terms of this
+ License, and the Corresponding Application Code in a form
+ suitable for, and under terms that permit, the user to
+ recombine or relink the Application with a modified version of
+ the Linked Version to produce a modified Combined Work, in the
+ manner specified by section 6 of the GNU GPL for conveying
+ Corresponding Source.
+
+ 1) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (a) uses at run time
+ a copy of the Library already present on the user's computer
+ system, and (b) will operate properly with a modified version
+ of the Library that is interface-compatible with the Linked
+ Version.
+
+ e) Provide Installation Information, but only if you would otherwise
+ be required to provide such information under section 6 of the
+ GNU GPL, and only to the extent that such information is
+ necessary to install and execute a modified version of the
+ Combined Work produced by recombining or relinking the
+ Application with a modified version of the Linked Version. (If
+ you use option 4d0, the Installation Information must accompany
+ the Minimal Corresponding Source and Corresponding Application
+ Code. If you use option 4d1, you must provide the Installation
+ Information in the manner specified by section 6 of the GNU GPL
+ for conveying Corresponding Source.)
+
+ 5. Combined Libraries.
+
+ You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+ a) Accompany the combined library with a copy of the same work based
+ on the Library, uncombined with any other library facilities,
+ conveyed under the terms of this License.
+
+ b) Give prominent notice with the combined library that part of it
+ is a work based on the Library, and explaining where to find the
+ accompanying uncombined form of the same work.
+
+ 6. Revised Versions of the GNU Lesser General Public License.
+
+ The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+ If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/lib/libesp32_eink/epdiy/Makefile b/lib/libesp32_eink/epdiy/Makefile
index 545c55a5e..385cc55f6 100755
--- a/lib/libesp32_eink/epdiy/Makefile
+++ b/lib/libesp32_eink/epdiy/Makefile
@@ -8,27 +8,41 @@ EXPORTED_MODES ?= 1,2,5,16,17
# Generate waveforms in room temperature range
EXPORT_TEMPERATURE_RANGE ?= 15,35
+FORMATTED_FILES := $(shell find ./ -regex '.*\.\(c\|cpp\|h\|ino\)$$' \
+ -not -regex '.*/\(.ccls-cache\|.cache\|waveforms\|\components\|build\)/.*' \
+ -not -regex '.*/img_.*.h' \
+ -not -regex '.*/build.*' \
+ -not -regex '.*/\(firasans_.*.h\|opensans.*.h\|amiri.h\|alexandria.h\|dragon.h\)' \
+ -not -regex '.*E[DS][0-9]*[A-Za-z]*[0-9].h')
+
# the default headers that should come with the distribution
default: \
- $(patsubst %,src/epd_driver/waveforms/epdiy_%.h,$(SUPPORTRED_DISPLAYS))
+ $(patsubst %,src/waveforms/epdiy_%.h,$(SUPPORTRED_DISPLAYS))
clean:
- rm src/epd_driver/waveforms/epdiy_*.h
- rm src/epd_driver/waveforms/eink_*.h
+ rm src/waveforms/epdiy_*.h
+ rm src/waveforms/eink_*.h
-src/epd_driver/waveforms/epdiy_%.h: src/epd_driver/waveforms/epdiy_%.json
+format:
+ clang-format --style=file -i $(FORMATTED_FILES)
+
+format-check:
+ clang-format --style=file --dry-run -Werror $(FORMATTED_FILES)
+
+
+src/waveforms/epdiy_%.h: src/waveforms/epdiy_%.json
python3 scripts/waveform_hdrgen.py \
--export-modes $(EXPORTED_MODES) \
--temperature-range $(EXPORT_TEMPERATURE_RANGE) \
epdiy_$* < $< > $@
-src/epd_driver/waveforms/eink_%.h: src/epd_driver/waveforms/eink_%.json
+src/waveforms/eink_%.h: src/waveforms/eink_%.json
python3 scripts/waveform_hdrgen.py \
--export-modes $(EXPORTED_MODES) \
--temperature-range $(EXPORT_TEMPERATURE_RANGE) \
eink_$* < $< > $@
-src/epd_driver/waveforms/epdiy_%.json:
+src/waveforms/epdiy_%.json:
python3 scripts/epdiy_waveform_gen.py $* > $@
-.PHONY: default
+.PHONY: default format
diff --git a/lib/libesp32_eink/epdiy/README.md b/lib/libesp32_eink/epdiy/README.md
index fc3135a04..33cbd4847 100755
--- a/lib/libesp32_eink/epdiy/README.md
+++ b/lib/libesp32_eink/epdiy/README.md
@@ -1,4 +1,4 @@
-[](https://epdiy.readthedocs.io/en/latest/?badge=latest) [](https://matrix.to/#/!GUXWriqsBKkWyXzsBK:matrix.vroland.de?via=matrix.vroland.de) [](https://join.slack.com/t/epdiy/shared_invite/zt-mw3iat5g-6jRylNrK2g79HSxeznvmPg)
+[](https://epdiy.readthedocs.io/en/latest/?badge=latest) [](https://matrix.to/#/!GUXWriqsBKkWyXzsBK:matrix.vroland.de?via=matrix.vroland.de) [](https://join.slack.com/t/epdiy/shared_invite/zt-189eo7328-bs94cfB~eXPbLYAD1rKQcg)
EPDiy E-Paper Driver
=======================================
@@ -9,35 +9,53 @@ EPDiy is a driver board which talks to affordable E-Paper (or E-Ink) screens, wh
* No power consumption when not updating
* Sunlight-readable
-Ready-made DIY modules for this size and with 4bpp (16 Grayscale) color support are currently quite expensive. This project uses Kindle replacement screens, which are available for 20$ (small) / 30$ (large) on ebay!
+Ready-made DIY modules for this size and with 4bpp (16 Grayscale) color support are currently quite expensive and / or slow.
+The EPDiy controller can drive the bare display modules, e.g. from old e-Readers, which are available for 20$ (small) / 30$ (large) on ebay!
+Additionally, since it is based on the ESP32S3 (V7) / ESP32 (V2-V6) microcontroller, it features WiFi and Bluetooth connectivity.
-The EPDiy driver board targets multiple E-Paper displays. As the driving method for all matrix-based E-ink displays seems to be more or less the same, only the right connector and timings are needed. The EPDiy PCB v5 features 33pin, 34pin and a 39pin connectors, which allow to drive the following display types: ED097OC4, ED060SC4, ED097TC2, ED060SC7. For the full list of supported displays, refer to the table below.
+The EPDiy driver board targets a range of E-Paper displays, as shown in the table below.
+As the driving method for all matrix-based E-ink displays is more or less the same, only the right connector and timings are needed.
+The current V7 board has three different display connectors, other display will require an adapter board.
-Revision 5 of the board is optimized for the use with LiPo batteries, featuring a LiPo charger and ultra-low deep sleep current.
+The controller is optimized for the use with LiPo batteries, featuring a LiPo charger and ultra-low deep sleep current.
This project supports a driver for the ESP-IDF and Arduino. For installation instructions, please refer to the [documentation](https://epdiy.readthedocs.io/en/latest/getting_started.html#getting-your-board).
+Note that for epdiy V7, update speeds are significantly lower when using the Arduino IDE, because it does not allow to change
+the sub-optimal cache configuration.
+
+Get Inspired
+------------
+
+The `examples` directory contains some example applications like a weather station or a screen diagnostic test.
+If you want to build something more useful though, how about:
+
+- A serial terminal for connecting to a raspberry pi: [video](https://cdn.hackaday.io/files/1681937195969312/terminal_demo.mp4) [repository](https://github.com/vroland/epdiy-terminal)]
+- A Music Player Daemon (MPD) dashboard: [repository](https://github.com/vroland/epdiy-mpd)]
+- An e-Paper picture frame: [video](https://www.youtube.com/watch?v=r7AcNQsSZUw)
+- And more to come!
Building It
-----------
-If you want to build a board right now, there are two possible routes:
+On the [EPDiy Hardware Page](https://vroland.github.io/epdiy-hardware/), you'll find a list of all boards and variants, adapters, and helpers.
+Next to each board, there are manufacturing files (gerbers), Bill of Materials (BoM), part placement files,
+and 3D models ready to use!
- - Use the new v5 PCB (`hardware/epaper-breakout/gerbers_v5.zip`).
- **So far, I only tested a prototype of it. The newest gerbers should work, but are untested!**
- **If you have tested them, please let me know!**
- The BOM is available at (`hardware/epaper-breakout/BOM.csv`).
- Positioning files for SMT assembly are available at (`hardware/epaper-breakout/gerbers/epaper-breakout-top-pos.csv`).
- Please double check the part positioning and Rotation with your assembly service!
- More information on the order process and where to find parts is in the [documentation](https://epdiy.readthedocs.io/en/latest/getting_started.html#getting-your-board).
+
+
+For ordering from JLCPCB for example, ordering is as easy as downloading the zipped gerbers, BoM, and placement file
+and uploading them. The process is very similar for other manufacturers, check your vendor's documentation for details.
+Don't forget to oder adapters if the board doesn't have connectors for your specific display.
+
+The current latest version is epdiy V7, beased on the ESP32S3.
+Older versions are also available on the hardware page.
+
+
+#### Contributing Hardware
+
+Want to contribute your own board variant or adapter?
+Check out the [epdiy-hardware repository](https://github.com/vroland/epdiy-hardware) for instructions.
- Make sure to select the `V5` board revision in `idf.py menuconfig` when building the examples.
-
- - Use the old v4 PCB (`hardware/epaper-breakout/gerbers_v4.zip`). This is a bit more fresh, but should work.
- The BOM is available at (`hardware/epaper-breakout/BOM.csv`).
- Positioning files for SMT assembly are available at (`hardware/epaper-breakout/gerbers/epaper-breakout-top-pos.csv`).
- Please double check the part positioning and Rotation with your assembly service!
-
- Make sure to select the `V4` board revision in `idf.py menuconfig` when building the examples.
Gettings Started
----------------
@@ -48,37 +66,40 @@ Join the Discussion
----------------
- [](https://matrix.to/#/!GUXWriqsBKkWyXzsBK:matrix.vroland.de?via=matrix.vroland.de) Matrix Community: +epdiy:matrix.vroland.de
- - [](https://join.slack.com/t/epdiy/shared_invite/zt-mw3iat5g-6jRylNrK2g79HSxeznvmPg)
+ - Slack: See badge
Displays
--------
-|Name|Size|Resolution|Compatible|Connector|Pin count|Compatible since pcb version|Notes
-| --: | --: | --: | --: | --: | --: |--: |--: |
-|ED060SC4|6"|800 x 600|yes, tested|FH26W-39S-0.3SHW(60)|39|v2|
-|ED097OC4|9.7"|1200 x 825|yes, tested|XF2M-3315-1A|33|V2|Cheap, inferior contrast
-|ED097TC2|9.7"|1200 x 825|yes, tested|XF2M-3315-1A|33|V2|Slightly higher price, better contrast
-|ED097OC1|9.7"|1200 x 825|yes (should work)|XF2M-3315-1A|33|V2|Cheap, inferior performance
-|ED047TC1|4.7"|960 x 540|yes, tested|40-pin|40|LILYGO 4.7" EPD|Supported only by 4.7" e-paper board by LILYGO
-|ED133UT2|13.3"|1600 x 1200|yes, tested|adapter board|39|V2|Adapter Board required, also PENG133D
-|ED060XC3|6"|758 x 1024|yes, tested|THD0515-34CL-SN|34|V5|Cheapest, good contrast and resolution
-|ED060XD4|6"|758 x 1024|yes, tested|THD0515-34CL-SN|34|V5|
-|ED060XC5|6"|758 x 1024|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060XD6|6"|758 x 1024|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060XH2|6"|758 x 1024|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060XC9|6"|758 x 1024|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060KD1|6"|1072 x 1448|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060KC1|6"|1072 x 1448|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|
-|ED060SCF|6"|600 x 800|yes, tested|THD0515-34CL-SN|34|V5|Different flex cable shape
-|ED060SCN|6"|600 x 800|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|Different flex cable shape
-|ED060SCP|6"|600 x 800|yes (should work as ED060XC3)|THD0515-34CL-SN|34|V5|Different flex cable shape
-|ED060SC7|6"|600 x 800|yes (should work) |AXT434124|34|v5|
-|ED060SCG|6"|600 x 800|yes (should work) |AXT434124|34|v5|
-| ED060SCE | 6" | 600 x 800 | yes (should work) | AXT434124 | 34 | v5 |
-| ED060SCM | 6" | 600 x 800 | yes (should work) | AXT434124 | 34 | v5 |
-| ED060SCT | 6" | 600 x 800 | yes, tested | AXT434124 | 34 | v5 |
+|Name |Size |Resolution|Compatible|Connector|Pin count|Compatible since pcb version|Notes
+| --: | --: | --: | --: | --: | --: | --: | --: |
+| ED060SC4 | 6" | 800 x 600
167 PPI | yes, tested | FH26W-39S-0.3SHW(60) | 39 | v2 | |
+|ED097OC4|9.7"|1200 x 825
150 PPI|yes, tested|XF2M-3315-1A|33|v2|Cheap, inferior contrast
+|ED097TC2|9.7"|1200 x 825
150 PPI|yes, tested|XF2M-3315-1A|33|v2|Slightly higher price, better contrast
+|ED097OC1|9.7"|1200 x 825
150 PPI|yes (should work)|XF2M-3315-1A|33|v2|Cheap, inferior performance
+|ED047TC1|4.7"|960 x 540
234 PPI|yes, tested|40-pin|40|LILYGO 4.7" EPD|Supported only by 4.7" e-paper board by LILYGO
+| ED050SC5 | 5" | 600 x 800
200 PPI | yes, tested | THD0510-33CL-GF | 33 | v5 |
+| ED050SC3 | 5" | 600 x 800
200 PPI | yes (should work) | THD0510-33CL-GF | 33 | v5 |
+| ED052TC4 | 5.2" | 1280 x 780
??? PPI | yes (should work) | WP27D-P050VA3 | 50 | v5 |
+| ED133UT2 | 13.3" | 1600 x 1200
150 PPI | yes, tested | adapter board | 39 | v2 | Adapter Board required, also PENG133D
+| ED060XC3 | 6" | 758 x 1024
212 PPI | yes, tested | THD0515-34CL-SN | 34 | v5 | Cheapest, good contrast and resolution
+| ED060XD4 | 6" | 758 x 1024
212 PPI | yes, tested | THD0515-34CL-SN | 34 | v5 |
+| ED060XC5 | 6" | 758 x 1024
212 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060XD6 | 6" | 758 x 1024
212 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060XH2 | 6" | 758 x 1024
212 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060XC9 | 6" | 758 x 1024
212 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060KD1 | 6" | 1072 x 1448
300 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060KC1 | 6" | 1072 x 1448
300 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 |
+| ED060SCF | 6" | 600 x 800
167 PPI | yes, tested | THD0515-34CL-SN | 34 | v5 | Different flex cable shape
+| ED060SCN | 6" | 600 x 800
167 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 | Different flex cable shape
+| ED060SCP | 6" | 600 x 800
167 PPI | yes (should work as ED060XC3) | THD0515-34CL-SN | 34 | v5 | Different flex cable shape
+| ED060SC7 | 6" | 600 x 800
167 PPI | yes (should work) | AXT334124 | 34 | v5 | connector dropped in v6
+| ED060SCG | 6" | 600 x 800
167 PPI | yes (should work) | AXT334124 | 34 | v5 | connector dropped in v6
+| ED060SCE | 6" | 600 x 800
167 PPI | yes (should work) | AXT334124 | 34 | v5 | connector dropped in v6
+| ED060SCM | 6" | 600 x 800
167 PPI | yes (should work) | AXT334124 | 34 | v5 | connector dropped in v6
+| ED060SCT | 6" | 600 x 800
167 PPI | yes, tested | AXT334124 | 34 | v5 | connector dropped in v6
+| ED078KC1 | 7.8" | 1872 x 1404
300 PPI | yes, tested | FH12-40S-0.5SH | 40 | v7 | 16 data lines
-**Please note that board revision v5 is still in prototype stage!**
Troubleshooting
---------------
@@ -88,7 +109,26 @@ The following list is compiled from past experiences and GitHub issues:
* **The existing image fades / darkens when updating a partial screen region.** Make sure the VCOM voltage is [calibrated](https://epdiy.readthedocs.io/en/latest/getting_started.html#calibrate-vcom) for your specific display.
* **The second third of the image is replaced with the last third.** This seems to be a timing issue we could not yet quite figure out the reason for. For a workarround or suggestions please [join the discussion](https://github.com/vroland/epdiy/issues/15).
* **The ESP does not boot correctly when external periperals are connected.** Make sure not to pull GPIO12 high during boot, as it is a strapping pin internal voltage selection (https://github.com/vroland/epdiy/issues/17).
-
+ * **The ESP power consumption in deep sleep is too high.** Add `rtc_gpio_isolate(GPIO_NUM_12);` to your solution. See also [Configuring IOs (Deep-sleep Only)](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html?highlight=rtc_gpio_isolate#configuring-ios-deep-sleep-only).
+
+LilyGo Boards
+---------------
+There are several differences with these boards.
+One particular one is the way the LilyGo handles power to the display the official lilygo code has two states.
+This is now handled in epdiy in a different way to the lilygo code.
+**epd_poweroff()** completely turns the power off to the display and the other peripherals of the lilygo.
+The new function **epd_powerdown()** keeps the peripherals on (this allows the touch functions to continue to work).
+**epd_poweroff() should allways be called before sleeping the system**
+You can still use touch to wake the screen with the following.
+In Arduino it works like this.
+`epd_poweroff();`
+
+ `epd_deinit();`
+
+ `esp_sleep_enable_ext1_wakeup(GPIO_SEL_13, ESP_EXT1_WAKEUP_ANY_HIGH);`
+
+ `esp_deep_sleep_start();`
+
More on E-Paper Displays
------------------------
@@ -106,8 +146,7 @@ Hackaday Project
For more details, see the project page on Hackaday: https://hackaday.io/project/168193-epdiy-976-e-paper-controller

-
-
+
Licenses
--------
@@ -116,6 +155,5 @@ The weather example is Copyright (c) David Bird 2018 (except for minor modificat
The board and schematic are licensed under a
Creative Commons Attribution-ShareAlike 4.0 International License.
-Firmware and remaining examples are licensed under the terms of the GNU GPL version 3.
+Firmware and remaining examples are licensed under the terms of the GNU Lesser GPL version 3.
Utilities are licensed under the terms of the MIT license.
-
diff --git a/lib/libesp32_eink/epdiy/boards.local.txt b/lib/libesp32_eink/epdiy/boards.local.txt
deleted file mode 100755
index c72bb245f..000000000
--- a/lib/libesp32_eink/epdiy/boards.local.txt
+++ /dev/null
@@ -1,452 +0,0 @@
-############################## Revision 5 Board ##############################
-epdiy_v5.name=EPDIY Board Revision 5
-
-epdiy_v5.upload.tool=esp32:esptool_py
-epdiy_v5.upload.maximum_size=1310720
-epdiy_v5.upload.maximum_data_size=327680
-epdiy_v5.upload.wait_for_upload_port=true
-
-epdiy_v5.serial.disableDTR=true
-epdiy_v5.serial.disableRTS=true
-
-epdiy_v5.build.mcu=esp32
-epdiy_v5.build.core=esp32:esp32
-epdiy_v5.build.variant=esp32
-epdiy_v5.build.board=ESP32_EPDIY
-
-epdiy_v5.build.f_cpu=240000000L
-epdiy_v5.build.flash_size=4MB
-epdiy_v5.build.flash_freq=40m
-epdiy_v5.build.flash_mode=dio
-epdiy_v5.build.boot=dio
-epdiy_v5.build.partitions=default
-epdiy_v5.build.defines=
-
-epdiy_v5.menu.DisplayType.default=ED097OC4
-epdiy_v5.menu.DisplayType.default.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-epdiy_v5.menu.DisplayType.ed097oc4_lq=ED097OC4 Low Quality
-epdiy_v5.menu.DisplayType.ed097oc4_lq.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-epdiy_v5.menu.DisplayType.ed060sc4=ED060SC4
-epdiy_v5.menu.DisplayType.ed060sc4.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED060SC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-epdiy_v5.menu.DisplayType.ed097tc2=ED097TC2
-epdiy_v5.menu.DisplayType.ed097tc2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097TC2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-epdiy_v5.menu.DisplayType.ed047tc1=ED047TC1 (LILYGO 4.7 inch)
-epdiy_v5.menu.DisplayType.ed047tc1.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED047TC1 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-epdiy_v5.menu.DisplayType.ed133ut2=ED133UT2
-epdiy_v5.menu.DisplayType.ed133ut2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED133UT2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V5
-
-epdiy_v5.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
-epdiy_v5.menu.PartitionScheme.default.build.partitions=default
-epdiy_v5.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
-epdiy_v5.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
-epdiy_v5.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
-epdiy_v5.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
-epdiy_v5.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
-epdiy_v5.menu.PartitionScheme.minimal.build.partitions=minimal
-epdiy_v5.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
-epdiy_v5.menu.PartitionScheme.no_ota.build.partitions=no_ota
-epdiy_v5.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
-epdiy_v5.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
-epdiy_v5.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
-epdiy_v5.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
-epdiy_v5.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
-epdiy_v5.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
-epdiy_v5.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
-epdiy_v5.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
-epdiy_v5.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
-epdiy_v5.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
-epdiy_v5.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
-epdiy_v5.menu.PartitionScheme.huge_app.build.partitions=huge_app
-epdiy_v5.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
-epdiy_v5.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
-epdiy_v5.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
-epdiy_v5.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
-epdiy_v5.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
-epdiy_v5.menu.PartitionScheme.fatflash.build.partitions=ffat
-
-epdiy_v5.menu.FlashMode.qio=QIO
-epdiy_v5.menu.FlashMode.qio.build.flash_mode=dio
-epdiy_v5.menu.FlashMode.qio.build.boot=qio
-epdiy_v5.menu.FlashMode.dio=DIO
-epdiy_v5.menu.FlashMode.dio.build.flash_mode=dio
-epdiy_v5.menu.FlashMode.dio.build.boot=dio
-epdiy_v5.menu.FlashMode.qout=QOUT
-epdiy_v5.menu.FlashMode.qout.build.flash_mode=dout
-epdiy_v5.menu.FlashMode.qout.build.boot=qout
-epdiy_v5.menu.FlashMode.dout=DOUT
-epdiy_v5.menu.FlashMode.dout.build.flash_mode=dout
-epdiy_v5.menu.FlashMode.dout.build.boot=dout
-
-epdiy_v5.menu.FlashFreq.80=80MHz
-epdiy_v5.menu.FlashFreq.80.build.flash_freq=80m
-epdiy_v5.menu.FlashFreq.40=40MHz
-epdiy_v5.menu.FlashFreq.40.build.flash_freq=40m
-
-epdiy_v5.menu.UploadSpeed.921600=921600
-epdiy_v5.menu.UploadSpeed.921600.upload.speed=921600
-epdiy_v5.menu.UploadSpeed.115200=115200
-epdiy_v5.menu.UploadSpeed.115200.upload.speed=115200
-epdiy_v5.menu.UploadSpeed.256000.windows=256000
-epdiy_v5.menu.UploadSpeed.256000.upload.speed=256000
-epdiy_v5.menu.UploadSpeed.230400.windows.upload.speed=256000
-epdiy_v5.menu.UploadSpeed.230400=230400
-epdiy_v5.menu.UploadSpeed.230400.upload.speed=230400
-epdiy_v5.menu.UploadSpeed.460800.linux=460800
-epdiy_v5.menu.UploadSpeed.460800.macosx=460800
-epdiy_v5.menu.UploadSpeed.460800.upload.speed=460800
-epdiy_v5.menu.UploadSpeed.512000.windows=512000
-epdiy_v5.menu.UploadSpeed.512000.upload.speed=512000
-
-epdiy_v5.menu.DebugLevel.none=None
-epdiy_v5.menu.DebugLevel.none.build.code_debug=0
-epdiy_v5.menu.DebugLevel.error=Error
-epdiy_v5.menu.DebugLevel.error.build.code_debug=1
-epdiy_v5.menu.DebugLevel.warn=Warn
-epdiy_v5.menu.DebugLevel.warn.build.code_debug=2
-epdiy_v5.menu.DebugLevel.info=Info
-epdiy_v5.menu.DebugLevel.info.build.code_debug=3
-epdiy_v5.menu.DebugLevel.debug=Debug
-epdiy_v5.menu.DebugLevel.debug.build.code_debug=4
-epdiy_v5.menu.DebugLevel.verbose=Verbose
-epdiy_v5.menu.DebugLevel.verbose.build.code_debug=5
-
-
-
-##############################################################
-
-menu.DisplayType=DisplayType
-
-epdiy_v2.name=EPDIY Board Revision 2/3
-
-epdiy_v2.upload.tool=esptool_py
-epdiy_v2.upload.maximum_size=1310720
-epdiy_v2.upload.maximum_data_size=327680
-epdiy_v2.upload.wait_for_upload_port=true
-
-epdiy_v2.serial.disableDTR=true
-epdiy_v2.serial.disableRTS=true
-
-epdiy_v2.build.mcu=esp32
-epdiy_v2.build.core=esp32:esp32
-epdiy_v2.build.variant=esp32
-epdiy_v2.build.board=ESP32_EPDIY
-
-epdiy_v2.build.f_cpu=240000000L
-epdiy_v2.build.flash_size=4MB
-epdiy_v2.build.flash_freq=40m
-epdiy_v2.build.flash_mode=dio
-epdiy_v2.build.boot=dio
-epdiy_v2.build.partitions=default
-
-epdiy_v2.menu.DisplayType.default=ED097OC4
-epdiy_v2.menu.DisplayType.default.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-epdiy_v2.menu.DisplayType.ed097oc4_lq=ED097OC4 Low Quality
-epdiy_v2.menu.DisplayType.ed097oc4_lq.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-epdiy_v2.menu.DisplayType.ed060sc4=ED060SC4
-epdiy_v2.menu.DisplayType.ed060sc4.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED060SC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-epdiy_v2.menu.DisplayType.ed097tc2=ED097TC2
-epdiy_v2.menu.DisplayType.ed097tc2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097TC2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-epdiy_v2.menu.DisplayType.ed047tc1=ED047TC1 (LILYGO 4.7 inch)
-epdiy_v2.menu.DisplayType.ed047tc1.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED047TC1 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-epdiy_v2.menu.DisplayType.ed133ut2=ED133UT2
-epdiy_v2.menu.DisplayType.ed133ut2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED133UT2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V2_V3
-
-epdiy_v2.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
-epdiy_v2.menu.PartitionScheme.default.build.partitions=default
-epdiy_v2.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
-epdiy_v2.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
-epdiy_v2.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
-epdiy_v2.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
-epdiy_v2.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
-epdiy_v2.menu.PartitionScheme.minimal.build.partitions=minimal
-epdiy_v2.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
-epdiy_v2.menu.PartitionScheme.no_ota.build.partitions=no_ota
-epdiy_v2.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
-epdiy_v2.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
-epdiy_v2.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
-epdiy_v2.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
-epdiy_v2.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
-epdiy_v2.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
-epdiy_v2.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
-epdiy_v2.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
-epdiy_v2.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
-epdiy_v2.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
-epdiy_v2.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
-epdiy_v2.menu.PartitionScheme.huge_app.build.partitions=huge_app
-epdiy_v2.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
-epdiy_v2.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
-epdiy_v2.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
-epdiy_v2.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
-epdiy_v2.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
-epdiy_v2.menu.PartitionScheme.fatflash.build.partitions=ffat
-
-epdiy_v2.menu.FlashMode.qio=QIO
-epdiy_v2.menu.FlashMode.qio.build.flash_mode=dio
-epdiy_v2.menu.FlashMode.qio.build.boot=qio
-epdiy_v2.menu.FlashMode.dio=DIO
-epdiy_v2.menu.FlashMode.dio.build.flash_mode=dio
-epdiy_v2.menu.FlashMode.dio.build.boot=dio
-epdiy_v2.menu.FlashMode.qout=QOUT
-epdiy_v2.menu.FlashMode.qout.build.flash_mode=dout
-epdiy_v2.menu.FlashMode.qout.build.boot=qout
-epdiy_v2.menu.FlashMode.dout=DOUT
-epdiy_v2.menu.FlashMode.dout.build.flash_mode=dout
-epdiy_v2.menu.FlashMode.dout.build.boot=dout
-
-epdiy_v2.menu.FlashFreq.80=80MHz
-epdiy_v2.menu.FlashFreq.80.build.flash_freq=80m
-epdiy_v2.menu.FlashFreq.40=40MHz
-epdiy_v2.menu.FlashFreq.40.build.flash_freq=40m
-
-epdiy_v2.menu.UploadSpeed.921600=921600
-epdiy_v2.menu.UploadSpeed.921600.upload.speed=921600
-epdiy_v2.menu.UploadSpeed.115200=115200
-epdiy_v2.menu.UploadSpeed.115200.upload.speed=115200
-epdiy_v2.menu.UploadSpeed.256000.windows=256000
-epdiy_v2.menu.UploadSpeed.256000.upload.speed=256000
-epdiy_v2.menu.UploadSpeed.230400.windows.upload.speed=256000
-epdiy_v2.menu.UploadSpeed.230400=230400
-epdiy_v2.menu.UploadSpeed.230400.upload.speed=230400
-epdiy_v2.menu.UploadSpeed.460800.linux=460800
-epdiy_v2.menu.UploadSpeed.460800.macosx=460800
-epdiy_v2.menu.UploadSpeed.460800.upload.speed=460800
-epdiy_v2.menu.UploadSpeed.512000.windows=512000
-epdiy_v2.menu.UploadSpeed.512000.upload.speed=512000
-
-epdiy_v2.menu.DebugLevel.none=None
-epdiy_v2.menu.DebugLevel.none.build.code_debug=0
-epdiy_v2.menu.DebugLevel.error=Error
-epdiy_v2.menu.DebugLevel.error.build.code_debug=1
-epdiy_v2.menu.DebugLevel.warn=Warn
-epdiy_v2.menu.DebugLevel.warn.build.code_debug=2
-epdiy_v2.menu.DebugLevel.info=Info
-epdiy_v2.menu.DebugLevel.info.build.code_debug=3
-epdiy_v2.menu.DebugLevel.debug=Debug
-epdiy_v2.menu.DebugLevel.debug.build.code_debug=4
-epdiy_v2.menu.DebugLevel.verbose=Verbose
-epdiy_v2.menu.DebugLevel.verbose.build.code_debug=5
-
-############################## Revision 4 Board ##############################
-epdiy_v4.name=EPDIY Board Revision 4
-
-epdiy_v4.upload.tool=esp32:esptool_py
-epdiy_v4.upload.maximum_size=1310720
-epdiy_v4.upload.maximum_data_size=327680
-epdiy_v4.upload.wait_for_upload_port=true
-
-epdiy_v4.serial.disableDTR=true
-epdiy_v4.serial.disableRTS=true
-
-epdiy_v4.build.mcu=esp32
-epdiy_v4.build.core=esp32:esp32
-epdiy_v4.build.variant=esp32
-epdiy_v4.build.board=ESP32_EPDIY
-
-epdiy_v4.build.f_cpu=240000000L
-epdiy_v4.build.flash_size=4MB
-epdiy_v4.build.flash_freq=40m
-epdiy_v4.build.flash_mode=dio
-epdiy_v4.build.boot=dio
-epdiy_v4.build.partitions=default
-epdiy_v4.build.defines=
-
-epdiy_v4.menu.DisplayType.default=ED097OC4
-epdiy_v4.menu.DisplayType.default.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-epdiy_v4.menu.DisplayType.ed097oc4_lq=ED097OC4 Low Quality
-epdiy_v4.menu.DisplayType.ed097oc4_lq.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-epdiy_v4.menu.DisplayType.ed060sc4=ED060SC4
-epdiy_v4.menu.DisplayType.ed060sc4.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED060SC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-epdiy_v4.menu.DisplayType.ed097tc2=ED097TC2
-epdiy_v4.menu.DisplayType.ed097tc2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097TC2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-epdiy_v4.menu.DisplayType.ed047tc1=ED047TC1 (LILYGO 4.7 inch)
-epdiy_v4.menu.DisplayType.ed047tc1.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED047TC1 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-epdiy_v4.menu.DisplayType.ed133ut2=ED133UT2
-epdiy_v4.menu.DisplayType.ed133ut2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED133UT2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_V4
-
-epdiy_v4.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
-epdiy_v4.menu.PartitionScheme.default.build.partitions=default
-epdiy_v4.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
-epdiy_v4.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
-epdiy_v4.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
-epdiy_v4.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
-epdiy_v4.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
-epdiy_v4.menu.PartitionScheme.minimal.build.partitions=minimal
-epdiy_v4.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
-epdiy_v4.menu.PartitionScheme.no_ota.build.partitions=no_ota
-epdiy_v4.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
-epdiy_v4.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
-epdiy_v4.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
-epdiy_v4.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
-epdiy_v4.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
-epdiy_v4.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
-epdiy_v4.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
-epdiy_v4.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
-epdiy_v4.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
-epdiy_v4.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
-epdiy_v4.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
-epdiy_v4.menu.PartitionScheme.huge_app.build.partitions=huge_app
-epdiy_v4.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
-epdiy_v4.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
-epdiy_v4.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
-epdiy_v4.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
-epdiy_v4.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
-epdiy_v4.menu.PartitionScheme.fatflash.build.partitions=ffat
-
-epdiy_v4.menu.FlashMode.qio=QIO
-epdiy_v4.menu.FlashMode.qio.build.flash_mode=dio
-epdiy_v4.menu.FlashMode.qio.build.boot=qio
-epdiy_v4.menu.FlashMode.dio=DIO
-epdiy_v4.menu.FlashMode.dio.build.flash_mode=dio
-epdiy_v4.menu.FlashMode.dio.build.boot=dio
-epdiy_v4.menu.FlashMode.qout=QOUT
-epdiy_v4.menu.FlashMode.qout.build.flash_mode=dout
-epdiy_v4.menu.FlashMode.qout.build.boot=qout
-epdiy_v4.menu.FlashMode.dout=DOUT
-epdiy_v4.menu.FlashMode.dout.build.flash_mode=dout
-epdiy_v4.menu.FlashMode.dout.build.boot=dout
-
-epdiy_v4.menu.FlashFreq.80=80MHz
-epdiy_v4.menu.FlashFreq.80.build.flash_freq=80m
-epdiy_v4.menu.FlashFreq.40=40MHz
-epdiy_v4.menu.FlashFreq.40.build.flash_freq=40m
-
-epdiy_v4.menu.UploadSpeed.921600=921600
-epdiy_v4.menu.UploadSpeed.921600.upload.speed=921600
-epdiy_v4.menu.UploadSpeed.115200=115200
-epdiy_v4.menu.UploadSpeed.115200.upload.speed=115200
-epdiy_v4.menu.UploadSpeed.256000.windows=256000
-epdiy_v4.menu.UploadSpeed.256000.upload.speed=256000
-epdiy_v4.menu.UploadSpeed.230400.windows.upload.speed=256000
-epdiy_v4.menu.UploadSpeed.230400=230400
-epdiy_v4.menu.UploadSpeed.230400.upload.speed=230400
-epdiy_v4.menu.UploadSpeed.460800.linux=460800
-epdiy_v4.menu.UploadSpeed.460800.macosx=460800
-epdiy_v4.menu.UploadSpeed.460800.upload.speed=460800
-epdiy_v4.menu.UploadSpeed.512000.windows=512000
-epdiy_v4.menu.UploadSpeed.512000.upload.speed=512000
-
-epdiy_v4.menu.DebugLevel.none=None
-epdiy_v4.menu.DebugLevel.none.build.code_debug=0
-epdiy_v4.menu.DebugLevel.error=Error
-epdiy_v4.menu.DebugLevel.error.build.code_debug=1
-epdiy_v4.menu.DebugLevel.warn=Warn
-epdiy_v4.menu.DebugLevel.warn.build.code_debug=2
-epdiy_v4.menu.DebugLevel.info=Info
-epdiy_v4.menu.DebugLevel.info.build.code_debug=3
-epdiy_v4.menu.DebugLevel.debug=Debug
-epdiy_v4.menu.DebugLevel.debug.build.code_debug=4
-epdiy_v4.menu.DebugLevel.verbose=Verbose
-epdiy_v4.menu.DebugLevel.verbose.build.code_debug=5
-
-
-############################## Revision 4 Board ##############################
-lilygo_t5_47.name=LILYGO T5-4.7 inch e-paper
-
-lilygo_t5_47.upload.tool=esp32:esptool_py
-lilygo_t5_47.upload.maximum_size=1310720
-lilygo_t5_47.upload.maximum_data_size=327680
-lilygo_t5_47.upload.wait_for_upload_port=true
-
-lilygo_t5_47.serial.disableDTR=true
-lilygo_t5_47.serial.disableRTS=true
-
-lilygo_t5_47.build.mcu=esp32
-lilygo_t5_47.build.core=esp32:esp32
-lilygo_t5_47.build.variant=esp32
-lilygo_t5_47.build.board=ESP32_EPDIY
-
-lilygo_t5_47.build.f_cpu=240000000L
-lilygo_t5_47.build.flash_size=4MB
-lilygo_t5_47.build.flash_freq=40m
-lilygo_t5_47.build.flash_mode=dio
-lilygo_t5_47.build.boot=dio
-lilygo_t5_47.build.partitions=default
-lilygo_t5_47.build.defines=-DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-
-lilygo_t5_47.menu.DisplayType.default=ED097OC4
-lilygo_t5_47.menu.DisplayType.default.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-lilygo_t5_47.menu.DisplayType.ed097oc4_lq=ED097OC4 Low Quality
-lilygo_t5_47.menu.DisplayType.ed097oc4_lq.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-lilygo_t5_47.menu.DisplayType.ed060sc4=ED060SC4
-lilygo_t5_47.menu.DisplayType.ed060sc4.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED060SC4 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-lilygo_t5_47.menu.DisplayType.ed097tc2=ED097TC2
-lilygo_t5_47.menu.DisplayType.ed097tc2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED097TC2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-lilygo_t5_47.menu.DisplayType.ed047tc1=ED047TC1 (LILYGO 4.7 inch)
-lilygo_t5_47.menu.DisplayType.ed047tc1.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED047TC1 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-lilygo_t5_47.menu.DisplayType.ed133ut2=ED133UT2
-lilygo_t5_47.menu.DisplayType.ed133ut2.build.defines=-DCONFIG_EPD_DISPLAY_TYPE_ED133UT2 -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue -DCONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-
-lilygo_t5_47.menu.PartitionScheme.default=Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.default.build.partitions=default
-lilygo_t5_47.menu.PartitionScheme.defaultffat=Default 4MB with ffat (1.2MB APP/1.5MB FATFS)
-lilygo_t5_47.menu.PartitionScheme.defaultffat.build.partitions=default_ffat
-lilygo_t5_47.menu.PartitionScheme.default_8MB=8M Flash (3MB APP/1.5MB FAT)
-lilygo_t5_47.menu.PartitionScheme.default_8MB.build.partitions=default_8MB
-lilygo_t5_47.menu.PartitionScheme.minimal=Minimal (1.3MB APP/700KB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.minimal.build.partitions=minimal
-lilygo_t5_47.menu.PartitionScheme.no_ota=No OTA (2MB APP/2MB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.no_ota.build.partitions=no_ota
-lilygo_t5_47.menu.PartitionScheme.no_ota.upload.maximum_size=2097152
-lilygo_t5_47.menu.PartitionScheme.noota_3g=No OTA (1MB APP/3MB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.noota_3g.build.partitions=noota_3g
-lilygo_t5_47.menu.PartitionScheme.noota_3g.upload.maximum_size=1048576
-lilygo_t5_47.menu.PartitionScheme.noota_ffat=No OTA (2MB APP/2MB FATFS)
-lilygo_t5_47.menu.PartitionScheme.noota_ffat.build.partitions=noota_ffat
-lilygo_t5_47.menu.PartitionScheme.noota_ffat.upload.maximum_size=2097152
-lilygo_t5_47.menu.PartitionScheme.noota_3gffat=No OTA (1MB APP/3MB FATFS)
-lilygo_t5_47.menu.PartitionScheme.noota_3gffat.build.partitions=noota_3gffat
-lilygo_t5_47.menu.PartitionScheme.noota_3gffat.upload.maximum_size=1048576
-lilygo_t5_47.menu.PartitionScheme.huge_app=Huge APP (3MB No OTA/1MB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.huge_app.build.partitions=huge_app
-lilygo_t5_47.menu.PartitionScheme.huge_app.upload.maximum_size=3145728
-lilygo_t5_47.menu.PartitionScheme.min_spiffs=Minimal SPIFFS (1.9MB APP with OTA/190KB SPIFFS)
-lilygo_t5_47.menu.PartitionScheme.min_spiffs.build.partitions=min_spiffs
-lilygo_t5_47.menu.PartitionScheme.min_spiffs.upload.maximum_size=1966080
-lilygo_t5_47.menu.PartitionScheme.fatflash=16M Flash (2MB APP/12.5MB FAT)
-lilygo_t5_47.menu.PartitionScheme.fatflash.build.partitions=ffat
-
-lilygo_t5_47.menu.FlashMode.qio=QIO
-lilygo_t5_47.menu.FlashMode.qio.build.flash_mode=dio
-lilygo_t5_47.menu.FlashMode.qio.build.boot=qio
-lilygo_t5_47.menu.FlashMode.dio=DIO
-lilygo_t5_47.menu.FlashMode.dio.build.flash_mode=dio
-lilygo_t5_47.menu.FlashMode.dio.build.boot=dio
-lilygo_t5_47.menu.FlashMode.qout=QOUT
-lilygo_t5_47.menu.FlashMode.qout.build.flash_mode=dout
-lilygo_t5_47.menu.FlashMode.qout.build.boot=qout
-lilygo_t5_47.menu.FlashMode.dout=DOUT
-lilygo_t5_47.menu.FlashMode.dout.build.flash_mode=dout
-lilygo_t5_47.menu.FlashMode.dout.build.boot=dout
-
-lilygo_t5_47.menu.FlashFreq.80=80MHz
-lilygo_t5_47.menu.FlashFreq.80.build.flash_freq=80m
-lilygo_t5_47.menu.FlashFreq.40=40MHz
-lilygo_t5_47.menu.FlashFreq.40.build.flash_freq=40m
-
-lilygo_t5_47.menu.UploadSpeed.921600=921600
-lilygo_t5_47.menu.UploadSpeed.921600.upload.speed=921600
-lilygo_t5_47.menu.UploadSpeed.115200=115200
-lilygo_t5_47.menu.UploadSpeed.115200.upload.speed=115200
-lilygo_t5_47.menu.UploadSpeed.256000.windows=256000
-lilygo_t5_47.menu.UploadSpeed.256000.upload.speed=256000
-lilygo_t5_47.menu.UploadSpeed.230400.windows.upload.speed=256000
-lilygo_t5_47.menu.UploadSpeed.230400=230400
-lilygo_t5_47.menu.UploadSpeed.230400.upload.speed=230400
-lilygo_t5_47.menu.UploadSpeed.460800.linux=460800
-lilygo_t5_47.menu.UploadSpeed.460800.macosx=460800
-lilygo_t5_47.menu.UploadSpeed.460800.upload.speed=460800
-lilygo_t5_47.menu.UploadSpeed.512000.windows=512000
-lilygo_t5_47.menu.UploadSpeed.512000.upload.speed=512000
-
-lilygo_t5_47.menu.DebugLevel.none=None
-lilygo_t5_47.menu.DebugLevel.none.build.code_debug=0
-lilygo_t5_47.menu.DebugLevel.error=Error
-lilygo_t5_47.menu.DebugLevel.error.build.code_debug=1
-lilygo_t5_47.menu.DebugLevel.warn=Warn
-lilygo_t5_47.menu.DebugLevel.warn.build.code_debug=2
-lilygo_t5_47.menu.DebugLevel.info=Info
-lilygo_t5_47.menu.DebugLevel.info.build.code_debug=3
-lilygo_t5_47.menu.DebugLevel.debug=Debug
-lilygo_t5_47.menu.DebugLevel.debug.build.code_debug=4
-lilygo_t5_47.menu.DebugLevel.verbose=Verbose
-lilygo_t5_47.menu.DebugLevel.verbose.build.code_debug=5
diff --git a/lib/libesp32_eink/epdiy/idf_component.yml b/lib/libesp32_eink/epdiy/idf_component.yml
new file mode 100644
index 000000000..468e38647
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/idf_component.yml
@@ -0,0 +1,4 @@
+version: "2.0.0"
+description: "Drive parallel e-Paper displays with epdiy-based boards."
+url: "https://github.com/vroland/epdiy"
+license: LGPL-3.0-or-later
diff --git a/lib/libesp32_eink/epdiy/library.json b/lib/libesp32_eink/epdiy/library.json
new file mode 100644
index 000000000..b0336ba43
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/library.json
@@ -0,0 +1,32 @@
+{
+ "name": "epdiy",
+ "version": "2.0.0",
+ "description": "Drive parallel e-Paper displays with epdiy-based boards.",
+ "keywords": "epd, driver, e-ink",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/vroland/epdiy.git"
+ },
+ "authors": [
+ {
+ "name": "Valentin Roland",
+ "email": "github@vroland.de",
+ "maintainer": true
+ }
+ ],
+ "license": "LGPL-3.0",
+ "frameworks": [
+ "arduino",
+ "espidf"
+ ],
+ "platforms": "espressif32",
+ "export": {
+ "exclude": [
+ "hardware"
+ ]
+ },
+ "build": {
+ "includeDir": "include",
+ "srcDir": "src/"
+ }
+}
diff --git a/lib/libesp32_eink/epdiy/library.properties b/lib/libesp32_eink/epdiy/library.properties
index 4635900d1..32f2aaac4 100755
--- a/lib/libesp32_eink/epdiy/library.properties
+++ b/lib/libesp32_eink/epdiy/library.properties
@@ -1,9 +1,9 @@
name=epdiy
-version=1.0.0
+version=2.0.0
author=Valentin Roland
maintainer=Valentin Roland
sentence=Drive parallel e-Paper displays with epdiy-based boards.
paragraph=See https://github.com/vroland/epdiy for details.
-architectures=esp32
+architectures=esp32,esp32s3
url=https://github.com/vroland/epdiy
category=Display
diff --git a/lib/libesp32_eink/epdiy/scripts/README.md b/lib/libesp32_eink/epdiy/scripts/README.md
new file mode 100644
index 000000000..5d74802fb
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/scripts/README.md
@@ -0,0 +1,101 @@
+## Scripts in this folder are for adding addtional capabilities to epdiy.
+
+
+
+## imgconvert.py
+
+#### usage:
+
+python3 imgconvert.py [-h] -i INPUTFILE -n NAME -o OUTPUTFILE [-maxw MAX_WIDTH]
+ [-maxh MAX_HEIGHT]
+
+**optional arguments:**
+
+ * **-h, --help** show this help message and exit
+
+ * **-i INPUTFILE**
+
+ * **-n NAME**
+
+ * **-o OUTPUTFILE**
+
+ * **-maxw MAX_WIDTH**
+
+ * **-maxh MAX_HEIGHT**
+
+
+==========================================================
+
+## fontconvert.py
+
+#### usage:
+
+python3 fontconvert.py [-h] [--compress] [--additional-intervals ADDITIONAL_INTERVALS]
+ [--string STRING]
+ name size fontstack [fontstack ...]
+
+Generate a header file from a font to be used with epdiy.
+
+**positional arguments:**
+
+ * **name** name of the font to be used in epdiy.
+ * **size** font size to use.
+ * **fontstack** list of font files, ordered by descending priority. This is not actually implemented as yet. Please just use one file for now.
+
+**optional arguments:**
+
+ * **-h**, --help show this help message and exit
+
+ * **--compress** compress glyph bitmaps.
+
+ * **--additional-intervals** ADDITIONAL_INTERVALS
+
+ Additional code point intervals to export as min,max. This argument
+ can be repeated.
+
+ * **--string STRING** A quoted string of all required characters. The intervals are will be made from these characters if they exist in the ttf file. Missing characters will warn about their abscence.
+
+
+
+####example:
+ 1. Download a ttf from where you like to a directory. As in: "~/Downloads/any_old_ttf.ttf"
+in the download directory
+
+ 2. Run
+
+ `python3 fontconvert.py my_font 30 ~/Downloads/any_old_ttf.ttf --string '/0123456789:;@ABCDEFGH[\]^_`abcdefgh\{|}~¡¢£¤¥¦§¨©ª' > fonts.h`
+
+ * you will need to use special escapes for characters like ' or " This is system dependant though.
+
+ 3. copy fonts.h into your app folder or where ever your app can find it.
+ 4. include it into your project with
+`#include fonts.h`
+Then use it just like any other font file in epdiy.
+
+**To run this script the freetype module needs to be installed. This can be done with `pip install freetype-py` You will be warned if it is not accessible by the script.**
+
+==========================================================
+
+##waveform_hdrgen.py
+
+####usage:
+
+waveform_hdrgen.py [-h] [--list-modes] [--temperature-range TEMPERATURE_RANGE]
+ [--export-modes EXPORT_MODES]
+ name
+
+**positional arguments:**
+ name name of the waveform object.
+
+**optional arguments:**
+
+ * **-h, --help** show this help message and exit
+
+ * **--list-modes** list the available modes for tis file.
+
+ * **--temperature-range TEMPERATURE_RANGE**
+ only export waveforms in the temperature range of min,max °C.
+
+ * **--export-modes EXPORT_MODES**
+ comma-separated list of waveform mode IDs to export.
+
diff --git a/lib/libesp32_eink/epdiy/scripts/fontconvert.py b/lib/libesp32_eink/epdiy/scripts/fontconvert.py
index aa233c90d..36cd62322 100755
--- a/lib/libesp32_eink/epdiy/scripts/fontconvert.py
+++ b/lib/libesp32_eink/epdiy/scripts/fontconvert.py
@@ -1,29 +1,11 @@
#!python3
-import freetype
-import zlib
import sys
-import re
-import math
-import argparse
-from collections import namedtuple
-
-parser = argparse.ArgumentParser(description="Generate a header file from a font to be used with epdiy.")
-parser.add_argument("name", action="store", help="name of the font.")
-parser.add_argument("size", type=int, help="font size to use.")
-parser.add_argument("fontstack", action="store", nargs='+', help="list of font files, ordered by descending priority.")
-parser.add_argument("--compress", dest="compress", action="store_true", help="compress glyph bitmaps.")
-parser.add_argument("--additional-intervals", dest="additional_intervals", action="append", help="Additional code point intervals to export as min,max. This argument can be repeated.")
-args = parser.parse_args()
-
-GlyphProps = namedtuple("GlyphProps", ["width", "height", "advance_x", "left", "top", "compressed_size", "data_offset", "code_point"])
-
-font_stack = [freetype.Face(f) for f in args.fontstack]
-compress = args.compress
-size = args.size
-font_name = args.name
# inclusive unicode code point intervals
# must not overlap and be in ascending order
+# modify intervals here
+# however if the "string" command line argument is used these are ignored
+
intervals = [
(32, 126),
(160, 255),
@@ -48,12 +30,107 @@ intervals = [
#(0x1F600, 0x1F680),
]
+
+
+try:
+ import freetype
+except ImportError as error:
+ sys.exit("To run this script the freetype module needs to be installed.\nThis can be done using:\npip install freetype-py")
+import zlib
+import sys
+import re
+import math
+import argparse
+from collections import namedtuple
+#see https://freetype-py.readthedocs.io/en/latest/ for documentation
+parser = argparse.ArgumentParser(description="Generate a header file from a font to be used with epdiy.")
+parser.add_argument("name", action="store", help="name of the font.")
+parser.add_argument("size", type=int, help="font size to use.")
+parser.add_argument("fontstack", action="store", nargs='+', help="list of font files, ordered by descending priority. This is not actually implemented please just use one file for now.")
+parser.add_argument("--compress", dest="compress", action="store_true", help="compress glyph bitmaps.")
+parser.add_argument("--additional-intervals", dest="additional_intervals", action="append", help="Additional code point intervals to export as min,max. This argument can be repeated.")
+parser.add_argument("--string", action="store", help="A string of all required characters. intervals are made up of this" )
+
+args = parser.parse_args()
+command_line = ""
+prev_arg = ""
+for arg in sys.argv:
+ # ~ if prev_arg == "--string":
+ # ~ command_line = command_line + " '" + arg +"'"
+ # ~ else:
+ command_line = command_line + " " + arg
+ # ~ prev_arg = arg
+
+# ~ print (command_line)
+GlyphProps = namedtuple("GlyphProps", ["width", "height", "advance_x", "left", "top", "compressed_size", "data_offset", "code_point"])
+
+font_stack = [freetype.Face(f) for f in args.fontstack]
+font_files = args.fontstack
+face_index = 0
+font_file = font_files[face_index]
+compress = args.compress
+size = args.size
+font_name = args.name
+
+for face in font_stack:
+ # shift by 6 bytes, because sizes are given as 6-bit fractions
+ # the display has about 150 dpi.
+ face.set_char_size(size << 6, size << 6, 150, 150)
+
+
+# assign intervals from argument parrameters ie. handle the string arg
+
+if args.string != None:
+ font_file = font_files[face_index]
+ string = " " + args.string # always add space to the string it is easily forgotten
+ chars = sorted(set(string))
+ #make array of code pointscode_ponts.append(ord(char))
+ code_points = list()
+ intervals = [] # empty the intevals array NB. if you want to allways add default characters comment out this line
+ # go through the sorted characters and make the intervals
+ for char in chars:
+ if( face.get_char_index(ord(char)) != 0 ):
+ # this character is in the font file so add it to the new string.
+ code_points.append(ord(char))
+ else:
+ print("The character ", char, " is not available in ", font_file, file=sys.stderr)
+ lower = code_points[0]
+ len_x = len(code_points)
+ x = 0
+ while x < len_x:
+ # ~ print ("loop value x = ", x , file=sys.stderr)
+ a = code_points[x];
+ b = a;
+ if( x < len_x - 1):
+ b = code_points[x + 1];
+
+ if( a == b - 1 ):
+ # ~ print("sequential", a, b, file=sys.stderr)
+ if( lower == -1):
+ lower = a
+ else:
+ # ~ print("non sequential", a, b , file=sys.stderr)
+ if( lower == -1):
+ # ~ print("single character")
+ interval = (a , a)
+ else:
+ interval = (lower, a)
+ # ~ print("interval", interval , file=sys.stderr)
+ intervals.append(interval)
+ lower = -1
+ x = x + 1
+
+
+# base intervals are assigned dditional intervals from arguments
add_ints = []
-if args.additional_intervals:
+if args.additional_intervals != None:
add_ints = [tuple([int(n, base=0) for n in i.split(",")]) for i in args.additional_intervals]
intervals = sorted(intervals + add_ints)
+# ~ print("Intervals are now: ", intervals, file=sys.stderr)
+
+
def norm_floor(val):
return int(math.floor(val / (1 << 6)))
@@ -73,21 +150,48 @@ total_size = 0
total_packed = 0
all_glyphs = []
+# new globals
+total_chars = 0
+ascender = 0
+descender = 100
+f_height = 0
+
def load_glyph(code_point):
+ global face_index
face_index = 0
while face_index < len(font_stack):
face = font_stack[face_index]
glyph_index = face.get_char_index(code_point)
if glyph_index > 0:
face.load_glyph(glyph_index, freetype.FT_LOAD_RENDER)
+ #count characters found and find bounds of characters
+ global ascender
+ if ascender < face.size.ascender:
+ ascender = face.size.ascender
+ global descender
+ if descender > face.size.descender:
+ descender = face.size.descender
+ global f_height
+ if f_height < face.size.height:
+ f_height = face.size.height
+ global total_chars
+ total_chars += 1
return face
break
face_index += 1
+ # this needs work
+ # this needs to be handled better to show failed character and continue not just die a questionable death
+ # this appears to have been designed to combine several font files
+ # but that is not clear to the end user and this then looks like a bug
print (f"falling back to font {face_index} for {chr(code_point)}.", file=sys.stderr)
raise ValueError(f"code point {code_point} not found in font stack!")
for i_start, i_end in intervals:
for code_point in range(i_start, i_end + 1):
+ # handle missing characters in font file
+ if( face.get_char_index(code_point) == 0 ):
+ print("Character ", chr(code_point), "(", code_point, ") is not in ", font_file, file=sys.stderr)
+ continue
face = load_glyph(code_point)
bitmap = face.glyph.bitmap
pixels = []
@@ -126,7 +230,8 @@ for i_start, i_end in intervals:
all_glyphs.append((glyph, compressed))
# pipe seems to be a good heuristic for the "real" descender
-face = load_glyph(ord('|'))
+# face = load_glyph(ord('|'))
+# removed as max descender and assender are handled above
glyph_data = []
glyph_props = []
@@ -134,23 +239,38 @@ for index, glyph in enumerate(all_glyphs):
props, compressed = glyph
glyph_data.extend([b for b in compressed])
glyph_props.append(props)
+print("", file=sys.stderr)
+print(f"Original font file {font_file} as {font_name} using {total_chars} characters", file=sys.stderr)
print("total", total_packed, file=sys.stderr)
print("compressed", total_size, file=sys.stderr)
print("#pragma once")
-print("#include \"epd_driver.h\"")
-print(f"const uint8_t {font_name}Bitmaps[{len(glyph_data)}] = {{")
+print("#include \"epdiy.h\"")
+
+# add font file origin and characters at the head of the output file
+print("/*")
+print ( "Created with")
+print(command_line)
+print(f"As '{font_name}' with available {total_chars} characters")
+for i, g in enumerate(glyph_props):
+ print (f"{chr(g.code_point)}", end ="" )
+print("")
+print("*/")
+
+print(f"const uint8_t {font_name}_Bitmaps[{len(glyph_data)}] = {{")
for c in chunks(glyph_data, 16):
print (" " + " ".join(f"0x{b:02X}," for b in c))
print ("};");
-print(f"const EpdGlyph {font_name}Glyphs[] = {{")
+
+print ('// GlyphProps[width, height, advance_x, left, top, compressed_size, data_offset, code_point]')
+print(f"const EpdGlyph {font_name}_Glyphs[] = {{")
for i, g in enumerate(glyph_props):
- print (" { " + ", ".join([f"{a}" for a in list(g[:-1])]),"},", f"// {chr(g.code_point) if g.code_point != 92 else ''}")
+ print (" { " + ", ".join([f"{a}" for a in list(g[:-1])]),"},", f"// '{chr(g.code_point) if g.code_point != 92 else ''}'")
print ("};");
-print(f"const EpdUnicodeInterval {font_name}Intervals[] = {{")
+print(f"const EpdUnicodeInterval {font_name}_Intervals[] = {{")
offset = 0
for i_start, i_end in intervals:
print (f" {{ 0x{i_start:X}, 0x{i_end:X}, 0x{offset:X} }},")
@@ -158,12 +278,22 @@ for i_start, i_end in intervals:
print ("};");
print(f"const EpdFont {font_name} = {{")
-print(f" {font_name}Bitmaps,")
-print(f" {font_name}Glyphs,")
-print(f" {font_name}Intervals,")
-print(f" {len(intervals)},")
-print(f" {1 if compress else 0},")
-print(f" {norm_ceil(face.size.height)},")
-print(f" {norm_ceil(face.size.ascender)},")
-print(f" {norm_floor(face.size.descender)},")
+print(f" {font_name}_Bitmaps, // (*bitmap) Glyph bitmap pointer, all concatenated together")
+print(f" {font_name}_Glyphs, // glyphs Glyph array")
+print(f" {font_name}_Intervals, // intervals Valid unicode intervals for this font")
+print(f" {len(intervals)}, // interval_count Number of unicode intervals.intervals")
+print(f" {1 if compress else 0}, // compressed Does this font use compressed glyph bitmaps?")
+print(f" {norm_ceil(f_height)}, // advance_y Newline distance (y axis)")
+print(f" {norm_ceil(ascender)}, // ascender Maximal height of a glyph above the base line")
+print(f" {norm_floor(descender)}, // descender Maximal height of a glyph below the base line")
print("};")
+print("/*")
+print("Included intervals")
+for i_start, i_end in intervals:
+ print (f" ( {i_start}, {i_end}), ie. '{chr(i_start)}' - '{chr(i_end)}'")
+print("Included intervals", file=sys.stderr)
+for i_start, i_end in intervals:
+ print (f" ( {i_start}, {i_end}), ie. '{chr(i_start)}' - '{chr(i_end)}'", file=sys.stderr)
+print("")
+print("*/")
+
diff --git a/lib/libesp32_eink/epdiy/scripts/imgconvert.py b/lib/libesp32_eink/epdiy/scripts/imgconvert.py
index ba7c581b3..be91f0b06 100755
--- a/lib/libesp32_eink/epdiy/scripts/imgconvert.py
+++ b/lib/libesp32_eink/epdiy/scripts/imgconvert.py
@@ -17,7 +17,7 @@ args = parser.parse_args()
im = Image.open(args.inputfile)
# convert to grayscale
im = im.convert(mode='L')
-im.thumbnail((args.max_width, args.max_height), Image.ANTIALIAS)
+im.thumbnail((args.max_width, args.max_height), Image.LANCZOS)
# Write out the output file.
with open(args.outputfile, 'w') as f:
diff --git a/lib/libesp32_eink/epdiy/scripts/waveform_hdrgen.py b/lib/libesp32_eink/epdiy/scripts/waveform_hdrgen.py
index bb2e5c382..7d8722324 100755
--- a/lib/libesp32_eink/epdiy/scripts/waveform_hdrgen.py
+++ b/lib/libesp32_eink/epdiy/scripts/waveform_hdrgen.py
@@ -18,24 +18,36 @@ waveforms = json.load(sys.stdin);
total_size = 0
-def phase_to_c(phase):
- """
- Convert a 5 bit phase to a 4 bit C LUT.
- """
- global total_size
+def phase_to_c(phase,bits_per_pixel_c=4):
+
+ N1 = len(phase)
+ N2 = len(phase[0])
+ N = 2**bits_per_pixel_c
+
+ if N1%N != 0:
+ raise ValueError(f"first dimension of phases is {N1}. Allowed are multiples of {N}")
+
+ step1 = int(N1/N)
+
+ if N2%N != 0:
+ raise ValueError(f"second dimension of phases is {N2}. Allowed are multiples of {N}")
+
+ step2 = int(N2/N)
targets = []
- for t in range(0, 32, 2):
+ for t in range(0, N1, step1):
chunk = 0
line = []
- for f in range(0, 32, 2):
+ i = 0
+ for f in range(0, N2, step2):
fr = phase[t][f]
chunk = (chunk << 2) | fr
- if f and f % 8 == 6:
+ i += 1
+ if i == 4:
+ i = 0
line.append(chunk)
chunk = 0
targets.append(line)
- total_size += len(line)
return targets
@@ -61,7 +73,7 @@ if args.temperature_range:
modes = []
-mode_filter = list(range(len(waveforms["modes"])))
+mode_filter = [wm["mode"] for wm in waveforms["modes"]]
if args.export_modes:
mode_filter = list(map(int, args.export_modes.split(",")))
@@ -72,6 +84,8 @@ num_modes = len(mode_filter)
temp_intervals = []
for bounds in waveforms["temperature_ranges"]["range_bounds"]:
+ if bounds["to"] < tmin or bounds["from"] > tmax:
+ continue
temp_intervals.append(f"{{ .min = {bounds['from']}, .max = {bounds['to']} }}")
modes = []
@@ -84,7 +98,7 @@ for m_index, mode in enumerate(waveforms["modes"]):
ranges = []
for i, r in enumerate(mode["ranges"]):
bounds = waveforms["temperature_ranges"]["range_bounds"][i]
- if bounds["from"] < tmin or bounds["from"] > tmax:
+ if bounds["to"] < tmin or bounds["from"] > tmax:
continue
phases = []
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/Makefile b/lib/libesp32_eink/epdiy/src/Makefile
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/Makefile
rename to lib/libesp32_eink/epdiy/src/Makefile
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board.c b/lib/libesp32_eink/epdiy/src/board/epd_board.c
new file mode 100644
index 000000000..ce0944c44
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board.c
@@ -0,0 +1,77 @@
+#include "epd_board.h"
+
+#include
+#include
+
+#include "epdiy.h"
+
+/**
+ * The board's display control pin state.
+ */
+static epd_ctrl_state_t ctrl_state;
+
+/**
+ * The EPDIY board in use.
+ */
+const EpdBoardDefinition* epd_board = NULL;
+
+void IRAM_ATTR epd_busy_delay(uint32_t cycles) {
+ volatile unsigned long counts = XTHAL_GET_CCOUNT() + cycles;
+ while (XTHAL_GET_CCOUNT() < counts) {
+ };
+}
+
+void epd_set_board(const EpdBoardDefinition* board_definition) {
+ if (epd_board == NULL) {
+ epd_board = board_definition;
+ } else {
+ ESP_LOGW("epdiy", "EPD board can only be set once!");
+ }
+}
+
+const EpdBoardDefinition* epd_current_board() {
+ return epd_board;
+}
+
+void epd_set_mode(bool state) {
+ ctrl_state.ep_output_enable = state;
+ ctrl_state.ep_mode = state;
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ };
+ epd_board->set_ctrl(&ctrl_state, &mask);
+}
+
+epd_ctrl_state_t* epd_ctrl_state() {
+ return &ctrl_state;
+}
+
+void epd_control_reg_init() {
+ ctrl_state.ep_latch_enable = false;
+ ctrl_state.ep_output_enable = false;
+ ctrl_state.ep_sth = true;
+ ctrl_state.ep_mode = false;
+ ctrl_state.ep_stv = true;
+ epd_ctrl_state_t mask = {
+ .ep_latch_enable = true,
+ .ep_output_enable = true,
+ .ep_sth = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+
+ epd_board->set_ctrl(&ctrl_state, &mask);
+}
+
+void epd_control_reg_deinit() {
+ ctrl_state.ep_output_enable = false;
+ ctrl_state.ep_mode = false;
+ ctrl_state.ep_stv = false;
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ epd_board->set_ctrl(&ctrl_state, &mask);
+}
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_common.c b/lib/libesp32_eink/epdiy/src/board/epd_board_common.c
new file mode 100644
index 000000000..21dd9cc1b
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_common.c
@@ -0,0 +1,34 @@
+#include "driver/adc.h"
+#include "epd_board.h"
+#include "esp_adc_cal.h"
+#include "esp_log.h"
+
+static const adc1_channel_t channel = ADC1_CHANNEL_7;
+static esp_adc_cal_characteristics_t adc_chars;
+
+#define NUMBER_OF_SAMPLES 100
+
+void epd_board_temperature_init_v2() {
+ esp_adc_cal_value_t val_type
+ = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, 1100, &adc_chars);
+ if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
+ ESP_LOGI("epd_temperature", "Characterized using Two Point Value\n");
+ } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
+ ESP_LOGI("esp_temperature", "Characterized using eFuse Vref\n");
+ } else {
+ ESP_LOGI("esp_temperature", "Characterized using Default Vref\n");
+ }
+ adc1_config_width(ADC_WIDTH_BIT_12);
+ adc1_config_channel_atten(channel, ADC_ATTEN_DB_6);
+}
+
+float epd_board_ambient_temperature_v2() {
+ uint32_t value = 0;
+ for (int i = 0; i < NUMBER_OF_SAMPLES; i++) {
+ value += adc1_get_raw(channel);
+ }
+ value /= NUMBER_OF_SAMPLES;
+ // voltage in mV
+ float voltage = esp_adc_cal_raw_to_voltage(value, &adc_chars);
+ return (voltage - 500.0) / 10.0;
+}
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_common.h b/lib/libesp32_eink/epdiy/src/board/epd_board_common.h
new file mode 100644
index 000000000..eaedbd367
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_common.h
@@ -0,0 +1,8 @@
+/**
+ * @file "epd_board_common.h"
+ * @brief Common board functions shared between boards.
+ */
+#pragma once
+
+void epd_board_temperature_init_v2();
+float epd_board_ambient_temperature_v2();
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_lilygo_t5_47.c b/lib/libesp32_eink/epdiy/src/board/epd_board_lilygo_t5_47.c
new file mode 100644
index 000000000..e153d7c3e
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_lilygo_t5_47.c
@@ -0,0 +1,227 @@
+#include "epd_board.h"
+
+#include
+#include "../output_i2s/i2s_data_bus.h"
+#include "../output_i2s/render_i2s.h"
+#include "../output_i2s/rmt_pulse.h"
+
+// Make this compile on the S3 to avoid long ifdefs
+#ifndef CONFIG_IDF_TARGET_ESP32
+#define GPIO_NUM_22 0
+#define GPIO_NUM_23 0
+#define GPIO_NUM_24 0
+#define GPIO_NUM_25 0
+#endif
+
+#define CFG_DATA GPIO_NUM_23
+#define CFG_CLK GPIO_NUM_18
+#define CFG_STR GPIO_NUM_0
+#define D7 GPIO_NUM_22
+#define D6 GPIO_NUM_21
+#define D5 GPIO_NUM_27
+#define D4 GPIO_NUM_2
+#define D3 GPIO_NUM_19
+#define D2 GPIO_NUM_4
+#define D1 GPIO_NUM_32
+#define D0 GPIO_NUM_33
+
+/* Control Lines */
+#define CKV GPIO_NUM_25
+#define STH GPIO_NUM_26
+
+#define V4_LATCH_ENABLE GPIO_NUM_15
+
+/* Edges */
+#define CKH GPIO_NUM_5
+
+typedef struct {
+ bool power_disable : 1;
+ bool pos_power_enable : 1;
+ bool neg_power_enable : 1;
+ bool ep_scan_direction : 1;
+} epd_config_register_t;
+
+static i2s_bus_config i2s_config = {
+ .clock = CKH,
+ .start_pulse = STH,
+ .data_0 = D0,
+ .data_1 = D1,
+ .data_2 = D2,
+ .data_3 = D3,
+ .data_4 = D4,
+ .data_5 = D5,
+ .data_6 = D6,
+ .data_7 = D7,
+};
+
+static void IRAM_ATTR push_cfg_bit(bool bit) {
+ gpio_set_level(CFG_CLK, 0);
+ gpio_set_level(CFG_DATA, bit);
+ gpio_set_level(CFG_CLK, 1);
+}
+
+static epd_config_register_t config_reg;
+
+static void epd_board_init(uint32_t epd_row_width) {
+ /* Power Control Output/Off */
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
+ gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
+ fast_gpio_set_lo(CFG_STR);
+
+ config_reg.power_disable = true;
+ config_reg.pos_power_enable = false;
+ config_reg.neg_power_enable = false;
+ config_reg.ep_scan_direction = true;
+
+ // Setup I2S
+ // add an offset off dummy bytes to allow for enough timing headroom
+ i2s_bus_init(&i2s_config, epd_row_width + 32);
+
+ rmt_pulse_init(CKV);
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ if (state->ep_sth) {
+ fast_gpio_set_hi(STH);
+ } else {
+ fast_gpio_set_lo(STH);
+ }
+
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv || mask->ep_latch_enable) {
+ fast_gpio_set_lo(CFG_STR);
+
+ // push config bits in reverse order
+ push_cfg_bit(state->ep_output_enable);
+ push_cfg_bit(state->ep_mode);
+ push_cfg_bit(config_reg.ep_scan_direction);
+ push_cfg_bit(state->ep_stv);
+
+ push_cfg_bit(config_reg.neg_power_enable);
+ push_cfg_bit(config_reg.pos_power_enable);
+ push_cfg_bit(config_reg.power_disable);
+ push_cfg_bit(state->ep_latch_enable);
+
+ fast_gpio_set_hi(CFG_STR);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ i2s_gpio_attach(&i2s_config);
+
+ // This was re-purposed as power enable.
+ config_reg.ep_scan_direction = true;
+
+ // POWERON
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_disable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ config_reg.neg_power_enable = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.pos_power_enable = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ state->ep_stv = true;
+ state->ep_sth = true;
+ mask.ep_sth = true;
+ epd_board_set_ctrl(state, &mask);
+ // END POWERON
+}
+
+void epd_powerdown_lilygo_t5_47() {
+ epd_ctrl_state_t* state = epd_ctrl_state();
+
+ // This was re-purposed as power enable however it also disables the touch.
+ // this workaround may still leave power on to epd and as such may cause other
+ // problems such as grey screen.
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(10 * 240);
+
+ config_reg.neg_power_enable = false;
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = false;
+ mask.ep_stv = true;
+ state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ state->ep_mode = false;
+ mask.ep_mode = true;
+ config_reg.power_disable = true;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+}
+
+static void epd_board_poweroff_common(epd_ctrl_state_t* state) {
+ // POWEROFF
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(10 * 240);
+
+ config_reg.neg_power_enable = false;
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = false;
+ mask.ep_stv = true;
+ state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ state->ep_mode = false;
+ mask.ep_mode = true;
+ config_reg.power_disable = true;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+ // END POWEROFF
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ // This was re-purposed as power enable.
+ config_reg.ep_scan_direction = false;
+ epd_board_poweroff_common(state);
+}
+
+static void epd_board_poweroff_touch(epd_ctrl_state_t* state) {
+ // This was re-purposed as power enable.
+ config_reg.ep_scan_direction = true;
+ epd_board_poweroff_common(state);
+}
+
+const EpdBoardDefinition epd_board_lilygo_t5_47 = {
+ .init = epd_board_init,
+ .deinit = NULL,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+ .get_temperature = NULL,
+};
+
+const EpdBoardDefinition epd_board_lilygo_t5_47_touch = {
+ .init = epd_board_init,
+ .deinit = NULL,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff_touch,
+ .get_temperature = NULL,
+ .set_vcom = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v2_v3.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v2_v3.c
new file mode 100644
index 000000000..87fe25437
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v2_v3.c
@@ -0,0 +1,172 @@
+#include "epd_board.h"
+
+#include
+#include "../output_i2s/i2s_data_bus.h"
+#include "../output_i2s/render_i2s.h"
+#include "../output_i2s/rmt_pulse.h"
+#include "epd_board_common.h"
+
+// Make this compile on the S3 to avoid long ifdefs
+#ifndef CONFIG_IDF_TARGET_ESP32
+#define GPIO_NUM_22 0
+#define GPIO_NUM_23 0
+#define GPIO_NUM_24 0
+#define GPIO_NUM_25 0
+#endif
+
+#define CFG_DATA GPIO_NUM_23
+#define CFG_CLK GPIO_NUM_18
+#define CFG_STR GPIO_NUM_19
+#define D7 GPIO_NUM_22
+#define D6 GPIO_NUM_21
+#define D5 GPIO_NUM_27
+#define D4 GPIO_NUM_2
+#define D3 GPIO_NUM_0
+#define D2 GPIO_NUM_4
+#define D1 GPIO_NUM_32
+#define D0 GPIO_NUM_33
+
+/* Control Lines */
+#define CKV GPIO_NUM_25
+#define STH GPIO_NUM_26
+
+/* Edges */
+#define CKH GPIO_NUM_5
+
+typedef struct {
+ bool power_disable : 1;
+ bool pos_power_enable : 1;
+ bool neg_power_enable : 1;
+ bool ep_scan_direction : 1;
+} epd_config_register_t;
+
+static i2s_bus_config i2s_config = {
+ .clock = CKH,
+ .start_pulse = STH,
+ .data_0 = D0,
+ .data_1 = D1,
+ .data_2 = D2,
+ .data_3 = D3,
+ .data_4 = D4,
+ .data_5 = D5,
+ .data_6 = D6,
+ .data_7 = D7,
+};
+
+static void IRAM_ATTR push_cfg_bit(bool bit) {
+ gpio_set_level(CFG_CLK, 0);
+ gpio_set_level(CFG_DATA, bit);
+ gpio_set_level(CFG_CLK, 1);
+}
+
+static epd_config_register_t config_reg;
+
+static void epd_board_init(uint32_t epd_row_width) {
+ /* Power Control Output/Off */
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
+ gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
+ fast_gpio_set_lo(CFG_STR);
+
+ config_reg.power_disable = true;
+ config_reg.pos_power_enable = false;
+ config_reg.neg_power_enable = false;
+ config_reg.ep_scan_direction = true;
+
+ // Setup I2S
+ // add an offset off dummy bytes to allow for enough timing headroom
+ i2s_bus_init(&i2s_config, epd_row_width + 32);
+
+ rmt_pulse_init(CKV);
+
+ epd_board_temperature_init_v2();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ if (state->ep_sth) {
+ fast_gpio_set_hi(STH);
+ } else {
+ fast_gpio_set_lo(STH);
+ }
+
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv || mask->ep_latch_enable) {
+ fast_gpio_set_lo(CFG_STR);
+
+ // push config bits in reverse order
+ push_cfg_bit(state->ep_output_enable);
+ push_cfg_bit(state->ep_mode);
+ push_cfg_bit(config_reg.ep_scan_direction);
+ push_cfg_bit(state->ep_stv);
+
+ push_cfg_bit(config_reg.neg_power_enable);
+ push_cfg_bit(config_reg.pos_power_enable);
+ push_cfg_bit(config_reg.power_disable);
+ push_cfg_bit(state->ep_latch_enable);
+
+ fast_gpio_set_hi(CFG_STR);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ // POWERON
+ i2s_gpio_attach(&i2s_config);
+
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_disable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ config_reg.neg_power_enable = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.pos_power_enable = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ state->ep_stv = true;
+ state->ep_sth = true;
+ mask.ep_sth = true;
+ epd_board_set_ctrl(state, &mask);
+ // END POWERON
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ // POWEROFF
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(10 * 240);
+
+ config_reg.neg_power_enable = false;
+ config_reg.pos_power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ state->ep_mode = false;
+ mask.ep_mode = true;
+ config_reg.power_disable = true;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+ // END POWEROFF
+}
+
+const EpdBoardDefinition epd_board_v2_v3 = {
+ .init = epd_board_init,
+ .deinit = NULL,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+ .get_temperature = epd_board_ambient_temperature_v2,
+ .set_vcom = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v4.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v4.c
new file mode 100644
index 000000000..be0d65784
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v4.c
@@ -0,0 +1,194 @@
+#include "epd_board.h"
+
+#include
+#include "../output_i2s/i2s_data_bus.h"
+#include "../output_i2s/render_i2s.h"
+#include "../output_i2s/rmt_pulse.h"
+#include "epd_board_common.h"
+
+// Make this compile on the S3 to avoid long ifdefs
+#ifndef CONFIG_IDF_TARGET_ESP32
+#define GPIO_NUM_22 0
+#define GPIO_NUM_23 0
+#define GPIO_NUM_24 0
+#define GPIO_NUM_25 0
+#endif
+
+#define CFG_DATA GPIO_NUM_23
+#define CFG_CLK GPIO_NUM_18
+#define CFG_STR GPIO_NUM_19
+#define D7 GPIO_NUM_22
+#define D6 GPIO_NUM_21
+#define D5 GPIO_NUM_27
+#define D4 GPIO_NUM_2
+#define D3 GPIO_NUM_0
+#define D2 GPIO_NUM_4
+#define D1 GPIO_NUM_32
+#define D0 GPIO_NUM_33
+
+/* Control Lines */
+#define CKV GPIO_NUM_25
+#define STH GPIO_NUM_26
+
+#define V4_LATCH_ENABLE GPIO_NUM_15
+
+/* Edges */
+#define CKH GPIO_NUM_5
+
+typedef struct {
+ bool power_disable : 1;
+ bool power_enable_vpos : 1;
+ bool power_enable_vneg : 1;
+ bool power_enable_gl : 1;
+ bool power_enable_gh : 1;
+} epd_config_register_t;
+
+static i2s_bus_config i2s_config = {
+ .clock = CKH,
+ .start_pulse = STH,
+ .data_0 = D0,
+ .data_1 = D1,
+ .data_2 = D2,
+ .data_3 = D3,
+ .data_4 = D4,
+ .data_5 = D5,
+ .data_6 = D6,
+ .data_7 = D7,
+};
+
+static void IRAM_ATTR push_cfg_bit(bool bit) {
+ gpio_set_level(CFG_CLK, 0);
+ gpio_set_level(CFG_DATA, bit);
+ gpio_set_level(CFG_CLK, 1);
+}
+
+static epd_config_register_t config_reg;
+
+static void epd_board_init(uint32_t epd_row_width) {
+ /* Power Control Output/Off */
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
+ gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
+ fast_gpio_set_lo(CFG_STR);
+
+ config_reg.power_disable = true;
+ config_reg.power_enable_vpos = false;
+ config_reg.power_enable_vneg = false;
+ config_reg.power_enable_gl = false;
+ config_reg.power_enable_gh = false;
+
+ // use latch pin as GPIO
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[V4_LATCH_ENABLE], PIN_FUNC_GPIO);
+ ESP_ERROR_CHECK(gpio_set_direction(V4_LATCH_ENABLE, GPIO_MODE_OUTPUT));
+ gpio_set_level(V4_LATCH_ENABLE, 0);
+
+ // Setup I2S
+ // add an offset off dummy bytes to allow for enough timing headroom
+ i2s_bus_init(&i2s_config, epd_row_width + 32);
+
+ rmt_pulse_init(CKV);
+
+ epd_board_temperature_init_v2();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ if (state->ep_sth) {
+ fast_gpio_set_hi(STH);
+ } else {
+ fast_gpio_set_lo(STH);
+ }
+
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv) {
+ fast_gpio_set_lo(CFG_STR);
+
+ // push config bits in reverse order
+ push_cfg_bit(state->ep_output_enable);
+ push_cfg_bit(state->ep_mode);
+ push_cfg_bit(config_reg.power_enable_gh);
+ push_cfg_bit(state->ep_stv);
+
+ push_cfg_bit(config_reg.power_enable_gl);
+ push_cfg_bit(config_reg.power_enable_vneg);
+ push_cfg_bit(config_reg.power_enable_vpos);
+ push_cfg_bit(config_reg.power_disable);
+
+ fast_gpio_set_hi(CFG_STR);
+ fast_gpio_set_lo(CFG_STR);
+ }
+
+ if (state->ep_latch_enable) {
+ fast_gpio_set_hi(V4_LATCH_ENABLE);
+ } else {
+ fast_gpio_set_lo(V4_LATCH_ENABLE);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ // POWERON
+ i2s_gpio_attach(&i2s_config);
+
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_disable = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ config_reg.power_enable_gl = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_vneg = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_gh = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_vpos = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ state->ep_stv = true;
+ state->ep_sth = true;
+ mask.ep_sth = true;
+ epd_board_set_ctrl(state, &mask);
+ // END POWERON
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ // POWEROFF
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_enable_gh = false;
+ config_reg.power_enable_vpos = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(10 * 240);
+ config_reg.power_enable_gl = false;
+ config_reg.power_enable_vneg = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ state->ep_mode = false;
+ mask.ep_mode = true;
+ config_reg.power_disable = true;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+ // END POWEROFF
+}
+
+const EpdBoardDefinition epd_board_v4 = {
+ .init = epd_board_init,
+ .deinit = NULL,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+ .get_temperature = epd_board_ambient_temperature_v2,
+ .set_vcom = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v5.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v5.c
new file mode 100644
index 000000000..e413d0d98
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v5.c
@@ -0,0 +1,196 @@
+#include "epd_board.h"
+
+#include
+#include "epd_board_common.h"
+
+#include "../output_i2s/i2s_data_bus.h"
+#include "../output_i2s/render_i2s.h"
+#include "../output_i2s/rmt_pulse.h"
+#include "driver/rtc_io.h"
+
+// Make this compile on the S3 to avoid long ifdefs
+#ifndef CONFIG_IDF_TARGET_ESP32
+#define GPIO_NUM_22 0
+#define GPIO_NUM_23 0
+#define GPIO_NUM_24 0
+#define GPIO_NUM_25 0
+#endif
+
+#define CFG_DATA GPIO_NUM_33
+#define CFG_CLK GPIO_NUM_32
+#define CFG_STR GPIO_NUM_0
+#define D7 GPIO_NUM_23
+#define D6 GPIO_NUM_22
+#define D5 GPIO_NUM_21
+#define D4 GPIO_NUM_19
+#define D3 GPIO_NUM_18
+#define D2 GPIO_NUM_5
+#define D1 GPIO_NUM_4
+#define D0 GPIO_NUM_25
+
+/* Control Lines */
+#define CKV GPIO_NUM_26
+#define STH GPIO_NUM_27
+
+#define V4_LATCH_ENABLE GPIO_NUM_2
+
+/* Edges */
+#define CKH GPIO_NUM_15
+
+typedef struct {
+ bool power_enable : 1;
+ bool power_enable_vpos : 1;
+ bool power_enable_vneg : 1;
+ bool power_enable_gl : 1;
+ bool power_enable_gh : 1;
+} epd_config_register_t;
+static epd_config_register_t config_reg;
+
+static i2s_bus_config i2s_config = {
+ .clock = CKH,
+ .start_pulse = STH,
+ .data_0 = D0,
+ .data_1 = D1,
+ .data_2 = D2,
+ .data_3 = D3,
+ .data_4 = D4,
+ .data_5 = D5,
+ .data_6 = D6,
+ .data_7 = D7,
+};
+
+static void IRAM_ATTR push_cfg_bit(bool bit) {
+ gpio_set_level(CFG_CLK, 0);
+ gpio_set_level(CFG_DATA, bit);
+ gpio_set_level(CFG_CLK, 1);
+}
+
+static void epd_board_init(uint32_t epd_row_width) {
+ /* Power Control Output/Off */
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
+ gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
+ fast_gpio_set_lo(CFG_STR);
+
+ config_reg.power_enable = false;
+ config_reg.power_enable_vpos = false;
+ config_reg.power_enable_vneg = false;
+ config_reg.power_enable_gl = false;
+ config_reg.power_enable_gh = false;
+
+ // use latch pin as GPIO
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[V4_LATCH_ENABLE], PIN_FUNC_GPIO);
+ ESP_ERROR_CHECK(gpio_set_direction(V4_LATCH_ENABLE, GPIO_MODE_OUTPUT));
+ gpio_set_level(V4_LATCH_ENABLE, 0);
+
+ // Setup I2S
+ // add an offset off dummy bytes to allow for enough timing headroom
+ i2s_bus_init(&i2s_config, epd_row_width + 32);
+
+ rmt_pulse_init(CKV);
+
+ epd_board_temperature_init_v2();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ if (state->ep_sth) {
+ fast_gpio_set_hi(STH);
+ } else {
+ fast_gpio_set_lo(STH);
+ }
+
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv) {
+ fast_gpio_set_lo(CFG_STR);
+
+ // push config bits in reverse order
+ push_cfg_bit(state->ep_output_enable);
+ push_cfg_bit(state->ep_mode);
+ push_cfg_bit(config_reg.power_enable_gh);
+ push_cfg_bit(state->ep_stv);
+
+ push_cfg_bit(config_reg.power_enable_gl);
+ push_cfg_bit(config_reg.power_enable_vneg);
+ push_cfg_bit(config_reg.power_enable_vpos);
+ push_cfg_bit(config_reg.power_enable);
+
+ fast_gpio_set_hi(CFG_STR);
+ fast_gpio_set_lo(CFG_STR);
+ }
+
+ if (state->ep_latch_enable) {
+ fast_gpio_set_hi(V4_LATCH_ENABLE);
+ } else {
+ fast_gpio_set_lo(V4_LATCH_ENABLE);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ // POWERON
+ i2s_gpio_attach(&i2s_config);
+
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_enable = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+ config_reg.power_enable_gl = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_vneg = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_gh = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(500 * 240);
+ config_reg.power_enable_vpos = true;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = true;
+ state->ep_sth = true;
+ mask.ep_sth = true;
+ epd_board_set_ctrl(state, &mask);
+ // END POWERON
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ // POWEROFF
+ epd_ctrl_state_t mask = {
+ // Trigger output to shift register
+ .ep_stv = true,
+ };
+ config_reg.power_enable_gh = false;
+ config_reg.power_enable_vpos = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(10 * 240);
+ config_reg.power_enable_gl = false;
+ config_reg.power_enable_vneg = false;
+ epd_board_set_ctrl(state, &mask);
+ epd_busy_delay(100 * 240);
+
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ state->ep_mode = false;
+ mask.ep_mode = true;
+ config_reg.power_enable = false;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+ // END POWEROFF
+}
+
+const EpdBoardDefinition epd_board_v5 = {
+ .init = epd_board_init,
+ .deinit = NULL,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+ .get_temperature = epd_board_ambient_temperature_v2,
+ .set_vcom = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v6.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v6.c
new file mode 100644
index 000000000..f544d1a8c
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v6.c
@@ -0,0 +1,359 @@
+#include "driver/gpio.h"
+#include "epd_board.h"
+
+#include
+#include
+#include
+#include "../output_i2s/i2s_data_bus.h"
+#include "../output_i2s/render_i2s.h"
+#include "../output_i2s/rmt_pulse.h"
+#include "pca9555.h"
+#include "tps65185.h"
+
+// Make this compile on the S3 to avoid long ifdefs
+#ifndef CONFIG_IDF_TARGET_ESP32
+#define GPIO_NUM_22 0
+#define GPIO_NUM_23 0
+#define GPIO_NUM_24 0
+#define GPIO_NUM_25 0
+#endif
+
+#define CFG_SCL GPIO_NUM_33
+#define CFG_SDA GPIO_NUM_32
+#define CFG_INTR GPIO_NUM_35
+#define EPDIY_I2C_PORT I2C_NUM_0
+#define CFG_PIN_OE (PCA_PIN_PC10 >> 8)
+#define CFG_PIN_MODE (PCA_PIN_PC11 >> 8)
+#define CFG_PIN_STV (PCA_PIN_PC12 >> 8)
+#define CFG_PIN_PWRUP (PCA_PIN_PC13 >> 8)
+#define CFG_PIN_VCOM_CTRL (PCA_PIN_PC14 >> 8)
+#define CFG_PIN_WAKEUP (PCA_PIN_PC15 >> 8)
+#define CFG_PIN_PWRGOOD (PCA_PIN_PC16 >> 8)
+#define CFG_PIN_INT (PCA_PIN_PC17 >> 8)
+#define D7 GPIO_NUM_23
+#define D6 GPIO_NUM_22
+#define D5 GPIO_NUM_21
+#define D4 GPIO_NUM_19
+#define D3 GPIO_NUM_18
+#define D2 GPIO_NUM_5
+#define D1 GPIO_NUM_4
+#define D0 GPIO_NUM_25
+
+/* Control Lines */
+#define CKV GPIO_NUM_26
+#define STH GPIO_NUM_27
+
+#define V4_LATCH_ENABLE GPIO_NUM_2
+
+/* Edges */
+#define CKH GPIO_NUM_15
+
+typedef struct {
+ i2c_port_t port;
+ bool pwrup;
+ bool vcom_ctrl;
+ bool wakeup;
+ bool others[8];
+} epd_config_register_t;
+
+static i2s_bus_config i2s_config = {
+ .clock = CKH,
+ .start_pulse = STH,
+ .data_0 = D0,
+ .data_1 = D1,
+ .data_2 = D2,
+ .data_3 = D3,
+ .data_4 = D4,
+ .data_5 = D5,
+ .data_6 = D6,
+ .data_7 = D7,
+};
+
+/** The VCOM voltage to use. */
+static int vcom = 1600;
+
+static bool interrupt_done = false;
+
+static void IRAM_ATTR interrupt_handler(void* arg) {
+ interrupt_done = true;
+}
+
+static epd_config_register_t config_reg;
+
+static void epd_board_init(uint32_t epd_row_width) {
+ gpio_hold_dis(CKH); // free CKH after wakeup
+
+ i2c_config_t conf;
+ conf.mode = I2C_MODE_MASTER;
+ conf.sda_io_num = CFG_SDA;
+ conf.scl_io_num = CFG_SCL;
+ conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.master.clk_speed = 400000;
+ conf.clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL;
+ ESP_ERROR_CHECK(i2c_param_config(EPDIY_I2C_PORT, &conf));
+
+ ESP_ERROR_CHECK(i2c_driver_install(EPDIY_I2C_PORT, I2C_MODE_MASTER, 0, 0, 0));
+
+ config_reg.port = EPDIY_I2C_PORT;
+ config_reg.pwrup = false;
+ config_reg.vcom_ctrl = false;
+ config_reg.wakeup = false;
+ for (int i = 0; i < 8; i++) {
+ config_reg.others[i] = false;
+ }
+
+ gpio_set_direction(CFG_INTR, GPIO_MODE_INPUT);
+ gpio_set_intr_type(CFG_INTR, GPIO_INTR_NEGEDGE);
+
+ ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_EDGE));
+
+ ESP_ERROR_CHECK(gpio_isr_handler_add(CFG_INTR, interrupt_handler, (void*)CFG_INTR));
+
+ // set all epdiy lines to output except TPS interrupt + PWR good
+ ESP_ERROR_CHECK(pca9555_set_config(config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT, 1));
+
+ // use latch pin as GPIO
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[V4_LATCH_ENABLE], PIN_FUNC_GPIO);
+ ESP_ERROR_CHECK(gpio_set_direction(V4_LATCH_ENABLE, GPIO_MODE_OUTPUT));
+ gpio_set_level(V4_LATCH_ENABLE, 0);
+
+ // Setup I2S
+ // add an offset off dummy bytes to allow for enough timing headroom
+ i2s_bus_init(&i2s_config, epd_row_width + 32);
+
+ rmt_pulse_init(CKV);
+}
+
+static void epd_board_deinit() {
+ // gpio_reset_pin(CFG_INTR);
+ // rtc_gpio_isolate(CFG_INTR);
+
+ ESP_ERROR_CHECK(pca9555_set_config(
+ config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT | CFG_PIN_VCOM_CTRL | CFG_PIN_PWRUP, 1
+ ));
+
+ int tries = 0;
+ while (!((pca9555_read_input(config_reg.port, 1) & 0xC0) == 0x80)) {
+ if (tries >= 500) {
+ ESP_LOGE("epdiy", "failed to shut down TPS65185!");
+ break;
+ }
+ tries++;
+ vTaskDelay(1);
+ printf("%X\n", pca9555_read_input(config_reg.port, 1));
+ }
+ // Not sure why we need this delay, but the TPS65185 seems to generate an interrupt after some
+ // time that needs to be cleared.
+ vTaskDelay(500);
+ pca9555_read_input(config_reg.port, 0);
+ pca9555_read_input(config_reg.port, 1);
+ i2c_driver_delete(EPDIY_I2C_PORT);
+ gpio_isr_handler_remove(CFG_INTR);
+ gpio_uninstall_isr_service();
+ gpio_reset_pin(CFG_INTR);
+ gpio_reset_pin(V4_LATCH_ENABLE);
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ uint8_t value = 0x00;
+ if (state->ep_sth) {
+ fast_gpio_set_hi(STH);
+ } else {
+ fast_gpio_set_lo(STH);
+ }
+
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv) {
+ if (state->ep_output_enable)
+ value |= CFG_PIN_OE;
+ if (state->ep_mode)
+ value |= CFG_PIN_MODE;
+ if (state->ep_stv)
+ value |= CFG_PIN_STV;
+ if (config_reg.pwrup)
+ value |= CFG_PIN_PWRUP;
+ if (config_reg.vcom_ctrl)
+ value |= CFG_PIN_VCOM_CTRL;
+ if (config_reg.wakeup)
+ value |= CFG_PIN_WAKEUP;
+
+ ESP_ERROR_CHECK(pca9555_set_value(config_reg.port, value, 1));
+ }
+
+ if (state->ep_latch_enable) {
+ fast_gpio_set_hi(V4_LATCH_ENABLE);
+ } else {
+ fast_gpio_set_lo(V4_LATCH_ENABLE);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ i2s_gpio_attach(&i2s_config);
+
+ epd_ctrl_state_t mask = {
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.vcom_ctrl = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+
+ int tries = 0;
+ while (!(pca9555_read_input(config_reg.port, 1) & CFG_PIN_PWRGOOD)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! INT status: 0x%X 0x%X",
+ tps_read_register(config_reg.port, TPS_REG_INT1),
+ tps_read_register(config_reg.port, TPS_REG_INT2)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+
+ ESP_ERROR_CHECK(tps_write_register(config_reg.port, TPS_REG_ENABLE, 0x3F));
+
+ tps_set_vcom(config_reg.port, vcom);
+
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_measure_vcom(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ state->ep_mode = false;
+ state->ep_output_enable = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ while (!(pca9555_read_input(config_reg.port, 1) & CFG_PIN_PWRGOOD)) {
+ }
+ ESP_LOGI("epdiy", "Power rails enabled");
+
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ int tries = 0;
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_stv = true,
+ .ep_output_enable = true,
+ .ep_mode = true,
+ };
+ config_reg.vcom_ctrl = false;
+ config_reg.pwrup = false;
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ state->ep_mode = false;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(1);
+ config_reg.wakeup = false;
+ epd_board_set_ctrl(state, &mask);
+
+ i2s_gpio_detach(&i2s_config);
+}
+
+static float epd_board_ambient_temperature() {
+ return tps_read_thermistor(EPDIY_I2C_PORT);
+}
+
+static esp_err_t gpio_set_direction_v6(int pin, bool make_input) {
+ static uint8_t direction = 0;
+ uint8_t mask = ~(1 << pin);
+ direction = (direction & mask) | (make_input << pin);
+
+ return pca9555_set_config(EPDIY_I2C_PORT, direction, 0);
+}
+
+/**
+ * Get the input level of the broken-out GPIO extender port.
+ */
+static bool gpio_get_level_v6(int pin) {
+ return (pca9555_read_input(EPDIY_I2C_PORT, 0) >> pin) & 1;
+}
+
+/**
+ * Get the input level of the broken-out GPIO extender port.
+ */
+static esp_err_t gpio_set_value_v6(int pin, bool value) {
+ static uint8_t state = 0;
+ uint8_t mask = ~(1 << pin);
+ state = (state & mask) | (value << pin);
+
+ return pca9555_set_value(EPDIY_I2C_PORT, state, 0);
+}
+
+static void set_vcom(int value) {
+ vcom = value;
+}
+
+const EpdBoardDefinition epd_board_v6 = {
+ .init = epd_board_init,
+ .deinit = epd_board_deinit,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+ .measure_vcom = epd_board_measure_vcom,
+ .get_temperature = epd_board_ambient_temperature,
+ .set_vcom = set_vcom,
+
+ .gpio_set_direction = gpio_set_direction_v6,
+ .gpio_read = gpio_get_level_v6,
+ .gpio_write = gpio_set_value_v6,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v7.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v7.c
new file mode 100644
index 000000000..1dd4414a4
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v7.c
@@ -0,0 +1,338 @@
+#include
+#include "epd_board.h"
+#include "epdiy.h"
+
+#include "../output_common/render_method.h"
+#include "../output_lcd/lcd_driver.h"
+#include "esp_log.h"
+#include "pca9555.h"
+#include "tps65185.h"
+
+#include
+#include
+#include
+
+// Make this compile von the ESP32 without ifdefing the whole file
+#ifndef CONFIG_IDF_TARGET_ESP32S3
+#define GPIO_NUM_40 -1
+#define GPIO_NUM_41 -1
+#define GPIO_NUM_42 -1
+#define GPIO_NUM_43 -1
+#define GPIO_NUM_44 -1
+#define GPIO_NUM_45 -1
+#define GPIO_NUM_46 -1
+#define GPIO_NUM_47 -1
+#define GPIO_NUM_48 -1
+#endif
+
+#define CFG_SCL GPIO_NUM_40
+#define CFG_SDA GPIO_NUM_39
+#define CFG_INTR GPIO_NUM_38
+#define EPDIY_I2C_PORT I2C_NUM_0
+
+#define CFG_PIN_OE (PCA_PIN_PC10 >> 8)
+#define CFG_PIN_MODE (PCA_PIN_PC11 >> 8)
+#define __CFG_PIN_STV (PCA_PIN_PC12 >> 8)
+#define CFG_PIN_PWRUP (PCA_PIN_PC13 >> 8)
+#define CFG_PIN_VCOM_CTRL (PCA_PIN_PC14 >> 8)
+#define CFG_PIN_WAKEUP (PCA_PIN_PC15 >> 8)
+#define CFG_PIN_PWRGOOD (PCA_PIN_PC16 >> 8)
+#define CFG_PIN_INT (PCA_PIN_PC17 >> 8)
+
+#define D15 GPIO_NUM_47
+#define D14 GPIO_NUM_21
+#define D13 GPIO_NUM_14
+#define D12 GPIO_NUM_13
+#define D11 GPIO_NUM_12
+#define D10 GPIO_NUM_11
+#define D9 GPIO_NUM_10
+#define D8 GPIO_NUM_9
+
+#define D7 GPIO_NUM_8
+#define D6 GPIO_NUM_18
+#define D5 GPIO_NUM_17
+#define D4 GPIO_NUM_16
+#define D3 GPIO_NUM_15
+#define D2 GPIO_NUM_7
+#define D1 GPIO_NUM_6
+#define D0 GPIO_NUM_5
+
+/* Control Lines */
+#define CKV GPIO_NUM_48
+#define STH GPIO_NUM_41
+#define LEH GPIO_NUM_42
+#define STV GPIO_NUM_45
+
+/* Edges */
+#define CKH GPIO_NUM_4
+
+typedef struct {
+ i2c_port_t port;
+ bool pwrup;
+ bool vcom_ctrl;
+ bool wakeup;
+ bool others[8];
+} epd_config_register_t;
+
+/** The VCOM voltage to use. */
+static int vcom = 1600;
+
+static epd_config_register_t config_reg;
+
+static bool interrupt_done = false;
+
+static void IRAM_ATTR interrupt_handler(void* arg) {
+ interrupt_done = true;
+}
+
+static lcd_bus_config_t lcd_config = {
+ .clock = CKH,
+ .ckv = CKV,
+ .leh = LEH,
+ .start_pulse = STH,
+ .stv = STV,
+ .data[0] = D0,
+ .data[1] = D1,
+ .data[2] = D2,
+ .data[3] = D3,
+ .data[4] = D4,
+ .data[5] = D5,
+ .data[6] = D6,
+ .data[7] = D7,
+ .data[8] = D8,
+ .data[9] = D9,
+ .data[10] = D10,
+ .data[11] = D11,
+ .data[12] = D12,
+ .data[13] = D13,
+ .data[14] = D14,
+ .data[15] = D15,
+};
+
+static void epd_board_init(uint32_t epd_row_width) {
+ gpio_hold_dis(CKH); // free CKH after wakeup
+
+ i2c_config_t conf;
+ conf.mode = I2C_MODE_MASTER;
+ conf.sda_io_num = CFG_SDA;
+ conf.scl_io_num = CFG_SCL;
+ conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.master.clk_speed = 100000;
+ conf.clk_flags = 0;
+ ESP_ERROR_CHECK(i2c_param_config(EPDIY_I2C_PORT, &conf));
+
+ ESP_ERROR_CHECK(i2c_driver_install(EPDIY_I2C_PORT, I2C_MODE_MASTER, 0, 0, 0));
+
+ config_reg.port = EPDIY_I2C_PORT;
+ config_reg.pwrup = false;
+ config_reg.vcom_ctrl = false;
+ config_reg.wakeup = false;
+ for (int i = 0; i < 8; i++) {
+ config_reg.others[i] = false;
+ }
+
+ gpio_set_direction(CFG_INTR, GPIO_MODE_INPUT);
+ gpio_set_intr_type(CFG_INTR, GPIO_INTR_NEGEDGE);
+
+ ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_EDGE));
+
+ ESP_ERROR_CHECK(gpio_isr_handler_add(CFG_INTR, interrupt_handler, (void*)CFG_INTR));
+
+ // set all epdiy lines to output except TPS interrupt + PWR good
+ ESP_ERROR_CHECK(pca9555_set_config(config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT, 1));
+
+ const EpdDisplay_t* display = epd_get_display();
+
+ LcdEpdConfig_t config = {
+ .pixel_clock = display->bus_speed * 1000 * 1000,
+ .ckv_high_time = 60,
+ .line_front_porch = 4,
+ .le_high_time = 4,
+ .bus_width = display->bus_width,
+ .bus = lcd_config,
+ };
+ epd_lcd_init(&config, display->width, display->height);
+}
+
+static void epd_board_deinit() {
+ epd_lcd_deinit();
+
+ ESP_ERROR_CHECK(pca9555_set_config(
+ config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT | CFG_PIN_VCOM_CTRL | CFG_PIN_PWRUP, 1
+ ));
+
+ int tries = 0;
+ while (!((pca9555_read_input(config_reg.port, 1) & 0xC0) == 0x80)) {
+ if (tries >= 50) {
+ ESP_LOGE("epdiy", "failed to shut down TPS65185!");
+ break;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+
+ // Not sure why we need this delay, but the TPS65185 seems to generate an interrupt after some
+ // time that needs to be cleared.
+ vTaskDelay(50);
+ pca9555_read_input(config_reg.port, 0);
+ pca9555_read_input(config_reg.port, 1);
+ i2c_driver_delete(EPDIY_I2C_PORT);
+
+ gpio_uninstall_isr_service();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ uint8_t value = 0x00;
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv) {
+ if (state->ep_output_enable)
+ value |= CFG_PIN_OE;
+ if (state->ep_mode)
+ value |= CFG_PIN_MODE;
+ // if (state->ep_stv) value |= CFG_PIN_STV;
+ if (config_reg.pwrup)
+ value |= CFG_PIN_PWRUP;
+ if (config_reg.vcom_ctrl)
+ value |= CFG_PIN_VCOM_CTRL;
+ if (config_reg.wakeup)
+ value |= CFG_PIN_WAKEUP;
+
+ ESP_ERROR_CHECK(pca9555_set_value(config_reg.port, value, 1));
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ state->ep_mode = false;
+ state->ep_output_enable = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.vcom_ctrl = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+
+ while (!(pca9555_read_input(config_reg.port, 1) & CFG_PIN_PWRGOOD)) {
+ }
+
+ ESP_ERROR_CHECK(tps_write_register(config_reg.port, TPS_REG_ENABLE, 0x3F));
+
+ tps_set_vcom(config_reg.port, vcom);
+
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ int tries = 0;
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_measure_vcom(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ state->ep_mode = false;
+ state->ep_output_enable = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ while (!(pca9555_read_input(config_reg.port, 1) & CFG_PIN_PWRGOOD)) {
+ }
+ ESP_LOGI("epdiy", "Power rails enabled");
+
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ int tries = 0;
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_stv = true,
+ .ep_output_enable = true,
+ .ep_mode = true,
+ };
+ config_reg.vcom_ctrl = false;
+ config_reg.pwrup = false;
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ state->ep_mode = false;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(1);
+ config_reg.wakeup = false;
+ epd_board_set_ctrl(state, &mask);
+}
+
+static float epd_board_ambient_temperature() {
+ return 20;
+}
+
+static void set_vcom(int value) {
+ vcom = value;
+}
+
+const EpdBoardDefinition epd_board_v7 = {
+ .init = epd_board_init,
+ .deinit = epd_board_deinit,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+
+ .measure_vcom = epd_board_measure_vcom,
+ .get_temperature = epd_board_ambient_temperature,
+ .set_vcom = set_vcom,
+
+ // unimplemented for now, but shares v6 implementation
+ .gpio_set_direction = NULL,
+ .gpio_read = NULL,
+ .gpio_write = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/epd_board_v7_raw.c b/lib/libesp32_eink/epdiy/src/board/epd_board_v7_raw.c
new file mode 100644
index 000000000..8c9865cf9
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/epd_board_v7_raw.c
@@ -0,0 +1,288 @@
+/**
+ * @file epd_board_v7_raw.c
+ * @author Martin Fasani www.fasani.de
+ * @brief Small v7 board without IO expander targeted only to 8-bit einks
+ * @date 2025-02-10
+ */
+#include
+#include "epd_board.h"
+#include "epdiy.h"
+
+#include "../output_common/render_method.h"
+#include "../output_lcd/lcd_driver.h"
+#include "esp_log.h"
+#include "tps65185.h"
+
+#include
+#include
+#include
+
+// Make this compile on the ESP32 without ifdefing the whole file
+#ifndef CONFIG_IDF_TARGET_ESP32S3
+#define GPIO_NUM_40 -1
+#define GPIO_NUM_41 -1
+#define GPIO_NUM_42 -1
+#define GPIO_NUM_43 -1
+#define GPIO_NUM_44 -1
+#define GPIO_NUM_45 -1
+#define GPIO_NUM_46 -1
+#define GPIO_NUM_47 -1
+#define GPIO_NUM_48 -1
+#endif
+
+#define CFG_SCL GPIO_NUM_40
+#define CFG_SDA GPIO_NUM_39
+#define EPDIY_I2C_PORT I2C_NUM_0
+
+#define CFG_PIN_OE GPIO_NUM_9
+#define CFG_PIN_MODE GPIO_NUM_10
+#define __CFG_PIN_STV GPIO_NUM_45
+#define CFG_PIN_PWRUP GPIO_NUM_11
+#define CFG_PIN_VCOM_CTRL GPIO_NUM_12
+#define CFG_PIN_WAKEUP GPIO_NUM_14
+#define CFG_PIN_PWRGOOD GPIO_NUM_47
+#define CFG_PIN_INT GPIO_NUM_13 // TPS65185 INT
+
+#define D7 GPIO_NUM_8
+#define D6 GPIO_NUM_18
+#define D5 GPIO_NUM_17
+#define D4 GPIO_NUM_16
+#define D3 GPIO_NUM_15
+#define D2 GPIO_NUM_7
+#define D1 GPIO_NUM_6
+#define D0 GPIO_NUM_5
+
+/* Control Lines */
+#define CKV GPIO_NUM_48
+#define STH GPIO_NUM_41
+#define LEH GPIO_NUM_42
+#define STV GPIO_NUM_45
+
+/* Edges */
+#define CKH GPIO_NUM_4
+
+typedef struct {
+ i2c_port_t port;
+ bool pwrup;
+ bool vcom_ctrl;
+ bool wakeup;
+ bool others[8];
+} epd_config_register_t;
+
+/** The VCOM voltage to use. */
+static int vcom = 1900;
+
+static epd_config_register_t config_reg;
+
+static bool interrupt_done = false;
+
+static void IRAM_ATTR interrupt_handler(void* arg) {
+ interrupt_done = true;
+}
+
+static lcd_bus_config_t lcd_config = { .clock = CKH,
+ .ckv = CKV,
+ .leh = LEH,
+ .start_pulse = STH,
+ .stv = STV,
+ .data[0] = D0,
+ .data[1] = D1,
+ .data[2] = D2,
+ .data[3] = D3,
+ .data[4] = D4,
+ .data[5] = D5,
+ .data[6] = D6,
+ .data[7] = D7 };
+
+static void epd_board_init(uint32_t epd_row_width) {
+ gpio_hold_dis(CKH); // free CKH after wakeup
+
+ i2c_config_t conf;
+ conf.mode = I2C_MODE_MASTER;
+ conf.sda_io_num = CFG_SDA;
+ conf.scl_io_num = CFG_SCL;
+ conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.master.clk_speed = 100000;
+ conf.clk_flags = 0;
+ ESP_ERROR_CHECK(i2c_param_config(EPDIY_I2C_PORT, &conf));
+
+ ESP_ERROR_CHECK(i2c_driver_install(EPDIY_I2C_PORT, I2C_MODE_MASTER, 0, 0, 0));
+
+ config_reg.port = EPDIY_I2C_PORT;
+ config_reg.pwrup = false;
+ config_reg.vcom_ctrl = false;
+ config_reg.wakeup = false;
+ for (int i = 0; i < 8; i++) {
+ config_reg.others[i] = false;
+ }
+
+ gpio_set_direction(CFG_PIN_INT, GPIO_MODE_INPUT);
+ gpio_set_intr_type(CFG_PIN_INT, GPIO_INTR_NEGEDGE);
+
+ ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_EDGE));
+
+ ESP_ERROR_CHECK(gpio_isr_handler_add(CFG_PIN_INT, interrupt_handler, (void*)CFG_PIN_INT));
+
+ // set all epdiy lines to output except TPS interrupt + PWR good
+ gpio_set_direction(CFG_PIN_PWRGOOD, GPIO_MODE_INPUT);
+ gpio_set_pull_mode(CFG_PIN_PWRGOOD, GPIO_PULLUP_ONLY);
+
+ gpio_set_direction(CFG_PIN_WAKEUP, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_PIN_PWRUP, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_PIN_VCOM_CTRL, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_PIN_OE, GPIO_MODE_OUTPUT);
+ gpio_set_direction(CFG_PIN_MODE, GPIO_MODE_OUTPUT);
+
+ const EpdDisplay_t* display = epd_get_display();
+ if (display->bus_width > 8) {
+ ESP_LOGE("v7_RAW", "displays > 8 bit width are not supported in this board");
+ }
+
+ LcdEpdConfig_t config = {
+ .pixel_clock = display->bus_speed * 1000 * 1000,
+ .ckv_high_time = 60,
+ .line_front_porch = 4,
+ .le_high_time = 4,
+ .bus_width = display->bus_width,
+ .bus = lcd_config,
+ };
+
+ epd_lcd_init(&config, display->width, display->height);
+}
+
+static void epd_board_deinit() {
+ epd_lcd_deinit();
+ gpio_set_level(CFG_PIN_PWRUP, false);
+
+ // Not sure why we need this delay, but the TPS65185 seems to generate an interrupt after some
+ // time that needs to be cleared.
+ vTaskDelay(50);
+ i2c_driver_delete(EPDIY_I2C_PORT);
+
+ gpio_uninstall_isr_service();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ if (state->ep_output_enable) {
+ gpio_set_level(CFG_PIN_OE, 1);
+ } else {
+ gpio_set_level(CFG_PIN_OE, 0);
+ }
+
+ if (state->ep_mode) {
+ gpio_set_level(CFG_PIN_MODE, 1);
+ } else {
+ gpio_set_level(CFG_PIN_MODE, 0);
+ }
+
+ if (config_reg.pwrup && !gpio_get_level(CFG_PIN_PWRUP)) {
+ gpio_set_level(CFG_PIN_PWRUP, 1);
+ } else {
+ gpio_set_level(CFG_PIN_PWRUP, 0);
+ }
+
+ if (config_reg.vcom_ctrl && !gpio_get_level(CFG_PIN_VCOM_CTRL)) {
+ gpio_set_level(CFG_PIN_VCOM_CTRL, 1);
+ } else {
+ gpio_set_level(CFG_PIN_VCOM_CTRL, 0);
+ }
+
+ if (config_reg.wakeup && !gpio_get_level(CFG_PIN_WAKEUP)) {
+ gpio_set_level(CFG_PIN_WAKEUP, 1);
+ } else {
+ gpio_set_level(CFG_PIN_WAKEUP, 0);
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ state->ep_mode = true;
+ state->ep_output_enable = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(pdMS_TO_TICKS(10));
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(pdMS_TO_TICKS(10));
+ config_reg.vcom_ctrl = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+
+ // Check if PWRs lines are up
+ int timeout_counter = 0;
+ const int timeout_limit = 20; // 20 * 100ms = 2 seconds
+ while (gpio_get_level(CFG_PIN_PWRGOOD) == 0) {
+ if (timeout_counter >= timeout_limit) {
+ ESP_LOGE("v7_RAW", "Timeout waiting for PWRGOOD signal");
+ break;
+ }
+ timeout_counter++;
+ vTaskDelay(pdMS_TO_TICKS(100));
+ }
+ ESP_LOGI("v7_RAW", "PWRGOOD OK");
+
+ tps_set_vcom(config_reg.port, vcom);
+
+ int tries = 0;
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_stv = true,
+ .ep_output_enable = true,
+ .ep_mode = true,
+ };
+ config_reg.vcom_ctrl = false;
+ config_reg.pwrup = false;
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ state->ep_mode = false;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(1);
+ config_reg.wakeup = false;
+ epd_board_set_ctrl(state, &mask);
+}
+
+static float epd_board_ambient_temperature() {
+ return tps_read_thermistor(EPDIY_I2C_PORT);
+}
+
+static void set_vcom(int value) {
+ vcom = value;
+}
+
+const EpdBoardDefinition epd_board_v7_raw = {
+ .init = epd_board_init,
+ .deinit = epd_board_deinit,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+
+ .get_temperature = epd_board_ambient_temperature,
+ .set_vcom = set_vcom,
+
+ // unimplemented for now, but shares v6 implementation
+ .gpio_set_direction = NULL,
+ .gpio_read = NULL,
+ .gpio_write = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/lilygo_board_s3.c b/lib/libesp32_eink/epdiy/src/board/lilygo_board_s3.c
new file mode 100644
index 000000000..500259380
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/lilygo_board_s3.c
@@ -0,0 +1,273 @@
+#include
+#include "epd_board.h"
+#include "epdiy.h"
+
+#include "../output_common/render_method.h"
+#include "../output_lcd/lcd_driver.h"
+#include "esp_log.h"
+#include "pca9555.h"
+#include "tps65185.h"
+
+#include
+#include
+#include
+
+// Make this compile von the ESP32 without ifdefing the whole file
+#ifndef CONFIG_IDF_TARGET_ESP32S3
+#define GPIO_NUM_40 -1
+#define GPIO_NUM_41 -1
+#define GPIO_NUM_42 -1
+#define GPIO_NUM_43 -1
+#define GPIO_NUM_44 -1
+#define GPIO_NUM_45 -1
+#define GPIO_NUM_46 -1
+#define GPIO_NUM_47 -1
+#define GPIO_NUM_48 -1
+#endif
+
+#define CFG_SCL GPIO_NUM_40
+#define CFG_SDA GPIO_NUM_39
+#define CFG_INTR GPIO_NUM_38
+#define EPDIY_I2C_PORT I2C_NUM_0
+
+#define CFG_PIN_OE (PCA_PIN_PC10 >> 8)
+#define CFG_PIN_MODE (PCA_PIN_PC11 >> 8)
+#define __CFG_PIN_STV (PCA_PIN_PC12 >> 8)
+#define CFG_PIN_PWRUP (PCA_PIN_PC13 >> 8)
+#define CFG_PIN_VCOM_CTRL (PCA_PIN_PC14 >> 8)
+#define CFG_PIN_WAKEUP (PCA_PIN_PC15 >> 8)
+#define CFG_PIN_PWRGOOD (PCA_PIN_PC16 >> 8)
+#define CFG_PIN_INT (PCA_PIN_PC17 >> 8)
+
+#define D7 GPIO_NUM_8
+#define D6 GPIO_NUM_18
+#define D5 GPIO_NUM_17
+#define D4 GPIO_NUM_16
+#define D3 GPIO_NUM_15
+#define D2 GPIO_NUM_7
+#define D1 GPIO_NUM_6
+#define D0 GPIO_NUM_5
+
+/* Control Lines */
+#define CKV GPIO_NUM_48
+#define STH GPIO_NUM_41
+#define LEH GPIO_NUM_42
+#define STV GPIO_NUM_45
+
+/* Edges */
+#define CKH GPIO_NUM_4
+
+typedef struct {
+ i2c_port_t port;
+ bool pwrup;
+ bool vcom_ctrl;
+ bool wakeup;
+ bool others[8];
+} epd_config_register_t;
+
+/** The VCOM voltage to use. */
+static int vcom = 1600;
+
+static epd_config_register_t config_reg;
+
+static bool interrupt_done = false;
+
+static void IRAM_ATTR interrupt_handler(void* arg) {
+ interrupt_done = true;
+}
+
+static lcd_bus_config_t lcd_config = {
+ .clock = CKH,
+ .ckv = CKV,
+ .leh = LEH,
+ .start_pulse = STH,
+ .stv = STV,
+ .data[0] = D0,
+ .data[1] = D1,
+ .data[2] = D2,
+ .data[3] = D3,
+ .data[4] = D4,
+ .data[5] = D5,
+ .data[6] = D6,
+ .data[7] = D7,
+};
+
+static void epd_board_init(uint32_t epd_row_width) {
+ gpio_hold_dis(CKH); // free CKH after wakeup
+
+ i2c_config_t conf;
+ conf.mode = I2C_MODE_MASTER;
+ conf.sda_io_num = CFG_SDA;
+ conf.scl_io_num = CFG_SCL;
+ conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
+ conf.master.clk_speed = 100000;
+ conf.clk_flags = 0;
+ ESP_ERROR_CHECK(i2c_param_config(EPDIY_I2C_PORT, &conf));
+
+ ESP_ERROR_CHECK(i2c_driver_install(EPDIY_I2C_PORT, I2C_MODE_MASTER, 0, 0, 0));
+
+ config_reg.port = EPDIY_I2C_PORT;
+ config_reg.pwrup = false;
+ config_reg.vcom_ctrl = false;
+ config_reg.wakeup = false;
+ for (int i = 0; i < 8; i++) {
+ config_reg.others[i] = false;
+ }
+
+ gpio_set_direction(CFG_INTR, GPIO_MODE_INPUT);
+ gpio_set_intr_type(CFG_INTR, GPIO_INTR_NEGEDGE);
+
+ ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG_EDGE));
+
+ ESP_ERROR_CHECK(gpio_isr_handler_add(CFG_INTR, interrupt_handler, (void*)CFG_INTR));
+
+ // set all epdiy lines to output except TPS interrupt + PWR good
+ ESP_ERROR_CHECK(pca9555_set_config(config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT, 1));
+
+ const EpdDisplay_t* display = epd_get_display();
+
+ LcdEpdConfig_t config = {
+ .pixel_clock = display->bus_speed * 1000 * 1000,
+ .ckv_high_time = 60,
+ .line_front_porch = 4,
+ .le_high_time = 4,
+ .bus_width = display->bus_width,
+ .bus = lcd_config,
+ };
+ epd_lcd_init(&config, display->width, display->height);
+}
+
+static void epd_board_deinit() {
+ epd_lcd_deinit();
+
+ ESP_ERROR_CHECK(pca9555_set_config(
+ config_reg.port, CFG_PIN_PWRGOOD | CFG_PIN_INT | CFG_PIN_VCOM_CTRL | CFG_PIN_PWRUP, 1
+ ));
+
+ int tries = 0;
+ while (!((pca9555_read_input(config_reg.port, 1) & 0xC0) == 0x80)) {
+ if (tries >= 50) {
+ ESP_LOGE("epdiy", "failed to shut down TPS65185!");
+ break;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+
+ // Not sure why we need this delay, but the TPS65185 seems to generate an interrupt after some
+ // time that needs to be cleared.
+ vTaskDelay(50);
+ pca9555_read_input(config_reg.port, 0);
+ pca9555_read_input(config_reg.port, 1);
+ i2c_driver_delete(EPDIY_I2C_PORT);
+
+ gpio_uninstall_isr_service();
+}
+
+static void epd_board_set_ctrl(epd_ctrl_state_t* state, const epd_ctrl_state_t* const mask) {
+ uint8_t value = 0x00;
+ if (mask->ep_output_enable || mask->ep_mode || mask->ep_stv) {
+ if (state->ep_output_enable)
+ value |= CFG_PIN_OE;
+ if (state->ep_mode)
+ value |= CFG_PIN_MODE;
+ // if (state->ep_stv) value |= CFG_PIN_STV;
+ if (config_reg.pwrup)
+ value |= CFG_PIN_PWRUP;
+ if (config_reg.vcom_ctrl)
+ value |= CFG_PIN_VCOM_CTRL;
+ if (config_reg.wakeup)
+ value |= CFG_PIN_WAKEUP;
+
+ ESP_ERROR_CHECK(pca9555_set_value(config_reg.port, value, 1));
+ }
+}
+
+static void epd_board_poweron(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_output_enable = true,
+ .ep_mode = true,
+ .ep_stv = true,
+ };
+ state->ep_stv = true;
+ state->ep_mode = false;
+ state->ep_output_enable = true;
+ config_reg.wakeup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.pwrup = true;
+ epd_board_set_ctrl(state, &mask);
+ config_reg.vcom_ctrl = true;
+ epd_board_set_ctrl(state, &mask);
+
+ // give the IC time to powerup and set lines
+ vTaskDelay(1);
+
+ while (!(pca9555_read_input(config_reg.port, 1) & CFG_PIN_PWRGOOD)) {
+ }
+
+ ESP_ERROR_CHECK(tps_write_register(config_reg.port, TPS_REG_ENABLE, 0x3F));
+
+ tps_set_vcom(config_reg.port, vcom);
+
+ state->ep_sth = true;
+ mask = (const epd_ctrl_state_t){
+ .ep_sth = true,
+ };
+ epd_board_set_ctrl(state, &mask);
+
+ int tries = 0;
+ while (!((tps_read_register(config_reg.port, TPS_REG_PG) & 0xFA) == 0xFA)) {
+ if (tries >= 500) {
+ ESP_LOGE(
+ "epdiy",
+ "Power enable failed! PG status: %X",
+ tps_read_register(config_reg.port, TPS_REG_PG)
+ );
+ return;
+ }
+ tries++;
+ vTaskDelay(1);
+ }
+}
+
+static void epd_board_poweroff(epd_ctrl_state_t* state) {
+ epd_ctrl_state_t mask = {
+ .ep_stv = true,
+ .ep_output_enable = true,
+ .ep_mode = true,
+ };
+ config_reg.vcom_ctrl = false;
+ config_reg.pwrup = false;
+ state->ep_stv = false;
+ state->ep_output_enable = false;
+ state->ep_mode = false;
+ epd_board_set_ctrl(state, &mask);
+ vTaskDelay(1);
+ config_reg.wakeup = false;
+ epd_board_set_ctrl(state, &mask);
+}
+
+static float epd_board_ambient_temperature() {
+ return 20;
+}
+
+static void set_vcom(int value) {
+ vcom = value;
+}
+
+const EpdBoardDefinition lilygo_board_s3 = {
+ .init = epd_board_init,
+ .deinit = epd_board_deinit,
+ .set_ctrl = epd_board_set_ctrl,
+ .poweron = epd_board_poweron,
+ .poweroff = epd_board_poweroff,
+
+ .get_temperature = epd_board_ambient_temperature,
+ .set_vcom = set_vcom,
+
+ // unimplemented for now, but shares v6 implementation
+ .gpio_set_direction = NULL,
+ .gpio_read = NULL,
+ .gpio_write = NULL,
+};
diff --git a/lib/libesp32_eink/epdiy/src/board/pca9555.c b/lib/libesp32_eink/epdiy/src/board/pca9555.c
new file mode 100644
index 000000000..5faabba17
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/pca9555.c
@@ -0,0 +1,107 @@
+
+
+#include "pca9555.h"
+#include
+#include
+#include
+#include
+
+#define REG_INPUT_PORT0 0
+#define REG_INPUT_PORT1 1
+
+#define REG_OUTPUT_PORT0 2
+#define REG_OUTPUT_PORT1 3
+
+#define REG_INVERT_PORT0 4
+#define REG_INVERT_PORT1 5
+
+#define REG_CONFIG_PORT0 6
+#define REG_CONFIG_PORT1 7
+
+static esp_err_t i2c_master_read_slave(i2c_port_t i2c_num, uint8_t* data_rd, size_t size, int reg) {
+ if (size == 0) {
+ return ESP_OK;
+ }
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ if (cmd == NULL) {
+ ESP_LOGE("epdiy", "insufficient memory for I2C transaction");
+ }
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_PCA9555_ADDR << 1) | I2C_MASTER_WRITE, true);
+ i2c_master_write_byte(cmd, reg, true);
+ i2c_master_stop(cmd);
+
+ esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
+ if (ret != ESP_OK) {
+ return ret;
+ }
+ i2c_cmd_link_delete(cmd);
+
+ cmd = i2c_cmd_link_create();
+ if (cmd == NULL) {
+ ESP_LOGE("epdiy", "insufficient memory for I2C transaction");
+ }
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_PCA9555_ADDR << 1) | I2C_MASTER_READ, true);
+ if (size > 1) {
+ i2c_master_read(cmd, data_rd, size - 1, I2C_MASTER_ACK);
+ }
+ i2c_master_read_byte(cmd, data_rd + size - 1, I2C_MASTER_NACK);
+ i2c_master_stop(cmd);
+
+ ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
+ if (ret != ESP_OK) {
+ return ret;
+ }
+ i2c_cmd_link_delete(cmd);
+
+ return ESP_OK;
+}
+
+static esp_err_t i2c_master_write_slave(
+ i2c_port_t i2c_num, uint8_t ctrl, uint8_t* data_wr, size_t size
+) {
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ if (cmd == NULL) {
+ ESP_LOGE("epdiy", "insufficient memory for I2C transaction");
+ }
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_PCA9555_ADDR << 1) | I2C_MASTER_WRITE, true);
+ i2c_master_write_byte(cmd, ctrl, true);
+
+ i2c_master_write(cmd, data_wr, size, true);
+ i2c_master_stop(cmd);
+ esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
+ i2c_cmd_link_delete(cmd);
+ return ret;
+}
+
+static esp_err_t pca9555_write_single(i2c_port_t port, int reg, uint8_t value) {
+ uint8_t w_data[1] = { value };
+ return i2c_master_write_slave(port, reg, w_data, sizeof(w_data));
+}
+
+esp_err_t pca9555_set_config(i2c_port_t port, uint8_t config_value, int high_port) {
+ return pca9555_write_single(port, REG_CONFIG_PORT0 + high_port, config_value);
+}
+
+esp_err_t pca9555_set_inversion(i2c_port_t port, uint8_t config_value, int high_port) {
+ return pca9555_write_single(port, REG_INVERT_PORT0 + high_port, config_value);
+}
+
+esp_err_t pca9555_set_value(i2c_port_t port, uint8_t config_value, int high_port) {
+ return pca9555_write_single(port, REG_OUTPUT_PORT0 + high_port, config_value);
+}
+
+uint8_t pca9555_read_input(i2c_port_t i2c_port, int high_port) {
+ esp_err_t err;
+ uint8_t r_data[1];
+
+ err = i2c_master_read_slave(i2c_port, r_data, 1, REG_INPUT_PORT0 + high_port);
+ if (err != ESP_OK) {
+ ESP_LOGE("PCA9555", "%s failed", __func__);
+ return 0;
+ }
+
+ return r_data[0];
+}
diff --git a/lib/libesp32_eink/epdiy/src/board/pca9555.h b/lib/libesp32_eink/epdiy/src/board/pca9555.h
new file mode 100644
index 000000000..8f31b031f
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/pca9555.h
@@ -0,0 +1,35 @@
+#ifndef PCA9555_H
+#define PCA9555_H
+
+#include
+#include
+
+#define PCA_PIN_P00 0x0001
+#define PCA_PIN_P01 0x0002
+#define PCA_PIN_P02 0x0004
+#define PCA_PIN_P03 0x0008
+#define PCA_PIN_P04 0x0010
+#define PCA_PIN_P05 0x0020
+#define PCA_PIN_P06 0x0040
+#define PCA_PIN_P07 0x0080
+#define PCA_PIN_PC10 0x0100
+#define PCA_PIN_PC11 0x0200
+#define PCA_PIN_PC12 0x0400
+#define PCA_PIN_PC13 0x0800
+#define PCA_PIN_PC14 0x1000
+#define PCA_PIN_PC15 0x2000
+#define PCA_PIN_PC16 0x4000
+#define PCA_PIN_PC17 0x8000
+#define PCA_PIN_P_ALL 0x00FF
+#define PCA_PIN_PC_ALL 0xFF00
+#define PCA_PIN_ALL 0xFFFF
+#define PCA_PIN_NULL 0x0000
+
+static const int EPDIY_PCA9555_ADDR = 0x20;
+
+uint8_t pca9555_read_input(i2c_port_t port, int high_port);
+esp_err_t pca9555_set_value(i2c_port_t port, uint8_t config_value, int high_port);
+esp_err_t pca9555_set_inversion(i2c_port_t port, uint8_t config_value, int high_port);
+esp_err_t pca9555_set_config(i2c_port_t port, uint8_t config_value, int high_port);
+
+#endif // PCA9555_H
diff --git a/lib/libesp32_eink/epdiy/src/board/tps65185.c b/lib/libesp32_eink/epdiy/src/board/tps65185.c
new file mode 100644
index 000000000..ef5cb3dac
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/tps65185.c
@@ -0,0 +1,128 @@
+
+#include "tps65185.h"
+#include "pca9555.h"
+#include "epd_board.h"
+#include "esp_err.h"
+#include "esp_log.h"
+
+#include
+#include
+
+static const int EPDIY_TPS_ADDR = 0x68;
+
+static uint8_t i2c_master_read_slave(i2c_port_t i2c_num, int reg) {
+ uint8_t r_data[1];
+
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_TPS_ADDR << 1) | I2C_MASTER_WRITE, true);
+ i2c_master_write_byte(cmd, reg, true);
+ i2c_master_stop(cmd);
+
+ ESP_ERROR_CHECK(i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS));
+ i2c_cmd_link_delete(cmd);
+
+ cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_TPS_ADDR << 1) | I2C_MASTER_READ, true);
+ /*
+ if (size > 1) {
+ i2c_master_read(cmd, data_rd, size - 1, I2C_MASTER_ACK);
+ }
+ */
+ i2c_master_read_byte(cmd, r_data, I2C_MASTER_NACK);
+ i2c_master_stop(cmd);
+
+ ESP_ERROR_CHECK(i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS));
+ i2c_cmd_link_delete(cmd);
+
+ return r_data[0];
+}
+
+static esp_err_t i2c_master_write_slave(
+ i2c_port_t i2c_num, uint8_t ctrl, uint8_t* data_wr, size_t size
+) {
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, (EPDIY_TPS_ADDR << 1) | I2C_MASTER_WRITE, true);
+ i2c_master_write_byte(cmd, ctrl, true);
+
+ i2c_master_write(cmd, data_wr, size, true);
+ i2c_master_stop(cmd);
+ esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 1000 / portTICK_PERIOD_MS);
+ i2c_cmd_link_delete(cmd);
+ return ret;
+}
+
+esp_err_t tps_write_register(i2c_port_t port, int reg, uint8_t value) {
+ uint8_t w_data[1];
+ esp_err_t err;
+
+ w_data[0] = value;
+
+ err = i2c_master_write_slave(port, reg, w_data, 1);
+ return err;
+}
+
+uint8_t tps_read_register(i2c_port_t i2c_num, int reg) {
+ return i2c_master_read_slave(i2c_num, reg);
+}
+
+void tps_set_vcom(i2c_port_t i2c_num, unsigned vcom_mV) {
+ unsigned val = vcom_mV / 10;
+ ESP_ERROR_CHECK(tps_write_register(i2c_num, 4, (val & 0x100) >> 8));
+ ESP_ERROR_CHECK(tps_write_register(i2c_num, 3, val & 0xFF));
+}
+
+int8_t tps_read_thermistor(i2c_port_t i2c_num) {
+ tps_write_register(i2c_num, TPS_REG_TMST1, 0x80);
+ int tries = 0;
+ while (true) {
+ uint8_t val = tps_read_register(i2c_num, TPS_REG_TMST1);
+ // temperature conversion done
+ if (val & 0x20) {
+ break;
+ }
+ tries++;
+
+ if (tries >= 100) {
+ ESP_LOGE("epdiy", "thermistor read timeout!");
+ break;
+ }
+ }
+ return (int8_t)tps_read_register(i2c_num, TPS_REG_TMST_VALUE);
+}
+
+void tps_vcom_kickback() {
+ printf("VCOM Kickback test\n");
+ // pull the WAKEUP pin and the PWRUP pin high to enable all output rails.
+ epd_current_board()->measure_vcom(epd_ctrl_state());
+ // set the HiZ bit in the VCOM2 register (BIT 5) 0x20
+ // this puts the VCOM pin in a high-impedance state.
+ // bit 3 & 4 Number of acquisitions that is averaged to a single kick-back V. measurement
+ tps_write_register(I2C_NUM_0, 4, 0x38);
+ vTaskDelay(1);
+
+ uint8_t int1reg = tps_read_register(I2C_NUM_0, TPS_REG_INT1);
+ uint8_t vcomreg = tps_read_register(I2C_NUM_0, TPS_REG_VCOM2);
+}
+
+void tps_vcom_kickback_start() {
+ uint8_t int1reg = tps_read_register(I2C_NUM_0, TPS_REG_INT1);
+ // set the ACQ bit in the VCOM2 register to 1 (BIT 7)
+ tps_write_register(I2C_NUM_0, TPS_REG_VCOM2, 0xA0);
+}
+
+unsigned tps_vcom_kickback_rdy() {
+ uint8_t int1reg = tps_read_register(I2C_NUM_0, TPS_REG_INT1);
+
+ if (int1reg == 0x02) {
+ uint8_t lsb = tps_read_register(I2C_NUM_0, 3);
+ uint8_t msb = tps_read_register(I2C_NUM_0, 4);
+ int u16Value = (lsb | (msb << 8)) & 0x1ff;
+ ESP_LOGI("vcom", "raw value:%d temperature:%d C", u16Value, tps_read_thermistor(I2C_NUM_0));
+ return u16Value * 10;
+ } else {
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/board/tps65185.h b/lib/libesp32_eink/epdiy/src/board/tps65185.h
new file mode 100644
index 000000000..96ba1d35f
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board/tps65185.h
@@ -0,0 +1,56 @@
+#ifndef TPS65185_H
+#define TPS65185_H
+
+#include
+
+#define TPS_REG_TMST_VALUE 0x00
+#define TPS_REG_ENABLE 0x01
+#define TPS_REG_VADJ 0x02
+#define TPS_REG_VCOM1 0x03
+#define TPS_REG_VCOM2 0x04
+#define TPS_REG_INT_EN1 0x05
+#define TPS_REG_INT_EN2 0x06
+#define TPS_REG_INT1 0x07
+#define TPS_REG_INT2 0x08
+#define TPS_REG_UPSEQ0 0x09
+#define TPS_REG_UPSEQ1 0x0A
+#define TPS_REG_DWNSEQ0 0x0B
+#define TPS_REG_DWNSEQ1 0x0C
+#define TPS_REG_TMST1 0x0D
+#define TPS_REG_TMST2 0x0E
+#define TPS_REG_PG 0x0F
+#define TPS_REG_REVID 0x10
+
+esp_err_t tps_write_register(i2c_port_t port, int reg, uint8_t value);
+uint8_t tps_read_register(i2c_port_t i2c_num, int reg);
+
+/**
+ * Sets the VCOM voltage in positive milivolts: 1600 -> -1.6V
+ */
+void tps_set_vcom(i2c_port_t i2c_num, unsigned vcom_mV);
+
+/**
+ * @brief Please read datasheet section 8.3.7.1 Kick-Back Voltage Measurement
+ * 1 Device enters ACTIVE mode
+ * 2 All power rails are up except VCOM
+ * VCOM pin is in HiZ state
+ */
+void tps_vcom_kickback();
+
+/**
+ * @brief start VCOM kick-back voltage measurements
+ */
+void tps_vcom_kickback_start();
+
+/**
+ * VCOM kick-back ACQC (Acquisition Complete) bit in the INT1 register is set
+ * @return unsigned: 0 is not read
+ */
+unsigned tps_vcom_kickback_rdy();
+
+/**
+ * Read the temperature via the on-board thermistor.
+ */
+int8_t tps_read_thermistor(i2c_port_t i2c_num);
+
+#endif // TPS65185_H
diff --git a/lib/libesp32_eink/epdiy/src/board_specific.c b/lib/libesp32_eink/epdiy/src/board_specific.c
new file mode 100644
index 000000000..6bea72098
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/board_specific.c
@@ -0,0 +1,5 @@
+#include "epd_board_specific.h"
+
+void epd_powerdown() {
+ epd_powerdown_lilygo_t5_47();
+}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/builtin_waveforms.c b/lib/libesp32_eink/epdiy/src/builtin_waveforms.c
old mode 100755
new mode 100644
similarity index 56%
rename from lib/libesp32_eink/epdiy/src/epd_driver/builtin_waveforms.c
rename to lib/libesp32_eink/epdiy/src/builtin_waveforms.c
index 5d85cd8f1..ba4ff8c19
--- a/lib/libesp32_eink/epdiy/src/epd_driver/builtin_waveforms.c
+++ b/lib/libesp32_eink/epdiy/src/builtin_waveforms.c
@@ -1,10 +1,15 @@
-#include "epd_driver.h"
+#include "epdiy.h"
-#include "waveforms/ED047TC2.h"
#include "waveforms/epdiy_ED047TC1.h"
+
+// Note: Alternative Waveform added by Lilygo on Oct 2021, size: 266 Kb (ED047TC1 is 37 Kb, 7 times
+// smaller)
+#include "waveforms/epdiy_ED047TC2.h"
+
#include "waveforms/epdiy_ED060SC4.h"
-#include "waveforms/epdiy_ED060XC3.h"
#include "waveforms/epdiy_ED060SCT.h"
+#include "waveforms/epdiy_ED060XC3.h"
#include "waveforms/epdiy_ED097OC4.h"
#include "waveforms/epdiy_ED097TC2.h"
#include "waveforms/epdiy_ED133UT2.h"
+#include "waveforms/epdiy_NULL.h"
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/diff.S b/lib/libesp32_eink/epdiy/src/diff.S
new file mode 100644
index 000000000..1210049db
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/diff.S
@@ -0,0 +1,159 @@
+#include
+#include
+#include "sdkconfig.h"
+
+#ifdef CONFIG_IDF_TARGET_ESP32S3
+
+.text
+.align 4
+.global epd_interlace_4bpp_line_VE
+.type epd_interlace_4bpp_line_VE,@function
+
+// // CRASH AND BURN for debugging
+// EE.MOVI.32.A q3, a2, 0
+// EE.MOVI.32.A q3, a3, 1
+// EE.MOVI.32.A q3, a4, 2
+// EE.MOVI.32.A q3, a5, 3
+// l8ui a10, a10, 0
+
+// bool interlace_line(
+// const uint8_t *to,
+// const uint8_t *from,
+// uint8_t *col_dirtyness;
+// uint8_t *interlaced,
+// int fb_width
+// )
+epd_interlace_4bpp_line_VE:
+// to - a2
+// from - a3
+// interlaced - a4
+// col_dirtyness - a5
+// fb_width - a6
+
+ entry a1, 32
+
+ // divide by 32 for loop count
+ srli a11, a6, 5
+
+ movi.n a10, 0xF0F0F0F0;
+ EE.MOVI.32.Q q6,a10,0
+ EE.MOVI.32.Q q6,a10,1
+ EE.MOVI.32.Q q6,a10,2
+ EE.MOVI.32.Q q6,a10,3
+
+ movi.n a10, 0x0F0F0F0F
+ EE.MOVI.32.Q q7,a10,0
+ EE.MOVI.32.Q q7,a10,1
+ EE.MOVI.32.Q q7,a10,2
+ EE.MOVI.32.Q q7,a10,3
+
+ // put 4 into shift amount
+ movi.n a10, 4
+ WSR.SAR a10
+
+ // "dirtyness" register
+ EE.ZERO.Q q5
+
+ // Instructions sometimes are in an unexpected order
+ // for best pipeline utilization
+ loopnez a11, .loop_end_difference
+
+ EE.VLD.128.IP q0, a2, 16
+ EE.VLD.128.IP q1, a3, 16
+
+ // load column dirtyness
+ EE.VLD.128.IP q3, a5, 0
+
+ // update dirtyness
+ EE.XORQ q4, q1, q0
+
+ // line dirtyness accumulator
+ EE.ORQ q5, q5, q4
+ // column dirtyness
+ EE.ORQ q3, q3, q4
+
+ // store column dirtyness
+ EE.VST.128.IP q3, a5, 16
+
+ // mask out every second value
+ EE.ANDQ q2, q0, q7
+ EE.ANDQ q0, q0, q6
+ EE.ANDQ q3, q1, q7
+ EE.ANDQ q1, q1, q6
+
+ // shift vectors to align
+ EE.VSL.32 q2, q2
+ EE.VSR.32 q1, q1
+
+ // the right shift sign-extends,
+ // so we make sure the resulting shift is logical by masking again
+ EE.ANDQ q1, q1, q7
+
+ // Combine "from" and "to" nibble
+ EE.ORQ q2, q2, q3
+ EE.ORQ q0, q0, q1
+
+ // Zip masked out values together
+ EE.VZIP.8 q2, q0
+
+ // store interlaced buffer data
+ EE.VST.128.IP q2, a4, 16
+ EE.VST.128.IP q0, a4, 16
+
+.loop_end_difference:
+
+ EE.MOVI.32.A q5, a2, 0
+ EE.MOVI.32.A q5, a3, 1
+ EE.MOVI.32.A q5, a4, 2
+ EE.MOVI.32.A q5, a5, 3
+ or a2, a2, a3
+ or a2, a2, a4
+ or a2, a2, a5
+
+ //movi.n a2, 1 // return "true"
+
+ // CRASH AND BURN for debugging
+ //EE.MOVI.32.A q5, a2, 0
+ //EE.MOVI.32.A q5, a3, 1
+ //EE.MOVI.32.A q5, a4, 2
+ //EE.MOVI.32.A q5, a5, 3
+ //movi.n a10, 0
+ //l8ui a10, a10, 0
+
+ retw.n
+
+
+.global epd_apply_line_mask_VE
+.type epd_apply_line_mask_VE,@function
+
+// void epd_apply_line_mask_VE(
+// uint8_t *line,
+// const uint8_t *mask,
+// int mask_len
+// )
+epd_apply_line_mask_VE:
+// line - a2
+// mask - a3
+// mask_len - a4
+
+ entry a1, 32
+
+ // divide by 16 for loop count
+ srli a4, a4, 4
+
+ // Instructions sometimes are in an unexpected order
+ // for best pipeline utilization
+ loopnez a4, .loop_end_mask
+
+ EE.VLD.128.IP q0, a2, 0
+ EE.VLD.128.IP q1, a3, 16
+
+ EE.ANDQ q0, q0, q1
+
+ EE.VST.128.IP q0, a2, 16
+
+.loop_end_mask:
+
+ retw.n
+
+#endif
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/displays.c b/lib/libesp32_eink/epdiy/src/displays.c
new file mode 100644
index 000000000..394761b41
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/displays.c
@@ -0,0 +1,83 @@
+#include "epd_display.h"
+
+const EpdDisplay_t ED060SCT = {
+ .width = 800,
+ .height = 600,
+ .bus_width = 8,
+ .bus_speed = 20,
+ .default_waveform = &epdiy_ED060SCT,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+const EpdDisplay_t ED060XC3 = {
+ .width = 1024,
+ .height = 768,
+ .bus_width = 8,
+ .bus_speed = 20,
+ .default_waveform = &epdiy_ED060XC3,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+const EpdDisplay_t ED097OC4 = {
+ .width = 1200,
+ .height = 825,
+ .bus_width = 8,
+ .bus_speed = 15,
+ .default_waveform = &epdiy_ED097OC4,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+const EpdDisplay_t ED097TC2 = {
+ .width = 1200,
+ .height = 825,
+ .bus_width = 8,
+ .bus_speed = 22,
+ .default_waveform = &epdiy_ED097TC2,
+ .display_type = DISPLAY_TYPE_ED097TC2,
+};
+
+const EpdDisplay_t ED133UT2 = {
+ .width = 1600,
+ .height = 1200,
+ .bus_width = 8,
+ .bus_speed = 20,
+ .default_waveform = &epdiy_ED097TC2,
+ .display_type = DISPLAY_TYPE_ED097TC2,
+};
+
+const EpdDisplay_t ED047TC1 = {
+ .width = 960,
+ .height = 540,
+ .bus_width = 8,
+ .bus_speed = 20,
+ .default_waveform = &epdiy_ED047TC1,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+const EpdDisplay_t ED047TC2 = {
+ .width = 960,
+ .height = 540,
+ .bus_width = 8,
+ .bus_speed = 20,
+ .default_waveform = &epdiy_ED047TC2,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+const EpdDisplay_t ED078KC1 = {
+ .width = 1872,
+ .height = 1404,
+ .bus_width = 16,
+ .bus_speed = 11,
+ .default_waveform = &epdiy_ED047TC2,
+ .display_type = DISPLAY_TYPE_GENERIC,
+};
+
+// Attention is by default horizontal rows mirrored
+const EpdDisplay_t ED052TC4 = {
+ .width = 1280,
+ .height = 720,
+ .bus_width = 8,
+ .bus_speed = 22,
+ .default_waveform = &epdiy_ED097TC2,
+ .display_type = DISPLAY_TYPE_ED097TC2,
+};
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/epd4in7.cpp b/lib/libesp32_eink/epdiy/src/epd4in7.cpp
index 252abfde5..5f85bc438 100644
--- a/lib/libesp32_eink/epdiy/src/epd4in7.cpp
+++ b/lib/libesp32_eink/epdiy/src/epd4in7.cpp
@@ -37,7 +37,7 @@
#include
#include
#include
-#include "epd_driver.h"
+//#include "epd_driver.h"
#include "epd_highlevel.h"
#define WAVEFORM EPD_BUILTIN_WAVEFORM
@@ -58,8 +58,8 @@ Epd47::Epd47(int16_t dwidth, int16_t dheight) : Renderer(dwidth, dheight) {
disp_bpp = 4;
}
-int32_t Epd47::Init(void) {
- epd_init(EPD_LUT_1K);
+int Epd47::Init(void) {
+ epd_init(&epd_board_lilygo_t5_47, &ED097TC2, EPD_LUT_1K);
hl = epd_hl_init(WAVEFORM);
epd47_buffer = epd_hl_get_framebuffer(&hl);
framebuffer = epd47_buffer;
diff --git a/lib/libesp32_eink/epdiy/src/epd4in7.cppZone.Identifier b/lib/libesp32_eink/epdiy/src/epd4in7.cppZone.Identifier
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/libesp32_eink/epdiy/src/epd4in7.hZone.Identifier b/lib/libesp32_eink/epdiy/src/epd4in7.hZone.Identifier
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/libesp32_eink/epdiy/src/epd_board.h b/lib/libesp32_eink/epdiy/src/epd_board.h
new file mode 100644
index 000000000..c5b1d29fd
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epd_board.h
@@ -0,0 +1,133 @@
+/**
+ * @file "epd_board.h"
+ * @brief Board-definitions provided by epdiy.
+ */
+
+#pragma once
+
+#include
+#include
+
+#include
+#include
+
+/**
+ * State of display control pins.
+ */
+typedef struct {
+ bool ep_latch_enable : 1;
+ bool ep_output_enable : 1;
+ bool ep_sth : 1;
+ bool ep_mode : 1;
+ bool ep_stv : 1;
+} epd_ctrl_state_t;
+
+/**
+ * Operations available on an epdiy board.
+ */
+typedef struct {
+ /**
+ * Initialize the board.
+ */
+ void (*init)(uint32_t epd_row_width);
+ /**
+ * Clean up resources and peripherals used by the board.
+ */
+ void (*deinit)(void);
+ /**
+ * Set display line state
+ */
+ void (*set_ctrl)(epd_ctrl_state_t*, const epd_ctrl_state_t* const);
+ /**
+ * Enable power to the display.
+ */
+ void (*poweron)(epd_ctrl_state_t*);
+
+ /**
+ * Measure VCOM kick-back. Only in v6 & v7 boards!
+ */
+ void (*measure_vcom)(epd_ctrl_state_t* state);
+
+ /**
+ * Disable power to the display.
+ */
+ void (*poweroff)(epd_ctrl_state_t*);
+
+ /**
+ * Set the display common voltage if supported.
+ *
+ * Voltage is set as absolute value in millivolts.
+ * Although VCOM is negative, this function takes a positive (absolute) value.
+ */
+ void (*set_vcom)(int);
+
+ /**
+ * Get the current temperature if supported by the board.
+ */
+ float (*get_temperature)(void);
+
+ /**
+ * Set GPIO direction of the broken-out GPIO extender port,
+ * if available.
+ * Setting `make_input` to `1` corresponds to input, `0` corresponds to output.
+ */
+ esp_err_t (*gpio_set_direction)(int pin, bool make_input);
+
+ /**
+ * Get the input level of a GPIO extender pin, if available.
+ */
+ bool (*gpio_read)(int pin);
+
+ /**
+ * Set the output level of a GPIO extender, if available.
+ */
+ esp_err_t (*gpio_write)(int pin, bool value);
+} EpdBoardDefinition;
+
+/**
+ * Get the current board.
+ */
+const EpdBoardDefinition* epd_current_board();
+
+/**
+ * Set the board hardware definition. This must be called before epd_init()
+ *
+ * The implementation of this method is in board/epd_board.c.
+ **/
+void epd_set_board(const EpdBoardDefinition* board);
+
+/**
+ * Get the board's current control register state.
+ */
+epd_ctrl_state_t* epd_ctrl_state();
+
+/**
+ * Set the display mode pin.
+ */
+void epd_set_mode(bool state);
+
+/**
+ * Initialize the control register
+ */
+void epd_control_reg_init();
+
+/**
+ * Put the control register into the state of lowest power consumption.
+ */
+void epd_control_reg_deinit();
+
+// Built in board definitions
+extern const EpdBoardDefinition epd_board_lilygo_t5_47;
+extern const EpdBoardDefinition epd_board_lilygo_t5_47_touch;
+extern const EpdBoardDefinition lilygo_board_s3;
+extern const EpdBoardDefinition epd_board_v2_v3;
+extern const EpdBoardDefinition epd_board_v4;
+extern const EpdBoardDefinition epd_board_v5;
+extern const EpdBoardDefinition epd_board_v6;
+extern const EpdBoardDefinition epd_board_v7;
+extern const EpdBoardDefinition epd_board_v7_raw;
+
+/**
+ * Helper for short, precise delays.
+ */
+void epd_busy_delay(uint32_t cycles);
diff --git a/lib/libesp32_eink/epdiy/src/epd_board_specific.h b/lib/libesp32_eink/epdiy/src/epd_board_specific.h
new file mode 100644
index 000000000..abb0138f8
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epd_board_specific.h
@@ -0,0 +1,32 @@
+/**
+ * @file "epd_board_specific.h"
+ * @brief Board-specific functions that are only conditionally defined.
+ */
+
+#pragma once
+
+#include
+
+/** This is a Lilygo47 specific function
+
+ This is a work around a hardware issue with the Lilygo47 epd_poweroff() turns off the epaper
+ completely however the hardware of the Lilygo47 is different than the official boards. Which means
+ that on the Lilygo47 this disables power to the touchscreen.
+
+ This is a workaround to allow to disable display power but not the touch screen.
+ On the Lilygo the epd power flag was re-purposed as power enable
+ for everything. This is a hardware thing.
+ \warning This workaround may still leave power on to epd and as such may cause other problems such
+ as grey screen.
+
+ Please use epd_poweroff() and epd_deinit() whenever you sleep the system.
+ The following code can be used to sleep the lilygo and power down the peripherals and wake the
+ unit on touch. However is should be noted that the touch controller is not powered and as such the
+ touch coordinates will not be captured. Arduino specific code: \code{.c} epd_poweroff();
+ epd_deinit();
+ esp_sleep_enable_ext1_wakeup(GPIO_SEL_13, ESP_EXT1_WAKEUP_ANY_HIGH);
+ esp_deep_sleep_start();
+ \endcode
+*/
+void epd_powerdown_lilygo_t5_47();
+void epd_powerdown() __attribute__((deprecated));
diff --git a/lib/libesp32_eink/epdiy/src/epd_display.h b/lib/libesp32_eink/epdiy/src/epd_display.h
new file mode 100644
index 000000000..c22e58735
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epd_display.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include
+#include "epd_internals.h"
+
+/**
+ * Display type as "compatibility classes",
+ * Grouping displays by workarounds needed.
+ */
+enum EpdDisplayType {
+ /// A generic EPD, assume default config.
+ DISPLAY_TYPE_GENERIC,
+ /// Fast display where we can get away with low hold times.
+ DISPLAY_TYPE_ED097TC2,
+};
+
+typedef struct {
+ /// Width of the display in pixels.
+ int width;
+ /// Height of the display in pixels.
+ int height;
+
+ /// Width of the data bus in bits.
+ uint8_t bus_width;
+ /// Speed of the data bus in MHz, if configurable.
+ /// (Only used by the LCD based renderer in V7+)
+ int bus_speed;
+
+ /// Default waveform to use.
+ const EpdWaveform* default_waveform;
+ /// Display type
+ enum EpdDisplayType display_type;
+} EpdDisplay_t;
+
+extern const EpdDisplay_t ED060SCT;
+extern const EpdDisplay_t ED060XC3;
+extern const EpdDisplay_t ED097OC4;
+extern const EpdDisplay_t ED097TC2;
+extern const EpdDisplay_t ED133UT2;
+extern const EpdDisplay_t ED047TC1;
+extern const EpdDisplay_t ED047TC2;
+extern const EpdDisplay_t ED078KC1;
+extern const EpdDisplay_t ED052TC4;
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver.h b/lib/libesp32_eink/epdiy/src/epd_driver.h
deleted file mode 100755
index 2635d0712..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#pragma once
-// This file is only used in the Arduino IDE
-// and just includes the IDF component header.
-#include "epd_driver/include/epd_driver.h"
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/CMakeLists.txt b/lib/libesp32_eink/epdiy/src/epd_driver/CMakeLists.txt
deleted file mode 100755
index 9df188ad8..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-set(app_sources "epd_driver.c"
- "render.c"
- "display_ops.c"
- "font.c"
- "lut.c"
- "builtin_waveforms.c"
- "i2s_data_bus.c"
- "rmt_pulse.c"
- "highlevel.c"
- "epd_temperature.c")
-
-
-idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "include" REQUIRES esp_adc_cal)
-
-set_source_files_properties("lut.c" PROPERTIES COMPILE_OPTIONS -mno-fix-esp32-psram-cache-issue)
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/Kconfig b/lib/libesp32_eink/epdiy/src/epd_driver/Kconfig
deleted file mode 100755
index e6c32f3e6..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/Kconfig
+++ /dev/null
@@ -1,52 +0,0 @@
-menu "E-Paper Driver"
- choice EPD_DRIVER_DISPLAY_TYPE
- prompt "Display Type"
- default EPD_DISPLAY_TYPE_ED097OC4
- help
- This option sets the display type to drive.
-
- config EPD_DISPLAY_TYPE_ED097OC4
- bool "ED097OC4"
-
- config EPD_DISPLAY_TYPE_ED060SC4
- bool "ED060SC4"
-
- config EPD_DISPLAY_TYPE_ED060XC3
- bool "ED060XC3"
-
- config EPD_DISPLAY_TYPE_ED060SCT
- bool "ED060SCT"
-
- config EPD_DISPLAY_TYPE_ED097TC2
- bool "ED097TC2"
-
- config EPD_DISPLAY_TYPE_ED133UT2
- bool "ED133UT2"
-
- config EPD_DISPLAY_TYPE_ED047TC1
- bool "ED047TC1 (LILYGO 4.7 inch)"
-
- config EPD_DISPLAY_TYPE_ED097OC4_LQ
- bool "ED097OC4 Low Quality"
- endchoice
-
-
- choice EPD_DRIVER_BOARD_REVISION
- prompt "Board / Board Revision"
- default EPD_BOARD_REVISION_V2_V3
- help
- The board revision to compile for.
-
- config EPD_BOARD_REVISION_LILYGO_T5_47
- bool "LILYGO T5-4.7 inch e-paper"
-
- config EPD_BOARD_REVISION_V2_V3
- bool "epdiy v2 / v3"
-
- config EPD_BOARD_REVISION_V4
- bool "epdiy v4"
-
- config EPD_BOARD_REVISION_V5
- bool "epdiy v5"
- endchoice
-endmenu
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/LICENSE b/lib/libesp32_eink/epdiy/src/epd_driver/LICENSE
deleted file mode 100755
index f288702d2..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/LICENSE
+++ /dev/null
@@ -1,674 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
-
- The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-the GNU General Public License is intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains free
-software for all its users. We, the Free Software Foundation, use the
-GNU General Public License for most of our software; it applies also to
-any other work released this way by its authors. You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-Also add information on how to contact you by electronic and paper mail.
-
- If the program does terminal interaction, make it output a short
-notice like this when it starts in an interactive mode:
-
- Copyright (C)
- This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, your program's commands
-might be different; for a GUI interface, you would use an "about box".
-
- You should also get your employer (if you work as a programmer) or school,
-if any, to sign a "copyright disclaimer" for the program, if necessary.
-For more information on this, and how to apply and follow the GNU GPL, see
-.
-
- The GNU General Public License does not permit incorporating your program
-into proprietary programs. If your program is a subroutine library, you
-may consider it more useful to permit linking proprietary applications with
-the library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License. But first, please read
-.
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v2.h b/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v2.h
deleted file mode 100755
index 6f300e21e..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v2.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#include "display_ops.h"
-#include
-
-typedef struct {
- bool ep_latch_enable : 1;
- bool power_disable : 1;
- bool pos_power_enable : 1;
- bool neg_power_enable : 1;
- bool ep_stv : 1;
- bool ep_scan_direction : 1;
- bool ep_mode : 1;
- bool ep_output_enable : 1;
-} epd_config_register_t;
-
-static void config_reg_init(epd_config_register_t *cfg) {
- cfg->ep_latch_enable = false;
- cfg->power_disable = true;
- cfg->pos_power_enable = false;
- cfg->neg_power_enable = false;
- cfg->ep_stv = true;
- cfg->ep_scan_direction = true;
- cfg->ep_mode = false;
- cfg->ep_output_enable = false;
-}
-
-inline static void IRAM_ATTR push_cfg_bit(bool bit);
-void IRAM_ATTR busy_delay(uint32_t cycles);
-inline static void fast_gpio_set_hi(gpio_num_t gpio_num);
-inline static void fast_gpio_set_lo(gpio_num_t gpio_num);
-
-static void IRAM_ATTR push_cfg(const epd_config_register_t *cfg) {
- fast_gpio_set_lo(CFG_STR);
-
- // push config bits in reverse order
- push_cfg_bit(cfg->ep_output_enable);
- push_cfg_bit(cfg->ep_mode);
- push_cfg_bit(cfg->ep_scan_direction);
- push_cfg_bit(cfg->ep_stv);
-
- push_cfg_bit(cfg->neg_power_enable);
- push_cfg_bit(cfg->pos_power_enable);
- push_cfg_bit(cfg->power_disable);
- push_cfg_bit(cfg->ep_latch_enable);
-
- fast_gpio_set_hi(CFG_STR);
-}
-
-static void cfg_poweron(epd_config_register_t *cfg) {
-#if defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
- // This was re-purposed as power enable.
- cfg->ep_scan_direction = true;
-#endif
- // POWERON
- cfg->power_disable = false;
- push_cfg(cfg);
- busy_delay(100 * 240);
- cfg->neg_power_enable = true;
- push_cfg(cfg);
- busy_delay(500 * 240);
- cfg->pos_power_enable = true;
- push_cfg(cfg);
- busy_delay(100 * 240);
- cfg->ep_stv = true;
- push_cfg(cfg);
- fast_gpio_set_hi(STH);
- // END POWERON
-}
-
-static void cfg_poweroff(epd_config_register_t *cfg) {
-#if defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
- // This was re-purposed as power enable.
- cfg->ep_scan_direction = false;
-#endif
- // POWEROFF
- cfg->pos_power_enable = false;
- push_cfg(cfg);
- busy_delay(10 * 240);
- cfg->neg_power_enable = false;
- push_cfg(cfg);
- busy_delay(100 * 240);
- cfg->power_disable = true;
- push_cfg(cfg);
- // END POWEROFF
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v4.h b/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v4.h
deleted file mode 100755
index b4848e323..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/config_reg_v4.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#include "display_ops.h"
-
-typedef struct {
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- bool power_enable : 1;
-#else
- bool power_disable : 1;
-#endif
- bool power_enable_vpos : 1;
- bool power_enable_vneg : 1;
- bool power_enable_gl : 1;
- bool ep_stv : 1;
- bool power_enable_gh : 1;
- bool ep_mode : 1;
- bool ep_output_enable : 1;
-} epd_config_register_t;
-
-static void config_reg_init(epd_config_register_t *cfg) {
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- cfg->power_enable = false;
-#else
- cfg->power_disable = true;
-#endif
- cfg->power_enable_vpos = false;
- cfg->power_enable_vneg = false;
- cfg->power_enable_gl = false;
- cfg->ep_stv = true;
- cfg->power_enable_gh = false;
- cfg->ep_mode = false;
- cfg->ep_output_enable = false;
-}
-
-inline static void IRAM_ATTR push_cfg_bit(bool bit);
-void IRAM_ATTR busy_delay(uint32_t cycles);
-inline static void fast_gpio_set_hi(gpio_num_t gpio_num);
-inline static void fast_gpio_set_lo(gpio_num_t gpio_num);
-
-static void IRAM_ATTR push_cfg(const epd_config_register_t *cfg) {
- fast_gpio_set_lo(CFG_STR);
-
- // push config bits in reverse order
- push_cfg_bit(cfg->ep_output_enable);
- push_cfg_bit(cfg->ep_mode);
- push_cfg_bit(cfg->power_enable_gh);
- push_cfg_bit(cfg->ep_stv);
-
- push_cfg_bit(cfg->power_enable_gl);
- push_cfg_bit(cfg->power_enable_vneg);
- push_cfg_bit(cfg->power_enable_vpos);
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- push_cfg_bit(cfg->power_enable);
-#else
- push_cfg_bit(cfg->power_disable);
-#endif
-
- fast_gpio_set_hi(CFG_STR);
- fast_gpio_set_lo(CFG_STR);
-}
-
-static void cfg_poweron(epd_config_register_t *cfg) {
- // POWERON
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- cfg->power_enable = true;
-#else
- cfg->power_disable = false;
-#endif
- push_cfg(cfg);
- busy_delay(100 * 240);
- cfg->power_enable_gl = true;
- push_cfg(cfg);
- busy_delay(500 * 240);
- cfg->power_enable_vneg = true;
- push_cfg(cfg);
- busy_delay(500 * 240);
- cfg->power_enable_gh = true;
- push_cfg(cfg);
- busy_delay(500 * 240);
- cfg->power_enable_vpos = true;
- push_cfg(cfg);
- busy_delay(100 * 240);
- cfg->ep_stv = true;
- push_cfg(cfg);
- fast_gpio_set_hi(STH);
- // END POWERON
-}
-
-static void cfg_poweroff(epd_config_register_t *cfg) {
- // POWEROFF
- cfg->power_enable_gh = false;
- cfg->power_enable_vpos = false;
- push_cfg(cfg);
- busy_delay(10 * 240);
- cfg->power_enable_gl = false;
- cfg->power_enable_vneg = false;
- push_cfg(cfg);
- busy_delay(100 * 240);
-
- cfg->ep_stv = false;
- cfg->ep_output_enable = false;
- cfg->ep_mode = false;
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- cfg->power_enable = false;
-#else
- cfg->power_disable = true;
-#endif
- push_cfg(cfg);
- // END POWEROFF
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.c b/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.c
deleted file mode 100755
index abfef3a26..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.c
+++ /dev/null
@@ -1,195 +0,0 @@
-#include "display_ops.h"
-#include "esp_timer.h"
-#include "esp_log.h"
-#include "i2s_data_bus.h"
-#include "rmt_pulse.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-
-#include "xtensa/core-macros.h"
-
-#if defined(CONFIG_EPD_BOARD_REVISION_V2_V3) || defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
-#include "config_reg_v2.h"
-#else
-#if defined(CONFIG_EPD_BOARD_REVISION_V4) || defined(CONFIG_EPD_BOARD_REVISION_V5)
-#include "config_reg_v4.h"
-#else
-#error "unknown revision"
-#endif
-#endif
-
-static epd_config_register_t config_reg;
-
-/*
- * Write bits directly using the registers.
- * Won't work for some pins (>= 32).
- */
-inline static void fast_gpio_set_hi(gpio_num_t gpio_num) {
- GPIO.out_w1ts = (1 << gpio_num);
-}
-
-inline static void fast_gpio_set_lo(gpio_num_t gpio_num) {
- GPIO.out_w1tc = (1 << gpio_num);
-}
-
-void IRAM_ATTR busy_delay(uint32_t cycles) {
- volatile unsigned long counts = XTHAL_GET_CCOUNT() + cycles;
- while (XTHAL_GET_CCOUNT() < counts) {
- };
-}
-
-inline static void IRAM_ATTR push_cfg_bit(bool bit) {
- gpio_set_level(CFG_CLK, 0);
- if (bit) {
- gpio_set_level(CFG_DATA, 1);
- } else {
- gpio_set_level(CFG_DATA, 0);
- }
- gpio_set_level(CFG_CLK, 1);
-}
-
-void epd_base_init(uint32_t epd_row_width) {
-
- config_reg_init(&config_reg);
-
- /* Power Control Output/Off */
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_DATA], PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_CLK], PIN_FUNC_GPIO);
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[CFG_STR], PIN_FUNC_GPIO);
- gpio_set_direction(CFG_DATA, GPIO_MODE_OUTPUT);
- gpio_set_direction(CFG_CLK, GPIO_MODE_OUTPUT);
- gpio_set_direction(CFG_STR, GPIO_MODE_OUTPUT);
-
-#if defined(CONFIG_EPD_BOARD_REVISION_V4) || defined(CONFIG_EPD_BOARD_REVISION_V5)
- // use latch pin as GPIO
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[V4_LATCH_ENABLE], PIN_FUNC_GPIO);
- ESP_ERROR_CHECK(gpio_set_direction(V4_LATCH_ENABLE, GPIO_MODE_OUTPUT));
- gpio_set_level(V4_LATCH_ENABLE, 0);
-#endif
- fast_gpio_set_lo(CFG_STR);
-
- push_cfg(&config_reg);
-
- // Setup I2S
- i2s_bus_config i2s_config;
- // add an offset off dummy bytes to allow for enough timing headroom
- i2s_config.epd_row_width = epd_row_width + 32;
- i2s_config.clock = CKH;
- i2s_config.start_pulse = STH;
- i2s_config.data_0 = D0;
- i2s_config.data_1 = D1;
- i2s_config.data_2 = D2;
- i2s_config.data_3 = D3;
- i2s_config.data_4 = D4;
- i2s_config.data_5 = D5;
- i2s_config.data_6 = D6;
- i2s_config.data_7 = D7;
-
- i2s_bus_init(&i2s_config);
-
- rmt_pulse_init(CKV);
-}
-
-void epd_poweron() { cfg_poweron(&config_reg); }
-
-void epd_poweroff() { cfg_poweroff(&config_reg); }
-
-void epd_base_deinit(){
- epd_poweroff();
- i2s_deinit();
-}
-
-void epd_start_frame() {
- while (i2s_is_busy() || rmt_busy()) {
- };
- config_reg.ep_mode = true;
- push_cfg(&config_reg);
-
- pulse_ckv_us(1, 1, true);
-
- // This is very timing-sensitive!
- config_reg.ep_stv = false;
- push_cfg(&config_reg);
- //busy_delay(240);
- pulse_ckv_us(100, 100, false);
- config_reg.ep_stv = true;
- push_cfg(&config_reg);
- //pulse_ckv_us(0, 10, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
-
- config_reg.ep_output_enable = true;
- push_cfg(&config_reg);
-}
-
-static inline void latch_row() {
-#if defined(CONFIG_EPD_BOARD_REVISION_V2_V3) || defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
- config_reg.ep_latch_enable = true;
- push_cfg(&config_reg);
-
- config_reg.ep_latch_enable = false;
- push_cfg(&config_reg);
-#else
-#if defined(CONFIG_EPD_BOARD_REVISION_V4) || defined(CONFIG_EPD_BOARD_REVISION_V5)
- fast_gpio_set_hi(V4_LATCH_ENABLE);
- fast_gpio_set_lo(V4_LATCH_ENABLE);
-#else
-#error "unknown revision"
-#endif
-#endif
-}
-
-void IRAM_ATTR epd_skip() {
-#if defined(CONFIG_EPD_DISPLAY_TYPE_ED097TC2) || \
- defined(CONFIG_EPD_DISPLAY_TYPE_ED133UT2)
- pulse_ckv_ticks(5, 5, false);
-#else
- // According to the spec, the OC4 maximum CKV frequency is 200kHz.
- pulse_ckv_ticks(45, 5, false);
-#endif
-}
-
-void IRAM_ATTR epd_output_row(uint32_t output_time_dus) {
-
- while (i2s_is_busy() || rmt_busy()) {
- };
-
- fast_gpio_set_hi(STH);
-
- latch_row();
-
-#if defined(CONFIG_EPD_DISPLAY_TYPE_ED097TC2) || \
- defined(CONFIG_EPD_DISPLAY_TYPE_ED133UT2)
- pulse_ckv_ticks(output_time_dus, 1, false);
-#else
- pulse_ckv_ticks(output_time_dus, 50, false);
-#endif
-
- i2s_start_line_output();
- i2s_switch_buffer();
-}
-
-void epd_end_frame() {
- config_reg.ep_stv = false;
- push_cfg(&config_reg);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- config_reg.ep_mode = false;
- push_cfg(&config_reg);
- pulse_ckv_us(0, 10, true);
- config_reg.ep_output_enable = false;
- push_cfg(&config_reg);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
- pulse_ckv_us(1, 1, true);
-}
-
-void IRAM_ATTR epd_switch_buffer() { i2s_switch_buffer(); }
-uint8_t IRAM_ATTR *epd_get_current_buffer() {
- return (uint8_t *)i2s_get_current_buffer();
-};
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.h b/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.h
deleted file mode 100755
index f60affa02..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/display_ops.h
+++ /dev/null
@@ -1,111 +0,0 @@
-#pragma once
-
-#include "driver/gpio.h"
-
-#define CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-
-
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
-#define D7 GPIO_NUM_23
-#define D6 GPIO_NUM_22
-#define D5 GPIO_NUM_21
-#define D4 GPIO_NUM_19
-#define D3 GPIO_NUM_18
-#define D2 GPIO_NUM_5
-#define D1 GPIO_NUM_4
-#define D0 GPIO_NUM_25
-
-
-/* Config Reggister Control */
-#define CFG_DATA GPIO_NUM_33
-#define CFG_CLK GPIO_NUM_32
-#define CFG_STR GPIO_NUM_0
-
-/* Control Lines */
-#define CKV GPIO_NUM_26
-#define STH GPIO_NUM_27
-
-
-#define V4_LATCH_ENABLE GPIO_NUM_2
-
-/* Edges */
-#define CKH GPIO_NUM_15
-
-#else
-#define D7 GPIO_NUM_22
-#define D6 GPIO_NUM_21
-#define D5 GPIO_NUM_27
-#define D4 GPIO_NUM_2
-#if defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
-#define D3 GPIO_NUM_19
-#else
-#define D3 GPIO_NUM_0
-#endif
-#define D2 GPIO_NUM_4
-#define D1 GPIO_NUM_32
-#define D0 GPIO_NUM_33
-
-#define CFG_DATA GPIO_NUM_23
-#define CFG_CLK GPIO_NUM_18
-#if defined(CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47)
-#define CFG_STR GPIO_NUM_0
-#else
-#define CFG_STR GPIO_NUM_19
-#endif
-
-/* Control Lines */
-#define CKV GPIO_NUM_25
-#define STH GPIO_NUM_26
-
-#define V4_LATCH_ENABLE GPIO_NUM_15
-
-/* Edges */
-#define CKH GPIO_NUM_5
-
-#endif
-
-void epd_base_init(uint32_t epd_row_width);
-void epd_base_deinit();
-void epd_poweron();
-void epd_poweroff();
-
-/**
- * Start a draw cycle.
- */
-void epd_start_frame();
-
-/**
- * End a draw cycle.
- */
-void epd_end_frame();
-
-/**
- * Waits until all previously submitted data has been written.
- * Then, the following operations are initiated:
- *
- * - Previously submitted data is latched to the output register.
- * - The RMT peripheral is set up to pulse the vertical (gate) driver for
- * `output_time_dus` / 10 microseconds.
- * - The I2S peripheral starts transmission of the current buffer to
- * the source driver.
- * - The line buffers are switched.
- *
- * This sequence of operations allows for pipelining data preparation and
- * transfer, reducing total refresh times.
- */
-void IRAM_ATTR epd_output_row(uint32_t output_time_dus);
-
-/** Skip a row without writing to it. */
-void IRAM_ATTR epd_skip();
-
-/**
- * Get the currently writable line buffer.
- */
-uint8_t IRAM_ATTR *epd_get_current_buffer();
-
-/**
- * Switches front and back line buffer.
- * If the switched-to line buffer is currently in use,
- * this function blocks until transmission is done.
- */
-void IRAM_ATTR epd_switch_buffer();
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/epd_driver.c b/lib/libesp32_eink/epdiy/src/epd_driver/epd_driver.c
deleted file mode 100755
index 565b570d4..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/epd_driver.c
+++ /dev/null
@@ -1,344 +0,0 @@
-#include "epd_driver.h"
-#include "epd_temperature.h"
-
-#include "esp_assert.h"
-#include "esp_heap_caps.h"
-#include "esp_log.h"
-#include "esp_types.h"
-
-
-#ifndef _swap_int
-#define _swap_int(a, b) \
- { \
- int t = a; \
- a = b; \
- b = t; \
- }
-#endif
-
-
-EpdRect epd_full_screen() {
- EpdRect area = {.x = 0, .y = 0, .width = EPD_WIDTH, .height = EPD_HEIGHT};
- return area;
-}
-
-void epd_clear() { epd_clear_area(epd_full_screen()); }
-
-void epd_draw_hline(int x, int y, int length, uint8_t color,
- uint8_t *framebuffer) {
- for (int i = 0; i < length; i++) {
- int xx = x + i;
- epd_draw_pixel(xx, y, color, framebuffer);
- }
-}
-
-void epd_draw_vline(int x, int y, int length, uint8_t color,
- uint8_t *framebuffer) {
- for (int i = 0; i < length; i++) {
- int yy = y + i;
- epd_draw_pixel(x, yy, color, framebuffer);
- }
-}
-
-void epd_draw_pixel(int x, int y, uint8_t color, uint8_t *framebuffer) {
- if (x < 0 || x >= EPD_WIDTH) {
- return;
- }
- if (y < 0 || y >= EPD_HEIGHT) {
- return;
- }
- uint8_t *buf_ptr = &framebuffer[y * EPD_WIDTH / 2 + x / 2];
- if (x % 2) {
- *buf_ptr = (*buf_ptr & 0x0F) | (color & 0xF0);
- } else {
- *buf_ptr = (*buf_ptr & 0xF0) | (color >> 4);
- }
-}
-
-void epd_draw_circle(int x0, int y0, int r, uint8_t color,
- uint8_t *framebuffer) {
- int f = 1 - r;
- int ddF_x = 1;
- int ddF_y = -2 * r;
- int x = 0;
- int y = r;
-
- epd_draw_pixel(x0, y0 + r, color, framebuffer);
- epd_draw_pixel(x0, y0 - r, color, framebuffer);
- epd_draw_pixel(x0 + r, y0, color, framebuffer);
- epd_draw_pixel(x0 - r, y0, color, framebuffer);
-
- while (x < y) {
- if (f >= 0) {
- y--;
- ddF_y += 2;
- f += ddF_y;
- }
- x++;
- ddF_x += 2;
- f += ddF_x;
-
- epd_draw_pixel(x0 + x, y0 + y, color, framebuffer);
- epd_draw_pixel(x0 - x, y0 + y, color, framebuffer);
- epd_draw_pixel(x0 + x, y0 - y, color, framebuffer);
- epd_draw_pixel(x0 - x, y0 - y, color, framebuffer);
- epd_draw_pixel(x0 + y, y0 + x, color, framebuffer);
- epd_draw_pixel(x0 - y, y0 + x, color, framebuffer);
- epd_draw_pixel(x0 + y, y0 - x, color, framebuffer);
- epd_draw_pixel(x0 - y, y0 - x, color, framebuffer);
- }
-}
-
-void epd_fill_circle(int x0, int y0, int r, uint8_t color,
- uint8_t *framebuffer) {
- epd_draw_vline(x0, y0 - r, 2 * r + 1, color, framebuffer);
- epd_fill_circle_helper(x0, y0, r, 3, 0, color, framebuffer);
-}
-
-void epd_fill_circle_helper(int x0, int y0, int r, int corners, int delta,
- uint8_t color, uint8_t *framebuffer) {
-
- int f = 1 - r;
- int ddF_x = 1;
- int ddF_y = -2 * r;
- int x = 0;
- int y = r;
- int px = x;
- int py = y;
-
- delta++; // Avoid some +1's in the loop
-
- while (x < y) {
- if (f >= 0) {
- y--;
- ddF_y += 2;
- f += ddF_y;
- }
- x++;
- ddF_x += 2;
- f += ddF_x;
- // These checks avoid double-drawing certain lines, important
- // for the SSD1306 library which has an INVERT drawing mode.
- if (x < (y + 1)) {
- if (corners & 1)
- epd_draw_vline(x0 + x, y0 - y, 2 * y + delta, color, framebuffer);
- if (corners & 2)
- epd_draw_vline(x0 - x, y0 - y, 2 * y + delta, color, framebuffer);
- }
- if (y != py) {
- if (corners & 1)
- epd_draw_vline(x0 + py, y0 - px, 2 * px + delta, color, framebuffer);
- if (corners & 2)
- epd_draw_vline(x0 - py, y0 - px, 2 * px + delta, color, framebuffer);
- py = y;
- }
- px = x;
- }
-}
-
-void epd_draw_rect(EpdRect rect, uint8_t color,
- uint8_t *framebuffer) {
-
- int x = rect.x; int y = rect.y; int w = rect.width; int h = rect.height;
- epd_draw_hline(x, y, w, color, framebuffer);
- epd_draw_hline(x, y + h - 1, w, color, framebuffer);
- epd_draw_vline(x, y, h, color, framebuffer);
- epd_draw_vline(x + w - 1, y, h, color, framebuffer);
-}
-
-void epd_fill_rect(EpdRect rect, uint8_t color, uint8_t *framebuffer) {
-
- int x = rect.x; int y = rect.y; int w = rect.width; int h = rect.height;
- for (int i = y; i < y + h; i++) {
- epd_draw_hline(x, i, w, color, framebuffer);
- }
-}
-
-static void epd_write_line(int x0, int y0, int x1, int y1, uint8_t color,
- uint8_t *framebuffer) {
- int steep = abs(y1 - y0) > abs(x1 - x0);
- if (steep) {
- _swap_int(x0, y0);
- _swap_int(x1, y1);
- }
-
- if (x0 > x1) {
- _swap_int(x0, x1);
- _swap_int(y0, y1);
- }
-
- int dx, dy;
- dx = x1 - x0;
- dy = abs(y1 - y0);
-
- int err = dx / 2;
- int ystep;
-
- if (y0 < y1) {
- ystep = 1;
- } else {
- ystep = -1;
- }
-
- for (; x0 <= x1; x0++) {
- if (steep) {
- epd_draw_pixel(y0, x0, color, framebuffer);
- } else {
- epd_draw_pixel(x0, y0, color, framebuffer);
- }
- err -= dy;
- if (err < 0) {
- y0 += ystep;
- err += dx;
- }
- }
-}
-
-void epd_draw_line(int x0, int y0, int x1, int y1, uint8_t color,
- uint8_t *framebuffer) {
- // Update in subclasses if desired!
- if (x0 == x1) {
- if (y0 > y1)
- _swap_int(y0, y1);
- epd_draw_vline(x0, y0, y1 - y0 + 1, color, framebuffer);
- } else if (y0 == y1) {
- if (x0 > x1)
- _swap_int(x0, x1);
- epd_draw_hline(x0, y0, x1 - x0 + 1, color, framebuffer);
- } else {
- epd_write_line(x0, y0, x1, y1, color, framebuffer);
- }
-}
-
-void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
- uint8_t color, uint8_t *framebuffer) {
- epd_draw_line(x0, y0, x1, y1, color, framebuffer);
- epd_draw_line(x1, y1, x2, y2, color, framebuffer);
- epd_draw_line(x2, y2, x0, y0, color, framebuffer);
-}
-
-void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
- uint8_t color, uint8_t *framebuffer) {
-
- int a, b, y, last;
-
- // Sort coordinates by Y order (y2 >= y1 >= y0)
- if (y0 > y1) {
- _swap_int(y0, y1);
- _swap_int(x0, x1);
- }
- if (y1 > y2) {
- _swap_int(y2, y1);
- _swap_int(x2, x1);
- }
- if (y0 > y1) {
- _swap_int(y0, y1);
- _swap_int(x0, x1);
- }
-
- if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
- a = b = x0;
- if (x1 < a)
- a = x1;
- else if (x1 > b)
- b = x1;
- if (x2 < a)
- a = x2;
- else if (x2 > b)
- b = x2;
- epd_draw_hline(a, y0, b - a + 1, color, framebuffer);
- return;
- }
-
- int dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0,
- dx12 = x2 - x1, dy12 = y2 - y1;
- int32_t sa = 0, sb = 0;
-
- // For upper part of triangle, find scanline crossings for segments
- // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
- // is included here (and second loop will be skipped, avoiding a /0
- // error there), otherwise scanline y1 is skipped here and handled
- // in the second loop...which also avoids a /0 error here if y0=y1
- // (flat-topped triangle).
- if (y1 == y2)
- last = y1; // Include y1 scanline
- else
- last = y1 - 1; // Skip it
-
- for (y = y0; y <= last; y++) {
- a = x0 + sa / dy01;
- b = x0 + sb / dy02;
- sa += dx01;
- sb += dx02;
- /* longhand:
- a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
- b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
- */
- if (a > b)
- _swap_int(a, b);
- epd_draw_hline(a, y, b - a + 1, color, framebuffer);
- }
-
- // For lower part of triangle, find scanline crossings for segments
- // 0-2 and 1-2. This loop is skipped if y1=y2.
- sa = (int32_t)dx12 * (y - y1);
- sb = (int32_t)dx02 * (y - y0);
- for (; y <= y2; y++) {
- a = x1 + sa / dy12;
- b = x0 + sb / dy02;
- sa += dx12;
- sb += dx02;
- /* longhand:
- a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
- b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
- */
- if (a > b)
- _swap_int(a, b);
- epd_draw_hline(a, y, b - a + 1, color, framebuffer);
- }
-}
-
-void epd_copy_to_framebuffer(EpdRect image_area, const uint8_t *image_data,
- uint8_t *framebuffer) {
-
- assert(framebuffer != NULL);
-
- for (uint32_t i = 0; i < image_area.width * image_area.height; i++) {
-
- uint32_t value_index = i;
- // for images of uneven width,
- // consume an additional nibble per row.
- if (image_area.width % 2) {
- value_index += i / image_area.width;
- }
- uint8_t val = (value_index % 2) ? (image_data[value_index / 2] & 0xF0) >> 4
- : image_data[value_index / 2] & 0x0F;
-
- int xx = image_area.x + i % image_area.width;
- if (xx < 0 || xx >= EPD_WIDTH) {
- continue;
- }
- int yy = image_area.y + i / image_area.width;
- if (yy < 0 || yy >= EPD_HEIGHT) {
- continue;
- }
- uint8_t *buf_ptr = &framebuffer[yy * EPD_WIDTH / 2 + xx / 2];
- if (xx % 2) {
- *buf_ptr = (*buf_ptr & 0x0F) | (val << 4);
- } else {
- *buf_ptr = (*buf_ptr & 0xF0) | val;
- }
- }
-}
-
-enum EpdDrawError epd_draw_image(EpdRect area, const uint8_t *data, const EpdWaveform *waveform) {
- int temperature = epd_ambient_temperature();
- assert(waveform != NULL);
- EpdRect no_crop = {
- .x = 0,
- .y = 0,
- .width = 0,
- .height = 0,
- };
- return epd_draw_base(area, data, no_crop, EPD_MODE_DEFAULT, temperature, NULL, waveform);
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.c b/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.c
deleted file mode 100755
index fa9b03842..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "driver/adc.h"
-#include "esp_adc_cal.h"
-#include "esp_log.h"
-
-/// Use GPIO 35
-static const adc1_channel_t channel = ADC1_CHANNEL_7;
-static esp_adc_cal_characteristics_t adc_chars;
-
-#define NUMBER_OF_SAMPLES 100
-
-void epd_temperature_init() {
- esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
- ADC_UNIT_1, ADC_ATTEN_DB_6, ADC_WIDTH_BIT_12, 1100, &adc_chars);
- if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
- ESP_LOGI("epd_temperature", "Characterized using Two Point Value\n");
- } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
- ESP_LOGI("esp_temperature", "Characterized using eFuse Vref\n");
- } else {
- ESP_LOGI("esp_temperature", "Characterized using Default Vref\n");
- }
- adc1_config_width(ADC_WIDTH_BIT_12);
- adc1_config_channel_atten(channel, ADC_ATTEN_DB_6);
-}
-
-float epd_ambient_temperature() {
- uint32_t value = 0;
- for (int i = 0; i < NUMBER_OF_SAMPLES; i++) {
- value += adc1_get_raw(channel);
- }
- value /= NUMBER_OF_SAMPLES;
- // voltage in mV
- float voltage = esp_adc_cal_raw_to_voltage(value, &adc_chars);
- return (voltage - 500.0) / 10.0;
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.h b/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.h
deleted file mode 100755
index ae615e2b1..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/epd_temperature.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#pragma once
-
-/**
- * Initialize the ADC for temperature measurement.
- */
-void epd_temperature_init();
-
-/**
- * Get the current ambient temperature in °C.
- */
-float epd_ambient_temperature();
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/font.c b/lib/libesp32_eink/epdiy/src/epd_driver/font.c
deleted file mode 100755
index 07e8f58f8..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/font.c
+++ /dev/null
@@ -1,375 +0,0 @@
-#include "epd_driver.h"
-#include "esp_assert.h"
-#include "esp_heap_caps.h"
-#include "esp_log.h"
-#if ESP_IDF_VERSION < (4, 0, 0) || ARDUINO_ARCH_ESP32
-#include "rom/miniz.h"
-#else
-#include "esp32/rom/miniz.h"
-#endif
-#include
-#include
-#include
-
-typedef struct {
- uint8_t mask; /* char data will be bitwise AND with this */
- uint8_t lead; /* start bytes of current char in utf-8 encoded character */
- uint32_t beg; /* beginning of codepoint range */
- uint32_t end; /* end of codepoint range */
- int bits_stored; /* the number of bits from the codepoint that fits in char */
-} utf_t;
-
-/*
- * UTF-8 decode inspired from rosetta code
- * https://rosettacode.org/wiki/UTF-8_encode_and_decode#C
- */
-static utf_t *utf[] = {
- /* mask lead beg end bits */
- [0] = &(utf_t){0b00111111, 0b10000000, 0, 0, 6},
- [1] = &(utf_t){0b01111111, 0b00000000, 0000, 0177, 7},
- [2] = &(utf_t){0b00011111, 0b11000000, 0200, 03777, 5},
- [3] = &(utf_t){0b00001111, 0b11100000, 04000, 0177777, 4},
- [4] = &(utf_t){0b00000111, 0b11110000, 0200000, 04177777, 3},
- &(utf_t){0},
-};
-
-/**
- * static decompressor object for compressed fonts.
- */
-static tinfl_decompressor decomp;
-
-static inline int min(int x, int y) { return x < y ? x : y; }
-static inline int max(int x, int y) { return x > y ? x : y; }
-
-static int utf8_len(const uint8_t ch) {
- int len = 0;
- for (utf_t **u = utf; *u; ++u) {
- if ((ch & ~(*u)->mask) == (*u)->lead) {
- break;
- }
- ++len;
- }
- if (len > 4) { /* Malformed leading byte */
- assert("invalid unicode.");
- }
- return len;
-}
-
-static uint32_t next_cp(const uint8_t **string) {
- if (**string == 0) {
- return 0;
- }
- int bytes = utf8_len(**string);
- const uint8_t *chr = *string;
- *string += bytes;
- int shift = utf[0]->bits_stored * (bytes - 1);
- uint32_t codep = (*chr++ & utf[bytes]->mask) << shift;
-
- for (int i = 1; i < bytes; ++i, ++chr) {
- shift -= utf[0]->bits_stored;
- codep |= ((const uint8_t)*chr & utf[0]->mask) << shift;
- }
-
- return codep;
-}
-
-EpdFontProperties epd_font_properties_default() {
- EpdFontProperties props = {
- .fg_color = 0, .bg_color = 15, .fallback_glyph = 0, .flags = EPD_DRAW_ALIGN_LEFT};
- return props;
-}
-
-const EpdGlyph* epd_get_glyph(const EpdFont *font, uint32_t code_point) {
- const EpdUnicodeInterval *intervals = font->intervals;
- for (int i = 0; i < font->interval_count; i++) {
- const EpdUnicodeInterval *interval = &intervals[i];
- if (code_point >= interval->first && code_point <= interval->last) {
- return &font->glyph[interval->offset + (code_point - interval->first)];
- }
- if (code_point < interval->first) {
- return NULL;
- }
- }
- return NULL;
-}
-
-static int uncompress(uint8_t *dest, uint32_t uncompressed_size, const uint8_t *source, uint32_t source_size) {
- if (uncompressed_size == 0 || dest == NULL || source_size == 0 || source == NULL) {
- return -1;
- }
- tinfl_init(&decomp);
-
- // we know everything will fit into the buffer.
- tinfl_status decomp_status = tinfl_decompress(&decomp, source, &source_size, dest, dest, &uncompressed_size, TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
- if (decomp_status != TINFL_STATUS_DONE) {
- return decomp_status;
- }
- return 0;
-}
-
-/*!
- @brief Draw a single character to a pre-allocated buffer.
-*/
-static enum EpdDrawError IRAM_ATTR draw_char(const EpdFont *font, uint8_t *buffer,
- int *cursor_x, int cursor_y, uint16_t buf_width,
- uint16_t buf_height, uint32_t cp,
- const EpdFontProperties *props) {
-
- assert(props != NULL);
-
- const EpdGlyph *glyph = epd_get_glyph(font, cp);
- if (!glyph) {
- glyph = epd_get_glyph(font, props->fallback_glyph);
- }
-
- if (!glyph) {
- return EPD_DRAW_GLYPH_FALLBACK_FAILED;
- }
-
- uint32_t offset = glyph->data_offset;
- uint8_t width = glyph->width, height = glyph->height;
- int left = glyph->left;
-
- int byte_width = (width / 2 + width % 2);
- unsigned long bitmap_size = byte_width * height;
- const uint8_t *bitmap = NULL;
- if (font->compressed) {
- uint8_t* tmp_bitmap = (uint8_t *)malloc(bitmap_size);
- if (tmp_bitmap == NULL && bitmap_size) {
- ESP_LOGE("font", "malloc failed.");
- return EPD_DRAW_FAILED_ALLOC;
- }
- uncompress(tmp_bitmap, bitmap_size, &font->bitmap[offset],
- glyph->compressed_size);
- bitmap = tmp_bitmap;
- } else {
- bitmap = &font->bitmap[offset];
- }
-
- uint8_t color_lut[16];
- for (int c = 0; c < 16; c++) {
- int color_difference = (int)props->fg_color - (int)props->bg_color;
- color_lut[c] = max(0, min(15, props->bg_color + c * color_difference / 15));
- }
-
- for (int y = 0; y < height; y++) {
- int yy = cursor_y - glyph->top + y;
- if (yy < 0 || yy >= buf_height) {
- continue;
- }
- int start_pos = *cursor_x + left;
- bool byte_complete = start_pos % 2;
- int x = max(0, -start_pos);
- int max_x = min(start_pos + width, buf_width * 2);
- for (int xx = start_pos; xx < max_x; xx++) {
- uint32_t buf_pos = yy * buf_width + xx / 2;
- uint8_t old = buffer[buf_pos];
- uint8_t bm = bitmap[y * byte_width + x / 2];
- if ((x & 1) == 0) {
- bm = bm & 0xF;
- } else {
- bm = bm >> 4;
- }
-
- if ((xx & 1) == 0) {
- buffer[buf_pos] = (old & 0xF0) | color_lut[bm];
- } else {
- buffer[buf_pos] = (old & 0x0F) | (color_lut[bm] << 4);
- }
- byte_complete = !byte_complete;
- x++;
- }
- }
- if (font->compressed) {
- free((uint8_t*)bitmap);
- }
- *cursor_x += glyph->advance_x;
- return EPD_DRAW_SUCCESS;
-}
-
-/*!
- * @brief Calculate the bounds of a character when drawn at (x, y), move the
- * cursor (*x) forward, adjust the given bounds.
- */
-static void get_char_bounds(const EpdFont *font, uint32_t cp, int *x, int *y,
- int *minx, int *miny, int *maxx, int *maxy,
- const EpdFontProperties *props) {
-
- assert(props != NULL);
-
- const EpdGlyph *glyph = epd_get_glyph(font, cp);
-
- if (!glyph) {
- glyph = epd_get_glyph(font, props->fallback_glyph);
- }
-
- if (!glyph) {
- return;
- }
-
- int x1 = *x + glyph->left, y1 = *y + glyph->top - glyph->height,
- x2 = x1 + glyph->width, y2 = y1 + glyph->height;
-
- // background needs to be taken into account
- if (props->flags & EPD_DRAW_BACKGROUND) {
- *minx = min(*x, min(*minx, x1));
- *maxx = max(max(*x + glyph->advance_x, x2), *maxx);
- *miny = min(*y + font->descender, min(*miny, y1));
- *maxy = max(*y + font->ascender, max(*maxy, y2));
- } else {
- if (x1 < *minx)
- *minx = x1;
- if (y1 < *miny)
- *miny = y1;
- if (x2 > *maxx)
- *maxx = x2;
- if (y2 > *maxy)
- *maxy = y2;
- }
- *x += glyph->advance_x;
-}
-
-void epd_get_text_bounds(const EpdFont *font, const char *string,
- const int *x, const int *y,
- int *x1, int *y1, int *w, int *h,
- const EpdFontProperties *properties) {
- // FIXME: Does not respect alignment!
-
- assert(properties != NULL);
- EpdFontProperties props = *properties;
-
- if (*string == '\0') {
- *w = 0;
- *h = 0;
- *y1 = *y;
- *x1 = *x;
- return;
- }
- int minx = 100000, miny = 100000, maxx = -1, maxy = -1;
- int original_x = *x;
- int temp_x = *x;
- int temp_y = *y;
- uint32_t c;
- while ((c = next_cp((const uint8_t **)&string))) {
- get_char_bounds(font, c, &temp_x, &temp_y, &minx, &miny, &maxx, &maxy, &props);
- }
- *x1 = min(original_x, minx);
- *w = maxx - *x1;
- *y1 = miny;
- *h = maxy - miny;
-}
-
-static enum EpdDrawError epd_write_line(
- const EpdFont *font, const char *string, int *cursor_x,
- int *cursor_y, uint8_t *framebuffer,
- const EpdFontProperties *properties)
-{
-
- assert(framebuffer != NULL);
-
- if (*string == '\0') {
- return EPD_DRAW_SUCCESS;
- }
-
- assert(properties != NULL);
- EpdFontProperties props = *properties;
- enum EpdFontFlags alignment_mask = EPD_DRAW_ALIGN_LEFT | EPD_DRAW_ALIGN_RIGHT | EPD_DRAW_ALIGN_CENTER;
- enum EpdFontFlags alignment = props.flags & alignment_mask;
-
- // alignments are mutually exclusive!
- if ((alignment & (alignment - 1)) != 0) {
- return EPD_DRAW_INVALID_FONT_FLAGS;
- }
-
-
- int x1 = 0, y1 = 0, w = 0, h = 0;
- int tmp_cur_x = *cursor_x;
- int tmp_cur_y = *cursor_y;
- epd_get_text_bounds(font, string, &tmp_cur_x, &tmp_cur_y, &x1, &y1, &w, &h, &props);
-
- // no printable characters
- if (w < 0 || h < 0) {
- return EPD_DRAW_NO_DRAWABLE_CHARACTERS;
- }
-
- int baseline_height = *cursor_y - y1;
-
- int buf_width = EPD_WIDTH / 2;
- int buf_height = EPD_HEIGHT;
-
- uint8_t* buffer = framebuffer;
- int local_cursor_x = *cursor_x;
- int local_cursor_y = *cursor_y;
- uint32_t c;
-
- int cursor_x_init = local_cursor_x;
- int cursor_y_init = local_cursor_y;
-
- switch (alignment) {
- case EPD_DRAW_ALIGN_LEFT: {
- break;
- }
- case EPD_DRAW_ALIGN_CENTER: {
- local_cursor_x -= w / 2;
- break;
- }
- case EPD_DRAW_ALIGN_RIGHT: {
- local_cursor_x -= w;
- break;
- }
- default:
- break;
- }
-
- uint8_t bg = props.bg_color;
- if (props.flags & EPD_DRAW_BACKGROUND) {
- for (int l = local_cursor_y - font->ascender;
- l < local_cursor_y - font->descender; l++) {
- epd_draw_hline(local_cursor_x, l, w, bg << 4, buffer);
- }
- }
- enum EpdDrawError err = EPD_DRAW_SUCCESS;
- while ((c = next_cp((const uint8_t **)&string))) {
- err |= draw_char(font, buffer, &local_cursor_x, local_cursor_y, buf_width,
- buf_height, c, &props);
- }
-
- *cursor_x += local_cursor_x - cursor_x_init;
- *cursor_y += local_cursor_y - cursor_y_init;
- return err;
-}
-
-enum EpdDrawError epd_write_default(const EpdFont *font, const char *string, int *cursor_x,
- int *cursor_y, uint8_t *framebuffer) {
- const EpdFontProperties props = epd_font_properties_default();
- return epd_write_string(font, string, cursor_x, cursor_y, framebuffer, &props);
-}
-
-enum EpdDrawError epd_write_string(
- const EpdFont *font, const char *string, int *cursor_x,
- int *cursor_y, uint8_t *framebuffer,
- const EpdFontProperties *properties
-) {
- char *token, *newstring, *tofree;
- if (string == NULL) {
- ESP_LOGE("font.c", "cannot draw a NULL string!");
- return EPD_DRAW_STRING_INVALID;
- }
- tofree = newstring = strdup(string);
- if (newstring == NULL) {
- ESP_LOGE("font.c", "cannot allocate string copy!");
- return EPD_DRAW_FAILED_ALLOC;
- }
-
- enum EpdDrawError err = EPD_DRAW_SUCCESS;
- // taken from the strsep manpage
- int line_start = *cursor_x;
- while ((token = strsep(&newstring, "\n")) != NULL) {
- *cursor_x = line_start;
- err |= epd_write_line(font, token, cursor_x, cursor_y, framebuffer, properties);
- *cursor_y += font->advance_y;
- }
-
- free(tofree);
- return err;
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/highlevel.c b/lib/libesp32_eink/epdiy/src/epd_driver/highlevel.c
deleted file mode 100755
index ac68d8268..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/highlevel.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * High-level API implementation for epdiy.
- */
-
-#include "epd_highlevel.h"
-#include
-#include
-#include
-#include
-#include
-
-static bool already_initialized = 0;
-
-const static int fb_size = EPD_WIDTH / 2 * EPD_HEIGHT;
-
-EpdiyHighlevelState epd_hl_init(const EpdWaveform* waveform) {
- assert(!already_initialized);
- assert(waveform != NULL);
-
- EpdiyHighlevelState state;
- state.front_fb = heap_caps_malloc(fb_size, MALLOC_CAP_SPIRAM);
- assert(state.front_fb != NULL);
- state.back_fb = heap_caps_malloc(fb_size, MALLOC_CAP_SPIRAM);
- assert(state.back_fb != NULL);
- state.difference_fb = heap_caps_malloc(2 * fb_size, MALLOC_CAP_SPIRAM);
- assert(state.difference_fb != NULL);
- state.dirty_lines = malloc(EPD_HEIGHT * sizeof(bool));
- assert(state.dirty_lines != NULL);
- state.waveform = waveform;
-
- memset(state.front_fb, 0xFF, fb_size);
- memset(state.back_fb, 0xFF, fb_size);
-
- already_initialized = true;
- return state;
-}
-
-
-uint8_t* epd_hl_get_framebuffer(EpdiyHighlevelState* state) {
- assert(state != NULL);
- return state->front_fb;
-}
-
-enum EpdDrawError epd_hl_update_screen(EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature) {
- return epd_hl_update_area(state, mode, temperature, epd_full_screen());
-}
-
-enum EpdDrawError epd_hl_update_area(EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature, EpdRect area) {
- assert(state != NULL);
-
- bool previously_white = false;
- bool previously_black = false;
-
- //FIXME: use crop information here, if available
- EpdRect diff_area = epd_difference_image_cropped(
- state->front_fb,
- state->back_fb,
- area,
- state->difference_fb,
- state->dirty_lines,
- &previously_white,
- &previously_black
- );
-
- if (diff_area.height == 0 || diff_area.width == 0) {
- return EPD_DRAW_SUCCESS;
- }
-
- enum EpdDrawError err;
- if (previously_white) {
- err = epd_draw_base(epd_full_screen(), state->front_fb, diff_area, MODE_PACKING_2PPB | PREVIOUSLY_WHITE | mode, temperature, state->dirty_lines, state->waveform);
- } else if (previously_black) {
- err = epd_draw_base(epd_full_screen(), state->front_fb, diff_area, MODE_PACKING_2PPB | PREVIOUSLY_BLACK | mode, temperature, state->dirty_lines, state->waveform);
- } else {
- err = epd_draw_base(epd_full_screen(), state->difference_fb, diff_area, MODE_PACKING_1PPB_DIFFERENCE | mode, temperature, state->dirty_lines, state->waveform);
- }
-
- for (int l=diff_area.y; l < diff_area.y + diff_area.height; l++) {
- if (state->dirty_lines[l]) {
- memcpy(
- state->back_fb + EPD_WIDTH / 2 * l,
- state->front_fb + EPD_WIDTH / 2 * l,
- EPD_WIDTH / 2
- );
- }
- }
- return err;
-}
-
-
-void epd_hl_set_all_white(EpdiyHighlevelState* state) {
- assert(state != NULL);
- memset(state->front_fb, 0xFF, fb_size);
-}
-
-void epd_fullclear(EpdiyHighlevelState* state, int temperature) {
- assert(state != NULL);
- epd_hl_set_all_white(state);
- enum EpdDrawError err = epd_hl_update_screen(state, MODE_GC16, temperature);
- assert(err == EPD_DRAW_SUCCESS);
- epd_clear();
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.c b/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.c
deleted file mode 100755
index f7082b3fb..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.c
+++ /dev/null
@@ -1,262 +0,0 @@
-#include "i2s_data_bus.h"
-#include "driver/periph_ctrl.h"
-#if ESP_IDF_VERSION < (4, 0, 0) || ARDUINO_ARCH_ESP32
-#include "rom/lldesc.h"
-#else
-#include "esp32/rom/lldesc.h"
-#endif
-#include "esp_heap_caps.h"
-#include "soc/i2s_reg.h"
-#include "soc/i2s_struct.h"
-#include "soc/rtc.h"
-
-/// DMA descriptors for front and back line buffer.
-/// We use two buffers, so one can be filled while the other
-/// is transmitted.
-typedef struct {
- volatile lldesc_t *dma_desc_a;
- volatile lldesc_t *dma_desc_b;
-
- /// Front and back line buffer.
- uint8_t *buf_a;
- uint8_t *buf_b;
-} i2s_parallel_state_t;
-
-/// Indicates which line buffer is currently back / front.
-static int current_buffer = 0;
-
-/// The I2S state instance.
-static i2s_parallel_state_t i2s_state;
-
-static intr_handle_t gI2S_intr_handle = NULL;
-
-/// Indicates the device has finished its transmission and is ready again.
-static volatile bool output_done = true;
-/// The start pulse pin extracted from the configuration for use in the "done"
-/// interrupt.
-static gpio_num_t start_pulse_pin;
-
-/// Initializes a DMA descriptor.
-static void fill_dma_desc(volatile lldesc_t *dmadesc, uint8_t *buf,
- i2s_bus_config *cfg) {
- dmadesc->size = cfg->epd_row_width / 4;
- dmadesc->length = cfg->epd_row_width / 4;
- dmadesc->buf = buf;
- dmadesc->eof = 1;
- dmadesc->sosf = 1;
- dmadesc->owner = 1;
- dmadesc->qe.stqe_next = 0;
- dmadesc->offset = 0;
-}
-
-/// Address of the currently front DMA descriptor,
-/// which uses only the lower 20bits (according to TRM)
-uint32_t dma_desc_addr() {
- return (uint32_t)(current_buffer ? i2s_state.dma_desc_a
- : i2s_state.dma_desc_b) &
- 0x000FFFFF;
-}
-
-/// Set up a GPIO as output and route it to a signal.
-static void gpio_setup_out(int gpio, int sig, bool invert) {
- if (gpio == -1)
- return;
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
- gpio_set_direction(gpio, GPIO_MODE_DEF_OUTPUT);
- gpio_matrix_out(gpio, sig, invert, false);
-}
-
-/// Resets "Start Pulse" signal when the current row output is done.
-static void IRAM_ATTR i2s_int_hdl(void *arg) {
- i2s_dev_t *dev = &I2S1;
- if (dev->int_st.out_done) {
- //gpio_set_level(start_pulse_pin, 1);
- //gpio_set_level(GPIO_NUM_26, 0);
- output_done = true;
- }
- // Clear the interrupt. Otherwise, the whole device would hang.
- dev->int_clr.val = dev->int_raw.val;
-}
-
-volatile uint8_t IRAM_ATTR *i2s_get_current_buffer() {
- return current_buffer ? i2s_state.dma_desc_a->buf : i2s_state.dma_desc_b->buf;
-}
-
-bool IRAM_ATTR i2s_is_busy() {
- // DMA and FIFO must be done
- return !output_done || !I2S1.state.tx_idle;
-}
-
-void IRAM_ATTR i2s_switch_buffer() {
- // either device is done transmitting or the switch must be away from the
- // buffer currently used by the DMA engine.
- while (i2s_is_busy() && dma_desc_addr() != I2S1.out_link.addr) {
- };
- current_buffer = !current_buffer;
-}
-
-void IRAM_ATTR i2s_start_line_output() {
- output_done = false;
-
- i2s_dev_t *dev = &I2S1;
- dev->conf.tx_start = 0;
- dev->conf.tx_reset = 1;
- dev->conf.tx_fifo_reset = 1;
- dev->conf.rx_fifo_reset = 1;
- dev->conf.tx_reset = 0;
- dev->conf.tx_fifo_reset = 0;
- dev->conf.rx_fifo_reset = 0;
- dev->out_link.addr = dma_desc_addr();
- dev->out_link.start = 1;
-
- // sth is pulled up through peripheral interrupt
- // This is timing-critical!
- gpio_set_level(start_pulse_pin, 0);
- dev->conf.tx_start = 1;
-}
-
-void i2s_bus_init(i2s_bus_config *cfg) {
- // TODO: Why?
- gpio_num_t I2S_GPIO_BUS[] = {cfg->data_6, cfg->data_7, cfg->data_4,
- cfg->data_5, cfg->data_2, cfg->data_3,
- cfg->data_0, cfg->data_1};
-
- gpio_set_direction(cfg->start_pulse, GPIO_MODE_OUTPUT);
- gpio_set_level(cfg->start_pulse, 1);
- // store pin in global variable for use in interrupt.
- start_pulse_pin = cfg->start_pulse;
-
- // Use I2S1 with no signal offset (for some reason the offset seems to be
- // needed in 16-bit mode, but not in 8 bit mode.
- int signal_base = I2S1O_DATA_OUT0_IDX;
-
- // Setup and route GPIOS
- for (int x = 0; x < 8; x++) {
- gpio_setup_out(I2S_GPIO_BUS[x], signal_base + x, false);
- }
- // Invert word select signal
- gpio_setup_out(cfg->clock, I2S1O_WS_OUT_IDX, true);
-
- periph_module_enable(PERIPH_I2S1_MODULE);
-
- i2s_dev_t *dev = &I2S1;
-
- // Initialize device
- dev->conf.tx_reset = 1;
- dev->conf.tx_reset = 0;
-
- // Reset DMA
- dev->lc_conf.in_rst = 1;
- dev->lc_conf.in_rst = 0;
- dev->lc_conf.out_rst = 1;
- dev->lc_conf.out_rst = 0;
-
- // Setup I2S config. See section 12 of Technical Reference Manual
- // Enable LCD mode
- dev->conf2.val = 0;
- dev->conf2.lcd_en = 1;
-
- // Enable FRAME1-Mode (See technical reference manual)
- dev->conf2.lcd_tx_wrx2_en = 1;
- dev->conf2.lcd_tx_sdx2_en = 0;
-
- // Set to 8 bit parallel output
- dev->sample_rate_conf.val = 0;
- dev->sample_rate_conf.tx_bits_mod = 8;
-
- // Half speed of bit clock in LCD mode.
- // (Smallest possible divider according to the spec).
- dev->sample_rate_conf.tx_bck_div_num = 2;
-
-#if defined(CONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ)
- // Initialize Audio Clock (APLL) for 120 Mhz.
- rtc_clk_apll_enable(1, 0, 0, 8, 0);
-#else
- // Initialize Audio Clock (APLL) for 100 Mhz.
- rtc_clk_apll_enable(1, 0, 0, 8, 0);
-#endif
-
- // Set Audio Clock Dividers
- dev->clkm_conf.val = 0;
- dev->clkm_conf.clka_en = 1;
- dev->clkm_conf.clkm_div_a = 1;
- dev->clkm_conf.clkm_div_b = 0;
- // 2 is the smallest possible divider according to the spec.
- dev->clkm_conf.clkm_div_num = 2;
-
- // Set up FIFO
- dev->fifo_conf.val = 0;
- dev->fifo_conf.tx_fifo_mod_force_en = 1;
- dev->fifo_conf.tx_fifo_mod = 1;
- dev->fifo_conf.tx_data_num = 32;
- dev->fifo_conf.dscr_en = 1;
-
- // Stop after transmission complete
- dev->conf1.val = 0;
- dev->conf1.tx_stop_en = 1;
- dev->conf1.tx_pcm_bypass = 1;
-
- // Configure TX channel
- dev->conf_chan.val = 0;
- dev->conf_chan.tx_chan_mod = 1;
- dev->conf.tx_right_first = 1;
-
- dev->timing.val = 0;
-
- // Allocate DMA descriptors
- i2s_state.buf_a = heap_caps_malloc(cfg->epd_row_width / 4, MALLOC_CAP_DMA);
- i2s_state.buf_b = heap_caps_malloc(cfg->epd_row_width / 4, MALLOC_CAP_DMA);
- i2s_state.dma_desc_a = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
- i2s_state.dma_desc_b = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
-
- // and fill them
- fill_dma_desc(i2s_state.dma_desc_a, i2s_state.buf_a, cfg);
- fill_dma_desc(i2s_state.dma_desc_b, i2s_state.buf_b, cfg);
-
- // enable "done" interrupt
- SET_PERI_REG_BITS(I2S_INT_ENA_REG(1), I2S_OUT_DONE_INT_ENA_V, 1,
- I2S_OUT_DONE_INT_ENA_S);
- // register interrupt
- esp_intr_alloc(ETS_I2S1_INTR_SOURCE, 0, i2s_int_hdl, 0, &gI2S_intr_handle);
-
- // Reset FIFO/DMA
- dev->lc_conf.in_rst = 1;
- dev->lc_conf.out_rst = 1;
- dev->lc_conf.ahbm_rst = 1;
- dev->lc_conf.ahbm_fifo_rst = 1;
- dev->lc_conf.in_rst = 0;
- dev->lc_conf.out_rst = 0;
- dev->lc_conf.ahbm_rst = 0;
- dev->lc_conf.ahbm_fifo_rst = 0;
- dev->conf.tx_reset = 1;
- dev->conf.tx_fifo_reset = 1;
- dev->conf.rx_fifo_reset = 1;
- dev->conf.tx_reset = 0;
- dev->conf.tx_fifo_reset = 0;
- dev->conf.rx_fifo_reset = 0;
-
- // Start dma on front buffer
- dev->lc_conf.val =
- I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN;
- dev->out_link.addr = ((uint32_t)(i2s_state.dma_desc_a));
- dev->out_link.start = 1;
-
- dev->int_clr.val = dev->int_raw.val;
-
- dev->int_ena.val = 0;
- dev->int_ena.out_done = 1;
-
- dev->conf.tx_start = 0;
-}
-
-void i2s_deinit() {
- esp_intr_free(gI2S_intr_handle);
-
- free(i2s_state.buf_a);
- free(i2s_state.buf_b);
- free((void *)i2s_state.dma_desc_a);
- free((void *)i2s_state.dma_desc_b);
-
- rtc_clk_apll_enable(0, 0, 0, 8, 0);
- periph_module_disable(PERIPH_I2S1_MODULE);
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.h b/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.h
deleted file mode 100755
index cef7a1091..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/i2s_data_bus.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Implements a 8bit parallel interface to transmit pixel
- * data to the display, based on the I2S peripheral.
- */
-
-#pragma once
-
-#include "driver/gpio.h"
-#include "esp_attr.h"
-#include
-
-/**
- * I2S bus configuration parameters.
- */
-typedef struct {
- /// GPIO numbers of the parallel bus pins.
- gpio_num_t data_0;
- gpio_num_t data_1;
- gpio_num_t data_2;
- gpio_num_t data_3;
- gpio_num_t data_4;
- gpio_num_t data_5;
- gpio_num_t data_6;
- gpio_num_t data_7;
-
- /// Data clock pin.
- gpio_num_t clock;
-
- /// "Start Pulse", enabling data input on the slave device (active low)
- gpio_num_t start_pulse;
-
- // Width of a display row in pixels.
- uint32_t epd_row_width;
-} i2s_bus_config;
-
-/**
- * Initialize the I2S data bus for communication
- * with a 8bit parallel display interface.
- */
-void i2s_bus_init(i2s_bus_config *cfg);
-
-/**
- * Get the currently writable line buffer.
- */
-volatile uint8_t IRAM_ATTR *i2s_get_current_buffer();
-
-/**
- * Switches front and back line buffer.
- * If the switched-to line buffer is currently in use,
- * this function blocks until transmission is done.
- */
-void IRAM_ATTR i2s_switch_buffer();
-
-/**
- * Start transmission of the current back buffer.
- */
-void IRAM_ATTR i2s_start_line_output();
-
-/**
- * Returns true if there is an ongoing transmission.
- */
-bool IRAM_ATTR i2s_is_busy();
-
-/**
- * Give up allocated resources.
- */
-void i2s_deinit();
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_driver.h b/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_driver.h
deleted file mode 100755
index 3c983e465..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_driver.h
+++ /dev/null
@@ -1,471 +0,0 @@
-/**
- * @file epd_driver.h
- * A driver library for drawing to an EPD.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define CONFIG_EPD_DISPLAY_TYPE_ED047TC1
-#define CONFIG_EPD_BOARD_REVISION_LILYGO_T5_47
-
-#pragma once
-#include "esp_attr.h"
-#include "epd_internals.h"
-
-#include
-#include
-
-/// An area on the display.
-typedef struct {
- /// Horizontal position.
- int x;
- /// Vertical position.
- int y;
- /// Area / image width, must be positive.
- int width;
- /// Area / image height, must be positive.
- int height;
-} EpdRect;
-
-/// Possible failures when drawing.
-enum EpdDrawError {
- EPD_DRAW_SUCCESS = 0x0,
- /// No valid framebuffer packing mode was specified.
- EPD_DRAW_INVALID_PACKING_MODE = 0x1,
-
- /// No lookup table implementation for this mode / packing.
- EPD_DRAW_LOOKUP_NOT_IMPLEMENTED = 0x2,
-
- /// The string to draw is invalid.
- EPD_DRAW_STRING_INVALID = 0x4,
-
- /// The string was not empty, but no characters where drawable.
- EPD_DRAW_NO_DRAWABLE_CHARACTERS = 0x8,
-
- /// Allocation failed
- EPD_DRAW_FAILED_ALLOC = 0x10,
-
- /// A glyph could not be drawn, and not fallback was present.
- EPD_DRAW_GLYPH_FALLBACK_FAILED = 0x20,
-
- /// The specified crop area is invalid.
- EPD_DRAW_INVALID_CROP = 0x40,
-
- /// No such mode is available with the current waveform.
- EPD_DRAW_MODE_NOT_FOUND = 0x80,
-
- /// The waveform info file contains no applicable temperature range.
- EPD_DRAW_NO_PHASES_AVAILABLE = 0x100,
-
- /// An invalid combination of font flags was used.
- EPD_DRAW_INVALID_FONT_FLAGS = 0x200,
-};
-
-/// Global EPD driver options.
-enum EpdInitOptions {
- /// Use the default options.
- EPD_OPTIONS_DEFAULT = 0,
- /// Use a small look-up table of 1024 bytes.
- /// The EPD driver will use less space, but performance may be worse.
- EPD_LUT_1K = 1,
- /// Use a 64K lookup table. (default)
- /// Best performance, but permanently occupies a 64k block of internal memory.
- EPD_LUT_64K = 2,
-
- /// Use a small feed queue of 8 display lines.
- /// This uses less memory, but may impact performance.
- EPD_FEED_QUEUE_8 = 4,
- /// Use a feed queue of 32 display lines. (default)
- /// Best performance, but larger memory footprint.
- EPD_FEED_QUEUE_32 = 8,
-};
-
-/// The image drawing mode.
-enum EpdDrawMode {
- /// An init waveform.
- /// This is currently unused, use `epd_clear()` instead.
- MODE_INIT = 0x0,
- /// Direct Update: Go from any color to black for white only.
- MODE_DU = 0x1,
- /// Go from any grayscale value to another with a flashing update.
- MODE_GC16 = 0x2,
- /// Faster version of `MODE_GC16`.
- /// Not available with default epdiy waveforms.
- MODE_GC16_FAST = 0x3,
- /// Animation Mode: Fast, monochrom updates.
- /// Not available with default epdiy waveforms.
- MODE_A2 = 0x4,
- /// Go from any grayscale value to another with a non-flashing update.
- MODE_GL16 = 0x5,
- /// Faster version of `MODE_GL16`.
- /// Not available with default epdiy waveforms.
- MODE_GL16_FAST = 0x6,
- /// A 4-grayscale version of `MODE_DU`.
- /// Not available with default epdiy waveforms.
- MODE_DU4 = 0x7,
- /// Arbitrary transitions for 4 grayscale values.
- /// Not available with default epdiy waveforms.
- MODE_GL4 = 0xA,
- /// Not available with default epdiy waveforms.
- MODE_GL16_INV = 0xB,
-
- /// Go from a white screen to arbitrary grayscale, quickly.
- /// Exclusively available with epdiy waveforms.
- MODE_EPDIY_WHITE_TO_GL16 = 0x10,
- /// Go from a black screen to arbitrary grayscale, quickly.
- /// Exclusively available with epdiy waveforms.
- MODE_EPDIY_BLACK_TO_GL16 = 0x11,
-
- /// Monochrome mode. Only supported with 1bpp buffers.
- MODE_EPDIY_MONOCHROME = 0x20,
-
- MODE_UNKNOWN_WAVEFORM = 0x3F,
-
- // Framebuffer packing modes
- /// 1 bit-per-pixel framebuffer with 0 = black, 1 = white.
- /// MSB is left is the leftmost pixel, LSB the rightmost pixel.
- MODE_PACKING_8PPB = 0x40,
- /// 4 bit-per pixel framebuffer with 0x0 = black, 0xF = white.
- /// The upper nibble corresponds to the left pixel.
- /// A byte cannot wrap over multiple rows, images of uneven width
- /// must add a padding nibble per line.
- MODE_PACKING_2PPB = 0x80,
- /// A difference image with one pixel per byte.
- /// The upper nibble marks the "from" color,
- /// the lower nibble the "to" color.
- MODE_PACKING_1PPB_DIFFERENCE = 0x100,
- // reserver for 4PPB mode
-
- /// Assert that the display has a uniform color, e.g. after initialization.
- /// If `MODE_PACKING_2PPB` is specified, a optimized output calculation can be used.
- /// Draw on a white background
- PREVIOUSLY_WHITE = 0x200,
- /// See `PREVIOUSLY_WHITE`.
- /// Draw on a black background
- PREVIOUSLY_BLACK = 0x400,
-};
-
-/// The default draw mode (non-flashy refresh, whith previously white screen).
-#define EPD_MODE_DEFAULT (MODE_GL16 | PREVIOUSLY_WHITE)
-
-/// Font drawing flags
-enum EpdFontFlags {
- /// Draw a background.
- ///
- /// Take the background into account
- /// when calculating the size.
- EPD_DRAW_BACKGROUND = 0x1,
-
- /// Left-Align lines
- EPD_DRAW_ALIGN_LEFT = 0x2,
- /// Right-align lines
- EPD_DRAW_ALIGN_RIGHT = 0x4,
- /// Center-align lines
- EPD_DRAW_ALIGN_CENTER = 0x8,
-};
-
-/// Font properties.
-typedef struct {
- /// Foreground color
- uint8_t fg_color : 4;
- /// Background color
- uint8_t bg_color : 4;
- /// Use the glyph for this codepoint for missing glyphs.
- uint32_t fallback_glyph;
- /// Additional flags, reserved for future use
- enum EpdFontFlags flags;
-} EpdFontProperties;
-
-/** Initialize the ePaper display */
-void epd_init(enum EpdInitOptions options);
-
-/** Deinit the ePaper display */
-void epd_deinit();
-
-/** Enable display power supply. */
-void epd_poweron();
-
-/** Disable display power supply. */
-void epd_poweroff();
-
-/** Clear the whole screen by flashing it. */
-void epd_clear();
-
-/**
- * Clear an area by flashing it.
- *
- * @param area: The area to clear.
- */
-void epd_clear_area(EpdRect area);
-
-/**
- * Clear an area by flashing it.
- *
- * @param area: The area to clear.
- * @param cycles: The number of black-to-white clear cycles.
- * @param cycle_time: Length of a cycle. Default: 50 (us).
- */
-void epd_clear_area_cycles(EpdRect area, int cycles, int cycle_time);
-
-/**
- * @returns Rectancle representing the whole screen area.
- */
-EpdRect epd_full_screen();
-
-/**
- * Draw a picture to a given framebuffer.
- *
- * @param image_area: The area to copy to. `width` and `height` of the area
- * must correspond to the image dimensions in pixels.
- * @param image_data: The image data, as a buffer of 4 bit wide brightness
- * values. Pixel data is packed (two pixels per byte). A byte cannot wrap over
- * multiple rows, images of uneven width must add a padding nibble per line.
- * @param framebuffer: The framebuffer object,
- * which must be `EPD_WIDTH / 2 * EPD_HEIGHT` large.
- */
-void epd_copy_to_framebuffer(EpdRect image_area, const uint8_t *image_data,
- uint8_t *framebuffer);
-
-/**
- * Draw a pixel a given framebuffer.
- *
- * @param x: Horizontal position in pixels.
- * @param y: Vertical position in pixels.
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_draw_pixel(int x, int y, uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a horizontal line to a given framebuffer.
- *
- * @param x: Horizontal start position in pixels.
- * @param y: Vertical start position in pixels.
- * @param length: Length of the line in pixels.
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- * which must be `EPD_WIDTH / 2 * EPD_HEIGHT` bytes large.
- */
-void epd_draw_hline(int x, int y, int length, uint8_t color,
- uint8_t *framebuffer);
-
-/**
- * Draw a horizontal line to a given framebuffer.
- *
- * @param x: Horizontal start position in pixels.
- * @param y: Vertical start position in pixels.
- * @param length: Length of the line in pixels.
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- * which must be `EPD_WIDTH / 2 * EPD_HEIGHT` bytes large.
- */
-void epd_draw_vline(int x, int y, int length, uint8_t color,
- uint8_t *framebuffer);
-
-void epd_fill_circle_helper(int x0, int y0, int r, int corners, int delta,
- uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a circle with given center and radius
- *
- * @param x: Center-point x coordinate
- * @param y: Center-point y coordinate
- * @param r: Radius of the circle in pixels
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_draw_circle(int x, int y, int r, uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a circle with fill with given center and radius
- *
- * @param x: Center-point x coordinate
- * @param y: Center-point y coordinate
- * @param r: Radius of the circle in pixels
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_fill_circle(int x, int y, int r, uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a rectanle with no fill color
- *
- * @param rect: The rectangle to draw.
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_draw_rect(EpdRect rect, uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a rectanle with fill color
- *
- * @param rect: The rectangle to fill.
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_fill_rect(EpdRect rect, uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a line
- *
- * @param x0 Start point x coordinate
- * @param y0 Start point y coordinate
- * @param x1 End point x coordinate
- * @param y1 End point y coordinate
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_draw_line(int x0, int y0, int x1, int y1, uint8_t color,
- uint8_t *framebuffer);
-
-/**
- * Draw a triangle with no fill color
- *
- * @param x0 Vertex #0 x coordinate
- * @param y0 Vertex #0 y coordinate
- * @param x1 Vertex #1 x coordinate
- * @param y1 Vertex #1 y coordinate
- * @param x2 Vertex #2 x coordinate
- * @param y2 Vertex #2 y coordinate
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_draw_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
- uint8_t color, uint8_t *framebuffer);
-
-/**
- * Draw a triangle with color-fill
- *
- * @param x0 Vertex #0 x coordinate
- * @param y0 Vertex #0 y coordinate
- * @param x1 Vertex #1 x coordinate
- * @param y1 Vertex #1 y coordinate
- * @param x2 Vertex #2 x coordinate
- * @param y2 Vertex #2 y coordinate
- * @param color: The gray value of the line (0-255);
- * @param framebuffer: The framebuffer to draw to,
- */
-void epd_fill_triangle(int x0, int y0, int x1, int y1, int x2, int y2,
- uint8_t color, uint8_t *framebuffer);
-/**
- * Get the current ambient temperature in °C, if supported by the board.
- * Requires the display to be powered on.
- */
-float epd_ambient_temperature();
-
-/**
- * The default font properties.
- */
-EpdFontProperties epd_font_properties_default();
-
-/*!
- * Get the text bounds for string, when drawn at (x, y).
- * Set font properties to NULL to use the defaults.
- */
-void epd_get_text_bounds(const EpdFont *font, const char *string,
- const int *x, const int *y,
- int *x1, int *y1, int *w, int *h,
- const EpdFontProperties *props);
-
-/**
- * Write text to the EPD.
- */
-enum EpdDrawError epd_write_string(const EpdFont *font, const char *string, int *cursor_x,
- int *cursor_y, uint8_t *framebuffer,
- const EpdFontProperties *properties);
-
-/**
- * Write a (multi-line) string to the EPD.
- */
-enum EpdDrawError epd_write_default(const EpdFont *font, const char *string, int *cursor_x,
- int *cursor_y, uint8_t *framebuffer);
-
-/**
- * Get the font glyph for a unicode code point.
- */
-const EpdGlyph* epd_get_glyph(const EpdFont *font, uint32_t code_point);
-
-
-/**
- * Darken / lighten an area for a given time.
- *
- * @param area: The area to darken / lighten.
- * @param time: The time in us to apply voltage to each pixel.
- * @param color: 1: lighten, 0: darken.
- */
-void epd_push_pixels(EpdRect area, short time, int color);
-
-/**
- * Base function for drawing an image on the screen.
- * If It is very customizable, and the documentation below should be studied carefully.
- * For simple applications, use the epdiy highlevel api in "epd_higlevel.h".
- *
- * @param area: The area of the screen to draw to.
- * This can be imagined as shifting the origin of the frame buffer.
- * @param data: A full framebuffer of display data.
- * It's structure depends on the chosen `mode`.
- * @param crop_to: Only draw a part of the frame buffer.
- * Set to `epd_full_screen()` to draw the full buffer.
- * @param mode: Specifies the Waveform used, the framebuffer format
- * and additional information, like if the display is cleared.
- * @param temperature: The temperature of the display in °C.
- * Currently, this is unused by the default waveforms at can be
- * set to room temperature, e.g. 20-25°C.
- * @param drawn_lines: If not NULL, an array of at least the height of the
- * image. Every line where the corresponding value in `lines` is `false` will be
- * skipped.
- * @param waveform: The waveform information to use for drawing.
- * If you don't have special waveforms, use `EPD_BUILTIN_WAVEFORM`.
- * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
- */
-enum EpdDrawError IRAM_ATTR epd_draw_base(EpdRect area,
- const uint8_t *data,
- EpdRect crop_to,
- enum EpdDrawMode mode,
- int temperature,
- const bool *drawn_lines,
- const EpdWaveform *waveform);
-/**
- * Calculate a `MODE_PACKING_1PPB_DIFFERENCE` difference image
- * from two `MODE_PACKING_2PPB` (4 bit-per-pixel) buffers.
- * If you're using the epdiy highlevel api, this is handled by the update functions.
- *
- * @param to: The goal image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
- * @param from: The previous image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
- * @param crop_to: Only calculate the difference for a crop of the input framebuffers.
- * The `interlaced` will not be modified outside the crop area.
- * @param interlaced: The resulting difference image in `MODE_PACKING_1PPB_DIFFERENCE` format.
- * @param dirty_lines: An array of at least `EPD_HEIGHT`.
- * The positions corresponding to lines where `to` and `from` differ
- * are set to `true`, otherwise to `false`.
- * @param previously_white: If not NULL, it is set to `true`
- * if the considered crop of the `from`-image is completely white.
- * @param previously_black: If not NULL, it is set to `true`
- * if the considered crop of the `from`-image is completely black.
- * @returns The smallest rectangle containing all changed pixels.
- */
-EpdRect epd_difference_image_cropped(
- const uint8_t* to,
- const uint8_t* from,
- EpdRect crop_to,
- uint8_t* interlaced,
- bool* dirty_lines,
- bool* previously_white,
- bool* previously_black
-);
-
-/**
- * Simplified version of `epd_difference_image_cropped()`, which considers the
- * whole display frame buffer.
- *
- * See `epd_difference_image_cropped() for details.`
- */
-EpdRect epd_difference_image(const uint8_t* to, const uint8_t* from, uint8_t* interlaced, bool* dirty_lines);
-
-
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_highlevel.h b/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_highlevel.h
deleted file mode 100755
index d22bc0df4..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_highlevel.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/**
- * @file "epd_highlevel.h"
- * @brief High-level API for drawing to e-paper displays.
- *
- * The functions in this library provide a simple way to manage updates of e-paper display.
- * To use it, follow the steps below:
- *
- * 1. First, we declare a global object that manages the display state.
- *
- * EpdiyHighlevelState hl;
- *
- * 2. Then, the driver and framebuffers must be initialized.
- *
- * epd_init(EPD_LUT_1K);
- * hl = epd_hl_init(EPD_BUILTIN_WAVEFORM);
- *
- * 3. Now, we can draw to the allocated framebuffer,
- * using the draw and text functions defined in `epd_driver.h`.
- * This will not yet update the display, but only its representation in memory.
- *
- * // A reference to the framebuffer
- * uint8_t* fb = epd_hl_get_framebuffer(&hl);
- *
- * // draw a black rectangle
- * EpdRect some_rect = {
- * .x = 100,
- * .y = 100,
- * .width = 100,
- * .height = 100
- * };
- * epd_fill_rect(some_rect, 0x0, fb);
- *
- * // write a message
- * int cursor_x = 100;
- * int cursor_y = 300;
- * epd_write_default(&FiraSans, "Hello, World!", &cursor_x, &cursor_y, fb);
- *
- * // finally, update the display!
- * int temperature = 25;
- * epd_poweron();
- * EpdDrawError err = epd_hl_update_screen(&hl, MODE_GC16, temperature);
- * epd_poweroff();
- *
- * That's it! For many application, this will be enough.
- * For special applications and requirements, have a
- * closer look at the `epd_driver.h` header.
- */
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
-#include "epd_driver.h"
-
-/// Holds the internal state of the high-level API.
-typedef struct {
- /// The "front" framebuffer object.
- uint8_t* front_fb;
- /// The "back" framebuffer object.
- uint8_t* back_fb;
- /// Buffer for holding the interlaced difference image.
- uint8_t* difference_fb;
- /// Tainted lines based on the last difference calculation.
- bool* dirty_lines;
- /// The waveform information to use.
- const EpdWaveform* waveform;
-} EpdiyHighlevelState;
-
-
-/**
- * Initialize a state object.
- * This allocates two framebuffers and an update buffer for
- * the display in the external PSRAM.
- * In order to keep things simple, a chip reset is triggered if this fails.
- *
- * @param waveform: The waveform to use for updates.
- * If you did not create your own, this will be `EPD_BUILTIN_WAVEFORM`.
- * @returns An initialized state object.
- */
-EpdiyHighlevelState epd_hl_init(const EpdWaveform* waveform);
-
-/// Get a reference to the front framebuffer.
-/// Use this to draw on the framebuffer before updating the screen with `epd_hl_update_screen()`.
-uint8_t* epd_hl_get_framebuffer(EpdiyHighlevelState* state);
-
-/**
- * Update the EPD screen to match the content of the front frame buffer.
- * Prior to this, power to the display must be enabled via `epd_poweron()`
- * and should be disabled afterwards if no immediate additional updates follow.
- *
- * @param state: A reference to the `EpdiyHighlevelState` object used.
- * @param mode: The update mode to use.
- * Additional mode settings like the framebuffer format or
- * previous display state are determined by the driver and must not be supplied here.
- * In most cases, one of `MODE_GC16` and `MODE_GL16` should be used.
- * @param temperature: Environmental temperature of the display in °C.
- * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
- */
-enum EpdDrawError epd_hl_update_screen(EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature);
-
-/**
- * Update an area of the screen to match the content of the front framebuffer.
- * Supplying a small area to update can speed up the update process.
- * Prior to this, power to the display must be enabled via `epd_poweron()`
- * and should be disabled afterwards if no immediate additional updates follow.
- *
- * @param state: A reference to the `EpdiyHighlevelState` object used.
- * @param mode: See `epd_hl_update_screen()`.
- * @param temperature: Environmental temperature of the display in °C.
- * @param area: Area of the screen to update.
- * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
- */
-enum EpdDrawError epd_hl_update_area(EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature, EpdRect area);
-
-/**
- * Reset the front framebuffer to a white state.
- *
- * @param state: A reference to the `EpdiyHighlevelState` object used.
- */
-void epd_hl_set_all_white(EpdiyHighlevelState* state);
-
-/**
- * Bring the display to a fully white state and get rid of any
- * remaining artifacts.
- */
-void epd_fullclear(EpdiyHighlevelState* state, int temperature);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_internals.h b/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_internals.h
deleted file mode 100755
index 923430579..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/include/epd_internals.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- * @file epd_internals.h
- * @brief Internal definitions and auxiliary data types.
- *
- * Unless you want to extend the library itself (Which you are very welcome to do),
- * you will most likely not need to know about this file.
- */
-
-#ifndef EPD_INTERNALS_H
-#define EPD_INTERNALS_H
-
-#include
-#include
-
-/// minimal draw time in ms for a frame layer,
-/// which will allow all particles to set properly.
-#ifndef MINIMUM_FRAME_TIME
-#define MINIMUM_FRAME_TIME 12
-#endif
-
-/// Frame draw time for monochrome mode in 1/10 us.
-#define MONOCHROME_FRAME_TIME 120
-
-#if defined(CONFIG_EPD_DISPLAY_TYPE_ED097OC4) || \
- defined(CONFIG_EPD_DISPLAY_TYPE_ED097TC2) || \
- defined(CONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ)
-/// Width of the display area in pixels.
-#define EPD_WIDTH 1200
-/// Height of the display area in pixels.
-#define EPD_HEIGHT 825
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED133UT2)
-#define EPD_WIDTH 1600
-#define EPD_HEIGHT 1200
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060SC4)
-/// Width of the display area in pixels.
-#define EPD_WIDTH 800
-/// Height of the display area in pixels.
-#define EPD_HEIGHT 600
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060SCT)
-/// Width of the display area in pixels.
-#define EPD_WIDTH 800
-/// Height of the display area in pixels.
-#define EPD_HEIGHT 600
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060XC3)
-/// Width of the display area in pixels.
-#define EPD_WIDTH 1024
-/// Height of the display area in pixels.
-#define EPD_HEIGHT 758
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED047TC1)
-/// Width of the display area in pixels.
-#define EPD_WIDTH 960
-/// Height of the display area in pixels.
-#define EPD_HEIGHT 540
-#else
-#error "no display type defined!"
-#endif
-
-
-typedef struct {
- int phases;
- const uint8_t* luts;
- /// If we have timing information for the individual
- /// phases, this is an array of the on-times for each phase.
- /// Otherwise, this is NULL.
- const int* phase_times;
-} EpdWaveformPhases;
-
-typedef struct {
- uint8_t type;
- uint8_t temp_ranges;
- EpdWaveformPhases const **range_data;
-} EpdWaveformMode;
-
-typedef struct {
- int min;
- int max;
-} EpdWaveformTempInterval;
-
-typedef struct {
- uint8_t num_modes;
- uint8_t num_temp_ranges;
- EpdWaveformMode const **mode_data;
- EpdWaveformTempInterval const *temp_intervals;
-} EpdWaveform;
-
-
-
-
-extern const EpdWaveform ed047tc2;
-extern const EpdWaveform epdiy_ED060SC4;
-extern const EpdWaveform epdiy_ED097OC4;
-extern const EpdWaveform epdiy_ED047TC1;
-extern const EpdWaveform epdiy_ED097TC2;
-extern const EpdWaveform epdiy_ED060XC3;
-extern const EpdWaveform epdiy_ED060SCT;
-extern const EpdWaveform epdiy_ED133UT2;
-
-#if defined(CONFIG_EPD_DISPLAY_TYPE_ED047TC1)
-//#define EPD_BUILTIN_WAVEFORM &epdiy_ED047TC1
-#define EPD_BUILTIN_WAVEFORM &ed047tc2
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060SC4)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED060SC4
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060XC3)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED060XC3
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED060SCT)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED060SCT
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED097OC4) || defined(CONFIG_EPD_DISPLAY_TYPE_ED097OC4_LQ)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED097OC4
-#elif defined(CONFIG_EPD_DISPLAY_TYPE_ED097TC2)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED097TC2
-#elif defined (CONFIG_EPD_DISPLAY_TYPE_ED133UT2)
-#define EPD_BUILTIN_WAVEFORM &epdiy_ED133UT2
-#endif
-
-/// Font data stored PER GLYPH
-typedef struct {
- uint8_t width; ///< Bitmap dimensions in pixels
- uint8_t height; ///< Bitmap dimensions in pixels
- uint8_t advance_x; ///< Distance to advance cursor (x axis)
- int16_t left; ///< X dist from cursor pos to UL corner
- int16_t top; ///< Y dist from cursor pos to UL corner
- uint16_t compressed_size; ///< Size of the zlib-compressed font data.
- uint32_t data_offset; ///< Pointer into EpdFont->bitmap
-} EpdGlyph;
-
-/// Glyph interval structure
-typedef struct {
- uint32_t first; ///< The first unicode code point of the interval
- uint32_t last; ///< The last unicode code point of the interval
- uint32_t offset; ///< Index of the first code point into the glyph array
-} EpdUnicodeInterval;
-
-/// Data stored for FONT AS A WHOLE
-typedef struct {
- const uint8_t *bitmap; ///< Glyph bitmaps, concatenated
- const EpdGlyph *glyph; ///< Glyph array
- const EpdUnicodeInterval *intervals; ///< Valid unicode intervals for this font
- uint32_t interval_count; ///< Number of unicode intervals.
- bool compressed; ///< Does this font use compressed glyph bitmaps?
- uint8_t advance_y; ///< Newline distance (y axis)
- int ascender; ///< Maximal height of a glyph above the base line
- int descender; ///< Maximal height of a glyph below the base line
-} EpdFont;
-
-
-#endif // EPD_INTERNALS_H
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/lut.c b/lib/libesp32_eink/epdiy/src/epd_driver/lut.c
deleted file mode 100755
index bf1364e33..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/lut.c
+++ /dev/null
@@ -1,617 +0,0 @@
-#include "lut.h"
-#include "display_ops.h"
-#include "esp_log.h"
-#include "freertos/task.h"
-#include
-
-/*
- * Build Lookup tables and translate via LUTs.
- * WARNING: These functions must only ever write to internal memory,
- * Since we disable the PSRAM workaround here for performance reasons.
- */
-
-/* Python script for generating the 1bpp lookup table:
- * for i in range(256):
- number = 0;
- for b in range(8):
- if not (i & (b << 1)):
- number |= 1 << (2*b)
- print ('0x%04x,'%number)
- */
-const static uint32_t lut_1bpp_black[256] = {
- 0x5555, 0x5554, 0x5551, 0x5550, 0x5545, 0x5544, 0x5541, 0x5540, 0x5515,
- 0x5514, 0x5511, 0x5510, 0x5505, 0x5504, 0x5501, 0x5500, 0x5455, 0x5454,
- 0x5451, 0x5450, 0x5445, 0x5444, 0x5441, 0x5440, 0x5415, 0x5414, 0x5411,
- 0x5410, 0x5405, 0x5404, 0x5401, 0x5400, 0x5155, 0x5154, 0x5151, 0x5150,
- 0x5145, 0x5144, 0x5141, 0x5140, 0x5115, 0x5114, 0x5111, 0x5110, 0x5105,
- 0x5104, 0x5101, 0x5100, 0x5055, 0x5054, 0x5051, 0x5050, 0x5045, 0x5044,
- 0x5041, 0x5040, 0x5015, 0x5014, 0x5011, 0x5010, 0x5005, 0x5004, 0x5001,
- 0x5000, 0x4555, 0x4554, 0x4551, 0x4550, 0x4545, 0x4544, 0x4541, 0x4540,
- 0x4515, 0x4514, 0x4511, 0x4510, 0x4505, 0x4504, 0x4501, 0x4500, 0x4455,
- 0x4454, 0x4451, 0x4450, 0x4445, 0x4444, 0x4441, 0x4440, 0x4415, 0x4414,
- 0x4411, 0x4410, 0x4405, 0x4404, 0x4401, 0x4400, 0x4155, 0x4154, 0x4151,
- 0x4150, 0x4145, 0x4144, 0x4141, 0x4140, 0x4115, 0x4114, 0x4111, 0x4110,
- 0x4105, 0x4104, 0x4101, 0x4100, 0x4055, 0x4054, 0x4051, 0x4050, 0x4045,
- 0x4044, 0x4041, 0x4040, 0x4015, 0x4014, 0x4011, 0x4010, 0x4005, 0x4004,
- 0x4001, 0x4000, 0x1555, 0x1554, 0x1551, 0x1550, 0x1545, 0x1544, 0x1541,
- 0x1540, 0x1515, 0x1514, 0x1511, 0x1510, 0x1505, 0x1504, 0x1501, 0x1500,
- 0x1455, 0x1454, 0x1451, 0x1450, 0x1445, 0x1444, 0x1441, 0x1440, 0x1415,
- 0x1414, 0x1411, 0x1410, 0x1405, 0x1404, 0x1401, 0x1400, 0x1155, 0x1154,
- 0x1151, 0x1150, 0x1145, 0x1144, 0x1141, 0x1140, 0x1115, 0x1114, 0x1111,
- 0x1110, 0x1105, 0x1104, 0x1101, 0x1100, 0x1055, 0x1054, 0x1051, 0x1050,
- 0x1045, 0x1044, 0x1041, 0x1040, 0x1015, 0x1014, 0x1011, 0x1010, 0x1005,
- 0x1004, 0x1001, 0x1000, 0x0555, 0x0554, 0x0551, 0x0550, 0x0545, 0x0544,
- 0x0541, 0x0540, 0x0515, 0x0514, 0x0511, 0x0510, 0x0505, 0x0504, 0x0501,
- 0x0500, 0x0455, 0x0454, 0x0451, 0x0450, 0x0445, 0x0444, 0x0441, 0x0440,
- 0x0415, 0x0414, 0x0411, 0x0410, 0x0405, 0x0404, 0x0401, 0x0400, 0x0155,
- 0x0154, 0x0151, 0x0150, 0x0145, 0x0144, 0x0141, 0x0140, 0x0115, 0x0114,
- 0x0111, 0x0110, 0x0105, 0x0104, 0x0101, 0x0100, 0x0055, 0x0054, 0x0051,
- 0x0050, 0x0045, 0x0044, 0x0041, 0x0040, 0x0015, 0x0014, 0x0011, 0x0010,
- 0x0005, 0x0004, 0x0001, 0x0000};
-
-// Timestamp when the last frame draw was started.
-// This is used to enforce a minimum frame draw time, allowing
-// all pixels to set.
-static uint64_t last_frame_start = 0;
-
-inline int min(int x, int y) { return x < y ? x : y; }
-inline int max(int x, int y) { return x > y ? x : y; }
-
-// status tracker for row skipping
-uint32_t skipping;
-
-// output a row to the display.
-void IRAM_ATTR write_row(uint32_t output_time_dus) {
- epd_output_row(output_time_dus);
- skipping = 0;
-}
-
-// skip a display row
-void IRAM_ATTR skip_row(uint8_t pipeline_finish_time) {
- // output previously loaded row, fill buffer with no-ops.
- if (skipping < 2) {
- memset(epd_get_current_buffer(), 0x00, EPD_LINE_BYTES);
- epd_output_row(pipeline_finish_time);
- } else {
- epd_skip();
- }
- skipping++;
-}
-
-void IRAM_ATTR reorder_line_buffer(uint32_t *line_data) {
- for (uint32_t i = 0; i < EPD_LINE_BYTES / 4; i++) {
- uint32_t val = *line_data;
- *(line_data++) = val >> 16 | ((val & 0x0000FFFF) << 16);
- }
-}
-
-static void IRAM_ATTR bit_shift_buffer_right(uint8_t *buf, uint32_t len,
- int shift) {
- uint8_t carry = 0xFF << (8 - shift);
- for (uint32_t i = 0; i < len; i++) {
- uint8_t val = buf[i];
- buf[i] = (val >> shift) | carry;
- carry = val << (8 - shift);
- }
-}
-
-static void IRAM_ATTR nibble_shift_buffer_right(uint8_t *buf, uint32_t len) {
- uint8_t carry = 0xF;
- for (uint32_t i = 0; i < len; i++) {
- uint8_t val = buf[i];
- buf[i] = (val << 4) | carry;
- carry = (val & 0xF0) >> 4;
- }
-}
-
-///////////////////////////// Looking up EPD Pixels
-//////////////////////////////////
-
-static void IRAM_ATTR calc_epd_input_1bpp(const uint32_t *line_data,
- uint8_t *epd_input,
- const uint8_t *lut) {
-
- uint32_t *wide_epd_input = (uint32_t *)epd_input;
- uint8_t *data_ptr = (uint8_t *)line_data;
- uint32_t *lut_32 = (uint32_t *)lut;
- // this is reversed for little-endian, but this is later compensated
- // through the output peripheral.
- for (uint32_t j = 0; j < EPD_WIDTH / 16; j++) {
- uint8_t v1 = *(data_ptr++);
- uint8_t v2 = *(data_ptr++);
- wide_epd_input[j] = (lut_32[v1] << 16) | lut_32[v2];
- }
-}
-
-static void IRAM_ATTR
-calc_epd_input_4bpp_lut_64k(const uint32_t *line_data, uint8_t *epd_input,
- const uint8_t *conversion_lut) {
-
- uint32_t *wide_epd_input = (uint32_t *)epd_input;
- const uint16_t *line_data_16 = (const uint16_t *)line_data;
-
- // this is reversed for little-endian, but this is later compensated
- // through the output peripheral.
- for (uint32_t j = 0; j < EPD_WIDTH / 16; j++) {
-
- uint16_t v1 = *(line_data_16++);
- uint16_t v2 = *(line_data_16++);
- uint16_t v3 = *(line_data_16++);
- uint16_t v4 = *(line_data_16++);
- uint32_t pixel = conversion_lut[v1] << 16 | conversion_lut[v2] << 24 |
- conversion_lut[v3] | conversion_lut[v4] << 8;
- wide_epd_input[j] = pixel;
- }
-}
-
-/**
- * Look up 4 pixels of a differential image.
- */
-static inline uint8_t
-lookup_differential_pixels(uint32_t in, const uint8_t *conversion_lut) {
- uint8_t out = conversion_lut[in & 0xFF];
- in = in >> 8;
- out |= (conversion_lut + 0x100)[in & 0xFF];
- in = in >> 8;
- out |= (conversion_lut + 0x200)[in & 0xFF];
- in = in >> 8;
- out |= (conversion_lut + 0x300)[in];
- return out;
-}
-
-/**
- * Calculate EPD input for a difference image with one pixel per byte.
- */
-static void IRAM_ATTR calc_epd_input_1ppB(const uint32_t *ld,
- uint8_t *epd_input,
- const uint8_t *conversion_lut) {
-
- // this is reversed for little-endian, but this is later compensated
- // through the output peripheral.
- for (uint32_t j = 0; j < EPD_WIDTH / 4; j += 4) {
- epd_input[j + 2] = lookup_differential_pixels(*(ld++), conversion_lut);
- epd_input[j + 3] = lookup_differential_pixels(*(ld++), conversion_lut);
- epd_input[j + 0] = lookup_differential_pixels(*(ld++), conversion_lut);
- epd_input[j + 1] = lookup_differential_pixels(*(ld++), conversion_lut);
- }
-}
-
-/**
- * Look up 4 pixels in a 1K LUT with fixed "from" value.
- */
-static inline uint8_t lookup_pixels_4bpp_1k(uint16_t in,
- const uint8_t *conversion_lut,
- uint8_t from) {
- uint8_t v;
- uint8_t out;
- v = ((in << 4) | from);
- out = conversion_lut[v & 0xFF];
- v = ((in & 0xF0) | from);
- out |= (conversion_lut + 0x100)[v & 0xFF];
- in = in >> 8;
- v = ((in << 4) | from);
- out |= (conversion_lut + 0x200)[v & 0xFF];
- v = ((in & 0xF0) | from);
- out |= (conversion_lut + 0x300)[v];
- return out;
-}
-
-/**
- * Calculate EPD input for a 4bpp buffer, but with a difference image LUT.
- * This is used for small-LUT mode.
- */
-static void IRAM_ATTR calc_epd_input_4bpp_1k_lut(const uint32_t *ld,
- uint8_t *epd_input,
- const uint8_t *conversion_lut,
- uint8_t from) {
-
- uint16_t *ptr = (uint16_t *)ld;
- // this is reversed for little-endian, but this is later compensated
- // through the output peripheral.
- for (uint32_t j = 0; j < EPD_WIDTH / 4; j += 4) {
- epd_input[j + 2] = lookup_pixels_4bpp_1k(*(ptr++), conversion_lut, from);
- epd_input[j + 3] = lookup_pixels_4bpp_1k(*(ptr++), conversion_lut, from);
- epd_input[j + 0] = lookup_pixels_4bpp_1k(*(ptr++), conversion_lut, from);
- epd_input[j + 1] = lookup_pixels_4bpp_1k(*(ptr++), conversion_lut, from);
- }
-}
-
-static void IRAM_ATTR calc_epd_input_4bpp_1k_lut_white(
- const uint32_t *ld, uint8_t *epd_input, const uint8_t *conversion_lut) {
- calc_epd_input_4bpp_1k_lut(ld, epd_input, conversion_lut, 0xF);
-}
-
-static void IRAM_ATTR calc_epd_input_4bpp_1k_lut_black(
- const uint32_t *ld, uint8_t *epd_input, const uint8_t *conversion_lut) {
- calc_epd_input_4bpp_1k_lut(ld, epd_input, conversion_lut, 0x0);
-}
-
-///////////////////////////// Calculate Lookup Tables
-//////////////////////////////////
-
-/**
- * Unpack the waveform data into a lookup table, with bit shifted copies.
- */
-static void IRAM_ATTR waveform_lut(const EpdWaveform *waveform, uint8_t *lut,
- uint8_t mode, int range, int frame) {
- const uint8_t *p_lut =
- waveform->mode_data[mode]->range_data[range]->luts + (16 * 4 * frame);
- for (uint8_t to = 0; to < 16; to++) {
- for (uint8_t from_packed = 0; from_packed < 4; from_packed++) {
- uint8_t index = (to << 4) | (from_packed * 4);
- uint8_t packed = *(p_lut++);
- lut[index] = (packed >> 6) & 3;
- lut[index + 1] = (packed >> 4) & 3;
- lut[index + 2] = (packed >> 2) & 3;
- lut[index + 3] = (packed >> 0) & 3;
- // printf("%2X%2X%2X%2X (%d)", lut[index], lut[index + 1], lut[index + 2],
- // lut[index + 3], index);
- }
- // printf("\n");
- }
- uint32_t index = 0x100;
- for (uint8_t s = 2; s <= 6; s += 2) {
- for (int i = 0; i < 0x100; i++) {
- lut[index] = lut[index % 0x100] << s;
- index++;
- }
- }
-}
-
-/**
- * Build a 16-bit LUT from the waveform if the previous color is
- * known, e.g. all white or all black.
- * This LUT is use to look up 4 pixels at once, as with the epdiy LUT.
- */
-static void IRAM_ATTR waveform_lut_static_from(const EpdWaveform *waveform,
- uint8_t *lut, uint8_t from,
- uint8_t mode, int range,
- int frame) {
- const uint8_t *p_lut =
- waveform->mode_data[mode]->range_data[range]->luts + (16 * 4 * frame);
-
- /// index into the packed "from" row
- uint8_t fi = from >> 2;
- /// bit shift amount for the packed "from" row
- uint8_t fs = 6 - 2 * (from & 3);
-
- // populate the first 4096 bytes
- uint8_t v1 = 0;
- uint32_t s1 = 0;
- for (uint8_t t2 = 0; t2 < 16; t2++) {
- uint8_t v2 = ((p_lut[(t2 << 2) + fi] >> fs) & 0x03) << 4;
- uint32_t s2 = t2 << 8;
- for (uint8_t t3 = 0; t3 < 16; t3++) {
- uint8_t v3 = ((p_lut[(t3 << 2) + fi] >> fs) & 0x03) << 2;
- uint32_t s3 = t3 << 4;
- for (uint8_t t4 = 0; t4 < 16; t4++) {
- uint8_t v4 = ((p_lut[(t4 << 2) + fi] >> fs) & 0x03) << 0;
- uint32_t s4 = t4;
- lut[s1 | s2 | s3 | s4] = v1 | v2 | v3 | v4;
- }
- }
- }
-
- // now just copy and the first 4096 bytes and add the upper two bits
- for (uint8_t t1 = 1; t1 < 16; t1++) {
- memcpy(&lut[t1 << 12], lut, 1 << 12);
- }
-
- for (int i = 0; i < 16; i++) {
- uint32_t v1 = ((p_lut[(i << 2) + fi] >> fs) & 0x03);
- uint32_t mask = (v1 << 30) | (v1 << 22) | (v1 << 14) | (v1 << 6);
- for (int j = 0; j < 16 * 16 * 16 / 4; j++) {
- ((uint32_t *)lut)[(i << 10) + j] |= mask;
- }
- }
-}
-
-void IRAM_ATTR provide_out(OutputParams *params) {
- while (true) {
- // line must be able to hold 2-pixel-per-byte or 1-pixel-per-byte data
- uint8_t line[EPD_WIDTH];
- memset(line, 255, EPD_WIDTH);
-
- xSemaphoreTake(params->start_smphr, portMAX_DELAY);
- EpdRect area = params->area;
- const uint8_t *ptr = params->data_ptr;
- const bool crop = (params->crop_to.width > 0 && params->crop_to.height > 0);
-
- // number of pixels per byte of input data
- int ppB = 0;
- int bytes_per_line = 0;
- int width_divider = 0;
-
- if (params->mode & MODE_PACKING_1PPB_DIFFERENCE) {
- ppB = 1;
- bytes_per_line = area.width;
- width_divider = 1;
- } else if (params->mode & MODE_PACKING_2PPB) {
- ppB = 2;
- bytes_per_line = area.width / 2 + area.width % 2;
- width_divider = 2;
- } else if (params->mode & MODE_PACKING_8PPB) {
- ppB = 8;
- bytes_per_line = (area.width / 8 + (area.width % 8 > 0));
- width_divider = 8;
- } else {
- params->error |= EPD_DRAW_INVALID_PACKING_MODE;
- }
-
- int crop_x = (crop ? params->crop_to.x : 0);
- int crop_y = (crop ? params->crop_to.y : 0);
- int crop_w = (crop ? params->crop_to.width : 0);
- int crop_h = (crop ? params->crop_to.height : 0);
-
- // Adjust for negative starting coordinates with optional crop
- if (area.x - crop_x < 0) {
- ptr += -(area.x - crop_x) / width_divider;
- }
-
- if (area.y - crop_y < 0) {
- ptr += -(area.y - crop_y) * bytes_per_line;
- }
-
- // calculate start and end row with crop
- int min_y = area.y + crop_y;
- int max_y = min(min_y + (crop ? crop_h : area.height), area.height);
- for (int i = 0; i < EPD_HEIGHT; i++) {
- if (i < min_y || i >= max_y) {
- continue;
- }
- if (params->drawn_lines != NULL && !params->drawn_lines[i - area.y]) {
- ptr += bytes_per_line;
- continue;
- }
-
- uint32_t *lp = (uint32_t *)line;
- bool shifted = false;
- if (area.width == EPD_WIDTH && area.x == 0 && !crop && !params->error) {
- lp = (uint32_t *)ptr;
- ptr += bytes_per_line;
- } else if (!params->error) {
- uint8_t *buf_start = (uint8_t *)line;
- uint32_t line_bytes = bytes_per_line;
-
- int min_x = area.x + crop_x;
- if (min_x >= 0) {
- buf_start += min_x / width_divider;
- } else {
- // reduce line_bytes to actually used bytes
- // ptr was already adjusted above
- line_bytes += min_x / width_divider;
- }
- line_bytes = min(line_bytes, EPD_WIDTH / width_divider -
- (uint32_t)(buf_start - line));
- memcpy(buf_start, ptr, line_bytes);
- ptr += bytes_per_line;
-
- int cropped_width = (crop ? crop_w : area.width);
- /// consider half-byte shifts in two-pixel-per-Byte mode.
- if (ppB == 2) {
- // mask last nibble for uneven width
- if (cropped_width % 2 == 1 &&
- min_x / 2 + cropped_width / 2 + 1 < EPD_WIDTH) {
- *(buf_start + line_bytes - 1) |= 0xF0;
- }
- if (area.x % 2 == 1 && !(crop_x % 2 == 1) && min_x < EPD_WIDTH) {
- shifted = true;
- uint32_t remaining =
- (uint32_t)line + EPD_WIDTH / 2 - (uint32_t)buf_start;
- uint32_t to_shift = min(line_bytes + 1, remaining);
- // shift one nibble to right
- nibble_shift_buffer_right(buf_start, to_shift);
- }
- // consider bit shifts in bit buffers
- } else if (ppB == 8) {
- // mask last n bits if width is not divisible by 8
- if (cropped_width % 8 != 0 && bytes_per_line + 1 < EPD_WIDTH) {
- uint8_t mask = 0;
- for (int s = 0; s < cropped_width % 8; s++) {
- mask = (mask << 1) | 1;
- }
- *(buf_start + line_bytes - 1) |= ~mask;
- }
-
- if (min_x % 8 != 0 && min_x < EPD_WIDTH) {
- // shift to right
- shifted = true;
- uint32_t remaining =
- (uint32_t)line + EPD_WIDTH / 8 - (uint32_t)buf_start;
- uint32_t to_shift = min(line_bytes + 1, remaining);
- bit_shift_buffer_right(buf_start, to_shift, min_x % 8);
- }
- }
- lp = (uint32_t *)line;
- }
- xQueueSendToBack(*params->output_queue, lp, portMAX_DELAY);
- if (shifted) {
- memset(line, 255, EPD_WIDTH / width_divider);
- }
- }
-
- xSemaphoreGive(params->done_smphr);
- }
-}
-
-/**
- * Set all pixels not in [xmin,xmax) to nop in the current line buffer.
- */
-static void IRAM_ATTR mask_line_buffer(int xmin, int xmax) {
- // lower bound to where byte order is not an issue.
- int memset_start = (xmin / 16) * 4;
- int memset_end = min(((xmax + 15) / 16) * 4, EPD_LINE_BYTES);
- uint8_t *lb = epd_get_current_buffer();
-
- // memset the areas where order is not an issue
- memset(lb, 0, memset_start);
- memset(lb + memset_end, 0, EPD_LINE_BYTES - memset_end);
-
- const int offset_table[4] = {2, 3, 0, 1};
-
- // mask unused pixels at the start of the output interval
- uint8_t line_start_mask = 0xFF << (2 * (xmin % 4));
- uint8_t line_end_mask = 0xFF >> (8 - 2 * (xmax % 4));
-
- // number of full bytes to mask
- int lower_full_bytes = max(0, (xmin / 4 - memset_start));
- int upper_full_bytes = max(0, (memset_end - ((xmax + 3) / 4)));
- assert(lower_full_bytes <= 3);
- assert(upper_full_bytes <= 3);
- assert(memset_end >= 4);
-
- // mask full bytes
- for (int i = 0; i < lower_full_bytes; i++) {
- lb[memset_start + offset_table[i]] = 0x0;
- }
- for (int i = 0; i < upper_full_bytes; i++) {
- lb[memset_end - 4 + offset_table[3 - i]] = 0x0;
- }
-
- // mask partial bytes
- if ((memset_start + lower_full_bytes) * 4 < xmin) {
- epd_get_current_buffer()[memset_start + offset_table[lower_full_bytes]] &=
- line_start_mask;
- }
- if ((memset_end - upper_full_bytes) * 4 > xmax) {
- epd_get_current_buffer()[memset_end - 4 +
- offset_table[3 - upper_full_bytes]] &=
- line_end_mask;
- }
-}
-
-void IRAM_ATTR busy_delay(uint32_t cycles);
-
-static enum EpdDrawError calculate_lut(OutputParams *params) {
-
- enum EpdDrawMode mode = params->mode;
- enum EpdDrawMode selected_mode = mode & 0x3F;
-
- // two pixel per byte packing with only target color
- if (mode & MODE_PACKING_2PPB && mode & PREVIOUSLY_WHITE &&
- params->conversion_lut_size == (1 << 16)) {
- waveform_lut_static_from(params->waveform, params->conversion_lut, 0x0F,
- params->waveform_index, params->waveform_range,
- params->frame);
- } else if (mode & MODE_PACKING_2PPB && mode & PREVIOUSLY_BLACK &&
- params->conversion_lut_size == (1 << 16)) {
- waveform_lut_static_from(params->waveform, params->conversion_lut, 0x00,
- params->waveform_index, params->waveform_range,
- params->frame);
-
- // one pixel per byte with from and to colors
- } else if (mode & MODE_PACKING_1PPB_DIFFERENCE ||
- (mode & MODE_PACKING_2PPB &&
- params->conversion_lut_size == (1 << 10))) {
- waveform_lut(params->waveform, params->conversion_lut,
- params->waveform_index, params->waveform_range, params->frame);
-
- // 1bit per pixel monochrome with only target color
- } else if (mode & MODE_PACKING_8PPB &&
- selected_mode == MODE_EPDIY_MONOCHROME) {
- // FIXME: Pack into waveform?
- if (mode & PREVIOUSLY_WHITE) {
- memcpy(params->conversion_lut, lut_1bpp_black, sizeof(lut_1bpp_black));
- } else if (mode & PREVIOUSLY_BLACK) {
- // FIXME: implement!
- // memcpy(params->conversion_lut, lut_1bpp_white, sizeof(lut_1bpp_white));
- return EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- } else {
- return EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- }
-
- // unknown format.
- } else {
- return EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- }
- return EPD_DRAW_SUCCESS;
-}
-
-void IRAM_ATTR feed_display(OutputParams *params) {
- while (true) {
- xSemaphoreTake(params->start_smphr, portMAX_DELAY);
-
- skipping = 0;
- EpdRect area = params->area;
- enum EpdDrawMode mode = params->mode;
- int frame_time = params->frame_time;
-
- params->error |= calculate_lut(params);
-
- void (*input_calc_func)(const uint32_t *, uint8_t *, const uint8_t *) =
- NULL;
- if (mode & MODE_PACKING_2PPB) {
- if (params->conversion_lut_size == 1024) {
- if (mode & PREVIOUSLY_WHITE) {
- input_calc_func = &calc_epd_input_4bpp_1k_lut_white;
- } else if (mode & PREVIOUSLY_BLACK) {
- input_calc_func = &calc_epd_input_4bpp_1k_lut_black;
- } else {
- params->error |= EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- }
- } else if (params->conversion_lut_size == (1 << 16)) {
- input_calc_func = &calc_epd_input_4bpp_lut_64k;
- } else {
- params->error |= EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- }
- } else if (mode & MODE_PACKING_1PPB_DIFFERENCE) {
- input_calc_func = &calc_epd_input_1ppB;
- } else if (mode & MODE_PACKING_8PPB) {
- input_calc_func = &calc_epd_input_1bpp;
- } else {
- params->error |= EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
- }
-
- // Adjust min and max row for crop.
- const bool crop = (params->crop_to.width > 0 && params->crop_to.height > 0);
- int crop_y = (crop ? params->crop_to.y : 0);
- int min_y = area.y + crop_y;
- int max_y = min(min_y + (crop ? params->crop_to.height : area.height), area.height);
-
- // interval of the output line that is needed
- // FIXME: only lookup needed parts
- int line_start_x = area.x + (crop ? params->crop_to.x : 0);
- int line_end_x = line_start_x + (crop ? params->crop_to.width : area.width);
- line_start_x = min(max(line_start_x, 0), EPD_WIDTH);
- line_end_x = min(max(line_end_x, 0), EPD_WIDTH);
-
- uint64_t now = esp_timer_get_time();
- uint64_t diff = (now - last_frame_start) / 1000;
- if (diff < MINIMUM_FRAME_TIME) {
- vTaskDelay(MINIMUM_FRAME_TIME - diff);
- }
-
- last_frame_start = esp_timer_get_time();
-
- epd_start_frame();
- for (int i = 0; i < EPD_HEIGHT; i++) {
- if (i < min_y || i >= max_y) {
- skip_row(frame_time);
- continue;
- }
- if (params->drawn_lines != NULL && !params->drawn_lines[i - area.y]) {
- skip_row(frame_time);
- continue;
- }
-
- uint8_t output[EPD_WIDTH];
- xQueueReceive(*params->output_queue, output, portMAX_DELAY);
- if (!params->error) {
- (*input_calc_func)((uint32_t *)output, epd_get_current_buffer(),
- params->conversion_lut);
- if (line_start_x > 0 || line_end_x < EPD_WIDTH) {
- mask_line_buffer(line_start_x, line_end_x);
- }
- }
- write_row(frame_time);
- }
- if (!skipping) {
- // Since we "pipeline" row output, we still have to latch out the last
- // row.
- write_row(frame_time);
- }
- epd_end_frame();
-
- xSemaphoreGive(params->done_smphr);
- }
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/lut.h b/lib/libesp32_eink/epdiy/src/epd_driver/lut.h
deleted file mode 100755
index 0d3c6b533..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/lut.h
+++ /dev/null
@@ -1,54 +0,0 @@
-#pragma once
-
-#include "esp_attr.h"
-#include
-#include "freertos/FreeRTOS.h"
-#include "freertos/semphr.h"
-#include "freertos/queue.h"
-#include "epd_driver.h"
-
-// number of bytes needed for one line of EPD pixel data.
-#define EPD_LINE_BYTES EPD_WIDTH / 4
-
-///////////////////////////// Utils /////////////////////////////////////
-
-/*
- * Reorder the output buffer to account for I2S FIFO order.
- */
-void IRAM_ATTR reorder_line_buffer(uint32_t *line_data);
-
-typedef struct {
- const uint8_t *data_ptr;
- EpdRect crop_to;
- SemaphoreHandle_t done_smphr;
- SemaphoreHandle_t start_smphr;
- EpdRect area;
- int frame;
- /// index of the waveform mode when using vendor waveforms.
- /// This is not necessarily the mode number if the waveform header
- //only contains a selection of modes!
- int waveform_index;
- /// waveform range when using vendor waveforms
- int waveform_range;
- /// Draw time for the current frame in 1/10ths of us.
- int frame_time;
- const EpdWaveform* waveform;
- enum EpdDrawMode mode;
- enum EpdDrawError error;
- const bool *drawn_lines;
- // Queue of input data lines
- QueueHandle_t* output_queue;
-
- // Lookup table size.
- size_t conversion_lut_size;
- // Lookup table space.
- uint8_t* conversion_lut;
-} OutputParams;
-
-
-void IRAM_ATTR feed_display(OutputParams *params);
-void IRAM_ATTR provide_out(OutputParams *params);
-
-
-void IRAM_ATTR write_row(uint32_t output_time_dus);
-void IRAM_ATTR skip_row(uint8_t pipeline_finish_time);
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/render.c b/lib/libesp32_eink/epdiy/src/epd_driver/render.c
deleted file mode 100755
index d7271cce3..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/render.c
+++ /dev/null
@@ -1,382 +0,0 @@
-#include "epd_temperature.h"
-#include "display_ops.h"
-#include "epd_driver.h"
-#include "include/epd_driver.h"
-#include "include/epd_internals.h"
-#include "lut.h"
-
-#include "driver/rtc_io.h"
-#include "esp_types.h"
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/queue.h"
-#include "freertos/semphr.h"
-#include "freertos/task.h"
-#include "xtensa/core-macros.h"
-#include
-
-inline int min(int x, int y) { return x < y ? x : y; }
-inline int max(int x, int y) { return x > y ? x : y; }
-
-const int clear_cycle_time = 12;
-
-const int DEFAULT_FRAME_TIME = 120;
-
-#define RTOS_ERROR_CHECK(x) \
- do { \
- esp_err_t __err_rc = (x); \
- if (__err_rc != pdPASS) { \
- abort(); \
- } \
- } while (0)
-
-#define CLEAR_BYTE 0B10101010
-#define DARK_BYTE 0B01010101
-
-// Queue of input data lines
-static QueueHandle_t output_queue;
-
-static OutputParams fetch_params;
-static OutputParams feed_params;
-
-// Space to use for the EPD output lookup table, which
-// is calculated for each cycle.
-static uint8_t* conversion_lut;
-
-void epd_push_pixels(EpdRect area, short time, int color) {
-
- uint8_t row[EPD_LINE_BYTES] = {0};
-
- const uint8_t color_choice[4] = {DARK_BYTE, CLEAR_BYTE, 0x00, 0xFF};
- for (uint32_t i = 0; i < area.width; i++) {
- uint32_t position = i + area.x % 4;
- uint8_t mask = color_choice[color] & (0b00000011 << (2 * (position % 4)));
- row[area.x / 4 + position / 4] |= mask;
- }
- reorder_line_buffer((uint32_t *)row);
-
- epd_start_frame();
-
- for (int i = 0; i < EPD_HEIGHT; i++) {
- // before are of interest: skip
- if (i < area.y) {
- skip_row(time);
- // start area of interest: set row data
- } else if (i == area.y) {
- epd_switch_buffer();
- memcpy(epd_get_current_buffer(), row, EPD_LINE_BYTES);
- epd_switch_buffer();
- memcpy(epd_get_current_buffer(), row, EPD_LINE_BYTES);
-
- write_row(time * 10);
- // load nop row if done with area
- } else if (i >= area.y + area.height) {
- skip_row(time);
- // output the same as before
- } else {
- write_row(time * 10);
- }
- }
- // Since we "pipeline" row output, we still have to latch out the last row.
- write_row(time * 10);
-
- epd_end_frame();
-}
-
-
-///////////////////////////// Coordination ///////////////////////////////
-
-
-/**
- * Find the waveform temperature range index for a given temperature in °C.
- * If no range in the waveform data fits the given temperature, return the
- * closest one.
- * Returns -1 if the waveform does not contain any temperature range.
- */
-int waveform_temp_range_index(const EpdWaveform* waveform, int temperature) {
- int idx = 0;
- if (waveform->num_temp_ranges == 0) {
- return -1;
- }
- while (idx < waveform->num_temp_ranges - 1
- && waveform->temp_intervals[idx].min < temperature) {
- idx++;
- }
- return idx;
-}
-
-//////////////////////////////// API Procedures //////////////////////////////////
-
-static int get_waveform_index(const EpdWaveform* waveform, enum EpdDrawMode mode) {
- for (int i=0; i < waveform->num_modes; i++) {
- if (waveform->mode_data[i]->type == (mode & 0x3F)) {
- return i;
- }
- }
- return -1;
-}
-
-enum EpdDrawError IRAM_ATTR epd_draw_base(EpdRect area,
- const uint8_t *data,
- EpdRect crop_to,
- enum EpdDrawMode mode,
- int temperature,
- const bool *drawn_lines,
- const EpdWaveform *waveform) {
- uint8_t line[EPD_WIDTH / 2];
- memset(line, 255, EPD_WIDTH / 2);
-
- int waveform_range = waveform_temp_range_index(waveform, temperature);
- if (waveform_range < 0) {
- return EPD_DRAW_NO_PHASES_AVAILABLE;
- }
- int waveform_index = 0;
- uint8_t frame_count = 0;
- const EpdWaveformPhases* waveform_phases = NULL;
-
- // no waveform required for monochrome mode
- if (!(mode & MODE_EPDIY_MONOCHROME)) {
- waveform_index = get_waveform_index(waveform, mode);
- if (waveform_index < 0) {
- return EPD_DRAW_MODE_NOT_FOUND;
- }
-
- waveform_phases = waveform->mode_data[waveform_index]
- ->range_data[waveform_range];
- // FIXME: error if not present
- frame_count = waveform_phases->phases;
- } else {
- frame_count = 1;
- }
-
- if (crop_to.width < 0 || crop_to.height < 0) {
- return EPD_DRAW_INVALID_CROP;
- }
-
- const bool crop = (crop_to.width > 0 && crop_to.height > 0);
- if (crop && (crop_to.width > area.width
- || crop_to.height > area.height
- || crop_to.x > area.width
- || crop_to.y > area.height)) {
- return EPD_DRAW_INVALID_CROP;
- }
-
- for (uint8_t k = 0; k < frame_count; k++) {
-
- int frame_time = DEFAULT_FRAME_TIME;
- if (waveform_phases != NULL && waveform_phases->phase_times != NULL) {
- frame_time = waveform_phases->phase_times[k];
- }
-
- if (mode & MODE_EPDIY_MONOCHROME) {
- frame_time = MONOCHROME_FRAME_TIME;
- }
-
- fetch_params.area = area;
- // IMPORTANT: This must only ever read from PSRAM,
- // Since the PSRAM workaround is disabled for lut.c
- fetch_params.data_ptr = data;
- fetch_params.crop_to = crop_to;
- fetch_params.frame = k;
- fetch_params.waveform_range = waveform_range;
- fetch_params.waveform_index = waveform_index;
- fetch_params.frame_time = frame_time;
- fetch_params.mode = mode;
- fetch_params.waveform = waveform;
- fetch_params.error = EPD_DRAW_SUCCESS;
- fetch_params.drawn_lines = drawn_lines;
- fetch_params.output_queue = &output_queue;
-
- feed_params.area = area;
- feed_params.data_ptr = data;
- feed_params.crop_to = crop_to;
- feed_params.frame = k;
- feed_params.frame_time = frame_time;
- feed_params.waveform_range = waveform_range;
- feed_params.waveform_index = waveform_index;
- feed_params.mode = mode;
- feed_params.waveform = waveform;
- feed_params.error = EPD_DRAW_SUCCESS;
- feed_params.drawn_lines = drawn_lines;
- feed_params.output_queue = &output_queue;
-
- xSemaphoreGive(fetch_params.start_smphr);
- xSemaphoreGive(feed_params.start_smphr);
- xSemaphoreTake(fetch_params.done_smphr, portMAX_DELAY);
- xSemaphoreTake(feed_params.done_smphr, portMAX_DELAY);
-
- enum EpdDrawError all_errors = fetch_params.error | feed_params.error;
- if (all_errors != EPD_DRAW_SUCCESS) {
- return all_errors;
- }
- }
- return EPD_DRAW_SUCCESS;
-}
-
-void epd_clear_area(EpdRect area) {
- epd_clear_area_cycles(area, 3, clear_cycle_time);
-}
-
-void epd_clear_area_cycles(EpdRect area, int cycles, int cycle_time) {
- const short white_time = cycle_time;
- const short dark_time = cycle_time;
-
- for (int c = 0; c < cycles; c++) {
- for (int i = 0; i < 10; i++) {
- epd_push_pixels(area, dark_time, 0);
- }
- for (int i = 0; i < 10; i++) {
- epd_push_pixels(area, white_time, 1);
- }
- }
-}
-
-
-
-void epd_init(enum EpdInitOptions options) {
- epd_base_init(EPD_WIDTH);
- epd_temperature_init();
-
- size_t lut_size = 0;
- if (options & EPD_LUT_1K) {
- lut_size = 1 << 10;
- } else if ((options & EPD_LUT_64K) || (options == EPD_OPTIONS_DEFAULT)) {
- lut_size = 1 << 16;
- } else {
- ESP_LOGE("epd", "invalid init options: %d", options);
- return;
- }
-
- conversion_lut = (uint8_t *)heap_caps_malloc(lut_size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
- if (conversion_lut == NULL) {
- ESP_LOGE("epd", "could not allocate LUT!");
- }
- assert(conversion_lut != NULL);
-
- fetch_params.conversion_lut = conversion_lut;
- fetch_params.conversion_lut_size = lut_size;
- feed_params.conversion_lut = conversion_lut;
- feed_params.conversion_lut_size = lut_size;
-
- fetch_params.done_smphr = xSemaphoreCreateBinary();
- fetch_params.start_smphr = xSemaphoreCreateBinary();
-
- feed_params.done_smphr = xSemaphoreCreateBinary();
- feed_params.start_smphr = xSemaphoreCreateBinary();
-
- RTOS_ERROR_CHECK(xTaskCreatePinnedToCore((void (*)(void *))provide_out,
- "epd_fetch", (1 << 12), &fetch_params, 5,
- NULL, 0));
-
- RTOS_ERROR_CHECK(xTaskCreatePinnedToCore((void (*)(void *))feed_display,
- "epd_feed", 1 << 12, &feed_params,
- 5, NULL, 1));
-
- //conversion_lut = (uint8_t *)heap_caps_malloc(1 << 16, MALLOC_CAP_8BIT);
- //assert(conversion_lut != NULL);
- int queue_len = 32;
- if (options & EPD_FEED_QUEUE_32) {
- queue_len = 32;
- } else if (options & EPD_FEED_QUEUE_8) {
- queue_len = 8;
- }
- output_queue = xQueueCreate(queue_len, EPD_WIDTH);
-}
-
-void epd_deinit() {
- // FIXME: deinit processes
-#if defined(CONFIG_EPD_BOARD_REVISION_V5)
- gpio_reset_pin(CKH);
- rtc_gpio_isolate(CKH);
-#endif
- epd_base_deinit();
-}
-
-
-EpdRect epd_difference_image_base(
- const uint8_t* to,
- const uint8_t* from,
- EpdRect crop_to,
- int fb_width,
- int fb_height,
- uint8_t* interlaced,
- bool* dirty_lines,
- uint8_t* from_or,
- uint8_t* from_and
-) {
- assert(from_or != NULL);
- assert(from_and != NULL);
- // OR over all pixels of the "from"-image
- *from_or = 0x00;
- // AND over all pixels of the "from"-image
- *from_and = 0xFF;
-
- uint8_t dirty_cols[EPD_WIDTH] = {0};
- int x_end = min(fb_width, crop_to.x + crop_to.width);
- int y_end = min(fb_height, crop_to.y + crop_to.height);
-
- for (int y=crop_to.y; y < y_end; y++) {
- uint8_t dirty = 0;
- for (int x = crop_to.x; x < x_end; x++) {
- uint8_t t = *(to + y*fb_width / 2 + x / 2);
- t = (x % 2) ? (t >> 4) : (t & 0x0f);
- uint8_t f = *(from + y*fb_width / 2+ x / 2);
- *from_or |= f;
- *from_and &= f;
- f = (x % 2) ? (f >> 4) : (f & 0x0f);
- dirty |= (t ^ f);
- dirty_cols[x] |= (t ^ f);
- interlaced[y * fb_width + x] = (t << 4) | f;
- }
- dirty_lines[y] = dirty > 0;
- }
- int min_x, min_y, max_x, max_y;
- for (min_x = crop_to.x; min_x < x_end; min_x++) {
- if (dirty_cols[min_x] != 0) break;
- }
- for (max_x = x_end - 1; max_x >= crop_to.x; max_x--) {
- if (dirty_cols[max_x] != 0) break;
- }
- for (min_y = crop_to.y; min_y < y_end; min_y++) {
- if (dirty_lines[min_y] != 0) break;
- }
- for (max_y = y_end - 1; max_y >= crop_to.y; max_y--) {
- if (dirty_lines[max_y] != 0) break;
- }
- EpdRect crop_rect = {
- .x = min_x,
- .y = min_y,
- .width = max(max_x - min_x + 1, 0),
- .height = max(max_y - min_y + 1, 0),
- };
- return crop_rect;
-}
-
-EpdRect epd_difference_image(
- const uint8_t* to,
- const uint8_t* from,
- uint8_t* interlaced,
- bool* dirty_lines
-) {
- uint8_t from_or = 0;
- uint8_t from_and = 0;
- return epd_difference_image_base(to, from, epd_full_screen(), EPD_WIDTH, EPD_HEIGHT, interlaced, dirty_lines, &from_or, &from_and);
-}
-
-EpdRect epd_difference_image_cropped(
- const uint8_t* to,
- const uint8_t* from,
- EpdRect crop_to,
- uint8_t* interlaced,
- bool* dirty_lines,
- bool* previously_white,
- bool* previously_black
-) {
- uint8_t from_or, from_and;
-
- EpdRect result = epd_difference_image_base(to, from, crop_to, EPD_WIDTH, EPD_HEIGHT, interlaced, dirty_lines, &from_or, &from_and);
-
- if (previously_white != NULL) *previously_white = (from_and == 0xFF);
- if (previously_black != NULL) *previously_black = (from_or == 0x00);
- return result;
-}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.c b/lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.c
deleted file mode 100755
index 8e93496f4..000000000
--- a/lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include "rmt_pulse.h"
-#include "driver/rmt.h"
-#include "esp_system.h"
-
-static intr_handle_t gRMT_intr_handle = NULL;
-
-// the RMT channel configuration object
-static rmt_config_t row_rmt_config;
-
-// keep track of wether the current pulse is ongoing
-volatile bool rmt_tx_done = true;
-
-/**
- * Remote peripheral interrupt. Used to signal when transmission is done.
- */
-static void IRAM_ATTR rmt_interrupt_handler(void *arg) {
- rmt_tx_done = true;
- RMT.int_clr.val = RMT.int_st.val;
-}
-
-void rmt_pulse_init(gpio_num_t pin) {
-
- row_rmt_config.rmt_mode = RMT_MODE_TX;
- // currently hardcoded: use channel 0
- row_rmt_config.channel = RMT_CHANNEL_1;
-
- row_rmt_config.gpio_num = pin;
- row_rmt_config.mem_block_num = 2;
-
- // Divide 80MHz APB Clock by 8 -> .1us resolution delay
- row_rmt_config.clk_div = 8;
-
- row_rmt_config.tx_config.loop_en = false;
- row_rmt_config.tx_config.carrier_en = false;
- row_rmt_config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
- row_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
- row_rmt_config.tx_config.idle_output_en = true;
-
- #if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) && ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 0, 2)
- #error "This driver is not compatible with IDF version 4.1.\nPlease use 4.0 or >= 4.2!"
- #endif
- esp_intr_alloc(ETS_RMT_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3,
- rmt_interrupt_handler, 0, &gRMT_intr_handle);
-
- rmt_config(&row_rmt_config);
- rmt_set_tx_intr_en(row_rmt_config.channel, true);
-}
-
-void IRAM_ATTR pulse_ckv_ticks(uint16_t high_time_ticks,
- uint16_t low_time_ticks, bool wait) {
- while (!rmt_tx_done) {
- };
- volatile rmt_item32_t *rmt_mem_ptr =
- &(RMTMEM.chan[row_rmt_config.channel].data32[0]);
- if (high_time_ticks > 0) {
- rmt_mem_ptr->level0 = 1;
- rmt_mem_ptr->duration0 = high_time_ticks;
- rmt_mem_ptr->level1 = 0;
- rmt_mem_ptr->duration1 = low_time_ticks;
- } else {
- rmt_mem_ptr->level0 = 1;
- rmt_mem_ptr->duration0 = low_time_ticks;
- rmt_mem_ptr->level1 = 0;
- rmt_mem_ptr->duration1 = 0;
- }
- RMTMEM.chan[row_rmt_config.channel].data32[1].val = 0;
- rmt_tx_done = false;
- RMT.conf_ch[row_rmt_config.channel].conf1.mem_rd_rst = 1;
- RMT.conf_ch[row_rmt_config.channel].conf1.mem_owner = RMT_MEM_OWNER_TX;
- RMT.conf_ch[row_rmt_config.channel].conf1.tx_start = 1;
- while (wait && !rmt_tx_done) {
- };
-}
-
-void IRAM_ATTR pulse_ckv_us(uint16_t high_time_us, uint16_t low_time_us,
- bool wait) {
- pulse_ckv_ticks(10 * high_time_us, 10 * low_time_us, wait);
-}
-
-bool IRAM_ATTR rmt_busy() { return !rmt_tx_done; }
diff --git a/lib/libesp32_eink/epdiy/src/epd_highlevel.h b/lib/libesp32_eink/epdiy/src/epd_highlevel.h
index 092fe2556..4a253a2c2 100755
--- a/lib/libesp32_eink/epdiy/src/epd_highlevel.h
+++ b/lib/libesp32_eink/epdiy/src/epd_highlevel.h
@@ -1,4 +1,157 @@
+/**
+ * @file "epd_highlevel.h"
+ * @brief High-level API for drawing to e-paper displays.
+ *
+ * The functions in this library provide a simple way to manage updates of e-paper display.
+ * To use it, follow the steps below:
+ *
+ * 1. First, we declare a global object that manages the display state.
+ *
+ * EpdiyHighlevelState hl;
+ *
+ * 2. Then, the driver and framebuffers must be initialized.
+ *
+ * epd_init(EPD_LUT_1K);
+ * hl = epd_hl_init(EPD_BUILTIN_WAVEFORM);
+ *
+ * 3. Now, we can draw to the allocated framebuffer,
+ * using the draw and text functions defined in `epdiy.h`.
+ * This will not yet update the display, but only its representation in memory.
+ *
+ * // A reference to the framebuffer
+ * uint8_t* fb = epd_hl_get_framebuffer(&hl);
+ *
+ * // draw a black rectangle
+ * EpdRect some_rect = {
+ * .x = 100,
+ * .y = 100,
+ * .width = 100,
+ * .height = 100
+ * };
+ * epd_fill_rect(some_rect, 0x0, fb);
+ *
+ * // write a message
+ * int cursor_x = 100;
+ * int cursor_y = 300;
+ * epd_write_default(&FiraSans, "Hello, World!", &cursor_x, &cursor_y, fb);
+ *
+ * // finally, update the display!
+ * int temperature = 25;
+ * epd_poweron();
+ * EpdDrawError err = epd_hl_update_screen(&hl, MODE_GC16, temperature);
+ * epd_poweroff();
+ *
+ * That's it! For many application, this will be enough.
+ * For special applications and requirements, have a
+ * closer look at the `epdiy.h` header.
+ *
+ * Colors
+ * ======
+ *
+ * Since most displays only support 16 colors, we're only using the upper 4 bits (nibble) of a byte
+ * to detect the color.
+ *
+ * char pixel_color = color & 0xF0;
+ *
+ * So keep in mind, when passing a color to any function, to always set the upper 4 bits, otherwise
+ * the color would be black.
+ *
+ * Possible colors are `0xF0` (white) through `0x80` (median gray) til `0x00` (black).
+ */
+
+#ifdef __cplusplus
+extern "C" {
+
+#endif
#pragma once
-// This file is only used in the Arduino IDE
-// and just includes the IDF component header.
-#include "epd_driver/include/epd_highlevel.h"
+#include
+#include "epdiy.h"
+
+#define EPD_BUILTIN_WAVEFORM NULL
+
+/// Holds the internal state of the high-level API.
+typedef struct {
+ /// The "front" framebuffer object.
+ uint8_t* front_fb;
+ /// The "back" framebuffer object.
+ uint8_t* back_fb;
+ /// Buffer for holding the interlaced difference image.
+ uint8_t* difference_fb;
+ /// Tainted lines based on the last difference calculation.
+ bool* dirty_lines;
+ /// Tainted column nibbles based on the last difference calculation.
+ uint8_t* dirty_columns;
+ /// The waveform information to use.
+ const EpdWaveform* waveform;
+} EpdiyHighlevelState;
+
+/**
+ * Initialize a state object.
+ * This allocates two framebuffers and an update buffer for
+ * the display in the external PSRAM.
+ * In order to keep things simple, a chip reset is triggered if this fails.
+ *
+ * @param waveform: The waveform to use for updates.
+ * If you did not create your own, this will be `EPD_BUILTIN_WAVEFORM`.
+ * @returns An initialized state object.
+ */
+EpdiyHighlevelState epd_hl_init(const EpdWaveform* waveform);
+
+/// Get a reference to the front framebuffer.
+/// Use this to draw on the framebuffer before updating the screen with `epd_hl_update_screen()`.
+uint8_t* epd_hl_get_framebuffer(EpdiyHighlevelState* state);
+
+/**
+ * Update the EPD screen to match the content of the front frame buffer.
+ * Prior to this, power to the display must be enabled via `epd_poweron()`
+ * and should be disabled afterwards if no immediate additional updates follow.
+ *
+ * @param state: A reference to the `EpdiyHighlevelState` object used.
+ * @param mode: The update mode to use.
+ * Additional mode settings like the framebuffer format or
+ * previous display state are determined by the driver and must not be supplied here.
+ * In most cases, one of `MODE_GC16` and `MODE_GL16` should be used.
+ * @param temperature: Environmental temperature of the display in °C.
+ * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
+ */
+enum EpdDrawError epd_hl_update_screen(
+ EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature
+);
+
+/**
+ * Update an area of the screen to match the content of the front framebuffer.
+ * Supplying a small area to update can speed up the update process.
+ * Prior to this, power to the display must be enabled via `epd_poweron()`
+ * and should be disabled afterwards if no immediate additional updates follow.
+ *
+ * @param state: A reference to the `EpdiyHighlevelState` object used.
+ * @param mode: See `epd_hl_update_screen()`.
+ * @param temperature: Environmental temperature of the display in °C.
+ * @param area: Area of the screen to update.
+ * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
+ */
+enum EpdDrawError epd_hl_update_area(
+ EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature, EpdRect area
+);
+
+/**
+ * Reset the front framebuffer to a white state.
+ *
+ * @param state: A reference to the `EpdiyHighlevelState` object used.
+ */
+void epd_hl_set_all_white(EpdiyHighlevelState* state);
+
+/**
+ * Bring the display to a fully white state and get rid of any
+ * remaining artifacts.
+ */
+void epd_fullclear(EpdiyHighlevelState* state, int temperature);
+
+/**
+ * Just changes the used Waveform
+ */
+void epd_hl_waveform(EpdiyHighlevelState* state, const EpdWaveform* waveform);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/epd_internals.h b/lib/libesp32_eink/epdiy/src/epd_internals.h
new file mode 100644
index 000000000..0cc5df3f6
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epd_internals.h
@@ -0,0 +1,89 @@
+/**
+ * @file epd_internals.h
+ * @brief Internal definitions and auxiliary data types.
+ *
+ * Unless you want to extend the library itself (Which you are very welcome to do),
+ * you will most likely not need to know about this file.
+ */
+
+#ifndef EPD_INTERNALS_H
+#define EPD_INTERNALS_H
+
+#include
+#include
+
+/// minimal draw time in ms for a frame layer,
+/// which will allow all particles to set properly.
+#define MINIMUM_FRAME_TIME 12
+
+/// Frame draw time for monochrome mode in 1/10 us.
+#define MONOCHROME_FRAME_TIME 120
+
+typedef struct {
+ int phases;
+ const uint8_t* luts;
+ /// If we have timing information for the individual
+ /// phases, this is an array of the on-times for each phase.
+ /// Otherwise, this is NULL.
+ const int* phase_times;
+} EpdWaveformPhases;
+
+typedef struct {
+ uint8_t type;
+ uint8_t temp_ranges;
+ EpdWaveformPhases const** range_data;
+} EpdWaveformMode;
+
+typedef struct {
+ int min;
+ int max;
+} EpdWaveformTempInterval;
+
+typedef struct {
+ uint8_t num_modes;
+ uint8_t num_temp_ranges;
+ EpdWaveformMode const** mode_data;
+ EpdWaveformTempInterval const* temp_intervals;
+} EpdWaveform;
+
+extern const EpdWaveform epdiy_ED060SC4;
+extern const EpdWaveform epdiy_ED097OC4;
+extern const EpdWaveform epdiy_ED047TC1;
+extern const EpdWaveform epdiy_ED047TC2;
+extern const EpdWaveform epdiy_ED097TC2;
+extern const EpdWaveform epdiy_ED060XC3;
+extern const EpdWaveform epdiy_ED060SCT;
+extern const EpdWaveform epdiy_ED133UT2;
+extern const EpdWaveform epdiy_NULL;
+
+/// Font data stored PER GLYPH
+typedef struct {
+ uint16_t width; ///< Bitmap dimensions in pixels
+ uint16_t height; ///< Bitmap dimensions in pixels
+ uint16_t advance_x; ///< Distance to advance cursor (x axis)
+ int16_t left; ///< X dist from cursor pos to UL corner
+ int16_t top; ///< Y dist from cursor pos to UL corner
+ uint32_t compressed_size; ///< Size of the zlib-compressed font data.
+ uint32_t data_offset; ///< Pointer into EpdFont->bitmap
+} EpdGlyph;
+
+/// Glyph interval structure
+typedef struct {
+ uint32_t first; ///< The first unicode code point of the interval
+ uint32_t last; ///< The last unicode code point of the interval
+ uint32_t offset; ///< Index of the first code point into the glyph array
+} EpdUnicodeInterval;
+
+/// Data stored for FONT AS A WHOLE
+typedef struct {
+ const uint8_t* bitmap; ///< Glyph bitmaps, concatenated
+ const EpdGlyph* glyph; ///< Glyph array
+ const EpdUnicodeInterval* intervals; ///< Valid unicode intervals for this font
+ uint32_t interval_count; ///< Number of unicode intervals.
+ bool compressed; ///< Does this font use compressed glyph bitmaps?
+ uint16_t advance_y; ///< Newline distance (y axis)
+ int ascender; ///< Maximal height of a glyph above the base line
+ int descender; ///< Maximal height of a glyph below the base line
+} EpdFont;
+
+#endif // EPD_INTERNALS_H
diff --git a/lib/libesp32_eink/epdiy/src/epdiy.c b/lib/libesp32_eink/epdiy/src/epdiy.c
new file mode 100644
index 000000000..9735df15e
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epdiy.c
@@ -0,0 +1,545 @@
+#include "epdiy.h"
+#include "epd_board.h"
+#include "epd_display.h"
+#include "output_common/render_method.h"
+#include "render.h"
+
+#include
+#include
+#include
+#include
+
+// Simple x and y coordinate
+typedef struct {
+ uint16_t x;
+ uint16_t y;
+} Coord_xy;
+
+static const EpdDisplay_t* display = NULL;
+
+// Display rotation. Can be updated using epd_set_rotation(enum EpdRotation)
+static enum EpdRotation display_rotation = EPD_ROT_LANDSCAPE;
+
+#ifndef _swap_int
+#define _swap_int(a, b) \
+ { \
+ int t = a; \
+ a = b; \
+ b = t; \
+ }
+#endif
+
+EpdRect epd_full_screen() {
+ EpdRect area = { .x = 0, .y = 0, .width = epd_width(), .height = epd_height() };
+ return area;
+}
+
+void epd_clear() {
+ epd_clear_area(epd_full_screen());
+}
+
+void epd_draw_hline(int x, int y, int length, uint8_t color, uint8_t* framebuffer) {
+ for (int i = 0; i < length; i++) {
+ int xx = x + i;
+ epd_draw_pixel(xx, y, color, framebuffer);
+ }
+}
+
+void epd_draw_vline(int x, int y, int length, uint8_t color, uint8_t* framebuffer) {
+ for (int i = 0; i < length; i++) {
+ int yy = y + i;
+ epd_draw_pixel(x, yy, color, framebuffer);
+ }
+}
+
+Coord_xy _rotate(uint16_t x, uint16_t y) {
+ switch (display_rotation) {
+ case EPD_ROT_LANDSCAPE:
+ break;
+ case EPD_ROT_PORTRAIT:
+ _swap_int(x, y);
+ x = epd_width() - x - 1;
+ break;
+ case EPD_ROT_INVERTED_LANDSCAPE:
+ x = epd_width() - x - 1;
+ y = epd_height() - y - 1;
+ break;
+ case EPD_ROT_INVERTED_PORTRAIT:
+ _swap_int(x, y);
+ y = epd_height() - y - 1;
+ break;
+ }
+ Coord_xy coord = { x, y };
+ return coord;
+}
+
+void epd_draw_pixel(int x, int y, uint8_t color, uint8_t* framebuffer) {
+ // Check rotation and move pixel around if necessary
+ Coord_xy coord = _rotate(x, y);
+ x = coord.x;
+ y = coord.y;
+
+ if (x < 0 || x >= epd_width()) {
+ return;
+ }
+ if (y < 0 || y >= epd_height()) {
+ return;
+ }
+
+ uint8_t* buf_ptr = &framebuffer[y * epd_width() / 2 + x / 2];
+ if (x % 2) {
+ *buf_ptr = (*buf_ptr & 0x0F) | (color & 0xF0);
+ } else {
+ *buf_ptr = (*buf_ptr & 0xF0) | (color >> 4);
+ }
+}
+
+void epd_draw_circle(int x0, int y0, int r, uint8_t color, uint8_t* framebuffer) {
+ int f = 1 - r;
+ int ddF_x = 1;
+ int ddF_y = -2 * r;
+ int x = 0;
+ int y = r;
+
+ epd_draw_pixel(x0, y0 + r, color, framebuffer);
+ epd_draw_pixel(x0, y0 - r, color, framebuffer);
+ epd_draw_pixel(x0 + r, y0, color, framebuffer);
+ epd_draw_pixel(x0 - r, y0, color, framebuffer);
+
+ while (x < y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ epd_draw_pixel(x0 + x, y0 + y, color, framebuffer);
+ epd_draw_pixel(x0 - x, y0 + y, color, framebuffer);
+ epd_draw_pixel(x0 + x, y0 - y, color, framebuffer);
+ epd_draw_pixel(x0 - x, y0 - y, color, framebuffer);
+ epd_draw_pixel(x0 + y, y0 + x, color, framebuffer);
+ epd_draw_pixel(x0 - y, y0 + x, color, framebuffer);
+ epd_draw_pixel(x0 + y, y0 - x, color, framebuffer);
+ epd_draw_pixel(x0 - y, y0 - x, color, framebuffer);
+ }
+}
+
+void epd_fill_circle(int x0, int y0, int r, uint8_t color, uint8_t* framebuffer) {
+ epd_draw_vline(x0, y0 - r, 2 * r + 1, color, framebuffer);
+ epd_fill_circle_helper(x0, y0, r, 3, 0, color, framebuffer);
+}
+
+void epd_fill_circle_helper(
+ int x0, int y0, int r, int corners, int delta, uint8_t color, uint8_t* framebuffer
+) {
+ int f = 1 - r;
+ int ddF_x = 1;
+ int ddF_y = -2 * r;
+ int x = 0;
+ int y = r;
+ int px = x;
+ int py = y;
+
+ delta++; // Avoid some +1's in the loop
+
+ while (x < y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+ // These checks avoid double-drawing certain lines, important
+ // for the SSD1306 library which has an INVERT drawing mode.
+ if (x < (y + 1)) {
+ if (corners & 1)
+ epd_draw_vline(x0 + x, y0 - y, 2 * y + delta, color, framebuffer);
+ if (corners & 2)
+ epd_draw_vline(x0 - x, y0 - y, 2 * y + delta, color, framebuffer);
+ }
+ if (y != py) {
+ if (corners & 1)
+ epd_draw_vline(x0 + py, y0 - px, 2 * px + delta, color, framebuffer);
+ if (corners & 2)
+ epd_draw_vline(x0 - py, y0 - px, 2 * px + delta, color, framebuffer);
+ py = y;
+ }
+ px = x;
+ }
+}
+
+void epd_draw_rect(EpdRect rect, uint8_t color, uint8_t* framebuffer) {
+ int x = rect.x;
+ int y = rect.y;
+ int w = rect.width;
+ int h = rect.height;
+ epd_draw_hline(x, y, w, color, framebuffer);
+ epd_draw_hline(x, y + h - 1, w, color, framebuffer);
+ epd_draw_vline(x, y, h, color, framebuffer);
+ epd_draw_vline(x + w - 1, y, h, color, framebuffer);
+}
+
+void epd_fill_rect(EpdRect rect, uint8_t color, uint8_t* framebuffer) {
+ int x = rect.x;
+ int y = rect.y;
+ int w = rect.width;
+ int h = rect.height;
+ for (int i = y; i < y + h; i++) {
+ epd_draw_hline(x, i, w, color, framebuffer);
+ }
+}
+
+static void epd_write_line(int x0, int y0, int x1, int y1, uint8_t color, uint8_t* framebuffer) {
+ int steep = abs(y1 - y0) > abs(x1 - x0);
+ if (steep) {
+ _swap_int(x0, y0);
+ _swap_int(x1, y1);
+ }
+
+ if (x0 > x1) {
+ _swap_int(x0, x1);
+ _swap_int(y0, y1);
+ }
+
+ int dx, dy;
+ dx = x1 - x0;
+ dy = abs(y1 - y0);
+
+ int err = dx / 2;
+ int ystep;
+
+ if (y0 < y1) {
+ ystep = 1;
+ } else {
+ ystep = -1;
+ }
+
+ for (; x0 <= x1; x0++) {
+ if (steep) {
+ epd_draw_pixel(y0, x0, color, framebuffer);
+ } else {
+ epd_draw_pixel(x0, y0, color, framebuffer);
+ }
+ err -= dy;
+ if (err < 0) {
+ y0 += ystep;
+ err += dx;
+ }
+ }
+}
+
+void epd_draw_line(int x0, int y0, int x1, int y1, uint8_t color, uint8_t* framebuffer) {
+ // Update in subclasses if desired!
+ if (x0 == x1) {
+ if (y0 > y1)
+ _swap_int(y0, y1);
+ epd_draw_vline(x0, y0, y1 - y0 + 1, color, framebuffer);
+ } else if (y0 == y1) {
+ if (x0 > x1)
+ _swap_int(x0, x1);
+ epd_draw_hline(x0, y0, x1 - x0 + 1, color, framebuffer);
+ } else {
+ epd_write_line(x0, y0, x1, y1, color, framebuffer);
+ }
+}
+
+void epd_draw_triangle(
+ int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color, uint8_t* framebuffer
+) {
+ epd_draw_line(x0, y0, x1, y1, color, framebuffer);
+ epd_draw_line(x1, y1, x2, y2, color, framebuffer);
+ epd_draw_line(x2, y2, x0, y0, color, framebuffer);
+}
+
+void epd_fill_triangle(
+ int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color, uint8_t* framebuffer
+) {
+ int a, b, y, last;
+
+ // Sort coordinates by Y order (y2 >= y1 >= y0)
+ if (y0 > y1) {
+ _swap_int(y0, y1);
+ _swap_int(x0, x1);
+ }
+ if (y1 > y2) {
+ _swap_int(y2, y1);
+ _swap_int(x2, x1);
+ }
+ if (y0 > y1) {
+ _swap_int(y0, y1);
+ _swap_int(x0, x1);
+ }
+
+ if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
+ a = b = x0;
+ if (x1 < a)
+ a = x1;
+ else if (x1 > b)
+ b = x1;
+ if (x2 < a)
+ a = x2;
+ else if (x2 > b)
+ b = x2;
+ epd_draw_hline(a, y0, b - a + 1, color, framebuffer);
+ return;
+ }
+
+ int dx01 = x1 - x0, dy01 = y1 - y0, dx02 = x2 - x0, dy02 = y2 - y0, dx12 = x2 - x1,
+ dy12 = y2 - y1;
+ int32_t sa = 0, sb = 0;
+
+ // For upper part of triangle, find scanline crossings for segments
+ // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
+ // is included here (and second loop will be skipped, avoiding a /0
+ // error there), otherwise scanline y1 is skipped here and handled
+ // in the second loop...which also avoids a /0 error here if y0=y1
+ // (flat-topped triangle).
+ if (y1 == y2)
+ last = y1; // Include y1 scanline
+ else
+ last = y1 - 1; // Skip it
+
+ for (y = y0; y <= last; y++) {
+ a = x0 + sa / dy01;
+ b = x0 + sb / dy02;
+ sa += dx01;
+ sb += dx02;
+ /* longhand:
+ a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
+ b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
+ */
+ if (a > b)
+ _swap_int(a, b);
+ epd_draw_hline(a, y, b - a + 1, color, framebuffer);
+ }
+
+ // For lower part of triangle, find scanline crossings for segments
+ // 0-2 and 1-2. This loop is skipped if y1=y2.
+ sa = (int32_t)dx12 * (y - y1);
+ sb = (int32_t)dx02 * (y - y0);
+ for (; y <= y2; y++) {
+ a = x1 + sa / dy12;
+ b = x0 + sb / dy02;
+ sa += dx12;
+ sb += dx02;
+ /* longhand:
+ a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
+ b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
+ */
+ if (a > b)
+ _swap_int(a, b);
+ epd_draw_hline(a, y, b - a + 1, color, framebuffer);
+ }
+}
+
+void epd_copy_to_framebuffer(EpdRect image_area, const uint8_t* image_data, uint8_t* framebuffer) {
+ assert(framebuffer != NULL);
+
+ for (uint32_t i = 0; i < image_area.width * image_area.height; i++) {
+ uint32_t value_index = i;
+ // for images of uneven width,
+ // consume an additional nibble per row.
+ if (image_area.width % 2) {
+ value_index += i / image_area.width;
+ }
+ uint8_t val = (value_index % 2) ? (image_data[value_index / 2] & 0xF0) >> 4
+ : image_data[value_index / 2] & 0x0F;
+
+ int xx = image_area.x + i % image_area.width;
+ if (xx < 0 || xx >= epd_width()) {
+ continue;
+ }
+ int yy = image_area.y + i / image_area.width;
+ if (yy < 0 || yy >= epd_height()) {
+ continue;
+ }
+ uint8_t* buf_ptr = &framebuffer[yy * epd_width() / 2 + xx / 2];
+ if (xx % 2) {
+ *buf_ptr = (*buf_ptr & 0x0F) | (val << 4);
+ } else {
+ *buf_ptr = (*buf_ptr & 0xF0) | val;
+ }
+ }
+}
+
+enum EpdDrawError epd_draw_image(EpdRect area, const uint8_t* data, const EpdWaveform* waveform) {
+ int temperature = epd_ambient_temperature();
+ assert(waveform != NULL);
+ EpdRect no_crop = {
+ .x = 0,
+ .y = 0,
+ .width = 0,
+ .height = 0,
+ };
+ return epd_draw_base(area, data, no_crop, EPD_MODE_DEFAULT, temperature, NULL, NULL, waveform);
+}
+
+void epd_set_rotation(enum EpdRotation rotation) {
+ display_rotation = rotation;
+}
+
+enum EpdRotation epd_get_rotation() {
+ return display_rotation;
+}
+
+int epd_rotated_display_width() {
+ int display_width = epd_width();
+ switch (display_rotation) {
+ case EPD_ROT_PORTRAIT:
+ display_width = epd_height();
+ break;
+ case EPD_ROT_INVERTED_PORTRAIT:
+ display_width = epd_height();
+ break;
+ case EPD_ROT_INVERTED_LANDSCAPE:
+ case EPD_ROT_LANDSCAPE:
+ break;
+ }
+ return display_width;
+}
+
+int epd_rotated_display_height() {
+ int display_height = epd_height();
+ switch (display_rotation) {
+ case EPD_ROT_PORTRAIT:
+ display_height = epd_width();
+ break;
+ case EPD_ROT_INVERTED_PORTRAIT:
+ display_height = epd_width();
+ break;
+ case EPD_ROT_INVERTED_LANDSCAPE:
+ case EPD_ROT_LANDSCAPE:
+ break;
+ }
+ return display_height;
+}
+
+uint8_t epd_get_pixel(int x, int y, int fb_width, int fb_height, const uint8_t* framebuffer) {
+ if (x < 0 || x >= fb_width) {
+ return 0;
+ }
+ if (y < 0 || y >= fb_height) {
+ return 0;
+ }
+ int fb_width_bytes = fb_width / 2 + fb_width % 2;
+ uint8_t buf_val = framebuffer[y * fb_width_bytes + x / 2];
+ if (x % 2) {
+ buf_val = (buf_val & 0xF0) >> 4;
+ } else {
+ buf_val = (buf_val & 0x0F);
+ }
+
+ // epd_draw_pixel needs a 0 -> 255 value
+ return buf_val << 4;
+}
+
+static void draw_rotated_transparent_image(
+ EpdRect image_area,
+ const uint8_t* image_buffer,
+ uint8_t* framebuffer,
+ uint8_t* transparent_color
+) {
+ uint16_t x_offset = 0;
+ uint16_t y_offset = 0;
+ uint8_t pixel_color;
+ for (uint16_t y = 0; y < image_area.height; y++) {
+ for (uint16_t x = 0; x < image_area.width; x++) {
+ x_offset = image_area.x + x;
+ y_offset = image_area.y + y;
+ if (x_offset >= epd_rotated_display_width())
+ continue;
+ if (y_offset >= epd_rotated_display_height())
+ continue;
+ pixel_color = epd_get_pixel(x, y, image_area.width, image_area.height, image_buffer);
+ if (transparent_color == NULL || pixel_color != (*transparent_color))
+ epd_draw_pixel(x_offset, y_offset, pixel_color, framebuffer);
+ }
+ }
+}
+
+void epd_draw_rotated_transparent_image(
+ EpdRect image_area, const uint8_t* image_buffer, uint8_t* framebuffer, uint8_t transparent_color
+) {
+ draw_rotated_transparent_image(image_area, image_buffer, framebuffer, &transparent_color);
+}
+
+void epd_draw_rotated_image(EpdRect image_area, const uint8_t* image_buffer, uint8_t* framebuffer) {
+ if (epd_get_rotation() != EPD_ROT_LANDSCAPE) {
+ draw_rotated_transparent_image(image_area, image_buffer, framebuffer, NULL);
+ } else {
+ epd_copy_to_framebuffer(image_area, image_buffer, framebuffer);
+ }
+}
+
+void epd_poweron() {
+ epd_current_board()->poweron(epd_ctrl_state());
+}
+
+void epd_poweroff() {
+ epd_current_board()->poweroff(epd_ctrl_state());
+}
+
+void epd_init(
+ const EpdBoardDefinition* board, const EpdDisplay_t* disp, enum EpdInitOptions options
+) {
+ display = disp;
+ epd_set_board(board);
+ epd_renderer_init(options);
+}
+
+void epd_deinit() {
+ epd_renderer_deinit();
+}
+
+float epd_ambient_temperature() {
+ if (!epd_current_board()) {
+ ESP_LOGE("epdiy", "Could not read temperature: board not set!");
+ return 0.0;
+ }
+
+ if (!epd_current_board()->get_temperature) {
+ ESP_LOGW("epdiy", "No ambient temperature sensor - returning 21C");
+ return 21.0;
+ }
+ return epd_current_board()->get_temperature();
+}
+
+void epd_set_vcom(uint16_t vcom) {
+ if (!epd_current_board()) {
+ ESP_LOGE("epdiy", "Could not set VCOM: board not set!");
+ return;
+ }
+
+ if (!epd_current_board()->set_vcom) {
+ ESP_LOGE("epdiy", "Could not set VCOM: board does not support setting VCOM in software.");
+ return;
+ }
+ return epd_current_board()->set_vcom(vcom);
+}
+
+const EpdDisplay_t* epd_get_display() {
+ assert(display != NULL);
+ return display;
+}
+
+int epd_width() {
+ return display->width;
+}
+
+int epd_height() {
+ return display->height;
+}
+
+void epd_set_lcd_pixel_clock_MHz(int frequency) {
+#ifdef RENDER_METHOD_LCD
+ void epd_lcd_set_pixel_clock_MHz(int frequency);
+ epd_lcd_set_pixel_clock_MHz(frequency);
+#else
+ ESP_LOGW("epdiy", "called set_lcd_pixel_clock_MHz, but LCD driver is not used!");
+#endif
+}
diff --git a/lib/libesp32_eink/epdiy/src/epdiy.h b/lib/libesp32_eink/epdiy/src/epdiy.h
new file mode 100644
index 000000000..9f8ffa5f7
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/epdiy.h
@@ -0,0 +1,605 @@
+/**
+ * @file epdiy.h
+ * A driver library for drawing to an EPD.
+ */
+#include "epd_display.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma once
+#include
+#include
+#include
+
+#include "epd_internals.h"
+
+/// An area on the display.
+typedef struct {
+ /// Horizontal position.
+ int x;
+ /// Vertical position.
+ int y;
+ /// Area / image width, must be positive.
+ int width;
+ /// Area / image height, must be positive.
+ int height;
+} EpdRect;
+
+/// Global EPD driver options.
+enum EpdInitOptions {
+ /// Use the default options.
+ EPD_OPTIONS_DEFAULT = 0,
+ /// Use a small look-up table of 1024 bytes.
+ /// The EPD driver will use less space, but performance may be worse.
+ EPD_LUT_1K = 1,
+ /// Use a 64K lookup table. (default)
+ /// Best performance, but permanently occupies a 64k block of internal memory.
+ EPD_LUT_64K = 2,
+
+ /// Use a small feed queue of 8 display lines.
+ /// This uses less memory, but may impact performance.
+ EPD_FEED_QUEUE_8 = 4,
+ /// Use a feed queue of 32 display lines. (default)
+ /// Best performance, but larger memory footprint.
+ EPD_FEED_QUEUE_32 = 8,
+};
+
+/// The image drawing mode.
+enum EpdDrawMode {
+ /// An init waveform.
+ /// This is currently unused, use `epd_clear()` instead.
+ MODE_INIT = 0x0,
+ /// Direct Update: Go from any color to black for white only.
+ MODE_DU = 0x1,
+ /// Go from any grayscale value to another with a flashing update.
+ MODE_GC16 = 0x2,
+ /// Faster version of `MODE_GC16`.
+ /// Not available with default epdiy waveforms.
+ MODE_GC16_FAST = 0x3,
+ /// Animation Mode: Fast, monochrom updates.
+ /// Not available with default epdiy waveforms.
+ MODE_A2 = 0x4,
+ /// Go from any grayscale value to another with a non-flashing update.
+ MODE_GL16 = 0x5,
+ /// Faster version of `MODE_GL16`.
+ /// Not available with default epdiy waveforms.
+ MODE_GL16_FAST = 0x6,
+ /// A 4-grayscale version of `MODE_DU`.
+ /// Not available with default epdiy waveforms.
+ MODE_DU4 = 0x7,
+ /// Arbitrary transitions for 4 grayscale values.
+ /// Not available with default epdiy waveforms.
+ MODE_GL4 = 0xA,
+ /// Not available with default epdiy waveforms.
+ MODE_GL16_INV = 0xB,
+
+ /// Go from a white screen to arbitrary grayscale, quickly.
+ /// Exclusively available with epdiy waveforms.
+ MODE_EPDIY_WHITE_TO_GL16 = 0x10,
+ /// Go from a black screen to arbitrary grayscale, quickly.
+ /// Exclusively available with epdiy waveforms.
+ MODE_EPDIY_BLACK_TO_GL16 = 0x11,
+
+ /// Monochrome mode. Only supported with 1bpp buffers.
+ MODE_EPDIY_MONOCHROME = 0x20,
+
+ MODE_UNKNOWN_WAVEFORM = 0x3F,
+
+ // Framebuffer packing modes
+ /// 1 bit-per-pixel framebuffer with 0 = black, 1 = white.
+ /// MSB is left is the leftmost pixel, LSB the rightmost pixel.
+ MODE_PACKING_8PPB = 0x40,
+ /// 4 bit-per pixel framebuffer with 0x0 = black, 0xF = white.
+ /// The upper nibble corresponds to the left pixel.
+ /// A byte cannot wrap over multiple rows, images of uneven width
+ /// must add a padding nibble per line.
+ MODE_PACKING_2PPB = 0x80,
+ /// A difference image with one pixel per byte.
+ /// The upper nibble marks the "from" color,
+ /// the lower nibble the "to" color.
+ MODE_PACKING_1PPB_DIFFERENCE = 0x100,
+ // reserver for 4PPB mode
+
+ /// Assert that the display has a uniform color, e.g. after initialization.
+ /// If `MODE_PACKING_2PPB` is specified, a optimized output calculation can be used.
+ /// Draw on a white background
+ PREVIOUSLY_WHITE = 0x200,
+ /// See `PREVIOUSLY_WHITE`.
+ /// Draw on a black background
+ PREVIOUSLY_BLACK = 0x400,
+
+ /// Enforce NOT using S3 Vector extensions.
+ /// USed for testing.
+ MODE_FORCE_NO_PIE = 0x800,
+};
+
+/** Display software rotation.
+ * Sets the rotation for the purposes of the drawing and font functions
+ * Use epd_set_rotation(EPD_ROT_*) to set it using one of the options below
+ * Use epd_get_rotation() in case you need to read this value
+ */
+enum EpdRotation {
+ EPD_ROT_LANDSCAPE = 0,
+ EPD_ROT_PORTRAIT = 1,
+ EPD_ROT_INVERTED_LANDSCAPE = 2,
+ EPD_ROT_INVERTED_PORTRAIT = 3,
+};
+
+/// Possible failures when drawing.
+enum EpdDrawError {
+ EPD_DRAW_SUCCESS = 0x0,
+ /// No valid framebuffer packing mode was specified.
+ EPD_DRAW_INVALID_PACKING_MODE = 0x1,
+
+ /// No lookup table implementation for this mode / packing.
+ EPD_DRAW_LOOKUP_NOT_IMPLEMENTED = 0x2,
+
+ /// The string to draw is invalid.
+ EPD_DRAW_STRING_INVALID = 0x4,
+
+ /// The string was not empty, but no characters where drawable.
+ EPD_DRAW_NO_DRAWABLE_CHARACTERS = 0x8,
+
+ /// Allocation failed
+ EPD_DRAW_FAILED_ALLOC = 0x10,
+
+ /// A glyph could not be drawn, and not fallback was present.
+ EPD_DRAW_GLYPH_FALLBACK_FAILED = 0x20,
+
+ /// The specified crop area is invalid.
+ EPD_DRAW_INVALID_CROP = 0x40,
+
+ /// No such mode is available with the current waveform.
+ EPD_DRAW_MODE_NOT_FOUND = 0x80,
+
+ /// The waveform info file contains no applicable temperature range.
+ EPD_DRAW_NO_PHASES_AVAILABLE = 0x100,
+
+ /// An invalid combination of font flags was used.
+ EPD_DRAW_INVALID_FONT_FLAGS = 0x200,
+
+ /// The waveform lookup could not keep up with the display output.
+ ///
+ /// Reduce the display clock speed.
+ EPD_DRAW_EMPTY_LINE_QUEUE = 0x400,
+};
+
+/// The default draw mode (non-flashy refresh, whith previously white screen).
+#define EPD_MODE_DEFAULT (MODE_GL16 | PREVIOUSLY_WHITE)
+
+/// Font drawing flags
+enum EpdFontFlags {
+ /// Draw a background.
+ ///
+ /// Take the background into account
+ /// when calculating the size.
+ EPD_DRAW_BACKGROUND = 0x1,
+
+ /// Left-Align lines
+ EPD_DRAW_ALIGN_LEFT = 0x2,
+ /// Right-align lines
+ EPD_DRAW_ALIGN_RIGHT = 0x4,
+ /// Center-align lines
+ EPD_DRAW_ALIGN_CENTER = 0x8,
+};
+
+/// Font properties.
+typedef struct {
+ /// Foreground color
+ uint8_t fg_color : 4;
+ /// Background color
+ uint8_t bg_color : 4;
+ /// Use the glyph for this codepoint for missing glyphs.
+ uint32_t fallback_glyph;
+ /// Additional flags, reserved for future use
+ enum EpdFontFlags flags;
+} EpdFontProperties;
+
+#include "epd_board.h"
+#include "epd_board_specific.h"
+#include "epd_display.h"
+#include "epd_highlevel.h"
+
+/** Initialize the ePaper display */
+void epd_init(
+ const EpdBoardDefinition* board, const EpdDisplay_t* display, enum EpdInitOptions options
+);
+
+/**
+ * Get the configured display.
+ */
+const EpdDisplay_t* epd_get_display();
+
+/**
+ * Get the EPD display's witdth.
+ */
+int epd_width();
+
+/**
+ * Get the EPD display's height.
+ */
+int epd_height();
+
+/**
+ * Set the display common voltage if supported.
+ *
+ * Voltage is set as absolute value in millivolts.
+ * Although VCOM is negative, this function takes a positive (absolute) value.
+ */
+void epd_set_vcom(uint16_t vcom);
+
+/**
+ * Get the current ambient temperature in °C,
+ * if the board has a sensor.
+ */
+float epd_ambient_temperature();
+
+/** Get the display rotation value */
+enum EpdRotation epd_get_rotation();
+
+/** Set the display rotation: Affects the drawing and font functions */
+void epd_set_rotation(enum EpdRotation rotation);
+
+/** Get screen width after rotation */
+int epd_rotated_display_width();
+
+/** Get screen height after rotation */
+int epd_rotated_display_height();
+
+/** Deinit the ePaper display */
+void epd_deinit();
+
+/** Enable display power supply. */
+void epd_poweron();
+
+/** Disable display power supply. */
+void epd_poweroff();
+
+/** Clear the whole screen by flashing it. */
+void epd_clear();
+
+/**
+ * Clear an area by flashing it.
+ *
+ * @param area: The area to clear.
+ */
+void epd_clear_area(EpdRect area);
+
+/**
+ * Clear an area by flashing it.
+ *
+ * @param area: The area to clear.
+ * @param cycles: The number of black-to-white clear cycles.
+ * @param cycle_time: Length of a cycle. Default: 50 (us).
+ */
+void epd_clear_area_cycles(EpdRect area, int cycles, int cycle_time);
+
+/**
+ * @returns Rectancle representing the whole screen area.
+ */
+EpdRect epd_full_screen();
+
+/**
+ * Draw a picture to a given framebuffer.
+ *
+ * @param image_area: The area to copy to. `width` and `height` of the area
+ * must correspond to the image dimensions in pixels.
+ * @param image_data: The image data, as a buffer of 4 bit wide brightness
+ * values. Pixel data is packed (two pixels per byte). A byte cannot wrap over
+ * multiple rows, images of uneven width must add a padding nibble per line.
+ * @param framebuffer: The framebuffer object,
+ * which must be `epd_width() / 2 * epd_height()` large.
+ */
+void epd_copy_to_framebuffer(EpdRect image_area, const uint8_t* image_data, uint8_t* framebuffer);
+
+/**
+ * Draw a pixel a given framebuffer.
+ *
+ * @param x: Horizontal position in pixels.
+ * @param y: Vertical position in pixels.
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_draw_pixel(int x, int y, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a horizontal line to a given framebuffer.
+ *
+ * @param x: Horizontal start position in pixels.
+ * @param y: Vertical start position in pixels.
+ * @param length: Length of the line in pixels.
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ * which must be `epd_width() / 2 * epd_height()` bytes large.
+ */
+void epd_draw_hline(int x, int y, int length, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a horizontal line to a given framebuffer.
+ *
+ * @param x: Horizontal start position in pixels.
+ * @param y: Vertical start position in pixels.
+ * @param length: Length of the line in pixels.
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ * which must be `epd_width() / 2 * epd_height()` bytes large.
+ */
+void epd_draw_vline(int x, int y, int length, uint8_t color, uint8_t* framebuffer);
+
+void epd_fill_circle_helper(
+ int x0, int y0, int r, int corners, int delta, uint8_t color, uint8_t* framebuffer
+);
+
+/**
+ * Draw a circle with given center and radius
+ *
+ * @param x: Center-point x coordinate
+ * @param y: Center-point y coordinate
+ * @param r: Radius of the circle in pixels
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_draw_circle(int x, int y, int r, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a circle with fill with given center and radius
+ *
+ * @param x: Center-point x coordinate
+ * @param y: Center-point y coordinate
+ * @param r: Radius of the circle in pixels
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_fill_circle(int x, int y, int r, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a rectanle with no fill color
+ *
+ * @param rect: The rectangle to draw.
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_draw_rect(EpdRect rect, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a rectanle with fill color
+ *
+ * @param rect: The rectangle to fill.
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_fill_rect(EpdRect rect, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a line
+ *
+ * @param x0 Start point x coordinate
+ * @param y0 Start point y coordinate
+ * @param x1 End point x coordinate
+ * @param y1 End point y coordinate
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_draw_line(int x0, int y0, int x1, int y1, uint8_t color, uint8_t* framebuffer);
+
+/**
+ * Draw a triangle with no fill color
+ *
+ * @param x0 Vertex #0 x coordinate
+ * @param y0 Vertex #0 y coordinate
+ * @param x1 Vertex #1 x coordinate
+ * @param y1 Vertex #1 y coordinate
+ * @param x2 Vertex #2 x coordinate
+ * @param y2 Vertex #2 y coordinate
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_draw_triangle(
+ int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color, uint8_t* framebuffer
+);
+
+/**
+ * Draw a triangle with color-fill
+ *
+ * @param x0 Vertex #0 x coordinate
+ * @param y0 Vertex #0 y coordinate
+ * @param x1 Vertex #1 x coordinate
+ * @param y1 Vertex #1 y coordinate
+ * @param x2 Vertex #2 x coordinate
+ * @param y2 Vertex #2 y coordinate
+ * @param color: The gray value of the line (see [Colors](#Colors));
+ * @param framebuffer: The framebuffer to draw to,
+ */
+void epd_fill_triangle(
+ int x0, int y0, int x1, int y1, int x2, int y2, uint8_t color, uint8_t* framebuffer
+);
+/**
+ * Get the current ambient temperature in °C, if supported by the board.
+ * Requires the display to be powered on.
+ */
+float epd_ambient_temperature();
+
+/**
+ * The default font properties.
+ */
+EpdFontProperties epd_font_properties_default();
+
+/*!
+ * Get the text bounds for string, when drawn at (x, y).
+ * Set font properties to NULL to use the defaults.
+ */
+void epd_get_text_bounds(
+ const EpdFont* font,
+ const char* string,
+ const int* x,
+ const int* y,
+ int* x1,
+ int* y1,
+ int* w,
+ int* h,
+ const EpdFontProperties* props
+);
+/*!
+ * Returns a rect with the bounds of the text
+ * @param font : the font used to get the character sizes
+ * @param string: pointer to c string
+ * @param x : left most position of rectangle
+ * @param y : top most point of the rectangle
+ * @param margin : to be pllied to the width and height
+ * @returns EpdRect with x and y as per the original and height and width
+ * adjusted to fit the text with the margin added as well.
+ */
+EpdRect epd_get_string_rect(
+ const EpdFont* font,
+ const char* string,
+ int x,
+ int y,
+ int margin,
+ const EpdFontProperties* properties
+);
+
+/**
+ * Write text to the EPD.
+ */
+enum EpdDrawError epd_write_string(
+ const EpdFont* font,
+ const char* string,
+ int* cursor_x,
+ int* cursor_y,
+ uint8_t* framebuffer,
+ const EpdFontProperties* properties
+);
+
+/**
+ * Write a (multi-line) string to the EPD.
+ */
+enum EpdDrawError epd_write_default(
+ const EpdFont* font, const char* string, int* cursor_x, int* cursor_y, uint8_t* framebuffer
+);
+
+/**
+ * Get the font glyph for a unicode code point.
+ */
+const EpdGlyph* epd_get_glyph(const EpdFont* font, uint32_t code_point);
+
+/**
+ * Darken / lighten an area for a given time.
+ *
+ * @param area: The area to darken / lighten.
+ * @param time: The time in us to apply voltage to each pixel.
+ * @param color: 1: lighten, 0: darken.
+ */
+void epd_push_pixels(EpdRect area, short time, int color);
+
+/**
+ * Base function for drawing an image on the screen.
+ * If It is very customizable, and the documentation below should be studied carefully.
+ * For simple applications, use the epdiy highlevel api in "epd_higlevel.h".
+ *
+ * @param area: The area of the screen to draw to.
+ * This can be imagined as shifting the origin of the frame buffer.
+ * @param data: A full framebuffer of display data.
+ * It's structure depends on the chosen `mode`.
+ * @param crop_to: Only draw a part of the frame buffer.
+ * Set to `epd_full_screen()` to draw the full buffer.
+ * @param mode: Specifies the Waveform used, the framebuffer format
+ * and additional information, like if the display is cleared.
+ * @param temperature: The temperature of the display in °C.
+ * Currently, this is unused by the default waveforms at can be
+ * set to room temperature, e.g. 20-25°C.
+ * @param drawn_lines: If not NULL, an array of at least the height of the
+ * image. Every line where the corresponding value in `lines` is `false` will be
+ * skipped.
+ * @param drawn_columns: If not NULL, an array of at least the width of the
+ * image / 2, 16-byte aligned.
+ * The image will only be updated in pixel columns where the corresponding nibbles are
+ * non-zero.
+ * @param waveform: The waveform information to use for drawing.
+ * If you don't have special waveforms, use `EPD_BUILTIN_WAVEFORM`.
+ * @returns `EPD_DRAW_SUCCESS` on sucess, a combination of error flags otherwise.
+ */
+enum EpdDrawError epd_draw_base(
+ EpdRect area,
+ const uint8_t* data,
+ EpdRect crop_to,
+ enum EpdDrawMode mode,
+ int temperature,
+ const bool* drawn_lines,
+ const uint8_t* drawn_columns,
+ const EpdWaveform* waveform
+);
+/**
+ * Calculate a `MODE_PACKING_1PPB_DIFFERENCE` difference image
+ * from two `MODE_PACKING_2PPB` (4 bit-per-pixel) buffers.
+ * If you're using the epdiy highlevel api, this is handled by the update functions.
+ *
+ * @param to: The goal image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
+ * @param from: The previous image as 4-bpp (`MODE_PACKING_2PPB`) framebuffer.
+ * @param crop_to: Only calculate the difference for a crop of the input framebuffers.
+ * The `interlaced` will not be modified outside the crop area.
+ * @param interlaced: The resulting difference image in `MODE_PACKING_1PPB_DIFFERENCE` format.
+ * @param dirty_lines: An array of at least `epd_height()`.
+ * The positions corresponding to lines where `to` and `from` differ
+ * are set to `true`, otherwise to `false`.
+ * @param col_dirtyness: An array of at least `epd_width() / 2`.
+ * If a nibble is set to non-zero, the pixel column is marked as changed, aka "dirty."
+ * The buffer must be 16 byte aligned.
+ * @returns The smallest rectangle containing all changed pixels.
+ */
+EpdRect epd_difference_image_cropped(
+ const uint8_t* to,
+ const uint8_t* from,
+ EpdRect crop_to,
+ uint8_t* interlaced,
+ bool* dirty_lines,
+ uint8_t* col_dirtiness
+);
+
+/**
+ * Simplified version of `epd_difference_image_cropped()`, which considers the
+ * whole display frame buffer.
+ *
+ * See `epd_difference_image_cropped() for details.`
+ */
+EpdRect epd_difference_image(
+ const uint8_t* to,
+ const uint8_t* from,
+ uint8_t* interlaced,
+ bool* dirty_lines,
+ uint8_t* col_dirtiness
+);
+
+/**
+ * Return the pixel color of a 4 bit image array
+ * x,y coordinates of the image pixel
+ * fb_width, fb_height dimensions
+ * @returns uint8_t 0-255 representing the color on given coordinates (as in epd_draw_pixel)
+ */
+uint8_t epd_get_pixel(int x, int y, int fb_width, int fb_height, const uint8_t* framebuffer);
+
+/**
+ * Draw an image reading pixel per pixel and being rotation aware (via epd_draw_pixel)
+ */
+void epd_draw_rotated_image(EpdRect image_area, const uint8_t* image_buffer, uint8_t* framebuffer);
+
+/**
+ * Draw an image reading pixel per pixel and being rotation aware (via epd_draw_pixel)
+ * With an optional transparent color (color key transparency)
+ */
+void epd_draw_rotated_transparent_image(
+ EpdRect image_area, const uint8_t* image_buffer, uint8_t* framebuffer, uint8_t transparent_color
+);
+
+/**
+ * Override the pixel clock when using the LCD driver for display output (Epdiy V7+).
+ * This may result in draws failing if it's set too high!
+ *
+ * This method can be used to tune your application for maximum refresh speed,
+ * if you can guarantee the driver can keep up.
+ */
+void epd_set_lcd_pixel_clock_MHz(int frequency);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/font.c b/lib/libesp32_eink/epdiy/src/font.c
new file mode 100644
index 000000000..39e41122d
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/font.c
@@ -0,0 +1,434 @@
+#include
+#include
+#include
+#include
+
+#include "epdiy.h"
+
+#include
+#include
+#include
+#include
+
+typedef struct {
+ uint8_t mask; /* char data will be bitwise AND with this */
+ uint8_t lead; /* start bytes of current char in utf-8 encoded character */
+ uint32_t beg; /* beginning of codepoint range */
+ uint32_t end; /* end of codepoint range */
+ int bits_stored; /* the number of bits from the codepoint that fits in char */
+} utf_t;
+
+/*
+ * UTF-8 decode inspired from rosetta code
+ * https://rosettacode.org/wiki/UTF-8_encode_and_decode#C
+ */
+static utf_t* utf[] = {
+ /* mask lead beg end bits */
+ [0] = &(utf_t){ 0b00111111, 0b10000000, 0, 0, 6 },
+ [1] = &(utf_t){ 0b01111111, 0b00000000, 0000, 0177, 7 },
+ [2] = &(utf_t){ 0b00011111, 0b11000000, 0200, 03777, 5 },
+ [3] = &(utf_t){ 0b00001111, 0b11100000, 04000, 0177777, 4 },
+ [4] = &(utf_t){ 0b00000111, 0b11110000, 0200000, 04177777, 3 },
+ &(utf_t){ 0 },
+};
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+static inline int max(int x, int y) {
+ return x > y ? x : y;
+}
+
+static int utf8_len(const uint8_t ch) {
+ int len = 0;
+ for (utf_t** u = utf; (*u)->mask; ++u) {
+ if ((ch & ~(*u)->mask) == (*u)->lead) {
+ break;
+ }
+ ++len;
+ }
+ if (len > 4) { /* Malformed leading byte */
+ assert("invalid unicode.");
+ }
+ return len;
+}
+
+static uint32_t next_cp(const uint8_t** string) {
+ if (**string == 0) {
+ return 0;
+ }
+ int bytes = utf8_len(**string);
+ const uint8_t* chr = *string;
+ *string += bytes;
+ int shift = utf[0]->bits_stored * (bytes - 1);
+ uint32_t codep = (*chr++ & utf[bytes]->mask) << shift;
+
+ for (int i = 1; i < bytes; ++i, ++chr) {
+ shift -= utf[0]->bits_stored;
+ codep |= ((const uint8_t)*chr & utf[0]->mask) << shift;
+ }
+
+ return codep;
+}
+
+EpdFontProperties epd_font_properties_default() {
+ EpdFontProperties props
+ = { .fg_color = 0, .bg_color = 15, .fallback_glyph = 0, .flags = EPD_DRAW_ALIGN_LEFT };
+ return props;
+}
+
+const EpdGlyph* epd_get_glyph(const EpdFont* font, uint32_t code_point) {
+ const EpdUnicodeInterval* intervals = font->intervals;
+ for (int i = 0; i < font->interval_count; i++) {
+ const EpdUnicodeInterval* interval = &intervals[i];
+ if (code_point >= interval->first && code_point <= interval->last) {
+ return &font->glyph[interval->offset + (code_point - interval->first)];
+ }
+ if (code_point < interval->first) {
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+static int uncompress(
+ uint8_t* dest, size_t uncompressed_size, const uint8_t* source, size_t source_size
+) {
+ tinfl_decompressor* decomp;
+ if (uncompressed_size == 0 || dest == NULL || source_size == 0 || source == NULL) {
+ return -1;
+ }
+ decomp = malloc(sizeof(tinfl_decompressor));
+ if (!decomp) {
+ // Out of memory
+ return -1;
+ }
+ tinfl_init(decomp);
+
+ // we know everything will fit into the buffer.
+ tinfl_status decomp_status = tinfl_decompress(
+ decomp,
+ source,
+ &source_size,
+ dest,
+ dest,
+ &uncompressed_size,
+ TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF
+ );
+ free(decomp);
+ if (decomp_status != TINFL_STATUS_DONE) {
+ return decomp_status;
+ }
+ return 0;
+}
+
+/*!
+ @brief Draw a single character to a pre-allocated buffer.
+*/
+static enum EpdDrawError IRAM_ATTR draw_char(
+ const EpdFont* font,
+ uint8_t* buffer,
+ int* cursor_x,
+ int cursor_y,
+ uint32_t cp,
+ const EpdFontProperties* props
+) {
+ assert(props != NULL);
+
+ const EpdGlyph* glyph = epd_get_glyph(font, cp);
+ if (!glyph) {
+ glyph = epd_get_glyph(font, props->fallback_glyph);
+ }
+
+ if (!glyph) {
+ return EPD_DRAW_GLYPH_FALLBACK_FAILED;
+ }
+
+ uint32_t offset = glyph->data_offset;
+ uint16_t width = glyph->width, height = glyph->height;
+ int left = glyph->left;
+
+ int byte_width = (width / 2 + width % 2);
+ unsigned long bitmap_size = byte_width * height;
+ const uint8_t* bitmap = NULL;
+ if (bitmap_size > 0 && font->compressed) {
+ uint8_t* tmp_bitmap = (uint8_t*)malloc(bitmap_size);
+ if (tmp_bitmap == NULL && bitmap_size) {
+ ESP_LOGE("font", "malloc failed.");
+ return EPD_DRAW_FAILED_ALLOC;
+ }
+ uncompress(tmp_bitmap, bitmap_size, &font->bitmap[offset], glyph->compressed_size);
+ bitmap = tmp_bitmap;
+ } else {
+ bitmap = &font->bitmap[offset];
+ }
+
+ uint8_t color_lut[16];
+ for (int c = 0; c < 16; c++) {
+ int color_difference = (int)props->fg_color - (int)props->bg_color;
+ color_lut[c] = max(0, min(15, props->bg_color + c * color_difference / 15));
+ }
+ bool background_needed = props->flags & EPD_DRAW_BACKGROUND;
+
+ for (int y = 0; y < height; y++) {
+ int yy = cursor_y - glyph->top + y;
+ int start_pos = *cursor_x + left;
+ bool byte_complete = start_pos % 2;
+ int x = max(0, -start_pos);
+ int max_x = start_pos + width;
+ uint8_t color;
+
+ for (int xx = start_pos; xx < max_x; xx++) {
+ uint8_t bm = bitmap[y * byte_width + x / 2];
+ if ((x & 1) == 0) {
+ bm = bm & 0xF;
+ } else {
+ bm = bm >> 4;
+ }
+ if (background_needed || bm) {
+ color = color_lut[bm] << 4;
+ epd_draw_pixel(xx, yy, color, buffer);
+ }
+ byte_complete = !byte_complete;
+ x++;
+ }
+ }
+ if (bitmap_size > 0 && font->compressed) {
+ free((uint8_t*)bitmap);
+ }
+ *cursor_x += glyph->advance_x;
+ return EPD_DRAW_SUCCESS;
+}
+
+/*!
+ * @brief Calculate the bounds of a character when drawn at (x, y), move the
+ * cursor (*x) forward, adjust the given bounds.
+ */
+static void get_char_bounds(
+ const EpdFont* font,
+ uint32_t cp,
+ int* x,
+ int* y,
+ int* minx,
+ int* miny,
+ int* maxx,
+ int* maxy,
+ const EpdFontProperties* props
+) {
+ assert(props != NULL);
+
+ const EpdGlyph* glyph = epd_get_glyph(font, cp);
+
+ if (!glyph) {
+ glyph = epd_get_glyph(font, props->fallback_glyph);
+ }
+
+ if (!glyph) {
+ return;
+ }
+
+ int x1 = *x + glyph->left, y1 = *y + glyph->top - glyph->height, x2 = x1 + glyph->width,
+ y2 = y1 + glyph->height;
+
+ // background needs to be taken into account
+ if (props->flags & EPD_DRAW_BACKGROUND) {
+ *minx = min(*x, min(*minx, x1));
+ *maxx = max(max(*x + glyph->advance_x, x2), *maxx);
+ *miny = min(*y + font->descender, min(*miny, y1));
+ *maxy = max(*y + font->ascender, max(*maxy, y2));
+ } else {
+ if (x1 < *minx)
+ *minx = x1;
+ if (y1 < *miny)
+ *miny = y1;
+ if (x2 > *maxx)
+ *maxx = x2;
+ if (y2 > *maxy)
+ *maxy = y2;
+ }
+ *x += glyph->advance_x;
+}
+
+EpdRect epd_get_string_rect(
+ const EpdFont* font,
+ const char* string,
+ int x,
+ int y,
+ int margin,
+ const EpdFontProperties* properties
+) {
+ assert(properties != NULL);
+ EpdFontProperties props = *properties;
+ props.flags |= EPD_DRAW_BACKGROUND;
+ EpdRect temp = { .x = x, .y = y, .width = 0, .height = 0 };
+ if (*string == '\0')
+ return temp;
+ int minx = 100000, miny = 100000, maxx = -1, maxy = -1;
+ int temp_x = x;
+ int temp_y = y + font->ascender;
+
+ // Go through each line and get it's co-ordinates
+ uint32_t c;
+ while ((c = next_cp((const uint8_t**)&string))) {
+ if (c == 0x000A) // newline
+ {
+ temp_x = x;
+ temp_y += font->advance_y;
+ } else
+ get_char_bounds(font, c, &temp_x, &temp_y, &minx, &miny, &maxx, &maxy, &props);
+ }
+ temp.width = maxx - x + (margin * 2);
+ temp.height = maxy - miny + (margin * 2);
+ return temp;
+}
+
+void epd_get_text_bounds(
+ const EpdFont* font,
+ const char* string,
+ const int* x,
+ const int* y,
+ int* x1,
+ int* y1,
+ int* w,
+ int* h,
+ const EpdFontProperties* properties
+) {
+ // FIXME: Does not respect alignment!
+
+ assert(properties != NULL);
+ EpdFontProperties props = *properties;
+
+ if (*string == '\0') {
+ *w = 0;
+ *h = 0;
+ *y1 = *y;
+ *x1 = *x;
+ return;
+ }
+ int minx = 100000, miny = 100000, maxx = -1, maxy = -1;
+ int original_x = *x;
+ int temp_x = *x;
+ int temp_y = *y;
+ uint32_t c;
+ while ((c = next_cp((const uint8_t**)&string))) {
+ get_char_bounds(font, c, &temp_x, &temp_y, &minx, &miny, &maxx, &maxy, &props);
+ }
+ *x1 = min(original_x, minx);
+ *w = maxx - *x1;
+ *y1 = miny;
+ *h = maxy - miny;
+}
+
+static enum EpdDrawError epd_write_line(
+ const EpdFont* font,
+ const char* string,
+ int* cursor_x,
+ int* cursor_y,
+ uint8_t* framebuffer,
+ const EpdFontProperties* properties
+) {
+ assert(framebuffer != NULL);
+
+ if (*string == '\0') {
+ return EPD_DRAW_SUCCESS;
+ }
+
+ assert(properties != NULL);
+ EpdFontProperties props = *properties;
+ enum EpdFontFlags alignment_mask
+ = EPD_DRAW_ALIGN_LEFT | EPD_DRAW_ALIGN_RIGHT | EPD_DRAW_ALIGN_CENTER;
+ enum EpdFontFlags alignment = props.flags & alignment_mask;
+
+ // alignments are mutually exclusive!
+ if ((alignment & (alignment - 1)) != 0) {
+ return EPD_DRAW_INVALID_FONT_FLAGS;
+ }
+
+ int x1 = 0, y1 = 0, w = 0, h = 0;
+ int tmp_cur_x = *cursor_x;
+ int tmp_cur_y = *cursor_y;
+ epd_get_text_bounds(font, string, &tmp_cur_x, &tmp_cur_y, &x1, &y1, &w, &h, &props);
+
+ // no printable characters
+ if (w < 0 || h < 0) {
+ return EPD_DRAW_NO_DRAWABLE_CHARACTERS;
+ }
+
+ uint8_t* buffer = framebuffer;
+ int local_cursor_x = *cursor_x;
+ int local_cursor_y = *cursor_y;
+ uint32_t c;
+
+ int cursor_x_init = local_cursor_x;
+ int cursor_y_init = local_cursor_y;
+
+ switch (alignment) {
+ case EPD_DRAW_ALIGN_LEFT: {
+ break;
+ }
+ case EPD_DRAW_ALIGN_CENTER: {
+ local_cursor_x -= w / 2;
+ break;
+ }
+ case EPD_DRAW_ALIGN_RIGHT: {
+ local_cursor_x -= w;
+ break;
+ }
+ default:
+ break;
+ }
+
+ uint8_t bg = props.bg_color;
+ if (props.flags & EPD_DRAW_BACKGROUND) {
+ for (int l = local_cursor_y - font->ascender; l < local_cursor_y - font->descender; l++) {
+ epd_draw_hline(local_cursor_x, l, w, bg << 4, buffer);
+ }
+ }
+ enum EpdDrawError err = EPD_DRAW_SUCCESS;
+ while ((c = next_cp((const uint8_t**)&string))) {
+ err |= draw_char(font, buffer, &local_cursor_x, local_cursor_y, c, &props);
+ }
+
+ *cursor_x += local_cursor_x - cursor_x_init;
+ *cursor_y += local_cursor_y - cursor_y_init;
+ return err;
+}
+
+enum EpdDrawError epd_write_default(
+ const EpdFont* font, const char* string, int* cursor_x, int* cursor_y, uint8_t* framebuffer
+) {
+ const EpdFontProperties props = epd_font_properties_default();
+ return epd_write_string(font, string, cursor_x, cursor_y, framebuffer, &props);
+}
+
+enum EpdDrawError epd_write_string(
+ const EpdFont* font,
+ const char* string,
+ int* cursor_x,
+ int* cursor_y,
+ uint8_t* framebuffer,
+ const EpdFontProperties* properties
+) {
+ char *token, *newstring, *tofree;
+ if (string == NULL) {
+ ESP_LOGE("font.c", "cannot draw a NULL string!");
+ return EPD_DRAW_STRING_INVALID;
+ }
+ tofree = newstring = strdup(string);
+ if (newstring == NULL) {
+ ESP_LOGE("font.c", "cannot allocate string copy!");
+ return EPD_DRAW_FAILED_ALLOC;
+ }
+
+ enum EpdDrawError err = EPD_DRAW_SUCCESS;
+ // taken from the strsep manpage
+ int line_start = *cursor_x;
+ while ((token = strsep(&newstring, "\n")) != NULL) {
+ *cursor_x = line_start;
+ err |= epd_write_line(font, token, cursor_x, cursor_y, framebuffer, properties);
+ *cursor_y += font->advance_y;
+ }
+
+ free(tofree);
+ return err;
+}
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/hacks.cmake b/lib/libesp32_eink/epdiy/src/hacks.cmake
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/hacks.cmake
rename to lib/libesp32_eink/epdiy/src/hacks.cmake
diff --git a/lib/libesp32_eink/epdiy/src/highlevel.c b/lib/libesp32_eink/epdiy/src/highlevel.c
new file mode 100644
index 000000000..0a82b92b4
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/highlevel.c
@@ -0,0 +1,216 @@
+/**
+ * High-level API implementation for epdiy.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "epd_highlevel.h"
+#include "epdiy.h"
+
+#ifndef _swap_int
+#define _swap_int(a, b) \
+ { \
+ int t = a; \
+ a = b; \
+ b = t; \
+ }
+#endif
+
+static bool already_initialized = 0;
+
+EpdiyHighlevelState epd_hl_init(const EpdWaveform* waveform) {
+ assert(!already_initialized);
+ if (waveform == NULL) {
+ waveform = epd_get_display()->default_waveform;
+ }
+
+ int fb_size = epd_width() / 2 * epd_height();
+
+#if !(defined(CONFIG_ESP32_SPIRAM_SUPPORT) || defined(CONFIG_ESP32S3_SPIRAM_SUPPORT))
+ ESP_LOGW(
+ "EPDiy", "Please enable PSRAM for the ESP32 (menuconfig→ Component config→ ESP32-specific)"
+ );
+#endif
+ EpdiyHighlevelState state;
+ state.back_fb = heap_caps_aligned_alloc(16, fb_size, MALLOC_CAP_SPIRAM);
+ assert(state.back_fb != NULL);
+ state.front_fb = heap_caps_aligned_alloc(16, fb_size, MALLOC_CAP_SPIRAM);
+ assert(state.front_fb != NULL);
+ state.difference_fb = heap_caps_aligned_alloc(16, 2 * fb_size, MALLOC_CAP_SPIRAM);
+ assert(state.difference_fb != NULL);
+ state.dirty_lines = malloc(epd_height() * sizeof(bool));
+ assert(state.dirty_lines != NULL);
+ state.dirty_columns
+ = heap_caps_aligned_alloc(16, epd_width() / 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
+ assert(state.dirty_columns != NULL);
+ state.waveform = waveform;
+
+ memset(state.front_fb, 0xFF, fb_size);
+ memset(state.back_fb, 0xFF, fb_size);
+
+ already_initialized = true;
+ return state;
+}
+
+uint8_t* epd_hl_get_framebuffer(EpdiyHighlevelState* state) {
+ assert(state != NULL);
+ return state->front_fb;
+}
+
+enum EpdDrawError epd_hl_update_screen(
+ EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature
+) {
+ return epd_hl_update_area(state, mode, temperature, epd_full_screen());
+}
+
+EpdRect _inverse_rotated_area(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
+ // If partial update uses full screen do not rotate anything
+ if (!(x == 0 && y == 0 && epd_width() == w && epd_height() == h)) {
+ // invert the current display rotation
+ switch (epd_get_rotation()) {
+ // 0 landscape: Leave it as is
+ case EPD_ROT_LANDSCAPE:
+ break;
+ // 1 90 ° clockwise
+ case EPD_ROT_PORTRAIT:
+ _swap_int(x, y);
+ _swap_int(w, h);
+ x = epd_width() - x - w;
+ break;
+
+ case EPD_ROT_INVERTED_LANDSCAPE:
+ // 3 180°
+ x = epd_width() - x - w;
+ y = epd_height() - y - h;
+ break;
+
+ case EPD_ROT_INVERTED_PORTRAIT:
+ // 3 270 °
+ _swap_int(x, y);
+ _swap_int(w, h);
+ y = epd_height() - y - h;
+ break;
+ }
+ }
+
+ EpdRect rotated = { x, y, w, h };
+ return rotated;
+}
+
+enum EpdDrawError epd_hl_update_area(
+ EpdiyHighlevelState* state, enum EpdDrawMode mode, int temperature, EpdRect area
+) {
+ assert(state != NULL);
+ // Not right to rotate here since this copies part of buffer directly
+
+ // Check rotation FIX
+ EpdRect rotated_area = _inverse_rotated_area(area.x, area.y, area.width, area.height);
+ area.x = rotated_area.x;
+ area.y = rotated_area.y;
+ area.width = rotated_area.width;
+ area.height = rotated_area.height;
+
+ uint32_t ts = esp_timer_get_time() / 1000;
+
+ // FIXME: use crop information here, if available
+ EpdRect diff_area = epd_difference_image_cropped(
+ state->front_fb,
+ state->back_fb,
+ area,
+ state->difference_fb,
+ state->dirty_lines,
+ state->dirty_columns
+ );
+
+ if (diff_area.height == 0 || diff_area.width == 0) {
+ return EPD_DRAW_SUCCESS;
+ }
+
+ uint32_t t1 = esp_timer_get_time() / 1000;
+
+ diff_area.x = 0;
+ diff_area.y = 0;
+ diff_area.width = epd_width();
+ diff_area.height = epd_height();
+
+ enum EpdDrawError err = EPD_DRAW_SUCCESS;
+ err = epd_draw_base(
+ epd_full_screen(),
+ state->difference_fb,
+ diff_area,
+ MODE_PACKING_1PPB_DIFFERENCE | mode,
+ temperature,
+ state->dirty_lines,
+ state->dirty_columns,
+ state->waveform
+ );
+
+ uint32_t t2 = esp_timer_get_time() / 1000;
+
+ diff_area.x = 0;
+ diff_area.y = 0;
+ diff_area.width = epd_width();
+ diff_area.height = epd_height();
+
+ int buf_width = epd_width();
+
+ for (int l = diff_area.y; l < diff_area.y + diff_area.height; l++) {
+ if (state->dirty_lines[l] > 0) {
+ uint8_t* lfb = state->front_fb + buf_width / 2 * l;
+ uint8_t* lbb = state->back_fb + buf_width / 2 * l;
+
+ int x = diff_area.x;
+ int x_last = diff_area.x + diff_area.width - 1;
+
+ if (x % 2) {
+ *(lbb + x / 2) = (*(lfb + x / 2) & 0xF0) | (*(lbb + x / 2) & 0x0F);
+ x += 1;
+ }
+
+ if (!(x_last % 2)) {
+ *(lbb + x_last / 2) = (*(lfb + x_last / 2) & 0x0F) | (*(lbb + x_last / 2) & 0xF0);
+ x_last -= 1;
+ }
+
+ memcpy(lbb + (x / 2), lfb + (x / 2), (x_last - x + 1) / 2);
+ }
+ }
+
+ uint32_t t3 = esp_timer_get_time() / 1000;
+
+ ESP_LOGI(
+ "epdiy",
+ "diff: %dms, draw: %dms, buffer update: %dms, total: %dms",
+ t1 - ts,
+ t2 - t1,
+ t3 - t2,
+ t3 - ts
+ );
+ return err;
+}
+
+void epd_hl_set_all_white(EpdiyHighlevelState* state) {
+ assert(state != NULL);
+ int fb_size = epd_width() / 2 * epd_height();
+ memset(state->front_fb, 0xFF, fb_size);
+}
+
+void epd_fullclear(EpdiyHighlevelState* state, int temperature) {
+ assert(state != NULL);
+ epd_hl_set_all_white(state);
+ enum EpdDrawError err = epd_hl_update_screen(state, MODE_GC16, temperature);
+ assert(err == EPD_DRAW_SUCCESS);
+ epd_clear();
+}
+
+void epd_hl_waveform(EpdiyHighlevelState* state, const EpdWaveform* waveform) {
+ if (waveform == NULL) {
+ waveform = epd_get_display()->default_waveform;
+ }
+ state->waveform = waveform;
+}
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_common/line_queue.c b/lib/libesp32_eink/epdiy/src/output_common/line_queue.c
new file mode 100644
index 000000000..5a2dfa604
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/line_queue.c
@@ -0,0 +1,86 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "line_queue.h"
+#include "render_method.h"
+
+static inline int ceil_div(int x, int y) {
+ return x / y + (x % y != 0);
+}
+
+/// Initialize the line queue and allocate memory.
+LineQueue_t lq_init(int queue_len, int element_size) {
+ LineQueue_t queue;
+ queue.element_size = element_size;
+ queue.size = queue_len;
+ queue.current = 0;
+ queue.last = 0;
+
+ int elem_buf_size = ceil_div(element_size, 16) * 16;
+
+ queue.bufs = calloc(queue.size, elem_buf_size);
+ assert(queue.bufs != NULL);
+
+ for (int i = 0; i < queue.size; i++) {
+ queue.bufs[i] = heap_caps_aligned_alloc(16, elem_buf_size, MALLOC_CAP_INTERNAL);
+ assert(queue.bufs[i] != NULL);
+ }
+
+ return queue;
+}
+
+/// Deinitialize the line queue and free memory.
+void lq_free(LineQueue_t* queue) {
+ for (int i = 0; i < queue->size; i++) {
+ heap_caps_free(queue->bufs[i]);
+ }
+
+ free(queue->bufs);
+}
+
+uint8_t* IRAM_ATTR lq_current(LineQueue_t* queue) {
+ int current = atomic_load_explicit(&queue->current, memory_order_acquire);
+ int last = atomic_load_explicit(&queue->last, memory_order_acquire);
+
+ if ((current + 1) % queue->size == last) {
+ return NULL;
+ }
+ return queue->bufs[current];
+}
+
+void IRAM_ATTR lq_commit(LineQueue_t* queue) {
+ int current = atomic_load_explicit(&queue->current, memory_order_acquire);
+
+ if (current == queue->size - 1) {
+ queue->current = 0;
+ } else {
+ atomic_fetch_add(&queue->current, 1);
+ }
+}
+
+int IRAM_ATTR lq_read(LineQueue_t* queue, uint8_t* dst) {
+ int current = atomic_load_explicit(&queue->current, memory_order_acquire);
+ int last = atomic_load_explicit(&queue->last, memory_order_acquire);
+
+ if (current == last) {
+ return -1;
+ }
+
+ memcpy(dst, queue->bufs[last], queue->element_size);
+
+ if (last == queue->size - 1) {
+ queue->last = 0;
+ } else {
+ atomic_fetch_add(&queue->last, 1);
+ }
+ return 0;
+}
+
+void IRAM_ATTR lq_reset(LineQueue_t* queue) {
+ queue->current = 0;
+ queue->last = 0;
+}
diff --git a/lib/libesp32_eink/epdiy/src/output_common/line_queue.h b/lib/libesp32_eink/epdiy/src/output_common/line_queue.h
new file mode 100644
index 000000000..e6fa81de2
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/line_queue.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/// Circular line queue with atomic read / write operations
+/// and accelerated masking on the output buffer.
+typedef struct {
+ int size;
+ atomic_int current;
+ atomic_int last;
+ uint8_t** bufs;
+ // size of an element
+ size_t element_size;
+} LineQueue_t;
+
+/// Initialize the line queue and allocate memory.
+LineQueue_t lq_init(int queue_len, int element_size);
+
+/// Deinitialize the line queue and free memory.
+void lq_free(LineQueue_t* queue);
+
+/// Pointer to the next empty element in the line queue.
+///
+/// NULL if the queue is currently full.
+uint8_t* lq_current(LineQueue_t* queue);
+
+/// Advance the line queue.
+void lq_commit(LineQueue_t* queue);
+
+/// Read from the line queue.
+///
+/// Returns 0 for a successful read to `dst`, -1 for a failed read (empty queue).
+int lq_read(LineQueue_t* queue, uint8_t* dst);
+
+/// Reset the queue into an empty state.
+/// This operation is *not* atomic!
+void lq_reset(LineQueue_t* queue);
diff --git a/lib/libesp32_eink/epdiy/src/output_common/lut.S b/lib/libesp32_eink/epdiy/src/output_common/lut.S
new file mode 100644
index 000000000..3bbbaaa73
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/lut.S
@@ -0,0 +1,145 @@
+#include
+#include
+#include "sdkconfig.h"
+
+#ifdef CONFIG_IDF_TARGET_ESP32S3
+
+.text
+.align 4
+.global calc_epd_input_1ppB_1k_S3_VE_aligned
+.type calc_epd_input_1ppB_1k_S3_VE_aligned,@function
+
+// // CRASH AND BURN for debugging
+// EE.MOVI.32.A q3, a2, 0
+// EE.MOVI.32.A q3, a3, 1
+// EE.MOVI.32.A q3, a4, 2
+// EE.MOVI.32.A q3, a5, 3
+// l8ui a10, a10, 0
+
+// void calc_epd_input_1ppB_1k_S3_VE_aligned(
+// const uint32_t *ld,
+// uint8_t *epd_input,
+// const uint8_t *conversion_lut,
+// uint32_t epd_width
+//);
+calc_epd_input_1ppB_1k_S3_VE_aligned:
+// input - a2
+// output - a3
+// lut - a4
+// len - a5
+
+ entry a1, 32
+
+ // divide by 16 and do one loop lesss,
+ // because the last loop is special
+ srli a5, a5, 4
+ addi.n a5, a5, -1
+
+
+ // bitmasks for bit shift by multiplication
+ movi.n a10, 0x40001000
+ EE.MOVI.32.Q q4,a10,0
+ movi.n a10, 0x04000100
+ EE.MOVI.32.Q q4,a10,1
+ movi.n a10, 0x00400010
+ EE.MOVI.32.Q q4,a10,2
+ movi a10, 0x00040001
+ EE.MOVI.32.Q q4,a10,3
+
+ EE.ZERO.Q q0
+
+ EE.VLD.128.IP q1, a2, 16
+
+ // Instructions sometimes are in an unexpected order
+ // for best pipeline utilization
+ loopnez a5, .loop_end_lut_lookup
+
+ // q1, q0 contain the input bytes, zero-extended to bits bytes
+ EE.VZIP.8 q1, q0
+
+ // load 32-bit LUT results
+ EE.LDXQ.32 q2, q0, a4, 0, 6
+ EE.LDXQ.32 q2, q0, a4, 1, 7
+ EE.LDXQ.32 q2, q0, a4, 2, 4
+ EE.LDXQ.32 q2, q0, a4, 3, 5
+ EE.LDXQ.32 q3, q0, a4, 0, 2
+ EE.LDXQ.32 q3, q0, a4, 1, 3
+ EE.LDXQ.32 q3, q0, a4, 2, 0
+ EE.LDXQ.32 q3, q0, a4, 3, 1
+
+ EE.ZERO.ACCX
+
+ // zip to have 16bit LUT results in q2, q3 zeroes
+ EE.VUNZIP.16 q2, q3
+
+ // combine results with using multiply-add as shift-or
+ EE.VMULAS.U16.ACCX q2,q4
+
+ // load 32-bit LUT results
+ EE.LDXQ.32 q2, q1, a4, 0, 6
+ EE.LDXQ.32 q2, q1, a4, 1, 7
+ EE.LDXQ.32 q2, q1, a4, 2, 4
+ EE.LDXQ.32 q2, q1, a4, 3, 5
+ EE.LDXQ.32 q0, q1, a4, 0, 2
+ EE.LDXQ.32 q0, q1, a4, 1, 3
+ EE.LDXQ.32 q0, q1, a4, 2, 0
+ EE.LDXQ.32 q0, q1, a4, 3, 1
+
+ // store multiplication result in a6
+ RUR.ACCX_0 a6
+ s16i a6, a3, 2
+
+ EE.ZERO.ACCX
+
+ // zip to have 16bit LUT results in q2, q0 zeroes
+ EE.VUNZIP.16 q2, q0
+
+ // Combine second set of results and load the next data
+ EE.VMULAS.U16.ACCX.LD.IP q1, a2, 16, q2, q4
+
+ // store result in a6
+ RUR.ACCX_0 a6
+ s16i a6, a3, 0
+
+ addi.n a3, a3, 4
+.loop_end_lut_lookup:
+
+ // Same as above, but in the last iteration
+ // we do not load to not access out of bounds.
+ EE.VZIP.8 q1, q0
+
+ EE.LDXQ.32 q2, q0, a4, 0, 6
+ EE.LDXQ.32 q2, q0, a4, 1, 7
+ EE.LDXQ.32 q2, q0, a4, 2, 4
+ EE.LDXQ.32 q2, q0, a4, 3, 5
+ EE.LDXQ.32 q3, q0, a4, 0, 2
+ EE.LDXQ.32 q3, q0, a4, 1, 3
+ EE.LDXQ.32 q3, q0, a4, 2, 0
+ EE.LDXQ.32 q3, q0, a4, 3, 1
+
+ EE.ZERO.ACCX
+ EE.VUNZIP.16 q2, q3
+ EE.VMULAS.U16.ACCX q2,q4
+
+ EE.LDXQ.32 q2, q1, a4, 0, 6
+ EE.LDXQ.32 q2, q1, a4, 1, 7
+ EE.LDXQ.32 q2, q1, a4, 2, 4
+ EE.LDXQ.32 q2, q1, a4, 3, 5
+ EE.LDXQ.32 q0, q1, a4, 0, 2
+ EE.LDXQ.32 q0, q1, a4, 1, 3
+ EE.LDXQ.32 q0, q1, a4, 2, 0
+ EE.LDXQ.32 q0, q1, a4, 3, 1
+
+ RUR.ACCX_0 a6
+ s16i a6, a3, 2
+ EE.ZERO.ACCX
+
+ EE.VUNZIP.16 q2, q0
+ EE.VMULAS.U16.ACCX q2, q4
+ RUR.ACCX_0 a6
+ s16i a6, a3, 0
+
+ movi.n a2, 0 // return status ESP_OK
+ retw.n
+
+#endif
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_common/lut.c b/lib/libesp32_eink/epdiy/src/output_common/lut.c
new file mode 100644
index 000000000..f19ef135e
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/lut.c
@@ -0,0 +1,495 @@
+#include "lut.h"
+
+#include "epdiy.h"
+#include "esp_attr.h"
+#include "render_context.h"
+#include "render_method.h"
+
+#include
+#include
+#include
+
+#include "esp_timer.h"
+
+/*
+ * Build Lookup tables and translate via LUTs.
+ * WARNING: These functions must only ever write to internal memory,
+ * Since we disable the PSRAM workaround here for performance reasons.
+ */
+
+/* Python script for generating the 8ppB, starting at white lookup table:
+ for i in range(256):
+ number = 0;
+ for b in range(8):
+ if not (i & (1 << b)):
+ number |= 1 << (2*b)
+ print ('0x%04x,'%number)
+ */
+const uint32_t lut_8ppB_start_at_white[256] = {
+ 0x5555, 0x5554, 0x5551, 0x5550, 0x5545, 0x5544, 0x5541, 0x5540, 0x5515, 0x5514, 0x5511, 0x5510,
+ 0x5505, 0x5504, 0x5501, 0x5500, 0x5455, 0x5454, 0x5451, 0x5450, 0x5445, 0x5444, 0x5441, 0x5440,
+ 0x5415, 0x5414, 0x5411, 0x5410, 0x5405, 0x5404, 0x5401, 0x5400, 0x5155, 0x5154, 0x5151, 0x5150,
+ 0x5145, 0x5144, 0x5141, 0x5140, 0x5115, 0x5114, 0x5111, 0x5110, 0x5105, 0x5104, 0x5101, 0x5100,
+ 0x5055, 0x5054, 0x5051, 0x5050, 0x5045, 0x5044, 0x5041, 0x5040, 0x5015, 0x5014, 0x5011, 0x5010,
+ 0x5005, 0x5004, 0x5001, 0x5000, 0x4555, 0x4554, 0x4551, 0x4550, 0x4545, 0x4544, 0x4541, 0x4540,
+ 0x4515, 0x4514, 0x4511, 0x4510, 0x4505, 0x4504, 0x4501, 0x4500, 0x4455, 0x4454, 0x4451, 0x4450,
+ 0x4445, 0x4444, 0x4441, 0x4440, 0x4415, 0x4414, 0x4411, 0x4410, 0x4405, 0x4404, 0x4401, 0x4400,
+ 0x4155, 0x4154, 0x4151, 0x4150, 0x4145, 0x4144, 0x4141, 0x4140, 0x4115, 0x4114, 0x4111, 0x4110,
+ 0x4105, 0x4104, 0x4101, 0x4100, 0x4055, 0x4054, 0x4051, 0x4050, 0x4045, 0x4044, 0x4041, 0x4040,
+ 0x4015, 0x4014, 0x4011, 0x4010, 0x4005, 0x4004, 0x4001, 0x4000, 0x1555, 0x1554, 0x1551, 0x1550,
+ 0x1545, 0x1544, 0x1541, 0x1540, 0x1515, 0x1514, 0x1511, 0x1510, 0x1505, 0x1504, 0x1501, 0x1500,
+ 0x1455, 0x1454, 0x1451, 0x1450, 0x1445, 0x1444, 0x1441, 0x1440, 0x1415, 0x1414, 0x1411, 0x1410,
+ 0x1405, 0x1404, 0x1401, 0x1400, 0x1155, 0x1154, 0x1151, 0x1150, 0x1145, 0x1144, 0x1141, 0x1140,
+ 0x1115, 0x1114, 0x1111, 0x1110, 0x1105, 0x1104, 0x1101, 0x1100, 0x1055, 0x1054, 0x1051, 0x1050,
+ 0x1045, 0x1044, 0x1041, 0x1040, 0x1015, 0x1014, 0x1011, 0x1010, 0x1005, 0x1004, 0x1001, 0x1000,
+ 0x0555, 0x0554, 0x0551, 0x0550, 0x0545, 0x0544, 0x0541, 0x0540, 0x0515, 0x0514, 0x0511, 0x0510,
+ 0x0505, 0x0504, 0x0501, 0x0500, 0x0455, 0x0454, 0x0451, 0x0450, 0x0445, 0x0444, 0x0441, 0x0440,
+ 0x0415, 0x0414, 0x0411, 0x0410, 0x0405, 0x0404, 0x0401, 0x0400, 0x0155, 0x0154, 0x0151, 0x0150,
+ 0x0145, 0x0144, 0x0141, 0x0140, 0x0115, 0x0114, 0x0111, 0x0110, 0x0105, 0x0104, 0x0101, 0x0100,
+ 0x0055, 0x0054, 0x0051, 0x0050, 0x0045, 0x0044, 0x0041, 0x0040, 0x0015, 0x0014, 0x0011, 0x0010,
+ 0x0005, 0x0004, 0x0001, 0x0000
+};
+
+/* Python script for generating the 8ppB, starting at black lookup table:
+ for i in range(256):
+ number = 0;
+ for b in range(8):
+ if (i & (1 << b)):
+ number |= 2 << (2*b)
+ print ('0x%04x,'%number)
+ */
+const uint32_t lut_8ppB_start_at_black[256] = {
+ 0x0000, 0x0002, 0x0008, 0x000a, 0x0020, 0x0022, 0x0028, 0x002a, 0x0080, 0x0082, 0x0088, 0x008a,
+ 0x00a0, 0x00a2, 0x00a8, 0x00aa, 0x0200, 0x0202, 0x0208, 0x020a, 0x0220, 0x0222, 0x0228, 0x022a,
+ 0x0280, 0x0282, 0x0288, 0x028a, 0x02a0, 0x02a2, 0x02a8, 0x02aa, 0x0800, 0x0802, 0x0808, 0x080a,
+ 0x0820, 0x0822, 0x0828, 0x082a, 0x0880, 0x0882, 0x0888, 0x088a, 0x08a0, 0x08a2, 0x08a8, 0x08aa,
+ 0x0a00, 0x0a02, 0x0a08, 0x0a0a, 0x0a20, 0x0a22, 0x0a28, 0x0a2a, 0x0a80, 0x0a82, 0x0a88, 0x0a8a,
+ 0x0aa0, 0x0aa2, 0x0aa8, 0x0aaa, 0x2000, 0x2002, 0x2008, 0x200a, 0x2020, 0x2022, 0x2028, 0x202a,
+ 0x2080, 0x2082, 0x2088, 0x208a, 0x20a0, 0x20a2, 0x20a8, 0x20aa, 0x2200, 0x2202, 0x2208, 0x220a,
+ 0x2220, 0x2222, 0x2228, 0x222a, 0x2280, 0x2282, 0x2288, 0x228a, 0x22a0, 0x22a2, 0x22a8, 0x22aa,
+ 0x2800, 0x2802, 0x2808, 0x280a, 0x2820, 0x2822, 0x2828, 0x282a, 0x2880, 0x2882, 0x2888, 0x288a,
+ 0x28a0, 0x28a2, 0x28a8, 0x28aa, 0x2a00, 0x2a02, 0x2a08, 0x2a0a, 0x2a20, 0x2a22, 0x2a28, 0x2a2a,
+ 0x2a80, 0x2a82, 0x2a88, 0x2a8a, 0x2aa0, 0x2aa2, 0x2aa8, 0x2aaa, 0x8000, 0x8002, 0x8008, 0x800a,
+ 0x8020, 0x8022, 0x8028, 0x802a, 0x8080, 0x8082, 0x8088, 0x808a, 0x80a0, 0x80a2, 0x80a8, 0x80aa,
+ 0x8200, 0x8202, 0x8208, 0x820a, 0x8220, 0x8222, 0x8228, 0x822a, 0x8280, 0x8282, 0x8288, 0x828a,
+ 0x82a0, 0x82a2, 0x82a8, 0x82aa, 0x8800, 0x8802, 0x8808, 0x880a, 0x8820, 0x8822, 0x8828, 0x882a,
+ 0x8880, 0x8882, 0x8888, 0x888a, 0x88a0, 0x88a2, 0x88a8, 0x88aa, 0x8a00, 0x8a02, 0x8a08, 0x8a0a,
+ 0x8a20, 0x8a22, 0x8a28, 0x8a2a, 0x8a80, 0x8a82, 0x8a88, 0x8a8a, 0x8aa0, 0x8aa2, 0x8aa8, 0x8aaa,
+ 0xa000, 0xa002, 0xa008, 0xa00a, 0xa020, 0xa022, 0xa028, 0xa02a, 0xa080, 0xa082, 0xa088, 0xa08a,
+ 0xa0a0, 0xa0a2, 0xa0a8, 0xa0aa, 0xa200, 0xa202, 0xa208, 0xa20a, 0xa220, 0xa222, 0xa228, 0xa22a,
+ 0xa280, 0xa282, 0xa288, 0xa28a, 0xa2a0, 0xa2a2, 0xa2a8, 0xa2aa, 0xa800, 0xa802, 0xa808, 0xa80a,
+ 0xa820, 0xa822, 0xa828, 0xa82a, 0xa880, 0xa882, 0xa888, 0xa88a, 0xa8a0, 0xa8a2, 0xa8a8, 0xa8aa,
+ 0xaa00, 0xaa02, 0xaa08, 0xaa0a, 0xaa20, 0xaa22, 0xaa28, 0xaa2a, 0xaa80, 0xaa82, 0xaa88, 0xaa8a,
+ 0xaaa0, 0xaaa2, 0xaaa8, 0xaaaa,
+};
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+static inline int max(int x, int y) {
+ return x > y ? x : y;
+}
+
+// status tracker for row skipping
+uint32_t skipping;
+
+__attribute__((optimize("O3"))) void IRAM_ATTR
+reorder_line_buffer(uint32_t* line_data, int buf_len) {
+ for (uint32_t i = 0; i < buf_len / 4; i++) {
+ uint32_t val = *line_data;
+ *(line_data++) = val >> 16 | ((val & 0x0000FFFF) << 16);
+ }
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR
+bit_shift_buffer_right(uint8_t* buf, uint32_t len, int shift) {
+ uint8_t carry = 0xFF << (8 - shift);
+ for (uint32_t i = 0; i < len; i++) {
+ uint8_t val = buf[i];
+ buf[i] = (val >> shift) | carry;
+ carry = val << (8 - shift);
+ }
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR
+nibble_shift_buffer_right(uint8_t* buf, uint32_t len) {
+ uint8_t carry = 0xF;
+ for (uint32_t i = 0; i < len; i++) {
+ uint8_t val = buf[i];
+ buf[i] = (val << 4) | carry;
+ carry = (val & 0xF0) >> 4;
+ }
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_8ppB(
+ const uint32_t* line_data, uint8_t* epd_input, const uint8_t* lut, uint32_t epd_width
+) {
+ uint32_t* wide_epd_input = (uint32_t*)epd_input;
+ uint8_t* data_ptr = (uint8_t*)line_data;
+ uint32_t* lut_32 = (uint32_t*)lut;
+ // this is reversed for little-endian, but this is later compensated
+ // through the output peripheral.
+ for (int j = 0; j < epd_width / 16; j++) {
+ uint8_t v1 = *(data_ptr++);
+ uint8_t v2 = *(data_ptr++);
+ wide_epd_input[j] = (lut_32[v2] << 16) | lut_32[v1];
+ }
+
+ // Account for missing line end if epd_width is not divisible by 16.
+ // We assume divisibility by 4.
+ for (int j = 0; j < (epd_width % 16) / 4; j++) {
+ uint8_t nibble = *data_ptr;
+ if (j % 2 == 1) {
+ nibble = nibble >> 4;
+ data_ptr++;
+ } else {
+ nibble = nibble & 0xF;
+ }
+ epd_input[(epd_width / 16) * 4 + j] = lut_32[nibble];
+ }
+}
+
+/**
+ * Look up 4 pixels of a differential image in a LUT constructed for use with vector extensions.
+ */
+__attribute__((optimize("O3"))) static inline uint8_t lookup_pixels_in_VE_LUT(
+ const uint32_t in, const uint8_t* conversion_lut
+) {
+ uint32_t* padded_lut = (uint32_t*)conversion_lut;
+ uint8_t out = padded_lut[(in >> 24) & 0xFF] << 6;
+ out |= padded_lut[(in >> 16) & 0xFF] << 4;
+ out |= padded_lut[(in >> 8) & 0xFF] << 2;
+ out |= padded_lut[(in >> 0) & 0xFF];
+ return out;
+}
+
+/**
+ * Lookup accelerated by the S3 Vector Extensions.
+ * Expects aligned buffers and a length that is divisible by 16.
+ */
+void IRAM_ATTR calc_epd_input_1ppB_1k_S3_VE_aligned(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+);
+
+#ifdef RENDER_METHOD_I2S
+void calc_epd_input_1ppB_1k_S3_VE_aligned(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ // dummy implementation, should never be called.
+ abort();
+}
+#endif
+
+/**
+ * Lookup accelerated by the S3 Vector Extensions.
+ * Uses a 1K padded LUT (each entry takes up 32 bits)
+ */
+void IRAM_ATTR calc_epd_input_1ppB_1k_S3_VE(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ // alignment boundaries in pixels
+ int unaligned_len_front = (16 - (uint32_t)ld % 16) % 16;
+ int unaligned_len_back = ((uint32_t)ld + epd_width) % 16;
+ int aligned_len = epd_width - unaligned_len_front - unaligned_len_back;
+
+ if (unaligned_len_front) {
+ for (int i = 0; i < unaligned_len_front / 4; i++) {
+ (*epd_input++) = lookup_pixels_in_VE_LUT((*ld++), conversion_lut);
+ }
+ }
+ calc_epd_input_1ppB_1k_S3_VE_aligned(ld, epd_input, conversion_lut, aligned_len);
+
+ ld += aligned_len / 4;
+ epd_input += aligned_len / 4;
+
+ if (unaligned_len_back) {
+ for (int i = 0; i < unaligned_len_back / 4; i++) {
+ (*epd_input++) = lookup_pixels_in_VE_LUT((*ld++), conversion_lut);
+ }
+ }
+}
+
+/**
+ * Calculate EPD input for a difference image with one pixel per byte.
+ */
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_1ppB_64k(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ const uint16_t* lp = (uint16_t*)ld;
+ for (uint32_t j = 0; j < epd_width / 4; j++) {
+ epd_input[j] = (conversion_lut[lp[2 * j + 1]] << 4) | conversion_lut[lp[2 * j]];
+ }
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_2ppB_lut_64k(
+ const uint32_t* line_data, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ const uint16_t* line_data_16 = (const uint16_t*)line_data;
+
+ for (uint32_t j = 0; j < epd_width / 4; j++) {
+ epd_input[j] = conversion_lut[*(line_data_16++)];
+ }
+}
+
+/**
+ * Look up 4 pixels in a 1K LUT with fixed "from" value.
+ */
+__attribute__((optimize("O3"))) static uint8_t lookup_pixels_2ppB_1k(
+ uint16_t in, const uint8_t* conversion_lut, uint8_t from
+) {
+ uint8_t v;
+ uint8_t out;
+
+ v = ((in << 4) | from);
+ out = conversion_lut[v & 0xFF];
+ v = ((in & 0xF0) | from);
+ out |= (conversion_lut + 0x100)[v & 0xFF];
+ in = in >> 8;
+ v = ((in << 4) | from);
+ out |= (conversion_lut + 0x200)[v & 0xFF];
+ v = ((in & 0xF0) | from);
+ out |= (conversion_lut + 0x300)[v];
+ return out;
+}
+
+/**
+ * Calculate EPD input for a 2ppB buffer, but with a difference image LUT.
+ * This is used for small-LUT mode.
+ */
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_2ppB_1k_lut(
+ const uint32_t* ld,
+ uint8_t* epd_input,
+ const uint8_t* conversion_lut,
+ uint8_t from,
+ uint32_t epd_width
+) {
+ const uint16_t* line_data_16 = (const uint16_t*)ld;
+
+ for (uint32_t j = 0; j < epd_width / 4; j++) {
+ epd_input[j] = lookup_pixels_2ppB_1k(*(line_data_16++), conversion_lut, from);
+ };
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_2ppB_1k_lut_white(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ calc_epd_input_2ppB_1k_lut(ld, epd_input, conversion_lut, 0xF, epd_width);
+}
+
+__attribute__((optimize("O3"))) void IRAM_ATTR calc_epd_input_2ppB_1k_lut_black(
+ const uint32_t* ld, uint8_t* epd_input, const uint8_t* conversion_lut, uint32_t epd_width
+) {
+ calc_epd_input_2ppB_1k_lut(ld, epd_input, conversion_lut, 0x0, epd_width);
+}
+
+///////////////////////////// Calculate Lookup Tables
+//////////////////////////////////
+
+/**
+ * Unpack the waveform data into a lookup table, with bit shifted copies.
+ */
+__attribute__((optimize("O3"))) static void IRAM_ATTR
+build_2ppB_lut_1k(uint8_t* lut, const EpdWaveformPhases* phases, int frame) {
+ const uint8_t* p_lut = phases->luts + (16 * 4 * frame);
+ for (uint8_t to = 0; to < 16; to++) {
+ for (uint8_t from_packed = 0; from_packed < 4; from_packed++) {
+ uint8_t index = (to << 4) | (from_packed * 4);
+ uint8_t packed = *(p_lut++);
+ lut[index] = (packed >> 6) & 3;
+ lut[index + 1] = (packed >> 4) & 3;
+ lut[index + 2] = (packed >> 2) & 3;
+ lut[index + 3] = (packed >> 0) & 3;
+ // printf("%2X%2X%2X%2X (%d)", lut[index], lut[index + 1], lut[index + 2],
+ // lut[index + 3], index);
+ }
+ // printf("\n");
+ }
+ uint32_t index = 0x100;
+ for (uint8_t s = 2; s <= 6; s += 2) {
+ for (int i = 0; i < 0x100; i++) {
+ lut[index] = lut[index % 0x100] << s;
+ index++;
+ }
+ }
+}
+
+/**
+ * Unpack the waveform data into a lookup table,
+ * 64k to loop up two bytes at once
+ */
+__attribute__((optimize("O3"))) static void IRAM_ATTR
+build_1ppB_lut_64k(uint8_t* lut, const EpdWaveformPhases* phases, int frame) {
+ const uint8_t* p_lut = phases->luts + (16 * 4 * frame);
+ for (uint8_t to = 0; to < 16; to++) {
+ for (uint8_t from_packed = 0; from_packed < 4; from_packed++) {
+ uint8_t index = (to << 4) | (from_packed * 4);
+ uint8_t packed = *(p_lut++);
+ lut[index] = (packed >> 6) & 3;
+ lut[index + 1] = (packed >> 4) & 3;
+ lut[index + 2] = (packed >> 2) & 3;
+ lut[index + 3] = (packed >> 0) & 3;
+ // printf("%2X%2X%2X%2X (%d)", lut[index], lut[index + 1], lut[index + 2],
+ // lut[index + 3], index);
+ }
+ // printf("\n");
+ }
+
+ for (int outer = 0xFF; outer >= 0; outer--) {
+ uint32_t outer_result = lut[outer] << 2;
+ outer_result |= (outer_result << 16);
+ outer_result |= (outer_result << 8);
+ uint32_t* lut_section = (uint32_t*)(&lut[outer << 8]);
+ memcpy(lut_section, lut, 0x100);
+ for (int i = 0; i < 0x100 / 4; i++) {
+ lut_section[i] = lut_section[i] | outer_result;
+ }
+ }
+}
+
+/**
+ * A 32bit aligned lookup table for lookup using the ESP32-S3 vector extensions.
+ */
+__attribute__((optimize("O3"))) static void IRAM_ATTR
+build_1ppB_lut_S3_VE_1k(uint8_t* lut, const EpdWaveformPhases* phases, int frame) {
+ uint32_t* lut32 = (uint32_t*)lut;
+ const uint8_t* p_lut = phases->luts + (16 * 4 * frame);
+ for (uint8_t to = 0; to < 16; to++) {
+ for (uint8_t from_packed = 0; from_packed < 4; from_packed++) {
+ uint8_t index = (to << 4) | (from_packed * 4);
+ uint8_t packed = *(p_lut++);
+ lut32[index] = (packed >> 6) & 3;
+ lut32[index + 1] = (packed >> 4) & 3;
+ lut32[index + 2] = (packed >> 2) & 3;
+ lut32[index + 3] = (packed >> 0) & 3;
+ }
+ }
+}
+
+/**
+ * Build a 16-bit LUT from the waveform if the previous color is
+ * known, e.g. all white or all black.
+ * This LUT is use to look up 4 pixels at once, as with the epdiy LUT.
+ */
+__attribute__((optimize("O3"))) static void build_2ppB_lut_64k_static_from(
+ uint8_t* lut, const EpdWaveformPhases* phases, uint8_t from, int frame
+) {
+ const uint8_t* p_lut = phases->luts + (16 * 4 * frame);
+
+ /// index into the packed "from" row
+ uint8_t fi = from >> 2;
+ /// bit shift amount for the packed "from" row
+ uint8_t fs = 6 - 2 * (from & 3);
+
+ // populate the first 4096 bytes
+ uint8_t v1 = 0;
+ uint32_t s1 = 0;
+ for (uint8_t t2 = 0; t2 < 16; t2++) {
+ uint8_t v2 = ((p_lut[(t2 << 2) + fi] >> fs) & 0x03) << 4;
+ uint32_t s2 = t2 << 8;
+ for (uint8_t t3 = 0; t3 < 16; t3++) {
+ uint8_t v3 = ((p_lut[(t3 << 2) + fi] >> fs) & 0x03) << 2;
+ uint32_t s3 = t3 << 4;
+ for (uint8_t t4 = 0; t4 < 16; t4++) {
+ uint8_t v4 = ((p_lut[(t4 << 2) + fi] >> fs) & 0x03) << 0;
+ uint32_t s4 = t4;
+ lut[s1 | s2 | s3 | s4] = v1 | v2 | v3 | v4;
+ }
+ }
+ }
+
+ // now just copy and the first 4096 bytes and add the upper two bits
+ for (uint8_t t1 = 1; t1 < 16; t1++) {
+ memcpy(&lut[t1 << 12], lut, 1 << 12);
+ }
+
+ for (int i = 0; i < 16; i++) {
+ uint32_t v1 = ((p_lut[(i << 2) + fi] >> fs) & 0x03);
+ uint32_t mask = (v1 << 30) | (v1 << 22) | (v1 << 14) | (v1 << 6);
+ for (int j = 0; j < 16 * 16 * 16 / 4; j++) {
+ ((uint32_t*)lut)[(i << 10) + j] |= mask;
+ }
+ }
+}
+
+static void build_2ppB_lut_64k_from_0(uint8_t* lut, const EpdWaveformPhases* phases, int frame) {
+ build_2ppB_lut_64k_static_from(lut, phases, 0, frame);
+}
+
+static void build_2ppB_lut_64k_from_15(uint8_t* lut, const EpdWaveformPhases* phases, int frame) {
+ build_2ppB_lut_64k_static_from(lut, phases, 0xF, frame);
+}
+
+static void build_8ppB_lut_256b_from_white(
+ uint8_t* lut, const EpdWaveformPhases* phases, int frame
+) {
+ memcpy(lut, lut_8ppB_start_at_white, sizeof(lut_8ppB_start_at_white));
+}
+
+static void build_8ppB_lut_256b_from_black(
+ uint8_t* lut, const EpdWaveformPhases* phases, int frame
+) {
+ memcpy(lut, lut_8ppB_start_at_black, sizeof(lut_8ppB_start_at_black));
+}
+
+void IRAM_ATTR epd_apply_line_mask(uint8_t* buf, const uint8_t* mask, int len) {
+ for (int i = 0; i < len / 4; i++) {
+ ((uint32_t*)buf)[i] &= ((uint32_t*)mask)[i];
+ }
+}
+
+LutFunctionPair find_lut_functions(enum EpdDrawMode mode, uint32_t lut_size) {
+ LutFunctionPair pair;
+ pair.build_func = NULL;
+ pair.lookup_func = NULL;
+
+ if (mode & MODE_PACKING_1PPB_DIFFERENCE) {
+ if (EPD_CURRENT_RENDER_METHOD == RENDER_METHOD_LCD && !(mode & MODE_FORCE_NO_PIE)
+ && lut_size >= 1024) {
+ pair.build_func = &build_1ppB_lut_S3_VE_1k;
+ pair.lookup_func = &calc_epd_input_1ppB_1k_S3_VE;
+ return pair;
+ } else if (lut_size >= 1 << 16) {
+ pair.build_func = &build_1ppB_lut_64k;
+ pair.lookup_func = &calc_epd_input_1ppB_64k;
+ return pair;
+ }
+ } else if (mode & MODE_PACKING_2PPB) {
+ if (lut_size >= 1 << 16) {
+ if (mode & PREVIOUSLY_WHITE) {
+ pair.build_func = &build_2ppB_lut_64k_from_15;
+ pair.lookup_func = &calc_epd_input_2ppB_lut_64k;
+ return pair;
+ } else if (mode & PREVIOUSLY_BLACK) {
+ pair.build_func = &build_2ppB_lut_64k_from_0;
+ pair.lookup_func = &calc_epd_input_2ppB_lut_64k;
+ return pair;
+ }
+ } else if (lut_size >= 1024) {
+ if (mode & PREVIOUSLY_WHITE) {
+ pair.build_func = &build_2ppB_lut_1k;
+ pair.lookup_func = &calc_epd_input_2ppB_1k_lut_white;
+ return pair;
+ } else if (mode & PREVIOUSLY_BLACK) {
+ pair.build_func = &build_2ppB_lut_1k;
+ pair.lookup_func = &calc_epd_input_2ppB_1k_lut_black;
+ return pair;
+ }
+ }
+ } else if (mode & MODE_PACKING_8PPB) {
+ if (lut_size < sizeof(lut_8ppB_start_at_white)) {
+ return pair;
+ }
+
+ if (mode & PREVIOUSLY_WHITE) {
+ pair.build_func = &build_8ppB_lut_256b_from_white;
+ pair.lookup_func = &calc_epd_input_8ppB;
+ return pair;
+ } else if (mode & PREVIOUSLY_BLACK) {
+ pair.build_func = &build_8ppB_lut_256b_from_black;
+ pair.lookup_func = &calc_epd_input_8ppB;
+ return pair;
+ }
+ }
+
+ return pair;
+}
diff --git a/lib/libesp32_eink/epdiy/src/output_common/lut.h b/lib/libesp32_eink/epdiy/src/output_common/lut.h
new file mode 100644
index 000000000..364636e4a
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/lut.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include
+#include "epdiy.h"
+
+// Make a block of 4 pixels lighter on the EPD.
+#define CLEAR_BYTE 0B10101010
+// Make a block of 4 pixels darker on the EPD.
+#define DARK_BYTE 0B01010101
+
+/**
+ * Type signature of a framebuffer to display output lookup function.
+ */
+typedef void (*lut_func_t)(
+ const uint32_t* line_buffer, uint8_t* epd_input, const uint8_t* lut, uint32_t epd_width
+);
+
+/**
+ * Type signature of a LUT preparation function.
+ */
+typedef void (*lut_build_func_t)(uint8_t* lut, const EpdWaveformPhases* phases, int frame);
+
+typedef struct {
+ lut_build_func_t build_func;
+ lut_func_t lookup_func;
+} LutFunctionPair;
+
+/**
+ * Select the appropriate LUT building and lookup function
+ * for the selected draw mode and allocated LUT size.
+ */
+LutFunctionPair find_lut_functions(enum EpdDrawMode mode, uint32_t lut_size);
+
+/*
+ * Reorder the output buffer to account for I2S FIFO order.
+ */
+void reorder_line_buffer(uint32_t* line_data, int buf_len);
+
+/**
+ * Apply a mask to a line buffer.
+ * `len` must be divisible by 4.
+ */
+void epd_apply_line_mask(uint8_t* buf, const uint8_t* mask, int len);
+
+// legacy functions
+void bit_shift_buffer_right(uint8_t* buf, uint32_t len, int shift);
+void nibble_shift_buffer_right(uint8_t* buf, uint32_t len);
diff --git a/lib/libesp32_eink/epdiy/src/output_common/render_context.c b/lib/libesp32_eink/epdiy/src/output_common/render_context.c
new file mode 100644
index 000000000..bb1890eaf
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/render_context.c
@@ -0,0 +1,106 @@
+#include "render_context.h"
+
+#include
+#include "esp_log.h"
+
+#include "../epdiy.h"
+#include "lut.h"
+#include "render_method.h"
+
+/// For waveforms without timing and the I2S diving method,
+/// the default hold time for each line is 12us
+const static int DEFAULT_FRAME_TIME = 120;
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+
+void get_buffer_params(
+ RenderContext_t* ctx,
+ int* bytes_per_line,
+ const uint8_t** start_ptr,
+ int* min_y,
+ int* max_y,
+ int* pixels_per_byte
+) {
+ EpdRect area = ctx->area;
+
+ enum EpdDrawMode mode = ctx->mode;
+ const EpdRect crop_to = ctx->crop_to;
+ const bool horizontally_cropped = !(crop_to.x == 0 && crop_to.width == area.width);
+ const bool vertically_cropped = !(crop_to.y == 0 && crop_to.height == area.height);
+
+ // number of pixels per byte of input data
+ int width_divider = 0;
+
+ if (mode & MODE_PACKING_1PPB_DIFFERENCE) {
+ *bytes_per_line = area.width;
+ width_divider = 1;
+ } else if (mode & MODE_PACKING_2PPB) {
+ *bytes_per_line = area.width / 2 + area.width % 2;
+ width_divider = 2;
+ } else if (mode & MODE_PACKING_8PPB) {
+ *bytes_per_line = (area.width / 8 + (area.width % 8 > 0));
+ width_divider = 8;
+ } else {
+ ctx->error |= EPD_DRAW_INVALID_PACKING_MODE;
+ }
+
+ int crop_x = (horizontally_cropped ? crop_to.x : 0);
+ int crop_y = (vertically_cropped ? crop_to.y : 0);
+ int crop_h = (vertically_cropped ? crop_to.height : 0);
+
+ const uint8_t* ptr_start = ctx->data_ptr;
+
+ // Adjust for negative starting coordinates with optional crop
+ if (area.x - crop_x < 0) {
+ ptr_start += -(area.x - crop_x) / width_divider;
+ }
+
+ if (area.y - crop_y < 0) {
+ ptr_start += -(area.y - crop_y) * *bytes_per_line;
+ }
+
+ // calculate start and end row with crop
+ *min_y = area.y + crop_y;
+ *max_y = min(*min_y + (vertically_cropped ? crop_h : area.height), area.height);
+ *start_ptr = ptr_start;
+ *pixels_per_byte = width_divider;
+}
+
+void IRAM_ATTR prepare_context_for_next_frame(RenderContext_t* ctx) {
+ int frame_time = DEFAULT_FRAME_TIME;
+ if (ctx->phase_times != NULL) {
+ frame_time = ctx->phase_times[ctx->current_frame];
+ }
+
+ if (ctx->mode & MODE_EPDIY_MONOCHROME) {
+ frame_time = MONOCHROME_FRAME_TIME;
+ }
+ ctx->frame_time = frame_time;
+
+ const EpdWaveformPhases* phases
+ = ctx->waveform->mode_data[ctx->waveform_index]->range_data[ctx->waveform_range];
+
+ assert(ctx->lut_build_func != NULL);
+ ctx->lut_build_func(ctx->conversion_lut, phases, ctx->current_frame);
+
+ ctx->lines_prepared = 0;
+ ctx->lines_consumed = 0;
+}
+
+void epd_populate_line_mask(uint8_t* line_mask, const uint8_t* dirty_columns, int mask_len) {
+ if (dirty_columns == NULL) {
+ memset(line_mask, 0xFF, mask_len);
+ } else {
+ int pixels = mask_len * 4;
+ for (int c = 0; c < pixels / 2; c += 2) {
+ uint8_t mask = 0;
+ mask |= (dirty_columns[c + 1] & 0xF0) != 0 ? 0xC0 : 0x00;
+ mask |= (dirty_columns[c + 1] & 0x0F) != 0 ? 0x30 : 0x00;
+ mask |= (dirty_columns[c] & 0xF0) != 0 ? 0x0C : 0x00;
+ mask |= (dirty_columns[c] & 0x0F) != 0 ? 0x03 : 0x00;
+ line_mask[c / 2] = mask;
+ }
+ }
+}
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_common/render_context.h b/lib/libesp32_eink/epdiy/src/output_common/render_context.h
new file mode 100644
index 000000000..47f8ddbc4
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/render_context.h
@@ -0,0 +1,110 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../epdiy.h"
+#include "line_queue.h"
+#include "lut.h"
+
+#define NUM_RENDER_THREADS 2
+
+typedef struct {
+ EpdRect area;
+ EpdRect crop_to;
+ const bool* drawn_lines;
+ const uint8_t* data_ptr;
+
+ /// The display width for quick access.
+ int display_width;
+ /// The display height for quick access.
+ int display_height;
+
+ /// index of the next line of data to process
+ atomic_int lines_prepared;
+ volatile int lines_consumed;
+ int lines_total;
+
+ /// frame currently in the current update cycle
+ int current_frame;
+ /// number of frames in the current update cycle
+ int cycle_frames;
+
+ TaskHandle_t feed_tasks[NUM_RENDER_THREADS];
+ SemaphoreHandle_t feed_done_smphr[NUM_RENDER_THREADS];
+ SemaphoreHandle_t frame_done;
+ /// Line buffers for feed tasks
+ uint8_t* feed_line_buffers[NUM_RENDER_THREADS];
+
+ /// index of the waveform mode when using vendor waveforms.
+ /// This is not necessarily the mode number if the waveform header
+ // only contains a selection of modes!
+ int waveform_index;
+ /// waveform range when using vendor waveforms
+ int waveform_range;
+ /// Draw time for the current frame in 1/10ths of us.
+ int frame_time;
+
+ const int* phase_times;
+
+ const EpdWaveform* waveform;
+ enum EpdDrawMode mode;
+ enum EpdDrawError error;
+
+ // Lookup table size.
+ size_t conversion_lut_size;
+ // Lookup table space.
+ uint8_t* conversion_lut;
+
+ /// LUT lookup function. Must not be NULL.
+ lut_func_t lut_lookup_func;
+ /// LUT building function. Must not be NULL
+ lut_build_func_t lut_build_func;
+
+ /// Queue of lines prepared for output to the display,
+ /// one for each thread.
+ LineQueue_t line_queues[NUM_RENDER_THREADS];
+ uint8_t* line_threads;
+
+ // Output line mask
+ uint8_t* line_mask;
+
+ /// track line skipping when working in old i2s mode
+ int skipping;
+
+ /// line buffer when using epd_push_pixels
+ uint8_t* static_line_buffer;
+} RenderContext_t;
+
+/**
+ * Based on the render context, assign the bytes per line,
+ * framebuffer start pointer, min and max vertical positions and the pixels per byte.
+ */
+void get_buffer_params(
+ RenderContext_t* ctx,
+ int* bytes_per_line,
+ const uint8_t** start_ptr,
+ int* min_y,
+ int* max_y,
+ int* pixels_per_byte
+);
+
+/**
+ * Prepare the render context for drawing the next frame.
+ *
+ * (Reset counters, etc)
+ */
+void prepare_context_for_next_frame(RenderContext_t* ctx);
+
+/**
+ * Populate an output line mask from line dirtyness with two bits per pixel.
+ * If the dirtyness data is NULL, set the mask to neutral.
+ *
+ * don't inline for to ensure availability in tests.
+ */
+void __attribute__((noinline)) epd_populate_line_mask(
+ uint8_t* line_mask, const uint8_t* dirty_columns, int mask_len
+);
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_common/render_method.c b/lib/libesp32_eink/epdiy/src/output_common/render_method.c
new file mode 100644
index 000000000..5404b7ee1
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/render_method.c
@@ -0,0 +1,10 @@
+#include "render_method.h"
+#include "sdkconfig.h"
+
+#ifdef CONFIG_IDF_TARGET_ESP32
+const enum EpdRenderMethod EPD_CURRENT_RENDER_METHOD = RENDER_METHOD_I2S;
+#elif defined(CONFIG_IDF_TARGET_ESP32S3)
+const enum EpdRenderMethod EPD_CURRENT_RENDER_METHOD = RENDER_METHOD_LCD;
+#else
+#error "unknown chip, cannot choose render method!"
+#endif
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_common/render_method.h b/lib/libesp32_eink/epdiy/src/output_common/render_method.h
new file mode 100644
index 000000000..217b41004
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_common/render_method.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include "sdkconfig.h"
+
+/**
+ * Rendering Method / Hardware to use.
+ */
+enum EpdRenderMethod {
+ /// Use the I2S peripheral on ESP32 chips.
+ RENDER_METHOD_I2S = 1,
+ /// Use the CAM/LCD peripheral in ESP32-S3 chips.
+ RENDER_METHOD_LCD = 2,
+};
+
+extern const enum EpdRenderMethod EPD_CURRENT_RENDER_METHOD;
+
+#ifdef CONFIG_IDF_TARGET_ESP32
+#define RENDER_METHOD_I2S 1
+#elif defined(CONFIG_IDF_TARGET_ESP32S3)
+#define RENDER_METHOD_LCD 1
+#else
+#error "unknown chip, cannot choose render method!"
+#endif
+
+#ifdef __clang__
+#define IRAM_ATTR
+// define this if we're using clangd to make it accept the GCC builtin
+void __assert_func(const char* file, int line, const char* func, const char* failedexpr);
+#endif
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.c b/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.c
new file mode 100644
index 000000000..6c63b10c5
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.c
@@ -0,0 +1,303 @@
+#include "i2s_data_bus.h"
+
+#include "esp_intr_alloc.h"
+#include "sdkconfig.h"
+
+// the I2S driver is based on ESP32 registers and won't compile on the S3
+#ifdef CONFIG_IDF_TARGET_ESP32
+
+#include "driver/rtc_io.h"
+#include "esp_system.h"
+#if ESP_IDF_VERSION < (4, 0, 0) || ARDUINO_ARCH_ESP32
+#include "rom/gpio.h"
+#include "rom/lldesc.h"
+#else
+#include "esp32/rom/gpio.h"
+#include "esp32/rom/lldesc.h"
+#endif
+#include "esp_heap_caps.h"
+#include "soc/i2s_reg.h"
+#include "soc/i2s_struct.h"
+#include "soc/rtc.h"
+
+#include "esp_system.h" // for ESP_IDF_VERSION_VAL
+#include "esp_private/periph_ctrl.h"
+
+/// DMA descriptors for front and back line buffer.
+/// We use two buffers, so one can be filled while the other
+/// is transmitted.
+typedef struct {
+ volatile lldesc_t* dma_desc_a;
+ volatile lldesc_t* dma_desc_b;
+
+ /// Front and back line buffer.
+ uint8_t* buf_a;
+ uint8_t* buf_b;
+} i2s_parallel_state_t;
+
+/// Indicates which line buffer is currently back / front.
+static int current_buffer = 0;
+
+/// The I2S state instance.
+static i2s_parallel_state_t i2s_state;
+
+static intr_handle_t gI2S_intr_handle = NULL;
+
+/// Indicates the device has finished its transmission and is ready again.
+static volatile bool output_done = true;
+/// The start pulse pin extracted from the configuration for use in the "done"
+/// interrupt.
+static gpio_num_t start_pulse_pin;
+
+/// Initializes a DMA descriptor.
+static void fill_dma_desc(
+ volatile lldesc_t* dmadesc, uint8_t* buf, uint32_t buf_size, uint32_t buf_length
+) {
+ assert(buf_length % 4 == 0); // Must be word aligned
+ dmadesc->size = buf_size;
+ dmadesc->length = buf_length;
+ dmadesc->buf = buf;
+ dmadesc->eof = 1;
+ dmadesc->sosf = 1;
+ dmadesc->owner = 1;
+ dmadesc->qe.stqe_next = 0;
+ dmadesc->offset = 0;
+}
+
+/// Address of the currently front DMA descriptor,
+/// which uses only the lower 20bits (according to TRM)
+uint32_t dma_desc_addr() {
+ return (uint32_t)(current_buffer ? i2s_state.dma_desc_a : i2s_state.dma_desc_b) & 0x000FFFFF;
+}
+
+// Helper function to help align values
+static size_t align_up(size_t x, size_t a) {
+ return (size_t)(x + ((size_t)a - 1)) & ~(size_t)(a - 1);
+}
+
+/// Set up a GPIO as output and route it to a signal.
+static void gpio_setup_out(int gpio, int sig, bool invert) {
+ if (gpio == -1)
+ return;
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
+ gpio_set_direction(gpio, GPIO_MODE_DEF_OUTPUT);
+ gpio_matrix_out(gpio, sig, invert, false);
+}
+
+/// Resets "Start Pulse" signal when the current row output is done.
+static void IRAM_ATTR i2s_int_hdl(void* arg) {
+ i2s_dev_t* dev = &I2S1;
+ if (dev->int_st.out_done) {
+ // gpio_set_level(start_pulse_pin, 1);
+ // gpio_set_level(GPIO_NUM_26, 0);
+ output_done = true;
+ }
+ // Clear the interrupt. Otherwise, the whole device would hang.
+ dev->int_clr.val = dev->int_raw.val;
+}
+
+uint8_t* IRAM_ATTR i2s_get_current_buffer() {
+ return (uint8_t*)(current_buffer ? i2s_state.dma_desc_a->buf : i2s_state.dma_desc_b->buf);
+}
+
+bool IRAM_ATTR i2s_is_busy() {
+ // DMA and FIFO must be done
+ return !output_done || !I2S1.state.tx_idle;
+}
+
+void IRAM_ATTR i2s_switch_buffer() {
+ // either device is done transmitting or the switch must be away from the
+ // buffer currently used by the DMA engine.
+ while (i2s_is_busy() && dma_desc_addr() != I2S1.out_link.addr) {
+ };
+ current_buffer = !current_buffer;
+}
+
+void IRAM_ATTR i2s_start_line_output() {
+ output_done = false;
+
+ i2s_dev_t* dev = &I2S1;
+ dev->conf.tx_start = 0;
+ dev->conf.tx_reset = 1;
+ dev->conf.tx_fifo_reset = 1;
+ dev->conf.rx_fifo_reset = 1;
+ dev->conf.tx_reset = 0;
+ dev->conf.tx_fifo_reset = 0;
+ dev->conf.rx_fifo_reset = 0;
+ dev->out_link.addr = dma_desc_addr();
+ dev->out_link.start = 1;
+
+ // sth is pulled up through peripheral interrupt
+ // This is timing-critical!
+ gpio_set_level(start_pulse_pin, 0);
+ dev->conf.tx_start = 1;
+}
+
+void i2s_gpio_attach(i2s_bus_config* cfg) {
+ gpio_num_t I2S_GPIO_BUS[] = { cfg->data_6, cfg->data_7, cfg->data_4, cfg->data_5,
+ cfg->data_2, cfg->data_3, cfg->data_0, cfg->data_1 };
+
+ gpio_set_direction(cfg->start_pulse, GPIO_MODE_OUTPUT);
+ gpio_set_level(cfg->start_pulse, 1);
+ // Use I2S1 with no signal offset (for some reason the offset seems to be
+ // needed in 16-bit mode, but not in 8 bit mode.
+ int signal_base = I2S1O_DATA_OUT0_IDX;
+
+ // Setup and route GPIOS
+ for (int x = 0; x < 8; x++) {
+ gpio_setup_out(I2S_GPIO_BUS[x], signal_base + x, false);
+ }
+
+ // Free CKH after wakeup
+ gpio_hold_dis(cfg->clock);
+ // Invert word select signal
+ gpio_setup_out(cfg->clock, I2S1O_WS_OUT_IDX, true);
+}
+
+void i2s_gpio_detach(i2s_bus_config* cfg) {
+ gpio_set_direction(cfg->data_0, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_1, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_2, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_3, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_4, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_5, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_6, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->data_7, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->start_pulse, GPIO_MODE_INPUT);
+ gpio_set_direction(cfg->clock, GPIO_MODE_INPUT);
+
+ gpio_reset_pin(cfg->clock);
+ if (cfg->clock != 5) {
+ rtc_gpio_isolate(cfg->clock);
+ }
+}
+
+void i2s_bus_init(i2s_bus_config* cfg, uint32_t epd_row_width) {
+ i2s_gpio_attach(cfg);
+
+ // store pin in global variable for use in interrupt.
+ start_pulse_pin = cfg->start_pulse;
+
+ periph_module_enable(PERIPH_I2S1_MODULE);
+
+ i2s_dev_t* dev = &I2S1;
+
+ // Initialize device
+ dev->conf.tx_reset = 1;
+ dev->conf.tx_reset = 0;
+
+ // Reset DMA
+ dev->lc_conf.in_rst = 1;
+ dev->lc_conf.in_rst = 0;
+ dev->lc_conf.out_rst = 1;
+ dev->lc_conf.out_rst = 0;
+
+ // Setup I2S config. See section 12 of Technical Reference Manual
+ // Enable LCD mode
+ dev->conf2.val = 0;
+ dev->conf2.lcd_en = 1;
+
+ // Enable FRAME1-Mode (See technical reference manual)
+ dev->conf2.lcd_tx_wrx2_en = 1;
+ dev->conf2.lcd_tx_sdx2_en = 0;
+
+ // Set to 8 bit parallel output
+ dev->sample_rate_conf.val = 0;
+ dev->sample_rate_conf.tx_bits_mod = 8;
+
+ // Half speed of bit clock in LCD mode.
+ // (Smallest possible divider according to the spec).
+ dev->sample_rate_conf.tx_bck_div_num = 2;
+
+ // Initialize Audio Clock (APLL)
+ rtc_clk_apll_enable(true);
+ rtc_clk_apll_coeff_set(0, 0, 0, 8);
+
+ // Set Audio Clock Dividers
+ dev->clkm_conf.val = 0;
+ dev->clkm_conf.clka_en = 1;
+ dev->clkm_conf.clkm_div_a = 1;
+ dev->clkm_conf.clkm_div_b = 0;
+ // 2 is the smallest possible divider according to the spec.
+ dev->clkm_conf.clkm_div_num = 2;
+
+ // Set up FIFO
+ dev->fifo_conf.val = 0;
+ dev->fifo_conf.tx_fifo_mod_force_en = 1;
+ dev->fifo_conf.tx_fifo_mod = 1;
+ dev->fifo_conf.tx_data_num = 32;
+ dev->fifo_conf.dscr_en = 1;
+
+ // Stop after transmission complete
+ dev->conf1.val = 0;
+ dev->conf1.tx_stop_en = 0;
+ dev->conf1.tx_pcm_bypass = 1;
+
+ // Configure TX channel
+ dev->conf_chan.val = 0;
+ dev->conf_chan.tx_chan_mod = 1;
+ dev->conf.tx_right_first = 1;
+
+ dev->timing.val = 0;
+
+ // Allocate DMA descriptors
+ const size_t buf_size = align_up(epd_row_width / 4, 4); // Buf size must be word aligned
+ i2s_state.buf_a = heap_caps_malloc(buf_size, MALLOC_CAP_DMA);
+ i2s_state.buf_b = heap_caps_malloc(buf_size, MALLOC_CAP_DMA);
+ i2s_state.dma_desc_a = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
+ i2s_state.dma_desc_b = heap_caps_malloc(sizeof(lldesc_t), MALLOC_CAP_DMA);
+
+ // and fill them
+ fill_dma_desc(i2s_state.dma_desc_a, i2s_state.buf_a, epd_row_width / 4, buf_size);
+ fill_dma_desc(i2s_state.dma_desc_b, i2s_state.buf_b, epd_row_width / 4, buf_size);
+
+ // enable "done" interrupt
+ SET_PERI_REG_BITS(I2S_INT_ENA_REG(1), I2S_OUT_DONE_INT_ENA_V, 1, I2S_OUT_DONE_INT_ENA_S);
+ // register interrupt
+ esp_intr_alloc(ETS_I2S1_INTR_SOURCE, 0, i2s_int_hdl, 0, &gI2S_intr_handle);
+
+ // Reset FIFO/DMA
+ dev->lc_conf.in_rst = 1;
+ dev->lc_conf.out_rst = 1;
+ dev->lc_conf.ahbm_rst = 1;
+ dev->lc_conf.ahbm_fifo_rst = 1;
+ dev->lc_conf.in_rst = 0;
+ dev->lc_conf.out_rst = 0;
+ dev->lc_conf.ahbm_rst = 0;
+ dev->lc_conf.ahbm_fifo_rst = 0;
+ dev->conf.tx_reset = 1;
+ dev->conf.tx_fifo_reset = 1;
+ dev->conf.rx_fifo_reset = 1;
+ dev->conf.tx_reset = 0;
+ dev->conf.tx_fifo_reset = 0;
+ dev->conf.rx_fifo_reset = 0;
+
+ // Start dma on front buffer
+ dev->lc_conf.val = I2S_OUT_DATA_BURST_EN | I2S_OUTDSCR_BURST_EN | I2S_OUT_DATA_BURST_EN;
+ dev->out_link.addr = ((uint32_t)(i2s_state.dma_desc_a));
+ dev->out_link.start = 1;
+
+ dev->int_clr.val = dev->int_raw.val;
+
+ dev->int_ena.val = 0;
+ dev->int_ena.out_done = 1;
+
+ dev->conf.tx_start = 0;
+}
+
+void i2s_bus_deinit() {
+ esp_intr_disable(gI2S_intr_handle);
+ esp_intr_free(gI2S_intr_handle);
+
+ free(i2s_state.buf_a);
+ free(i2s_state.buf_b);
+ free((void*)i2s_state.dma_desc_a);
+ free((void*)i2s_state.dma_desc_b);
+
+ rtc_clk_apll_coeff_set(0, 0, 0, 8);
+ rtc_clk_apll_enable(true);
+
+ periph_module_disable(PERIPH_I2S1_MODULE);
+}
+
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.h b/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.h
new file mode 100644
index 000000000..2aeb1f0e8
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/i2s_data_bus.h
@@ -0,0 +1,77 @@
+/**
+ * Implements a 8bit parallel interface to transmit pixel
+ * data to the display, based on the I2S peripheral.
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * I2S bus configuration parameters.
+ */
+typedef struct {
+ // GPIO numbers of the parallel bus pins.
+ gpio_num_t data_0;
+ gpio_num_t data_1;
+ gpio_num_t data_2;
+ gpio_num_t data_3;
+ gpio_num_t data_4;
+ gpio_num_t data_5;
+ gpio_num_t data_6;
+ gpio_num_t data_7;
+
+ // Data clock pin.
+ gpio_num_t clock;
+
+ // "Start Pulse", enabling data input on the slave device (active low)
+ gpio_num_t start_pulse;
+} i2s_bus_config;
+
+/**
+ * Initialize the I2S data bus for communication
+ * with a 8bit parallel display interface.
+ */
+void i2s_bus_init(i2s_bus_config* cfg, uint32_t epd_row_width);
+
+/**
+ * Attach I2S to gpio's
+ */
+void i2s_gpio_attach(i2s_bus_config* cfg);
+
+/**
+ * Detach I2S from gpio's
+ */
+void i2s_gpio_detach(i2s_bus_config* cfg);
+
+/**
+ * Get the currently writable line buffer.
+ */
+uint8_t* i2s_get_current_buffer();
+
+/**
+ * Switches front and back line buffer.
+ * If the switched-to line buffer is currently in use,
+ * this function blocks until transmission is done.
+ */
+void i2s_switch_buffer();
+
+/**
+ * Start transmission of the current back buffer.
+ */
+void i2s_start_line_output();
+
+/**
+ * Returns true if there is an ongoing transmission.
+ */
+bool i2s_is_busy();
+
+/**
+ * Give up allocated resources.
+ */
+void i2s_bus_deinit();
diff --git a/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.c b/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.c
new file mode 100644
index 000000000..08db81062
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.c
@@ -0,0 +1,402 @@
+#include "render_i2s.h"
+
+#include "../output_common/render_method.h"
+
+#ifdef RENDER_METHOD_I2S
+#include
+#include
+
+#include
+
+#include "epd_internals.h"
+#include "epdiy.h"
+
+// output a row to the display.
+#include "../output_common/lut.h"
+#include "../output_common/render_context.h"
+#include "i2s_data_bus.h"
+#include "rmt_pulse.h"
+
+static const epd_ctrl_state_t NoChangeState = { 0 };
+
+/**
+ * Waits until all previously submitted data has been written.
+ * Then, the following operations are initiated:
+ *
+ * - Previously submitted data is latched to the output register.
+ * - The RMT peripheral is set up to pulse the vertical (gate) driver for
+ * `output_time_dus` / 10 microseconds.
+ * - The I2S peripheral starts transmission of the current buffer to
+ * the source driver.
+ * - The line buffers are switched.
+ *
+ * This sequence of operations allows for pipelining data preparation and
+ * transfer, reducing total refresh times.
+ */
+static void IRAM_ATTR i2s_output_row(uint32_t output_time_dus) {
+ while (i2s_is_busy() || rmt_busy()) {
+ };
+
+ const EpdBoardDefinition* epd_board = epd_current_board();
+ epd_ctrl_state_t* ctrl_state = epd_ctrl_state();
+ epd_ctrl_state_t mask = NoChangeState;
+
+ ctrl_state->ep_sth = true;
+ ctrl_state->ep_latch_enable = true;
+ mask.ep_sth = true;
+ mask.ep_latch_enable = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+
+ mask = NoChangeState;
+ ctrl_state->ep_latch_enable = false;
+ mask.ep_latch_enable = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+
+ if (epd_get_display()->display_type == DISPLAY_TYPE_ED097TC2) {
+ pulse_ckv_ticks(output_time_dus, 1, false);
+ } else {
+ pulse_ckv_ticks(output_time_dus, 50, false);
+ }
+
+ i2s_start_line_output();
+ i2s_switch_buffer();
+}
+
+/** Line i2s_output_row, but resets skip indicator. */
+static void IRAM_ATTR i2s_write_row(RenderContext_t* ctx, uint32_t output_time_dus) {
+ i2s_output_row(output_time_dus);
+ ctx->skipping = 0;
+}
+
+/** Skip a row without writing to it. */
+static void IRAM_ATTR i2s_skip_row(RenderContext_t* ctx, uint8_t pipeline_finish_time) {
+ int line_bytes = ctx->display_width / 4;
+ // output previously loaded row, fill buffer with no-ops.
+ if (ctx->skipping < 2) {
+ memset((void*)i2s_get_current_buffer(), 0x00, line_bytes);
+ i2s_output_row(pipeline_finish_time);
+ } else {
+ if (epd_get_display()->display_type == DISPLAY_TYPE_ED097TC2) {
+ pulse_ckv_ticks(5, 5, false);
+ } else {
+ // According to the spec, the OC4 maximum CKV frequency is 200kHz.
+ pulse_ckv_ticks(45, 5, false);
+ }
+ }
+ ctx->skipping++;
+}
+
+/**
+ * Start a draw cycle.
+ */
+static void i2s_start_frame() {
+ while (i2s_is_busy() || rmt_busy()) {
+ };
+
+ const EpdBoardDefinition* epd_board = epd_current_board();
+ epd_ctrl_state_t* ctrl_state = epd_ctrl_state();
+ epd_ctrl_state_t mask = NoChangeState;
+
+ ctrl_state->ep_mode = true;
+ mask.ep_mode = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+
+ pulse_ckv_us(1, 1, true);
+
+ // This is very timing-sensitive!
+ mask = NoChangeState;
+ ctrl_state->ep_stv = false;
+ mask.ep_stv = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+ // busy_delay(240);
+ pulse_ckv_us(1000, 100, false);
+ mask = NoChangeState;
+ ctrl_state->ep_stv = true;
+ mask.ep_stv = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+ // pulse_ckv_us(0, 10, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+
+ mask = NoChangeState;
+ ctrl_state->ep_output_enable = true;
+ mask.ep_output_enable = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+}
+
+/**
+ * End a draw cycle.
+ */
+static void i2s_end_frame() {
+ const EpdBoardDefinition* epd_board = epd_current_board();
+ epd_ctrl_state_t* ctrl_state = epd_ctrl_state();
+ epd_ctrl_state_t mask = NoChangeState;
+
+ ctrl_state->ep_stv = false;
+ mask.ep_stv = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ mask = NoChangeState;
+ ctrl_state->ep_mode = false;
+ mask.ep_mode = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+ pulse_ckv_us(0, 10, true);
+ mask = NoChangeState;
+ ctrl_state->ep_output_enable = false;
+ mask.ep_output_enable = true;
+ epd_board->set_ctrl(ctrl_state, &mask);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+ pulse_ckv_us(1, 1, true);
+}
+
+void i2s_do_update(RenderContext_t* ctx) {
+ for (uint8_t k = 0; k < ctx->cycle_frames; k++) {
+ prepare_context_for_next_frame(ctx);
+
+ // start both feeder tasks
+ xTaskNotifyGive(ctx->feed_tasks[!xPortGetCoreID()]);
+ xTaskNotifyGive(ctx->feed_tasks[xPortGetCoreID()]);
+
+ // transmission is started in renderer threads, now wait util it's done
+ xSemaphoreTake(ctx->frame_done, portMAX_DELAY);
+
+ for (int i = 0; i < NUM_RENDER_THREADS; i++) {
+ xSemaphoreTake(ctx->feed_done_smphr[i], portMAX_DELAY);
+ }
+
+ ctx->current_frame++;
+
+ // make the watchdog happy.
+ if (k % 10 == 0) {
+ vTaskDelay(0);
+ }
+ }
+}
+
+void IRAM_ATTR epd_push_pixels_i2s(RenderContext_t* ctx, EpdRect area, short time, int color) {
+ int line_bytes = ctx->display_width / 4;
+ uint8_t row[line_bytes];
+ memset(row, 0, line_bytes);
+
+ const uint8_t color_choice[4] = { DARK_BYTE, CLEAR_BYTE, 0x00, 0xFF };
+ for (uint32_t i = 0; i < area.width; i++) {
+ uint32_t position = i + area.x % 4;
+ uint8_t mask = color_choice[color] & (0b00000011 << (2 * (position % 4)));
+ row[area.x / 4 + position / 4] |= mask;
+ }
+ reorder_line_buffer((uint32_t*)row, line_bytes);
+
+ i2s_start_frame();
+
+ for (int i = 0; i < ctx->display_height; i++) {
+ // before are of interest: skip
+ if (i < area.y) {
+ i2s_skip_row(ctx, time);
+ // start area of interest: set row data
+ } else if (i == area.y) {
+ i2s_switch_buffer();
+ memcpy((void*)i2s_get_current_buffer(), row, line_bytes);
+ i2s_switch_buffer();
+ memcpy((void*)i2s_get_current_buffer(), row, line_bytes);
+
+ i2s_write_row(ctx, time * 10);
+ // load nop row if done with area
+ } else if (i >= area.y + area.height) {
+ i2s_skip_row(ctx, time);
+ // output the same as before
+ } else {
+ i2s_write_row(ctx, time * 10);
+ }
+ }
+ // Since we "pipeline" row output, we still have to latch out the last row.
+ i2s_write_row(ctx, time * 10);
+
+ i2s_end_frame();
+}
+
+void IRAM_ATTR i2s_output_frame(RenderContext_t* ctx, int thread_id) {
+ uint8_t* line_buf = ctx->feed_line_buffers[thread_id];
+
+ ctx->skipping = 0;
+ EpdRect area = ctx->area;
+ int frame_time = ctx->frame_time;
+
+ i2s_start_frame();
+ for (int i = 0; i < ctx->display_height; i++) {
+ LineQueue_t* lq = &ctx->line_queues[0];
+
+ memset(line_buf, 0, ctx->display_width);
+ while (lq_read(lq, line_buf) < 0) {
+ };
+
+ ctx->lines_consumed += 1;
+
+ if (ctx->drawn_lines != NULL && !ctx->drawn_lines[i - area.y]) {
+ i2s_skip_row(ctx, frame_time);
+ continue;
+ }
+
+ // lookup pixel actions in the waveform LUT
+ ctx->lut_lookup_func(
+ (uint32_t*)line_buf,
+ (uint8_t*)i2s_get_current_buffer(),
+ ctx->conversion_lut,
+ ctx->display_width
+ );
+
+ // apply the line mask
+ epd_apply_line_mask(i2s_get_current_buffer(), ctx->line_mask, ctx->display_width / 4);
+
+ reorder_line_buffer((uint32_t*)i2s_get_current_buffer(), ctx->display_width / 4);
+ i2s_write_row(ctx, frame_time);
+ }
+ if (!ctx->skipping) {
+ // Since we "pipeline" row output, we still have to latch out the
+ // last row.
+ i2s_write_row(ctx, frame_time);
+ }
+ i2s_end_frame();
+
+ xSemaphoreGive(ctx->feed_done_smphr[thread_id]);
+ xSemaphoreGive(ctx->frame_done);
+}
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+static inline int max(int x, int y) {
+ return x > y ? x : y;
+}
+
+void IRAM_ATTR i2s_fetch_frame_data(RenderContext_t* ctx, int thread_id) {
+ uint8_t* input_line = ctx->feed_line_buffers[thread_id];
+
+ // line must be able to hold 2-pixel-per-byte or 1-pixel-per-byte data
+ memset(input_line, 0x00, ctx->display_width);
+
+ LineQueue_t* lq = &ctx->line_queues[thread_id];
+
+ EpdRect area = ctx->area;
+
+ int min_y, max_y, bytes_per_line, pixels_per_byte;
+ const uint8_t* ptr_start;
+ get_buffer_params(ctx, &bytes_per_line, &ptr_start, &min_y, &max_y, &pixels_per_byte);
+
+ const EpdRect crop_to = ctx->crop_to;
+ const bool horizontally_cropped = !(crop_to.x == 0 && crop_to.width == area.width);
+ int crop_x = (horizontally_cropped ? crop_to.x : 0);
+ int crop_w = (horizontally_cropped ? crop_to.width : 0);
+
+ // interval of the output line that is needed
+ // FIXME: only lookup needed parts
+ int line_start_x = area.x + (horizontally_cropped ? crop_to.x : 0);
+ int line_end_x = line_start_x + (horizontally_cropped ? crop_to.width : area.width);
+ line_start_x = min(max(line_start_x, 0), ctx->display_width);
+ line_end_x = min(max(line_end_x, 0), ctx->display_width);
+
+ int l = 0;
+ while (l = atomic_fetch_add(&ctx->lines_prepared, 1), l < ctx->display_height) {
+ // if (thread_id) gpio_set_level(15, 0);
+ ctx->line_threads[l] = thread_id;
+
+ if (l < min_y || l >= max_y
+ || (ctx->drawn_lines != NULL && !ctx->drawn_lines[l - area.y])) {
+ uint8_t* buf = NULL;
+ while (buf == NULL)
+ buf = lq_current(lq);
+ memset(buf, 0x00, lq->element_size);
+ lq_commit(lq);
+ continue;
+ }
+
+ uint32_t* lp = (uint32_t*)input_line;
+ bool shifted = false;
+ const uint8_t* ptr = ptr_start + bytes_per_line * (l - min_y);
+
+ if (area.width == ctx->display_width && area.x == 0 && !ctx->error) {
+ lp = (uint32_t*)ptr;
+ } else if (!ctx->error) {
+ uint8_t* buf_start = (uint8_t*)input_line;
+ uint32_t line_bytes = bytes_per_line;
+
+ int min_x = area.x + crop_x;
+ if (min_x >= 0) {
+ buf_start += min_x / pixels_per_byte;
+ } else {
+ // reduce line_bytes to actually used bytes
+ // ptr was already adjusted above
+ line_bytes += min_x / pixels_per_byte;
+ }
+ line_bytes = min(
+ line_bytes,
+ ctx->display_width / pixels_per_byte - (uint32_t)(buf_start - input_line)
+ );
+
+ memcpy(buf_start, ptr, line_bytes);
+
+ int cropped_width = (horizontally_cropped ? crop_w : area.width);
+ /// consider half-byte shifts in two-pixel-per-Byte mode.
+ if (pixels_per_byte == 2) {
+ // mask last nibble for uneven width
+ if (cropped_width % 2 == 1
+ && min_x / 2 + cropped_width / 2 + 1 < ctx->display_width) {
+ *(buf_start + line_bytes - 1) |= 0xF0;
+ }
+ if (area.x % 2 == 1 && !(crop_x % 2 == 1) && min_x < ctx->display_width) {
+ shifted = true;
+ uint32_t remaining
+ = (uint32_t)input_line + ctx->display_width / 2 - (uint32_t)buf_start;
+ uint32_t to_shift = min(line_bytes + 1, remaining);
+ // shift one nibble to right
+ nibble_shift_buffer_right(buf_start, to_shift);
+ }
+ // consider bit shifts in bit buffers
+ } else if (pixels_per_byte == 8) {
+ // mask last n bits if width is not divisible by 8
+ if (cropped_width % 8 != 0 && bytes_per_line + 1 < ctx->display_width) {
+ uint8_t mask = 0;
+ for (int s = 0; s < cropped_width % 8; s++) {
+ mask = (mask << 1) | 1;
+ }
+ *(buf_start + line_bytes - 1) |= ~mask;
+ }
+
+ if (min_x % 8 != 0 && min_x < ctx->display_width) {
+ // shift to right
+ shifted = true;
+ uint32_t remaining
+ = (uint32_t)input_line + ctx->display_width / 8 - (uint32_t)buf_start;
+ uint32_t to_shift = min(line_bytes + 1, remaining);
+ bit_shift_buffer_right(buf_start, to_shift, min_x % 8);
+ }
+ }
+ lp = (uint32_t*)input_line;
+ }
+
+ uint8_t* buf = NULL;
+ while (buf == NULL)
+ buf = lq_current(lq);
+
+ memcpy(buf, lp, lq->element_size);
+
+ lq_commit(lq);
+
+ if (shifted) {
+ memset(input_line, 255, ctx->display_width / pixels_per_byte);
+ }
+ }
+}
+
+void i2s_deinit() {
+ rmt_pulse_deinit();
+ i2s_bus_deinit();
+}
+
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.h b/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.h
new file mode 100644
index 000000000..ec16c825c
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/render_i2s.h
@@ -0,0 +1,59 @@
+#include "epdiy.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "../output_common/render_context.h"
+#include "sdkconfig.h"
+
+/**
+ * Lighten / darken picels using the I2S driving method.
+ */
+void epd_push_pixels_i2s(RenderContext_t* ctx, EpdRect area, short time, int color);
+
+/**
+ * Do a full update cycle with a configured context.
+ */
+void i2s_do_update(RenderContext_t* ctx);
+
+/**
+ * Worker to fetch framebuffer data and write into a queue for processing.
+ */
+void i2s_fetch_frame_data(RenderContext_t* ctx, int thread_id);
+
+/**
+ * Worker to output frame data to the display.
+ */
+void i2s_output_frame(RenderContext_t* ctx, int thread_id);
+
+/**
+ * Deinitialize the I2S peripheral for low power consumption.
+ */
+void i2s_deinit();
+
+/*
+ * Write bits directly using the registers in the ESP32.
+ * Won't work for some pins (>= 32).
+ */
+inline void fast_gpio_set_hi(gpio_num_t gpio_num) {
+#ifdef CONFIG_IDF_TARGET_ESP32
+ gpio_dev_t* device = GPIO_LL_GET_HW(GPIO_PORT_0);
+ device->out_w1ts = (1 << gpio_num);
+#else
+ // not supportd on non ESP32 chips
+ assert(false);
+#endif
+}
+
+inline void fast_gpio_set_lo(gpio_num_t gpio_num) {
+#ifdef CONFIG_IDF_TARGET_ESP32
+ gpio_dev_t* device = GPIO_LL_GET_HW(GPIO_PORT_0);
+ device->out_w1tc = (1 << gpio_num);
+#else
+ // not supportd on non ESP32 chips
+ assert(false);
+#endif
+}
diff --git a/lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.c b/lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.c
new file mode 100644
index 000000000..f5ca71b49
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.c
@@ -0,0 +1,97 @@
+#include "../output_common/render_method.h"
+#include "esp_intr_alloc.h"
+
+#ifdef RENDER_METHOD_I2S
+
+#include "driver/rmt.h"
+#include "rmt_pulse.h"
+
+#include "soc/rmt_struct.h"
+
+static intr_handle_t gRMT_intr_handle = NULL;
+
+// the RMT channel configuration object
+static rmt_config_t row_rmt_config;
+
+// keep track of wether the current pulse is ongoing
+volatile bool rmt_tx_done = true;
+
+/**
+ * Remote peripheral interrupt. Used to signal when transmission is done.
+ */
+static void IRAM_ATTR rmt_interrupt_handler(void* arg) {
+ rmt_tx_done = true;
+ RMT.int_clr.val = RMT.int_st.val;
+}
+
+// The extern line is declared in esp-idf/components/driver/deprecated/rmt_legacy.c. It has access
+// to RMTMEM through the rmt_private.h header which we can't access outside the sdk. Declare our own
+// extern here to properly use the RMTMEM smybol defined in
+// components/soc/[target]/ld/[target].peripherals.ld Also typedef the new rmt_mem_t struct to the
+// old rmt_block_mem_t struct. Same data fields, different names
+typedef rmt_mem_t rmt_block_mem_t;
+extern rmt_block_mem_t RMTMEM;
+
+void rmt_pulse_init(gpio_num_t pin) {
+ row_rmt_config.rmt_mode = RMT_MODE_TX;
+ // currently hardcoded: use channel 0
+ row_rmt_config.channel = RMT_CHANNEL_1;
+
+ row_rmt_config.gpio_num = pin;
+ row_rmt_config.mem_block_num = 2;
+
+ // Divide 80MHz APB Clock by 8 -> .1us resolution delay
+ row_rmt_config.clk_div = 8;
+
+ row_rmt_config.tx_config.loop_en = false;
+ row_rmt_config.tx_config.carrier_en = false;
+ row_rmt_config.tx_config.carrier_level = RMT_CARRIER_LEVEL_LOW;
+ row_rmt_config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW;
+ row_rmt_config.tx_config.idle_output_en = true;
+
+ esp_intr_alloc(
+ ETS_RMT_INTR_SOURCE, ESP_INTR_FLAG_LEVEL3, rmt_interrupt_handler, 0, &gRMT_intr_handle
+ );
+
+ rmt_config(&row_rmt_config);
+ rmt_set_tx_intr_en(row_rmt_config.channel, true);
+}
+
+void rmt_pulse_deinit() {
+ esp_intr_disable(gRMT_intr_handle);
+ esp_intr_free(gRMT_intr_handle);
+}
+
+void IRAM_ATTR pulse_ckv_ticks(uint16_t high_time_ticks, uint16_t low_time_ticks, bool wait) {
+ while (!rmt_tx_done) {
+ };
+ volatile rmt_item32_t* rmt_mem_ptr = &(RMTMEM.chan[row_rmt_config.channel].data32[0]);
+ if (high_time_ticks > 0) {
+ rmt_mem_ptr->level0 = 1;
+ rmt_mem_ptr->duration0 = high_time_ticks;
+ rmt_mem_ptr->level1 = 0;
+ rmt_mem_ptr->duration1 = low_time_ticks;
+ } else {
+ rmt_mem_ptr->level0 = 1;
+ rmt_mem_ptr->duration0 = low_time_ticks;
+ rmt_mem_ptr->level1 = 0;
+ rmt_mem_ptr->duration1 = 0;
+ }
+ RMTMEM.chan[row_rmt_config.channel].data32[1].val = 0;
+ rmt_tx_done = false;
+ RMT.conf_ch[row_rmt_config.channel].conf1.mem_rd_rst = 1;
+ RMT.conf_ch[row_rmt_config.channel].conf1.mem_owner = RMT_MEM_OWNER_TX;
+ RMT.conf_ch[row_rmt_config.channel].conf1.tx_start = 1;
+ while (wait && !rmt_tx_done) {
+ };
+}
+
+void IRAM_ATTR pulse_ckv_us(uint16_t high_time_us, uint16_t low_time_us, bool wait) {
+ pulse_ckv_ticks(10 * high_time_us, 10 * low_time_us, wait);
+}
+
+bool IRAM_ATTR rmt_busy() {
+ return !rmt_tx_done;
+}
+
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.h b/lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.h
old mode 100755
new mode 100644
similarity index 78%
rename from lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.h
rename to lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.h
index c55a8084d..263c48066
--- a/lib/libesp32_eink/epdiy/src/epd_driver/rmt_pulse.h
+++ b/lib/libesp32_eink/epdiy/src/output_i2s/rmt_pulse.h
@@ -3,9 +3,9 @@
*/
#pragma once
+#include
#include "driver/gpio.h"
#include "esp_attr.h"
-#include
/**
* Initializes RMT Channel 0 with a pin for RMT pulsing.
@@ -13,6 +13,11 @@
*/
void rmt_pulse_init(gpio_num_t pin);
+/**
+ * Resets the pin and RMT peripheral, frees associated resources.
+ */
+void rmt_pulse_deinit();
+
/**
* Outputs a single pulse (high -> low) on the configured pin.
* This function will always wait for a previous call to finish.
@@ -21,12 +26,11 @@ void rmt_pulse_init(gpio_num_t pin);
* @param: low_time_us Pulse low time in us.
* @param: wait Block until the pulse is finished.
*/
-void IRAM_ATTR pulse_ckv_us(uint16_t high_time_us, uint16_t low_time_us,
- bool wait);
+void pulse_ckv_us(uint16_t high_time_us, uint16_t low_time_us, bool wait);
/**
* Indicates if the rmt is currently sending a pulse.
*/
-bool IRAM_ATTR rmt_busy();
+bool rmt_busy();
/**
* Outputs a single pulse (high -> low) on the configured pin.
@@ -36,5 +40,4 @@ bool IRAM_ATTR rmt_busy();
* @param: low_time_us Pulse low time in clock ticks.
* @param: wait Block until the pulse is finished.
*/
-void IRAM_ATTR pulse_ckv_ticks(uint16_t high_time_us, uint16_t low_time_us,
- bool wait);
+void pulse_ckv_ticks(uint16_t high_time_us, uint16_t low_time_us, bool wait);
diff --git a/lib/libesp32_eink/epdiy/src/output_lcd/idf-4-backports.h b/lib/libesp32_eink/epdiy/src/output_lcd/idf-4-backports.h
new file mode 100644
index 000000000..916789a8d
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_lcd/idf-4-backports.h
@@ -0,0 +1,22 @@
+/**
+ * Backported functions to make the LCD-based driver compile with IDF < 5.0
+ */
+
+#define RMT_BASECLK_DEFAULT RMT_BASECLK_APB
+typedef int rmt_clock_source_t;
+
+static inline void rmt_ll_enable_periph_clock(rmt_dev_t* dev, bool enable) {
+ dev->sys_conf.clk_en = enable; // register clock gating
+ dev->sys_conf.mem_clk_force_on = enable; // memory clock gating
+}
+
+static inline void rmt_ll_enable_mem_access_nonfifo(rmt_dev_t* dev, bool enable) {
+ dev->sys_conf.apb_fifo_mask = enable;
+}
+
+__attribute__((always_inline)) static inline void rmt_ll_tx_fix_idle_level(
+ rmt_dev_t* dev, uint32_t channel, uint8_t level, bool enable
+) {
+ dev->chnconf0[channel].idle_out_en_n = enable;
+ dev->chnconf0[channel].idle_out_lv_n = level;
+}
diff --git a/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.c b/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.c
new file mode 100644
index 000000000..ae5c833a3
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.c
@@ -0,0 +1,706 @@
+#include "lcd_driver.h"
+#include "epdiy.h"
+
+#include "../output_common/render_method.h"
+#include "esp_heap_caps.h"
+#include "esp_intr_alloc.h"
+#include "hal/gpio_types.h"
+
+#ifdef RENDER_METHOD_LCD
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "hal/gpio_hal.h"
+
+gpio_hal_context_t hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) };
+
+#define TAG "epdiy"
+
+#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 3, 2)
+#define LCD_PERIPH_SIGNALS lcd_periph_signals
+#else
+#define LCD_PERIPH_SIGNALS lcd_periph_rgb_signals
+#endif
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+static inline int max(int x, int y) {
+ return x > y ? x : y;
+}
+
+#define S3_LCD_PIN_NUM_BK_LIGHT -1
+// #define S3_LCD_PIN_NUM_MODE 4
+
+#define LINE_BATCH 1000
+#define BOUNCE_BUF_LINES 4
+
+#define RMT_CKV_CHAN RMT_CHANNEL_1
+
+// The extern line is declared in esp-idf/components/driver/deprecated/rmt_legacy.c. It has access
+// to RMTMEM through the rmt_private.h header which we can't access outside the sdk. Declare our own
+// extern here to properly use the RMTMEM smybol defined in
+// components/soc/[target]/ld/[target].peripherals.ld Also typedef the new rmt_mem_t struct to the
+// old rmt_block_mem_t struct. Same data fields, different names
+typedef rmt_mem_t rmt_block_mem_t;
+extern rmt_block_mem_t RMTMEM;
+
+// spinlock for protecting the critical section at frame start
+static portMUX_TYPE frame_start_spinlock = portMUX_INITIALIZER_UNLOCKED;
+
+typedef struct {
+ lcd_hal_context_t hal;
+ intr_handle_t vsync_intr;
+ intr_handle_t done_intr;
+
+ frame_done_func_t frame_done_cb;
+ line_cb_func_t line_source_cb;
+ void* line_cb_payload;
+ void* frame_cb_payload;
+
+ int line_length_us;
+ int line_cycles;
+ int lcd_res_h;
+
+ LcdEpdConfig_t config;
+
+ uint8_t* bounce_buffer[2];
+ // size of a single bounce buffer
+ size_t bb_size;
+ size_t batches;
+
+ // Number of DMA descriptors that used to carry the frame buffer
+ size_t num_dma_nodes;
+ // DMA channel handle
+ gdma_channel_handle_t dma_chan;
+ // DMA descriptors pool
+ dma_descriptor_t* dma_nodes;
+
+ /// The number of bytes in a horizontal display register line.
+ int line_bytes;
+
+ // With 8 bit bus width, we need a dummy cycle before the actual data,
+ // because the LCD peripheral behaves weirdly.
+ // Also see:
+ // https://blog.adafruit.com/2022/06/14/esp32uesday-hacking-the-esp32-s3-lcd-peripheral/
+ int dummy_bytes;
+
+ /// The number of lines of the display
+ int display_lines;
+} s3_lcd_t;
+
+static s3_lcd_t lcd = { 0 };
+
+void IRAM_ATTR epd_lcd_line_source_cb(line_cb_func_t line_source, void* payload) {
+ lcd.line_source_cb = line_source;
+ lcd.line_cb_payload = payload;
+}
+
+void IRAM_ATTR epd_lcd_frame_done_cb(frame_done_func_t cb, void* payload) {
+ lcd.frame_done_cb = cb;
+ lcd.frame_cb_payload = payload;
+}
+
+static IRAM_ATTR bool fill_bounce_buffer(uint8_t* buffer) {
+ bool task_awoken = false;
+
+ for (int i = 0; i < BOUNCE_BUF_LINES; i++) {
+ if (lcd.line_source_cb != NULL) {
+ // this is strange, with 16 bit need a dummy cycle. But still, the first byte in the
+ // FIFO is correct. So we only need a true dummy byte in the FIFO in the 8 bit
+ // configuration.
+ int buffer_offset = i * (lcd.line_bytes + lcd.dummy_bytes) + (lcd.dummy_bytes % 2);
+ task_awoken |= lcd.line_source_cb(lcd.line_cb_payload, &buffer[buffer_offset]);
+ } else {
+ memset(&buffer[i * lcd.line_bytes], 0x00, lcd.line_bytes);
+ }
+ }
+ return task_awoken;
+}
+
+static void start_ckv_cycles(int cycles) {
+ rmt_ll_tx_enable_loop_count(&RMT, RMT_CKV_CHAN, true);
+ rmt_ll_tx_enable_loop_autostop(&RMT, RMT_CKV_CHAN, true);
+ rmt_ll_tx_set_loop_count(&RMT, RMT_CKV_CHAN, cycles);
+ rmt_ll_tx_reset_pointer(&RMT, RMT_CKV_CHAN);
+ rmt_ll_tx_start(&RMT, RMT_CKV_CHAN);
+}
+
+/**
+ * Build the RMT signal according to the timing set in the lcd object.
+ */
+static void ckv_rmt_build_signal() {
+ int low_time = (lcd.line_length_us * 10 - lcd.config.ckv_high_time);
+ volatile rmt_item32_t* rmt_mem_ptr = &(RMTMEM.chan[RMT_CKV_CHAN].data32[0]);
+ rmt_mem_ptr->duration0 = lcd.config.ckv_high_time;
+ rmt_mem_ptr->level0 = 1;
+ rmt_mem_ptr->duration1 = low_time;
+ rmt_mem_ptr->level1 = 0;
+ rmt_mem_ptr[1].val = 0;
+}
+
+/**
+ * Configure the RMT peripheral for use as the CKV clock.
+ */
+static void init_ckv_rmt() {
+ periph_module_reset(PERIPH_RMT_MODULE);
+ periph_module_enable(PERIPH_RMT_MODULE);
+
+ rmt_ll_enable_periph_clock(&RMT, true);
+
+ // Divide 80MHz APB Clock by 8 -> .1us resolution delay
+ // idf >= 5.0 calculates the clock divider differently
+ rmt_ll_set_group_clock_src(&RMT, RMT_CKV_CHAN, RMT_CLK_SRC_DEFAULT, 1, 0, 0);
+ rmt_ll_tx_set_channel_clock_div(&RMT, RMT_CKV_CHAN, 8);
+ rmt_ll_tx_set_mem_blocks(&RMT, RMT_CKV_CHAN, 2);
+ rmt_ll_enable_mem_access_nonfifo(&RMT, true);
+ rmt_ll_tx_fix_idle_level(&RMT, RMT_CKV_CHAN, RMT_IDLE_LEVEL_LOW, true);
+ rmt_ll_tx_enable_carrier_modulation(&RMT, RMT_CKV_CHAN, false);
+
+ rmt_ll_tx_enable_loop(&RMT, RMT_CKV_CHAN, true);
+
+ gpio_hal_func_sel(&hal, lcd.config.bus.ckv, PIN_FUNC_GPIO);
+ gpio_set_direction(lcd.config.bus.ckv, GPIO_MODE_OUTPUT);
+ esp_rom_gpio_connect_out_signal(
+ lcd.config.bus.ckv, rmt_periph_signals.groups[0].channels[RMT_CKV_CHAN].tx_sig, false, 0
+ );
+
+ ckv_rmt_build_signal();
+}
+
+/**
+ * Reset the CKV RMT configuration.
+ */
+static void deinit_ckv_rmt() {
+ periph_module_reset(PERIPH_RMT_MODULE);
+ periph_module_disable(PERIPH_RMT_MODULE);
+
+ gpio_reset_pin(lcd.config.bus.ckv);
+}
+
+__attribute__((optimize("O3"))) IRAM_ATTR static void lcd_isr_vsync(void* args) {
+ bool need_yield = false;
+
+ uint32_t intr_status = lcd_ll_get_interrupt_status(lcd.hal.dev);
+ lcd_ll_clear_interrupt_status(lcd.hal.dev, intr_status);
+
+ if (intr_status & LCD_LL_EVENT_VSYNC_END) {
+ int batches_needed = lcd.display_lines / LINE_BATCH;
+ if (lcd.batches >= batches_needed) {
+ lcd_ll_stop(lcd.hal.dev);
+ if (lcd.frame_done_cb != NULL) {
+ (*lcd.frame_done_cb)(lcd.frame_cb_payload);
+ }
+ } else {
+ int ckv_cycles = 0;
+ // last batch
+ if (lcd.batches == batches_needed - 1) {
+ lcd_ll_enable_auto_next_frame(lcd.hal.dev, false);
+ lcd_ll_set_vertical_timing(lcd.hal.dev, 1, 0, lcd.display_lines % LINE_BATCH, 10);
+ ckv_cycles = lcd.display_lines % LINE_BATCH + 10;
+ } else {
+ lcd_ll_set_vertical_timing(lcd.hal.dev, 1, 0, LINE_BATCH, 1);
+ ckv_cycles = LINE_BATCH + 1;
+ }
+ // apparently, this is needed for the new timing to take effect.
+ lcd_ll_start(lcd.hal.dev);
+
+ // skip the LCD front porch line, which is not actual data
+ esp_rom_delay_us(lcd.line_length_us);
+ start_ckv_cycles(ckv_cycles);
+ }
+
+ lcd.batches += 1;
+ }
+
+ if (need_yield) {
+ portYIELD_FROM_ISR();
+ }
+};
+
+// ISR handling bounce buffer refill
+static IRAM_ATTR bool lcd_rgb_panel_eof_handler(
+ gdma_channel_handle_t dma_chan, gdma_event_data_t* event_data, void* user_data
+) {
+ dma_descriptor_t* desc = (dma_descriptor_t*)event_data->tx_eof_desc_addr;
+ // Figure out which bounce buffer to write to.
+ // Note: what we receive is the *last* descriptor of this bounce buffer.
+ int bb = (desc == &lcd.dma_nodes[0]) ? 0 : 1;
+ return fill_bounce_buffer(lcd.bounce_buffer[bb]);
+}
+
+static esp_err_t init_dma_trans_link() {
+ lcd.dma_nodes[0].dw0.suc_eof = 1;
+ lcd.dma_nodes[0].dw0.size = lcd.bb_size;
+ lcd.dma_nodes[0].dw0.length = lcd.bb_size;
+ lcd.dma_nodes[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU;
+ lcd.dma_nodes[0].buffer = lcd.bounce_buffer[0];
+
+ lcd.dma_nodes[1].dw0.suc_eof = 1;
+ lcd.dma_nodes[1].dw0.size = lcd.bb_size;
+ lcd.dma_nodes[1].dw0.length = lcd.bb_size;
+ lcd.dma_nodes[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_CPU;
+ lcd.dma_nodes[1].buffer = lcd.bounce_buffer[1];
+
+ // loop end back to start
+ lcd.dma_nodes[0].next = &lcd.dma_nodes[1];
+ lcd.dma_nodes[1].next = &lcd.dma_nodes[0];
+
+ // alloc DMA channel and connect to LCD peripheral
+ gdma_channel_alloc_config_t dma_chan_config = {
+ .direction = GDMA_CHANNEL_DIRECTION_TX,
+ };
+ ESP_RETURN_ON_ERROR(
+ gdma_new_channel(&dma_chan_config, &lcd.dma_chan), TAG, "alloc DMA channel failed"
+ );
+ gdma_trigger_t trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_LCD, 0);
+ ESP_RETURN_ON_ERROR(gdma_connect(lcd.dma_chan, trigger), TAG, "dma connect error");
+ gdma_transfer_ability_t ability = {
+ .psram_trans_align = 64,
+ .sram_trans_align = 4,
+ };
+ ESP_RETURN_ON_ERROR(gdma_set_transfer_ability(lcd.dma_chan, &ability), TAG, "dma setup error");
+
+ gdma_tx_event_callbacks_t cbs = {
+ .on_trans_eof = lcd_rgb_panel_eof_handler,
+ };
+ ESP_RETURN_ON_ERROR(
+ gdma_register_tx_event_callbacks(lcd.dma_chan, &cbs, NULL), TAG, "dma setup error"
+ );
+
+ return ESP_OK;
+}
+
+void deinit_dma_trans_link() {
+ gdma_reset(lcd.dma_chan);
+ gdma_disconnect(lcd.dma_chan);
+ gdma_del_channel(lcd.dma_chan);
+}
+
+/**
+ * Configure LCD peripheral and auxiliary GPIOs
+ */
+static esp_err_t init_bus_gpio() {
+ const int DATA_LINES[16] = {
+ lcd.config.bus.data[14], lcd.config.bus.data[15], lcd.config.bus.data[12],
+ lcd.config.bus.data[13], lcd.config.bus.data[10], lcd.config.bus.data[11],
+ lcd.config.bus.data[8], lcd.config.bus.data[9], lcd.config.bus.data[6],
+ lcd.config.bus.data[7], lcd.config.bus.data[4], lcd.config.bus.data[5],
+ lcd.config.bus.data[2], lcd.config.bus.data[3], lcd.config.bus.data[0],
+ lcd.config.bus.data[1],
+ };
+
+ // connect peripheral signals via GPIO matrix
+ for (size_t i = (16 - lcd.config.bus_width); i < 16; i++) {
+ gpio_hal_func_sel(&hal, DATA_LINES[i], PIN_FUNC_GPIO);
+ gpio_set_direction(DATA_LINES[i], GPIO_MODE_OUTPUT);
+ esp_rom_gpio_connect_out_signal(
+ DATA_LINES[i], LCD_PERIPH_SIGNALS.panels[0].data_sigs[i], false, false
+ );
+ }
+ gpio_hal_func_sel(&hal, lcd.config.bus.leh, PIN_FUNC_GPIO);
+ gpio_set_direction(lcd.config.bus.leh, GPIO_MODE_OUTPUT);
+ gpio_hal_func_sel(&hal, lcd.config.bus.clock, PIN_FUNC_GPIO);
+ gpio_set_direction(lcd.config.bus.clock, GPIO_MODE_OUTPUT);
+ gpio_hal_func_sel(&hal, lcd.config.bus.start_pulse, PIN_FUNC_GPIO);
+ gpio_set_direction(lcd.config.bus.start_pulse, GPIO_MODE_OUTPUT);
+
+ esp_rom_gpio_connect_out_signal(
+ lcd.config.bus.leh, LCD_PERIPH_SIGNALS.panels[0].hsync_sig, false, false
+ );
+ esp_rom_gpio_connect_out_signal(
+ lcd.config.bus.clock, LCD_PERIPH_SIGNALS.panels[0].pclk_sig, false, false
+ );
+ esp_rom_gpio_connect_out_signal(
+ lcd.config.bus.start_pulse, LCD_PERIPH_SIGNALS.panels[0].de_sig, false, false
+ );
+
+ gpio_config_t vsync_gpio_conf = {
+ .mode = GPIO_MODE_OUTPUT,
+ .pin_bit_mask = 1ull << lcd.config.bus.stv,
+ };
+ gpio_config(&vsync_gpio_conf);
+ gpio_set_level(lcd.config.bus.stv, 1);
+ return ESP_OK;
+}
+
+/**
+ * Reset bus GPIO pin functions.
+ */
+static void deinit_bus_gpio() {
+ for (size_t i = (16 - lcd.config.bus_width); i < 16; i++) {
+ gpio_reset_pin(lcd.config.bus.data[i]);
+ }
+
+ gpio_reset_pin(lcd.config.bus.leh);
+ gpio_reset_pin(lcd.config.bus.clock);
+ gpio_reset_pin(lcd.config.bus.start_pulse);
+ gpio_reset_pin(lcd.config.bus.stv);
+}
+
+/**
+ * Check if the PSRAM cache is properly configured.
+ */
+static void check_cache_configuration() {
+ if (CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE < 64) {
+ ESP_LOGE(
+ "epdiy",
+ "cache line size is set to %d (< 64B)! This will degrade performance, please update "
+ "this option in menuconfig.",
+ CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE
+ );
+ ESP_LOGE(
+ "epdiy",
+ "If you are on arduino, you can't set this option yourself, you'll need to use a lower "
+ "speed."
+ );
+ ESP_LOGE(
+ "epdiy",
+ "Reducing the pixel clock from %d MHz to %d MHz for now!",
+ lcd.config.pixel_clock / 1000 / 1000,
+ lcd.config.pixel_clock / 1000 / 1000 / 2
+ );
+ lcd.config.pixel_clock = lcd.config.pixel_clock / 2;
+
+ // fixme: this would be nice, but doesn't work :(
+ // uint32_t d_autoload = Cache_Suspend_DCache();
+ /// Cache_Set_DCache_Mode(CACHE_SIZE_FULL, CACHE_4WAYS_ASSOC, CACHE_LINE_SIZE_32B);
+ // Cache_Invalidate_DCache_All();
+ // Cache_Resume_DCache(d_autoload);
+ }
+}
+
+/**
+ * Assign LCD configuration parameters from a given configuration, without allocating memory or
+ * touching the LCD peripheral config.
+ */
+static void assign_lcd_parameters_from_config(
+ const LcdEpdConfig_t* config, int display_width, int display_height
+) {
+ // copy over the configuraiton object
+ memcpy(&lcd.config, config, sizeof(LcdEpdConfig_t));
+
+ // Make sure the bounce buffers divide the display height evenly.
+ lcd.display_lines = (((display_height + 7) / 8) * 8);
+
+ lcd.line_bytes = display_width / 4;
+ lcd.lcd_res_h = lcd.line_bytes / (lcd.config.bus_width / 8);
+
+ // With 8 bit bus width, we need a dummy cycle before the actual data,
+ // because the LCD peripheral behaves weirdly.
+ // Also see:
+ // https://blog.adafruit.com/2022/06/14/esp32uesday-hacking-the-esp32-s3-lcd-peripheral/
+ lcd.dummy_bytes = lcd.config.bus_width / 8;
+
+ // each bounce buffer holds a number of lines with data + dummy bytes each
+ lcd.bb_size = BOUNCE_BUF_LINES * (lcd.line_bytes + lcd.dummy_bytes);
+
+ check_cache_configuration();
+
+ ESP_LOGI(TAG, "using resolution %dx%d", lcd.lcd_res_h, lcd.display_lines);
+}
+
+/**
+ * Allocate buffers for LCD driver operation.
+ */
+static esp_err_t allocate_lcd_buffers() {
+ uint32_t dma_flags = MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA;
+
+ // allocate bounce buffers
+ for (int i = 0; i < 2; i++) {
+ lcd.bounce_buffer[i] = heap_caps_aligned_calloc(4, 1, lcd.bb_size, dma_flags);
+ ESP_RETURN_ON_FALSE(lcd.bounce_buffer[i], ESP_ERR_NO_MEM, TAG, "install interrupt failed");
+ }
+
+ // So far, I haven't seen any displays with > 4096 pixels per line,
+ // so we only need one DMA node for now.
+ assert(lcd.bb_size < DMA_DESCRIPTOR_BUFFER_MAX_SIZE);
+ lcd.dma_nodes = heap_caps_calloc(1, sizeof(dma_descriptor_t) * 2, dma_flags);
+ ESP_RETURN_ON_FALSE(lcd.dma_nodes, ESP_ERR_NO_MEM, TAG, "no mem for dma nodes");
+ return ESP_OK;
+}
+
+static void free_lcd_buffers() {
+ for (int i = 0; i < 2; i++) {
+ uint8_t* buf = lcd.bounce_buffer[i];
+ if (buf != NULL) {
+ heap_caps_free(buf);
+ lcd.bounce_buffer[i] = NULL;
+ }
+ }
+
+ if (lcd.dma_nodes != NULL) {
+ heap_caps_free(lcd.dma_nodes);
+ lcd.dma_nodes = NULL;
+ }
+}
+
+/**
+ * Initialize the LCD peripheral itself and install interrupts.
+ */
+static esp_err_t init_lcd_peripheral() {
+ esp_err_t ret = ESP_OK;
+
+ // enable APB to access LCD registers
+ periph_module_enable(PERIPH_LCD_CAM_MODULE);
+ periph_module_reset(PERIPH_LCD_CAM_MODULE);
+
+ lcd_hal_init(&lcd.hal, 0);
+ lcd_ll_enable_clock(lcd.hal.dev, true);
+ lcd_ll_select_clk_src(lcd.hal.dev, LCD_CLK_SRC_PLL240M);
+ ESP_RETURN_ON_ERROR(ret, TAG, "set source clock failed");
+
+ // install interrupt service, (LCD peripheral shares the interrupt source with Camera by
+ // different mask)
+ int flags = ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED
+ | ESP_INTR_FLAG_LOWMED;
+
+ int source = LCD_PERIPH_SIGNALS.panels[0].irq_id;
+ uint32_t status = (uint32_t)lcd_ll_get_interrupt_status_reg(lcd.hal.dev);
+ ret = esp_intr_alloc_intrstatus(
+ source, flags, status, LCD_LL_EVENT_VSYNC_END, lcd_isr_vsync, NULL, &lcd.vsync_intr
+ );
+ ESP_RETURN_ON_ERROR(ret, TAG, "install interrupt failed");
+
+ status = (uint32_t)lcd_ll_get_interrupt_status_reg(lcd.hal.dev);
+ ret = esp_intr_alloc_intrstatus(
+ source, flags, status, LCD_LL_EVENT_TRANS_DONE, lcd_isr_vsync, NULL, &lcd.done_intr
+ );
+ ESP_RETURN_ON_ERROR(ret, TAG, "install interrupt failed");
+
+ lcd_ll_fifo_reset(lcd.hal.dev);
+ lcd_ll_reset(lcd.hal.dev);
+
+ // pixel clock phase and polarity
+ lcd_ll_set_clock_idle_level(lcd.hal.dev, false);
+ lcd_ll_set_pixel_clock_edge(lcd.hal.dev, false);
+
+ // enable RGB mode and set data width
+ lcd_ll_enable_rgb_mode(lcd.hal.dev, true);
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
+ lcd_ll_set_dma_read_stride(lcd.hal.dev, lcd.config.bus_width);
+ lcd_ll_set_data_wire_width(lcd.hal.dev, lcd.config.bus_width);
+#else
+ lcd_ll_set_data_width(lcd.hal.dev, lcd.config.bus_width);
+#endif
+ lcd_ll_set_phase_cycles(lcd.hal.dev, 0, (lcd.dummy_bytes > 0), 1); // enable data phase only
+ lcd_ll_enable_output_hsync_in_porch_region(lcd.hal.dev, false); // enable data phase only
+
+ // number of data cycles is controlled by DMA buffer size
+ lcd_ll_enable_output_always_on(lcd.hal.dev, false);
+ lcd_ll_set_idle_level(lcd.hal.dev, false, true, true);
+
+ // configure blank region timing
+ // RGB panel always has a front and back blank (porch region)
+ lcd_ll_set_blank_cycles(lcd.hal.dev, 1, 1);
+
+ // output hsync even in porch region?
+ lcd_ll_enable_output_hsync_in_porch_region(lcd.hal.dev, false);
+ // send next frame automatically in stream mode
+ lcd_ll_enable_auto_next_frame(lcd.hal.dev, false);
+
+ lcd_ll_enable_interrupt(lcd.hal.dev, LCD_LL_EVENT_VSYNC_END, true);
+ lcd_ll_enable_interrupt(lcd.hal.dev, LCD_LL_EVENT_TRANS_DONE, true);
+
+ // enable intr
+ esp_intr_enable(lcd.vsync_intr);
+ esp_intr_enable(lcd.done_intr);
+ return ret;
+}
+
+static void deinit_lcd_peripheral() {
+ // disable and free interrupts
+ esp_intr_disable(lcd.vsync_intr);
+ esp_intr_disable(lcd.done_intr);
+ esp_intr_free(lcd.vsync_intr);
+ esp_intr_free(lcd.done_intr);
+
+ lcd_ll_fifo_reset(lcd.hal.dev);
+ lcd_ll_reset(lcd.hal.dev);
+
+ periph_module_reset(PERIPH_LCD_CAM_MODULE);
+ periph_module_disable(PERIPH_LCD_CAM_MODULE);
+}
+
+/**
+ * Configure the LCD driver for epdiy.
+ */
+void epd_lcd_init(const LcdEpdConfig_t* config, int display_width, int display_height) {
+ esp_err_t ret = ESP_OK;
+ assign_lcd_parameters_from_config(config, display_width, display_height);
+
+ check_cache_configuration();
+
+ ret = allocate_lcd_buffers();
+ ESP_GOTO_ON_ERROR(ret, err, TAG, "lcd buffer allocation failed");
+
+ ret = init_lcd_peripheral();
+ ESP_GOTO_ON_ERROR(ret, err, TAG, "lcd peripheral init failed");
+
+ ret = init_dma_trans_link();
+ ESP_GOTO_ON_ERROR(ret, err, TAG, "install DMA failed");
+
+ ret = init_bus_gpio();
+ ESP_GOTO_ON_ERROR(ret, err, TAG, "configure GPIO failed");
+
+ init_ckv_rmt();
+
+ // setup driver state
+ epd_lcd_set_pixel_clock_MHz(lcd.config.pixel_clock / 1000 / 1000);
+ epd_lcd_line_source_cb(NULL, NULL);
+
+ ESP_LOGI(TAG, "LCD init done.");
+ return;
+err:
+ ESP_LOGE(TAG, "LCD initialization failed!");
+ abort();
+}
+
+/**
+ * Deinitializue the LCD driver, i.e., free resources and peripherals.
+ */
+void epd_lcd_deinit() {
+ epd_lcd_line_source_cb(NULL, NULL);
+
+ deinit_bus_gpio();
+ deinit_lcd_peripheral();
+ deinit_dma_trans_link();
+ free_lcd_buffers();
+ deinit_ckv_rmt();
+
+ ESP_LOGI(TAG, "LCD deinitialized.");
+}
+
+void epd_lcd_set_pixel_clock_MHz(int frequency) {
+ lcd.config.pixel_clock = frequency * 1000 * 1000;
+
+ // set pclk
+ int flags = 0;
+
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
+ hal_utils_clk_div_t clk_div = {};
+/**
+ * There was a change in the parameters of this function in this commit:
+ * https://github.com/espressif/esp-idf/commit/d39388fe4f4c5bfb0b52df9177307b1688f41016#diff-2df607d77e3f6e350bab8eb31cfd914500ae42744564e1640cec47006cc17a9c
+ * There are different builds with the same IDF minor version, some with, some without the commit.
+ * So we try to select the correct one by checking if the flag value is defined.
+ */
+#ifdef LCD_HAL_PCLK_FLAG_ALLOW_EQUAL_SYSCLK
+ uint32_t freq
+ = lcd_hal_cal_pclk_freq(&lcd.hal, 240000000, lcd.config.pixel_clock, flags, &clk_div);
+#else
+ uint32_t freq = lcd_hal_cal_pclk_freq(&lcd.hal, 240000000, lcd.config.pixel_clock, &clk_div);
+#endif
+ lcd_ll_set_group_clock_coeff(
+ &LCD_CAM, (int)clk_div.integer, (int)clk_div.denominator, (int)clk_div.numerator
+ );
+#else
+ uint32_t freq = lcd_hal_cal_pclk_freq(&lcd.hal, 240000000, lcd.config.pixel_clock, flags);
+#endif
+
+ ESP_LOGI(TAG, "pclk freq: %d Hz", freq);
+ lcd.line_length_us = (lcd.lcd_res_h + lcd.config.le_high_time + lcd.config.line_front_porch - 1)
+ * 1000000 / lcd.config.pixel_clock
+ + 1;
+ lcd.line_cycles = lcd.line_length_us * lcd.config.pixel_clock / 1000000;
+ ESP_LOGI(TAG, "line width: %dus, %d cylces", lcd.line_length_us, lcd.line_cycles);
+
+ ckv_rmt_build_signal();
+}
+
+void IRAM_ATTR epd_lcd_start_frame() {
+ int initial_lines = min(LINE_BATCH, lcd.display_lines);
+
+ // hsync: pulse with, back porch, active width, front porch
+ int end_line
+ = lcd.line_cycles - lcd.lcd_res_h - lcd.config.le_high_time - lcd.config.line_front_porch;
+ lcd_ll_set_horizontal_timing(
+ lcd.hal.dev,
+ lcd.config.le_high_time - (lcd.dummy_bytes > 0),
+ lcd.config.line_front_porch,
+ // a dummy byte is neeed in 8 bit mode to work around LCD peculiarities
+ lcd.lcd_res_h + (lcd.dummy_bytes > 0),
+ end_line
+ );
+ lcd_ll_set_vertical_timing(lcd.hal.dev, 1, 0, initial_lines, 1);
+
+ // generate the hsync at the very beginning of line
+ lcd_ll_set_hsync_position(lcd.hal.dev, 1);
+
+ // reset FIFO of DMA and LCD, incase there remains old frame data
+ gdma_reset(lcd.dma_chan);
+ lcd_ll_stop(lcd.hal.dev);
+ lcd_ll_fifo_reset(lcd.hal.dev);
+ lcd_ll_enable_auto_next_frame(lcd.hal.dev, true);
+
+ lcd.batches = 0;
+ fill_bounce_buffer(lcd.bounce_buffer[0]);
+ fill_bounce_buffer(lcd.bounce_buffer[1]);
+
+ // the start of DMA should be prior to the start of LCD engine
+ gdma_start(lcd.dma_chan, (intptr_t)&lcd.dma_nodes[0]);
+
+ // enter a critical section to ensure the frame start timing is correct
+ taskENTER_CRITICAL(&frame_start_spinlock);
+
+ // delay 1us is sufficient for DMA to pass data to LCD FIFO
+ // in fact, this is only needed when LCD pixel clock is set too high
+ gpio_set_level(lcd.config.bus.stv, 0);
+ // esp_rom_delay_us(1);
+ // for picture clarity, it seems to be important to start CKV at a "good"
+ // time, seemingly start or towards end of line.
+ start_ckv_cycles(initial_lines + 5);
+ esp_rom_delay_us(lcd.line_length_us);
+ gpio_set_level(lcd.config.bus.stv, 1);
+ esp_rom_delay_us(lcd.line_length_us);
+ esp_rom_delay_us(lcd.config.ckv_high_time / 10);
+
+ // start LCD engine
+ lcd_ll_start(lcd.hal.dev);
+
+ taskEXIT_CRITICAL(&frame_start_spinlock);
+}
+
+#else
+
+/// Dummy implementation to link on the old ESP32
+void epd_lcd_init(const LcdEpdConfig_t* config, int display_width, int display_height) {
+ assert(false);
+}
+
+#endif // S3 Target
diff --git a/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.h b/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.h
new file mode 100644
index 000000000..34c453aab
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_lcd/lcd_driver.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+
+/**
+ * LCD bus configuration parameters.
+ */
+typedef struct {
+ // GPIO numbers of the parallel bus pins.
+ gpio_num_t data[16];
+
+ // horizontal clock pin.
+ gpio_num_t clock;
+ // vertical clock pin
+ gpio_num_t ckv;
+
+ // horizontal "Start Pulse", enabling data input on the line shift register
+ gpio_num_t start_pulse;
+ // latch enable
+ gpio_num_t leh;
+ // vertical start pulse, resetting the vertical line shift register.
+ gpio_num_t stv;
+} lcd_bus_config_t;
+
+/// Configuration structure for the LCD-based Epd driver.
+typedef struct {
+ // high time for CKV in 1/10us.
+ size_t pixel_clock; // = 12000000
+ int ckv_high_time; // = 70
+ int line_front_porch; // = 4
+ int le_high_time; // = 4
+ int bus_width; // = 16
+ lcd_bus_config_t bus;
+} LcdEpdConfig_t;
+
+typedef bool (*line_cb_func_t)(void*, uint8_t*);
+typedef void (*frame_done_func_t)(void*);
+
+void epd_lcd_init(const LcdEpdConfig_t* config, int display_width, int display_height);
+void epd_lcd_deinit();
+void epd_lcd_frame_done_cb(frame_done_func_t, void* payload);
+void epd_lcd_line_source_cb(line_cb_func_t, void* payload);
+void epd_lcd_start_frame();
+/**
+ * Set the LCD pixel clock frequency in MHz.
+ */
+void epd_lcd_set_pixel_clock_MHz(int frequency);
diff --git a/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.c b/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.c
new file mode 100644
index 000000000..c5229d3d9
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.c
@@ -0,0 +1,246 @@
+#include
+#include
+
+#include "../output_common/render_method.h"
+
+#ifdef RENDER_METHOD_LCD
+
+#include
+#include
+
+#include "../epd_internals.h"
+#include "../output_common/line_queue.h"
+#include "../output_common/lut.h"
+#include "../output_common/render_context.h"
+#include "epd_board.h"
+#include "epdiy.h"
+#include "lcd_driver.h"
+#include "render_lcd.h"
+
+// declare vector optimized line mask application.
+void epd_apply_line_mask_VE(uint8_t* line, const uint8_t* mask, int mask_len);
+
+__attribute__((optimize("O3"))) static bool IRAM_ATTR
+retrieve_line_isr(RenderContext_t* ctx, uint8_t* buf) {
+ if (ctx->lines_consumed >= ctx->lines_total) {
+ return false;
+ }
+ int thread = ctx->line_threads[ctx->lines_consumed];
+ assert(thread < NUM_RENDER_THREADS);
+
+ LineQueue_t* lq = &ctx->line_queues[thread];
+
+ BaseType_t awoken = pdFALSE;
+
+ if (lq_read(lq, buf) != 0) {
+ ctx->error |= EPD_DRAW_EMPTY_LINE_QUEUE;
+ memset(buf, 0x00, ctx->display_width / 4);
+ }
+
+ if (ctx->lines_consumed >= ctx->display_height) {
+ memset(buf, 0x00, ctx->display_width / 4);
+ }
+ ctx->lines_consumed += 1;
+ return awoken;
+}
+
+/// start the next frame in the current update cycle
+static void IRAM_ATTR handle_lcd_frame_done(RenderContext_t* ctx) {
+ epd_lcd_frame_done_cb(NULL, NULL);
+ epd_lcd_line_source_cb(NULL, NULL);
+
+ BaseType_t task_awoken = pdFALSE;
+ xSemaphoreGiveFromISR(ctx->frame_done, &task_awoken);
+
+ portYIELD_FROM_ISR();
+}
+
+void lcd_do_update(RenderContext_t* ctx) {
+ epd_set_mode(1);
+
+ for (uint8_t k = 0; k < ctx->cycle_frames; k++) {
+ epd_lcd_frame_done_cb((frame_done_func_t)handle_lcd_frame_done, ctx);
+ prepare_context_for_next_frame(ctx);
+
+ // start both feeder tasks
+ xTaskNotifyGive(ctx->feed_tasks[!xPortGetCoreID()]);
+ xTaskNotifyGive(ctx->feed_tasks[xPortGetCoreID()]);
+
+ // transmission is started in renderer threads, now wait util it's done
+ xSemaphoreTake(ctx->frame_done, portMAX_DELAY);
+
+ for (int i = 0; i < NUM_RENDER_THREADS; i++) {
+ xSemaphoreTake(ctx->feed_done_smphr[i], portMAX_DELAY);
+ }
+
+ ctx->current_frame++;
+
+ // make the watchdog happy.
+ vTaskDelay(0);
+ }
+
+ epd_lcd_line_source_cb(NULL, NULL);
+ epd_lcd_frame_done_cb(NULL, NULL);
+
+ epd_set_mode(0);
+}
+
+__attribute__((optimize("O3"))) static bool IRAM_ATTR
+push_pixels_isr(RenderContext_t* ctx, uint8_t* buf) {
+ // Output no-op outside of drawn area
+ if (ctx->lines_consumed < ctx->area.y) {
+ memset(buf, 0, ctx->display_width / 4);
+ } else if (ctx->lines_consumed >= ctx->area.y + ctx->area.height) {
+ memset(buf, 0, ctx->display_width / 4);
+ } else {
+ memcpy(buf, ctx->static_line_buffer, ctx->display_width / 4);
+ }
+ ctx->lines_consumed += 1;
+ return pdFALSE;
+}
+
+/**
+ * Populate the line mask for use in epd_push_pixels.
+ */
+static void push_pixels_populate_line(RenderContext_t* ctx, int color) {
+ // Select fill pattern by draw color
+ int fill_byte = 0;
+ switch (color) {
+ case 0:
+ fill_byte = DARK_BYTE;
+ break;
+ case 1:
+ fill_byte = CLEAR_BYTE;
+ break;
+ default:
+ fill_byte = 0x00;
+ }
+
+ // Compute a line mask based on the drawn area
+ uint8_t* dirtyness = malloc(ctx->display_width / 2);
+ assert(dirtyness != NULL);
+
+ memset(dirtyness, 0, ctx->display_width / 2);
+
+ for (int i = 0; i < ctx->display_width; i++) {
+ if ((i >= ctx->area.x) && (i < ctx->area.x + ctx->area.width)) {
+ dirtyness[i / 2] |= i % 2 ? 0xF0 : 0x0F;
+ }
+ }
+ epd_populate_line_mask(ctx->line_mask, dirtyness, ctx->display_width / 4);
+
+ // mask the line pattern with the populated mask
+ memset(ctx->static_line_buffer, fill_byte, ctx->display_width / 4);
+ epd_apply_line_mask(ctx->static_line_buffer, ctx->line_mask, ctx->display_width / 4);
+
+ free(dirtyness);
+}
+
+void epd_push_pixels_lcd(RenderContext_t* ctx, short time, int color) {
+ ctx->current_frame = 0;
+ ctx->lines_total = ctx->display_height;
+ ctx->lines_consumed = 0;
+ ctx->static_line_buffer = malloc(ctx->display_width / 4);
+ assert(ctx->static_line_buffer != NULL);
+
+ push_pixels_populate_line(ctx, color);
+ epd_lcd_frame_done_cb((frame_done_func_t)handle_lcd_frame_done, ctx);
+ epd_lcd_line_source_cb((line_cb_func_t)&push_pixels_isr, ctx);
+
+ epd_set_mode(1);
+ epd_lcd_start_frame();
+ xSemaphoreTake(ctx->frame_done, portMAX_DELAY);
+ epd_set_mode(0);
+
+ free(ctx->static_line_buffer);
+ ctx->static_line_buffer = NULL;
+}
+
+#define int_min(a, b) (((a) < (b)) ? (a) : (b))
+__attribute__((optimize("O3"))) void IRAM_ATTR
+lcd_calculate_frame(RenderContext_t* ctx, int thread_id) {
+ assert(ctx->lut_lookup_func != NULL);
+ uint8_t* input_line = ctx->feed_line_buffers[thread_id];
+
+ LineQueue_t* lq = &ctx->line_queues[thread_id];
+ int l = 0;
+
+ // if there is an error, start the frame but don't feed data.
+ if (ctx->error) {
+ memset(ctx->line_threads, 0, ctx->lines_total);
+ epd_lcd_line_source_cb((line_cb_func_t)&retrieve_line_isr, ctx);
+ epd_lcd_start_frame();
+ ESP_LOGW("epd_lcd", "draw frame draw initiated, but an error flag is set: %X", ctx->error);
+ return;
+ }
+
+ // line must be able to hold 2-pixel-per-byte or 1-pixel-per-byte data
+ memset(input_line, 0x00, ctx->display_width);
+
+ EpdRect area = ctx->area;
+ int min_y, max_y, bytes_per_line, _ppB;
+ const uint8_t* ptr_start;
+ get_buffer_params(ctx, &bytes_per_line, &ptr_start, &min_y, &max_y, &_ppB);
+
+ assert(area.width == ctx->display_width && area.x == 0 && !ctx->error);
+
+ // index of the line that triggers the frame output when processed
+ int trigger_line = int_min(63, max_y - min_y);
+
+ while (l = atomic_fetch_add(&ctx->lines_prepared, 1), l < ctx->lines_total) {
+ ctx->line_threads[l] = thread_id;
+
+ // queue is sufficiently filled to fill both bounce buffers, frame
+ // can begin
+ if (l - min_y == trigger_line) {
+ epd_lcd_line_source_cb((line_cb_func_t)&retrieve_line_isr, ctx);
+ epd_lcd_start_frame();
+ }
+
+ if (l < min_y || l >= max_y
+ || (ctx->drawn_lines != NULL && !ctx->drawn_lines[l - area.y])) {
+ uint8_t* buf = NULL;
+ while (buf == NULL) {
+ // break in case of errors
+ if (ctx->error & EPD_DRAW_EMPTY_LINE_QUEUE) {
+ printf("on err 1: %d %d\n", ctx->lines_prepared, ctx->lines_consumed);
+ lq_reset(lq);
+ return;
+ };
+
+ buf = lq_current(lq);
+ }
+ memset(buf, 0x00, lq->element_size);
+ lq_commit(lq);
+ continue;
+ }
+
+ uint32_t* lp = (uint32_t*)input_line;
+ const uint8_t* ptr = ptr_start + bytes_per_line * (l - min_y);
+
+ Cache_Start_DCache_Preload((uint32_t)ptr, ctx->display_width, 0);
+
+ lp = (uint32_t*)ptr;
+
+ uint8_t* buf = NULL;
+ while (buf == NULL) {
+ // break in case of errors
+ if (ctx->error & EPD_DRAW_EMPTY_LINE_QUEUE) {
+ lq_reset(lq);
+ printf("on err 2: %d %d\n", ctx->lines_prepared, ctx->lines_consumed);
+ return;
+ };
+
+ buf = lq_current(lq);
+ }
+
+ ctx->lut_lookup_func(lp, buf, ctx->conversion_lut, ctx->display_width);
+
+ // apply the line mask
+ epd_apply_line_mask_VE(buf, ctx->line_mask, ctx->display_width / 4);
+
+ lq_commit(lq);
+ }
+}
+
+#endif
diff --git a/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.h b/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.h
new file mode 100644
index 000000000..3c521e856
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/output_lcd/render_lcd.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "../output_common/render_context.h"
+
+/**
+ * Lighten / darken picels using the LCD driving method.
+ */
+void epd_push_pixels_lcd(RenderContext_t* ctx, short time, int color);
+
+/**
+ * Do a full update cycle with a configured context.
+ */
+void lcd_do_update(RenderContext_t* ctx);
+
+/**
+ * Worker thread for output calculation.
+ * In LCD mode, both threads do the same thing.
+ */
+void lcd_calculate_frame(RenderContext_t* ctx, int thread_id);
diff --git a/lib/libesp32_eink/epdiy/src/render.c b/lib/libesp32_eink/epdiy/src/render.c
new file mode 100644
index 000000000..eaba217d8
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/render.c
@@ -0,0 +1,526 @@
+#include "render.h"
+
+#include "epd_board.h"
+#include "epd_internals.h"
+#include "epdiy.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "esp_heap_caps.h"
+#include "output_common/line_queue.h"
+#include "output_common/lut.h"
+#include "output_common/render_context.h"
+#include "output_common/render_method.h"
+#include "output_i2s/render_i2s.h"
+#include "output_lcd/render_lcd.h"
+
+static inline int min(int x, int y) {
+ return x < y ? x : y;
+}
+static inline int max(int x, int y) {
+ return x > y ? x : y;
+}
+
+const int clear_cycle_time = 12;
+
+#define RTOS_ERROR_CHECK(x) \
+ do { \
+ esp_err_t __err_rc = (x); \
+ if (__err_rc != pdPASS) { \
+ abort(); \
+ } \
+ } while (0)
+
+static RenderContext_t render_context;
+
+void epd_push_pixels(EpdRect area, short time, int color) {
+ render_context.area = area;
+#ifdef RENDER_METHOD_LCD
+ epd_push_pixels_lcd(&render_context, time, color);
+#else
+ epd_push_pixels_i2s(&render_context, area, time, color);
+#endif
+}
+
+///////////////////////////// Coordination ///////////////////////////////
+
+/**
+ * Find the waveform temperature range index for a given temperature in °C.
+ * If no range in the waveform data fits the given temperature, return the
+ * closest one.
+ * Returns -1 if the waveform does not contain any temperature range.
+ */
+int waveform_temp_range_index(const EpdWaveform* waveform, int temperature) {
+ int idx = 0;
+ if (waveform->num_temp_ranges == 0) {
+ return -1;
+ }
+ while (idx < waveform->num_temp_ranges - 1 && waveform->temp_intervals[idx].min < temperature) {
+ idx++;
+ }
+ return idx;
+}
+
+static int get_waveform_index(const EpdWaveform* waveform, enum EpdDrawMode mode) {
+ for (int i = 0; i < waveform->num_modes; i++) {
+ if (waveform->mode_data[i]->type == (mode & 0x3F)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+///////////////////////////// API Procedures //////////////////////////////////
+
+/// Rounded up display height for even division into multi-line buffers.
+static inline int rounded_display_height() {
+ return (((epd_height() + 7) / 8) * 8);
+}
+
+// FIXME: fix misleading naming:
+// area -> buffer dimensions
+// crop -> area taken out of buffer
+enum EpdDrawError IRAM_ATTR epd_draw_base(
+ EpdRect area,
+ const uint8_t* data,
+ EpdRect crop_to,
+ enum EpdDrawMode mode,
+ int temperature,
+ const bool* drawn_lines,
+ const uint8_t* drawn_columns,
+ const EpdWaveform* waveform
+) {
+ if (waveform == NULL) {
+ return EPD_DRAW_NO_PHASES_AVAILABLE;
+ }
+ int waveform_range = waveform_temp_range_index(waveform, temperature);
+ if (waveform_range < 0) {
+ return EPD_DRAW_NO_PHASES_AVAILABLE;
+ }
+ int waveform_index = 0;
+ uint8_t frame_count = 0;
+ const EpdWaveformPhases* waveform_phases = NULL;
+
+ // no waveform required for monochrome mode
+ if (!(mode & MODE_EPDIY_MONOCHROME)) {
+ waveform_index = get_waveform_index(waveform, mode);
+ if (waveform_index < 0) {
+ return EPD_DRAW_MODE_NOT_FOUND;
+ }
+
+ waveform_phases = waveform->mode_data[waveform_index]->range_data[waveform_range];
+ // FIXME: error if not present
+ frame_count = waveform_phases->phases;
+ } else {
+ frame_count = 1;
+ }
+
+ if (crop_to.width < 0 || crop_to.height < 0) {
+ return EPD_DRAW_INVALID_CROP;
+ }
+
+ const bool crop = (crop_to.width > 0 && crop_to.height > 0);
+ if (crop
+ && (crop_to.width > area.width || crop_to.height > area.height || crop_to.x > area.width
+ || crop_to.y > area.height)) {
+ return EPD_DRAW_INVALID_CROP;
+ }
+
+#ifdef RENDER_METHOD_LCD
+ if (mode & MODE_PACKING_1PPB_DIFFERENCE && render_context.conversion_lut_size > 1 << 10) {
+ ESP_LOGI(
+ "epdiy",
+ "Using optimized vector implementation on the ESP32-S3, only 1k of %d LUT in use!",
+ render_context.conversion_lut_size
+ );
+ }
+#endif
+
+ LutFunctionPair lut_functions = find_lut_functions(mode, render_context.conversion_lut_size);
+ if (lut_functions.build_func == NULL || lut_functions.lookup_func == NULL) {
+ ESP_LOGE("epdiy", "no output lookup method found for your mode and LUT size!");
+ return EPD_DRAW_LOOKUP_NOT_IMPLEMENTED;
+ }
+
+ render_context.area = area;
+ render_context.crop_to = crop_to;
+ render_context.waveform_range = waveform_range;
+ render_context.waveform_index = waveform_index;
+ render_context.mode = mode;
+ render_context.waveform = waveform;
+ render_context.error = EPD_DRAW_SUCCESS;
+ render_context.drawn_lines = drawn_lines;
+ render_context.data_ptr = data;
+ render_context.lut_build_func = lut_functions.build_func;
+ render_context.lut_lookup_func = lut_functions.lookup_func;
+
+ render_context.lines_prepared = 0;
+ render_context.lines_consumed = 0;
+ render_context.lines_total = rounded_display_height();
+ render_context.current_frame = 0;
+ render_context.cycle_frames = frame_count;
+ render_context.phase_times = NULL;
+ if (waveform_phases != NULL && waveform_phases->phase_times != NULL) {
+ render_context.phase_times = waveform_phases->phase_times;
+ }
+
+ epd_populate_line_mask(
+ render_context.line_mask, drawn_columns, render_context.display_width / 4
+ );
+
+#ifdef RENDER_METHOD_I2S
+ i2s_do_update(&render_context);
+#elif defined(RENDER_METHOD_LCD)
+ lcd_do_update(&render_context);
+#endif
+
+ if (render_context.error & EPD_DRAW_EMPTY_LINE_QUEUE) {
+ ESP_LOGE("epdiy", "line buffer underrun occurred!");
+ }
+
+ if (render_context.error != EPD_DRAW_SUCCESS) {
+ return render_context.error;
+ }
+ return EPD_DRAW_SUCCESS;
+}
+
+static void IRAM_ATTR render_thread(void* arg) {
+ int thread_id = (int)arg;
+
+ while (true) {
+ ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+#ifdef RENDER_METHOD_LCD
+ lcd_calculate_frame(&render_context, thread_id);
+#elif defined(RENDER_METHOD_I2S)
+ if (thread_id == 0) {
+ i2s_fetch_frame_data(&render_context, thread_id);
+ } else {
+ i2s_output_frame(&render_context, thread_id);
+ }
+#endif
+
+ xSemaphoreGive(render_context.feed_done_smphr[thread_id]);
+ }
+}
+
+void epd_clear_area(EpdRect area) {
+ epd_clear_area_cycles(area, 3, clear_cycle_time);
+}
+
+void epd_clear_area_cycles(EpdRect area, int cycles, int cycle_time) {
+ const short white_time = cycle_time;
+ const short dark_time = cycle_time;
+
+ for (int c = 0; c < cycles; c++) {
+ for (int i = 0; i < 10; i++) {
+ epd_push_pixels(area, dark_time, 0);
+ }
+ for (int i = 0; i < 10; i++) {
+ epd_push_pixels(area, white_time, 1);
+ }
+ for (int i = 0; i < 2; i++) {
+ epd_push_pixels(area, white_time, 2);
+ }
+ }
+}
+
+void epd_renderer_init(enum EpdInitOptions options) {
+ // Either the board should be set in menuconfig or the epd_set_board() must
+ // be called before epd_init()
+ assert((epd_current_board() != NULL));
+
+ epd_current_board()->init(epd_width());
+ epd_control_reg_init();
+
+ render_context.display_width = epd_width();
+ render_context.display_height = epd_height();
+
+ size_t lut_size = 0;
+ if (options & EPD_LUT_1K) {
+ lut_size = 1 << 10;
+ } else if (options & EPD_LUT_64K) {
+ lut_size = 1 << 16;
+ } else if (options == EPD_OPTIONS_DEFAULT) {
+#ifdef RENDER_METHOD_LCD
+ lut_size = 1 << 10;
+#else
+ lut_size = 1 << 16;
+#endif
+ } else {
+ ESP_LOGE("epd", "invalid init options: %d", options);
+ return;
+ }
+
+ ESP_LOGI("epd", "Space used for waveform LUT: %dK", lut_size / 1024);
+ render_context.conversion_lut
+ = (uint8_t*)heap_caps_malloc(lut_size, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+ if (render_context.conversion_lut == NULL) {
+ ESP_LOGE("epd", "could not allocate LUT!");
+ abort();
+ }
+ render_context.conversion_lut_size = lut_size;
+ render_context.static_line_buffer = NULL;
+
+ render_context.frame_done = xSemaphoreCreateBinary();
+
+ for (int i = 0; i < NUM_RENDER_THREADS; i++) {
+ render_context.feed_done_smphr[i] = xSemaphoreCreateBinary();
+ }
+
+ // When using the LCD peripheral, we may need padding lines to
+ // satisfy the bounce buffer size requirements
+ render_context.line_threads = (uint8_t*)heap_caps_malloc(
+ rounded_display_height(), MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL
+ );
+
+ int queue_len = 32;
+ if (options & EPD_FEED_QUEUE_32) {
+ queue_len = 32;
+ } else if (options & EPD_FEED_QUEUE_8) {
+ queue_len = 8;
+ }
+
+ if (render_context.conversion_lut == NULL) {
+ ESP_LOGE("epd", "could not allocate line mask!");
+ abort();
+ }
+
+ render_context.line_mask
+ = heap_caps_aligned_alloc(16, epd_width() / 4, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
+ assert(render_context.line_mask != NULL);
+
+#ifdef RENDER_METHOD_LCD
+ size_t queue_elem_size = render_context.display_width / 4;
+#elif defined(RENDER_METHOD_I2S)
+ size_t queue_elem_size = render_context.display_width;
+#endif
+
+ for (int i = 0; i < NUM_RENDER_THREADS; i++) {
+ render_context.line_queues[i] = lq_init(queue_len, queue_elem_size);
+ render_context.feed_line_buffers[i] = (uint8_t*)heap_caps_malloc(
+ render_context.display_width, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL
+ );
+ assert(render_context.feed_line_buffers[i] != NULL);
+ RTOS_ERROR_CHECK(xTaskCreatePinnedToCore(
+ render_thread,
+ "epd_prep",
+ 1 << 12,
+ (void*)i,
+ configMAX_PRIORITIES - 1,
+ &render_context.feed_tasks[i],
+ i
+ ));
+ }
+}
+
+void epd_renderer_deinit() {
+ const EpdBoardDefinition* epd_board = epd_current_board();
+
+ epd_board->poweroff(epd_ctrl_state());
+
+ for (int i = 0; i < NUM_RENDER_THREADS; i++) {
+ vTaskDelete(render_context.feed_tasks[i]);
+ lq_free(&render_context.line_queues[i]);
+ heap_caps_free(render_context.feed_line_buffers[i]);
+ vSemaphoreDelete(render_context.feed_done_smphr[i]);
+ }
+
+#ifdef RENDER_METHOD_I2S
+ i2s_deinit();
+#endif
+
+ epd_control_reg_deinit();
+
+ if (epd_board->deinit) {
+ epd_board->deinit();
+ }
+
+ heap_caps_free(render_context.conversion_lut);
+ heap_caps_free(render_context.line_threads);
+ heap_caps_free(render_context.line_mask);
+ vSemaphoreDelete(render_context.frame_done);
+}
+
+#ifdef RENDER_METHOD_LCD
+uint32_t epd_interlace_4bpp_line_VE(
+ const uint8_t* to,
+ const uint8_t* from,
+ uint8_t* interlaced,
+ uint8_t* col_dirtyness,
+ int fb_width
+);
+#endif
+
+/**
+ * Interlaces `len` nibbles from the buffers `to` and `from` into `interlaced`.
+ * In the process, tracks which nibbles differ in `col_dirtyness`.
+ * Returns `1` if there are differences, `0` otherwise.
+ * Does not require special alignment of the buffers beyond 32 bit alignment.
+ */
+__attribute__((optimize("O3"))) static inline int _interlace_line_unaligned(
+ const uint8_t* to, const uint8_t* from, uint8_t* interlaced, uint8_t* col_dirtyness, int len
+) {
+ int dirty = 0;
+ for (int x = 0; x < len; x++) {
+ uint8_t t = *(to + x / 2);
+ uint8_t f = *(from + x / 2);
+ t = (x % 2) ? (t >> 4) : (t & 0x0f);
+ f = (x % 2) ? (f >> 4) : (f & 0x0f);
+ col_dirtyness[x / 2] |= (t ^ f) << (4 * (x % 2));
+ dirty |= (t ^ f);
+ interlaced[x] = (t << 4) | f;
+ }
+ return dirty;
+}
+
+/**
+ * Interlaces the lines at `to`, `from` into `interlaced`.
+ * returns `1` if there are differences, `0` otherwise.
+ */
+__attribute__((optimize("O3"))) bool _epd_interlace_line(
+ const uint8_t* to,
+ const uint8_t* from,
+ uint8_t* interlaced,
+ uint8_t* col_dirtyness,
+ int fb_width
+) {
+#ifdef RENDER_METHOD_I2S
+ return _interlace_line_unaligned(to, from, interlaced, col_dirtyness, fb_width) > 0;
+#elif defined(RENDER_METHOD_LCD)
+ // Use Vector Extensions with the ESP32-S3.
+ // Both input buffers should have the same alignment w.r.t. 16 bytes,
+ // as asserted in epd_difference_image_base.
+ uint32_t dirty = 0;
+
+ // alignment boundaries in pixels
+ int unaligned_len_front_px = ((16 - (uint32_t)to % 16) * 2) % 32;
+ int unaligned_len_back_px = (((uint32_t)to + fb_width / 2) % 16) * 2;
+ int unaligned_back_start_px = fb_width - unaligned_len_back_px;
+ int aligned_len_px = fb_width - unaligned_len_front_px - unaligned_len_back_px;
+
+ dirty |= _interlace_line_unaligned(to, from, interlaced, col_dirtyness, unaligned_len_front_px);
+ dirty |= epd_interlace_4bpp_line_VE(
+ to + unaligned_len_front_px / 2,
+ from + unaligned_len_front_px / 2,
+ interlaced + unaligned_len_front_px,
+ col_dirtyness + unaligned_len_front_px / 2,
+ aligned_len_px
+ );
+ dirty |= _interlace_line_unaligned(
+ to + unaligned_back_start_px / 2,
+ from + unaligned_back_start_px / 2,
+ interlaced + unaligned_back_start_px,
+ col_dirtyness + unaligned_back_start_px / 2,
+ unaligned_len_back_px
+ );
+ return dirty;
+#endif
+}
+
+EpdRect epd_difference_image_base(
+ const uint8_t* to,
+ const uint8_t* from,
+ EpdRect crop_to,
+ int fb_width,
+ int fb_height,
+ uint8_t* interlaced,
+ bool* dirty_lines,
+ uint8_t* col_dirtyness
+) {
+ assert(fb_width % 8 == 0);
+ assert(col_dirtyness != NULL);
+
+ // these buffers should be allocated 16 byte aligned
+ assert((uint32_t)to % 16 == 0);
+ assert((uint32_t)from % 16 == 0);
+ assert((uint32_t)col_dirtyness % 16 == 0);
+ assert((uint32_t)interlaced % 16 == 0);
+
+ memset(col_dirtyness, 0, fb_width / 2);
+ memset(dirty_lines, 0, sizeof(bool) * fb_height);
+
+ int x_end = min(fb_width, crop_to.x + crop_to.width);
+ int y_end = min(fb_height, crop_to.y + crop_to.height);
+
+ for (int y = crop_to.y; y < y_end; y++) {
+ uint32_t offset = y * fb_width / 2;
+ int dirty = _epd_interlace_line(
+ to + offset, from + offset, interlaced + offset * 2, col_dirtyness, fb_width
+ );
+ dirty_lines[y] = dirty;
+ }
+
+ int min_x, min_y, max_x, max_y;
+ for (min_x = crop_to.x; min_x < x_end; min_x++) {
+ uint8_t mask = min_x % 2 ? 0xF0 : 0x0F;
+ if ((col_dirtyness[min_x / 2] & mask) != 0)
+ break;
+ }
+ for (max_x = x_end - 1; max_x >= crop_to.x; max_x--) {
+ uint8_t mask = min_x % 2 ? 0xF0 : 0x0F;
+ if ((col_dirtyness[max_x / 2] & mask) != 0)
+ break;
+ }
+ for (min_y = crop_to.y; min_y < y_end; min_y++) {
+ if (dirty_lines[min_y] != 0)
+ break;
+ }
+ for (max_y = y_end - 1; max_y >= crop_to.y; max_y--) {
+ if (dirty_lines[max_y] != 0)
+ break;
+ }
+
+ EpdRect crop_rect = {
+ .x = min_x,
+ .y = min_y,
+ .width = max(max_x - min_x + 1, 0),
+ .height = max(max_y - min_y + 1, 0),
+ };
+
+ return crop_rect;
+}
+
+EpdRect epd_difference_image(
+ const uint8_t* to,
+ const uint8_t* from,
+ uint8_t* interlaced,
+ bool* dirty_lines,
+ uint8_t* col_dirtyness
+) {
+ return epd_difference_image_base(
+ to,
+ from,
+ epd_full_screen(),
+ epd_width(),
+ epd_height(),
+ interlaced,
+ dirty_lines,
+ col_dirtyness
+ );
+}
+
+EpdRect epd_difference_image_cropped(
+ const uint8_t* to,
+ const uint8_t* from,
+ EpdRect crop_to,
+ uint8_t* interlaced,
+ bool* dirty_lines,
+ uint8_t* col_dirtyness
+) {
+ EpdRect result = epd_difference_image_base(
+ to, from, crop_to, epd_width(), epd_height(), interlaced, dirty_lines, col_dirtyness
+ );
+ return result;
+}
diff --git a/lib/libesp32_eink/epdiy/src/render.h b/lib/libesp32_eink/epdiy/src/render.h
new file mode 100644
index 000000000..9a0810e62
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/render.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "epdiy.h"
+/**
+ * Initialize the EPD renderer and its render context.
+ */
+void epd_renderer_init(enum EpdInitOptions options);
+
+/**
+ * Deinitialize the EPD renderer and free up its resources.
+ */
+void epd_renderer_deinit();
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED047TC1.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED047TC1.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED047TC1.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED047TC1.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/ED047TC2.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED047TC2.h
similarity index 98%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/ED047TC2.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED047TC2.h
index d213dd2f4..18eb71948 100644
--- a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/ED047TC2.h
+++ b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED047TC2.h
@@ -1,52 +1,52 @@
#include
-const uint8_t epd_wp_ed047tc2_1_5_data[25][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x80,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x00,0x15,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_5 = { .phases = 25, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_5_data[0] };
-const uint8_t epd_wp_ed047tc2_1_6_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x84,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x84,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x04}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x04}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x04}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x18}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x18}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x98}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_6 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_6_data[0] };
-const uint8_t epd_wp_ed047tc2_1_7_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x90}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_7 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_7_data[0] };
-const uint8_t epd_wp_ed047tc2_1_8_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_8 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_8_data[0] };
-const uint8_t epd_wp_ed047tc2_1_9_data[18][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x15,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x80,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x84}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_9 = { .phases = 18, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_9_data[0] };
-const uint8_t epd_wp_ed047tc2_1_10_data[17][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x90,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x90,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa4,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x40}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x40}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x90}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa4}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_10 = { .phases = 17, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_10_data[0] };
-const uint8_t epd_wp_ed047tc2_1_11_data[15][16][4] = {{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x54}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x90,0x00,0x54}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x54}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x54}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x40,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x85,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_1_11 = { .phases = 15, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_1_11_data[0] };
-const EpdWaveformPhases* epd_wm_ed047tc2_1_ranges[7] = { &epd_wp_ed047tc2_1_5,&epd_wp_ed047tc2_1_6,&epd_wp_ed047tc2_1_7,&epd_wp_ed047tc2_1_8,&epd_wp_ed047tc2_1_9,&epd_wp_ed047tc2_1_10,&epd_wp_ed047tc2_1_11 };
+const uint8_t epd_wp_ED047TC2_1_5_data[25][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x80,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x00,0x15,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_5 = { .phases = 25, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_5_data[0] };
+const uint8_t epd_wp_ED047TC2_1_6_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x84,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x84,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x04}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x04}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x04}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x18}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x18}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x98}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_6 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_6_data[0] };
+const uint8_t epd_wp_ED047TC2_1_7_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x80}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x90}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_7 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_7_data[0] };
+const uint8_t epd_wp_ED047TC2_1_8_data[22][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x04}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x88}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x01,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_8 = { .phases = 22, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_8_data[0] };
+const uint8_t epd_wp_ED047TC2_1_9_data[18][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x15},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa8,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x15,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x80,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x01,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x00}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x04}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x84}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_9 = { .phases = 18, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_9_data[0] };
+const uint8_t epd_wp_ED047TC2_1_10_data[17][16][4] = {{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x90,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x01},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x90,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa4,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa8,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x00}},{{0x00,0x00,0x01,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x00}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x00,0x00}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa0,0x40}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x40}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0x90}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa0}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa4}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_10 = { .phases = 17, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_10_data[0] };
+const uint8_t epd_wp_ED047TC2_1_11_data[15][16][4] = {{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xa0,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x00,0x00,0x54}},{{0x00,0x00,0x00,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x80,0x00,0x54}},{{0x00,0x00,0x05,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x90,0x00,0x54}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x54}},{{0x00,0x00,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xa0,0x00,0x54}},{{0x00,0x05,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x40,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0x85,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x15,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_1_11 = { .phases = 15, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_1_11_data[0] };
+const EpdWaveformPhases* epd_wm_ed047tc2_1_ranges[7] = { &epd_wp_ED047TC2_1_5,&epd_wp_ED047TC2_1_6,&epd_wp_ED047TC2_1_7,&epd_wp_ED047TC2_1_8,&epd_wp_ED047TC2_1_9,&epd_wp_ED047TC2_1_10,&epd_wp_ED047TC2_1_11 };
const EpdWaveformMode epd_wm_ed047tc2_1 = { .type = 1, .temp_ranges = 7, .range_data = &epd_wm_ed047tc2_1_ranges[0] };
-const uint8_t epd_wp_ed047tc2_2_5_data[46][16][4] = {{{0x00,0x00,0x00,0x00},{0x20,0x88,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x80,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x08,0x00},{0x00,0x02,0x00,0x80},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa2,0x88,0x20,0x88},{0x22,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x00,0x44,0x08,0x00},{0xa0,0x02,0x20,0xa8},{0x08,0x62,0x88,0x80},{0x00,0x00,0x00,0x08},{0x08,0x22,0x88,0x80},{0x00,0x80,0x00,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x24,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x80,0x82,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x84,0x84,0x28,0x80},{0xa0,0x02,0x20,0xaa},{0xa8,0xaa,0x8a,0x80},{0x22,0x84,0x00,0x28},{0x2a,0xaa,0xaa,0xa0},{0x00,0x80,0x28,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x08,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x00,0x20,0x02},{0x00,0x00,0x00,0x02},{0x84,0x88,0x2a,0xa2},{0xa0,0xaa,0xa8,0xa8},{0xa8,0xaa,0x8a,0x80},{0x2a,0xaa,0x08,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x08}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0x24,0x80,0x00},{0x00,0x00,0x00,0x00},{0x29,0x80,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x02,0xa0,0x00},{0x02,0x00,0x00,0x81},{0x88,0xa8,0xaa,0xa9},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0x8a,0x81},{0x2a,0xaa,0x2a,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x04}},{{0xaa,0xaa,0xa8,0xa4},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0xa8,0x80,0x00},{0x00,0x20,0x00,0x00},{0x2a,0x84,0xa0,0x08},{0x2a,0x68,0x20,0x80},{0x80,0xa2,0xa2,0xa8},{0x80,0x02,0xa0,0x01},{0x02,0x80,0x00,0xa9},{0x9a,0xa8,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x89},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x8a,0x28,0x04}},{{0xaa,0xaa,0xa8,0x64},{0x2a,0xaa,0xaa,0x01},{0x00,0x88,0x02,0x00},{0x29,0xa8,0x80,0x00},{0x00,0x28,0x08,0x02},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xa2,0xa2,0xa9},{0x80,0x02,0xa0,0x01},{0x02,0xa0,0x00,0xa9},{0x9a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0x8a,0xa8,0x84}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x00,0x8a,0x02,0x08},{0x2a,0xa8,0x88,0x00},{0x00,0x28,0x8a,0x01},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xaa,0xaa,0xa9},{0x80,0x02,0xa0,0x01},{0x0a,0xaa,0x80,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x8a,0xaa,0x56}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x20,0x8a,0x0a,0x08},{0x2a,0xa8,0xaa,0x00},{0x00,0x2a,0x8a,0x01},{0x2a,0xaa,0xa8,0x08},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x80,0x02,0xa0,0x81},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x59},{0x69,0x8a,0xaa,0x56}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa0,0x8a,0x0a,0x0a},{0xaa,0xaa,0xaa,0x02},{0x08,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x09},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x82,0x82,0xa0,0xa1},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0x59,0x8a,0xaa,0x55}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa2,0x8a,0x2a,0x09},{0xaa,0xaa,0xaa,0x09},{0x28,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x89},{0x2a,0xaa,0xa8,0xa1},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0xa0,0xa9},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x55}},{{0xaa,0xaa,0xaa,0x58},{0x2a,0xaa,0xa5,0x05},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x01},{0x2a,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x01},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x55}},{{0xaa,0xaa,0x96,0xa8},{0xaa,0xaa,0x55,0x09},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x98,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa4,0x55},{0xaa,0xa8,0x8a,0x55},{0xaa,0xaa,0xa5,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x54,0xaa,0xaa,0x55}},{{0xaa,0xa5,0x96,0xa8},{0xaa,0xa5,0x55,0xa9},{0xaa,0xaa,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x90,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0xaa,0x55},{0xa6,0x99,0x55,0x55},{0x94,0xaa,0xa6,0x51}},{{0xaa,0xa5,0x56,0xa8},{0xaa,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x15,0x55},{0x92,0x95,0x65,0x55},{0xaa,0xaa,0xa5,0x55},{0x95,0x95,0x55,0x55},{0x94,0xaa,0x96,0x01}},{{0xa9,0x55,0x56,0xa8},{0xa9,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa5},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x9a,0x85,0x55,0x55},{0x94,0x95,0x55,0x55},{0x99,0xa9,0x95,0x55},{0x95,0x55,0x55,0x55},{0x94,0xaa,0x96,0x01}},{{0x95,0x55,0x56,0xa8},{0xa5,0x55,0x5a,0xa5},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0xa5},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0x96,0x65},{0xaa,0xaa,0x1a,0x59},{0xaa,0x59,0x51,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xa8,0x55,0x55,0x55},{0x98,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x94,0x6a,0x96,0x01}},{{0x95,0x55,0x55,0x94},{0x95,0x55,0xaa,0x95},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0x95},{0x2a,0xaa,0xa5,0x55},{0x9a,0x6a,0x55,0x55},{0xaa,0x85,0x5a,0x55},{0xaa,0x59,0x55,0x55},{0xaa,0xa9,0x5a,0x55},{0xa8,0xaa,0x00,0x55},{0xa8,0x55,0x55,0x55},{0x91,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x90,0x69,0x95,0x01}},{{0x55,0x55,0x55,0x54},{0x96,0x5a,0xaa,0x15},{0xaa,0xa6,0xa9,0x05},{0xaa,0x9a,0x65,0x55},{0x2a,0x96,0x65,0x55},{0x96,0x65,0x55,0x55},{0xa1,0x95,0x56,0x55},{0x28,0x55,0x55,0x55},{0xaa,0xa9,0x52,0x55},{0xa9,0x01,0x05,0x55},{0x25,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x55,0x55,0x69,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa6,0xa5,0x85},{0x9a,0x56,0x55,0x55},{0xaa,0x95,0x65,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0xa1,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x55,0x5a,0xa9,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa5,0xa5,0x85},{0x92,0x55,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x15,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x56,0xaa,0xa9,0x55},{0x99,0xaa,0xa1,0x55},{0xaa,0x65,0x95,0x45},{0x95,0x55,0x55,0x55},{0xa6,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x54,0x55},{0x55,0x55,0x55,0x55},{0x05,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x01}},{{0x6a,0xaa,0xaa,0x55},{0x95,0xaa,0x15,0x55},{0x9a,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0xa5,0x55,0x55},{0x99,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x15,0x65,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x41,0x01}},{{0xaa,0xaa,0x56,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x56},{0x55,0x55,0x55,0x55},{0x69,0x55,0x55,0x55},{0xaa,0x55,0x41,0x01}},{{0xa9,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x55,0x55,0x96},{0x65,0x55,0x55,0x56},{0x6a,0x65,0x55,0xa6},{0xaa,0x94,0x49,0x02}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x6a,0x2a,0x8a,0xaa},{0x6a,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x51,0x56},{0x65,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x40,0xaa},{0x55,0x54,0x45,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x56,0xa6,0x50},{0x55,0x56,0x95,0x56},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x95,0x55,0x55},{0x55,0x55,0x95,0x04},{0x45,0x05,0x55,0xaa},{0x55,0x55,0x55,0xaa},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x45,0x48,0x58,0x50},{0x55,0x55,0x41,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x54,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x54},{0x41,0x04,0x44,0x12},{0x6a,0x2a,0x21,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x69},{0x55,0x55,0x55,0x54},{0x45,0x05,0x15,0x16},{0x41,0x41,0x15,0x02},{0x6a,0x00,0xa0,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x66},{0x55,0x59,0x59,0xa6},{0x60,0x00,0x00,0x0a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x6a,0x59,0x51,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x50,0x55,0x55,0x52},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x6a,0x55,0x55,0x02},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xa5,0x96,0xa6,0x5a},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_5 = { .phases = 46, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_5_data[0] };
-const uint8_t epd_wp_ed047tc2_2_6_data[43][16][4] = {{{0x02,0xaa,0x00,0x00},{0x20,0x22,0xa8,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x22,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xa8,0x20},{0x00,0x00,0x00,0x00},{0x20,0x02,0x08,0x80},{0x00,0x80,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x2a,0xaa,0x00,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x28},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xaa,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x20},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa0,0x20,0x2a},{0x28,0x22,0xa8,0xa8},{0x28,0x00,0x00,0x00}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa8,0x22,0x2a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x80}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0xa2,0x82,0x08,0x80},{0x08,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x42}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x20,0x00,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0xa8},{0x00,0x00,0x00,0x00},{0xaa,0x82,0x88,0xa0},{0x8a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0x94},{0x24,0x00,0x28,0x42}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x20,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0x8a,0x8a,0xa0},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x24,0x00,0x28,0x42}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x22,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0xa0,0xa0,0xa8,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa5},{0xa6,0xaa,0xaa,0x95},{0x24,0x00,0x26,0x41}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x42},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xa2,0xa8,0xaa,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xa8},{0x08,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa6,0x55},{0x56,0x02,0x95,0x55}},{{0xaa,0xaa,0xa0,0x04},{0x20,0xaa,0xa5,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x26},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0x98},{0x88,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xa5,0xa9,0x65,0x55},{0x56,0x0a,0x95,0x55}},{{0xaa,0xa9,0xa0,0x24},{0x20,0xa9,0x55,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x25},{0x2a,0x80,0x00,0x02},{0x20,0xa0,0x28,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x80},{0xa0,0x00,0x00,0x01},{0x20,0xa2,0xa8,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xa2,0xa8,0xaa},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xa5,0x95,0x55,0x55},{0x56,0x0a,0x95,0x55}},{{0xaa,0x95,0xa8,0xa4},{0x20,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x29},{0xa2,0x88,0x00,0x15},{0x2a,0x80,0x00,0x01},{0x20,0xa8,0x28,0x14},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x81},{0xa0,0x00,0x00,0x01},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x56,0x89,0x55,0x55}},{{0xaa,0x95,0x98,0x94},{0xa0,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x25},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0x20,0xaa,0xa8,0x94},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0xa1},{0xa0,0x22,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x94},{0xa8,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0xa9,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x15}},{{0xa9,0x55,0x9a,0x98},{0xa8,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0xa2,0xaa,0xaa,0x94},{0xaa,0xaa,0xaa,0x89},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x2a,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x56},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0x95,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x15}},{{0xa5,0x55,0x5a,0xa8},{0xa8,0x95,0x55,0x45},{0xa0,0x82,0x20,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x85,0x69},{0xaa,0x2a,0xa8,0x29},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xa9,0xa9,0xa5,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0xa5,0x41,0x15}},{{0x95,0x55,0x6a,0x68},{0xa8,0x55,0x55,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xa9,0x55,0x69},{0xaa,0x2a,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0x99,0xa9,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x65,0x40,0x15}},{{0x95,0x55,0x66,0x58},{0xa8,0x55,0x5a,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0xa8,0xa0,0x15},{0xaa,0x62,0xa8,0x19},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x95},{0xaa,0x95,0x55,0x55},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa9,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x65,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x91,0x55,0x40,0x15}},{{0x95,0x56,0xa5,0x94},{0xa8,0x56,0xaa,0x85},{0xa8,0xaa,0xa0,0x95},{0xaa,0xa8,0xa0,0x15},{0xaa,0x6a,0xaa,0x15},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x55,0x55},{0x89,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0x99,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x50,0x00,0x15}},{{0x55,0x6a,0x89,0x94},{0x98,0x6a,0xaa,0x85},{0xaa,0xaa,0xa0,0x95},{0xaa,0xa6,0xa0,0x15},{0x8a,0x6a,0xaa,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xaa,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x89,0x50,0x00,0x15}},{{0x56,0xaa,0x9a,0x14},{0x98,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xa2,0x15},{0x99,0x6a,0xaa,0x95},{0xaa,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xa9,0x10,0x00,0x05}},{{0x5a,0xaa,0x12,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0xa9,0x10,0x00,0x05}},{{0x6a,0xaa,0x55,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0x9a,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x8a,0x55,0x55,0x55},{0xaa,0x00,0x00,0x01}},{{0x6a,0xaa,0x55,0x55},{0x9a,0x96,0xaa,0x41},{0x6a,0xaa,0xaa,0x55},{0x99,0x66,0xaa,0x95},{0x95,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x59,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0x99,0x65},{0xaa,0x00,0x00,0x01}},{{0xaa,0xaa,0x55,0x55},{0x96,0x56,0xa5,0x51},{0x6a,0x69,0x8a,0x55},{0x95,0x66,0xaa,0x95},{0x95,0x69,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x01}},{{0xaa,0xa8,0x55,0x55},{0x96,0x55,0x55,0x55},{0x6a,0x65,0x58,0x55},{0x95,0x66,0x59,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x01}},{{0xa9,0x45,0x55,0x45},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa5,0x55,0x55,0x41},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x5a,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x95,0x55,0x55,0x41},{0x56,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x45,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x56,0x59,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x2a},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x51},{0x59,0x55,0x55,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x56},{0x55,0x15,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x15},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x10,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x42},{0x6a,0x95,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x59},{0x15,0x55,0x55,0x82},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x55},{0x99,0x50,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0xaa,0x99,0x55,0x6a},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_6 = { .phases = 43, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_6_data[0] };
-const uint8_t epd_wp_ed047tc2_2_7_data[40][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x0a,0x08,0x80},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa0,0x80,0x00,0x00},{0x08,0x80,0x20,0x00},{0x00,0x12,0x22,0x00},{0x00,0x00,0x00,0x00},{0x1a,0x20,0x00,0x00},{0x01,0x80,0x00,0x00},{0x88,0x00,0x00,0x00},{0x00,0x10,0x80,0x00},{0x20,0x0a,0x88,0x82},{0x80,0x00,0x05,0x08},{0x0a,0xa0,0x00,0x20},{0x20,0x00,0x00,0x20},{0x00,0x80,0x00,0x08},{0x80,0x28,0x08,0x80},{0x2a,0x80,0xa0,0x28},{0x20,0x00,0x80,0x04}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x11,0x22,0xa2,0x00},{0x04,0x04,0x00,0x00},{0x2a,0xa0,0x20,0x00},{0x22,0xa0,0x00,0x00},{0x98,0x12,0x00,0x0a},{0x18,0xa0,0x80,0x00},{0x28,0x0a,0x8a,0x82},{0x88,0x88,0x09,0x28},{0x0a,0xa2,0x20,0x20},{0x20,0x00,0x02,0xa0},{0x00,0xa4,0x00,0x08},{0xa8,0xa8,0xa8,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x20,0x02,0x88,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x22,0x22,0xa2,0x28},{0x04,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x20,0x0a},{0x98,0x56,0x02,0x8a},{0xa8,0xa4,0x80,0x00},{0x28,0x0a,0xaa,0x82},{0x88,0xaa,0x0a,0x28},{0x2a,0xaa,0xa8,0x22},{0x20,0x40,0xa2,0xa2},{0x12,0xa8,0xa0,0x28},{0xa8,0xaa,0xaa,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x28,0x82,0xa8,0x85}},{{0xa8,0xa0,0x00,0x00},{0x08,0xa0,0x20,0x00},{0x26,0x22,0xa2,0x28},{0x05,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x28,0x0a},{0x99,0xaa,0x82,0x8a},{0xaa,0xa8,0xa2,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0x28},{0x2a,0xaa,0xa8,0xa2},{0x20,0xa6,0xa2,0xa2},{0x92,0xaa,0xa8,0x28},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x98},{0x58,0x8a,0xa8,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xa0,0x20,0x00},{0x2a,0x66,0xa2,0x28},{0x09,0x0a,0x00,0x00},{0x2a,0xa2,0x28,0x00},{0x2a,0xa0,0xa8,0x0a},{0xa9,0xaa,0x82,0x8a},{0xaa,0xaa,0xaa,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa2},{0x25,0xa6,0xaa,0xa2},{0xaa,0xaa,0xa8,0x2a},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x58,0x8a,0xaa,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0x20,0x80},{0x2a,0xa6,0xa2,0x28},{0x19,0x0a,0x00,0x00},{0x2a,0xa2,0xa8,0x00},{0x2a,0xaa,0xa8,0x89},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x02},{0x2a,0x8a,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x81},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa0,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0x2a,0xaa,0xa8,0x04},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x82},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa4},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0xaa,0xaa,0xa8,0x88},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x96},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x95},{0x5a,0xaa,0xa9,0x55}},{{0xa8,0xa0,0x00,0x14},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xaa,0x28},{0xaa,0x2a,0x00,0x00},{0xaa,0xaa,0xaa,0x99},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x5a,0xaa,0x69,0x55}},{{0xa8,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x16},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0xa9,0xa5,0x55,0x55},{0x9a,0xaa,0x65,0x51}},{{0x98,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x15},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x64,0x51}},{{0x98,0x50,0x00,0x28},{0x8a,0x6a,0x9a,0x41},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x18,0x80},{0xaa,0xaa,0x96,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xaa,0xa5,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x80,0x55},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x54,0x51}},{{0x94,0x50,0x00,0x28},{0xa6,0x55,0x55,0x61},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x28,0x80},{0xa9,0x9a,0x96,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0xa9,0x69,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xa5,0x65,0x55},{0xaa,0xa6,0x25,0x55},{0xaa,0x01,0x55,0x55},{0xaa,0xaa,0x59,0x55},{0xaa,0x55,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0xa5,0x54,0x41}},{{0x94,0xa0,0x00,0x28},{0xa5,0x55,0x55,0x51},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0xa1},{0xa5,0x59,0x55,0x55},{0xaa,0x5a,0x55,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0xa5,0x15,0x55},{0xa9,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x65,0x54,0x41}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x55,0x59},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0x95},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xaa,0xa5,0x65,0x55},{0xaa,0x55,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa8,0x65,0x54,0x41}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x55},{0x8a,0x99,0x59,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0xa5,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x92,0x25,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x95},{0x89,0x99,0x55,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x25,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0x50,0x80,0x15},{0xa5,0x95,0x65,0x95},{0x99,0x95,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x58,0x5a,0x80,0x15},{0xa9,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x98,0x5a,0x80,0x15},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x2a,0x95,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa6,0x54,0x14,0x00}},{{0x98,0x5a,0x48,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x25,0x95,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0x55,0x55,0x65},{0xa6,0x54,0x10,0x00}},{{0x9a,0x55,0x68,0x55},{0x6a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x25,0x55,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x25,0x55,0x55,0x66},{0x2a,0xaa,0xaa,0x6a},{0xa6,0x10,0x00,0x00}},{{0x9a,0x55,0x64,0x41},{0x5a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0xa6,0x10,0x08,0x00}},{{0x9a,0x55,0x94,0x81},{0x5a,0x6a,0x9a,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x0a,0x9a,0x81},{0xa6,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x0a,0xa9,0x41},{0xa5,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x15,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x44,0x85,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x0a,0x65,0x41},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x55,0x55,0x69},{0x55,0x55,0x55,0x69},{0x55,0x56,0x11,0x59},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x66},{0x65,0x44,0x42,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x51},{0x55,0xaa,0xaa,0x54},{0x45,0x55,0x55,0x56},{0x59,0x59,0x11,0x56},{0x55,0x55,0x14,0x52},{0x55,0x55,0x55,0x55},{0x55,0x51,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x61},{0x40,0x55,0x55,0x80},{0x6a,0xaa,0xaa,0xaa},{0x55,0x04,0x02,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x59,0x55,0x65,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x40,0x00,0x00,0x42},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x64,0x0a,0x9a,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x59},{0x65,0x55,0x55,0x55},{0x55,0x64,0x55,0x41},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x6a,0x2a,0x82,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x45},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x44},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x95,0x55,0x51,0x42},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x50,0x50,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_7 = { .phases = 40, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_7_data[0] };
-const uint8_t epd_wp_ed047tc2_2_8_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x80,0x08,0x82},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x08},{0x00,0x00,0x00,0x00},{0x02,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0x20,0x00,0x00,0x08},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x20},{0x80,0x00,0x00,0x00},{0xaa,0x08,0xaa,0x08},{0x00,0x00,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x20,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0xa0,0x00,0x00,0x0a},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x2a},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa8},{0x00,0x20,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x81},{0xa0,0x00,0x00,0x05},{0x20,0x00,0x00,0x01},{0x02,0x82,0x00,0xa9},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa4},{0x12,0x28,0xaa,0x01}},{{0xa8,0x00,0x0a,0x00},{0x88,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x82,0xa8,0x08,0x81},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x08},{0x00,0x02,0x0a,0x80},{0x88,0x00,0x02,0x81},{0xa0,0x00,0x00,0x25},{0x28,0x00,0x00,0x21},{0x22,0x82,0x00,0xa5},{0x80,0x00,0x00,0x21},{0xaa,0xaa,0xaa,0xa4},{0x19,0x2a,0xaa,0x81}},{{0xa8,0x00,0x0a,0x00},{0x8a,0xa8,0x8a,0x0a},{0x00,0x20,0x00,0x28},{0x80,0x00,0x00,0x00},{0x20,0x00,0x00,0x0a},{0x82,0xaa,0x08,0x81},{0x08,0x20,0x02,0x02},{0x08,0x00,0x00,0x08},{0x28,0x02,0x0a,0x80},{0x88,0x08,0x0a,0x81},{0xa0,0x00,0x08,0x25},{0x2a,0x00,0x0a,0x21},{0x22,0xa2,0x00,0x95},{0x80,0x02,0x00,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x19,0xaa,0xaa,0x81}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0x8a,0x0a},{0x02,0x20,0x00,0x28},{0x88,0x00,0x00,0x02},{0x20,0x00,0x00,0x09},{0xa2,0xaa,0xa8,0x85},{0x8a,0x28,0x0a,0x09},{0x88,0x00,0x00,0x08},{0x28,0x02,0x8a,0x80},{0x88,0x0a,0x0a,0x81},{0xa8,0x02,0x08,0x25},{0xaa,0xaa,0x0a,0x21},{0x2a,0xaa,0x2a,0x95},{0xa0,0x02,0x82,0x81},{0xaa,0xaa,0xaa,0x95},{0x19,0xaa,0xaa,0x81}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0xaa,0x09},{0x02,0x20,0x08,0x04},{0x88,0x00,0x00,0x21},{0x28,0x00,0x00,0x09},{0xaa,0xaa,0xa8,0x85},{0x8a,0xaa,0x0a,0x09},{0x88,0x08,0x00,0x04},{0xaa,0x82,0x8a,0x82},{0xaa,0xaa,0xaa,0x81},{0xa8,0x22,0xa8,0x15},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0x2a,0x95},{0xa0,0x22,0x82,0x91},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xaa,0x85}},{{0xa8,0x00,0x05,0x10},{0x8a,0xaa,0xaa,0x09},{0x22,0x20,0x28,0x14},{0x88,0x00,0x00,0x25},{0x28,0x00,0x00,0x05},{0xaa,0xaa,0xa8,0x45},{0xaa,0xaa,0xaa,0x05},{0x88,0x0a,0x00,0x85},{0xaa,0xa2,0x8a,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa2,0x2a,0x8a,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xa6,0x85}},{{0xa8,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x09},{0xaa,0x22,0xaa,0x15},{0x88,0x00,0x00,0x25},{0xa8,0x00,0x00,0x25},{0xaa,0xaa,0xa8,0x65},{0xaa,0xaa,0xaa,0x25},{0xa8,0x2a,0x80,0xa5},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa2,0xaa,0x8a,0x95},{0xa9,0xaa,0x66,0x55},{0x15,0x6a,0x56,0x45}},{{0x94,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x29},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x08,0x00,0x25},{0xaa,0xaa,0xa6,0x65},{0xaa,0xaa,0xaa,0x25},{0xaa,0x2a,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x45},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0x29,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xa9,0xa9,0x55,0x55},{0x25,0x6a,0x55,0x55}},{{0x94,0x00,0x0a,0x64},{0x8a,0xaa,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x0a,0x0a,0x15},{0xaa,0x6a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa9,0x69,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x99,0xa5,0x55,0x55},{0x21,0x15,0x55,0x55}},{{0x94,0x00,0x0a,0x64},{0xaa,0x9a,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x8a,0x00,0x00,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x5a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0x55},{0x9a,0xaa,0xa6,0x55},{0x9a,0xaa,0xa5,0x55},{0xa9,0x69,0xaa,0x55},{0xaa,0xa9,0x6a,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x55}},{{0x94,0x00,0x0a,0xa5},{0xaa,0x5a,0x65,0x15},{0xaa,0x22,0xaa,0x95},{0xaa,0xa0,0x08,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x55,0x56,0x55},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x9a,0xa9,0x56,0x55},{0x9a,0xa1,0x55,0x55},{0xa9,0x69,0x95,0x55},{0xaa,0xa9,0x69,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x55}},{{0x68,0x00,0x0a,0x95},{0xa6,0x55,0x55,0x15},{0xaa,0x12,0x8a,0x15},{0xaa,0xa0,0x28,0x15},{0xa8,0x2a,0x8a,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0xaa,0xa5,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0xa5,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0x91,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x9a,0xa9,0x65,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x55}},{{0x68,0x00,0x0a,0x55},{0xa6,0x55,0x9a,0x15},{0xaa,0x12,0x06,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x99,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x55}},{{0x68,0x00,0x05,0x55},{0xa5,0x55,0x9a,0x25},{0xa9,0x91,0x55,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x95},{0x59,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa5,0x6a,0x55},{0xaa,0xa9,0x65,0x55},{0xa4,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x55}},{{0x68,0x00,0x05,0x55},{0xa5,0x65,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xaa,0xaa,0xa8,0x95},{0x9a,0x25,0x65,0x95},{0x51,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xa6,0x85,0x65,0x55},{0x9a,0x29,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x55}},{{0x54,0x00,0x05,0x55},{0xa9,0xa5,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xa6,0xaa,0xaa,0x95},{0x96,0xa5,0x65,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x85,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x55,0x55,0x55},{0xaa,0x95,0x11,0x56}},{{0x94,0x00,0x05,0x55},{0x69,0xaa,0xaa,0x25},{0x95,0x99,0x55,0x55},{0xa6,0xaa,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x56},{0xa6,0x55,0x55,0x59},{0xaa,0x95,0x21,0x56}},{{0x94,0x00,0x85,0x51},{0x6a,0xaa,0xaa,0xa5},{0x95,0x99,0x55,0x55},{0x65,0x59,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x66},{0xaa,0x56,0x99,0x6a},{0xaa,0xaa,0xaa,0xaa}},{{0x94,0x22,0x85,0x51},{0x6a,0xaa,0x20,0x95},{0x55,0x59,0x55,0x55},{0x55,0x55,0x56,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x66,0x56,0x95,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x96,0x2a,0x65,0x01},{0xa2,0x8a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x96,0xa9,0x50,0x01},{0xa6,0x0a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x45,0x55,0x55,0x4a},{0x55,0x55,0x55,0x55},{0x66,0x96,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x42,0x95,0x90,0x01},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x52},{0x65,0x54,0x01,0x2a},{0x65,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x56,0xa0,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x64},{0x66,0x6a,0xa9,0x50},{0x55,0x55,0x55,0x64},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x45,0x50,0x00,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x6a,0x60,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x56},{0x55,0x5a,0x95,0x5a},{0x55,0x15,0x55,0x20},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0xa9,0x50,0x05},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x59,0x65,0x6a,0xa6},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x41,0x50,0x15,0x6a},{0x45,0x54,0x55,0x91},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x50,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x65,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x54,0x10,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x55,0x50,0x15},{0x55,0x55,0x55,0x55},{0x6a,0xa2,0xaa,0xa2},{0x52,0xa6,0x65,0x92},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xa2},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x84,0x50,0x05,0x0a},{0x40,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xa5,0x50,0x15,0x48},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x45},{0x00,0x00,0x00,0x00},{0x81,0x51,0x11,0x68},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x45,0x55,0x55,0x44},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_8 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_8_data[0] };
-const uint8_t epd_wp_ed047tc2_2_9_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x0a,0x82,0x02,0x00},{0x40,0x00,0x00,0x00},{0x00,0x80,0x02,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,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x0a,0x8a,0x82,0x00},{0x40,0x08,0x00,0x40},{0x00,0x80,0x22,0x08},{0x00,0x08,0x08,0x08},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x04,0x00,0x00},{0x11,0x40,0x20,0x00},{0x81,0x00,0x00,0x20},{0x28,0x08,0x00,0x82},{0x00,0x20,0x80,0x80},{0x00,0x00,0x02,0x80}},{{0x80,0x00,0x00,0x00},{0x6a,0x8a,0x8a,0x00},{0x90,0x08,0x01,0x40},{0x00,0x80,0x22,0x08},{0x00,0x28,0x88,0x0a},{0x80,0x08,0x00,0x00},{0x00,0x08,0x02,0x00},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x80,0x00},{0x14,0x14,0x00,0x00},{0x21,0x50,0x20,0x80},{0x81,0x18,0x00,0xa0},{0x29,0x0a,0x02,0x81},{0x2a,0xa2,0xaa,0xa0},{0x00,0x2a,0x02,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xa0,0x08,0x02,0x80},{0x80,0x88,0x22,0x08},{0x20,0xa8,0x89,0x0a},{0x80,0xa8,0x00,0x02},{0xaa,0x8a,0x0a,0x08},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x02},{0x08,0x08,0x80,0x00},{0x24,0x54,0x22,0x80},{0x25,0x52,0x2a,0xa0},{0x86,0xa8,0x20,0xa8},{0xaa,0x2a,0x82,0x81},{0x2a,0xaa,0xaa,0xa0},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xaa,0x8a,0x2a,0x80},{0x80,0x88,0x22,0x08},{0x22,0xaa,0x8a,0x0a},{0x82,0xa8,0x00,0x02},{0xaa,0xaa,0x0a,0x0a},{0x00,0x08,0x02,0x28},{0x00,0x00,0x00,0x02},{0x2a,0x8a,0x80,0x00},{0xa5,0xaa,0xa2,0xa0},{0x26,0x96,0xaa,0xa0},{0x8a,0xa8,0xa0,0xa8},{0xaa,0x2a,0x8a,0x81},{0x2a,0xaa,0xaa,0xa8},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x0a},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0x2a,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x00,0x02},{0x2a,0xaa,0x80,0x00},{0xa9,0xaa,0xa2,0xa0},{0x26,0xa6,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0x2a,0x8a,0x41},{0xaa,0xaa,0xaa,0xa8},{0x08,0xaa,0x12,0x41}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x29},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0xaa,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x08,0x80},{0x2a,0xaa,0x8a,0x22},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x12,0x41}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x02},{0xaa,0xaa,0xaa,0x09},{0x20,0x08,0x02,0x28},{0x00,0x02,0x0a,0xa0},{0x2a,0xaa,0x8a,0x2a},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x11,0x45}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x81,0x88,0xa2,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0x8a,0x02,0x28},{0x00,0x82,0xaa,0xa1},{0x2a,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0x91,0x45}},{{0x80,0x00,0x00,0x20},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0x80},{0x82,0x88,0xaa,0x24},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x82,0x04},{0x20,0xa2,0xaa,0xa1},{0x2a,0xaa,0xaa,0x29},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x55},{0x96,0xa5,0x65,0x55},{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0x91,0x45}},{{0x80,0x00,0x00,0x10},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x9a,0x14},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x21},{0xaa,0xaa,0xaa,0x85},{0x2a,0xaa,0x8a,0x15},{0x20,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0x25},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0xaa,0x55},{0x96,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x56},{0x2a,0x99,0x91,0x45}},{{0x80,0x00,0x00,0x94},{0xaa,0xa9,0x45,0x44},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x99,0x16},{0xaa,0xa6,0xa6,0x95},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa9,0xa5},{0xaa,0xaa,0xa9,0x95},{0x2a,0xaa,0xaa,0x69},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0x55,0x56},{0x1a,0x95,0x99,0x05}},{{0x80,0x00,0x00,0x64},{0xa9,0x65,0x45,0x48},{0xaa,0xaa,0xa9,0xa2},{0xa2,0x6a,0x99,0x15},{0xaa,0xa5,0x65,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa5,0xa5},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x59},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x99,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x99,0x55,0x55},{0x19,0x55,0x89,0x05}},{{0x40,0x00,0x00,0xa4},{0xa5,0x65,0x45,0x4a},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x6a,0x99,0x15},{0xa9,0x95,0x65,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa5,0x95,0xa5},{0xaa,0xa6,0xa9,0x95},{0xaa,0xaa,0xa6,0x55},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x59,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x99,0x55,0x55},{0x15,0x55,0x49,0x15}},{{0x40,0x00,0x00,0x54},{0xa5,0x65,0x45,0x88},{0xaa,0xaa,0xa9,0xa1},{0xaa,0x66,0x11,0x15},{0xa9,0x55,0x65,0x55},{0xaa,0x96,0xa9,0x95},{0xa5,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x15},{0xaa,0xaa,0x95,0x55},{0x26,0xa5,0x65,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x45,0x15}},{{0x40,0x00,0x00,0x55},{0xa5,0x55,0x46,0x89},{0xaa,0xa6,0xa5,0x61},{0xaa,0x66,0x51,0x15},{0x95,0x55,0x55,0x55},{0x28,0x56,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x55},{0xaa,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x15}},{{0xa0,0x00,0x00,0x55},{0x95,0x56,0x8a,0x99},{0xaa,0xaa,0x9a,0x51},{0xaa,0x66,0x55,0x95},{0x95,0x55,0x55,0x55},{0x29,0x55,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa5,0x45,0x55},{0xaa,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x16}},{{0xa0,0x00,0x00,0x55},{0x9a,0x9a,0x8a,0x65},{0xaa,0xa5,0x56,0x51},{0x6a,0x56,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x96},{0x95,0x55,0x55,0x55},{0x05,0x55,0x45,0x16}},{{0xa0,0x00,0x20,0x51},{0x5a,0xaa,0x8a,0x65},{0xa5,0x65,0x56,0x59},{0x69,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x85,0x55,0x45,0x12}},{{0x60,0x28,0xa0,0x51},{0x6a,0xaa,0x8a,0x65},{0x95,0x55,0x56,0x55},{0x59,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x84,0x55,0x44,0x12}},{{0x6a,0xaa,0xa8,0x11},{0x6a,0xaa,0x8a,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x45,0x44,0x12}},{{0x5a,0xaa,0x64,0x01},{0xa6,0x99,0x45,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x44,0x46,0x12}},{{0x5a,0x95,0x56,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x99,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x56,0x5a,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x95},{0x95,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x65,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x25,0x6a,0x99,0x01},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x65},{0x56,0x5a,0x56,0x56},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x65},{0x95,0x55,0x41,0x56},{0x95,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x5a,0x66,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0xaa,0x56,0x05},{0x55,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x95,0x61},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x45},{0x55,0x55,0x55,0x59},{0x55,0x55,0x54,0x55},{0x55,0x54,0x00,0x15},{0x91,0x55,0x15,0x42},{0x55,0x55,0x24,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0x95,0x56,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x65,0x49,0x91},{0x55,0x55,0x54,0x44},{0x55,0x55,0x55,0x49},{0x15,0x55,0x55,0x54},{0x55,0x51,0x54,0x0a},{0x55,0x04,0x00,0x2a},{0xaa,0xaa,0xaa,0xaa},{0x55,0x54,0x10,0x55},{0x65,0x56,0x9a,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xa2,0x1a,0x06,0x50},{0x68,0xa0,0xa8,0xaa},{0x55,0x45,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x04,0x00,0xaa},{0x55,0x55,0x65,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x51,0x05,0x01,0x02},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x6a,0xaa,0xa9,0xa4},{0x55,0x55,0x55,0x00},{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_9 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_9_data[0] };
-const uint8_t epd_wp_ed047tc2_2_10_data[44][16][4] = {{{0x00,0x00,0x00,0x00},{0x80,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x00,0x08,0x02},{0x00,0x80,0x00,0x08},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x02,0x00,0x00,0x00},{0xa2,0x88,0x20,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x80,0x20,0x00},{0x00,0x80,0x00,0x00},{0x00,0x82,0x00,0x00},{0xa8,0x00,0x08,0x82},{0x00,0x80,0x20,0x0a},{0x92,0x00,0x00,0x8a},{0x2a,0x20,0xa2,0xa8},{0x00,0x00,0x00,0x08}},{{0x02,0x00,0x00,0x00},{0xa2,0x8a,0x20,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x08,0x05,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x00,0x80,0x20,0x00},{0x02,0xa0,0xa0,0x00},{0x00,0x82,0x00,0x02},{0xaa,0x20,0x08,0x82},{0x84,0x80,0xa0,0x0a},{0xa2,0x84,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x08}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa0,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x15,0x42,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xa0,0x20,0x80},{0x02,0xaa,0xa8,0x00},{0x00,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x82},{0x9a,0x90,0xa8,0x0a},{0xa6,0xa8,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x00,0x80,0x2a}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x1a,0x46,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xaa,0x28,0x80},{0x2a,0xaa,0xa8,0x00},{0x02,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0x08,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x8a,0x88,0x26}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x90},{0x02,0xa0,0x08,0x02},{0x2a,0x2a,0x86,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x80},{0x2a,0xaa,0xa8,0x20},{0x02,0x82,0x00,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0x8a,0x8a,0xa6}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x0a},{0x80,0x00,0x00,0x90},{0x02,0xaa,0x2a,0x02},{0x2a,0xaa,0x8a,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xa2,0xa2,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0xaa,0x4a,0x55}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0x90},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa0},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x16,0xaa,0x46,0x55}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa4},{0x15,0x9a,0x65,0x55}},{{0x82,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0x80,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0x15,0x95,0x65,0x55}},{{0x81,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0xa2,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x8a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x02,0x82,0x20},{0x00,0x0a,0x00,0x09},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0xa8},{0xaa,0xaa,0x9a,0x2a},{0xa2,0xa2,0x02,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x82,0x82,0xa0},{0x00,0x8a,0x80,0x09},{0x2a,0xaa,0xaa,0x22},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0x21},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xa9,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0xa8},{0xaa,0x66,0x9a,0x2a},{0xa2,0xa2,0x22,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0x2a,0xa2,0xa0,0x80},{0x02,0x8a,0x80,0x05},{0x2a,0xaa,0x8a,0x20},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xa0,0x61},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0x94},{0xaa,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x82},{0x02,0x8a,0x82,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xa8,0xaa,0xa1},{0xaa,0xaa,0xa0,0x65},{0xaa,0xaa,0x20,0x85},{0xaa,0xaa,0xaa,0x65},{0xaa,0x95,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x41,0x00,0x40,0x94},{0x69,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xa2,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0x9a},{0xaa,0x28,0xaa,0xa9},{0xaa,0xaa,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x42,0x00,0x48,0xa4},{0x59,0x55,0x55,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xaa,0x25},{0x2a,0xaa,0xaa,0x9a},{0xa8,0x80,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x8a,0x29},{0x2a,0xaa,0x56,0x99},{0xaa,0x28,0xa8,0xa9},{0xaa,0x82,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x42,0x00,0x48,0x64},{0x59,0x59,0x65,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xa0,0x65},{0x2a,0xaa,0xa9,0x56},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0xa9,0x8a},{0xaa,0xaa,0xaa,0x05},{0xaa,0x2a,0x86,0x69},{0x2a,0x55,0x55,0x99},{0xaa,0x69,0x89,0xa9},{0x96,0x82,0x00,0x45},{0xaa,0x22,0x10,0x05},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x62,0x00,0x4a,0x54},{0x59,0x9a,0xa9,0x95},{0xaa,0xaa,0x22,0x65},{0x82,0xaa,0xa5,0x45},{0x26,0xaa,0xa9,0x55},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0x29,0x89},{0xaa,0xaa,0xaa,0x85},{0xaa,0x55,0x54,0x69},{0x21,0x55,0x55,0x55},{0xaa,0x69,0x45,0xa9},{0x95,0x55,0x55,0x55},{0xaa,0x22,0x10,0x05},{0x89,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0xa2,0x00,0x8a,0x54},{0x66,0xaa,0xaa,0x95},{0xaa,0xaa,0x22,0x55},{0x82,0x95,0x55,0x55},{0x16,0xa5,0x55,0x55},{0xa2,0xa0,0x20,0x09},{0xaa,0xa9,0x29,0x09},{0xaa,0xaa,0xaa,0x85},{0xa9,0x55,0x55,0x59},{0x11,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa1,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55}},{{0xa2,0x00,0x86,0x54},{0xa6,0xaa,0xaa,0xa5},{0xaa,0xaa,0x22,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x5a,0xa9,0x55},{0xa2,0xaa,0x28,0x01},{0xaa,0xa9,0x29,0x55},{0xaa,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x55,0x55,0x55}},{{0xa1,0x00,0x85,0x54},{0xaa,0xa2,0xaa,0x65},{0xaa,0xaa,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x15,0xa5,0x55,0x55},{0xa2,0xaa,0xa8,0x01},{0xaa,0xa9,0x69,0x55},{0xaa,0xa5,0x69,0xa5},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x45,0x55,0x55}},{{0xa1,0x00,0x85,0x54},{0x9a,0x95,0x55,0x55},{0xaa,0x99,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa2,0xa9,0x55,0x55},{0xaa,0xa5,0x69,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x85,0x55}},{{0x61,0x00,0x45,0x54},{0x95,0x55,0x55,0x55},{0xaa,0x99,0x61,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa5,0x55,0x55,0x55},{0xaa,0x65,0x55,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x89,0x95}},{{0x61,0x00,0x45,0x50},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0xaa,0x8a,0xa9}},{{0x61,0x00,0x45,0x10},{0x15,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xa9}},{{0x51,0x20,0x41,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x16,0x6a,0x94,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x50,0x2a,0x40,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x2a,0x00,0x01},{0x55,0x55,0x55,0x55},{0x51,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0xaa}},{{0x28,0xa9,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x28,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x24,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x99},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x99},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x9a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x14,0x6a,0x20,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x65},{0x55,0x14,0x54,0x56},{0x41,0x55,0x55,0x56},{0x55,0x55,0x55,0x5a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x14,0x6a,0x10,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x11},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x15},{0x6a,0xaa,0xaa,0x99},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x96,0x10,0x05},{0x55,0x55,0x55,0x19},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x21},{0xa9,0x55,0x56,0xa5},{0x55,0x55,0x55,0x55},{0x66,0xa9,0x69,0x54},{0x55,0x50,0x14,0x1a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x95,0x10,0x45},{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x65},{0x6a,0x6a,0x9a,0x11},{0x95,0x55,0x55,0x55},{0x69,0x55,0x55,0x59},{0x51,0x56,0x16,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x55,0x10,0x55},{0x00,0x00,0x00,0x00},{0x55,0x65,0x56,0x54},{0x55,0x15,0x45,0x02},{0x80,0x00,0x00,0x0a},{0x55,0x55,0x55,0x16},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x15,0x55,0x15,0x55},{0x00,0x00,0x00,0x00},{0x59,0x55,0x55,0x14},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x65,0x45,0x54,0x0a},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_10 = { .phases = 44, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_10_data[0] };
-const uint8_t epd_wp_ed047tc2_2_11_data[57][16][4] = {{{0x20,0x8a,0x80,0x00},{0x15,0x55,0x5a,0xa4},{0x44,0x10,0x0a,0x41},{0x40,0x00,0x09,0x54},{0x10,0x50,0x00,0x00},{0x00,0x00,0x04,0x28},{0x40,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x40,0x00},{0x00,0x00,0x00,0x00},{0x00,0x40,0x00,0x68},{0x00,0x00,0x40,0x00},{0x00,0x00,0x0a,0x54},{0x00,0x0a,0x80,0x00},{0x10,0x09,0x60,0x00},{0x00,0x00,0x00,0x50}},{{0xaa,0xaa,0x8a,0x00},{0x0a,0x60,0x0a,0xa8},{0x54,0x54,0x8a,0x41},{0x41,0x02,0x09,0x54},{0x15,0x50,0x06,0x24},{0x00,0x08,0xa4,0x28},{0x44,0x00,0x09,0xa8},{0x05,0x00,0x2a,0xa8},{0x01,0x10,0x46,0xa8},{0x04,0x00,0x00,0xa8},{0x00,0x40,0x00,0x54},{0x04,0x00,0x44,0xa8},{0x00,0x00,0x8a,0x54},{0x00,0x0a,0x8a,0x58},{0x50,0x19,0x65,0x54},{0x00,0x00,0x00,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x6a,0xaa,0xa8},{0x55,0x94,0x89,0x55},{0x41,0x02,0x09,0x54},{0x15,0x50,0x66,0x24},{0x40,0x04,0xa4,0x68},{0x44,0x0a,0x09,0x54},{0x05,0x08,0x55,0x54},{0x11,0x14,0x56,0x54},{0x04,0x40,0x00,0x58},{0x01,0x40,0x0a,0x54},{0x04,0x0a,0x44,0xa8},{0x01,0x00,0x8a,0x54},{0x00,0x0a,0x6a,0x54},{0x50,0x19,0x65,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x2a,0xaa,0xa8},{0x96,0x95,0x55,0x55},{0x51,0x0a,0x05,0x54},{0x15,0x50,0x66,0xa4},{0x40,0x04,0x54,0x54},{0x44,0x05,0x09,0x54},{0x05,0x18,0x55,0x54},{0x51,0x14,0x56,0x54},{0x04,0x40,0x02,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x58},{0x01,0x0a,0x85,0x54},{0x01,0x05,0x65,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x96,0xa5,0x55,0x55},{0x51,0x09,0x05,0x55},{0x15,0x50,0x65,0x94},{0x44,0x14,0x54,0x54},{0x54,0x15,0x95,0x54},{0x05,0x56,0x55,0x54},{0x51,0x14,0x55,0x54},{0x14,0x40,0x82,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x54},{0x01,0x0a,0x45,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x49,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x14,0x55,0x55},{0x14,0x40,0x8a,0x54},{0x01,0x40,0x85,0x54},{0x04,0x15,0x44,0x54},{0x01,0x0a,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x55,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0xa9,0x54},{0x01,0x40,0x45,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0x69,0x55},{0x01,0x40,0x65,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x55,0x54},{0x01,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x52,0x55,0x54},{0x54,0x14,0x56,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x65,0x55},{0x01,0x50,0x65,0x55},{0x04,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x92,0x55,0x55},{0x55,0x14,0x56,0x54},{0x54,0x55,0x55,0x55},{0x45,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x91,0x55,0x15,0x55},{0x16,0x92,0x55,0x55},{0x55,0x14,0x56,0x55},{0x54,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0x92,0x55,0x95,0x55},{0x6a,0x91,0x55,0x55},{0x55,0x54,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x05,0x15,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0x91,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x4a,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x4a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0xa1,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa9,0x15,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0xa5,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x95,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0x99,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0x56,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x55,0x55,0x55},{0x15,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x05,0x55,0x55},{0xa9,0x66,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x55},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0xa9,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x15,0x45,0x55,0x55},{0x11,0x55,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x15,0x55,0x55},{0xa9,0x66,0x95,0x55},{0x00,0x10,0x55,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x96},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x55,0x55,0x55},{0x5a,0x95,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x19,0x45,0x55,0x55},{0x11,0x95,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x66,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x9a,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x96},{0xaa,0xa6,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x5a,0xa5,0x55,0x55},{0xaa,0x65,0x55,0x55},{0x29,0x85,0x55,0x55},{0x12,0x95,0x55,0x55},{0x59,0x55,0x56,0x55},{0x56,0x15,0x55,0x55},{0xa6,0x15,0x55,0x55},{0xaa,0x6a,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x95,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x9a,0xa5,0x55,0x55},{0xaa,0x69,0x95,0x55},{0x2a,0x85,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x55,0x95,0x55},{0x56,0x15,0x55,0x55},{0xaa,0x1a,0x95,0x55},{0xaa,0x6a,0xaa,0xa9},{0x00,0x15,0x55,0x54}},{{0x55,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0xa9},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0xa9,0x55},{0xa9,0xaa,0x56,0x55},{0xaa,0xa5,0x95,0x55},{0xaa,0x69,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x1a,0xaa,0xa5},{0xaa,0xaa,0xaa,0xa9},{0x20,0x95,0x55,0x54}},{{0x55,0x55,0x8a,0x00},{0xaa,0xaa,0xa5,0x5a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0x99,0x59},{0xaa,0xa8,0xa9,0x55},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0x6a,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0xa6,0x15,0x55,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x5a,0x8a,0x00},{0xaa,0xaa,0x55,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0x9a,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x6a,0x8a,0x00},{0xaa,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xa9,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0xa5,0x55,0x95},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0xaa,0x8a,0x00},{0xa9,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x95,0x55,0x55},{0x66,0xa5,0x55,0xa9},{0xaa,0xaa,0x99,0x55},{0xaa,0x2a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x12,0x45,0x55,0x54}},{{0x6a,0xaa,0x8a,0x00},{0xa5,0x55,0xa5,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0x95,0x55,0xa5},{0xa6,0xa5,0x9a,0xa9},{0xaa,0xaa,0x99,0xa5},{0xaa,0x2a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x41,0x55,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x95,0x6a,0xa5,0x56},{0xaa,0x69,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0x96,0xa9},{0xa6,0xa5,0xaa,0xaa},{0xaa,0xaa,0x99,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x85,0x00},{0x55,0x6a,0xa5,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xa9,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0xaa,0xaa},{0xaa,0xa5,0xaa,0xaa},{0xaa,0xaa,0xa9,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x45,0x00},{0x5a,0x6a,0x55,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x99,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x40,0x02,0xa0}},{{0xaa,0xa5,0x45,0x00},{0x6a,0x55,0x55,0x56},{0x69,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x40,0x02,0xa8}},{{0xaa,0x55,0x45,0x00},{0x6a,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0xa5,0x55,0x45,0x00},{0x66,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x55,0x95,0x55,0x55},{0x55,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x5a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x99,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x55,0x69},{0x69,0x6a,0xaa,0xaa},{0xaa,0x5a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0xa9,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x5a,0xa9,0xaa},{0xa5,0x6a,0xaa,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x0a,0xa9}},{{0x55,0x55,0x40,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0xa9,0xaa},{0x95,0x6a,0x66,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa9}},{{0x55,0x50,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x99,0xaa},{0x55,0x46,0x66,0xaa},{0xa8,0x6a,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa9}},{{0x50,0x00,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x95,0x56},{0x55,0x45,0x55,0xa6},{0x65,0x96,0x96,0xaa},{0x26,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x08,0x28,0xaa,0xa9}},{{0x00,0x00,0x00,0x60},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x55,0xa6},{0x55,0x96,0x66,0xaa},{0x2a,0x4a,0xaa,0xaa},{0xaa,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x88,0x2a,0xaa,0xa8}},{{0x00,0x00,0x20,0x50},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x66,0x6a},{0x12,0x86,0xaa,0xaa},{0x85,0x4a,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0xa8,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x61,0x09,0x55,0x55},{0x45,0x55,0x55,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x98,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x99,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x56,0xaa},{0x94,0x6a,0xaa,0xaa},{0x56,0x65,0x55,0x55},{0xa6,0x55,0x66,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x00,0x00,0x25,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x95,0x55,0x55},{0xa9,0x8a,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x00,0x05,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xa4,0x6a,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x05,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x01,0x50,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_2_11 = { .phases = 57, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_2_11_data[0] };
-const EpdWaveformPhases* epd_wm_ed047tc2_2_ranges[7] = { &epd_wp_ed047tc2_2_5,&epd_wp_ed047tc2_2_6,&epd_wp_ed047tc2_2_7,&epd_wp_ed047tc2_2_8,&epd_wp_ed047tc2_2_9,&epd_wp_ed047tc2_2_10,&epd_wp_ed047tc2_2_11 };
+const uint8_t epd_wp_ED047TC2_2_5_data[46][16][4] = {{{0x00,0x00,0x00,0x00},{0x20,0x88,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x80,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x08,0x00},{0x00,0x02,0x00,0x80},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa2,0x88,0x20,0x88},{0x22,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x00,0x44,0x08,0x00},{0xa0,0x02,0x20,0xa8},{0x08,0x62,0x88,0x80},{0x00,0x00,0x00,0x08},{0x08,0x22,0x88,0x80},{0x00,0x80,0x00,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x24,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x80,0x82,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x84,0x84,0x28,0x80},{0xa0,0x02,0x20,0xaa},{0xa8,0xaa,0x8a,0x80},{0x22,0x84,0x00,0x28},{0x2a,0xaa,0xaa,0xa0},{0x00,0x80,0x28,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x08,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x00,0x20,0x02},{0x00,0x00,0x00,0x02},{0x84,0x88,0x2a,0xa2},{0xa0,0xaa,0xa8,0xa8},{0xa8,0xaa,0x8a,0x80},{0x2a,0xaa,0x08,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x08}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0x24,0x80,0x00},{0x00,0x00,0x00,0x00},{0x29,0x80,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x02,0xa0,0x00},{0x02,0x00,0x00,0x81},{0x88,0xa8,0xaa,0xa9},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0x8a,0x81},{0x2a,0xaa,0x2a,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x04}},{{0xaa,0xaa,0xa8,0xa4},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0xa8,0x80,0x00},{0x00,0x20,0x00,0x00},{0x2a,0x84,0xa0,0x08},{0x2a,0x68,0x20,0x80},{0x80,0xa2,0xa2,0xa8},{0x80,0x02,0xa0,0x01},{0x02,0x80,0x00,0xa9},{0x9a,0xa8,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x89},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x8a,0x28,0x04}},{{0xaa,0xaa,0xa8,0x64},{0x2a,0xaa,0xaa,0x01},{0x00,0x88,0x02,0x00},{0x29,0xa8,0x80,0x00},{0x00,0x28,0x08,0x02},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xa2,0xa2,0xa9},{0x80,0x02,0xa0,0x01},{0x02,0xa0,0x00,0xa9},{0x9a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0x8a,0xa8,0x84}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x00,0x8a,0x02,0x08},{0x2a,0xa8,0x88,0x00},{0x00,0x28,0x8a,0x01},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xaa,0xaa,0xa9},{0x80,0x02,0xa0,0x01},{0x0a,0xaa,0x80,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x8a,0xaa,0x56}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x20,0x8a,0x0a,0x08},{0x2a,0xa8,0xaa,0x00},{0x00,0x2a,0x8a,0x01},{0x2a,0xaa,0xa8,0x08},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x80,0x02,0xa0,0x81},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x59},{0x69,0x8a,0xaa,0x56}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa0,0x8a,0x0a,0x0a},{0xaa,0xaa,0xaa,0x02},{0x08,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x09},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x82,0x82,0xa0,0xa1},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0x59,0x8a,0xaa,0x55}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa2,0x8a,0x2a,0x09},{0xaa,0xaa,0xaa,0x09},{0x28,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x89},{0x2a,0xaa,0xa8,0xa1},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0xa0,0xa9},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x55}},{{0xaa,0xaa,0xaa,0x58},{0x2a,0xaa,0xa5,0x05},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x01},{0x2a,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x01},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x55}},{{0xaa,0xaa,0x96,0xa8},{0xaa,0xaa,0x55,0x09},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x98,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa4,0x55},{0xaa,0xa8,0x8a,0x55},{0xaa,0xaa,0xa5,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x54,0xaa,0xaa,0x55}},{{0xaa,0xa5,0x96,0xa8},{0xaa,0xa5,0x55,0xa9},{0xaa,0xaa,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x90,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0xaa,0x55},{0xa6,0x99,0x55,0x55},{0x94,0xaa,0xa6,0x51}},{{0xaa,0xa5,0x56,0xa8},{0xaa,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x15,0x55},{0x92,0x95,0x65,0x55},{0xaa,0xaa,0xa5,0x55},{0x95,0x95,0x55,0x55},{0x94,0xaa,0x96,0x01}},{{0xa9,0x55,0x56,0xa8},{0xa9,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa5},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x9a,0x85,0x55,0x55},{0x94,0x95,0x55,0x55},{0x99,0xa9,0x95,0x55},{0x95,0x55,0x55,0x55},{0x94,0xaa,0x96,0x01}},{{0x95,0x55,0x56,0xa8},{0xa5,0x55,0x5a,0xa5},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0xa5},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0x96,0x65},{0xaa,0xaa,0x1a,0x59},{0xaa,0x59,0x51,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xa8,0x55,0x55,0x55},{0x98,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x94,0x6a,0x96,0x01}},{{0x95,0x55,0x55,0x94},{0x95,0x55,0xaa,0x95},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0x95},{0x2a,0xaa,0xa5,0x55},{0x9a,0x6a,0x55,0x55},{0xaa,0x85,0x5a,0x55},{0xaa,0x59,0x55,0x55},{0xaa,0xa9,0x5a,0x55},{0xa8,0xaa,0x00,0x55},{0xa8,0x55,0x55,0x55},{0x91,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x90,0x69,0x95,0x01}},{{0x55,0x55,0x55,0x54},{0x96,0x5a,0xaa,0x15},{0xaa,0xa6,0xa9,0x05},{0xaa,0x9a,0x65,0x55},{0x2a,0x96,0x65,0x55},{0x96,0x65,0x55,0x55},{0xa1,0x95,0x56,0x55},{0x28,0x55,0x55,0x55},{0xaa,0xa9,0x52,0x55},{0xa9,0x01,0x05,0x55},{0x25,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x55,0x55,0x69,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa6,0xa5,0x85},{0x9a,0x56,0x55,0x55},{0xaa,0x95,0x65,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0xa1,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x55,0x5a,0xa9,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa5,0xa5,0x85},{0x92,0x55,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x15,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x01}},{{0x56,0xaa,0xa9,0x55},{0x99,0xaa,0xa1,0x55},{0xaa,0x65,0x95,0x45},{0x95,0x55,0x55,0x55},{0xa6,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x54,0x55},{0x55,0x55,0x55,0x55},{0x05,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x01}},{{0x6a,0xaa,0xaa,0x55},{0x95,0xaa,0x15,0x55},{0x9a,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0xa5,0x55,0x55},{0x99,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x15,0x65,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x55,0x01}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x41,0x01}},{{0xaa,0xaa,0x56,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x56},{0x55,0x55,0x55,0x55},{0x69,0x55,0x55,0x55},{0xaa,0x55,0x41,0x01}},{{0xa9,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x55,0x55,0x96},{0x65,0x55,0x55,0x56},{0x6a,0x65,0x55,0xa6},{0xaa,0x94,0x49,0x02}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x6a,0x2a,0x8a,0xaa},{0x6a,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x51,0x56},{0x65,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x40,0xaa},{0x55,0x54,0x45,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x56,0xa6,0x50},{0x55,0x56,0x95,0x56},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x95,0x55,0x55},{0x55,0x55,0x95,0x04},{0x45,0x05,0x55,0xaa},{0x55,0x55,0x55,0xaa},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x45,0x48,0x58,0x50},{0x55,0x55,0x41,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x54,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x54},{0x41,0x04,0x44,0x12},{0x6a,0x2a,0x21,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x69},{0x55,0x55,0x55,0x54},{0x45,0x05,0x15,0x16},{0x41,0x41,0x15,0x02},{0x6a,0x00,0xa0,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x66},{0x55,0x59,0x59,0xa6},{0x60,0x00,0x00,0x0a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x6a,0x59,0x51,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x50,0x55,0x55,0x52},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x6a,0x55,0x55,0x02},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xa5,0x96,0xa6,0x5a},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_5 = { .phases = 46, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_5_data[0] };
+const uint8_t epd_wp_ED047TC2_2_6_data[43][16][4] = {{{0x02,0xaa,0x00,0x00},{0x20,0x22,0xa8,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x22,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xa8,0x20},{0x00,0x00,0x00,0x00},{0x20,0x02,0x08,0x80},{0x00,0x80,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x2a,0xaa,0x00,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x28},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xaa,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x20},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa0,0x20,0x2a},{0x28,0x22,0xa8,0xa8},{0x28,0x00,0x00,0x00}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa8,0x22,0x2a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x80}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0xa2,0x82,0x08,0x80},{0x08,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x42}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x20,0x00,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0xa8},{0x00,0x00,0x00,0x00},{0xaa,0x82,0x88,0xa0},{0x8a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0x94},{0x24,0x00,0x28,0x42}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x20,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0x8a,0x8a,0xa0},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x24,0x00,0x28,0x42}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x22,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0xa0,0xa0,0xa8,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa5},{0xa6,0xaa,0xaa,0x95},{0x24,0x00,0x26,0x41}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x42},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xa2,0xa8,0xaa,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xa8},{0x08,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa6,0x55},{0x56,0x02,0x95,0x55}},{{0xaa,0xaa,0xa0,0x04},{0x20,0xaa,0xa5,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x26},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0x98},{0x88,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xa5,0xa9,0x65,0x55},{0x56,0x0a,0x95,0x55}},{{0xaa,0xa9,0xa0,0x24},{0x20,0xa9,0x55,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x25},{0x2a,0x80,0x00,0x02},{0x20,0xa0,0x28,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x80},{0xa0,0x00,0x00,0x01},{0x20,0xa2,0xa8,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xa2,0xa8,0xaa},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xa5,0x95,0x55,0x55},{0x56,0x0a,0x95,0x55}},{{0xaa,0x95,0xa8,0xa4},{0x20,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x29},{0xa2,0x88,0x00,0x15},{0x2a,0x80,0x00,0x01},{0x20,0xa8,0x28,0x14},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x81},{0xa0,0x00,0x00,0x01},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x56,0x89,0x55,0x55}},{{0xaa,0x95,0x98,0x94},{0xa0,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x25},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0x20,0xaa,0xa8,0x94},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0xa1},{0xa0,0x22,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x94},{0xa8,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0xa9,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x15}},{{0xa9,0x55,0x9a,0x98},{0xa8,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0xa2,0xaa,0xaa,0x94},{0xaa,0xaa,0xaa,0x89},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x2a,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x56},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0x95,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x15}},{{0xa5,0x55,0x5a,0xa8},{0xa8,0x95,0x55,0x45},{0xa0,0x82,0x20,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x85,0x69},{0xaa,0x2a,0xa8,0x29},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xa9,0xa9,0xa5,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0xa5,0x41,0x15}},{{0x95,0x55,0x6a,0x68},{0xa8,0x55,0x55,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xa9,0x55,0x69},{0xaa,0x2a,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0x99,0xa9,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x65,0x40,0x15}},{{0x95,0x55,0x66,0x58},{0xa8,0x55,0x5a,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0xa8,0xa0,0x15},{0xaa,0x62,0xa8,0x19},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x95},{0xaa,0x95,0x55,0x55},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa9,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x65,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x91,0x55,0x40,0x15}},{{0x95,0x56,0xa5,0x94},{0xa8,0x56,0xaa,0x85},{0xa8,0xaa,0xa0,0x95},{0xaa,0xa8,0xa0,0x15},{0xaa,0x6a,0xaa,0x15},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x55,0x55},{0x89,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0x99,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x50,0x00,0x15}},{{0x55,0x6a,0x89,0x94},{0x98,0x6a,0xaa,0x85},{0xaa,0xaa,0xa0,0x95},{0xaa,0xa6,0xa0,0x15},{0x8a,0x6a,0xaa,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xaa,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x89,0x50,0x00,0x15}},{{0x56,0xaa,0x9a,0x14},{0x98,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xa2,0x15},{0x99,0x6a,0xaa,0x95},{0xaa,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xa9,0x10,0x00,0x05}},{{0x5a,0xaa,0x12,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0xa9,0x10,0x00,0x05}},{{0x6a,0xaa,0x55,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0x9a,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x8a,0x55,0x55,0x55},{0xaa,0x00,0x00,0x01}},{{0x6a,0xaa,0x55,0x55},{0x9a,0x96,0xaa,0x41},{0x6a,0xaa,0xaa,0x55},{0x99,0x66,0xaa,0x95},{0x95,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x59,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0x99,0x65},{0xaa,0x00,0x00,0x01}},{{0xaa,0xaa,0x55,0x55},{0x96,0x56,0xa5,0x51},{0x6a,0x69,0x8a,0x55},{0x95,0x66,0xaa,0x95},{0x95,0x69,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x01}},{{0xaa,0xa8,0x55,0x55},{0x96,0x55,0x55,0x55},{0x6a,0x65,0x58,0x55},{0x95,0x66,0x59,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x01}},{{0xa9,0x45,0x55,0x45},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa5,0x55,0x55,0x41},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x5a,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x95,0x55,0x55,0x41},{0x56,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x45,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x56,0x59,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x2a},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x51},{0x59,0x55,0x55,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x56},{0x55,0x15,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x00,0x15},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x10,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x42},{0x6a,0x95,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x59},{0x15,0x55,0x55,0x82},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x55},{0x99,0x50,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0xaa,0x99,0x55,0x6a},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_6 = { .phases = 43, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_6_data[0] };
+const uint8_t epd_wp_ED047TC2_2_7_data[40][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x0a,0x08,0x80},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa0,0x80,0x00,0x00},{0x08,0x80,0x20,0x00},{0x00,0x12,0x22,0x00},{0x00,0x00,0x00,0x00},{0x1a,0x20,0x00,0x00},{0x01,0x80,0x00,0x00},{0x88,0x00,0x00,0x00},{0x00,0x10,0x80,0x00},{0x20,0x0a,0x88,0x82},{0x80,0x00,0x05,0x08},{0x0a,0xa0,0x00,0x20},{0x20,0x00,0x00,0x20},{0x00,0x80,0x00,0x08},{0x80,0x28,0x08,0x80},{0x2a,0x80,0xa0,0x28},{0x20,0x00,0x80,0x04}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x11,0x22,0xa2,0x00},{0x04,0x04,0x00,0x00},{0x2a,0xa0,0x20,0x00},{0x22,0xa0,0x00,0x00},{0x98,0x12,0x00,0x0a},{0x18,0xa0,0x80,0x00},{0x28,0x0a,0x8a,0x82},{0x88,0x88,0x09,0x28},{0x0a,0xa2,0x20,0x20},{0x20,0x00,0x02,0xa0},{0x00,0xa4,0x00,0x08},{0xa8,0xa8,0xa8,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x20,0x02,0x88,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x22,0x22,0xa2,0x28},{0x04,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x20,0x0a},{0x98,0x56,0x02,0x8a},{0xa8,0xa4,0x80,0x00},{0x28,0x0a,0xaa,0x82},{0x88,0xaa,0x0a,0x28},{0x2a,0xaa,0xa8,0x22},{0x20,0x40,0xa2,0xa2},{0x12,0xa8,0xa0,0x28},{0xa8,0xaa,0xaa,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x28,0x82,0xa8,0x85}},{{0xa8,0xa0,0x00,0x00},{0x08,0xa0,0x20,0x00},{0x26,0x22,0xa2,0x28},{0x05,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x28,0x0a},{0x99,0xaa,0x82,0x8a},{0xaa,0xa8,0xa2,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0x28},{0x2a,0xaa,0xa8,0xa2},{0x20,0xa6,0xa2,0xa2},{0x92,0xaa,0xa8,0x28},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x98},{0x58,0x8a,0xa8,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xa0,0x20,0x00},{0x2a,0x66,0xa2,0x28},{0x09,0x0a,0x00,0x00},{0x2a,0xa2,0x28,0x00},{0x2a,0xa0,0xa8,0x0a},{0xa9,0xaa,0x82,0x8a},{0xaa,0xaa,0xaa,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa2},{0x25,0xa6,0xaa,0xa2},{0xaa,0xaa,0xa8,0x2a},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x58,0x8a,0xaa,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0x20,0x80},{0x2a,0xa6,0xa2,0x28},{0x19,0x0a,0x00,0x00},{0x2a,0xa2,0xa8,0x00},{0x2a,0xaa,0xa8,0x89},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x02},{0x2a,0x8a,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x81},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa0,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0x2a,0xaa,0xa8,0x04},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x82},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa4},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x95}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0xaa,0xaa,0xa8,0x88},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x96},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x95},{0x5a,0xaa,0xa9,0x55}},{{0xa8,0xa0,0x00,0x14},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xaa,0x28},{0xaa,0x2a,0x00,0x00},{0xaa,0xaa,0xaa,0x99},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x5a,0xaa,0x69,0x55}},{{0xa8,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x16},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0xa9,0xa5,0x55,0x55},{0x9a,0xaa,0x65,0x51}},{{0x98,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x15},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x64,0x51}},{{0x98,0x50,0x00,0x28},{0x8a,0x6a,0x9a,0x41},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x18,0x80},{0xaa,0xaa,0x96,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xaa,0xa5,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x80,0x55},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x54,0x51}},{{0x94,0x50,0x00,0x28},{0xa6,0x55,0x55,0x61},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x28,0x80},{0xa9,0x9a,0x96,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0xa9,0x69,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xa5,0x65,0x55},{0xaa,0xa6,0x25,0x55},{0xaa,0x01,0x55,0x55},{0xaa,0xaa,0x59,0x55},{0xaa,0x55,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0xa5,0x54,0x41}},{{0x94,0xa0,0x00,0x28},{0xa5,0x55,0x55,0x51},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0xa1},{0xa5,0x59,0x55,0x55},{0xaa,0x5a,0x55,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0xa5,0x15,0x55},{0xa9,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x65,0x54,0x41}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x55,0x59},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0x95},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xaa,0xa5,0x65,0x55},{0xaa,0x55,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa8,0x65,0x54,0x41}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x55},{0x8a,0x99,0x59,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0xa5,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x92,0x25,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x95},{0x89,0x99,0x55,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x25,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0x50,0x80,0x15},{0xa5,0x95,0x65,0x95},{0x99,0x95,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x58,0x5a,0x80,0x15},{0xa9,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x98,0x5a,0x80,0x15},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x2a,0x95,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa6,0x54,0x14,0x00}},{{0x98,0x5a,0x48,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x25,0x95,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0x55,0x55,0x65},{0xa6,0x54,0x10,0x00}},{{0x9a,0x55,0x68,0x55},{0x6a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x25,0x55,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x25,0x55,0x55,0x66},{0x2a,0xaa,0xaa,0x6a},{0xa6,0x10,0x00,0x00}},{{0x9a,0x55,0x64,0x41},{0x5a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0xa6,0x10,0x08,0x00}},{{0x9a,0x55,0x94,0x81},{0x5a,0x6a,0x9a,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x0a,0x9a,0x81},{0xa6,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x0a,0xa9,0x41},{0xa5,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x15,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x44,0x85,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x0a,0x65,0x41},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x55,0x55,0x69},{0x55,0x55,0x55,0x69},{0x55,0x56,0x11,0x59},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x66},{0x65,0x44,0x42,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x51},{0x55,0xaa,0xaa,0x54},{0x45,0x55,0x55,0x56},{0x59,0x59,0x11,0x56},{0x55,0x55,0x14,0x52},{0x55,0x55,0x55,0x55},{0x55,0x51,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x61},{0x40,0x55,0x55,0x80},{0x6a,0xaa,0xaa,0xaa},{0x55,0x04,0x02,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x59,0x55,0x65,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x40,0x00,0x00,0x42},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x64,0x0a,0x9a,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x59},{0x65,0x55,0x55,0x55},{0x55,0x64,0x55,0x41},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x6a,0x2a,0x82,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x45},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x44},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x95,0x55,0x51,0x42},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x50,0x50,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_7 = { .phases = 40, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_7_data[0] };
+const uint8_t epd_wp_ED047TC2_2_8_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x80,0x08,0x82},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x08},{0x00,0x00,0x00,0x00},{0x02,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0x20,0x00,0x00,0x08},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x20},{0x80,0x00,0x00,0x00},{0xaa,0x08,0xaa,0x08},{0x00,0x00,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x20,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0xa0,0x00,0x00,0x0a},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x2a},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa8},{0x00,0x20,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x81},{0xa0,0x00,0x00,0x05},{0x20,0x00,0x00,0x01},{0x02,0x82,0x00,0xa9},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa4},{0x12,0x28,0xaa,0x01}},{{0xa8,0x00,0x0a,0x00},{0x88,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x82,0xa8,0x08,0x81},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x08},{0x00,0x02,0x0a,0x80},{0x88,0x00,0x02,0x81},{0xa0,0x00,0x00,0x25},{0x28,0x00,0x00,0x21},{0x22,0x82,0x00,0xa5},{0x80,0x00,0x00,0x21},{0xaa,0xaa,0xaa,0xa4},{0x19,0x2a,0xaa,0x81}},{{0xa8,0x00,0x0a,0x00},{0x8a,0xa8,0x8a,0x0a},{0x00,0x20,0x00,0x28},{0x80,0x00,0x00,0x00},{0x20,0x00,0x00,0x0a},{0x82,0xaa,0x08,0x81},{0x08,0x20,0x02,0x02},{0x08,0x00,0x00,0x08},{0x28,0x02,0x0a,0x80},{0x88,0x08,0x0a,0x81},{0xa0,0x00,0x08,0x25},{0x2a,0x00,0x0a,0x21},{0x22,0xa2,0x00,0x95},{0x80,0x02,0x00,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x19,0xaa,0xaa,0x81}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0x8a,0x0a},{0x02,0x20,0x00,0x28},{0x88,0x00,0x00,0x02},{0x20,0x00,0x00,0x09},{0xa2,0xaa,0xa8,0x85},{0x8a,0x28,0x0a,0x09},{0x88,0x00,0x00,0x08},{0x28,0x02,0x8a,0x80},{0x88,0x0a,0x0a,0x81},{0xa8,0x02,0x08,0x25},{0xaa,0xaa,0x0a,0x21},{0x2a,0xaa,0x2a,0x95},{0xa0,0x02,0x82,0x81},{0xaa,0xaa,0xaa,0x95},{0x19,0xaa,0xaa,0x81}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0xaa,0x09},{0x02,0x20,0x08,0x04},{0x88,0x00,0x00,0x21},{0x28,0x00,0x00,0x09},{0xaa,0xaa,0xa8,0x85},{0x8a,0xaa,0x0a,0x09},{0x88,0x08,0x00,0x04},{0xaa,0x82,0x8a,0x82},{0xaa,0xaa,0xaa,0x81},{0xa8,0x22,0xa8,0x15},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0x2a,0x95},{0xa0,0x22,0x82,0x91},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xaa,0x85}},{{0xa8,0x00,0x05,0x10},{0x8a,0xaa,0xaa,0x09},{0x22,0x20,0x28,0x14},{0x88,0x00,0x00,0x25},{0x28,0x00,0x00,0x05},{0xaa,0xaa,0xa8,0x45},{0xaa,0xaa,0xaa,0x05},{0x88,0x0a,0x00,0x85},{0xaa,0xa2,0x8a,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa2,0x2a,0x8a,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xa6,0x85}},{{0xa8,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x09},{0xaa,0x22,0xaa,0x15},{0x88,0x00,0x00,0x25},{0xa8,0x00,0x00,0x25},{0xaa,0xaa,0xa8,0x65},{0xaa,0xaa,0xaa,0x25},{0xa8,0x2a,0x80,0xa5},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa2,0xaa,0x8a,0x95},{0xa9,0xaa,0x66,0x55},{0x15,0x6a,0x56,0x45}},{{0x94,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x29},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x08,0x00,0x25},{0xaa,0xaa,0xa6,0x65},{0xaa,0xaa,0xaa,0x25},{0xaa,0x2a,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x45},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0x29,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xa9,0xa9,0x55,0x55},{0x25,0x6a,0x55,0x55}},{{0x94,0x00,0x0a,0x64},{0x8a,0xaa,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x0a,0x0a,0x15},{0xaa,0x6a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa9,0x69,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x99,0xa5,0x55,0x55},{0x21,0x15,0x55,0x55}},{{0x94,0x00,0x0a,0x64},{0xaa,0x9a,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x8a,0x00,0x00,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x5a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0x55},{0x9a,0xaa,0xa6,0x55},{0x9a,0xaa,0xa5,0x55},{0xa9,0x69,0xaa,0x55},{0xaa,0xa9,0x6a,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x55}},{{0x94,0x00,0x0a,0xa5},{0xaa,0x5a,0x65,0x15},{0xaa,0x22,0xaa,0x95},{0xaa,0xa0,0x08,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x55,0x56,0x55},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x9a,0xa9,0x56,0x55},{0x9a,0xa1,0x55,0x55},{0xa9,0x69,0x95,0x55},{0xaa,0xa9,0x69,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x55}},{{0x68,0x00,0x0a,0x95},{0xa6,0x55,0x55,0x15},{0xaa,0x12,0x8a,0x15},{0xaa,0xa0,0x28,0x15},{0xa8,0x2a,0x8a,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0xaa,0xa5,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0xa5,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0x91,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x9a,0xa9,0x65,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x55}},{{0x68,0x00,0x0a,0x55},{0xa6,0x55,0x9a,0x15},{0xaa,0x12,0x06,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x99,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x55}},{{0x68,0x00,0x05,0x55},{0xa5,0x55,0x9a,0x25},{0xa9,0x91,0x55,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x95},{0x59,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa5,0x6a,0x55},{0xaa,0xa9,0x65,0x55},{0xa4,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x55}},{{0x68,0x00,0x05,0x55},{0xa5,0x65,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xaa,0xaa,0xa8,0x95},{0x9a,0x25,0x65,0x95},{0x51,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xa6,0x85,0x65,0x55},{0x9a,0x29,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x55}},{{0x54,0x00,0x05,0x55},{0xa9,0xa5,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xa6,0xaa,0xaa,0x95},{0x96,0xa5,0x65,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x85,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x55,0x55,0x55},{0xaa,0x95,0x11,0x56}},{{0x94,0x00,0x05,0x55},{0x69,0xaa,0xaa,0x25},{0x95,0x99,0x55,0x55},{0xa6,0xaa,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x56},{0xa6,0x55,0x55,0x59},{0xaa,0x95,0x21,0x56}},{{0x94,0x00,0x85,0x51},{0x6a,0xaa,0xaa,0xa5},{0x95,0x99,0x55,0x55},{0x65,0x59,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x66},{0xaa,0x56,0x99,0x6a},{0xaa,0xaa,0xaa,0xaa}},{{0x94,0x22,0x85,0x51},{0x6a,0xaa,0x20,0x95},{0x55,0x59,0x55,0x55},{0x55,0x55,0x56,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x66,0x56,0x95,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x96,0x2a,0x65,0x01},{0xa2,0x8a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x96,0xa9,0x50,0x01},{0xa6,0x0a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x45,0x55,0x55,0x4a},{0x55,0x55,0x55,0x55},{0x66,0x96,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x42,0x95,0x90,0x01},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x52},{0x65,0x54,0x01,0x2a},{0x65,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x56,0xa0,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x64},{0x66,0x6a,0xa9,0x50},{0x55,0x55,0x55,0x64},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x45,0x50,0x00,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x6a,0x60,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x56},{0x55,0x5a,0x95,0x5a},{0x55,0x15,0x55,0x20},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0xa9,0x50,0x05},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x59,0x65,0x6a,0xa6},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x41,0x50,0x15,0x6a},{0x45,0x54,0x55,0x91},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x50,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x65,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x54,0x10,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x55,0x50,0x15},{0x55,0x55,0x55,0x55},{0x6a,0xa2,0xaa,0xa2},{0x52,0xa6,0x65,0x92},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x41,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xa2},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x84,0x50,0x05,0x0a},{0x40,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xa5,0x50,0x15,0x48},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x45},{0x00,0x00,0x00,0x00},{0x81,0x51,0x11,0x68},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x45,0x55,0x55,0x44},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_8 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_8_data[0] };
+const uint8_t epd_wp_ED047TC2_2_9_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x0a,0x82,0x02,0x00},{0x40,0x00,0x00,0x00},{0x00,0x80,0x02,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,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x0a,0x8a,0x82,0x00},{0x40,0x08,0x00,0x40},{0x00,0x80,0x22,0x08},{0x00,0x08,0x08,0x08},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x04,0x00,0x00},{0x11,0x40,0x20,0x00},{0x81,0x00,0x00,0x20},{0x28,0x08,0x00,0x82},{0x00,0x20,0x80,0x80},{0x00,0x00,0x02,0x80}},{{0x80,0x00,0x00,0x00},{0x6a,0x8a,0x8a,0x00},{0x90,0x08,0x01,0x40},{0x00,0x80,0x22,0x08},{0x00,0x28,0x88,0x0a},{0x80,0x08,0x00,0x00},{0x00,0x08,0x02,0x00},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x80,0x00},{0x14,0x14,0x00,0x00},{0x21,0x50,0x20,0x80},{0x81,0x18,0x00,0xa0},{0x29,0x0a,0x02,0x81},{0x2a,0xa2,0xaa,0xa0},{0x00,0x2a,0x02,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xa0,0x08,0x02,0x80},{0x80,0x88,0x22,0x08},{0x20,0xa8,0x89,0x0a},{0x80,0xa8,0x00,0x02},{0xaa,0x8a,0x0a,0x08},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x02},{0x08,0x08,0x80,0x00},{0x24,0x54,0x22,0x80},{0x25,0x52,0x2a,0xa0},{0x86,0xa8,0x20,0xa8},{0xaa,0x2a,0x82,0x81},{0x2a,0xaa,0xaa,0xa0},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xaa,0x8a,0x2a,0x80},{0x80,0x88,0x22,0x08},{0x22,0xaa,0x8a,0x0a},{0x82,0xa8,0x00,0x02},{0xaa,0xaa,0x0a,0x0a},{0x00,0x08,0x02,0x28},{0x00,0x00,0x00,0x02},{0x2a,0x8a,0x80,0x00},{0xa5,0xaa,0xa2,0xa0},{0x26,0x96,0xaa,0xa0},{0x8a,0xa8,0xa0,0xa8},{0xaa,0x2a,0x8a,0x81},{0x2a,0xaa,0xaa,0xa8},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x0a},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0x2a,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x00,0x02},{0x2a,0xaa,0x80,0x00},{0xa9,0xaa,0xa2,0xa0},{0x26,0xa6,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0x2a,0x8a,0x41},{0xaa,0xaa,0xaa,0xa8},{0x08,0xaa,0x12,0x41}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x29},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0xaa,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x08,0x80},{0x2a,0xaa,0x8a,0x22},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x12,0x41}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x02},{0xaa,0xaa,0xaa,0x09},{0x20,0x08,0x02,0x28},{0x00,0x02,0x0a,0xa0},{0x2a,0xaa,0x8a,0x2a},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x11,0x45}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x81,0x88,0xa2,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0x8a,0x02,0x28},{0x00,0x82,0xaa,0xa1},{0x2a,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0x91,0x45}},{{0x80,0x00,0x00,0x20},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0x80},{0x82,0x88,0xaa,0x24},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x82,0x04},{0x20,0xa2,0xaa,0xa1},{0x2a,0xaa,0xaa,0x29},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x55},{0x96,0xa5,0x65,0x55},{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0x91,0x45}},{{0x80,0x00,0x00,0x10},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x9a,0x14},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x21},{0xaa,0xaa,0xaa,0x85},{0x2a,0xaa,0x8a,0x15},{0x20,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0x25},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0xaa,0x55},{0x96,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x56},{0x2a,0x99,0x91,0x45}},{{0x80,0x00,0x00,0x94},{0xaa,0xa9,0x45,0x44},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x99,0x16},{0xaa,0xa6,0xa6,0x95},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa9,0xa5},{0xaa,0xaa,0xa9,0x95},{0x2a,0xaa,0xaa,0x69},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0x55,0x56},{0x1a,0x95,0x99,0x05}},{{0x80,0x00,0x00,0x64},{0xa9,0x65,0x45,0x48},{0xaa,0xaa,0xa9,0xa2},{0xa2,0x6a,0x99,0x15},{0xaa,0xa5,0x65,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa5,0xa5},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x59},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x99,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x99,0x55,0x55},{0x19,0x55,0x89,0x05}},{{0x40,0x00,0x00,0xa4},{0xa5,0x65,0x45,0x4a},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x6a,0x99,0x15},{0xa9,0x95,0x65,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa5,0x95,0xa5},{0xaa,0xa6,0xa9,0x95},{0xaa,0xaa,0xa6,0x55},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x59,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x99,0x55,0x55},{0x15,0x55,0x49,0x15}},{{0x40,0x00,0x00,0x54},{0xa5,0x65,0x45,0x88},{0xaa,0xaa,0xa9,0xa1},{0xaa,0x66,0x11,0x15},{0xa9,0x55,0x65,0x55},{0xaa,0x96,0xa9,0x95},{0xa5,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x15},{0xaa,0xaa,0x95,0x55},{0x26,0xa5,0x65,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x45,0x15}},{{0x40,0x00,0x00,0x55},{0xa5,0x55,0x46,0x89},{0xaa,0xa6,0xa5,0x61},{0xaa,0x66,0x51,0x15},{0x95,0x55,0x55,0x55},{0x28,0x56,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x55},{0xaa,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x15}},{{0xa0,0x00,0x00,0x55},{0x95,0x56,0x8a,0x99},{0xaa,0xaa,0x9a,0x51},{0xaa,0x66,0x55,0x95},{0x95,0x55,0x55,0x55},{0x29,0x55,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa5,0x45,0x55},{0xaa,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x16}},{{0xa0,0x00,0x00,0x55},{0x9a,0x9a,0x8a,0x65},{0xaa,0xa5,0x56,0x51},{0x6a,0x56,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x96},{0x95,0x55,0x55,0x55},{0x05,0x55,0x45,0x16}},{{0xa0,0x00,0x20,0x51},{0x5a,0xaa,0x8a,0x65},{0xa5,0x65,0x56,0x59},{0x69,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x85,0x55,0x45,0x12}},{{0x60,0x28,0xa0,0x51},{0x6a,0xaa,0x8a,0x65},{0x95,0x55,0x56,0x55},{0x59,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x84,0x55,0x44,0x12}},{{0x6a,0xaa,0xa8,0x11},{0x6a,0xaa,0x8a,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x45,0x44,0x12}},{{0x5a,0xaa,0x64,0x01},{0xa6,0x99,0x45,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x44,0x46,0x12}},{{0x5a,0x95,0x56,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x99,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x56,0x5a,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x95},{0x95,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x65,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x25,0x6a,0x99,0x01},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x65},{0x56,0x5a,0x56,0x56},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x65},{0x95,0x55,0x41,0x56},{0x95,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x5a,0x66,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0xaa,0x56,0x05},{0x55,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x95,0x61},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x45},{0x55,0x55,0x55,0x59},{0x55,0x55,0x54,0x55},{0x55,0x54,0x00,0x15},{0x91,0x55,0x15,0x42},{0x55,0x55,0x24,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0x95,0x56,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x65,0x49,0x91},{0x55,0x55,0x54,0x44},{0x55,0x55,0x55,0x49},{0x15,0x55,0x55,0x54},{0x55,0x51,0x54,0x0a},{0x55,0x04,0x00,0x2a},{0xaa,0xaa,0xaa,0xaa},{0x55,0x54,0x10,0x55},{0x65,0x56,0x9a,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xa2,0x1a,0x06,0x50},{0x68,0xa0,0xa8,0xaa},{0x55,0x45,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x04,0x00,0xaa},{0x55,0x55,0x65,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x51,0x05,0x01,0x02},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x6a,0xaa,0xa9,0xa4},{0x55,0x55,0x55,0x00},{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_9 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_9_data[0] };
+const uint8_t epd_wp_ED047TC2_2_10_data[44][16][4] = {{{0x00,0x00,0x00,0x00},{0x80,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x00,0x08,0x02},{0x00,0x80,0x00,0x08},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x02,0x00,0x00,0x00},{0xa2,0x88,0x20,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x80,0x20,0x00},{0x00,0x80,0x00,0x00},{0x00,0x82,0x00,0x00},{0xa8,0x00,0x08,0x82},{0x00,0x80,0x20,0x0a},{0x92,0x00,0x00,0x8a},{0x2a,0x20,0xa2,0xa8},{0x00,0x00,0x00,0x08}},{{0x02,0x00,0x00,0x00},{0xa2,0x8a,0x20,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x08,0x05,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x00,0x80,0x20,0x00},{0x02,0xa0,0xa0,0x00},{0x00,0x82,0x00,0x02},{0xaa,0x20,0x08,0x82},{0x84,0x80,0xa0,0x0a},{0xa2,0x84,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x08}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa0,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x15,0x42,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xa0,0x20,0x80},{0x02,0xaa,0xa8,0x00},{0x00,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x82},{0x9a,0x90,0xa8,0x0a},{0xa6,0xa8,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x00,0x80,0x2a}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x1a,0x46,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xaa,0x28,0x80},{0x2a,0xaa,0xa8,0x00},{0x02,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0x08,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x8a,0x88,0x26}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x90},{0x02,0xa0,0x08,0x02},{0x2a,0x2a,0x86,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x80},{0x2a,0xaa,0xa8,0x20},{0x02,0x82,0x00,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0x8a,0x8a,0xa6}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x0a},{0x80,0x00,0x00,0x90},{0x02,0xaa,0x2a,0x02},{0x2a,0xaa,0x8a,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xa2,0xa2,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0xaa,0x4a,0x55}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0x90},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa0},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x16,0xaa,0x46,0x55}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa4},{0x15,0x9a,0x65,0x55}},{{0x82,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0x80,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0x15,0x95,0x65,0x55}},{{0x81,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0xa2,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x8a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x02,0x82,0x20},{0x00,0x0a,0x00,0x09},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0xa8},{0xaa,0xaa,0x9a,0x2a},{0xa2,0xa2,0x02,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x82,0x82,0xa0},{0x00,0x8a,0x80,0x09},{0x2a,0xaa,0xaa,0x22},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0x21},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xa9,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0xa8},{0xaa,0x66,0x9a,0x2a},{0xa2,0xa2,0x22,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0x2a,0xa2,0xa0,0x80},{0x02,0x8a,0x80,0x05},{0x2a,0xaa,0x8a,0x20},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xa0,0x61},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x81,0x00,0x80,0x94},{0xaa,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x82},{0x02,0x8a,0x82,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xa8,0xaa,0xa1},{0xaa,0xaa,0xa0,0x65},{0xaa,0xaa,0x20,0x85},{0xaa,0xaa,0xaa,0x65},{0xaa,0x95,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x41,0x00,0x40,0x94},{0x69,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xa2,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0x9a},{0xaa,0x28,0xaa,0xa9},{0xaa,0xaa,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x42,0x00,0x48,0xa4},{0x59,0x55,0x55,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xaa,0x25},{0x2a,0xaa,0xaa,0x9a},{0xa8,0x80,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x8a,0x29},{0x2a,0xaa,0x56,0x99},{0xaa,0x28,0xa8,0xa9},{0xaa,0x82,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x42,0x00,0x48,0x64},{0x59,0x59,0x65,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xa0,0x65},{0x2a,0xaa,0xa9,0x56},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0xa9,0x8a},{0xaa,0xaa,0xaa,0x05},{0xaa,0x2a,0x86,0x69},{0x2a,0x55,0x55,0x99},{0xaa,0x69,0x89,0xa9},{0x96,0x82,0x00,0x45},{0xaa,0x22,0x10,0x05},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0x62,0x00,0x4a,0x54},{0x59,0x9a,0xa9,0x95},{0xaa,0xaa,0x22,0x65},{0x82,0xaa,0xa5,0x45},{0x26,0xaa,0xa9,0x55},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0x29,0x89},{0xaa,0xaa,0xaa,0x85},{0xaa,0x55,0x54,0x69},{0x21,0x55,0x55,0x55},{0xaa,0x69,0x45,0xa9},{0x95,0x55,0x55,0x55},{0xaa,0x22,0x10,0x05},{0x89,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55}},{{0xa2,0x00,0x8a,0x54},{0x66,0xaa,0xaa,0x95},{0xaa,0xaa,0x22,0x55},{0x82,0x95,0x55,0x55},{0x16,0xa5,0x55,0x55},{0xa2,0xa0,0x20,0x09},{0xaa,0xa9,0x29,0x09},{0xaa,0xaa,0xaa,0x85},{0xa9,0x55,0x55,0x59},{0x11,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa1,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55}},{{0xa2,0x00,0x86,0x54},{0xa6,0xaa,0xaa,0xa5},{0xaa,0xaa,0x22,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x5a,0xa9,0x55},{0xa2,0xaa,0x28,0x01},{0xaa,0xa9,0x29,0x55},{0xaa,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x55,0x55,0x55}},{{0xa1,0x00,0x85,0x54},{0xaa,0xa2,0xaa,0x65},{0xaa,0xaa,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x15,0xa5,0x55,0x55},{0xa2,0xaa,0xa8,0x01},{0xaa,0xa9,0x69,0x55},{0xaa,0xa5,0x69,0xa5},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x45,0x55,0x55}},{{0xa1,0x00,0x85,0x54},{0x9a,0x95,0x55,0x55},{0xaa,0x99,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa2,0xa9,0x55,0x55},{0xaa,0xa5,0x69,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x85,0x55}},{{0x61,0x00,0x45,0x54},{0x95,0x55,0x55,0x55},{0xaa,0x99,0x61,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa5,0x55,0x55,0x55},{0xaa,0x65,0x55,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x89,0x95}},{{0x61,0x00,0x45,0x50},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0xaa,0x8a,0xa9}},{{0x61,0x00,0x45,0x10},{0x15,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xa9}},{{0x51,0x20,0x41,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x16,0x6a,0x94,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x50,0x2a,0x40,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x2a,0x00,0x01},{0x55,0x55,0x55,0x55},{0x51,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0xaa}},{{0x28,0xa9,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x28,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x24,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x99},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x99},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x9a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x14,0x6a,0x20,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x65},{0x55,0x14,0x54,0x56},{0x41,0x55,0x55,0x56},{0x55,0x55,0x55,0x5a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x14,0x6a,0x10,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x11},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x15},{0x6a,0xaa,0xaa,0x99},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x96,0x10,0x05},{0x55,0x55,0x55,0x19},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x21},{0xa9,0x55,0x56,0xa5},{0x55,0x55,0x55,0x55},{0x66,0xa9,0x69,0x54},{0x55,0x50,0x14,0x1a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x95,0x10,0x45},{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x65},{0x6a,0x6a,0x9a,0x11},{0x95,0x55,0x55,0x55},{0x69,0x55,0x55,0x59},{0x51,0x56,0x16,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x18,0x55,0x10,0x55},{0x00,0x00,0x00,0x00},{0x55,0x65,0x56,0x54},{0x55,0x15,0x45,0x02},{0x80,0x00,0x00,0x0a},{0x55,0x55,0x55,0x16},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x15,0x55,0x15,0x55},{0x00,0x00,0x00,0x00},{0x59,0x55,0x55,0x14},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x65,0x45,0x54,0x0a},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_10 = { .phases = 44, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_10_data[0] };
+const uint8_t epd_wp_ED047TC2_2_11_data[57][16][4] = {{{0x20,0x8a,0x80,0x00},{0x15,0x55,0x5a,0xa4},{0x44,0x10,0x0a,0x41},{0x40,0x00,0x09,0x54},{0x10,0x50,0x00,0x00},{0x00,0x00,0x04,0x28},{0x40,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x40,0x00},{0x00,0x00,0x00,0x00},{0x00,0x40,0x00,0x68},{0x00,0x00,0x40,0x00},{0x00,0x00,0x0a,0x54},{0x00,0x0a,0x80,0x00},{0x10,0x09,0x60,0x00},{0x00,0x00,0x00,0x50}},{{0xaa,0xaa,0x8a,0x00},{0x0a,0x60,0x0a,0xa8},{0x54,0x54,0x8a,0x41},{0x41,0x02,0x09,0x54},{0x15,0x50,0x06,0x24},{0x00,0x08,0xa4,0x28},{0x44,0x00,0x09,0xa8},{0x05,0x00,0x2a,0xa8},{0x01,0x10,0x46,0xa8},{0x04,0x00,0x00,0xa8},{0x00,0x40,0x00,0x54},{0x04,0x00,0x44,0xa8},{0x00,0x00,0x8a,0x54},{0x00,0x0a,0x8a,0x58},{0x50,0x19,0x65,0x54},{0x00,0x00,0x00,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x6a,0xaa,0xa8},{0x55,0x94,0x89,0x55},{0x41,0x02,0x09,0x54},{0x15,0x50,0x66,0x24},{0x40,0x04,0xa4,0x68},{0x44,0x0a,0x09,0x54},{0x05,0x08,0x55,0x54},{0x11,0x14,0x56,0x54},{0x04,0x40,0x00,0x58},{0x01,0x40,0x0a,0x54},{0x04,0x0a,0x44,0xa8},{0x01,0x00,0x8a,0x54},{0x00,0x0a,0x6a,0x54},{0x50,0x19,0x65,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x2a,0xaa,0xa8},{0x96,0x95,0x55,0x55},{0x51,0x0a,0x05,0x54},{0x15,0x50,0x66,0xa4},{0x40,0x04,0x54,0x54},{0x44,0x05,0x09,0x54},{0x05,0x18,0x55,0x54},{0x51,0x14,0x56,0x54},{0x04,0x40,0x02,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x58},{0x01,0x0a,0x85,0x54},{0x01,0x05,0x65,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x96,0xa5,0x55,0x55},{0x51,0x09,0x05,0x55},{0x15,0x50,0x65,0x94},{0x44,0x14,0x54,0x54},{0x54,0x15,0x95,0x54},{0x05,0x56,0x55,0x54},{0x51,0x14,0x55,0x54},{0x14,0x40,0x82,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x54},{0x01,0x0a,0x45,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x49,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x14,0x55,0x55},{0x14,0x40,0x8a,0x54},{0x01,0x40,0x85,0x54},{0x04,0x15,0x44,0x54},{0x01,0x0a,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x55,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0xa9,0x54},{0x01,0x40,0x45,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0x69,0x55},{0x01,0x40,0x65,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x55,0x54},{0x01,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x52,0x55,0x54},{0x54,0x14,0x56,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x65,0x55},{0x01,0x50,0x65,0x55},{0x04,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x92,0x55,0x55},{0x55,0x14,0x56,0x54},{0x54,0x55,0x55,0x55},{0x45,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x91,0x55,0x15,0x55},{0x16,0x92,0x55,0x55},{0x55,0x14,0x56,0x55},{0x54,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0x92,0x55,0x95,0x55},{0x6a,0x91,0x55,0x55},{0x55,0x54,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x05,0x15,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0x91,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x4a,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x4a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0xa1,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa9,0x15,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0xa5,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x95,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0x99,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0x56,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x55,0x55,0x55},{0x15,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x05,0x55,0x55},{0xa9,0x66,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x55},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0xa9,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x15,0x45,0x55,0x55},{0x11,0x55,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x15,0x55,0x55},{0xa9,0x66,0x95,0x55},{0x00,0x10,0x55,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x96},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x55,0x55,0x55},{0x5a,0x95,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x19,0x45,0x55,0x55},{0x11,0x95,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x66,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x9a,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x96},{0xaa,0xa6,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x5a,0xa5,0x55,0x55},{0xaa,0x65,0x55,0x55},{0x29,0x85,0x55,0x55},{0x12,0x95,0x55,0x55},{0x59,0x55,0x56,0x55},{0x56,0x15,0x55,0x55},{0xa6,0x15,0x55,0x55},{0xaa,0x6a,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x95,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x9a,0xa5,0x55,0x55},{0xaa,0x69,0x95,0x55},{0x2a,0x85,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x55,0x95,0x55},{0x56,0x15,0x55,0x55},{0xaa,0x1a,0x95,0x55},{0xaa,0x6a,0xaa,0xa9},{0x00,0x15,0x55,0x54}},{{0x55,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0xa9},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0xa9,0x55},{0xa9,0xaa,0x56,0x55},{0xaa,0xa5,0x95,0x55},{0xaa,0x69,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x1a,0xaa,0xa5},{0xaa,0xaa,0xaa,0xa9},{0x20,0x95,0x55,0x54}},{{0x55,0x55,0x8a,0x00},{0xaa,0xaa,0xa5,0x5a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0x99,0x59},{0xaa,0xa8,0xa9,0x55},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0x6a,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0xa6,0x15,0x55,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x5a,0x8a,0x00},{0xaa,0xaa,0x55,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0x9a,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x6a,0x8a,0x00},{0xaa,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xa9,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0xa5,0x55,0x95},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0xaa,0x8a,0x00},{0xa9,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x95,0x55,0x55},{0x66,0xa5,0x55,0xa9},{0xaa,0xaa,0x99,0x55},{0xaa,0x2a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x12,0x45,0x55,0x54}},{{0x6a,0xaa,0x8a,0x00},{0xa5,0x55,0xa5,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0x95,0x55,0xa5},{0xa6,0xa5,0x9a,0xa9},{0xaa,0xaa,0x99,0xa5},{0xaa,0x2a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x41,0x55,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x95,0x6a,0xa5,0x56},{0xaa,0x69,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0x96,0xa9},{0xa6,0xa5,0xaa,0xaa},{0xaa,0xaa,0x99,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x85,0x00},{0x55,0x6a,0xa5,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xa9,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0xaa,0xaa},{0xaa,0xa5,0xaa,0xaa},{0xaa,0xaa,0xa9,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x45,0x00},{0x5a,0x6a,0x55,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x99,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x40,0x02,0xa0}},{{0xaa,0xa5,0x45,0x00},{0x6a,0x55,0x55,0x56},{0x69,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x40,0x02,0xa8}},{{0xaa,0x55,0x45,0x00},{0x6a,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0xa5,0x55,0x45,0x00},{0x66,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x55,0x95,0x55,0x55},{0x55,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x5a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x99,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x55,0x69},{0x69,0x6a,0xaa,0xaa},{0xaa,0x5a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0xa9,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x0a,0xa9}},{{0x55,0x55,0x45,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x5a,0xa9,0xaa},{0xa5,0x6a,0xaa,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x0a,0xa9}},{{0x55,0x55,0x40,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0xa9,0xaa},{0x95,0x6a,0x66,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa9}},{{0x55,0x50,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x99,0xaa},{0x55,0x46,0x66,0xaa},{0xa8,0x6a,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa9}},{{0x50,0x00,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x95,0x56},{0x55,0x45,0x55,0xa6},{0x65,0x96,0x96,0xaa},{0x26,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x08,0x28,0xaa,0xa9}},{{0x00,0x00,0x00,0x60},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x55,0xa6},{0x55,0x96,0x66,0xaa},{0x2a,0x4a,0xaa,0xaa},{0xaa,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x88,0x2a,0xaa,0xa8}},{{0x00,0x00,0x20,0x50},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x66,0x6a},{0x12,0x86,0xaa,0xaa},{0x85,0x4a,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0xa8,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x61,0x09,0x55,0x55},{0x45,0x55,0x55,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x98,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x99,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x56,0xaa},{0x94,0x6a,0xaa,0xaa},{0x56,0x65,0x55,0x55},{0xa6,0x55,0x66,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x00,0x00,0x25,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x95,0x55,0x55},{0xa9,0x8a,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x00,0x05,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xa4,0x6a,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa}},{{0x05,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x01,0x50,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_2_11 = { .phases = 57, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_2_11_data[0] };
+const EpdWaveformPhases* epd_wm_ed047tc2_2_ranges[7] = { &epd_wp_ED047TC2_2_5,&epd_wp_ED047TC2_2_6,&epd_wp_ED047TC2_2_7,&epd_wp_ED047TC2_2_8,&epd_wp_ED047TC2_2_9,&epd_wp_ED047TC2_2_10,&epd_wp_ED047TC2_2_11 };
const EpdWaveformMode epd_wm_ed047tc2_2 = { .type = 2, .temp_ranges = 7, .range_data = &epd_wm_ed047tc2_2_ranges[0] };
-const uint8_t epd_wp_ed047tc2_5_5_data[46][16][4] = {{{0x00,0x00,0x00,0x00},{0x20,0x88,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x80,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x08,0x00},{0x00,0x02,0x00,0x80},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa2,0x88,0x20,0x88},{0x22,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x00,0x44,0x08,0x00},{0xa0,0x02,0x20,0xa8},{0x08,0x62,0x88,0x80},{0x00,0x00,0x00,0x08},{0x08,0x22,0x88,0x80},{0x00,0x80,0x00,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x24,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x80,0x82,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x84,0x84,0x28,0x80},{0xa0,0x02,0x20,0xaa},{0xa8,0xaa,0x8a,0x80},{0x22,0x84,0x00,0x28},{0x2a,0xaa,0xaa,0xa0},{0x00,0x80,0x28,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x08,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x00,0x20,0x02},{0x00,0x00,0x00,0x02},{0x84,0x88,0x2a,0xa2},{0xa0,0xaa,0xa8,0xa8},{0xa8,0xaa,0x8a,0x80},{0x2a,0xaa,0x08,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x08}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0x24,0x80,0x00},{0x00,0x00,0x00,0x00},{0x29,0x80,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x02,0xa0,0x00},{0x02,0x00,0x00,0x81},{0x88,0xa8,0xaa,0xa9},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0x8a,0x81},{0x2a,0xaa,0x2a,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x04}},{{0xaa,0xaa,0xa8,0xa4},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0xa8,0x80,0x00},{0x00,0x20,0x00,0x00},{0x2a,0x84,0xa0,0x08},{0x2a,0x68,0x20,0x80},{0x80,0xa2,0xa2,0xa8},{0x80,0x02,0xa0,0x01},{0x02,0x80,0x00,0xa9},{0x9a,0xa8,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x89},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x8a,0x28,0x04}},{{0xaa,0xaa,0xa8,0x64},{0x2a,0xaa,0xaa,0x01},{0x00,0x88,0x02,0x00},{0x29,0xa8,0x80,0x00},{0x00,0x28,0x08,0x02},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xa2,0xa2,0xa9},{0x80,0x02,0xa0,0x01},{0x02,0xa0,0x00,0xa9},{0x9a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0x8a,0xa8,0x84}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x00,0x8a,0x02,0x08},{0x2a,0xa8,0x88,0x00},{0x00,0x28,0x8a,0x01},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xaa,0xaa,0xa9},{0x80,0x02,0xa0,0x01},{0x0a,0xaa,0x80,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x20,0x8a,0x0a,0x08},{0x2a,0xa8,0xaa,0x00},{0x00,0x2a,0x8a,0x01},{0x2a,0xaa,0xa8,0x08},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x80,0x02,0xa0,0x81},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x59},{0x69,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa0,0x8a,0x0a,0x0a},{0xaa,0xaa,0xaa,0x02},{0x08,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x09},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x82,0x82,0xa0,0xa1},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0x59,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa2,0x8a,0x2a,0x09},{0xaa,0xaa,0xaa,0x09},{0x28,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x89},{0x2a,0xaa,0xa8,0xa1},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0xa0,0xa9},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x58},{0x2a,0xaa,0xa5,0x05},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x01},{0x2a,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x01},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x54}},{{0xaa,0xaa,0x96,0xa8},{0xaa,0xaa,0x55,0x09},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x98,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa4,0x55},{0xaa,0xa8,0x8a,0x55},{0xaa,0xaa,0xa5,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x54,0xaa,0xaa,0x54}},{{0xaa,0xa5,0x96,0xa8},{0xaa,0xa5,0x55,0xa9},{0xaa,0xaa,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x90,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0xaa,0x55},{0xa6,0x99,0x55,0x55},{0x94,0xaa,0xa6,0x50}},{{0xaa,0xa5,0x56,0xa8},{0xaa,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x15,0x55},{0x92,0x95,0x65,0x55},{0xaa,0xaa,0xa5,0x55},{0x95,0x95,0x55,0x55},{0x94,0xaa,0x96,0x00}},{{0xa9,0x55,0x56,0xa8},{0xa9,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa5},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x9a,0x85,0x55,0x55},{0x94,0x95,0x55,0x55},{0x99,0xa9,0x95,0x55},{0x95,0x55,0x55,0x55},{0x94,0xaa,0x96,0x00}},{{0x95,0x55,0x56,0xa8},{0xa5,0x55,0x5a,0xa5},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0xa5},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0x96,0x65},{0xaa,0xaa,0x1a,0x59},{0xaa,0x59,0x51,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xa8,0x55,0x55,0x55},{0x98,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x94,0x6a,0x96,0x00}},{{0x95,0x55,0x55,0x94},{0x95,0x55,0xaa,0x95},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0x95},{0x2a,0xaa,0xa5,0x55},{0x9a,0x6a,0x55,0x55},{0xaa,0x85,0x5a,0x55},{0xaa,0x59,0x55,0x55},{0xaa,0xa9,0x5a,0x55},{0xa8,0xaa,0x00,0x55},{0xa8,0x55,0x55,0x55},{0x91,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x90,0x69,0x95,0x00}},{{0x55,0x55,0x55,0x54},{0x96,0x5a,0xaa,0x15},{0xaa,0xa6,0xa9,0x05},{0xaa,0x9a,0x65,0x55},{0x2a,0x96,0x65,0x55},{0x96,0x65,0x55,0x55},{0xa1,0x95,0x56,0x55},{0x28,0x55,0x55,0x55},{0xaa,0xa9,0x52,0x55},{0xa9,0x01,0x05,0x55},{0x25,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x55,0x55,0x69,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa6,0xa5,0x85},{0x9a,0x56,0x55,0x55},{0xaa,0x95,0x65,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0xa1,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x55,0x5a,0xa9,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa5,0xa5,0x85},{0x92,0x55,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x15,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x56,0xaa,0xa9,0x55},{0x99,0xaa,0xa1,0x55},{0xaa,0x65,0x95,0x45},{0x95,0x55,0x55,0x55},{0xa6,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x54,0x55},{0x55,0x55,0x55,0x55},{0x05,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x00}},{{0x6a,0xaa,0xaa,0x55},{0x95,0xaa,0x15,0x55},{0x9a,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0xa5,0x55,0x55},{0x99,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x15,0x65,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x41,0x00}},{{0xaa,0xaa,0x56,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x56},{0x55,0x55,0x55,0x55},{0x69,0x55,0x55,0x55},{0xaa,0x55,0x41,0x00}},{{0xa9,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x55,0x55,0x96},{0x65,0x55,0x55,0x56},{0x6a,0x65,0x55,0xa6},{0xaa,0x94,0x49,0x00}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x6a,0x2a,0x8a,0xaa},{0x6a,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x51,0x56},{0x65,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x40,0xaa},{0x55,0x54,0x45,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x56,0xa6,0x50},{0x55,0x56,0x95,0x56},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x95,0x55,0x55},{0x55,0x55,0x95,0x04},{0x45,0x05,0x55,0xaa},{0x55,0x55,0x55,0xaa},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x45,0x48,0x58,0x50},{0x55,0x55,0x41,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x54,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x54},{0x41,0x04,0x44,0x12},{0x6a,0x2a,0x21,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x69},{0x55,0x55,0x55,0x54},{0x45,0x05,0x15,0x16},{0x41,0x41,0x15,0x02},{0x6a,0x00,0xa0,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x66},{0x55,0x59,0x59,0xa6},{0x60,0x00,0x00,0x0a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x6a,0x59,0x51,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x50,0x55,0x55,0x52},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x6a,0x55,0x55,0x02},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xa5,0x96,0xa6,0x5a},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_5 = { .phases = 46, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_5_data[0] };
-const uint8_t epd_wp_ed047tc2_5_6_data[43][16][4] = {{{0x02,0xaa,0x00,0x00},{0x20,0x22,0xa8,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x22,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xa8,0x20},{0x00,0x00,0x00,0x00},{0x20,0x02,0x08,0x80},{0x00,0x80,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x2a,0xaa,0x00,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x28},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xaa,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x20},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa0,0x20,0x2a},{0x28,0x22,0xa8,0xa8},{0x28,0x00,0x00,0x00}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa8,0x22,0x2a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x80}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0xa2,0x82,0x08,0x80},{0x08,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x40}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x20,0x00,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0xa8},{0x00,0x00,0x00,0x00},{0xaa,0x82,0x88,0xa0},{0x8a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0x94},{0x24,0x00,0x28,0x40}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x20,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0x8a,0x8a,0xa0},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x24,0x00,0x28,0x40}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x22,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0xa0,0xa0,0xa8,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa5},{0xa6,0xaa,0xaa,0x95},{0x24,0x00,0x26,0x40}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x42},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xa2,0xa8,0xaa,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xa8},{0x08,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa6,0x55},{0x56,0x02,0x95,0x54}},{{0xaa,0xaa,0xa0,0x04},{0x20,0xaa,0xa5,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x26},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0x98},{0x88,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xa5,0xa9,0x65,0x55},{0x56,0x0a,0x95,0x54}},{{0xaa,0xa9,0xa0,0x24},{0x20,0xa9,0x55,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x25},{0x2a,0x80,0x00,0x02},{0x20,0xa0,0x28,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x80},{0xa0,0x00,0x00,0x01},{0x20,0xa2,0xa8,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xa2,0xa8,0xaa},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xa5,0x95,0x55,0x55},{0x56,0x0a,0x95,0x54}},{{0xaa,0x95,0xa8,0xa4},{0x20,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x29},{0xa2,0x88,0x00,0x15},{0x2a,0x80,0x00,0x01},{0x20,0xa8,0x28,0x14},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x81},{0xa0,0x00,0x00,0x01},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x56,0x89,0x55,0x54}},{{0xaa,0x95,0x98,0x94},{0xa0,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x25},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0x20,0xaa,0xa8,0x94},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0xa1},{0xa0,0x22,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x94},{0xa8,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0xa9,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x14}},{{0xa9,0x55,0x9a,0x98},{0xa8,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0xa2,0xaa,0xaa,0x94},{0xaa,0xaa,0xaa,0x89},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x2a,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x56},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0x95,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x14}},{{0xa5,0x55,0x5a,0xa8},{0xa8,0x95,0x55,0x45},{0xa0,0x82,0x20,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x85,0x69},{0xaa,0x2a,0xa8,0x29},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xa9,0xa9,0xa5,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0xa5,0x41,0x14}},{{0x95,0x55,0x6a,0x68},{0xa8,0x55,0x55,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xa9,0x55,0x69},{0xaa,0x2a,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0x99,0xa9,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x65,0x40,0x14}},{{0x95,0x55,0x66,0x58},{0xa8,0x55,0x5a,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0xa8,0xa0,0x15},{0xaa,0x62,0xa8,0x19},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x95},{0xaa,0x95,0x55,0x55},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa9,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x65,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x91,0x55,0x40,0x14}},{{0x95,0x56,0xa5,0x94},{0xa8,0x56,0xaa,0x85},{0xa8,0xaa,0xa0,0x95},{0xaa,0xa8,0xa0,0x15},{0xaa,0x6a,0xaa,0x15},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x55,0x55},{0x89,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0x99,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x50,0x00,0x14}},{{0x55,0x6a,0x89,0x94},{0x98,0x6a,0xaa,0x85},{0xaa,0xaa,0xa0,0x95},{0xaa,0xa6,0xa0,0x15},{0x8a,0x6a,0xaa,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xaa,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x89,0x50,0x00,0x14}},{{0x56,0xaa,0x9a,0x14},{0x98,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xa2,0x15},{0x99,0x6a,0xaa,0x95},{0xaa,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xa9,0x10,0x00,0x04}},{{0x5a,0xaa,0x12,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0xa9,0x10,0x00,0x04}},{{0x6a,0xaa,0x55,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0x9a,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x8a,0x55,0x55,0x55},{0xaa,0x00,0x00,0x00}},{{0x6a,0xaa,0x55,0x55},{0x9a,0x96,0xaa,0x41},{0x6a,0xaa,0xaa,0x55},{0x99,0x66,0xaa,0x95},{0x95,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x59,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0x99,0x65},{0xaa,0x00,0x00,0x00}},{{0xaa,0xaa,0x55,0x55},{0x96,0x56,0xa5,0x51},{0x6a,0x69,0x8a,0x55},{0x95,0x66,0xaa,0x95},{0x95,0x69,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xaa,0xa8,0x55,0x55},{0x96,0x55,0x55,0x55},{0x6a,0x65,0x58,0x55},{0x95,0x66,0x59,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa9,0x45,0x55,0x45},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa5,0x55,0x55,0x41},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x5a,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x95,0x55,0x55,0x41},{0x56,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x45,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x56,0x59,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x2a},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x51},{0x59,0x55,0x55,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x56},{0x55,0x15,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x15},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x10,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x42},{0x6a,0x95,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x59},{0x15,0x55,0x55,0x82},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x55},{0x99,0x50,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0xaa,0x99,0x55,0x6a},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_6 = { .phases = 43, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_6_data[0] };
-const uint8_t epd_wp_ed047tc2_5_7_data[40][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x0a,0x08,0x80},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa0,0x80,0x00,0x00},{0x08,0x80,0x20,0x00},{0x00,0x12,0x22,0x00},{0x00,0x00,0x00,0x00},{0x1a,0x20,0x00,0x00},{0x01,0x80,0x00,0x00},{0x88,0x00,0x00,0x00},{0x00,0x10,0x80,0x00},{0x20,0x0a,0x88,0x82},{0x80,0x00,0x05,0x08},{0x0a,0xa0,0x00,0x20},{0x20,0x00,0x00,0x20},{0x00,0x80,0x00,0x08},{0x80,0x28,0x08,0x80},{0x2a,0x80,0xa0,0x28},{0x20,0x00,0x80,0x04}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x11,0x22,0xa2,0x00},{0x04,0x04,0x00,0x00},{0x2a,0xa0,0x20,0x00},{0x22,0xa0,0x00,0x00},{0x98,0x12,0x00,0x0a},{0x18,0xa0,0x80,0x00},{0x28,0x0a,0x8a,0x82},{0x88,0x88,0x09,0x28},{0x0a,0xa2,0x20,0x20},{0x20,0x00,0x02,0xa0},{0x00,0xa4,0x00,0x08},{0xa8,0xa8,0xa8,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x20,0x02,0x88,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x22,0x22,0xa2,0x28},{0x04,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x20,0x0a},{0x98,0x56,0x02,0x8a},{0xa8,0xa4,0x80,0x00},{0x28,0x0a,0xaa,0x82},{0x88,0xaa,0x0a,0x28},{0x2a,0xaa,0xa8,0x22},{0x20,0x40,0xa2,0xa2},{0x12,0xa8,0xa0,0x28},{0xa8,0xaa,0xaa,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x28,0x82,0xa8,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0xa0,0x20,0x00},{0x26,0x22,0xa2,0x28},{0x05,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x28,0x0a},{0x99,0xaa,0x82,0x8a},{0xaa,0xa8,0xa2,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0x28},{0x2a,0xaa,0xa8,0xa2},{0x20,0xa6,0xa2,0xa2},{0x92,0xaa,0xa8,0x28},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x98},{0x58,0x8a,0xa8,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xa0,0x20,0x00},{0x2a,0x66,0xa2,0x28},{0x09,0x0a,0x00,0x00},{0x2a,0xa2,0x28,0x00},{0x2a,0xa0,0xa8,0x0a},{0xa9,0xaa,0x82,0x8a},{0xaa,0xaa,0xaa,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa2},{0x25,0xa6,0xaa,0xa2},{0xaa,0xaa,0xa8,0x2a},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x58,0x8a,0xaa,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0x20,0x80},{0x2a,0xa6,0xa2,0x28},{0x19,0x0a,0x00,0x00},{0x2a,0xa2,0xa8,0x00},{0x2a,0xaa,0xa8,0x89},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x02},{0x2a,0x8a,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x81},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa0,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0x2a,0xaa,0xa8,0x04},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x82},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa4},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0xaa,0xaa,0xa8,0x88},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x96},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x95},{0x5a,0xaa,0xa9,0x54}},{{0xa8,0xa0,0x00,0x14},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xaa,0x28},{0xaa,0x2a,0x00,0x00},{0xaa,0xaa,0xaa,0x99},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x5a,0xaa,0x69,0x54}},{{0xa8,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x16},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0xa9,0xa5,0x55,0x55},{0x9a,0xaa,0x65,0x50}},{{0x98,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x15},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x64,0x50}},{{0x98,0x50,0x00,0x28},{0x8a,0x6a,0x9a,0x41},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x18,0x80},{0xaa,0xaa,0x96,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xaa,0xa5,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x80,0x55},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x54,0x50}},{{0x94,0x50,0x00,0x28},{0xa6,0x55,0x55,0x61},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x28,0x80},{0xa9,0x9a,0x96,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0xa9,0x69,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xa5,0x65,0x55},{0xaa,0xa6,0x25,0x55},{0xaa,0x01,0x55,0x55},{0xaa,0xaa,0x59,0x55},{0xaa,0x55,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0xa5,0x54,0x40}},{{0x94,0xa0,0x00,0x28},{0xa5,0x55,0x55,0x51},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0xa1},{0xa5,0x59,0x55,0x55},{0xaa,0x5a,0x55,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0xa5,0x15,0x55},{0xa9,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x65,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x55,0x59},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0x95},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xaa,0xa5,0x65,0x55},{0xaa,0x55,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa8,0x65,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x55},{0x8a,0x99,0x59,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0xa5,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x92,0x25,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x95},{0x89,0x99,0x55,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x25,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0x50,0x80,0x15},{0xa5,0x95,0x65,0x95},{0x99,0x95,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x58,0x5a,0x80,0x15},{0xa9,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x98,0x5a,0x80,0x15},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x2a,0x95,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa6,0x54,0x14,0x00}},{{0x98,0x5a,0x48,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x25,0x95,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0x55,0x55,0x65},{0xa6,0x54,0x10,0x00}},{{0x9a,0x55,0x68,0x55},{0x6a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x25,0x55,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x25,0x55,0x55,0x66},{0x2a,0xaa,0xaa,0x6a},{0xa6,0x10,0x00,0x00}},{{0x9a,0x55,0x64,0x41},{0x5a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0xa6,0x10,0x08,0x00}},{{0x9a,0x55,0x94,0x81},{0x5a,0x6a,0x9a,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x0a,0x9a,0x81},{0xa6,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x0a,0xa9,0x41},{0xa5,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x15,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x44,0x85,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x0a,0x65,0x41},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x55,0x55,0x69},{0x55,0x55,0x55,0x69},{0x55,0x56,0x11,0x59},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x66},{0x65,0x44,0x42,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x51},{0x55,0xaa,0xaa,0x54},{0x45,0x55,0x55,0x56},{0x59,0x59,0x11,0x56},{0x55,0x55,0x14,0x52},{0x55,0x55,0x55,0x55},{0x55,0x51,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x61},{0x40,0x55,0x55,0x80},{0x6a,0xaa,0xaa,0xaa},{0x55,0x04,0x02,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x59,0x55,0x65,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x40,0x00,0x00,0x42},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x64,0x0a,0x9a,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x59},{0x65,0x55,0x55,0x55},{0x55,0x64,0x55,0x41},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x6a,0x2a,0x82,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x45},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x44},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x95,0x55,0x51,0x42},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x50,0x50,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_7 = { .phases = 40, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_7_data[0] };
-const uint8_t epd_wp_ed047tc2_5_8_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x80,0x08,0x82},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x08},{0x00,0x00,0x00,0x00},{0x02,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0x20,0x00,0x00,0x08},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x20},{0x80,0x00,0x00,0x00},{0xaa,0x08,0xaa,0x08},{0x00,0x00,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x20,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0xa0,0x00,0x00,0x0a},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x2a},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa8},{0x00,0x20,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x81},{0xa0,0x00,0x00,0x05},{0x20,0x00,0x00,0x01},{0x02,0x82,0x00,0xa9},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa4},{0x12,0x28,0xaa,0x00}},{{0xa8,0x00,0x0a,0x00},{0x88,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x82,0xa8,0x08,0x81},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x08},{0x00,0x02,0x0a,0x80},{0x88,0x00,0x02,0x81},{0xa0,0x00,0x00,0x25},{0x28,0x00,0x00,0x21},{0x22,0x82,0x00,0xa5},{0x80,0x00,0x00,0x21},{0xaa,0xaa,0xaa,0xa4},{0x19,0x2a,0xaa,0x80}},{{0xa8,0x00,0x0a,0x00},{0x8a,0xa8,0x8a,0x0a},{0x00,0x20,0x00,0x28},{0x80,0x00,0x00,0x00},{0x20,0x00,0x00,0x0a},{0x82,0xaa,0x08,0x81},{0x08,0x20,0x02,0x02},{0x08,0x00,0x00,0x08},{0x28,0x02,0x0a,0x80},{0x88,0x08,0x0a,0x81},{0xa0,0x00,0x08,0x25},{0x2a,0x00,0x0a,0x21},{0x22,0xa2,0x00,0x95},{0x80,0x02,0x00,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x19,0xaa,0xaa,0x80}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0x8a,0x0a},{0x02,0x20,0x00,0x28},{0x88,0x00,0x00,0x02},{0x20,0x00,0x00,0x09},{0xa2,0xaa,0xa8,0x85},{0x8a,0x28,0x0a,0x09},{0x88,0x00,0x00,0x08},{0x28,0x02,0x8a,0x80},{0x88,0x0a,0x0a,0x81},{0xa8,0x02,0x08,0x25},{0xaa,0xaa,0x0a,0x21},{0x2a,0xaa,0x2a,0x95},{0xa0,0x02,0x82,0x81},{0xaa,0xaa,0xaa,0x95},{0x19,0xaa,0xaa,0x80}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0xaa,0x09},{0x02,0x20,0x08,0x04},{0x88,0x00,0x00,0x21},{0x28,0x00,0x00,0x09},{0xaa,0xaa,0xa8,0x85},{0x8a,0xaa,0x0a,0x09},{0x88,0x08,0x00,0x04},{0xaa,0x82,0x8a,0x82},{0xaa,0xaa,0xaa,0x81},{0xa8,0x22,0xa8,0x15},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0x2a,0x95},{0xa0,0x22,0x82,0x91},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xaa,0x84}},{{0xa8,0x00,0x05,0x10},{0x8a,0xaa,0xaa,0x09},{0x22,0x20,0x28,0x14},{0x88,0x00,0x00,0x25},{0x28,0x00,0x00,0x05},{0xaa,0xaa,0xa8,0x45},{0xaa,0xaa,0xaa,0x05},{0x88,0x0a,0x00,0x85},{0xaa,0xa2,0x8a,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa2,0x2a,0x8a,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xa6,0x84}},{{0xa8,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x09},{0xaa,0x22,0xaa,0x15},{0x88,0x00,0x00,0x25},{0xa8,0x00,0x00,0x25},{0xaa,0xaa,0xa8,0x65},{0xaa,0xaa,0xaa,0x25},{0xa8,0x2a,0x80,0xa5},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa2,0xaa,0x8a,0x95},{0xa9,0xaa,0x66,0x55},{0x15,0x6a,0x56,0x44}},{{0x94,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x29},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x08,0x00,0x25},{0xaa,0xaa,0xa6,0x65},{0xaa,0xaa,0xaa,0x25},{0xaa,0x2a,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x45},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0x29,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xa9,0xa9,0x55,0x55},{0x25,0x6a,0x55,0x54}},{{0x94,0x00,0x0a,0x64},{0x8a,0xaa,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x0a,0x0a,0x15},{0xaa,0x6a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa9,0x69,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x99,0xa5,0x55,0x55},{0x21,0x15,0x55,0x54}},{{0x94,0x00,0x0a,0x64},{0xaa,0x9a,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x8a,0x00,0x00,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x5a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0x55},{0x9a,0xaa,0xa6,0x55},{0x9a,0xaa,0xa5,0x55},{0xa9,0x69,0xaa,0x55},{0xaa,0xa9,0x6a,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x54}},{{0x94,0x00,0x0a,0xa5},{0xaa,0x5a,0x65,0x15},{0xaa,0x22,0xaa,0x95},{0xaa,0xa0,0x08,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x55,0x56,0x55},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x9a,0xa9,0x56,0x55},{0x9a,0xa1,0x55,0x55},{0xa9,0x69,0x95,0x55},{0xaa,0xa9,0x69,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x54}},{{0x68,0x00,0x0a,0x95},{0xa6,0x55,0x55,0x15},{0xaa,0x12,0x8a,0x15},{0xaa,0xa0,0x28,0x15},{0xa8,0x2a,0x8a,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0xaa,0xa5,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0xa5,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0x91,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x9a,0xa9,0x65,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x54}},{{0x68,0x00,0x0a,0x55},{0xa6,0x55,0x9a,0x15},{0xaa,0x12,0x06,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x99,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x54}},{{0x68,0x00,0x05,0x55},{0xa5,0x55,0x9a,0x25},{0xa9,0x91,0x55,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x95},{0x59,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa5,0x6a,0x55},{0xaa,0xa9,0x65,0x55},{0xa4,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x54}},{{0x68,0x00,0x05,0x55},{0xa5,0x65,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xaa,0xaa,0xa8,0x95},{0x9a,0x25,0x65,0x95},{0x51,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xa6,0x85,0x65,0x55},{0x9a,0x29,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x54}},{{0x54,0x00,0x05,0x55},{0xa9,0xa5,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xa6,0xaa,0xaa,0x95},{0x96,0xa5,0x65,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x85,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x55,0x55,0x55},{0xaa,0x95,0x11,0x54}},{{0x94,0x00,0x05,0x55},{0x69,0xaa,0xaa,0x25},{0x95,0x99,0x55,0x55},{0xa6,0xaa,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x56},{0xa6,0x55,0x55,0x59},{0xaa,0x95,0x21,0x54}},{{0x94,0x00,0x85,0x51},{0x6a,0xaa,0xaa,0xa5},{0x95,0x99,0x55,0x55},{0x65,0x59,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x66},{0xaa,0x56,0x99,0x6a},{0xaa,0xaa,0xaa,0xa8}},{{0x94,0x22,0x85,0x51},{0x6a,0xaa,0x20,0x95},{0x55,0x59,0x55,0x55},{0x55,0x55,0x56,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x66,0x56,0x95,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x96,0x2a,0x65,0x01},{0xa2,0x8a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x96,0xa9,0x50,0x01},{0xa6,0x0a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x45,0x55,0x55,0x4a},{0x55,0x55,0x55,0x55},{0x66,0x96,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x90,0x01},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x52},{0x65,0x54,0x01,0x2a},{0x65,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x56,0xa0,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x64},{0x66,0x6a,0xa9,0x50},{0x55,0x55,0x55,0x64},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x45,0x50,0x00,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x6a,0x60,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x56},{0x55,0x5a,0x95,0x5a},{0x55,0x15,0x55,0x20},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0xa9,0x50,0x05},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x59,0x65,0x6a,0xa6},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x41,0x50,0x15,0x6a},{0x45,0x54,0x55,0x91},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x50,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x65,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x54,0x10,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x55,0x50,0x15},{0x55,0x55,0x55,0x55},{0x6a,0xa2,0xaa,0xa2},{0x52,0xa6,0x65,0x92},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xa2},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x84,0x50,0x05,0x0a},{0x40,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xa5,0x50,0x15,0x48},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x45},{0x00,0x00,0x00,0x00},{0x81,0x51,0x11,0x68},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x45,0x55,0x55,0x44},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_8 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_8_data[0] };
-const uint8_t epd_wp_ed047tc2_5_9_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x0a,0x82,0x02,0x00},{0x40,0x00,0x00,0x00},{0x00,0x80,0x02,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,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x0a,0x8a,0x82,0x00},{0x40,0x08,0x00,0x40},{0x00,0x80,0x22,0x08},{0x00,0x08,0x08,0x08},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x04,0x00,0x00},{0x11,0x40,0x20,0x00},{0x81,0x00,0x00,0x20},{0x28,0x08,0x00,0x82},{0x00,0x20,0x80,0x80},{0x00,0x00,0x02,0x80}},{{0x80,0x00,0x00,0x00},{0x6a,0x8a,0x8a,0x00},{0x90,0x08,0x01,0x40},{0x00,0x80,0x22,0x08},{0x00,0x28,0x88,0x0a},{0x80,0x08,0x00,0x00},{0x00,0x08,0x02,0x00},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x80,0x00},{0x14,0x14,0x00,0x00},{0x21,0x50,0x20,0x80},{0x81,0x18,0x00,0xa0},{0x29,0x0a,0x02,0x81},{0x2a,0xa2,0xaa,0xa0},{0x00,0x2a,0x02,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xa0,0x08,0x02,0x80},{0x80,0x88,0x22,0x08},{0x20,0xa8,0x89,0x0a},{0x80,0xa8,0x00,0x02},{0xaa,0x8a,0x0a,0x08},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x02},{0x08,0x08,0x80,0x00},{0x24,0x54,0x22,0x80},{0x25,0x52,0x2a,0xa0},{0x86,0xa8,0x20,0xa8},{0xaa,0x2a,0x82,0x81},{0x2a,0xaa,0xaa,0xa0},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xaa,0x8a,0x2a,0x80},{0x80,0x88,0x22,0x08},{0x22,0xaa,0x8a,0x0a},{0x82,0xa8,0x00,0x02},{0xaa,0xaa,0x0a,0x0a},{0x00,0x08,0x02,0x28},{0x00,0x00,0x00,0x02},{0x2a,0x8a,0x80,0x00},{0xa5,0xaa,0xa2,0xa0},{0x26,0x96,0xaa,0xa0},{0x8a,0xa8,0xa0,0xa8},{0xaa,0x2a,0x8a,0x81},{0x2a,0xaa,0xaa,0xa8},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x0a},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0x2a,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x00,0x02},{0x2a,0xaa,0x80,0x00},{0xa9,0xaa,0xa2,0xa0},{0x26,0xa6,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0x2a,0x8a,0x41},{0xaa,0xaa,0xaa,0xa8},{0x08,0xaa,0x12,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x29},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0xaa,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x08,0x80},{0x2a,0xaa,0x8a,0x22},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x12,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x02},{0xaa,0xaa,0xaa,0x09},{0x20,0x08,0x02,0x28},{0x00,0x02,0x0a,0xa0},{0x2a,0xaa,0x8a,0x2a},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x11,0x44}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x81,0x88,0xa2,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0x8a,0x02,0x28},{0x00,0x82,0xaa,0xa1},{0x2a,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0x91,0x44}},{{0x80,0x00,0x00,0x20},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0x80},{0x82,0x88,0xaa,0x24},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x82,0x04},{0x20,0xa2,0xaa,0xa1},{0x2a,0xaa,0xaa,0x29},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x55},{0x96,0xa5,0x65,0x55},{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0x91,0x44}},{{0x80,0x00,0x00,0x10},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x9a,0x14},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x21},{0xaa,0xaa,0xaa,0x85},{0x2a,0xaa,0x8a,0x15},{0x20,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0x25},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0xaa,0x55},{0x96,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x56},{0x2a,0x99,0x91,0x44}},{{0x80,0x00,0x00,0x94},{0xaa,0xa9,0x45,0x44},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x99,0x16},{0xaa,0xa6,0xa6,0x95},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa9,0xa5},{0xaa,0xaa,0xa9,0x95},{0x2a,0xaa,0xaa,0x69},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0x55,0x56},{0x1a,0x95,0x99,0x04}},{{0x80,0x00,0x00,0x64},{0xa9,0x65,0x45,0x48},{0xaa,0xaa,0xa9,0xa2},{0xa2,0x6a,0x99,0x15},{0xaa,0xa5,0x65,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa5,0xa5},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x59},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x99,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x99,0x55,0x55},{0x19,0x55,0x89,0x04}},{{0x40,0x00,0x00,0xa4},{0xa5,0x65,0x45,0x4a},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x6a,0x99,0x15},{0xa9,0x95,0x65,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa5,0x95,0xa5},{0xaa,0xa6,0xa9,0x95},{0xaa,0xaa,0xa6,0x55},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x59,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x99,0x55,0x55},{0x15,0x55,0x49,0x14}},{{0x40,0x00,0x00,0x54},{0xa5,0x65,0x45,0x88},{0xaa,0xaa,0xa9,0xa1},{0xaa,0x66,0x11,0x15},{0xa9,0x55,0x65,0x55},{0xaa,0x96,0xa9,0x95},{0xa5,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x15},{0xaa,0xaa,0x95,0x55},{0x26,0xa5,0x65,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0x40,0x00,0x00,0x55},{0xa5,0x55,0x46,0x89},{0xaa,0xa6,0xa5,0x61},{0xaa,0x66,0x51,0x15},{0x95,0x55,0x55,0x55},{0x28,0x56,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x55},{0xaa,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0xa0,0x00,0x00,0x55},{0x95,0x56,0x8a,0x99},{0xaa,0xaa,0x9a,0x51},{0xaa,0x66,0x55,0x95},{0x95,0x55,0x55,0x55},{0x29,0x55,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa5,0x45,0x55},{0xaa,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0xa0,0x00,0x00,0x55},{0x9a,0x9a,0x8a,0x65},{0xaa,0xa5,0x56,0x51},{0x6a,0x56,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x96},{0x95,0x55,0x55,0x55},{0x05,0x55,0x45,0x14}},{{0xa0,0x00,0x20,0x51},{0x5a,0xaa,0x8a,0x65},{0xa5,0x65,0x56,0x59},{0x69,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x85,0x55,0x45,0x10}},{{0x60,0x28,0xa0,0x51},{0x6a,0xaa,0x8a,0x65},{0x95,0x55,0x56,0x55},{0x59,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x84,0x55,0x44,0x10}},{{0x6a,0xaa,0xa8,0x11},{0x6a,0xaa,0x8a,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x45,0x44,0x10}},{{0x5a,0xaa,0x64,0x01},{0xa6,0x99,0x45,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x44,0x46,0x10}},{{0x5a,0x95,0x56,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x99,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x56,0x5a,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x95},{0x95,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x65,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x25,0x6a,0x99,0x01},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x65},{0x56,0x5a,0x56,0x56},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x65},{0x95,0x55,0x41,0x56},{0x95,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x5a,0x66,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0xaa,0x56,0x05},{0x55,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x95,0x61},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x45},{0x55,0x55,0x55,0x59},{0x55,0x55,0x54,0x55},{0x55,0x54,0x00,0x15},{0x91,0x55,0x15,0x42},{0x55,0x55,0x24,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0x95,0x56,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x65,0x49,0x91},{0x55,0x55,0x54,0x44},{0x55,0x55,0x55,0x49},{0x15,0x55,0x55,0x54},{0x55,0x51,0x54,0x0a},{0x55,0x04,0x00,0x2a},{0xaa,0xaa,0xaa,0xaa},{0x55,0x54,0x10,0x55},{0x65,0x56,0x9a,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xa2,0x1a,0x06,0x50},{0x68,0xa0,0xa8,0xaa},{0x55,0x45,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x04,0x00,0xaa},{0x55,0x55,0x65,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x51,0x05,0x01,0x02},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x6a,0xaa,0xa9,0xa4},{0x55,0x55,0x55,0x00},{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_9 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_9_data[0] };
-const uint8_t epd_wp_ed047tc2_5_10_data[44][16][4] = {{{0x00,0x00,0x00,0x00},{0x80,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x00,0x08,0x02},{0x00,0x80,0x00,0x08},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x02,0x00,0x00,0x00},{0xa2,0x88,0x20,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x80,0x20,0x00},{0x00,0x80,0x00,0x00},{0x00,0x82,0x00,0x00},{0xa8,0x00,0x08,0x82},{0x00,0x80,0x20,0x0a},{0x92,0x00,0x00,0x8a},{0x2a,0x20,0xa2,0xa8},{0x00,0x00,0x00,0x08}},{{0x02,0x00,0x00,0x00},{0xa2,0x8a,0x20,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x08,0x05,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x00,0x80,0x20,0x00},{0x02,0xa0,0xa0,0x00},{0x00,0x82,0x00,0x02},{0xaa,0x20,0x08,0x82},{0x84,0x80,0xa0,0x0a},{0xa2,0x84,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x08}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa0,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x15,0x42,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xa0,0x20,0x80},{0x02,0xaa,0xa8,0x00},{0x00,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x82},{0x9a,0x90,0xa8,0x0a},{0xa6,0xa8,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x00,0x80,0x28}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x1a,0x46,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xaa,0x28,0x80},{0x2a,0xaa,0xa8,0x00},{0x02,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0x08,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x8a,0x88,0x24}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x90},{0x02,0xa0,0x08,0x02},{0x2a,0x2a,0x86,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x80},{0x2a,0xaa,0xa8,0x20},{0x02,0x82,0x00,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0x8a,0x8a,0xa4}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x0a},{0x80,0x00,0x00,0x90},{0x02,0xaa,0x2a,0x02},{0x2a,0xaa,0x8a,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xa2,0xa2,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0xaa,0x4a,0x54}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0x90},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa0},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x16,0xaa,0x46,0x54}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa4},{0x15,0x9a,0x65,0x54}},{{0x82,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0x80,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0x15,0x95,0x65,0x54}},{{0x81,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0xa2,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x8a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x02,0x82,0x20},{0x00,0x0a,0x00,0x09},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0xa8},{0xaa,0xaa,0x9a,0x2a},{0xa2,0xa2,0x02,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x82,0x82,0xa0},{0x00,0x8a,0x80,0x09},{0x2a,0xaa,0xaa,0x22},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0x21},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xa9,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0xa8},{0xaa,0x66,0x9a,0x2a},{0xa2,0xa2,0x22,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0x2a,0xa2,0xa0,0x80},{0x02,0x8a,0x80,0x05},{0x2a,0xaa,0x8a,0x20},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xa0,0x61},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0x94},{0xaa,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x82},{0x02,0x8a,0x82,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xa8,0xaa,0xa1},{0xaa,0xaa,0xa0,0x65},{0xaa,0xaa,0x20,0x85},{0xaa,0xaa,0xaa,0x65},{0xaa,0x95,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x41,0x00,0x40,0x94},{0x69,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xa2,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0x9a},{0xaa,0x28,0xaa,0xa9},{0xaa,0xaa,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x42,0x00,0x48,0xa4},{0x59,0x55,0x55,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xaa,0x25},{0x2a,0xaa,0xaa,0x9a},{0xa8,0x80,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x8a,0x29},{0x2a,0xaa,0x56,0x99},{0xaa,0x28,0xa8,0xa9},{0xaa,0x82,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x42,0x00,0x48,0x64},{0x59,0x59,0x65,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xa0,0x65},{0x2a,0xaa,0xa9,0x56},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0xa9,0x8a},{0xaa,0xaa,0xaa,0x05},{0xaa,0x2a,0x86,0x69},{0x2a,0x55,0x55,0x99},{0xaa,0x69,0x89,0xa9},{0x96,0x82,0x00,0x45},{0xaa,0x22,0x10,0x05},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x62,0x00,0x4a,0x54},{0x59,0x9a,0xa9,0x95},{0xaa,0xaa,0x22,0x65},{0x82,0xaa,0xa5,0x45},{0x26,0xaa,0xa9,0x55},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0x29,0x89},{0xaa,0xaa,0xaa,0x85},{0xaa,0x55,0x54,0x69},{0x21,0x55,0x55,0x55},{0xaa,0x69,0x45,0xa9},{0x95,0x55,0x55,0x55},{0xaa,0x22,0x10,0x05},{0x89,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0xa2,0x00,0x8a,0x54},{0x66,0xaa,0xaa,0x95},{0xaa,0xaa,0x22,0x55},{0x82,0x95,0x55,0x55},{0x16,0xa5,0x55,0x55},{0xa2,0xa0,0x20,0x09},{0xaa,0xa9,0x29,0x09},{0xaa,0xaa,0xaa,0x85},{0xa9,0x55,0x55,0x59},{0x11,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa1,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x54}},{{0xa2,0x00,0x86,0x54},{0xa6,0xaa,0xaa,0xa5},{0xaa,0xaa,0x22,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x5a,0xa9,0x55},{0xa2,0xaa,0x28,0x01},{0xaa,0xa9,0x29,0x55},{0xaa,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x55,0x55,0x54}},{{0xa1,0x00,0x85,0x54},{0xaa,0xa2,0xaa,0x65},{0xaa,0xaa,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x15,0xa5,0x55,0x55},{0xa2,0xaa,0xa8,0x01},{0xaa,0xa9,0x69,0x55},{0xaa,0xa5,0x69,0xa5},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x45,0x55,0x54}},{{0xa1,0x00,0x85,0x54},{0x9a,0x95,0x55,0x55},{0xaa,0x99,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa2,0xa9,0x55,0x55},{0xaa,0xa5,0x69,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x85,0x54}},{{0x61,0x00,0x45,0x54},{0x95,0x55,0x55,0x55},{0xaa,0x99,0x61,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa5,0x55,0x55,0x55},{0xaa,0x65,0x55,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x89,0x94}},{{0x61,0x00,0x45,0x50},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0xaa,0x8a,0xa8}},{{0x61,0x00,0x45,0x10},{0x15,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xa8}},{{0x51,0x20,0x41,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x16,0x6a,0x94,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x50,0x2a,0x40,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x2a,0x00,0x01},{0x55,0x55,0x55,0x55},{0x51,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x28,0xa9,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x28,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x24,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x99},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x99},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x9a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x14,0x6a,0x20,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x65},{0x55,0x14,0x54,0x56},{0x41,0x55,0x55,0x56},{0x55,0x55,0x55,0x5a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x14,0x6a,0x10,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x11},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x15},{0x6a,0xaa,0xaa,0x99},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x96,0x10,0x05},{0x55,0x55,0x55,0x19},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x21},{0xa9,0x55,0x56,0xa5},{0x55,0x55,0x55,0x55},{0x66,0xa9,0x69,0x54},{0x55,0x50,0x14,0x1a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x95,0x10,0x45},{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x65},{0x6a,0x6a,0x9a,0x11},{0x95,0x55,0x55,0x55},{0x69,0x55,0x55,0x59},{0x51,0x56,0x16,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x55,0x10,0x55},{0x00,0x00,0x00,0x00},{0x55,0x65,0x56,0x54},{0x55,0x15,0x45,0x02},{0x80,0x00,0x00,0x0a},{0x55,0x55,0x55,0x16},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x15,0x55},{0x00,0x00,0x00,0x00},{0x59,0x55,0x55,0x14},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x65,0x45,0x54,0x0a},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_10 = { .phases = 44, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_10_data[0] };
-const uint8_t epd_wp_ed047tc2_5_11_data[57][16][4] = {{{0x20,0x8a,0x80,0x00},{0x15,0x55,0x5a,0xa4},{0x44,0x10,0x0a,0x41},{0x40,0x00,0x09,0x54},{0x10,0x50,0x00,0x00},{0x00,0x00,0x04,0x28},{0x40,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x40,0x00},{0x00,0x00,0x00,0x00},{0x00,0x40,0x00,0x68},{0x00,0x00,0x40,0x00},{0x00,0x00,0x0a,0x54},{0x00,0x0a,0x80,0x00},{0x10,0x09,0x60,0x00},{0x00,0x00,0x00,0x50}},{{0xaa,0xaa,0x8a,0x00},{0x0a,0x60,0x0a,0xa8},{0x54,0x54,0x8a,0x41},{0x41,0x02,0x09,0x54},{0x15,0x50,0x06,0x24},{0x00,0x08,0xa4,0x28},{0x44,0x00,0x09,0xa8},{0x05,0x00,0x2a,0xa8},{0x01,0x10,0x46,0xa8},{0x04,0x00,0x00,0xa8},{0x00,0x40,0x00,0x54},{0x04,0x00,0x44,0xa8},{0x00,0x00,0x8a,0x54},{0x00,0x0a,0x8a,0x58},{0x50,0x19,0x65,0x54},{0x00,0x00,0x00,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x6a,0xaa,0xa8},{0x55,0x94,0x89,0x55},{0x41,0x02,0x09,0x54},{0x15,0x50,0x66,0x24},{0x40,0x04,0xa4,0x68},{0x44,0x0a,0x09,0x54},{0x05,0x08,0x55,0x54},{0x11,0x14,0x56,0x54},{0x04,0x40,0x00,0x58},{0x01,0x40,0x0a,0x54},{0x04,0x0a,0x44,0xa8},{0x01,0x00,0x8a,0x54},{0x00,0x0a,0x6a,0x54},{0x50,0x19,0x65,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x2a,0xaa,0xa8},{0x96,0x95,0x55,0x55},{0x51,0x0a,0x05,0x54},{0x15,0x50,0x66,0xa4},{0x40,0x04,0x54,0x54},{0x44,0x05,0x09,0x54},{0x05,0x18,0x55,0x54},{0x51,0x14,0x56,0x54},{0x04,0x40,0x02,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x58},{0x01,0x0a,0x85,0x54},{0x01,0x05,0x65,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x96,0xa5,0x55,0x55},{0x51,0x09,0x05,0x55},{0x15,0x50,0x65,0x94},{0x44,0x14,0x54,0x54},{0x54,0x15,0x95,0x54},{0x05,0x56,0x55,0x54},{0x51,0x14,0x55,0x54},{0x14,0x40,0x82,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x54},{0x01,0x0a,0x45,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x49,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x14,0x55,0x55},{0x14,0x40,0x8a,0x54},{0x01,0x40,0x85,0x54},{0x04,0x15,0x44,0x54},{0x01,0x0a,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x55,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0xa9,0x54},{0x01,0x40,0x45,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0x69,0x55},{0x01,0x40,0x65,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x55,0x54},{0x01,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x52,0x55,0x54},{0x54,0x14,0x56,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x65,0x55},{0x01,0x50,0x65,0x55},{0x04,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x92,0x55,0x55},{0x55,0x14,0x56,0x54},{0x54,0x55,0x55,0x55},{0x45,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x91,0x55,0x15,0x55},{0x16,0x92,0x55,0x55},{0x55,0x14,0x56,0x55},{0x54,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0x92,0x55,0x95,0x55},{0x6a,0x91,0x55,0x55},{0x55,0x54,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x05,0x15,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0x91,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x4a,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x4a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0xa1,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa9,0x15,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0xa5,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x95,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0x99,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0x56,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x55,0x55,0x55},{0x15,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x05,0x55,0x55},{0xa9,0x66,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x55},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0xa9,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x15,0x45,0x55,0x55},{0x11,0x55,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x15,0x55,0x55},{0xa9,0x66,0x95,0x55},{0x00,0x10,0x55,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x96},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x55,0x55,0x55},{0x5a,0x95,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x19,0x45,0x55,0x55},{0x11,0x95,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x66,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x9a,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x96},{0xaa,0xa6,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x5a,0xa5,0x55,0x55},{0xaa,0x65,0x55,0x55},{0x29,0x85,0x55,0x55},{0x12,0x95,0x55,0x55},{0x59,0x55,0x56,0x55},{0x56,0x15,0x55,0x55},{0xa6,0x15,0x55,0x55},{0xaa,0x6a,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x95,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x9a,0xa5,0x55,0x55},{0xaa,0x69,0x95,0x55},{0x2a,0x85,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x55,0x95,0x55},{0x56,0x15,0x55,0x55},{0xaa,0x1a,0x95,0x55},{0xaa,0x6a,0xaa,0xa9},{0x00,0x15,0x55,0x54}},{{0x55,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0xa9},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0xa9,0x55},{0xa9,0xaa,0x56,0x55},{0xaa,0xa5,0x95,0x55},{0xaa,0x69,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x1a,0xaa,0xa5},{0xaa,0xaa,0xaa,0xa9},{0x20,0x95,0x55,0x54}},{{0x55,0x55,0x8a,0x00},{0xaa,0xaa,0xa5,0x5a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0x99,0x59},{0xaa,0xa8,0xa9,0x55},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0x6a,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0xa6,0x15,0x55,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x5a,0x8a,0x00},{0xaa,0xaa,0x55,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0x9a,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x6a,0x8a,0x00},{0xaa,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xa9,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0xa5,0x55,0x95},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0xaa,0x8a,0x00},{0xa9,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x95,0x55,0x55},{0x66,0xa5,0x55,0xa9},{0xaa,0xaa,0x99,0x55},{0xaa,0x2a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x12,0x45,0x55,0x54}},{{0x6a,0xaa,0x8a,0x00},{0xa5,0x55,0xa5,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0x95,0x55,0xa5},{0xa6,0xa5,0x9a,0xa9},{0xaa,0xaa,0x99,0xa5},{0xaa,0x2a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x41,0x55,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x95,0x6a,0xa5,0x56},{0xaa,0x69,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0x96,0xa9},{0xa6,0xa5,0xaa,0xaa},{0xaa,0xaa,0x99,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x85,0x00},{0x55,0x6a,0xa5,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xa9,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0xaa,0xaa},{0xaa,0xa5,0xaa,0xaa},{0xaa,0xaa,0xa9,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x45,0x00},{0x5a,0x6a,0x55,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x99,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x40,0x02,0xa0}},{{0xaa,0xa5,0x45,0x00},{0x6a,0x55,0x55,0x56},{0x69,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x40,0x02,0xa8}},{{0xaa,0x55,0x45,0x00},{0x6a,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0xa5,0x55,0x45,0x00},{0x66,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x55,0x95,0x55,0x55},{0x55,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x5a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x99,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x55,0x69},{0x69,0x6a,0xaa,0xaa},{0xaa,0x5a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0xa9,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x5a,0xa9,0xaa},{0xa5,0x6a,0xaa,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x0a,0xa8}},{{0x55,0x55,0x40,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0xa9,0xaa},{0x95,0x6a,0x66,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa8}},{{0x55,0x50,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x99,0xaa},{0x55,0x46,0x66,0xaa},{0xa8,0x6a,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa8}},{{0x50,0x00,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x95,0x56},{0x55,0x45,0x55,0xa6},{0x65,0x96,0x96,0xaa},{0x26,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x08,0x28,0xaa,0xa8}},{{0x00,0x00,0x00,0x60},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x55,0xa6},{0x55,0x96,0x66,0xaa},{0x2a,0x4a,0xaa,0xaa},{0xaa,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x88,0x2a,0xaa,0xa8}},{{0x00,0x00,0x20,0x50},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x66,0x6a},{0x12,0x86,0xaa,0xaa},{0x85,0x4a,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0xa8,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x61,0x09,0x55,0x55},{0x45,0x55,0x55,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x98,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x99,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x56,0xaa},{0x94,0x6a,0xaa,0xaa},{0x56,0x65,0x55,0x55},{0xa6,0x55,0x66,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x25,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x95,0x55,0x55},{0xa9,0x8a,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x05,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xa4,0x6a,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x01,0x50,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
-const EpdWaveformPhases epd_wp_ed047tc2_5_11 = { .phases = 57, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ed047tc2_5_11_data[0] };
-const EpdWaveformPhases* epd_wm_ed047tc2_5_ranges[7] = { &epd_wp_ed047tc2_5_5,&epd_wp_ed047tc2_5_6,&epd_wp_ed047tc2_5_7,&epd_wp_ed047tc2_5_8,&epd_wp_ed047tc2_5_9,&epd_wp_ed047tc2_5_10,&epd_wp_ed047tc2_5_11 };
+const uint8_t epd_wp_ED047TC2_5_5_data[46][16][4] = {{{0x00,0x00,0x00,0x00},{0x20,0x88,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x80,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x08,0x00},{0x00,0x02,0x00,0x80},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa2,0x88,0x20,0x88},{0x22,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x00,0x44,0x08,0x00},{0xa0,0x02,0x20,0xa8},{0x08,0x62,0x88,0x80},{0x00,0x00,0x00,0x08},{0x08,0x22,0x88,0x80},{0x00,0x80,0x00,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x04,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x24,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x80,0x82,0xa2,0x08},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x02},{0x84,0x84,0x28,0x80},{0xa0,0x02,0x20,0xaa},{0xa8,0xaa,0x8a,0x80},{0x22,0x84,0x00,0x28},{0x2a,0xaa,0xaa,0xa0},{0x00,0x80,0x28,0x00}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x08,0x00,0x80,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x00,0x20,0x02},{0x00,0x00,0x00,0x02},{0x84,0x88,0x2a,0xa2},{0xa0,0xaa,0xa8,0xa8},{0xa8,0xaa,0x8a,0x80},{0x2a,0xaa,0x08,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x08}},{{0xaa,0xaa,0xa8,0xa8},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0x24,0x80,0x00},{0x00,0x00,0x00,0x00},{0x29,0x80,0x00,0x00},{0x00,0x40,0x20,0x00},{0x80,0xa2,0xa2,0x88},{0x00,0x02,0xa0,0x00},{0x02,0x00,0x00,0x81},{0x88,0xa8,0xaa,0xa9},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0x8a,0x81},{0x2a,0xaa,0x2a,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x80,0x28,0x04}},{{0xaa,0xaa,0xa8,0xa4},{0x2a,0xaa,0xaa,0x02},{0x00,0x08,0x00,0x00},{0x28,0xa8,0x80,0x00},{0x00,0x20,0x00,0x00},{0x2a,0x84,0xa0,0x08},{0x2a,0x68,0x20,0x80},{0x80,0xa2,0xa2,0xa8},{0x80,0x02,0xa0,0x01},{0x02,0x80,0x00,0xa9},{0x9a,0xa8,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x89},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xa8},{0x22,0x8a,0x28,0x04}},{{0xaa,0xaa,0xa8,0x64},{0x2a,0xaa,0xaa,0x01},{0x00,0x88,0x02,0x00},{0x29,0xa8,0x80,0x00},{0x00,0x28,0x08,0x02},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xa2,0xa2,0xa9},{0x80,0x02,0xa0,0x01},{0x02,0xa0,0x00,0xa9},{0x9a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x2a,0x8a,0xa8,0x84}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x00,0x8a,0x02,0x08},{0x2a,0xa8,0x88,0x00},{0x00,0x28,0x8a,0x01},{0x2a,0x88,0xa8,0x08},{0x2a,0xaa,0xa0,0xa0},{0xaa,0xaa,0xaa,0xa9},{0x80,0x02,0xa0,0x01},{0x0a,0xaa,0x80,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xa8,0x54},{0x2a,0xaa,0xaa,0x01},{0x20,0x8a,0x0a,0x08},{0x2a,0xa8,0xaa,0x00},{0x00,0x2a,0x8a,0x01},{0x2a,0xaa,0xa8,0x08},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x80,0x02,0xa0,0x81},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x59},{0x69,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa0,0x8a,0x0a,0x0a},{0xaa,0xaa,0xaa,0x02},{0x08,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x09},{0x2a,0xaa,0xa0,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x82,0x82,0xa0,0xa1},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0x59,0x8a,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0xaa,0x01},{0xa2,0x8a,0x2a,0x09},{0xaa,0xaa,0xaa,0x09},{0x28,0x2a,0x8a,0x01},{0x2a,0xaa,0xaa,0x89},{0x2a,0xaa,0xa8,0xa1},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0xa0,0xa9},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x54}},{{0xaa,0xaa,0xaa,0x58},{0x2a,0xaa,0xa5,0x05},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x01},{0x2a,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x01},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0xa9},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x59,0xaa,0xaa,0x54}},{{0xaa,0xaa,0x96,0xa8},{0xaa,0xaa,0x55,0x09},{0xaa,0x8a,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0x21},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x98,0xa9},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa4,0x55},{0xaa,0xa8,0x8a,0x55},{0xaa,0xaa,0xa5,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x54,0xaa,0xaa,0x54}},{{0xaa,0xa5,0x96,0xa8},{0xaa,0xa5,0x55,0xa9},{0xaa,0xaa,0xaa,0x09},{0xaa,0xaa,0xaa,0x09},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xa8,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x90,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0xaa,0x55},{0xa6,0x99,0x55,0x55},{0x94,0xaa,0xa6,0x50}},{{0xaa,0xa5,0x56,0xa8},{0xaa,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xa9,0x15,0x55},{0x92,0x95,0x65,0x55},{0xaa,0xaa,0xa5,0x55},{0x95,0x95,0x55,0x55},{0x94,0xaa,0x96,0x00}},{{0xa9,0x55,0x56,0xa8},{0xa9,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0x05},{0xaa,0xaa,0xaa,0xa5},{0x2a,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x98,0x51},{0xaa,0xa9,0x59,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x9a,0x85,0x55,0x55},{0x94,0x95,0x55,0x55},{0x99,0xa9,0x95,0x55},{0x95,0x55,0x55,0x55},{0x94,0xaa,0x96,0x00}},{{0x95,0x55,0x56,0xa8},{0xa5,0x55,0x5a,0xa5},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0xa5},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0x96,0x65},{0xaa,0xaa,0x1a,0x59},{0xaa,0x59,0x51,0x55},{0xaa,0xa9,0x5a,0x55},{0xaa,0xaa,0xaa,0x55},{0xa8,0x55,0x55,0x55},{0x98,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x94,0x6a,0x96,0x00}},{{0x95,0x55,0x55,0x94},{0x95,0x55,0xaa,0x95},{0xaa,0xa6,0xaa,0x05},{0xaa,0xaa,0x6a,0x95},{0x2a,0xaa,0xa5,0x55},{0x9a,0x6a,0x55,0x55},{0xaa,0x85,0x5a,0x55},{0xaa,0x59,0x55,0x55},{0xaa,0xa9,0x5a,0x55},{0xa8,0xaa,0x00,0x55},{0xa8,0x55,0x55,0x55},{0x91,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x90,0x69,0x95,0x00}},{{0x55,0x55,0x55,0x54},{0x96,0x5a,0xaa,0x15},{0xaa,0xa6,0xa9,0x05},{0xaa,0x9a,0x65,0x55},{0x2a,0x96,0x65,0x55},{0x96,0x65,0x55,0x55},{0xa1,0x95,0x56,0x55},{0x28,0x55,0x55,0x55},{0xaa,0xa9,0x52,0x55},{0xa9,0x01,0x05,0x55},{0x25,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x55,0x55,0x69,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa6,0xa5,0x85},{0x9a,0x56,0x55,0x55},{0xaa,0x95,0x65,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0xa1,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x55,0x5a,0xa9,0x55},{0x9a,0xaa,0xaa,0x55},{0xaa,0xa5,0xa5,0x85},{0x92,0x55,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x15,0x56,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa0,0x65,0x55,0x00}},{{0x56,0xaa,0xa9,0x55},{0x99,0xaa,0xa1,0x55},{0xaa,0x65,0x95,0x45},{0x95,0x55,0x55,0x55},{0xa6,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x54,0x55},{0x55,0x55,0x55,0x55},{0x05,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x00}},{{0x6a,0xaa,0xaa,0x55},{0x95,0xaa,0x15,0x55},{0x9a,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa0,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0xa5,0x55,0x55},{0x99,0x65,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa8,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x15,0x65,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x55,0x00}},{{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0x55,0x41,0x00}},{{0xaa,0xaa,0x56,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x56},{0x55,0x55,0x55,0x55},{0x69,0x55,0x55,0x55},{0xaa,0x55,0x41,0x00}},{{0xa9,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x55,0x55,0x96},{0x65,0x55,0x55,0x56},{0x6a,0x65,0x55,0xa6},{0xaa,0x94,0x49,0x00}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x6a,0x2a,0x8a,0xaa},{0x6a,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x51,0x56},{0x65,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x40,0xaa},{0x55,0x54,0x45,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x56,0xa6,0x50},{0x55,0x56,0x95,0x56},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x95,0x55,0x55},{0x55,0x55,0x95,0x04},{0x45,0x05,0x55,0xaa},{0x55,0x55,0x55,0xaa},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x45,0x48,0x58,0x50},{0x55,0x55,0x41,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x54,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x54},{0x41,0x04,0x44,0x12},{0x6a,0x2a,0x21,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x69},{0x55,0x55,0x55,0x54},{0x45,0x05,0x15,0x16},{0x41,0x41,0x15,0x02},{0x6a,0x00,0xa0,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x66},{0x55,0x59,0x59,0xa6},{0x60,0x00,0x00,0x0a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x6a,0x59,0x51,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x50,0x55,0x55,0x52},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x6a,0x55,0x55,0x02},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xa5,0x96,0xa6,0x5a},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_5 = { .phases = 46, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_5_data[0] };
+const uint8_t epd_wp_ED047TC2_5_6_data[43][16][4] = {{{0x02,0xaa,0x00,0x00},{0x20,0x22,0xa8,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x00,0x22,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xa8,0x20},{0x00,0x00,0x00,0x00},{0x20,0x02,0x08,0x80},{0x00,0x80,0x00,0x00},{0x20,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x2a,0xaa,0x00,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x28},{0x00,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x20,0x22,0xaa,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x20},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa0,0x20,0x2a},{0x28,0x22,0xa8,0xa8},{0x28,0x00,0x00,0x00}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0x22,0x02,0x08,0x80},{0x00,0xa8,0x22,0x2a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x80}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0x80},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x22,0x2a,0xaa,0xa0},{0x00,0x00,0x00,0x00},{0xa2,0x82,0x08,0x80},{0x08,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x40}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x20},{0x20,0x00,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x2a,0x2a,0xaa,0xa8},{0x00,0x00,0x00,0x00},{0xaa,0x82,0x88,0xa0},{0x8a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0x94},{0x24,0x00,0x28,0x40}},{{0xaa,0xaa,0x20,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x20,0x88,0x00,0x2a},{0x20,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0x20,0x80,0x00,0x02},{0xaa,0x2a,0xaa,0x80},{0x80,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0x8a,0x8a,0xa0},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x24,0x00,0x28,0x40}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x80},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x22,0x80,0x00,0x00},{0x00,0x00,0x00,0x28},{0xa0,0xa0,0xa8,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0x2a,0xaa,0xa8},{0x08,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa5},{0xa6,0xaa,0xaa,0x95},{0x24,0x00,0x26,0x40}},{{0xaa,0xaa,0xa0,0x00},{0x20,0xaa,0xaa,0x42},{0x80,0x00,0x00,0x22},{0x20,0x88,0x00,0x2a},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xa2,0xa8,0xaa,0x02},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xa8},{0x08,0x00,0x00,0x20},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa6,0x55},{0x56,0x02,0x95,0x54}},{{0xaa,0xaa,0xa0,0x04},{0x20,0xaa,0xa5,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x26},{0x2a,0x80,0x00,0x02},{0x20,0x80,0x20,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x82},{0x80,0x00,0x00,0x01},{0x20,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0x98},{0x88,0x80,0x00,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xa5,0xa9,0x65,0x55},{0x56,0x0a,0x95,0x54}},{{0xaa,0xa9,0xa0,0x24},{0x20,0xa9,0x55,0x4a},{0x80,0x00,0x00,0x29},{0xa0,0x88,0x00,0x25},{0x2a,0x80,0x00,0x02},{0x20,0xa0,0x28,0x28},{0xaa,0xaa,0xaa,0x01},{0xaa,0x2a,0xaa,0x80},{0xa0,0x00,0x00,0x01},{0x20,0xa2,0xa8,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xa2,0xa8,0xaa},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xa5,0x95,0x55,0x55},{0x56,0x0a,0x95,0x54}},{{0xaa,0x95,0xa8,0xa4},{0x20,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x29},{0xa2,0x88,0x00,0x15},{0x2a,0x80,0x00,0x01},{0x20,0xa8,0x28,0x14},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x81},{0xa0,0x00,0x00,0x01},{0xa2,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x94},{0x88,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x56,0x89,0x55,0x54}},{{0xaa,0x95,0x98,0x94},{0xa0,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x25},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0x20,0xaa,0xa8,0x94},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0xa1},{0xa0,0x22,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x94},{0xa8,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0xa9,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x14}},{{0xa9,0x55,0x9a,0x98},{0xa8,0xa9,0x55,0x45},{0xa0,0x00,0x00,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x00,0x21},{0xa2,0xaa,0xaa,0x94},{0xaa,0xaa,0xaa,0x89},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x2a,0xa0,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x56},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0xa6,0x55},{0xaa,0xaa,0x95,0x55},{0x95,0x55,0x55,0x55},{0x55,0xa5,0x55,0x14}},{{0xa5,0x55,0x5a,0xa8},{0xa8,0x95,0x55,0x45},{0xa0,0x82,0x20,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x85,0x69},{0xaa,0x2a,0xa8,0x29},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xa9,0xa9,0xa5,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0xa5,0x41,0x14}},{{0x95,0x55,0x6a,0x68},{0xa8,0x55,0x55,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0x88,0x00,0x15},{0xaa,0x80,0x20,0x21},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xa9,0x55,0x69},{0xaa,0x2a,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0x99,0xa9,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x65,0x40,0x14}},{{0x95,0x55,0x66,0x58},{0xa8,0x55,0x5a,0x85},{0xa8,0xaa,0xa0,0x15},{0xaa,0xa8,0xa0,0x15},{0xaa,0x62,0xa8,0x19},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x95},{0xaa,0x95,0x55,0x55},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa9,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x65,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x91,0x55,0x40,0x14}},{{0x95,0x56,0xa5,0x94},{0xa8,0x56,0xaa,0x85},{0xa8,0xaa,0xa0,0x95},{0xaa,0xa8,0xa0,0x15},{0xaa,0x6a,0xaa,0x15},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x55,0x55},{0x89,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0x99,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x50,0x00,0x14}},{{0x55,0x6a,0x89,0x94},{0x98,0x6a,0xaa,0x85},{0xaa,0xaa,0xa0,0x95},{0xaa,0xa6,0xa0,0x15},{0x8a,0x6a,0xaa,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa9,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xaa,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x89,0x50,0x00,0x14}},{{0x56,0xaa,0x9a,0x14},{0x98,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xa2,0x15},{0x99,0x6a,0xaa,0x95},{0xaa,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xa6,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xa9,0x10,0x00,0x04}},{{0x5a,0xaa,0x12,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0xaa,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0xa9,0x10,0x00,0x04}},{{0x6a,0xaa,0x55,0x54},{0xaa,0xaa,0xaa,0x81},{0xaa,0xaa,0xaa,0x95},{0x9a,0x66,0xaa,0x15},{0x95,0x6a,0xaa,0x95},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x8a,0x55,0x55,0x55},{0xaa,0x00,0x00,0x00}},{{0x6a,0xaa,0x55,0x55},{0x9a,0x96,0xaa,0x41},{0x6a,0xaa,0xaa,0x55},{0x99,0x66,0xaa,0x95},{0x95,0x6a,0x95,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x59,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0x99,0x65},{0xaa,0x00,0x00,0x00}},{{0xaa,0xaa,0x55,0x55},{0x96,0x56,0xa5,0x51},{0x6a,0x69,0x8a,0x55},{0x95,0x66,0xaa,0x95},{0x95,0x69,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xaa,0xa8,0x55,0x55},{0x96,0x55,0x55,0x55},{0x6a,0x65,0x58,0x55},{0x95,0x66,0x59,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa9,0x45,0x55,0x45},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x00,0x00,0x00}},{{0xa5,0x55,0x55,0x41},{0x96,0x55,0x55,0x55},{0x56,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x5a,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x95,0x55,0x55,0x41},{0x56,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x45,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x56,0x59,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x2a},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x51},{0x59,0x55,0x55,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x51},{0x55,0x55,0x55,0x56},{0x55,0x15,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x00,0x15},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0x6a,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x10,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x42},{0x6a,0x95,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x59},{0x15,0x55,0x55,0x82},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x55},{0x99,0x50,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x51,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0xaa,0x99,0x55,0x6a},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_6 = { .phases = 43, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_6_data[0] };
+const uint8_t epd_wp_ED047TC2_5_7_data[40][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x04,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x0a,0x08,0x80},{0x00,0x00,0x00,0x08},{0x00,0x80,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa0,0x80,0x00,0x00},{0x08,0x80,0x20,0x00},{0x00,0x12,0x22,0x00},{0x00,0x00,0x00,0x00},{0x1a,0x20,0x00,0x00},{0x01,0x80,0x00,0x00},{0x88,0x00,0x00,0x00},{0x00,0x10,0x80,0x00},{0x20,0x0a,0x88,0x82},{0x80,0x00,0x05,0x08},{0x0a,0xa0,0x00,0x20},{0x20,0x00,0x00,0x20},{0x00,0x80,0x00,0x08},{0x80,0x28,0x08,0x80},{0x2a,0x80,0xa0,0x28},{0x20,0x00,0x80,0x04}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x11,0x22,0xa2,0x00},{0x04,0x04,0x00,0x00},{0x2a,0xa0,0x20,0x00},{0x22,0xa0,0x00,0x00},{0x98,0x12,0x00,0x0a},{0x18,0xa0,0x80,0x00},{0x28,0x0a,0x8a,0x82},{0x88,0x88,0x09,0x28},{0x0a,0xa2,0x20,0x20},{0x20,0x00,0x02,0xa0},{0x00,0xa4,0x00,0x08},{0xa8,0xa8,0xa8,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x20,0x02,0x88,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0x80,0x20,0x00},{0x22,0x22,0xa2,0x28},{0x04,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x20,0x0a},{0x98,0x56,0x02,0x8a},{0xa8,0xa4,0x80,0x00},{0x28,0x0a,0xaa,0x82},{0x88,0xaa,0x0a,0x28},{0x2a,0xaa,0xa8,0x22},{0x20,0x40,0xa2,0xa2},{0x12,0xa8,0xa0,0x28},{0xa8,0xaa,0xaa,0xa0},{0xaa,0xaa,0xaa,0xa8},{0x28,0x82,0xa8,0x84}},{{0xa8,0xa0,0x00,0x00},{0x08,0xa0,0x20,0x00},{0x26,0x22,0xa2,0x28},{0x05,0x08,0x00,0x00},{0x2a,0xa0,0x28,0x00},{0x2a,0xa0,0x28,0x0a},{0x99,0xaa,0x82,0x8a},{0xaa,0xa8,0xa2,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0x28},{0x2a,0xaa,0xa8,0xa2},{0x20,0xa6,0xa2,0xa2},{0x92,0xaa,0xa8,0x28},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x98},{0x58,0x8a,0xa8,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xa0,0x20,0x00},{0x2a,0x66,0xa2,0x28},{0x09,0x0a,0x00,0x00},{0x2a,0xa2,0x28,0x00},{0x2a,0xa0,0xa8,0x0a},{0xa9,0xaa,0x82,0x8a},{0xaa,0xaa,0xaa,0x00},{0x28,0x8a,0xaa,0x82},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa2},{0x25,0xa6,0xaa,0xa2},{0xaa,0xaa,0xa8,0x2a},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0x58,0x8a,0xaa,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0x20,0x80},{0x2a,0xa6,0xa2,0x28},{0x19,0x0a,0x00,0x00},{0x2a,0xa2,0xa8,0x00},{0x2a,0xaa,0xa8,0x89},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x02},{0x2a,0x8a,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x81},{0x2a,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa0,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0x2a,0xaa,0xa8,0x04},{0x2a,0xaa,0xa8,0xa9},{0xaa,0xaa,0x8a,0x89},{0xaa,0xaa,0xaa,0x82},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa4},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0x58,0xaa,0xa9,0x94}},{{0xa8,0xa0,0x00,0x00},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xa2,0x28},{0x9a,0x2a,0x00,0x00},{0xaa,0xaa,0xa8,0x88},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x96},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x95},{0x5a,0xaa,0xa9,0x54}},{{0xa8,0xa0,0x00,0x14},{0x0a,0xaa,0xa8,0x82},{0xaa,0xaa,0xaa,0x28},{0xaa,0x2a,0x00,0x00},{0xaa,0xaa,0xaa,0x99},{0x2a,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0x55,0x55},{0x5a,0xaa,0x69,0x54}},{{0xa8,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x16},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa5,0x55},{0xa9,0xa5,0x55,0x55},{0x9a,0xaa,0x65,0x50}},{{0x98,0x50,0x00,0x14},{0x8a,0xaa,0x9a,0x81},{0xaa,0xaa,0xaa,0x15},{0xaa,0x2a,0x08,0x00},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x85},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x64,0x50}},{{0x98,0x50,0x00,0x28},{0x8a,0x6a,0x9a,0x41},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x18,0x80},{0xaa,0xaa,0x96,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xa9,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xaa,0xa5,0x59},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x80,0x55},{0xaa,0xaa,0xa9,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0xa9,0x54,0x50}},{{0x94,0x50,0x00,0x28},{0xa6,0x55,0x55,0x61},{0xaa,0xaa,0xa9,0x15},{0xaa,0xaa,0x28,0x80},{0xa9,0x9a,0x96,0x95},{0xaa,0xaa,0x96,0x55},{0xaa,0xa9,0x69,0x65},{0xaa,0xaa,0x69,0x95},{0xaa,0xa5,0x65,0x55},{0xaa,0xa6,0x25,0x55},{0xaa,0x01,0x55,0x55},{0xaa,0xaa,0x59,0x55},{0xaa,0x55,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0xa5,0x54,0x40}},{{0x94,0xa0,0x00,0x28},{0xa5,0x55,0x55,0x51},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0xa1},{0xa5,0x59,0x55,0x55},{0xaa,0x5a,0x55,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xaa,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0xa5,0x15,0x55},{0xa9,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x65,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x55,0x59},{0xaa,0xa9,0x59,0x15},{0xaa,0xaa,0x68,0x95},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0xaa,0xa5,0x65,0x55},{0xaa,0x55,0x55,0x55},{0xaa,0xa5,0x55,0x55},{0xaa,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa8,0x65,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x55},{0x8a,0x99,0x59,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0xa5,0x65,0x55},{0xa5,0x55,0x55,0x55},{0x92,0x25,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0xa0,0x00,0x14},{0xa5,0x55,0x65,0x95},{0x89,0x99,0x55,0x15},{0xaa,0xa5,0xaa,0x95},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x25,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x54,0x40}},{{0x64,0x50,0x80,0x15},{0xa5,0x95,0x65,0x95},{0x99,0x95,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x26,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x58,0x5a,0x80,0x15},{0xa9,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0xaa,0x95,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa4,0x55,0x14,0x00}},{{0x98,0x5a,0x80,0x15},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x2a,0x95,0xa5,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0xa6,0x54,0x14,0x00}},{{0x98,0x5a,0x48,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x55,0x55,0x15},{0x25,0x95,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0x55,0x55,0x65},{0xa6,0x54,0x10,0x00}},{{0x9a,0x55,0x68,0x55},{0x6a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x25,0x55,0x95,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x25,0x55,0x55,0x66},{0x2a,0xaa,0xaa,0x6a},{0xa6,0x10,0x00,0x00}},{{0x9a,0x55,0x64,0x41},{0x5a,0xaa,0x9a,0x55},{0x15,0x55,0x55,0x15},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0xa6,0x10,0x08,0x00}},{{0x9a,0x55,0x94,0x81},{0x5a,0x6a,0x9a,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x0a,0x9a,0x81},{0xa6,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x0a,0xa9,0x41},{0xa5,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x15,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x44,0x85,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x0a,0x65,0x41},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x55,0x55,0x69},{0x55,0x55,0x55,0x69},{0x55,0x56,0x11,0x59},{0x55,0x55,0x55,0x61},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x66},{0x65,0x44,0x42,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x51},{0x55,0xaa,0xaa,0x54},{0x45,0x55,0x55,0x56},{0x59,0x59,0x11,0x56},{0x55,0x55,0x14,0x52},{0x55,0x55,0x55,0x55},{0x55,0x51,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x46,0x05,0x55,0x41},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x61},{0x40,0x55,0x55,0x80},{0x6a,0xaa,0xaa,0xaa},{0x55,0x04,0x02,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x59,0x55,0x65,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x40,0x00,0x00,0x42},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x64,0x0a,0x9a,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x45,0x05,0x55,0x55},{0x55,0x55,0x55,0x59},{0x65,0x55,0x55,0x55},{0x55,0x64,0x55,0x41},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x6a,0x2a,0x82,0x2a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x45},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x2a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x44},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x40},{0x55,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x42},{0x95,0x55,0x51,0x42},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x50,0x50,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_7 = { .phases = 40, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_7_data[0] };
+const uint8_t epd_wp_ED047TC2_5_8_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x80,0x08,0x82},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x00,0x00,0x00,0x08},{0x00,0x00,0x00,0x00},{0x02,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x00,0x8a,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0x20,0x00,0x00,0x08},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x20},{0x80,0x00,0x00,0x00},{0xaa,0x08,0xaa,0x08},{0x00,0x00,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0x20,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x82},{0xa0,0x00,0x00,0x0a},{0x20,0x00,0x00,0x00},{0x02,0x82,0x00,0x2a},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa8},{0x00,0x20,0x08,0x00}},{{0xa8,0x00,0x0a,0x00},{0x08,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0xa0,0x08,0x81},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x81},{0xa0,0x00,0x00,0x05},{0x20,0x00,0x00,0x01},{0x02,0x82,0x00,0xa9},{0x80,0x00,0x00,0x01},{0xaa,0xaa,0xaa,0xa4},{0x12,0x28,0xaa,0x00}},{{0xa8,0x00,0x0a,0x00},{0x88,0xa0,0x8a,0x02},{0x00,0x20,0x00,0x20},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x82,0xa8,0x08,0x81},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x08},{0x00,0x02,0x0a,0x80},{0x88,0x00,0x02,0x81},{0xa0,0x00,0x00,0x25},{0x28,0x00,0x00,0x21},{0x22,0x82,0x00,0xa5},{0x80,0x00,0x00,0x21},{0xaa,0xaa,0xaa,0xa4},{0x19,0x2a,0xaa,0x80}},{{0xa8,0x00,0x0a,0x00},{0x8a,0xa8,0x8a,0x0a},{0x00,0x20,0x00,0x28},{0x80,0x00,0x00,0x00},{0x20,0x00,0x00,0x0a},{0x82,0xaa,0x08,0x81},{0x08,0x20,0x02,0x02},{0x08,0x00,0x00,0x08},{0x28,0x02,0x0a,0x80},{0x88,0x08,0x0a,0x81},{0xa0,0x00,0x08,0x25},{0x2a,0x00,0x0a,0x21},{0x22,0xa2,0x00,0x95},{0x80,0x02,0x00,0xa1},{0xaa,0xaa,0xaa,0xa5},{0x19,0xaa,0xaa,0x80}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0x8a,0x0a},{0x02,0x20,0x00,0x28},{0x88,0x00,0x00,0x02},{0x20,0x00,0x00,0x09},{0xa2,0xaa,0xa8,0x85},{0x8a,0x28,0x0a,0x09},{0x88,0x00,0x00,0x08},{0x28,0x02,0x8a,0x80},{0x88,0x0a,0x0a,0x81},{0xa8,0x02,0x08,0x25},{0xaa,0xaa,0x0a,0x21},{0x2a,0xaa,0x2a,0x95},{0xa0,0x02,0x82,0x81},{0xaa,0xaa,0xaa,0x95},{0x19,0xaa,0xaa,0x80}},{{0xa8,0x00,0x05,0x00},{0x8a,0xaa,0xaa,0x09},{0x02,0x20,0x08,0x04},{0x88,0x00,0x00,0x21},{0x28,0x00,0x00,0x09},{0xaa,0xaa,0xa8,0x85},{0x8a,0xaa,0x0a,0x09},{0x88,0x08,0x00,0x04},{0xaa,0x82,0x8a,0x82},{0xaa,0xaa,0xaa,0x81},{0xa8,0x22,0xa8,0x15},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0x2a,0x95},{0xa0,0x22,0x82,0x91},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xaa,0x84}},{{0xa8,0x00,0x05,0x10},{0x8a,0xaa,0xaa,0x09},{0x22,0x20,0x28,0x14},{0x88,0x00,0x00,0x25},{0x28,0x00,0x00,0x05},{0xaa,0xaa,0xa8,0x45},{0xaa,0xaa,0xaa,0x05},{0x88,0x0a,0x00,0x85},{0xaa,0xa2,0x8a,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0x2a,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa2,0x2a,0x8a,0x95},{0xaa,0xaa,0xaa,0x95},{0x15,0x6a,0xa6,0x84}},{{0xa8,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x09},{0xaa,0x22,0xaa,0x15},{0x88,0x00,0x00,0x25},{0xa8,0x00,0x00,0x25},{0xaa,0xaa,0xa8,0x65},{0xaa,0xaa,0xaa,0x25},{0xa8,0x2a,0x80,0xa5},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xa2,0xaa,0x8a,0x95},{0xa9,0xaa,0x66,0x55},{0x15,0x6a,0x56,0x44}},{{0x94,0x00,0x05,0x90},{0x8a,0xaa,0x65,0x29},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x08,0x00,0x25},{0xaa,0xaa,0xa6,0x65},{0xaa,0xaa,0xaa,0x25},{0xaa,0x2a,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x45},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0x29,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0xa9,0xa9,0x55,0x55},{0x25,0x6a,0x55,0x54}},{{0x94,0x00,0x0a,0x64},{0x8a,0xaa,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x88,0x00,0x00,0x25},{0xa8,0x0a,0x0a,0x15},{0xaa,0x6a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0x8a,0xa5},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xa9,0x69,0xaa,0x55},{0xaa,0xaa,0xaa,0x55},{0x99,0xa5,0x55,0x55},{0x21,0x15,0x55,0x54}},{{0x94,0x00,0x0a,0x64},{0xaa,0x9a,0x65,0x19},{0xaa,0x22,0xaa,0x95},{0x8a,0x00,0x00,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x5a,0xa6,0x55},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa8,0x55},{0x9a,0xaa,0xa6,0x55},{0x9a,0xaa,0xa5,0x55},{0xa9,0x69,0xaa,0x55},{0xaa,0xa9,0x6a,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x54}},{{0x94,0x00,0x0a,0xa5},{0xaa,0x5a,0x65,0x15},{0xaa,0x22,0xaa,0x95},{0xaa,0xa0,0x08,0x15},{0xa8,0x2a,0x8a,0x15},{0xaa,0x55,0x56,0x55},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x15},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa5,0x55},{0x9a,0xa9,0x56,0x55},{0x9a,0xa1,0x55,0x55},{0xa9,0x69,0x95,0x55},{0xaa,0xa9,0x69,0x55},{0x95,0x55,0x55,0x55},{0x22,0x15,0x55,0x54}},{{0x68,0x00,0x0a,0x95},{0xa6,0x55,0x55,0x15},{0xaa,0x12,0x8a,0x15},{0xaa,0xa0,0x28,0x15},{0xa8,0x2a,0x8a,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0xaa,0xa5,0x95},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0xa5,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0x91,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x9a,0xa9,0x65,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x54}},{{0x68,0x00,0x0a,0x55},{0xa6,0x55,0x9a,0x15},{0xaa,0x12,0x06,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x15},{0xa9,0x55,0x56,0x55},{0xaa,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xa9,0x65,0x55},{0xaa,0xa5,0x55,0x55},{0x9a,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x99,0x95,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa2,0x15,0x55,0x54}},{{0x68,0x00,0x05,0x55},{0xa5,0x55,0x9a,0x25},{0xa9,0x91,0x55,0x55},{0xaa,0xaa,0x28,0x15},{0xa8,0x2a,0xaa,0x95},{0x59,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa5,0x6a,0x55},{0xaa,0xa9,0x65,0x55},{0xa4,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x54}},{{0x68,0x00,0x05,0x55},{0xa5,0x65,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xaa,0xaa,0xa8,0x95},{0x9a,0x25,0x65,0x95},{0x51,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xa6,0x85,0x65,0x55},{0x9a,0x29,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x15,0x55,0x54}},{{0x54,0x00,0x05,0x55},{0xa9,0xa5,0x9a,0x25},{0x99,0x91,0x55,0x55},{0xa6,0xaa,0xaa,0x95},{0x96,0xa5,0x65,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa6,0x85,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x96,0x55,0x55,0x55},{0xaa,0x95,0x11,0x54}},{{0x94,0x00,0x05,0x55},{0x69,0xaa,0xaa,0x25},{0x95,0x99,0x55,0x55},{0xa6,0xaa,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x56},{0xa6,0x55,0x55,0x59},{0xaa,0x95,0x21,0x54}},{{0x94,0x00,0x85,0x51},{0x6a,0xaa,0xaa,0xa5},{0x95,0x99,0x55,0x55},{0x65,0x59,0x96,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x66},{0xaa,0x56,0x99,0x6a},{0xaa,0xaa,0xaa,0xa8}},{{0x94,0x22,0x85,0x51},{0x6a,0xaa,0x20,0x95},{0x55,0x59,0x55,0x55},{0x55,0x55,0x56,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x66,0x56,0x95,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x96,0x2a,0x65,0x01},{0xa2,0x8a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x96,0x95,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x15,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x96,0xa9,0x50,0x01},{0xa6,0x0a,0x65,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x45,0x55,0x55,0x4a},{0x55,0x55,0x55,0x55},{0x66,0x96,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x90,0x01},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x55,0x95,0x55,0x95},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x52},{0x65,0x54,0x01,0x2a},{0x65,0x55,0x55,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x56,0xa0,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x64},{0x66,0x6a,0xa9,0x50},{0x55,0x55,0x55,0x64},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x55},{0x45,0x50,0x00,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x6a,0x60,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x56},{0x55,0x5a,0x95,0x5a},{0x55,0x15,0x55,0x20},{0x55,0x55,0x55,0x5a},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x56},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0xa9,0x50,0x05},{0x55,0x55,0x55,0x55},{0x65,0x55,0x55,0x65},{0x55,0x55,0x55,0x55},{0x59,0x65,0x6a,0xa6},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x41,0x50,0x15,0x6a},{0x45,0x54,0x55,0x91},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x42,0x95,0x50,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x51},{0x65,0x55,0x55,0x54},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x54,0x10,0x6a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x55,0x50,0x15},{0x55,0x55,0x55,0x55},{0x6a,0xa2,0xaa,0xa2},{0x52,0xa6,0x65,0x92},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x41,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xa2},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x40,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x84,0x50,0x05,0x0a},{0x40,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0xa5,0x50,0x15,0x48},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x45},{0x00,0x00,0x00,0x00},{0x81,0x51,0x11,0x68},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x45,0x55,0x55,0x44},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_8 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_8_data[0] };
+const uint8_t epd_wp_ED047TC2_5_9_data[38][16][4] = {{{0x00,0x00,0x00,0x00},{0x0a,0x82,0x02,0x00},{0x40,0x00,0x00,0x00},{0x00,0x80,0x02,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,0x00},{0x00,0x00,0x00,0x00},{0x28,0x00,0x00,0x02},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x0a,0x8a,0x82,0x00},{0x40,0x08,0x00,0x40},{0x00,0x80,0x22,0x08},{0x00,0x08,0x08,0x08},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x10,0x04,0x00,0x00},{0x11,0x40,0x20,0x00},{0x81,0x00,0x00,0x20},{0x28,0x08,0x00,0x82},{0x00,0x20,0x80,0x80},{0x00,0x00,0x02,0x80}},{{0x80,0x00,0x00,0x00},{0x6a,0x8a,0x8a,0x00},{0x90,0x08,0x01,0x40},{0x00,0x80,0x22,0x08},{0x00,0x28,0x88,0x0a},{0x80,0x08,0x00,0x00},{0x00,0x08,0x02,0x00},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x80,0x00},{0x14,0x14,0x00,0x00},{0x21,0x50,0x20,0x80},{0x81,0x18,0x00,0xa0},{0x29,0x0a,0x02,0x81},{0x2a,0xa2,0xaa,0xa0},{0x00,0x2a,0x02,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xa0,0x08,0x02,0x80},{0x80,0x88,0x22,0x08},{0x20,0xa8,0x89,0x0a},{0x80,0xa8,0x00,0x02},{0xaa,0x8a,0x0a,0x08},{0x00,0x08,0x02,0x00},{0x00,0x00,0x00,0x02},{0x08,0x08,0x80,0x00},{0x24,0x54,0x22,0x80},{0x25,0x52,0x2a,0xa0},{0x86,0xa8,0x20,0xa8},{0xaa,0x2a,0x82,0x81},{0x2a,0xaa,0xaa,0xa0},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x00},{0xaa,0x8a,0x2a,0x80},{0x80,0x88,0x22,0x08},{0x22,0xaa,0x8a,0x0a},{0x82,0xa8,0x00,0x02},{0xaa,0xaa,0x0a,0x0a},{0x00,0x08,0x02,0x28},{0x00,0x00,0x00,0x02},{0x2a,0x8a,0x80,0x00},{0xa5,0xaa,0xa2,0xa0},{0x26,0x96,0xaa,0xa0},{0x8a,0xa8,0xa0,0xa8},{0xaa,0x2a,0x8a,0x81},{0x2a,0xaa,0xaa,0xa8},{0x00,0xaa,0x22,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x0a},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0x2a,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x00,0x02},{0x2a,0xaa,0x80,0x00},{0xa9,0xaa,0xa2,0xa0},{0x26,0xa6,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0x2a,0x8a,0x41},{0xaa,0xaa,0xaa,0xa8},{0x08,0xaa,0x12,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0x8a,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x29},{0xa2,0xa8,0x02,0x02},{0xaa,0xaa,0xaa,0x0a},{0x00,0x08,0x02,0x2a},{0x00,0x00,0x08,0x80},{0x2a,0xaa,0x8a,0x22},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa0},{0x8a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x69},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x12,0x40}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x80,0x88,0x22,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x02},{0xaa,0xaa,0xaa,0x09},{0x20,0x08,0x02,0x28},{0x00,0x02,0x0a,0xa0},{0x2a,0xaa,0x8a,0x2a},{0xaa,0xaa,0xaa,0xa0},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xaa,0xa8},{0x28,0xaa,0x11,0x44}},{{0x80,0x00,0x00,0x00},{0xaa,0xaa,0x8a,0x80},{0xaa,0xaa,0xaa,0x80},{0x81,0x88,0xa2,0x24},{0xaa,0xaa,0x8a,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0x8a,0x02,0x28},{0x00,0x82,0xaa,0xa1},{0x2a,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x95},{0xa6,0xaa,0xa9,0x55},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0x91,0x44}},{{0x80,0x00,0x00,0x20},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0x80},{0x82,0x88,0xaa,0x24},{0xaa,0xaa,0xaa,0x25},{0xaa,0xaa,0x0a,0x21},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x82,0x04},{0x20,0xa2,0xaa,0xa1},{0x2a,0xaa,0xaa,0x29},{0xaa,0xaa,0xaa,0xa8},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x55},{0x96,0xa5,0x65,0x55},{0xaa,0xaa,0xaa,0x54},{0x2a,0xaa,0x91,0x44}},{{0x80,0x00,0x00,0x10},{0xaa,0xaa,0x89,0x80},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x9a,0x14},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0x8a,0x21},{0xaa,0xaa,0xaa,0x85},{0x2a,0xaa,0x8a,0x15},{0x20,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0x25},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0xaa,0x55},{0x96,0x95,0x55,0x55},{0xaa,0xaa,0xaa,0x56},{0x2a,0x99,0x91,0x44}},{{0x80,0x00,0x00,0x94},{0xaa,0xa9,0x45,0x44},{0xaa,0xaa,0xaa,0xa0},{0xa2,0xa8,0x99,0x16},{0xaa,0xa6,0xa6,0x95},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xa9,0xa5},{0xaa,0xaa,0xa9,0x95},{0x2a,0xaa,0xaa,0x69},{0x2a,0xaa,0xaa,0x95},{0xaa,0xaa,0xaa,0x5a},{0xaa,0xaa,0x9a,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0xaa,0x55,0x56},{0x1a,0x95,0x99,0x04}},{{0x80,0x00,0x00,0x64},{0xa9,0x65,0x45,0x48},{0xaa,0xaa,0xa9,0xa2},{0xa2,0x6a,0x99,0x15},{0xaa,0xa5,0x65,0x95},{0xaa,0xaa,0xaa,0x99},{0xaa,0xaa,0xa5,0xa5},{0xaa,0xaa,0xa9,0x95},{0xaa,0xaa,0xaa,0x59},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x99,0x55},{0xaa,0xaa,0x95,0x55},{0xaa,0xaa,0x9a,0x55},{0x95,0x95,0x55,0x55},{0xaa,0x99,0x55,0x55},{0x19,0x55,0x89,0x04}},{{0x40,0x00,0x00,0xa4},{0xa5,0x65,0x45,0x4a},{0xaa,0xaa,0xa9,0xa1},{0xa2,0x6a,0x99,0x15},{0xa9,0x95,0x65,0x95},{0xaa,0xaa,0xaa,0x95},{0xaa,0xa5,0x95,0xa5},{0xaa,0xa6,0xa9,0x95},{0xaa,0xaa,0xa6,0x55},{0x2a,0xaa,0x6a,0x95},{0xaa,0xaa,0x59,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0xa6,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x99,0x55,0x55},{0x15,0x55,0x49,0x14}},{{0x40,0x00,0x00,0x54},{0xa5,0x65,0x45,0x88},{0xaa,0xaa,0xa9,0xa1},{0xaa,0x66,0x11,0x15},{0xa9,0x55,0x65,0x55},{0xaa,0x96,0xa9,0x95},{0xa5,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x15},{0xaa,0xaa,0x95,0x55},{0x26,0xa5,0x65,0x95},{0xaa,0xa9,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0x40,0x00,0x00,0x55},{0xa5,0x55,0x46,0x89},{0xaa,0xa6,0xa5,0x61},{0xaa,0x66,0x51,0x15},{0x95,0x55,0x55,0x55},{0x28,0x56,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa6,0xa9,0x55},{0xaa,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0xaa,0xa9,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0xa0,0x00,0x00,0x55},{0x95,0x56,0x8a,0x99},{0xaa,0xaa,0x9a,0x51},{0xaa,0x66,0x55,0x95},{0x95,0x55,0x55,0x55},{0x29,0x55,0xa5,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xa5,0x45,0x55},{0xaa,0xa9,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x9a,0xa9,0x55,0x55},{0xa5,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x45,0x14}},{{0xa0,0x00,0x00,0x55},{0x9a,0x9a,0x8a,0x65},{0xaa,0xa5,0x56,0x51},{0x6a,0x56,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x85,0x55,0x55,0x55},{0xaa,0x59,0x55,0x55},{0x95,0x55,0x55,0x55},{0x9a,0x55,0x55,0x55},{0x99,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x96},{0x95,0x55,0x55,0x55},{0x05,0x55,0x45,0x14}},{{0xa0,0x00,0x20,0x51},{0x5a,0xaa,0x8a,0x65},{0xa5,0x65,0x56,0x59},{0x69,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x85,0x55,0x45,0x10}},{{0x60,0x28,0xa0,0x51},{0x6a,0xaa,0x8a,0x65},{0x95,0x55,0x56,0x55},{0x59,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x84,0x55,0x44,0x10}},{{0x6a,0xaa,0xa8,0x11},{0x6a,0xaa,0x8a,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x45,0x44,0x10}},{{0x5a,0xaa,0x64,0x01},{0xa6,0x99,0x45,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xa6,0x44,0x46,0x10}},{{0x5a,0x95,0x56,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x99,0x01},{0x95,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x56,0x5a,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x95},{0x95,0x55,0x55,0x51},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x65,0x55},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x25,0x6a,0x99,0x01},{0x15,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x65,0x65},{0x56,0x5a,0x56,0x56},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x65},{0x95,0x55,0x41,0x56},{0x95,0x55,0x55,0x41},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x5a,0x66,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0xaa,0x56,0x05},{0x55,0x55,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x95,0x61},{0x55,0x55,0x55,0x59},{0x55,0x55,0x55,0x45},{0x55,0x55,0x55,0x59},{0x55,0x55,0x54,0x55},{0x55,0x54,0x00,0x15},{0x91,0x55,0x15,0x42},{0x55,0x55,0x24,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x2a,0x95,0x56,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x65,0x49,0x91},{0x55,0x55,0x54,0x44},{0x55,0x55,0x55,0x49},{0x15,0x55,0x55,0x54},{0x55,0x51,0x54,0x0a},{0x55,0x04,0x00,0x2a},{0xaa,0xaa,0xaa,0xaa},{0x55,0x54,0x10,0x55},{0x65,0x56,0x9a,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x05},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xa2,0x1a,0x06,0x50},{0x68,0xa0,0xa8,0xaa},{0x55,0x45,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x45,0x04,0x00,0xaa},{0x55,0x55,0x65,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x51,0x05,0x01,0x02},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x6a},{0x00,0x00,0x00,0x00},{0x80,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x2a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x06},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x58},{0x55,0x55,0x55,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x6a,0xaa,0xa9,0xa4},{0x55,0x55,0x55,0x00},{0x15,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x54},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_9 = { .phases = 38, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_9_data[0] };
+const uint8_t epd_wp_ED047TC2_5_10_data[44][16][4] = {{{0x00,0x00,0x00,0x00},{0x80,0x80,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x00,0x00},{0x00,0x80,0x00,0x00},{0x80,0x00,0x08,0x02},{0x00,0x80,0x00,0x08},{0x10,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x02,0x00,0x00,0x00},{0xa2,0x88,0x20,0x05},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x02},{0x08,0x00,0x02,0x00},{0x00,0x00,0x00,0x00},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x80,0x20,0x00},{0x00,0x80,0x00,0x00},{0x00,0x82,0x00,0x00},{0xa8,0x00,0x08,0x82},{0x00,0x80,0x20,0x0a},{0x92,0x00,0x00,0x8a},{0x2a,0x20,0xa2,0xa8},{0x00,0x00,0x00,0x08}},{{0x02,0x00,0x00,0x00},{0xa2,0x8a,0x20,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x08,0x05,0x02,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x00,0x80,0x20,0x00},{0x02,0xa0,0xa0,0x00},{0x00,0x82,0x00,0x02},{0xaa,0x20,0x08,0x82},{0x84,0x80,0xa0,0x0a},{0xa2,0x84,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x08}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa0,0x05},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x15,0x42,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xa0,0x20,0x80},{0x02,0xaa,0xa8,0x00},{0x00,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x82},{0x9a,0x90,0xa8,0x0a},{0xa6,0xa8,0x00,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x00,0x80,0x28}},{{0x82,0x00,0x00,0x00},{0xa2,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x40},{0x00,0x00,0x00,0x02},{0x29,0x1a,0x46,0x00},{0x00,0x00,0x00,0x02},{0x00,0x02,0x02,0x00},{0x00,0x00,0x00,0x0a},{0x02,0xaa,0x28,0x80},{0x2a,0xaa,0xa8,0x00},{0x02,0x82,0x00,0x02},{0xaa,0xa8,0x2a,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0x08,0x8a},{0x2a,0xaa,0xaa,0xaa},{0x22,0x8a,0x88,0x24}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x09},{0x00,0x00,0x00,0x90},{0x02,0xa0,0x08,0x02},{0x2a,0x2a,0x86,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x80},{0x2a,0xaa,0xa8,0x20},{0x02,0x82,0x00,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xa8,0xaa,0x0a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0x8a,0x8a,0xa4}},{{0x82,0x00,0x00,0x00},{0xaa,0xaa,0xa8,0x0a},{0x80,0x00,0x00,0x90},{0x02,0xaa,0x2a,0x02},{0x2a,0xaa,0x8a,0x20},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xa2,0xa2,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0xaa},{0x1a,0xaa,0x4a,0x54}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0x90},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa0},{0x08,0x00,0x00,0x02},{0x00,0x02,0x02,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xa8,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x16,0xaa,0x46,0x54}},{{0x82,0x00,0x00,0x08},{0xaa,0xaa,0xaa,0x0a},{0x80,0x02,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0x8a},{0xaa,0xaa,0xaa,0x2a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa4},{0x15,0x9a,0x65,0x54}},{{0x82,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0x80,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x02},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x00,0x02,0x82,0x20},{0x00,0x00,0x00,0x0a},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0x20},{0x2a,0xaa,0xaa,0x02},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0x55},{0x15,0x95,0x65,0x54}},{{0x81,0x00,0x00,0x28},{0xaa,0xaa,0xaa,0x0a},{0xa2,0x22,0x00,0xaa},{0x02,0xaa,0xaa,0x8a},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x02,0x82,0x20},{0x00,0x0a,0x00,0x09},{0x2a,0xaa,0xaa,0x82},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0xa9},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0xa8},{0xaa,0xaa,0x9a,0x2a},{0xa2,0xa2,0x02,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xaa,0xa8},{0x28,0x00,0x00,0x02},{0x0a,0x82,0x82,0xa0},{0x00,0x8a,0x80,0x09},{0x2a,0xaa,0xaa,0x22},{0x2a,0xaa,0xaa,0xa2},{0xaa,0xaa,0xaa,0x01},{0xaa,0xaa,0xa2,0x21},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0xa9,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0xa8},{0xaa,0x66,0x9a,0x2a},{0xa2,0xa2,0x22,0xaa},{0x02,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0x2a,0xa2,0xa0,0x80},{0x02,0x8a,0x80,0x05},{0x2a,0xaa,0x8a,0x20},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa1},{0xaa,0xaa,0xa0,0x61},{0xaa,0xaa,0xaa,0xa5},{0xaa,0xaa,0xaa,0x65},{0xaa,0xaa,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x81,0x00,0x80,0x94},{0xaa,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa9},{0x2a,0xaa,0xa9,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x82},{0x02,0x8a,0x82,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xa8,0xaa,0xa1},{0xaa,0xaa,0xa0,0x65},{0xaa,0xaa,0x20,0x85},{0xaa,0xaa,0xaa,0x65},{0xaa,0x95,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x41,0x00,0x40,0x94},{0x69,0x65,0x56,0x26},{0xa2,0xaa,0x22,0xaa},{0x82,0xaa,0xaa,0xa1},{0x2a,0xaa,0xaa,0xaa},{0xa8,0x00,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xa2,0x05},{0x2a,0xaa,0x8a,0x21},{0x2a,0xaa,0xaa,0x9a},{0xaa,0x28,0xaa,0xa9},{0xaa,0xaa,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x42,0x00,0x48,0xa4},{0x59,0x55,0x55,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xaa,0x25},{0x2a,0xaa,0xaa,0x9a},{0xa8,0x80,0x00,0x01},{0xaa,0xaa,0xa8,0x8a},{0xaa,0xaa,0xaa,0x05},{0x2a,0xaa,0x8a,0x29},{0x2a,0xaa,0x56,0x99},{0xaa,0x28,0xa8,0xa9},{0xaa,0x82,0x80,0x65},{0xaa,0x2a,0x00,0x85},{0xaa,0xaa,0xa6,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x42,0x00,0x48,0x64},{0x59,0x59,0x65,0xa9},{0xa6,0xaa,0x22,0x69},{0x82,0xaa,0xa0,0x65},{0x2a,0xaa,0xa9,0x56},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0xa9,0x8a},{0xaa,0xaa,0xaa,0x05},{0xaa,0x2a,0x86,0x69},{0x2a,0x55,0x55,0x99},{0xaa,0x69,0x89,0xa9},{0x96,0x82,0x00,0x45},{0xaa,0x22,0x10,0x05},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0x62,0x00,0x4a,0x54},{0x59,0x9a,0xa9,0x95},{0xaa,0xaa,0x22,0x65},{0x82,0xaa,0xa5,0x45},{0x26,0xaa,0xa9,0x55},{0xaa,0x80,0x00,0x09},{0xaa,0xa9,0x29,0x89},{0xaa,0xaa,0xaa,0x85},{0xaa,0x55,0x54,0x69},{0x21,0x55,0x55,0x55},{0xaa,0x69,0x45,0xa9},{0x95,0x55,0x55,0x55},{0xaa,0x22,0x10,0x05},{0x89,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x54}},{{0xa2,0x00,0x8a,0x54},{0x66,0xaa,0xaa,0x95},{0xaa,0xaa,0x22,0x55},{0x82,0x95,0x55,0x55},{0x16,0xa5,0x55,0x55},{0xa2,0xa0,0x20,0x09},{0xaa,0xa9,0x29,0x09},{0xaa,0xaa,0xaa,0x85},{0xa9,0x55,0x55,0x59},{0x11,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xa1,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x25,0x55,0x55,0x54}},{{0xa2,0x00,0x86,0x54},{0xa6,0xaa,0xaa,0xa5},{0xaa,0xaa,0x22,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x5a,0xa9,0x55},{0xa2,0xaa,0x28,0x01},{0xaa,0xa9,0x29,0x55},{0xaa,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x55,0x55,0x54}},{{0xa1,0x00,0x85,0x54},{0xaa,0xa2,0xaa,0x65},{0xaa,0xaa,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x15,0xa5,0x55,0x55},{0xa2,0xaa,0xa8,0x01},{0xaa,0xa9,0x69,0x55},{0xaa,0xa5,0x69,0xa5},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x29,0x45,0x55,0x54}},{{0xa1,0x00,0x85,0x54},{0x9a,0x95,0x55,0x55},{0xaa,0x99,0x21,0x55},{0xa9,0x55,0x55,0x55},{0x16,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa2,0xa9,0x55,0x55},{0xaa,0xa5,0x69,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x85,0x54}},{{0x61,0x00,0x45,0x54},{0x95,0x55,0x55,0x55},{0xaa,0x99,0x61,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0xa5,0x55,0x55,0x55},{0xaa,0x65,0x55,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x2a,0x65,0x89,0x94}},{{0x61,0x00,0x45,0x50},{0x95,0x55,0x55,0x55},{0x9a,0x99,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x85},{0x95,0x55,0x55,0x55},{0xa9,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x2a,0xaa,0x8a,0xa8}},{{0x61,0x00,0x45,0x10},{0x15,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x96,0xaa,0xaa,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xa8}},{{0x51,0x20,0x41,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0xa9,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x16,0x6a,0x94,0x65},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x50,0x2a,0x40,0x00},{0x55,0x55,0x55,0x55},{0x59,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x2a,0x00,0x01},{0x55,0x55,0x55,0x55},{0x51,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0xa9},{0xaa,0xaa,0xaa,0xa8}},{{0x28,0xa9,0x00,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x28,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x99,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x24,0x95,0x20,0x01},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x99},{0x95,0x55,0x55,0x55},{0x15,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x99},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x9a},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x14,0x6a,0x20,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x56},{0x95,0x55,0x55,0x65},{0x55,0x14,0x54,0x56},{0x41,0x55,0x55,0x56},{0x55,0x55,0x55,0x5a},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x14,0x6a,0x10,0x01},{0x55,0x55,0x55,0x56},{0x55,0x55,0x55,0x95},{0x55,0x55,0x55,0x11},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x59,0x55,0x95,0x55},{0x55,0x55,0x55,0x54},{0x55,0x55,0x55,0x15},{0x6a,0xaa,0xaa,0x99},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x96,0x10,0x05},{0x55,0x55,0x55,0x19},{0x55,0x55,0x55,0x65},{0x55,0x55,0x55,0x21},{0xa9,0x55,0x56,0xa5},{0x55,0x55,0x55,0x55},{0x66,0xa9,0x69,0x54},{0x55,0x50,0x14,0x1a},{0x6a,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x46},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x95,0x10,0x45},{0x55,0x55,0x55,0x15},{0x55,0x55,0x55,0x65},{0x6a,0x6a,0x9a,0x11},{0x95,0x55,0x55,0x55},{0x69,0x55,0x55,0x59},{0x51,0x56,0x16,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x18,0x55,0x10,0x55},{0x00,0x00,0x00,0x00},{0x55,0x65,0x56,0x54},{0x55,0x15,0x45,0x02},{0x80,0x00,0x00,0x0a},{0x55,0x55,0x55,0x16},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x15,0x55,0x15,0x55},{0x00,0x00,0x00,0x00},{0x59,0x55,0x55,0x14},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x65,0x45,0x54,0x0a},{0x2a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x40,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0x15,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x80,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0x95,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x95,0x55,0x55,0x55},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x6a,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_10 = { .phases = 44, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_10_data[0] };
+const uint8_t epd_wp_ED047TC2_5_11_data[57][16][4] = {{{0x20,0x8a,0x80,0x00},{0x15,0x55,0x5a,0xa4},{0x44,0x10,0x0a,0x41},{0x40,0x00,0x09,0x54},{0x10,0x50,0x00,0x00},{0x00,0x00,0x04,0x28},{0x40,0x00,0x00,0x00},{0x00,0x00,0x20,0x00},{0x00,0x00,0x40,0x00},{0x00,0x00,0x00,0x00},{0x00,0x40,0x00,0x68},{0x00,0x00,0x40,0x00},{0x00,0x00,0x0a,0x54},{0x00,0x0a,0x80,0x00},{0x10,0x09,0x60,0x00},{0x00,0x00,0x00,0x50}},{{0xaa,0xaa,0x8a,0x00},{0x0a,0x60,0x0a,0xa8},{0x54,0x54,0x8a,0x41},{0x41,0x02,0x09,0x54},{0x15,0x50,0x06,0x24},{0x00,0x08,0xa4,0x28},{0x44,0x00,0x09,0xa8},{0x05,0x00,0x2a,0xa8},{0x01,0x10,0x46,0xa8},{0x04,0x00,0x00,0xa8},{0x00,0x40,0x00,0x54},{0x04,0x00,0x44,0xa8},{0x00,0x00,0x8a,0x54},{0x00,0x0a,0x8a,0x58},{0x50,0x19,0x65,0x54},{0x00,0x00,0x00,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x6a,0xaa,0xa8},{0x55,0x94,0x89,0x55},{0x41,0x02,0x09,0x54},{0x15,0x50,0x66,0x24},{0x40,0x04,0xa4,0x68},{0x44,0x0a,0x09,0x54},{0x05,0x08,0x55,0x54},{0x11,0x14,0x56,0x54},{0x04,0x40,0x00,0x58},{0x01,0x40,0x0a,0x54},{0x04,0x0a,0x44,0xa8},{0x01,0x00,0x8a,0x54},{0x00,0x0a,0x6a,0x54},{0x50,0x19,0x65,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x2a,0x2a,0xaa,0xa8},{0x96,0x95,0x55,0x55},{0x51,0x0a,0x05,0x54},{0x15,0x50,0x66,0xa4},{0x40,0x04,0x54,0x54},{0x44,0x05,0x09,0x54},{0x05,0x18,0x55,0x54},{0x51,0x14,0x56,0x54},{0x04,0x40,0x02,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x58},{0x01,0x0a,0x85,0x54},{0x01,0x05,0x65,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x01,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x96,0xa5,0x55,0x55},{0x51,0x09,0x05,0x55},{0x15,0x50,0x65,0x94},{0x44,0x14,0x54,0x54},{0x54,0x15,0x95,0x54},{0x05,0x56,0x55,0x54},{0x51,0x14,0x55,0x54},{0x14,0x40,0x82,0x54},{0x01,0x40,0x8a,0x54},{0x04,0x05,0x44,0x54},{0x01,0x0a,0x45,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x54},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x49,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x14,0x55,0x55},{0x14,0x40,0x8a,0x54},{0x01,0x40,0x85,0x54},{0x04,0x15,0x44,0x54},{0x01,0x0a,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x6a,0xaa,0xaa,0xa8},{0x9a,0xa6,0x55,0x55},{0x51,0x55,0x25,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x95,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0xa9,0x54},{0x01,0x40,0x45,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x65,0x54},{0x01,0x05,0x55,0x54},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x50,0x55,0x54},{0x54,0x14,0x54,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x14,0x40,0x69,0x55},{0x01,0x40,0x65,0x55},{0x04,0x15,0x44,0x54},{0x01,0x05,0x55,0x54},{0x01,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x52,0x55,0x54},{0x54,0x14,0x56,0x54},{0x54,0x15,0x55,0x55},{0x05,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x65,0x55},{0x01,0x50,0x65,0x55},{0x04,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x54,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x51,0x55,0x15,0x55},{0x15,0x92,0x55,0x55},{0x55,0x14,0x56,0x54},{0x54,0x55,0x55,0x55},{0x45,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x40,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xa6,0x65,0x55},{0x91,0x55,0x15,0x55},{0x16,0x92,0x55,0x55},{0x55,0x14,0x56,0x55},{0x54,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x50,0x55,0x55},{0x05,0x15,0x64,0x54},{0x01,0x05,0x55,0x55},{0x11,0x05,0x55,0x55},{0x55,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0x92,0x55,0x95,0x55},{0x6a,0x91,0x55,0x55},{0x55,0x54,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x15,0x55,0x55},{0x15,0x48,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x05,0x15,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x8a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0x91,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x4a,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa5,0x15,0x55,0x55},{0x00,0x00,0x05,0x54}},{{0xaa,0xaa,0x4a,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x55,0x55,0x55},{0x6a,0xa1,0x55,0x55},{0x95,0x54,0x55,0x55},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x5a,0x55,0x55},{0x15,0x55,0x54,0x55},{0x11,0x05,0x55,0x55},{0x55,0x05,0x55,0x55},{0xa9,0x15,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0xa5,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0x65,0x55},{0xa6,0x95,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0x99,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0x56,0x55,0x55,0x55},{0x15,0x46,0x55,0x55},{0x01,0x55,0x55,0x55},{0x15,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x05,0x55,0x55},{0xa9,0x66,0x55,0x55},{0x00,0x10,0x45,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x55},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x55,0x55},{0xa9,0x54,0x55,0x55},{0x99,0x55,0x55,0x55},{0x5a,0x55,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x15,0x45,0x55,0x55},{0x11,0x55,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x56,0x15,0x55,0x55},{0xa9,0x66,0x95,0x55},{0x00,0x10,0x55,0x54}},{{0xaa,0x95,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xa6,0x96},{0xa6,0xa5,0x56,0x55},{0x6a,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x55,0x55,0x55},{0x5a,0x95,0x55,0x55},{0xa6,0x55,0x55,0x55},{0x19,0x45,0x55,0x55},{0x11,0x95,0x55,0x55},{0x19,0x55,0x54,0x55},{0x56,0x15,0x55,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x66,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x9a,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xa8},{0xaa,0xaa,0xaa,0x96},{0xaa,0xa6,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0x68,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x5a,0xa5,0x55,0x55},{0xaa,0x65,0x55,0x55},{0x29,0x85,0x55,0x55},{0x12,0x95,0x55,0x55},{0x59,0x55,0x56,0x55},{0x56,0x15,0x55,0x55},{0xa6,0x15,0x55,0x55},{0xaa,0x6a,0x9a,0x55},{0x00,0x14,0x55,0x54}},{{0x95,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0x55},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0x59,0x55},{0xa9,0x65,0x55,0x55},{0x9a,0xa5,0x55,0x55},{0xaa,0x69,0x95,0x55},{0x2a,0x85,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x55,0x95,0x55},{0x56,0x15,0x55,0x55},{0xaa,0x1a,0x95,0x55},{0xaa,0x6a,0xaa,0xa9},{0x00,0x15,0x55,0x54}},{{0x55,0x55,0x45,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x56,0xa9},{0xaa,0xa5,0x99,0x55},{0xaa,0xa8,0xa9,0x55},{0xa9,0xaa,0x56,0x55},{0xaa,0xa5,0x95,0x55},{0xaa,0x69,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x52,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0x66,0x15,0x55,0x55},{0xaa,0x1a,0xaa,0xa5},{0xaa,0xaa,0xaa,0xa9},{0x20,0x95,0x55,0x54}},{{0x55,0x55,0x8a,0x00},{0xaa,0xaa,0xa5,0x5a},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0x99,0x59},{0xaa,0xa8,0xa9,0x55},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0x6a,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x5a,0x6a,0x99,0x55},{0xa6,0x15,0x55,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x5a,0x8a,0x00},{0xaa,0xaa,0x55,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xa5,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0x95,0x55,0x55},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0x9a,0xa9},{0xaa,0x1a,0xaa,0xa9},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0x6a,0x8a,0x00},{0xaa,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xa9,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x66,0x55},{0xaa,0xaa,0xaa,0x55},{0xaa,0xaa,0xa9,0x55},{0x6a,0x95,0x55,0x55},{0x56,0xa5,0x55,0x95},{0x6a,0xaa,0x99,0x55},{0xaa,0x1a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x26,0x95,0x55,0x54}},{{0x55,0xaa,0x8a,0x00},{0xa9,0x55,0x5a,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0x6a,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0x95},{0xaa,0xaa,0x6a,0xa9},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xaa,0xaa,0xa9},{0x6a,0x95,0x55,0x55},{0x66,0xa5,0x55,0xa9},{0xaa,0xaa,0x99,0x55},{0xaa,0x2a,0xaa,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x12,0x45,0x55,0x54}},{{0x6a,0xaa,0x8a,0x00},{0xa5,0x55,0xa5,0x56},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0x59},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x6a,0x95,0x55,0xa5},{0xa6,0xa5,0x9a,0xa9},{0xaa,0xaa,0x99,0xa5},{0xaa,0x2a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x41,0x55,0x54}},{{0xaa,0xaa,0x8a,0x00},{0x95,0x6a,0xa5,0x56},{0xaa,0x69,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa9},{0xaa,0xa9,0xa9,0xa9},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0x96,0xa9},{0xa6,0xa5,0xaa,0xaa},{0xaa,0xaa,0x99,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x85,0x00},{0x55,0x6a,0xa5,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xa9,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x95,0xaa,0xaa},{0xaa,0xa5,0xaa,0xaa},{0xaa,0xaa,0xa9,0xa9},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x11,0x40,0x00,0x54}},{{0xaa,0xaa,0x45,0x00},{0x5a,0x6a,0x55,0x56},{0xa9,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x99,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x40,0x02,0xa0}},{{0xaa,0xa5,0x45,0x00},{0x6a,0x55,0x55,0x56},{0x69,0x59,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xa9,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x40,0x02,0xa8}},{{0xaa,0x55,0x45,0x00},{0x6a,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0xa5,0x55,0x45,0x00},{0x66,0x95,0x55,0x55},{0x65,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x55,0x95,0x55,0x55},{0x55,0x55,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x5a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x99,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x59,0x55,0x69},{0x69,0x6a,0xaa,0xaa},{0xaa,0x5a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x95,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x6a,0xaa,0xaa},{0xa9,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x0a,0xa8}},{{0x55,0x55,0x45,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x6a,0x5a,0xa9,0xaa},{0xa5,0x6a,0xaa,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x0a,0xa8}},{{0x55,0x55,0x40,0x00},{0x95,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0xa9,0xaa},{0x95,0x6a,0x66,0xaa},{0xaa,0x6a,0xaa,0xaa},{0xaa,0x9a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa8}},{{0x55,0x50,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x99,0xaa},{0x55,0x46,0x66,0xaa},{0xa8,0x6a,0x9a,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x01,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x20,0x8a,0xa8}},{{0x50,0x00,0x00,0x80},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x94,0x95,0x95,0x56},{0x55,0x45,0x55,0xa6},{0x65,0x96,0x96,0xaa},{0x26,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x08,0x28,0xaa,0xa8}},{{0x00,0x00,0x00,0x60},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x55,0xa6},{0x55,0x96,0x66,0xaa},{0x2a,0x4a,0xaa,0xaa},{0xaa,0x8a,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x88,0x2a,0xaa,0xa8}},{{0x00,0x00,0x20,0x50},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x95,0x66,0x6a},{0x12,0x86,0xaa,0xaa},{0x85,0x4a,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xa9,0xaa,0xaa,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0xa8,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x61,0x09,0x55,0x55},{0x45,0x55,0x55,0xaa},{0xa8,0xaa,0xaa,0xaa},{0x98,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x10,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x45,0x99,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x56,0xaa},{0x94,0x6a,0xaa,0xaa},{0x56,0x65,0x55,0x55},{0xa6,0x55,0x66,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x00,0x25,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x68,0x95,0x55,0x55},{0xa9,0x8a,0xaa,0xaa},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x00,0x05,0x65,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xa4,0x6a,0xaa,0xaa},{0x02,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xa8}},{{0x05,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x01,0x50,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xa8}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x55,0x55,0x55,0x55},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0xaa,0xaa,0xaa,0xaa},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_ED047TC2_5_11 = { .phases = 57, .phase_times = NULL, .luts = (const uint8_t*)&epd_wp_ED047TC2_5_11_data[0] };
+const EpdWaveformPhases* epd_wm_ed047tc2_5_ranges[7] = { &epd_wp_ED047TC2_5_5,&epd_wp_ED047TC2_5_6,&epd_wp_ED047TC2_5_7,&epd_wp_ED047TC2_5_8,&epd_wp_ED047TC2_5_9,&epd_wp_ED047TC2_5_10,&epd_wp_ED047TC2_5_11 };
const EpdWaveformMode epd_wm_ed047tc2_5 = { .type = 5, .temp_ranges = 7, .range_data = &epd_wm_ed047tc2_5_ranges[0] };
const EpdWaveformTempInterval ed047tc2_intervals[14] = { { .min = 0, .max = 3 },{ .min = 3, .max = 6 },{ .min = 6, .max = 9 },{ .min = 9, .max = 12 },{ .min = 12, .max = 15 },{ .min = 15, .max = 18 },{ .min = 18, .max = 21 },{ .min = 21, .max = 24 },{ .min = 24, .max = 27 },{ .min = 27, .max = 30 },{ .min = 30, .max = 33 },{ .min = 33, .max = 38 },{ .min = 38, .max = 43 },{ .min = 43, .max = 48 } };
const EpdWaveformMode* ed047tc2_modes[3] = { &epd_wm_ed047tc2_1,&epd_wm_ed047tc2_2,&epd_wm_ed047tc2_5 };
-const EpdWaveform ed047tc2 = { .num_modes = 3, .num_temp_ranges = 7, .mode_data = &ed047tc2_modes[0], .temp_intervals = &ed047tc2_intervals[0] };
+const EpdWaveform epdiy_ED047TC2 = { .num_modes = 3, .num_temp_ranges = 7, .mode_data = &ed047tc2_modes[0], .temp_intervals = &ed047tc2_intervals[0] };
\ No newline at end of file
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060SC4.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060SC4.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060SC4.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060SC4.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060SCT.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060SCT.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060SCT.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060SCT.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060XC3.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060XC3.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED060XC3.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED060XC3.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED097OC4.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED097OC4.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED097OC4.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED097OC4.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED097TC2.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED097TC2.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED097TC2.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED097TC2.h
diff --git a/lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED133UT2.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED133UT2.h
old mode 100755
new mode 100644
similarity index 100%
rename from lib/libesp32_eink/epdiy/src/epd_driver/waveforms/epdiy_ED133UT2.h
rename to lib/libesp32_eink/epdiy/src/waveforms/epdiy_ED133UT2.h
diff --git a/lib/libesp32_eink/epdiy/src/waveforms/epdiy_NULL.h b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_NULL.h
new file mode 100644
index 000000000..ffa1612ee
--- /dev/null
+++ b/lib/libesp32_eink/epdiy/src/waveforms/epdiy_NULL.h
@@ -0,0 +1,28 @@
+const int epd_wp_epdiy_NULL_1_0_times[5] = { 1000,1000,1000,1000,1000 };
+const uint8_t epd_wp_epdiy_NULL_1_0_data[5][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_epdiy_NULL_1_0 = { .phases = 5, .phase_times = &epd_wp_epdiy_NULL_1_0_times[0], .luts = (const uint8_t*)&epd_wp_epdiy_NULL_1_0_data[0] };
+const EpdWaveformPhases* epd_wm_epdiy_NULL_1_ranges[1] = { &epd_wp_epdiy_NULL_1_0 };
+const EpdWaveformMode epd_wm_epdiy_NULL_1 = { .type = 1, .temp_ranges = 1, .range_data = &epd_wm_epdiy_NULL_1_ranges[0] };
+const int epd_wp_epdiy_NULL_2_0_times[30] = { 15,8,8,8,8,8,10,10,10,10,20,20,50,100,200,15,8,4,3,3,3,3,6,6,6,6,15,20,50,150 };
+const uint8_t epd_wp_epdiy_NULL_2_0_data[30][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_epdiy_NULL_2_0 = { .phases = 30, .phase_times = &epd_wp_epdiy_NULL_2_0_times[0], .luts = (const uint8_t*)&epd_wp_epdiy_NULL_2_0_data[0] };
+const EpdWaveformPhases* epd_wm_epdiy_NULL_2_ranges[1] = { &epd_wp_epdiy_NULL_2_0 };
+const EpdWaveformMode epd_wm_epdiy_NULL_2 = { .type = 2, .temp_ranges = 1, .range_data = &epd_wm_epdiy_NULL_2_ranges[0] };
+const int epd_wp_epdiy_NULL_5_0_times[30] = { 15,8,8,8,8,8,10,10,10,10,20,20,50,100,200,15,8,4,3,3,3,3,6,6,6,6,15,20,50,150 };
+const uint8_t epd_wp_epdiy_NULL_5_0_data[30][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_epdiy_NULL_5_0 = { .phases = 30, .phase_times = &epd_wp_epdiy_NULL_5_0_times[0], .luts = (const uint8_t*)&epd_wp_epdiy_NULL_5_0_data[0] };
+const EpdWaveformPhases* epd_wm_epdiy_NULL_5_ranges[1] = { &epd_wp_epdiy_NULL_5_0 };
+const EpdWaveformMode epd_wm_epdiy_NULL_5 = { .type = 5, .temp_ranges = 1, .range_data = &epd_wm_epdiy_NULL_5_ranges[0] };
+const int epd_wp_epdiy_NULL_16_0_times[15] = { 15,8,8,8,8,8,10,10,10,10,20,20,50,100,200 };
+const uint8_t epd_wp_epdiy_NULL_16_0_data[15][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_epdiy_NULL_16_0 = { .phases = 15, .phase_times = &epd_wp_epdiy_NULL_16_0_times[0], .luts = (const uint8_t*)&epd_wp_epdiy_NULL_16_0_data[0] };
+const EpdWaveformPhases* epd_wm_epdiy_NULL_16_ranges[1] = { &epd_wp_epdiy_NULL_16_0 };
+const EpdWaveformMode epd_wm_epdiy_NULL_16 = { .type = 16, .temp_ranges = 1, .range_data = &epd_wm_epdiy_NULL_16_ranges[0] };
+const int epd_wp_epdiy_NULL_17_0_times[15] = { 15,8,4,3,3,3,3,6,6,6,6,15,20,50,150 };
+const uint8_t epd_wp_epdiy_NULL_17_0_data[15][16][4] = {{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}},{{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00},{0x00,0x00,0x00,0x00}}};
+const EpdWaveformPhases epd_wp_epdiy_NULL_17_0 = { .phases = 15, .phase_times = &epd_wp_epdiy_NULL_17_0_times[0], .luts = (const uint8_t*)&epd_wp_epdiy_NULL_17_0_data[0] };
+const EpdWaveformPhases* epd_wm_epdiy_NULL_17_ranges[1] = { &epd_wp_epdiy_NULL_17_0 };
+const EpdWaveformMode epd_wm_epdiy_NULL_17 = { .type = 17, .temp_ranges = 1, .range_data = &epd_wm_epdiy_NULL_17_ranges[0] };
+const EpdWaveformTempInterval epdiy_NULL_intervals[1] = { { .min = 20, .max = 30 } };
+const EpdWaveformMode* epdiy_NULL_modes[5] = { &epd_wm_epdiy_NULL_1,&epd_wm_epdiy_NULL_2,&epd_wm_epdiy_NULL_5,&epd_wm_epdiy_NULL_16,&epd_wm_epdiy_NULL_17 };
+const EpdWaveform epdiy_NULL = { .num_modes = 5, .num_temp_ranges = 1, .mode_data = &epdiy_NULL_modes[0], .temp_intervals = &epdiy_NULL_intervals[0] };
diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino
index 71fdb9890..81fbf377e 100755
--- a/tasmota/tasmota_support/support.ino
+++ b/tasmota/tasmota_support/support.ino
@@ -2553,14 +2553,6 @@ void SyslogAsync(bool refresh) {
} else {
strcpy(msgid, "-"); // -
}
-/*
- char msgid[2] = { 0 };
- char* line_msgid = strchr(msg_start, ':');
- if ((line_msgid == nullptr) || (line_msgid - msg_start != 3)) { // Only 3 character message id supported
- strcpy(msgid, "-"); // -
- }
-*/
-/*
snprintf_P(header, sizeof(header), PSTR("<%d>1 %s%s000%s %s tasmota - %s -"),
128 + min(loglevel * 3, 7), // Error (1) = 131, Info (2) = 134, Debug (3) = 135, DebugMore = (4) 135
GetDate().c_str(), timestamp, GetTimeZone().c_str(), // 1970-01-01T00:00:02.096000+01:00