Full Code of loboris/ESP32_ePaper_example for AI

master 413b5759898e cached
106 files
1.3 MB
635.9k tokens
619 symbols
1 requests
Download .txt
Showing preview only (1,432K chars total). Download the full file or copy to clipboard to get everything.
Repository: loboris/ESP32_ePaper_example
Branch: master
Commit: 413b5759898e
Files: 106
Total size: 1.3 MB

Directory structure:
gitextract_tqp4d6q6/

├── .gitignore
├── Makefile
├── README.md
├── components/
│   ├── epaper/
│   │   ├── DefaultFont.c
│   │   ├── DejaVuSans18.c
│   │   ├── DejaVuSans24.c
│   │   ├── EPD.c
│   │   ├── EPD.h
│   │   ├── EPDspi.c
│   │   ├── EPDspi.h
│   │   ├── SmallFont.c
│   │   ├── Ubuntu16.c
│   │   ├── comic24.c
│   │   ├── component.mk
│   │   ├── dejavuX.c
│   │   ├── minya24.c
│   │   └── tooney32.c
│   ├── mkspiffs/
│   │   ├── .travis.yml
│   │   ├── Makefile.projbuild
│   │   ├── component.mk
│   │   └── src/
│   │       ├── Makefile
│   │       ├── Makefile.original
│   │       ├── README.md
│   │       ├── appveyor.yml
│   │       ├── main.cpp
│   │       ├── mkspiffs
│   │       ├── spiffs/
│   │       │   ├── esp_spiffs.c
│   │       │   ├── esp_spiffs.h
│   │       │   ├── spiffs.h
│   │       │   ├── spiffs_cache.c
│   │       │   ├── spiffs_check.c
│   │       │   ├── spiffs_config.h
│   │       │   ├── spiffs_gc.c
│   │       │   ├── spiffs_hydrogen.c
│   │       │   ├── spiffs_nucleus.c
│   │       │   └── spiffs_nucleus.h
│   │       └── tclap/
│   │           ├── Arg.h
│   │           ├── ArgException.h
│   │           ├── ArgTraits.h
│   │           ├── COPYING
│   │           ├── CmdLine.h
│   │           ├── CmdLineInterface.h
│   │           ├── CmdLineOutput.h
│   │           ├── Constraint.h
│   │           ├── DocBookOutput.h
│   │           ├── HelpVisitor.h
│   │           ├── IgnoreRestVisitor.h
│   │           ├── MultiArg.h
│   │           ├── MultiSwitchArg.h
│   │           ├── OptionalUnlabeledTracker.h
│   │           ├── StandardTraits.h
│   │           ├── StdOutput.h
│   │           ├── SwitchArg.h
│   │           ├── UnlabeledMultiArg.h
│   │           ├── UnlabeledValueArg.h
│   │           ├── ValueArg.h
│   │           ├── ValuesConstraint.h
│   │           ├── VersionVisitor.h
│   │           ├── Visitor.h
│   │           ├── XorHandler.h
│   │           └── ZshCompletionOutput.h
│   ├── spidriver/
│   │   ├── component.mk
│   │   ├── spi_master_lobo.c
│   │   └── spi_master_lobo.h
│   ├── spiffs/
│   │   ├── component.mk
│   │   ├── esp_spiffs.c
│   │   ├── esp_spiffs.h
│   │   ├── list.c
│   │   ├── list.h
│   │   ├── mutex.c
│   │   ├── mutex.h
│   │   ├── spiffs.h
│   │   ├── spiffs_cache.c
│   │   ├── spiffs_check.c
│   │   ├── spiffs_config.h
│   │   ├── spiffs_gc.c
│   │   ├── spiffs_hydrogen.c
│   │   ├── spiffs_nucleus.c
│   │   ├── spiffs_nucleus.h
│   │   ├── spiffs_vfs.c
│   │   └── spiffs_vfs.h
│   └── spiffs_image/
│       ├── Makefile.projbuild
│       ├── component.mk
│       ├── image/
│       │   ├── fonts/
│       │   │   ├── BigFont.fon
│       │   │   ├── DejaVuSans12.fon
│       │   │   ├── DejaVuSans18.fon
│       │   │   ├── DejaVuSans24.fon
│       │   │   ├── DotMatrix_M.fon
│       │   │   ├── Grotesk24x48.fon
│       │   │   ├── SmallFont.fon
│       │   │   ├── Ubuntu.fon
│       │   │   ├── arial_bold.fon
│       │   │   ├── ocrfont.c
│       │   │   └── swiss721_outline.fon
│       │   └── spiffs.info
│       └── spiffs_image.img
├── main/
│   ├── Kconfig.projbuild
│   ├── component.mk
│   ├── ePaper.c
│   ├── ePaper.h
│   ├── img1.h
│   ├── img2.h
│   ├── img3.h
│   └── img_hacking.c
├── partitions_example.csv
└── sdkconfig.defaults

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
.config
*.o
*.pyc
*.a
*.d

# gtags
GTAGS
GRTAGS
GPATH

# emacs
.dir-locals.el

# emacs temp file suffixes
*~
.#*
\#*#

sdkconfig
sdkconfig.old
sdkconfig.lobo
.cproject
.project
.settings
BUILD
build/
temp/
local/
*.dis
*.elf
*.map
**/.DS_Store


================================================
FILE: Makefile
================================================
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#

PROJECT_NAME := ePaper

#EXTRA_CFLAGS += --save-temps

include $(IDF_PATH)/make/project.mk



================================================
FILE: README.md
================================================

### ePaper library for ESP32

---


#### Features

* Support for **GDEH029A1** / **SSD1608** based ePaper modules in 4-wire SPI mode. Support for other controllers will be added later
* **emulated** 4-bit gray scale mode
* **SPI displays oriented SPI driver library** based on *spi-master* driver
* Combined **DMA SPI** transfer mode and **direct SPI** for maximal speed
* **4-bit Grayscale mode** or **1-bit b/w mode** can be selected during runtime
* SPI speeds up to **20 MHz** are tested and works without problems
* **Demo application** included which demonstrates most of the library features


* **Graphics drawing functions**:
  * **EPD_drawPixel**  Draw pixel at given x,y coordinates
  * **EPD_drawLine**  Draw line between two points
  * **EPD_drawFastVLine**, **EPD_drawFastHLine**  Draw vertical or horizontal line of given lenght
  * **EPD_drawLineByAngle**  Draw line on screen from (x,y) point at given angle
  * **EPD_drawRect**, **EPD_fillRect**  Draw rectangle on screen or fill given rectangular screen region with color
  * **EPD_drawRoundRect**, **EPD_fillRoundRect**  Draw rectangle on screen or fill given rectangular screen region with color with rounded corners
  * **EPD_drawCircle**, **EPD_fillCircle**  Draw or fill circle on screen
  * **EPD_drawEllipse**, **EPD_fillEllipse**  Draw or fill ellipse on screen
  * **EPD_drawTriangel**, **EPD_fillTriangle**  Draw or fill triangle on screen
  * **EPD_drawArc**  Draw circle arc on screen, from ~ to given angles, with given thickness. Can be outlined with different color
  * **EPD_drawPolygon**  Draw poligon on screen with given number of sides (3~60). Can be outlined with different color and rotated by given angle.
* **Fonts**:
  * **fixed** width and proportional fonts are supported; 8 fonts embeded
  * unlimited number of **fonts from file**
  * **7-segment vector font** with variable width/height is included (only numbers and few characters)
  * Proportional fonts can be used in fixed width mode.
  * Related functions:
    * **EPD_setFont**  Set current font from one of embeded fonts or font file
    * **EPD_getfontsize**  Returns current font height & width in pixels.
    * **EPD_getfontheight**  Returns current font height in pixels.
    * **set_7seg_font_atrib**  Set atributes for 7 segment vector font
    * **getFontCharacters**  Get all font's characters to buffer
* **String write function**:
  * **EPD_print**  Write text to display.
    * Strings can be printed at **any angle**. Rotation of the displayed text depends on *font_ratate* variable (0~360)
    * if *font_transparent* variable is set to 1, no background pixels will be printed
    * If the text does not fit the screen/window width it will be clipped ( if *text_wrap=0* ), or continued on next line ( if *text_wrap=1* )
    * Two special characters are allowed in strings: *\r* CR (0x0D), clears the display to EOL, *\n* LF (ox0A), continues to the new line, x=0
    * Special values can be entered for X position:
      * *CENTER*  centers the text
      * *RIGHT*   right justifies the text horizontaly
      * *LASTX*   continues from last X position; offset can be used: *LASTX+n*
    * Special values can be entered for Y:
      * *CENTER*  centers the text verticaly
      * *BOTTOM*  bottom justifies the text
      * *LASTY*   continues from last Y position; offset can be used: *LASTY+n*
  * **EPD_getStringWidth** Returns the string width in pixels based on current font characteristics. Useful for positioning strings on the screen.
  * **EPD_clearStringRect** Fills the rectangle occupied by string with current background color
* **Images**:
  * **EPD_jpg_image**  Decodes and displays JPG images
    * Limits:
      * Baseline only. Progressive and Lossless JPEG format are not supported.
      * Image size: Up to 65520 x 65520 pixels
      * Color space: YCbCr three components only. Gray scale image is not supported.
      * Sampling factor: 4:4:4, 4:2:2 or 4:2:0.
    * Can display the image **from file** or **memory buffer**
    * Image can be **scaled** by factor 0 ~ 3  (1/1, 1/2, 1/4 or 1/8)
    * Image is displayed from X,Y position on screen/window:
      * X: image left position; constants CENTER & RIGHT can be used; *negative* value is accepted
      * Y: image top position;  constants CENTER & BOTTOM can be used; *negative* value is accepted
    * Image is converted to **4-bit Gray Scale mode**
* **Other display functions**:
  * **EPD_fillScreen**  Fill the whole screen with black, white or gray scale
* **compile_font_file**  Function which compiles font c source file to font file which can be used in *EPD_setFont()* function to select external font. Created file have the same name as source file and extension *.fnt*


* **Global wariables**
  * **orientation**  current screen orientation
  * **font_ratate**  current font rotate angle (0~395)
  * **font_transparent**  if not 0 draw fonts transparent
  * **font_forceFixed**  if not zero force drawing proportional fonts with fixed width
  * **text_wrap**  if not 0 wrap long text to the new line, else clip
  * **_fg**  current foreground color for fonts
  * **_bg**  current background for non transparent fonts
  * **_angleOffset**  angle offset for arc, polygon and line by angle functions
  * **image_debug**  print debug messages during image decode if set to 1
  * **cfont**  Currently used font structure
  * **EPD_X**  X position of the next character after EPD_print() function
  * **EPD_Y**  Y position of the next character after EPD_print() function
  * **_gs**  use 4-bit Gray scale if set to 1
  * **_width** screen width (larger dimension) in pixels
  * **_height** screen height (smaller dimension) in pixels

---

Full functions **syntax and descriptions** can be found in *EPD.h* and *EPDspi.h* files.

Full **demo application**, well documented, is included, please **analyze it** to learn how to use the library functions.

---

#### Connecting the display

To run the demo, attach display module to ESP32. Default pins used are:
* mosi: 23
*  sck: 18
*   CS:  5 (display CS)
*   DC: 26 (display DC)
*  RST: 27 (display RESET)
* BUSY: 32 (display BUSY output)

The display can be powered from 3.3V or from **GPIO pin**. See *EPDspi.h* for configuration options.

**If you want to use different pins, change them in** *EPDspi.h*

Using *make menuconfig* **select tick rate 1000** ( → Component config → FreeRTOS → Tick rate (Hz) ) to get more accurate timings

---

#### How to build

Configure your esp32 build environment as for **esp-idf examples**

Clone the repository

`git clone https://github.com/loboris/ESP32_ePaper_example.git`

Execute menuconfig and configure your Serial flash config and other settings. Included *sdkconfig.defaults* sets some defaults to be used.

Navigate to **ePaper Display DEMO Configuration** and set **SPIFFS** options.

Select if you want to use **wifi** (recommended) to get the time from **NTP** server and set your WiFi SSID and password.

`make menuconfig`

Make and flash the example.

`make all && make flash`

---

#### Prepare **SPIFFS** image

*The demo uses some image and font files and it is necessary to flash the spiffs image*

**To flash already prepared image** *components/spiffs_image/spiffs_image.img* execute:

`make copyfs`

---

You can also prepare different SFPIFFS **image** and flash it to ESP32.

Files to be included on spiffs are already in **components/spiffs_image/image/** directory. You can add or remove the files you want to include.

Then execute:

`make makefs`

to create **spiffs image** in *build* directory **without flashing** to ESP32

Or execute:

`make flashfs`

to create **spiffs image** in *build* directory and **flash** it to ESP32

---

Tested on Waveshare 2.9" ePaper module connected to SparkFun ESP32 Thing board.
![Tested on](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/2.9inch-e-paper-module-4.jpg)

---

![Fonts](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/EPD-fonts.jpg)
![Rotated](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/EPD-Rotated.jpg)
![7-segFont](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/EPD-7sef_font.jpg)
![Grayscale](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/EPD_Grayscale.jpg)
![No power](https://raw.githubusercontent.com/loboris/ESP32_ePaper_example/master/Documents/EPD-No_power.jpg)


================================================
FILE: components/epaper/DefaultFont.c
================================================
// Default font

// ========================================================================
// This comes with no warranty, implied or otherwise

// This data structure was designed to support Proportional fonts
// fonts. Individual characters do not have to be multiples of 8 bits wide.
// Any width is fine and does not need to be fixed.

// The data bits are packed to minimize data requirements, but the tradeoff
// is that a header is required per character.

// Header Format:
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset	(start Y of visible pixels)
// Width				(width of the visible pixels)
// Height				(height of the visible pixels)
// xOffset				(start X of visible pixels)
// xDelta				(the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.
// ========================================================================

// dejavu
// Point Size   : 12
// Memory usage : 1158 bytes
// # characters : 95

const unsigned char tft_DefaultFont[] =
{
0x00, 0x0B, 0x86, 0x04,

// ' '
0x20,0x0A,0x00,0x00,0x00,0x04,

// '!'
0x21,0x01,0x01,0x09,0x02,0x05,
0xFD,0x80,
// '"'
0x22,0x01,0x03,0x03,0x01,0x05,
0xB6,0x80,
// '#'
0x23,0x02,0x08,0x08,0x01,0x0A,
0x12,0x14,0x7F,0x24,0x24,0xFE,0x28,0x48,
// '$'
0x24,0x01,0x06,0x0B,0x02,0x08,
0x21,0xCA,0xA8,0xE0,0xE2,0xAA,0x70,0x82,0x00,
// '%'
0x25,0x01,0x0A,0x09,0x00,0x0B,
0x61,0x24,0x89,0x22,0x50,0x6D,0x82,0x91,0x24,0x49,0x21,0x80,
// '&'
0x26,0x01,0x09,0x09,0x01,0x0A,
0x30,0x24,0x10,0x0C,0x05,0x14,0x4A,0x19,0x8C,0x7B,0x00,
// '''
0x27,0x01,0x01,0x03,0x01,0x03,
0xE0,
// '('
0x28,0x00,0x03,0x0B,0x01,0x05,
0x69,0x49,0x24,0x48,0x80,
// ')'
0x29,0x00,0x03,0x0B,0x01,0x05,
0x89,0x12,0x49,0x4A,0x00,
// '*'
0x2A,0x01,0x05,0x06,0x01,0x06,
0x25,0x5C,0xEA,0x90,
// '+'
0x2B,0x03,0x07,0x07,0x01,0x0A,
0x10,0x20,0x47,0xF1,0x02,0x04,0x00,
// ','
0x2C,0x08,0x01,0x03,0x01,0x04,
0xE0,
// '-'
0x2D,0x06,0x03,0x01,0x01,0x04,
0xE0,
// '.'
0x2E,0x08,0x01,0x02,0x01,0x04,
0xC0,
// '/'
0x2F,0x01,0x04,0x0A,0x00,0x04,
0x11,0x22,0x24,0x44,0x88,
// '0'
0x30,0x01,0x06,0x09,0x01,0x08,
0x79,0x28,0x61,0x86,0x18,0x52,0x78,
// '1'
0x31,0x01,0x05,0x09,0x01,0x08,
0xE1,0x08,0x42,0x10,0x84,0xF8,
// '2'
0x32,0x01,0x07,0x09,0x01,0x08,
0x79,0x18,0x10,0x20,0x82,0x08,0x20,0xFC,
// '3'
0x33,0x01,0x06,0x09,0x01,0x08,
0x7A,0x10,0x41,0x38,0x30,0x63,0x78,
// '4'
0x34,0x01,0x06,0x09,0x01,0x08,
0x18,0x62,0x92,0x4A,0x2F,0xC2,0x08,
// '5'
0x35,0x01,0x06,0x09,0x01,0x08,
0xFA,0x08,0x3C,0x0C,0x10,0x63,0x78,
// '6'
0x36,0x01,0x06,0x09,0x01,0x08,
0x39,0x18,0x3E,0xCE,0x18,0x53,0x78,
// '7'
0x37,0x01,0x06,0x09,0x01,0x08,
0xFC,0x10,0x82,0x10,0x42,0x08,0x40,
// '8'
0x38,0x01,0x06,0x09,0x01,0x08,
0x7B,0x38,0x73,0x7B,0x38,0x73,0x78,
// '9'
0x39,0x01,0x06,0x09,0x01,0x08,
0x7B,0x28,0x61,0xCD,0xD0,0x62,0x70,
// ':'
0x3A,0x04,0x01,0x06,0x01,0x04,
0xCC,
// ';'
0x3B,0x04,0x01,0x07,0x01,0x04,
0xCE,
// '<'
0x3C,0x03,0x08,0x06,0x01,0x0A,
0x03,0x1E,0xE0,0xE0,0x1E,0x03,
// '='
0x3D,0x05,0x08,0x03,0x01,0x0A,
0xFF,0x00,0xFF,
// '>'
0x3E,0x03,0x08,0x06,0x01,0x0A,
0xC0,0x78,0x07,0x07,0x78,0xC0,
// '?'
0x3F,0x01,0x05,0x09,0x00,0x06,
0x74,0x42,0x22,0x10,0x04,0x20,
// '@'
0x40,0x01,0x0B,0x0B,0x01,0x0D,
0x1F,0x06,0x19,0x01,0x46,0x99,0x13,0x22,0x64,0x54,0x6C,0x40,0x04,0x10,0x7C,0x00,
// 'A'
0x41,0x01,0x08,0x09,0x00,0x08,
0x18,0x18,0x24,0x24,0x24,0x42,0x7E,0x42,0x81,
// 'B'
0x42,0x01,0x06,0x09,0x01,0x08,
0xFA,0x18,0x61,0xFA,0x18,0x61,0xF8,
// 'C'
0x43,0x01,0x06,0x09,0x01,0x08,
0x39,0x18,0x20,0x82,0x08,0x11,0x38,
// 'D'
0x44,0x01,0x07,0x09,0x01,0x09,
0xF9,0x0A,0x0C,0x18,0x30,0x60,0xC2,0xF8,
// 'E'
0x45,0x01,0x06,0x09,0x01,0x08,
0xFE,0x08,0x20,0xFE,0x08,0x20,0xFC,
// 'F'
0x46,0x01,0x05,0x09,0x01,0x07,
0xFC,0x21,0x0F,0xC2,0x10,0x80,
// 'G'
0x47,0x01,0x07,0x09,0x01,0x09,
0x3C,0x86,0x04,0x08,0xF0,0x60,0xA1,0x3C,
// 'H'
0x48,0x01,0x07,0x09,0x01,0x09,
0x83,0x06,0x0C,0x1F,0xF0,0x60,0xC1,0x82,
// 'I'
0x49,0x01,0x01,0x09,0x01,0x03,
0xFF,0x80,
// 'J'
0x4A,0x01,0x03,0x0B,0xFF,0x03,
0x24,0x92,0x49,0x27,0x00,
// 'K'
0x4B,0x01,0x07,0x09,0x01,0x07,
0x85,0x12,0x45,0x0C,0x14,0x24,0x44,0x84,
// 'L'
0x4C,0x01,0x05,0x09,0x01,0x06,
0x84,0x21,0x08,0x42,0x10,0xF8,
// 'M'
0x4D,0x01,0x08,0x09,0x01,0x0A,
0x81,0xC3,0xC3,0xA5,0xA5,0x99,0x99,0x81,0x81,
// 'N'
0x4E,0x01,0x07,0x09,0x01,0x09,
0xC3,0x86,0x8D,0x19,0x31,0x62,0xC3,0x86,
// 'O'
0x4F,0x01,0x07,0x09,0x01,0x09,
0x38,0x8A,0x0C,0x18,0x30,0x60,0xA2,0x38,
// 'P'
0x50,0x01,0x06,0x09,0x01,0x08,
0xFA,0x38,0x63,0xFA,0x08,0x20,0x80,
// 'Q'
0x51,0x01,0x07,0x0B,0x01,0x09,
0x38,0x8A,0x0C,0x18,0x30,0x60,0xA2,0x38,0x10,0x10,
// 'R'
0x52,0x01,0x07,0x09,0x01,0x08,
0xF9,0x1A,0x14,0x6F,0x91,0x21,0x42,0x82,
// 'S'
0x53,0x01,0x06,0x09,0x01,0x08,
0x7B,0x18,0x30,0x78,0x30,0x63,0x78,
// 'T'
0x54,0x01,0x07,0x09,0x00,0x07,
0xFE,0x20,0x40,0x81,0x02,0x04,0x08,0x10,
// 'U'
0x55,0x01,0x07,0x09,0x01,0x09,
0x83,0x06,0x0C,0x18,0x30,0x60,0xA2,0x38,
// 'V'
0x56,0x01,0x0A,0x09,0xFF,0x08,
0x40,0x90,0x22,0x10,0x84,0x21,0x04,0x81,0x20,0x30,0x0C,0x00,
// 'W'
0x57,0x01,0x0B,0x09,0x00,0x0B,
0x84,0x28,0x89,0x11,0x27,0x22,0xA8,0x55,0x0E,0xE0,0x88,0x11,0x00,
// 'X'
0x58,0x01,0x07,0x09,0x00,0x07,
0xC6,0x88,0xA1,0xC1,0x07,0x0A,0x22,0x82,
// 'Y'
0x59,0x01,0x07,0x09,0x00,0x07,
0x82,0x89,0x11,0x43,0x82,0x04,0x08,0x10,
// 'Z'
0x5A,0x01,0x07,0x09,0x01,0x09,
0xFE,0x04,0x10,0x41,0x04,0x10,0x40,0xFE,
// '['
0x5B,0x01,0x02,0x0B,0x02,0x05,
0xEA,0xAA,0xAC,
// '\'
0x5C,0x01,0x04,0x0A,0x00,0x04,
0x88,0x44,0x42,0x22,0x11,
// ']'
0x5D,0x01,0x02,0x0B,0x01,0x05,
0xD5,0x55,0x5C,
// '^'
0x5E,0x01,0x08,0x03,0x01,0x0A,
0x18,0x24,0x42,
// '_'
0x5F,0x0C,0x06,0x01,0x00,0x06,
0xFC,
// '`'
0x60,0x00,0x03,0x02,0x01,0x06,
0x44,
// 'a'
0x61,0x03,0x06,0x07,0x01,0x08,
0x7A,0x30,0x5F,0x86,0x37,0x40,
// 'b'
0x62,0x00,0x06,0x0A,0x01,0x08,
0x82,0x08,0x2E,0xCA,0x18,0x61,0xCE,0xE0,
// 'c'
0x63,0x03,0x05,0x07,0x01,0x07,
0x72,0x61,0x08,0x25,0xC0,
// 'd'
0x64,0x00,0x06,0x0A,0x01,0x08,
0x04,0x10,0x5D,0xCE,0x18,0x61,0xCD,0xD0,
// 'e'
0x65,0x03,0x06,0x07,0x01,0x08,
0x39,0x38,0x7F,0x81,0x13,0x80,
// 'f'
0x66,0x00,0x04,0x0A,0x00,0x04,
0x34,0x4F,0x44,0x44,0x44,
// 'g'
0x67,0x03,0x06,0x0A,0x01,0x08,
0x77,0x38,0x61,0x87,0x37,0x41,0x4C,0xE0,
// 'h'
0x68,0x00,0x06,0x0A,0x01,0x08,
0x82,0x08,0x2E,0xC6,0x18,0x61,0x86,0x10,
// 'i'
0x69,0x01,0x01,0x09,0x01,0x03,
0xBF,0x80,
// 'j'
0x6A,0x01,0x02,0x0C,0x00,0x03,
0x45,0x55,0x56,
// 'k'
0x6B,0x00,0x06,0x0A,0x01,0x07,
0x82,0x08,0x22,0x92,0x8E,0x28,0x92,0x20,
// 'l'
0x6C,0x00,0x01,0x0A,0x01,0x03,
0xFF,0xC0,
// 'm'
0x6D,0x03,0x09,0x07,0x01,0x0B,
0xB3,0x66,0x62,0x31,0x18,0x8C,0x46,0x22,
// 'n'
0x6E,0x03,0x06,0x07,0x01,0x08,
0xBB,0x18,0x61,0x86,0x18,0x40,
// 'o'
0x6F,0x03,0x06,0x07,0x01,0x08,
0x7B,0x38,0x61,0x87,0x37,0x80,
// 'p'
0x70,0x03,0x06,0x0A,0x01,0x08,
0xBB,0x28,0x61,0x87,0x3B,0xA0,0x82,0x00,
// 'q'
0x71,0x03,0x06,0x0A,0x01,0x08,
0x77,0x38,0x61,0x87,0x37,0x41,0x04,0x10,
// 'r'
0x72,0x03,0x04,0x07,0x01,0x05,
0xBC,0x88,0x88,0x80,
// 's'
0x73,0x03,0x06,0x07,0x01,0x07,
0x72,0x28,0x1C,0x0A,0x27,0x00,
// 't'
0x74,0x01,0x04,0x09,0x00,0x05,
0x44,0xF4,0x44,0x44,0x30,
// 'u'
0x75,0x03,0x06,0x07,0x01,0x08,
0x86,0x18,0x61,0x86,0x37,0x40,
// 'v'
0x76,0x03,0x08,0x07,0xFF,0x06,
0x42,0x42,0x24,0x24,0x24,0x18,0x18,
// 'w'
0x77,0x03,0x09,0x07,0x00,0x09,
0x88,0xC4,0x57,0x4A,0xA5,0x51,0x10,0x88,
// 'x'
0x78,0x03,0x06,0x07,0x00,0x06,
0x85,0x24,0x8C,0x49,0x28,0x40,
// 'y'
0x79,0x03,0x08,0x0A,0xFF,0x06,
0x42,0x42,0x24,0x24,0x14,0x18,0x08,0x08,0x10,0x60,
// 'z'
0x7A,0x03,0x05,0x07,0x00,0x05,
0xF8,0x44,0x44,0x43,0xE0,
// '{'
0x7B,0x01,0x05,0x0B,0x02,0x08,
0x19,0x08,0x42,0x60,0x84,0x21,0x06,
// '|'
0x7C,0x01,0x01,0x0C,0x02,0x04,
0xFF,0xF0,
// '}'
0x7D,0x01,0x05,0x0B,0x01,0x08,
0xC1,0x08,0x42,0x0C,0x84,0x21,0x30,
// '~'
0x7E,0x04,0x08,0x03,0x01,0x0A,
0x00,0x71,0x8E,

// Terminator
0xFF
};


================================================
FILE: components/epaper/DejaVuSans18.c
================================================
// ============================================================================
// Proportional font Header Format:
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset
// Width
// Height
// xOffset
// xDelta (the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.
// ============================================================================

// DejaVuSans
// Point Size   : 18
// Memory usage : 1828 bytes
// # characters : 95

const unsigned char tft_Dejavu18x[] =
{
0x00, 0x12, 0x00, 0x00,

// ' '
0x20,0x0E,0x00,0x00,0x00,0x06,

// '!'
0x21,0x01,0x02,0x0D,0x03,0x07,
0xFF,0xFF,0xC3,0xC0,
// '"'
0x22,0x01,0x06,0x05,0x01,0x08,
0xCF,0x3C,0xF3,0xCC,
// '#'
0x23,0x00,0x0C,0x0E,0x01,0x0F,
0x04,0x40,0x44,0x0C,0xC0,0xC8,0x7F,0xF7,0xFF,0x09,0x81,0x90,0xFF,0xEF,0xFE,0x13,0x03,0x30,0x32,0x02,0x20,
// '$'
0x24,0x00,0x0A,0x11,0x01,0x0B,
0x08,0x02,0x03,0xE1,0xFC,0xE9,0x32,0x0F,0x81,0xF8,0x0F,0x02,0x60,0x9A,0x2E,0xFF,0x1F,0x80,0x80,0x20,0x08,0x00,
// '%'
0x25,0x01,0x0F,0x0D,0x01,0x11,
0x78,0x10,0x90,0x43,0x31,0x86,0x62,0x0C,0xC8,0x19,0x10,0x1E,0x4F,0x01,0x12,0x02,0x66,0x08,0xCC,0x31,0x98,0x41,0x21,0x03,0xC0,
// '&'
0x26,0x01,0x0C,0x0D,0x01,0x0D,
0x0F,0x01,0xF8,0x30,0x83,0x00,0x38,0x03,0xC0,0x7E,0x6C,0x76,0xC3,0xCC,0x18,0xE1,0xC7,0xFE,0x3E,0x70,
// '''
0x27,0x01,0x02,0x05,0x01,0x04,
0xFF,0xC0,
// '('
0x28,0x00,0x04,0x10,0x02,0x07,
0x32,0x66,0x4C,0xCC,0xCC,0xC4,0x66,0x23,
// ')'
0x29,0x00,0x04,0x10,0x01,0x07,
0xC4,0x66,0x23,0x33,0x33,0x32,0x66,0x4C,
// '*'
0x2A,0x01,0x07,0x08,0x01,0x09,
0x11,0x25,0x51,0xC3,0x8A,0xA4,0x88,
// '+'
0x2B,0x02,0x0C,0x0C,0x02,0x0F,
0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x0F,0xFF,0xFF,0xF0,0x60,0x06,0x00,0x60,0x06,0x00,0x60,
// ','
0x2C,0x0C,0x03,0x04,0x01,0x06,
0x6D,0x40,
// '-'
0x2D,0x08,0x05,0x02,0x01,0x07,
0xFF,0xC0,
// '.'
0x2E,0x0C,0x02,0x02,0x02,0x06,
0xF0,
// '/'
0x2F,0x01,0x06,0x0F,0x00,0x06,
0x0C,0x31,0x86,0x18,0xE3,0x0C,0x31,0xC6,0x18,0x63,0x0C,0x00,
// '0'
0x30,0x01,0x09,0x0D,0x01,0x0B,
0x3E,0x3F,0x98,0xD8,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xD8,0xCF,0xE3,0xE0,
// '1'
0x31,0x01,0x08,0x0D,0x02,0x0B,
0x38,0xF8,0xD8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xFF,
// '2'
0x32,0x01,0x09,0x0D,0x01,0x0B,
0x7C,0x7F,0x21,0xC0,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x1F,0xEF,0xF0,
// '3'
0x33,0x01,0x09,0x0D,0x01,0x0B,
0x7E,0x7F,0xA0,0xE0,0x30,0x39,0xF0,0xFC,0x07,0x01,0x80,0xE0,0xFF,0xE7,0xE0,
// '4'
0x34,0x01,0x0A,0x0D,0x01,0x0B,
0x07,0x01,0xC0,0xB0,0x6C,0x13,0x08,0xC6,0x31,0x0C,0xFF,0xFF,0xF0,0x30,0x0C,0x03,0x00,
// '5'
0x35,0x01,0x08,0x0D,0x01,0x0B,
0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x47,0x03,0x03,0x03,0x87,0xFE,0x7C,
// '6'
0x36,0x01,0x09,0x0D,0x01,0x0B,
0x1E,0x1F,0x9C,0x5C,0x0C,0x06,0xF3,0xFD,0xC7,0xC1,0xE0,0xD8,0xEF,0xE1,0xE0,
// '7'
0x37,0x01,0x08,0x0D,0x01,0x0B,
0xFF,0xFF,0x06,0x06,0x06,0x0E,0x0C,0x0C,0x1C,0x18,0x18,0x38,0x30,
// '8'
0x38,0x01,0x09,0x0D,0x01,0x0B,
0x3E,0x3F,0xB8,0xF8,0x3E,0x39,0xF1,0xFD,0xC7,0xC1,0xE0,0xF8,0xEF,0xE3,0xE0,
// '9'
0x39,0x01,0x09,0x0D,0x01,0x0B,
0x3C,0x3F,0xB8,0xD8,0x3C,0x1F,0x1D,0xFE,0x7B,0x01,0x81,0xD1,0xCF,0xC3,0xC0,
// ':'
0x3A,0x05,0x02,0x09,0x02,0x06,
0xF0,0x03,0xC0,
// ';'
0x3B,0x05,0x03,0x0B,0x01,0x06,
0x6C,0x00,0x03,0x6A,0x00,
// '<'
0x3C,0x04,0x0B,0x0A,0x02,0x0F,
0x00,0x20,0x3C,0x1F,0x1F,0x0F,0x81,0xF0,0x0F,0x80,0x3E,0x01,0xE0,0x04,
// '='
0x3D,0x05,0x0B,0x06,0x02,0x0F,
0xFF,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0xC0,
// '>'
0x3E,0x04,0x0B,0x0A,0x02,0x0F,
0x80,0x1E,0x01,0xF0,0x07,0xC0,0x3E,0x07,0xC3,0xE3,0xE0,0xF0,0x10,0x00,
// '?'
0x3F,0x01,0x07,0x0D,0x01,0x0A,
0x79,0xFA,0x38,0x30,0x61,0x86,0x18,0x30,0x60,0x01,0x83,0x00,
// '@'
0x40,0x01,0x10,0x10,0x01,0x12,
0x07,0xE0,0x1F,0xF8,0x3C,0x1C,0x70,0x06,0x60,0x07,0xE3,0x63,0xC7,0xE3,0xC6,0x63,0xC6,0x66,0xC7,0xFC,0xE3,0x70,0x60,0x00,0x70,0x00,0x3C,0x30,0x1F,0xF0,0x07,0xC0,
// 'A'
0x41,0x01,0x0C,0x0D,0x00,0x0C,
0x06,0x00,0x60,0x0F,0x00,0xF0,0x19,0x81,0x98,0x19,0x83,0x0C,0x3F,0xC7,0xFE,0x60,0x66,0x06,0xC0,0x30,
// 'B'
0x42,0x01,0x09,0x0D,0x02,0x0C,
0xFC,0x7F,0xB0,0xD8,0x6C,0x37,0xF3,0xF9,0x86,0xC1,0xE0,0xF0,0xFF,0xEF,0xE0,
// 'C'
0x43,0x01,0x0B,0x0D,0x01,0x0D,
0x0F,0xC7,0xFD,0xC0,0xB0,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x0C,0x01,0xC0,0x9F,0xF0,0xFC,
// 'D'
0x44,0x01,0x0B,0x0D,0x02,0x0E,
0xFE,0x1F,0xF3,0x07,0x60,0x6C,0x07,0x80,0xF0,0x1E,0x03,0xC0,0x78,0x1B,0x07,0x7F,0xCF,0xE0,
// 'E'
0x45,0x01,0x08,0x0D,0x02,0x0B,
0xFF,0xFF,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,
// 'F'
0x46,0x01,0x08,0x0D,0x02,0x0A,
0xFF,0xFF,0xC0,0xC0,0xC0,0xFE,0xFE,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
// 'G'
0x47,0x01,0x0B,0x0D,0x01,0x0E,
0x0F,0xC7,0xFD,0xC0,0xB0,0x0C,0x01,0x87,0xF0,0xFE,0x03,0xC0,0x6C,0x0D,0xC1,0x9F,0xE0,0xF8,
// 'H'
0x48,0x01,0x0A,0x0D,0x02,0x0E,
0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xFF,0xFF,0xFF,0x03,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xC0,
// 'I'
0x49,0x01,0x02,0x0D,0x02,0x06,
0xFF,0xFF,0xFF,0xC0,
// 'J'
0x4A,0x01,0x05,0x11,0xFF,0x06,
0x18,0xC6,0x31,0x8C,0x63,0x18,0xC6,0x31,0x8C,0xFE,0xE0,
// 'K'
0x4B,0x01,0x0B,0x0D,0x02,0x0C,
0xC1,0x98,0x63,0x18,0x66,0x0D,0x81,0xE0,0x3C,0x06,0xC0,0xCC,0x18,0xC3,0x0C,0x60,0xCC,0x0C,
// 'L'
0x4C,0x01,0x08,0x0D,0x02,0x0A,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,
// 'M'
0x4D,0x01,0x0C,0x0D,0x02,0x10,
0xE0,0x7F,0x0F,0xF0,0xFD,0x8B,0xD9,0xBD,0x9B,0xCF,0x3C,0xF3,0xC6,0x3C,0x63,0xC0,0x3C,0x03,0xC0,0x30,
// 'N'
0x4E,0x01,0x0A,0x0D,0x02,0x0E,
0xE0,0xF8,0x3F,0x0F,0xC3,0xD8,0xF6,0x3C,0xCF,0x1B,0xC6,0xF0,0xFC,0x3F,0x07,0xC1,0xC0,
// 'O'
0x4F,0x01,0x0C,0x0D,0x01,0x0E,
0x1F,0x83,0xFC,0x70,0xE6,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x70,0xE3,0xFC,0x1F,0x80,
// 'P'
0x50,0x01,0x08,0x0D,0x02,0x0B,
0xFC,0xFE,0xC7,0xC3,0xC3,0xC7,0xFE,0xFC,0xC0,0xC0,0xC0,0xC0,0xC0,
// 'Q'
0x51,0x01,0x0C,0x0F,0x01,0x0E,
0x1F,0x83,0xFC,0x70,0xE6,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x70,0xE3,0xFC,0x1F,0x80,0x18,0x00,0xC0,
// 'R'
0x52,0x01,0x0A,0x0D,0x02,0x0D,
0xFC,0x3F,0x8C,0x73,0x0C,0xC3,0x31,0xCF,0xE3,0xF0,0xC6,0x30,0xCC,0x33,0x06,0xC1,0xC0,
// 'S'
0x53,0x01,0x0A,0x0D,0x01,0x0B,
0x3E,0x1F,0xCE,0x13,0x00,0xC0,0x1F,0x03,0xF0,0x0E,0x01,0x80,0x68,0x3B,0xFC,0x7E,0x00,
// 'T'
0x54,0x01,0x0C,0x0D,0x00,0x0C,
0xFF,0xFF,0xFF,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,
// 'U'
0x55,0x01,0x0A,0x0D,0x02,0x0E,
0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x36,0x19,0xFE,0x1E,0x00,
// 'V'
0x56,0x01,0x0C,0x0D,0x00,0x0C,
0xC0,0x36,0x06,0x60,0x66,0x06,0x30,0xC3,0x0C,0x19,0x81,0x98,0x19,0x80,0xF0,0x0F,0x00,0x60,0x06,0x00,
// 'W'
0x57,0x01,0x11,0x0D,0x01,0x13,
0xC1,0xC1,0xE0,0xE0,0xD8,0xF8,0xCC,0x6C,0x66,0x36,0x33,0x1B,0x18,0xD8,0xD8,0x6C,0x6C,0x36,0x36,0x1F,0x1F,0x07,0x07,0x03,0x83,0x81,0xC1,0xC0,
// 'X'
0x58,0x01,0x0B,0x0D,0x01,0x0D,
0x70,0xE6,0x18,0xE6,0x0D,0xC0,0xF0,0x1C,0x03,0x80,0x78,0x1B,0x07,0x30,0xC7,0x30,0x6E,0x0E,
// 'Y'
0x59,0x01,0x0C,0x0D,0x00,0x0C,
0xE0,0x76,0x06,0x30,0xC1,0x98,0x19,0x80,0xF0,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,
// 'Z'
0x5A,0x01,0x0B,0x0D,0x01,0x0D,
0xFF,0xFF,0xFC,0x07,0x01,0xC0,0x30,0x0E,0x03,0x80,0xE0,0x18,0x06,0x01,0xC0,0x7F,0xFF,0xFE,
// '['
0x5B,0x00,0x04,0x10,0x01,0x07,
0xFF,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFF,
// '\'
0x5C,0x01,0x06,0x0F,0x00,0x06,
0xC3,0x06,0x18,0x61,0xC3,0x0C,0x30,0xE1,0x86,0x18,0x30,0xC0,
// ']'
0x5D,0x00,0x04,0x10,0x02,0x07,
0xFF,0x33,0x33,0x33,0x33,0x33,0x33,0xFF,
// '^'
0x5E,0x01,0x0B,0x05,0x02,0x0F,
0x0E,0x03,0xE0,0xC6,0x30,0x6C,0x06,
// '_'
0x5F,0x10,0x09,0x02,0x00,0x09,
0xFF,0xFF,0xC0,
// '`'
0x60,0x00,0x04,0x03,0x02,0x09,
0xC6,0x30,
// 'a'
0x61,0x04,0x08,0x0A,0x01,0x0A,
0x3C,0x7E,0x47,0x03,0x3F,0xFF,0xC3,0xC7,0xFF,0x7B,
// 'b'
0x62,0x00,0x09,0x0E,0x02,0x0B,
0xC0,0x60,0x30,0x18,0x0D,0xE7,0xFB,0x8F,0x83,0xC1,0xE0,0xF0,0x7C,0x7F,0xF6,0xF0,
// 'c'
0x63,0x04,0x08,0x0A,0x01,0x09,
0x1E,0x7F,0x61,0xC0,0xC0,0xC0,0xC0,0x61,0x7F,0x1E,
// 'd'
0x64,0x00,0x09,0x0E,0x01,0x0B,
0x01,0x80,0xC0,0x60,0x33,0xDB,0xFF,0x8F,0x83,0xC1,0xE0,0xF0,0x7C,0x77,0xF9,0xEC,
// 'e'
0x65,0x04,0x0A,0x0A,0x01,0x0B,
0x1F,0x1F,0xE6,0x1F,0x03,0xFF,0xFF,0xFC,0x01,0x81,0x7F,0xC7,0xE0,
// 'f'
0x66,0x00,0x07,0x0E,0x00,0x06,
0x1E,0x7C,0xC1,0x8F,0xFF,0xCC,0x18,0x30,0x60,0xC1,0x83,0x06,0x00,
// 'g'
0x67,0x04,0x09,0x0E,0x01,0x0B,
0x3D,0xBF,0xF8,0xF8,0x3C,0x1E,0x0F,0x07,0xC7,0x7F,0x9E,0xC0,0x68,0x67,0xF1,0xF0,
// 'h'
0x68,0x00,0x08,0x0E,0x02,0x0B,
0xC0,0xC0,0xC0,0xC0,0xDE,0xFE,0xE7,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,
// 'i'
0x69,0x00,0x02,0x0E,0x02,0x05,
0xF0,0xFF,0xFF,0xF0,
// 'j'
0x6A,0x00,0x04,0x12,0x00,0x05,
0x33,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0xEC,
// 'k'
0x6B,0x00,0x09,0x0E,0x02,0x0A,
0xC0,0x60,0x30,0x18,0x0C,0x36,0x33,0x31,0xB0,0xF0,0x78,0x36,0x19,0x8C,0x66,0x18,
// 'l'
0x6C,0x00,0x02,0x0E,0x02,0x05,
0xFF,0xFF,0xFF,0xF0,
// 'm'
0x6D,0x04,0x0E,0x0A,0x02,0x11,
0xDC,0x7B,0xFB,0xEE,0x79,0xF0,0xC3,0xC3,0x0F,0x0C,0x3C,0x30,0xF0,0xC3,0xC3,0x0F,0x0C,0x30,
// 'n'
0x6E,0x04,0x08,0x0A,0x02,0x0B,
0xDE,0xFE,0xE7,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,
// 'o'
0x6F,0x04,0x0A,0x0A,0x01,0x0B,
0x1E,0x1F,0xE6,0x1B,0x03,0xC0,0xF0,0x3C,0x0D,0x86,0x7F,0x87,0x80,
// 'p'
0x70,0x04,0x09,0x0E,0x02,0x0B,
0xDE,0x7F,0xB8,0xF8,0x3C,0x1E,0x0F,0x07,0xC7,0xFF,0x6F,0x30,0x18,0x0C,0x06,0x00,
// 'q'
0x71,0x04,0x09,0x0E,0x01,0x0B,
0x3D,0xBF,0xF8,0xF8,0x3C,0x1E,0x0F,0x07,0xC7,0x7F,0x9E,0xC0,0x60,0x30,0x18,0x0C,
// 'r'
0x72,0x04,0x06,0x0A,0x02,0x08,
0xDF,0xFE,0x30,0xC3,0x0C,0x30,0xC3,0x00,
// 's'
0x73,0x04,0x08,0x0A,0x01,0x08,
0x7C,0xFE,0xC2,0xE0,0x7C,0x1E,0x06,0x86,0xFE,0x78,
// 't'
0x74,0x01,0x06,0x0D,0x01,0x07,
0x61,0x86,0x3F,0xFD,0x86,0x18,0x61,0x86,0x1F,0x3C,
// 'u'
0x75,0x04,0x08,0x0A,0x02,0x0B,
0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xE7,0x7F,0x7B,
// 'v'
0x76,0x04,0x0C,0x0A,0x00,0x0B,
0x60,0x66,0x06,0x30,0xC3,0x0C,0x19,0x81,0x98,0x19,0x80,0xF0,0x0F,0x00,0x60,
// 'w'
0x77,0x04,0x0F,0x0A,0x01,0x10,
0x63,0x8C,0xC7,0x19,0x8E,0x31,0xB6,0xC3,0x6D,0x86,0xDB,0x0F,0x1E,0x0E,0x38,0x1C,0x70,0x38,0xE0,
// 'x'
0x78,0x04,0x0A,0x0A,0x01,0x0B,
0xE1,0xD8,0x63,0x30,0xCC,0x1E,0x07,0x83,0x30,0xCC,0x61,0xB8,0x70,
// 'y'
0x79,0x04,0x0C,0x0E,0x00,0x0B,
0x60,0x66,0x06,0x30,0xC3,0x0C,0x19,0x81,0x98,0x0F,0x00,0xF0,0x06,0x00,0x60,0x06,0x00,0xC0,0x3C,0x03,0x80,
// 'z'
0x7A,0x04,0x08,0x0A,0x01,0x09,
0xFF,0xFF,0x06,0x0C,0x1C,0x38,0x30,0x70,0xFF,0xFF,
// '{'
0x7B,0x00,0x08,0x11,0x02,0x0B,
0x0F,0x1F,0x18,0x18,0x18,0x18,0x38,0xF0,0xF0,0x38,0x18,0x18,0x18,0x18,0x18,0x1F,0x0F,
// '|'
0x7C,0x00,0x02,0x12,0x02,0x06,
0xFF,0xFF,0xFF,0xFF,0xF0,
// '}'
0x7D,0x00,0x08,0x11,0x02,0x0B,
0xF0,0xF8,0x18,0x18,0x18,0x18,0x1C,0x0F,0x0F,0x1C,0x18,0x18,0x18,0x18,0x18,0xF8,0xF0,
// '~'
0x7E,0x05,0x0B,0x05,0x02,0x0F,
0x00,0x0F,0x87,0xFF,0xC3,0xE0,0x00,

// Terminator
0xFF
};


================================================
FILE: components/epaper/DejaVuSans24.c
================================================
// ========================================================================
// This comes with no warranty, implied or otherwise

// This data structure was designed to support Proportional fonts
// fonts. Individual characters do not have to be multiples of 8 bits wide. 
// Any width is fine and does not need to be fixed.

// The data bits are packed to minimize data requirements, but the tradeoff
// is that a header is required per character.

// Header Format:
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset
// Width
// Height
// xOffset
// xDelta (the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.
// ========================================================================

// dejavu
// Point Size   : 24
// Memory usage : 2724 bytes
// # characters : 95

const unsigned char tft_Dejavu24[] =
{
0x00, 0x17, 0x00, 0x00,

// ' '
0x20,0x13,0x00,0x00,0x00,0x08,

// '!'
0x21,0x01,0x02,0x12,0x04,0x0A,
0xFF,0xFF,0xFF,0x03,0xF0,
// '"'
0x22,0x01,0x06,0x07,0x02,0x0B,
0xCF,0x3C,0xF3,0xCF,0x3C,0xC0,
// '#'
0x23,0x01,0x10,0x12,0x02,0x14,
0x03,0x08,0x03,0x18,0x03,0x18,0x03,0x18,0x02,0x18,0x7F,0xFF,0x7F,0xFF,0x06,0x30,0x04,0x30,0x0C,0x20,0x0C,0x60,0xFF,0xFE,0xFF,0xFE,0x18,0x40,0x18,0xC0,0x18,0xC0,0x18,0xC0,0x10,0xC0,
// '$'
0x24,0x01,0x0B,0x16,0x02,0x0F,
0x04,0x00,0x80,0x10,0x0F,0xC7,0xFD,0xC8,0xB1,0x06,0x20,0xE4,0x0F,0x80,0xFE,0x03,0xE0,0x4E,0x08,0xC1,0x1E,0x27,0xFF,0xC7,0xE0,0x10,0x02,0x00,0x40,0x08,0x00,
// '%'
0x25,0x01,0x14,0x12,0x01,0x17,
0x3C,0x03,0x06,0x60,0x60,0xC3,0x06,0x0C,0x30,0xC0,0xC3,0x1C,0x0C,0x31,0x80,0xC3,0x38,0x0C,0x33,0x00,0x66,0x63,0xC3,0xC6,0x66,0x00,0xCC,0x30,0x1C,0xC3,0x01,0x8C,0x30,0x38,0xC3,0x03,0x0C,0x30,0x60,0xC3,0x06,0x06,0x60,0xC0,0x3C,
// '&'
0x26,0x01,0x10,0x12,0x01,0x13,
0x07,0xC0,0x1F,0xE0,0x38,0x20,0x30,0x00,0x30,0x00,0x30,0x00,0x18,0x00,0x1C,0x00,0x3E,0x00,0x77,0x06,0xE3,0x86,0xC1,0xCC,0xC0,0xFC,0xC0,0x78,0xE0,0x78,0x70,0xFC,0x3F,0xCE,0x0F,0x87,
// '''
0x27,0x01,0x02,0x07,0x02,0x07,
0xFF,0xFC,
// '('
0x28,0x01,0x05,0x15,0x02,0x09,
0x19,0x8C,0xC6,0x31,0x18,0xC6,0x31,0x8C,0x61,0x0C,0x63,0x0C,0x61,0x80,
// ')'
0x29,0x01,0x05,0x15,0x02,0x09,
0xC3,0x18,0x63,0x18,0x43,0x18,0xC6,0x31,0x8C,0x46,0x31,0x98,0xCC,0x00,
// '*'
0x2A,0x01,0x0B,0x0A,0x00,0x0C,
0x04,0x00,0x83,0x11,0xBA,0xE1,0xF0,0x3E,0x1D,0x76,0x23,0x04,0x00,0x80,
// '+'
0x2B,0x03,0x10,0x10,0x03,0x14,
0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0xFF,0xFF,0xFF,0xFF,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,0x01,0x80,
// ','
0x2C,0x10,0x03,0x06,0x02,0x08,
0x6D,0xBD,0x80,
// '-'
0x2D,0x0B,0x06,0x02,0x01,0x09,
0xFF,0xF0,
// '.'
0x2E,0x10,0x02,0x03,0x03,0x08,
0xFC,
// '/'
0x2F,0x01,0x08,0x14,0x00,0x08,
0x03,0x07,0x06,0x06,0x06,0x0C,0x0C,0x0C,0x18,0x18,0x18,0x18,0x30,0x30,0x30,0x60,0x60,0x60,0xE0,0xC0,
// '0'
0x30,0x01,0x0C,0x12,0x02,0x0F,
0x0F,0x03,0xFC,0x70,0xE6,0x06,0x60,0x6C,0x03,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x60,0x67,0x0E,0x3F,0xC0,0xF0,
// '1'
0x31,0x01,0x0A,0x12,0x03,0x0F,
0x3C,0x3F,0x0C,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0xFF,0xFF,0xF0,
// '2'
0x32,0x01,0x0C,0x12,0x02,0x0F,
0x3F,0x0F,0xF8,0xC1,0xC0,0x0E,0x00,0x60,0x06,0x00,0x60,0x0C,0x01,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xFF,0xEF,0xFE,
// '3'
0x33,0x01,0x0C,0x12,0x02,0x0F,
0x3F,0x07,0xFC,0x41,0xC0,0x06,0x00,0x60,0x06,0x00,0x60,0x0C,0x1F,0x81,0xFC,0x00,0xE0,0x07,0x00,0x30,0x03,0x00,0x78,0x0E,0xFF,0xC3,0xF0,
// '4'
0x34,0x01,0x0D,0x12,0x01,0x0F,
0x01,0xC0,0x1E,0x00,0xB0,0x0D,0x80,0xCC,0x06,0x60,0x63,0x03,0x18,0x30,0xC3,0x06,0x18,0x31,0x81,0x8F,0xFF,0xFF,0xFC,0x03,0x00,0x18,0x00,0xC0,0x06,0x00,
// '5'
0x35,0x01,0x0B,0x12,0x02,0x0F,
0x7F,0xCF,0xF9,0x80,0x30,0x06,0x00,0xC0,0x1F,0xC3,0xFC,0x41,0xC0,0x1C,0x01,0x80,0x30,0x06,0x00,0xC0,0x3C,0x0E,0xFF,0x8F,0xC0,
// '6'
0x36,0x01,0x0C,0x12,0x02,0x0F,
0x07,0xC1,0xFE,0x38,0x27,0x00,0x60,0x0C,0x00,0xCF,0x8D,0xFC,0xF8,0xEF,0x07,0xE0,0x3E,0x03,0xE0,0x36,0x03,0x70,0x77,0x8E,0x3F,0xC0,0xF8,
// '7'
0x37,0x01,0x0B,0x12,0x02,0x0F,
0xFF,0xFF,0xFC,0x03,0x00,0x60,0x1C,0x03,0x00,0x60,0x18,0x03,0x00,0xE0,0x18,0x03,0x00,0xC0,0x18,0x07,0x00,0xC0,0x18,0x06,0x00,
// '8'
0x38,0x01,0x0C,0x12,0x02,0x0F,
0x1F,0x87,0xFE,0x70,0xEC,0x03,0xC0,0x3C,0x03,0xC0,0x37,0x0E,0x3F,0xC3,0xFC,0x70,0xEC,0x03,0xC0,0x3C,0x03,0xC0,0x37,0x0E,0x7F,0xE1,0xF8,
// '9'
0x39,0x01,0x0C,0x12,0x02,0x0F,
0x1F,0x03,0xFC,0x71,0xCE,0x0E,0xC0,0x6C,0x07,0xC0,0x7C,0x07,0xE0,0xF7,0x1F,0x3F,0xB1,0xF3,0x00,0x30,0x06,0x00,0xE4,0x1C,0x7F,0x83,0xE0,
// ':'
0x3A,0x07,0x02,0x0C,0x03,0x08,
0xFC,0x00,0x3F,
// ';'
0x3B,0x07,0x03,0x0F,0x02,0x08,
0x6D,0x80,0x00,0x0D,0xB7,0xB0,
// '<'
0x3C,0x05,0x0F,0x0D,0x03,0x14,
0x00,0x02,0x00,0x3C,0x03,0xF0,0x3F,0x01,0xF8,0x1F,0x80,0x3C,0x00,0x7E,0x00,0x1F,0x80,0x0F,0xC0,0x03,0xF0,0x00,0xF0,0x00,0x20,
// '='
0x3D,0x08,0x0F,0x07,0x03,0x14,
0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0x80,
// '>'
0x3E,0x05,0x0F,0x0D,0x03,0x14,
0x80,0x01,0xE0,0x01,0xF8,0x00,0x7E,0x00,0x3F,0x00,0x0F,0xC0,0x07,0x80,0x3F,0x03,0xF0,0x1F,0x81,0xF8,0x07,0x80,0x08,0x00,0x00,
// '?'
0x3F,0x01,0x09,0x12,0x02,0x0D,
0x3E,0x3F,0xB0,0xF0,0x30,0x18,0x0C,0x0C,0x0E,0x0E,0x0E,0x06,0x03,0x01,0x80,0x00,0x00,0x30,0x18,0x0C,0x00,
// '@'
0x40,0x02,0x15,0x15,0x02,0x18,
0x00,0xFC,0x00,0x3F,0xF8,0x03,0xC0,0xF0,0x38,0x01,0xC3,0x80,0x07,0x38,0x79,0x99,0x8F,0xEC,0xFC,0x71,0xE3,0xC7,0x07,0x1E,0x30,0x18,0xF1,0x80,0xC7,0x8C,0x06,0x3C,0x70,0x73,0x71,0xC7,0xB9,0x8F,0xEF,0x8E,0x1E,0x70,0x38,0x00,0x00,0xE0,0x04,0x03,0xC0,0xE0,0x0F,0xFE,0x00,0x0F,0x80,0x00,
// 'A'
0x41,0x01,0x10,0x12,0x00,0x10,
0x03,0xC0,0x03,0xC0,0x03,0xC0,0x07,0xE0,0x06,0x60,0x06,0x60,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x18,0x18,0x18,0x18,0x38,0x1C,0x3F,0xFC,0x3F,0xFC,0x60,0x06,0x60,0x06,0x60,0x06,0xC0,0x03,
// 'B'
0x42,0x01,0x0C,0x12,0x02,0x10,
0xFF,0x0F,0xFC,0xC0,0xEC,0x06,0xC0,0x6C,0x06,0xC0,0x6C,0x0C,0xFF,0x8F,0xFC,0xC0,0x6C,0x03,0xC0,0x3C,0x03,0xC0,0x3C,0x06,0xFF,0xEF,0xF8,
// 'C'
0x43,0x01,0x0E,0x12,0x01,0x11,
0x07,0xE0,0x7F,0xE3,0xC1,0xDC,0x01,0x60,0x01,0x80,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0x60,0x01,0x80,0x07,0x00,0x4F,0x07,0x1F,0xF8,0x1F,0x80,
// 'D'
0x44,0x01,0x0F,0x12,0x02,0x12,
0xFF,0x81,0xFF,0xE3,0x01,0xE6,0x00,0xEC,0x00,0xD8,0x01,0xF0,0x01,0xE0,0x03,0xC0,0x07,0x80,0x0F,0x00,0x1E,0x00,0x3C,0x00,0xF8,0x01,0xB0,0x07,0x60,0x3C,0xFF,0xF1,0xFF,0x00,
// 'E'
0x45,0x01,0x0B,0x12,0x02,0x0F,
0xFF,0xFF,0xFF,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xFF,0xDF,0xFB,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xFF,0xFF,0xFC,
// 'F'
0x46,0x01,0x0A,0x12,0x02,0x0E,
0xFF,0xFF,0xFC,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xFF,0xBF,0xEC,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x00,
// 'G'
0x47,0x01,0x0F,0x12,0x01,0x13,
0x07,0xE0,0x3F,0xF0,0xE0,0x73,0x80,0x26,0x00,0x1C,0x00,0x30,0x00,0x60,0x00,0xC0,0x7F,0x80,0xFF,0x00,0x1E,0x00,0x36,0x00,0x6C,0x00,0xDC,0x01,0x9E,0x07,0x1F,0xFC,0x0F,0xE0,
// 'H'
0x48,0x01,0x0D,0x12,0x02,0x12,
0xC0,0x1E,0x00,0xF0,0x07,0x80,0x3C,0x01,0xE0,0x0F,0x00,0x78,0x03,0xFF,0xFF,0xFF,0xF0,0x07,0x80,0x3C,0x01,0xE0,0x0F,0x00,0x78,0x03,0xC0,0x1E,0x00,0xC0,
// 'I'
0x49,0x01,0x02,0x12,0x02,0x07,
0xFF,0xFF,0xFF,0xFF,0xF0,
// 'J'
0x4A,0x01,0x06,0x17,0xFE,0x07,
0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x1B,0xEF,0x00,
// 'K'
0x4B,0x01,0x0F,0x12,0x02,0x10,
0xC0,0x71,0x81,0xC3,0x07,0x06,0x1C,0x0C,0x70,0x19,0xC0,0x37,0x00,0x7C,0x00,0xF8,0x01,0xB0,0x03,0x38,0x06,0x38,0x0C,0x38,0x18,0x38,0x30,0x38,0x60,0x38,0xC0,0x39,0x80,0x38,
// 'L'
0x4C,0x01,0x0B,0x12,0x02,0x0D,
0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xFF,0xFF,0xFC,
// 'M'
0x4D,0x01,0x10,0x12,0x02,0x15,
0xE0,0x07,0xF0,0x0F,0xF0,0x0F,0xF8,0x1F,0xD8,0x1B,0xD8,0x1B,0xCC,0x33,0xCC,0x33,0xCC,0x33,0xC6,0x63,0xC6,0x63,0xC7,0xE3,0xC3,0xC3,0xC3,0xC3,0xC1,0x83,0xC0,0x03,0xC0,0x03,0xC0,0x03,
// 'N'
0x4E,0x01,0x0D,0x12,0x02,0x12,
0xE0,0x1F,0x80,0xFC,0x07,0xF0,0x3D,0x81,0xE6,0x0F,0x30,0x78,0xC3,0xC6,0x1E,0x18,0xF0,0xC7,0x83,0x3C,0x19,0xE0,0x6F,0x03,0x78,0x0F,0xC0,0x7E,0x01,0xC0,
// 'O'
0x4F,0x01,0x10,0x12,0x01,0x13,
0x07,0xE0,0x1F,0xF8,0x3C,0x3C,0x70,0x0E,0x60,0x06,0x60,0x06,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0x60,0x06,0x60,0x06,0x70,0x0E,0x3C,0x3C,0x1F,0xF8,0x07,0xE0,
// 'P'
0x50,0x01,0x0B,0x12,0x02,0x0E,
0xFF,0x1F,0xFB,0x07,0x60,0x3C,0x07,0x80,0xF0,0x1E,0x0E,0xFF,0xDF,0xE3,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x00,
// 'Q'
0x51,0x01,0x10,0x15,0x01,0x13,
0x07,0xE0,0x1F,0xF8,0x3C,0x3C,0x70,0x0E,0x60,0x06,0x60,0x06,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0xC0,0x03,0x60,0x07,0x60,0x06,0x70,0x0E,0x3C,0x3C,0x1F,0xF8,0x07,0xF0,0x00,0x38,0x00,0x18,0x00,0x0C,
// 'R'
0x52,0x01,0x0D,0x12,0x02,0x11,
0xFF,0x07,0xFE,0x30,0x31,0x80,0xCC,0x06,0x60,0x33,0x01,0x98,0x18,0xFF,0xC7,0xFC,0x30,0x71,0x81,0x8C,0x06,0x60,0x33,0x01,0xD8,0x06,0xC0,0x36,0x00,0xC0,
// 'S'
0x53,0x01,0x0C,0x12,0x02,0x0F,
0x1F,0x87,0xFE,0x70,0x6C,0x00,0xC0,0x0C,0x00,0xC0,0x07,0x00,0x7F,0x01,0xFC,0x00,0xE0,0x07,0x00,0x30,0x03,0x00,0x3C,0x0E,0xFF,0xE3,0xF8,
// 'T'
0x54,0x01,0x0E,0x12,0x00,0x0F,
0xFF,0xFF,0xFF,0xF0,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,
// 'U'
0x55,0x01,0x0D,0x12,0x02,0x12,
0xC0,0x1E,0x00,0xF0,0x07,0x80,0x3C,0x01,0xE0,0x0F,0x00,0x78,0x03,0xC0,0x1E,0x00,0xF0,0x07,0x80,0x3C,0x01,0xE0,0x0D,0x80,0xCE,0x0E,0x3F,0xE0,0x7C,0x00,
// 'V'
0x56,0x01,0x10,0x12,0x00,0x10,
0xC0,0x03,0x60,0x06,0x60,0x06,0x60,0x06,0x30,0x0C,0x30,0x0C,0x38,0x1C,0x18,0x18,0x18,0x18,0x0C,0x30,0x0C,0x30,0x0C,0x30,0x06,0x60,0x06,0x60,0x07,0x60,0x03,0xC0,0x03,0xC0,0x03,0xC0,
// 'W'
0x57,0x01,0x16,0x12,0x01,0x18,
0xC0,0x78,0x0F,0x01,0xE0,0x36,0x07,0x81,0x98,0x1E,0x06,0x60,0xEC,0x19,0x83,0x30,0x63,0x0C,0xC3,0x0C,0x33,0x0C,0x30,0xCE,0x30,0xC6,0x18,0xC1,0x98,0x66,0x06,0x61,0x98,0x19,0x86,0x60,0x6C,0x0D,0x80,0xF0,0x3C,0x03,0xC0,0xF0,0x0F,0x03,0xC0,0x38,0x07,0x00,
// 'X'
0x58,0x01,0x0F,0x12,0x01,0x11,
0x70,0x0E,0x60,0x18,0x60,0x60,0xE1,0xC0,0xC7,0x00,0xCC,0x01,0xF0,0x01,0xE0,0x03,0x80,0x07,0x80,0x1F,0x00,0x37,0x00,0xC6,0x03,0x86,0x0E,0x0E,0x18,0x0C,0x60,0x0D,0xC0,0x1C,
// 'Y'
0x59,0x01,0x0E,0x12,0x00,0x0F,
0xE0,0x1D,0x80,0x63,0x03,0x0E,0x1C,0x18,0x60,0x33,0x00,0xFC,0x01,0xE0,0x07,0x80,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,
// 'Z'
0x5A,0x01,0x0E,0x12,0x01,0x10,
0xFF,0xFF,0xFF,0xF0,0x01,0x80,0x0E,0x00,0x70,0x01,0x80,0x0C,0x00,0x60,0x03,0x80,0x1C,0x00,0x60,0x03,0x00,0x18,0x00,0xE0,0x07,0x00,0x18,0x00,0xFF,0xFF,0xFF,0xF0,
// '['
0x5B,0x01,0x05,0x15,0x02,0x09,
0xFF,0xF1,0x8C,0x63,0x18,0xC6,0x31,0x8C,0x63,0x18,0xC6,0x31,0xFF,0x80,
// '\'
0x5C,0x01,0x08,0x14,0x00,0x08,
0xC0,0xE0,0x60,0x60,0x60,0x30,0x30,0x30,0x18,0x18,0x18,0x18,0x0C,0x0C,0x0C,0x06,0x06,0x06,0x07,0x03,
// ']'
0x5D,0x01,0x05,0x15,0x02,0x09,
0xFF,0xC6,0x31,0x8C,0x63,0x18,0xC6,0x31,0x8C,0x63,0x18,0xC7,0xFF,0x80,
// '^'
0x5E,0x01,0x0F,0x07,0x03,0x14,
0x03,0x80,0x0F,0x80,0x3B,0x80,0xE3,0x83,0x83,0x8E,0x03,0xB8,0x03,0x80,
// '_'
0x5F,0x17,0x0C,0x02,0x00,0x0C,
0xFF,0xFF,0xFF,
// '`'
0x60,0x00,0x06,0x04,0x02,0x0C,
0x60,0xC1,0x83,
// 'a'
0x61,0x06,0x0B,0x0D,0x01,0x0E,
0x3F,0x0F,0xF9,0x03,0x00,0x30,0x06,0x3F,0xDF,0xFF,0x03,0xC0,0x78,0x1F,0x87,0xBF,0xF3,0xE6,
// 'b'
0x62,0x01,0x0C,0x12,0x02,0x0F,
0xC0,0x0C,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0xF8,0xFF,0xCF,0x0E,0xE0,0x6C,0x03,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xE0,0x6F,0x0E,0xFF,0xCC,0xF8,
// 'c'
0x63,0x06,0x0A,0x0D,0x01,0x0D,
0x0F,0x8F,0xF7,0x05,0x80,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x18,0x07,0x04,0xFF,0x0F,0x80,
// 'd'
0x64,0x01,0x0C,0x12,0x01,0x0F,
0x00,0x30,0x03,0x00,0x30,0x03,0x00,0x31,0xF3,0x3F,0xF7,0x0F,0x60,0x7C,0x03,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0x60,0x77,0x0F,0x3F,0xF1,0xF3,
// 'e'
0x65,0x06,0x0C,0x0D,0x01,0x0E,
0x0F,0x83,0xFC,0x70,0xE6,0x07,0xC0,0x3F,0xFF,0xFF,0xFC,0x00,0xC0,0x06,0x00,0x70,0x23,0xFE,0x0F,0xC0,
// 'f'
0x66,0x01,0x08,0x12,0x01,0x08,
0x0F,0x1F,0x38,0x30,0x30,0xFF,0xFF,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,
// 'g'
0x67,0x06,0x0C,0x12,0x01,0x0F,
0x1F,0x33,0xFF,0x70,0xF6,0x07,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x07,0x70,0xF3,0xFF,0x1F,0x30,0x03,0x00,0x72,0x0E,0x3F,0xC1,0xF8,
// 'h'
0x68,0x01,0x0B,0x12,0x02,0x0F,
0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x9F,0x3F,0xF7,0x87,0xE0,0x78,0x0F,0x01,0xE0,0x3C,0x07,0x80,0xF0,0x1E,0x03,0xC0,0x78,0x0C,
// 'i'
0x69,0x01,0x02,0x12,0x02,0x07,
0xFC,0x3F,0xFF,0xFF,0xF0,
// 'j'
0x6A,0x01,0x05,0x17,0xFF,0x07,
0x18,0xC6,0x00,0x0C,0x63,0x18,0xC6,0x31,0x8C,0x63,0x18,0xC6,0x33,0xFB,0x80,
// 'k'
0x6B,0x01,0x0C,0x12,0x02,0x0E,
0xC0,0x0C,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0x1C,0xC3,0x8C,0x70,0xCE,0x0D,0xC0,0xF8,0x0F,0x80,0xDC,0x0C,0xE0,0xC7,0x0C,0x38,0xC1,0xCC,0x0E,
// 'l'
0x6C,0x01,0x02,0x12,0x02,0x06,
0xFF,0xFF,0xFF,0xFF,0xF0,
// 'm'
0x6D,0x06,0x14,0x0D,0x02,0x18,
0xCF,0x87,0xCF,0xFC,0xFE,0xF0,0xF8,0x7E,0x07,0x03,0xC0,0x60,0x3C,0x06,0x03,0xC0,0x60,0x3C,0x06,0x03,0xC0,0x60,0x3C,0x06,0x03,0xC0,0x60,0x3C,0x06,0x03,0xC0,0x60,0x30,
// 'n'
0x6E,0x06,0x0B,0x0D,0x02,0x0F,
0xCF,0x9F,0xFB,0xC3,0xF0,0x3C,0x07,0x80,0xF0,0x1E,0x03,0xC0,0x78,0x0F,0x01,0xE0,0x3C,0x06,
// 'o'
0x6F,0x06,0x0C,0x0D,0x01,0x0E,
0x1F,0x83,0xFC,0x70,0xE6,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x70,0xE3,0xFC,0x1F,0x80,
// 'p'
0x70,0x06,0x0C,0x12,0x02,0x0F,
0xCF,0x8F,0xFC,0xF0,0xEE,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x3E,0x06,0xF0,0xEF,0xFC,0xCF,0x8C,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0x00,
// 'q'
0x71,0x06,0x0C,0x12,0x01,0x0F,
0x1F,0x33,0xFF,0x70,0xF6,0x07,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x07,0x70,0xF3,0xFF,0x1F,0x30,0x03,0x00,0x30,0x03,0x00,0x30,0x03,
// 'r'
0x72,0x06,0x08,0x0D,0x02,0x0A,
0xCF,0xFF,0xF0,0xE0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
// 's'
0x73,0x06,0x0B,0x0D,0x01,0x0C,
0x3F,0x0F,0xF3,0x82,0x60,0x0C,0x00,0xF0,0x0F,0xC0,0x3C,0x00,0xC0,0x1A,0x07,0x7F,0xC7,0xF0,
// 't'
0x74,0x02,0x08,0x11,0x00,0x09,
0x30,0x30,0x30,0x30,0xFF,0xFF,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x1F,0x0F,
// 'u'
0x75,0x06,0x0B,0x0D,0x02,0x0F,
0xC0,0x78,0x0F,0x01,0xE0,0x3C,0x07,0x80,0xF0,0x1E,0x03,0xC0,0x78,0x1F,0x87,0xBF,0xF3,0xE6,
// 'v'
0x76,0x06,0x0D,0x0D,0x01,0x0F,
0xC0,0x1B,0x01,0x98,0x0C,0xC0,0x63,0x06,0x18,0x30,0x63,0x03,0x18,0x18,0xC0,0x6C,0x03,0x60,0x1F,0x00,0x70,0x00,
// 'w'
0x77,0x06,0x12,0x0D,0x01,0x14,
0xC1,0xE0,0xF0,0x78,0x36,0x1E,0x19,0x87,0x86,0x63,0x31,0x9C,0xCC,0xE3,0x33,0x30,0xCC,0xCC,0x36,0x1B,0x07,0x87,0x81,0xE1,0xE0,0x78,0x78,0x1C,0x0E,0x00,
// 'x'
0x78,0x06,0x0D,0x0D,0x01,0x0F,
0xE0,0x3B,0x83,0x8E,0x38,0x31,0x80,0xD8,0x07,0xC0,0x1C,0x01,0xF0,0x1D,0xC0,0xC6,0x0C,0x18,0xE0,0xEE,0x03,0x80,
// 'y'
0x79,0x06,0x0D,0x12,0x01,0x0F,
0xC0,0x1B,0x01,0x98,0x0C,0xE0,0xE3,0x06,0x18,0x70,0x63,0x03,0x18,0x0D,0x80,0x6C,0x03,0xE0,0x0E,0x00,0x70,0x03,0x00,0x18,0x01,0x80,0x7C,0x03,0xC0,0x00,
// 'z'
0x7A,0x06,0x0B,0x0D,0x01,0x0D,
0xFF,0xFF,0xFC,0x03,0x00,0xE0,0x38,0x0E,0x03,0x80,0xE0,0x38,0x0E,0x01,0x80,0x7F,0xFF,0xFE,
// '{'
0x7B,0x01,0x09,0x16,0x03,0x0F,
0x03,0x83,0xC3,0x81,0x80,0xC0,0x60,0x30,0x18,0x0C,0x0E,0x3E,0x1F,0x01,0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0xC0,0x78,0x1C,
// '|'
0x7C,0x01,0x02,0x18,0x03,0x08,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
// '}'
0x7D,0x01,0x09,0x16,0x03,0x0F,
0xE0,0x78,0x0E,0x03,0x01,0x80,0xC0,0x60,0x30,0x18,0x0E,0x03,0xE1,0xF1,0xC0,0xC0,0x60,0x30,0x18,0x0C,0x06,0x07,0x0F,0x07,0x00,
// '~'
0x7E,0x09,0x0F,0x05,0x03,0x14,
0x00,0x00,0x7C,0x05,0xFE,0x1E,0x1F,0xE0,0x0F,0x80,

// Terminator
0xFF
};


================================================
FILE: components/epaper/EPD.c
================================================
/* EPD library
 *
 *  Author: LoBo (loboris@gmail.com, loboris.github)
 *
 *  Module supporting SPI ePaper displays
*/

#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "time.h"
#include <math.h>
#include "rom/tjpgd.h"
#include "esp_heap_alloc_caps.h"
#include "EPD.h"
#include "EPDspi.h"
#include "rom/tjpgd.h"


#define DEG_TO_RAD 0.01745329252
#define RAD_TO_DEG 57.295779513
#define deg_to_rad 0.01745329252 + 3.14159265359
#define swap(a, b) { int16_t t = a; a = b; b = t; }
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

#if !defined(max)
#define max(A,B) ( (A) > (B) ? (A):(B))
#endif

#if !defined(min)
#define min(A,B) ( (A) < (B) ? (A):(B))
#endif

// Embedded fonts
extern uint8_t tft_SmallFont[];
extern uint8_t tft_DefaultFont[];
extern uint8_t tft_Dejavu18[];
extern uint8_t tft_Dejavu24[];
extern uint8_t tft_Ubuntu16[];
extern uint8_t tft_Comic24[];
extern uint8_t tft_minya24[];
extern uint8_t tft_tooney32[];

// ==============================================================
// ==== Set default values of global variables ==================

uint8_t orientation = LANDSCAPE_0;	// screen orientation
uint16_t font_rotate = 0;			// font rotation
uint8_t	font_transparent = 0;
uint8_t	font_forceFixed = 0;
uint8_t	text_wrap = 0;				// character wrapping to new line
color_t	_fg = EPD_BLACK;
color_t _bg = EPD_WHITE;

float _angleOffset = DEFAULT_ANGLE_OFFSET;

int	EPD_X = 0;
int	EPD_Y = 0;

dispWin_t dispWin = {
  .x1 = 0,
  .y1 = 0,
  .x2 = EPD_DISPLAY_WIDTH-1,
  .y2 = EPD_DISPLAY_HEIGHT-1,
};

Font_t cfont = {
	.font = tft_DefaultFont,
	.x_size = 0,
	.y_size = 0x0B,
	.offset = 0,
	.numchars = 95,
	.bitmap = 1,
};

uint8_t font_line_space = 0;
uint8_t image_debug = 0;

// ==============================================================


typedef struct {
      uint8_t charCode;
      int adjYOffset;
      int width;
      int height;
      int xOffset;
      int xDelta;
      uint16_t dataPtr;
} propFont;

static dispWin_t dispWinTemp;

static uint8_t *userfont = NULL;
static int EPD_OFFSET = 0;
static propFont	fontChar;
static float _arcAngleMax = DEFAULT_ARC_ANGLE_MAX;



// ==============================================================================================================
//----------------------------------------------
static void drawPixel(int x, int y, uint8_t val)
{
	if (orientation == LANDSCAPE_180) {
		x = _width - x - 1;
		y = _height - y - 1;
	}
	if (_gs) {
		val &= 0x0F;
		//if (gs_drawBuff[(y * _width) + x] != val) {
			gs_drawBuff[(y * _width) + x] = val;
			gs_used_shades |= (1<<val);
		//}
	}
	else {
		val &= 0x01;
		uint8_t buf_val = drawBuff[(x * (_height >> 3)) + (y>>3)];
		uint8_t new_val = buf_val;
		if (val) new_val &= (0x80 >> (y % 8)) ^ 0xFF;
		else new_val |= (0x80 >> (y % 8));
		//if (new_val != buf_val) drawBuff[(x * (_height>>3)) + (y>>3)] = new_val;
		drawBuff[(x * (_height>>3)) + (y>>3)] = new_val;
	}
}

//-------------------------------------------------------------------------
static void EPD_pushColorRep(int x1, int y1, int x2, int y2, color_t color)
{
	if (_gs == 0) color &= 0x01;
	else color &= 0x0F;
	for (int y=y1; y<=y2; y++) {
		for (int x = x1; x<=x2; x++){
			drawPixel(x, y, color);
		}
	}
}

/*
//---------------------------------------------------------------------------------------
static void copyBuff(int x1, int y1, int x2, int y2, uint8_t *src_buf, uint8_t *dest_buf)
{
	if
	uint8_t buf_val1 = (src_buf[(x1 * (EPD_DISPLAY_HEIGHT>>3)) + (y1>>3)]) ;
	uint8_t val = 0x80 >> (y1 % 8);
	if (val) buf_val &= (0x80 >> (y % 8)) ^ 0xFF;
	else buf_val |= (0x80 >> (y % 8));

	drawBuff[(x * (EPD_DISPLAY_HEIGHT>>3)) + (y>>3)] = buf_val;
}
*/

// ==============================================================================================================

// =========================================================================
// ** All drawings are clipped to 'dispWin' **
// ** All x,y coordinates in public functions are relative to clip window **
// =========== : Public functions
// ----------- : Local functions
// =========================================================================


// Compare two colors; return 0 if equal
//============================================
int EPD_compare_colors(color_t c1, color_t c2)
{
	if (c1 != c2) return 1;

	return 0;
}

// draw color pixel on screen
//-----------------------------------------------------------
static void _drawPixel(int16_t x, int16_t y, color_t color) {

	if ((x < dispWin.x1) || (y < dispWin.y1) || (x > dispWin.x2) || (y > dispWin.y2)) return;
	drawPixel(x, y, color);
}

//=======================================================
void EPD_drawPixel(int16_t x, int16_t y, color_t color) {

	_drawPixel(x+dispWin.x1, y+dispWin.y1, color);
}

//--------------------------------------------------------------------------
static void _drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color) {
	// clipping
	if ((x < dispWin.x1) || (x > dispWin.x2) || (y > dispWin.y2)) return;
	if (y < dispWin.y1) {
		h -= (dispWin.y1 - y);
		y = dispWin.y1;
	}
	if (h < 0) h = 0;
	if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1;
	if (h == 0) h = 1;
	EPD_pushColorRep(x, y, x, y+h-1, color);
}

//--------------------------------------------------------------------------
static void _drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) {
	// clipping
	if ((y < dispWin.y1) || (x > dispWin.x2) || (y > dispWin.y2)) return;
	if (x < dispWin.x1) {
		w -= (dispWin.x1 - x);
		x = dispWin.x1;
	}
	if (w < 0) w = 0;
	if ((x + w) > (dispWin.x2+1)) w = dispWin.x2 - x + 1;
	if (w == 0) w = 1;

	EPD_pushColorRep(x, y, x+w-1, y, color);
}

//======================================================================
void EPD_drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color) {
	_drawFastVLine(x+dispWin.x1, y+dispWin.y1, h, color);
}

//======================================================================
void EPD_drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) {
	_drawFastHLine(x+dispWin.x1, y+dispWin.y1, w, color);
}

// Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer this uses
// the eficient FastH/V Line draw routine for segments of 2 pixels or more
//----------------------------------------------------------------------------------
static void _drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t color)
{
  if (x0 == x1) {
	  if (y0 <= y1) _drawFastVLine(x0, y0, y1-y0, color);
	  else _drawFastVLine(x0, y1, y0-y1, color);
	  return;
  }
  if (y0 == y1) {
	  if (x0 <= x1) _drawFastHLine(x0, y0, x1-x0, color);
	  else _drawFastHLine(x1, y0, x0-x1, color);
	  return;
  }

  int steep = 0;
  if (abs(y1 - y0) > abs(x1 - x0)) steep = 1;
  if (steep) {
    swap(x0, y0);
    swap(x1, y1);
  }
  if (x0 > x1) {
    swap(x0, x1);
    swap(y0, y1);
  }

  int16_t dx = x1 - x0, dy = abs(y1 - y0);;
  int16_t err = dx >> 1, ystep = -1, xs = x0, dlen = 0;

  if (y0 < y1) ystep = 1;

  // Split into steep and not steep for FastH/V separation
  if (steep) {
    for (; x0 <= x1; x0++) {
      dlen++;
      err -= dy;
      if (err < 0) {
        err += dx;
        if (dlen == 1) _drawPixel(y0, xs, color);
        else _drawFastVLine(y0, xs, dlen, color);
        dlen = 0; y0 += ystep; xs = x0 + 1;
      }
    }
    if (dlen) _drawFastVLine(y0, xs, dlen, color);
  }
  else
  {
    for (; x0 <= x1; x0++) {
      dlen++;
      err -= dy;
      if (err < 0) {
        err += dx;
        if (dlen == 1) _drawPixel(xs, y0, color);
        else _drawFastHLine(xs, y0, dlen, color);
        dlen = 0; y0 += ystep; xs = x0 + 1;
      }
    }
    if (dlen) _drawFastHLine(xs, y0, dlen, color);
  }
}

//==============================================================================
void EPD_drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t color)
{
	_drawLine(x0+dispWin.x1, y0+dispWin.y1, x1+dispWin.x1, y1+dispWin.y1, color);
}

// fill a rectangle
//--------------------------------------------------------------------------------
static void _fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t color) {
	// clipping
	if ((x >= dispWin.x2) || (y > dispWin.y2)) return;

	if (x < dispWin.x1) {
		w -= (dispWin.x1 - x);
		x = dispWin.x1;
	}
	if (y < dispWin.y1) {
		h -= (dispWin.y1 - y);
		y = dispWin.y1;
	}
	if (w < 0) w = 0;
	if (h < 0) h = 0;

	if ((x + w) > (dispWin.x2+1)) w = dispWin.x2 - x + 1;
	if ((y + h) > (dispWin.y2+1)) h = dispWin.y2 - y + 1;
	if (w == 0) w = 1;
	if (h == 0) h = 1;
	EPD_pushColorRep(x, y, x+w-1, y+h-1, color);
}

//============================================================================
void EPD_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t color) {
	_fillRect(x+dispWin.x1, y+dispWin.y1, w, h, color);
}

//==================================
void EPD_fillScreen(color_t color) {
	color &= 0x0F;
	memset(disp_buffer, ((color&1) ? 0 : 0xFF), _width * (_height/8));
	memset(gs_disp_buffer, color, _width * _height);
	gs_used_shades = 0;
}

//==================================
void EPD_fillWindow(color_t color) {
	EPD_pushColorRep(dispWin.x1, dispWin.y1, dispWin.x2, dispWin.y2, 0xFF);
}

// ^^^============= Basics drawing functions ================================^^^


// ================ Graphics drawing functions ==================================

//-----------------------------------------------------------------------------------
static void _drawRect(uint16_t x1,uint16_t y1,uint16_t w,uint16_t h, color_t color) {
  _drawFastHLine(x1,y1,w, color);
  _drawFastVLine(x1+w-1,y1,h, color);
  _drawFastHLine(x1,y1+h-1,w, color);
  _drawFastVLine(x1,y1,h, color);
}

//===============================================================================
void EPD_drawRect(uint16_t x1,uint16_t y1,uint16_t w,uint16_t h, color_t color) {
	_drawRect(x1+dispWin.x1, y1+dispWin.y1, w, h, color);
}

//-------------------------------------------------------------------------------------------------
static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername, color_t color)
{
	int16_t f = 1 - r;
	int16_t ddF_x = 1;
	int16_t ddF_y = -2 * r;
	int16_t x = 0;
	int16_t y = r;

	while (x < y) {
		if (f >= 0) {
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;
		if (cornername & 0x4) {
			_drawPixel(x0 + x, y0 + y, color);
			_drawPixel(x0 + y, y0 + x, color);
		}
		if (cornername & 0x2) {
			_drawPixel(x0 + x, y0 - y, color);
			_drawPixel(x0 + y, y0 - x, color);
		}
		if (cornername & 0x8) {
			_drawPixel(x0 - y, y0 + x, color);
			_drawPixel(x0 - x, y0 + y, color);
		}
		if (cornername & 0x1) {
			_drawPixel(x0 - y, y0 - x, color);
			_drawPixel(x0 - x, y0 - y, color);
		}
	}
}

// Used to do circles and roundrects
//----------------------------------------------------------------------------------------------------------------
static void fillCircleHelper(int16_t x0, int16_t y0, int16_t r,	uint8_t cornername, int16_t delta, color_t color)
{
	int16_t f = 1 - r;
	int16_t ddF_x = 1;
	int16_t ddF_y = -2 * r;
	int16_t x = 0;
	int16_t y = r;
	int16_t ylm = x0 - r;

	while (x < y) {
		if (f >= 0) {
			if (cornername & 0x1) _drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color);
			if (cornername & 0x2) _drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color);
			ylm = x0 - y;
			y--;
			ddF_y += 2;
			f += ddF_y;
		}
		x++;
		ddF_x += 2;
		f += ddF_x;

		if ((x0 - x) > ylm) {
			if (cornername & 0x1) _drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color);
			if (cornername & 0x2) _drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color);
		}
	}
}

// Draw a rounded rectangle
//=============================================================================================
void EPD_drawRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, color_t color)
{
	x += dispWin.x1;
	y += dispWin.y1;

	// smarter version
	_drawFastHLine(x + r, y, w - 2 * r, color);			// Top
	_drawFastHLine(x + r, y + h - 1, w - 2 * r, color);	// Bottom
	_drawFastVLine(x, y + r, h - 2 * r, color);			// Left
	_drawFastVLine(x + w - 1, y + r, h - 2 * r, color);	// Right

	// draw four corners
	drawCircleHelper(x + r, y + r, r, 1, color);
	drawCircleHelper(x + w - r - 1, y + r, r, 2, color);
	drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color);
	drawCircleHelper(x + r, y + h - r - 1, r, 8, color);
}

// Fill a rounded rectangle
//=============================================================================================
void EPD_fillRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, color_t color)
{
	x += dispWin.x1;
	y += dispWin.y1;

	// smarter version
	_fillRect(x + r, y, w - 2 * r, h, color);

	// draw four corners
	fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color);
	fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color);
}




//-----------------------------------------------------------------------------------------------
static void _drawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16_t length, color_t color)
{
	_drawLine(
		x,
		y,
		x + length * cos((angle + _angleOffset) * DEG_TO_RAD),
		y + length * sin((angle + _angleOffset) * DEG_TO_RAD), color);
}

//---------------------------------------------------------------------------------------------------------------
static void _DrawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16_t start, uint16_t length, color_t color)
{
	_drawLine(
		x + start * cos((angle + _angleOffset) * DEG_TO_RAD),
		y + start * sin((angle + _angleOffset) * DEG_TO_RAD),
		x + (start + length) * cos((angle + _angleOffset) * DEG_TO_RAD),
		y + (start + length) * sin((angle + _angleOffset) * DEG_TO_RAD), color);
}

//===========================================================================================================
void EPD_drawLineByAngle(uint16_t x, uint16_t y, uint16_t start, uint16_t len, uint16_t angle, color_t color)
{
	x += dispWin.x1;
	y += dispWin.y1;

	if (start == 0) _drawLineByAngle(x, y, angle, len, color);
	else _DrawLineByAngle(x, y, angle, start, len, color);
}


// Draw a triangle
//--------------------------------------------------------------------------------------------------------------------
static void _drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color)
{
	_drawLine(x0, y0, x1, y1, color);
	_drawLine(x1, y1, x2, y2, color);
	_drawLine(x2, y2, x0, y0, color);
}

//================================================================================================================
void EPD_drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color)
{
	x0 += dispWin.x1;
	y0 += dispWin.y1;
	x1 += dispWin.x1;
	y1 += dispWin.y1;
	x2 += dispWin.x1;
	y2 += dispWin.y1;

	_drawLine(x0, y0, x1, y1, color);
	_drawLine(x1, y1, x2, y2, color);
	_drawLine(x2, y2, x0, y0, color);
}

// Fill a triangle
//--------------------------------------------------------------------------------------------------------------------
static void _fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color)
{
  int16_t a, b, y, last;

  // Sort coordinates by Y order (y2 >= y1 >= y0)
  if (y0 > y1) {
    swap(y0, y1); swap(x0, x1);
  }
  if (y1 > y2) {
    swap(y2, y1); swap(x2, x1);
  }
  if (y0 > y1) {
    swap(y0, y1); swap(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;
    _drawFastHLine(a, y0, b-a+1, color);
    return;
  }

  int16_t
    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(a,b);
    _drawFastHLine(a, y, b-a+1, color);
  }

  // For lower part of triangle, find scanline crossings for segments
  // 0-2 and 1-2.  This loop is skipped if y1=y2.
  sa = dx12 * (y - y1);
  sb = 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(a,b);
    _drawFastHLine(a, y, b-a+1, color);
  }
}

//================================================================================================================
void EPD_fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color)
{
	_fillTriangle(
			x0 + dispWin.x1, y0 + dispWin.y1,
			x1 + dispWin.x1, y1 + dispWin.y1,
			x2 + dispWin.x1, y2 + dispWin.y1,
			color);
}

//====================================================================
void EPD_drawCircle(int16_t x, int16_t y, int radius, color_t color) {
	x += dispWin.x1;
	y += dispWin.y1;
	int f = 1 - radius;
	int ddF_x = 1;
	int ddF_y = -2 * radius;
	int x1 = 0;
	int y1 = radius;

	_drawPixel(x, y + radius, color);
	_drawPixel(x, y - radius, color);
	_drawPixel(x + radius, y, color);
	_drawPixel(x - radius, y, color);
	while(x1 < y1) {
		if (f >= 0) {
			y1--;
			ddF_y += 2;
			f += ddF_y;
		}
		x1++;
		ddF_x += 2;
		f += ddF_x;
		_drawPixel(x + x1, y + y1, color);
		_drawPixel(x - x1, y + y1, color);
		_drawPixel(x + x1, y - y1, color);
		_drawPixel(x - x1, y - y1, color);
		_drawPixel(x + y1, y + x1, color);
		_drawPixel(x - y1, y + x1, color);
		_drawPixel(x + y1, y - x1, color);
		_drawPixel(x - y1, y - x1, color);
	}
}

//====================================================================
void EPD_fillCircle(int16_t x, int16_t y, int radius, color_t color) {
	x += dispWin.x1;
	y += dispWin.y1;

	_drawFastVLine(x, y-radius, 2*radius+1, color);
	fillCircleHelper(x, y, radius, 3, 0, color);
}

//----------------------------------------------------------------------------------------------------------------
static void _draw_ellipse_section(uint16_t x, uint16_t y, uint16_t x0, uint16_t y0, color_t color, uint8_t option)
{
    // upper right
    if ( option & EPD_ELLIPSE_UPPER_RIGHT ) _drawPixel(x0 + x, y0 - y, color);
    // upper left
    if ( option & EPD_ELLIPSE_UPPER_LEFT ) _drawPixel(x0 - x, y0 - y, color);
    // lower right
    if ( option & EPD_ELLIPSE_LOWER_RIGHT ) _drawPixel(x0 + x, y0 + y, color);
    // lower left
    if ( option & EPD_ELLIPSE_LOWER_LEFT ) _drawPixel(x0 - x, y0 + y, color);
}

//=====================================================================================================
void EPD_drawEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, color_t color, uint8_t option)
{
	x0 += dispWin.x1;
	y0 += dispWin.y1;

	uint16_t x, y;
	int32_t xchg, ychg;
	int32_t err;
	int32_t rxrx2;
	int32_t ryry2;
	int32_t stopx, stopy;

	rxrx2 = rx;
	rxrx2 *= rx;
	rxrx2 *= 2;

	ryry2 = ry;
	ryry2 *= ry;
	ryry2 *= 2;

	x = rx;
	y = 0;

	xchg = 1;
	xchg -= rx;
	xchg -= rx;
	xchg *= ry;
	xchg *= ry;

	ychg = rx;
	ychg *= rx;

	err = 0;

	stopx = ryry2;
	stopx *= rx;
	stopy = 0;

	while( stopx >= stopy ) {
		_draw_ellipse_section(x, y, x0, y0, color, option);
		y++;
		stopy += rxrx2;
		err += ychg;
		ychg += rxrx2;
		if ( 2*err+xchg > 0 ) {
			x--;
			stopx -= ryry2;
			err += xchg;
			xchg += ryry2;
		}
	}

	x = 0;
	y = ry;

	xchg = ry;
	xchg *= ry;

	ychg = 1;
	ychg -= ry;
	ychg -= ry;
	ychg *= rx;
	ychg *= rx;

	err = 0;

	stopx = 0;

	stopy = rxrx2;
	stopy *= ry;

	while( stopx <= stopy ) {
		_draw_ellipse_section(x, y, x0, y0, color, option);
		x++;
		stopx += ryry2;
		err += xchg;
		xchg += ryry2;
		if ( 2*err+ychg > 0 ) {
			y--;
			stopy -= rxrx2;
			err += ychg;
			ychg += rxrx2;
		}
	}
}

//-----------------------------------------------------------------------------------------------------------------------
static void _draw_filled_ellipse_section(uint16_t x, uint16_t y, uint16_t x0, uint16_t y0, color_t color, uint8_t option)
{
    // upper right
    if ( option & EPD_ELLIPSE_UPPER_RIGHT ) _drawFastVLine(x0+x, y0-y, y+1, color);
    // upper left
    if ( option & EPD_ELLIPSE_UPPER_LEFT ) _drawFastVLine(x0-x, y0-y, y+1, color);
    // lower right
    if ( option & EPD_ELLIPSE_LOWER_RIGHT ) _drawFastVLine(x0+x, y0, y+1, color);
    // lower left
    if ( option & EPD_ELLIPSE_LOWER_LEFT ) _drawFastVLine(x0-x, y0, y+1, color);
}

//=====================================================================================================
void EPD_fillEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, color_t color, uint8_t option)
{
	x0 += dispWin.x1;
	y0 += dispWin.y1;

	uint16_t x, y;
	int32_t xchg, ychg;
	int32_t err;
	int32_t rxrx2;
	int32_t ryry2;
	int32_t stopx, stopy;

	rxrx2 = rx;
	rxrx2 *= rx;
	rxrx2 *= 2;

	ryry2 = ry;
	ryry2 *= ry;
	ryry2 *= 2;

	x = rx;
	y = 0;

	xchg = 1;
	xchg -= rx;
	xchg -= rx;
	xchg *= ry;
	xchg *= ry;

	ychg = rx;
	ychg *= rx;

	err = 0;

	stopx = ryry2;
	stopx *= rx;
	stopy = 0;

	while( stopx >= stopy ) {
		_draw_filled_ellipse_section(x, y, x0, y0, color, option);
		y++;
		stopy += rxrx2;
		err += ychg;
		ychg += rxrx2;
		if ( 2*err+xchg > 0 ) {
			x--;
			stopx -= ryry2;
			err += xchg;
			xchg += ryry2;
		}
	}

	x = 0;
	y = ry;

	xchg = ry;
	xchg *= ry;

	ychg = 1;
	ychg -= ry;
	ychg -= ry;
	ychg *= rx;
	ychg *= rx;

	err = 0;

	stopx = 0;

	stopy = rxrx2;
	stopy *= ry;

	while( stopx <= stopy ) {
		_draw_filled_ellipse_section(x, y, x0, y0, color, option);
		x++;
		stopx += ryry2;
		err += xchg;
		xchg += ryry2;
		if ( 2*err+ychg > 0 ) {
			y--;
			stopy -= rxrx2;
			err += ychg;
			ychg += rxrx2;
		}
	}
}


// ==== ARC DRAWING ===================================================================

//---------------------------------------------------------------------------------------------------------------------------------
static void _fillArcOffsetted(uint16_t cx, uint16_t cy, uint16_t radius, uint16_t thickness, float start, float end, color_t color)
{
	//float sslope = (float)cos_lookup(start) / (float)sin_lookup(start);
	//float eslope = (float)cos_lookup(end) / (float)sin_lookup(end);
	float sslope = (cos(start/_arcAngleMax * 2 * PI) * _arcAngleMax) / (sin(start/_arcAngleMax * 2 * PI) * _arcAngleMax) ;
	float eslope = (cos(end/_arcAngleMax * 2 * PI) * _arcAngleMax) / (sin(end/_arcAngleMax * 2 * PI) * _arcAngleMax);

	if (end == 360) eslope = -1000000;

	int ir2 = (radius - thickness) * (radius - thickness);
	int or2 = radius * radius;

	for (int x = -radius; x <= radius; x++) {
		for (int y = -radius; y <= radius; y++) {
			int x2 = x * x;
			int y2 = y * y;

			if (
				(x2 + y2 < or2 && x2 + y2 >= ir2) &&
				(
				(y > 0 && start < 180 && x <= y * sslope) ||
				(y < 0 && start > 180 && x >= y * sslope) ||
				(y < 0 && start <= 180) ||
				(y == 0 && start <= 180 && x < 0) ||
				(y == 0 && start == 0 && x > 0)
				) &&
				(
				(y > 0 && end < 180 && x >= y * eslope) ||
				(y < 0 && end > 180 && x <= y * eslope) ||
				(y > 0 && end >= 180) ||
				(y == 0 && end >= 180 && x < 0) ||
				(y == 0 && start == 0 && x > 0)
				)
				)
				_drawPixel(cx+x, cy+y, color);
		}
	}
}


//===========================================================================================================================
void EPD_drawArc(uint16_t cx, uint16_t cy, uint16_t r, uint16_t th, float start, float end, color_t color, color_t fillcolor)
{
	cx += dispWin.x1;
	cy += dispWin.y1;

	if (th < 1) th = 1;
	if (th > r) th = r;

	int f = EPD_compare_colors(fillcolor, color);

	float astart = fmodf(start, _arcAngleMax);
	float aend = fmodf(end, _arcAngleMax);

	astart += _angleOffset;
	aend += _angleOffset;

	if (astart < 0) astart += (float)360;
	if (aend < 0) aend += (float)360;

	if (aend == 0) aend = (float)360;

	if (astart > aend) {
		_fillArcOffsetted(cx, cy, r, th, astart, _arcAngleMax, fillcolor);
		_fillArcOffsetted(cx, cy, r, th, 0, aend, fillcolor);
		if (f) {
			_fillArcOffsetted(cx, cy, r, 1, astart, _arcAngleMax, color);
			_fillArcOffsetted(cx, cy, r, 1, 0, aend, color);
			_fillArcOffsetted(cx, cy, r-th, 1, astart, _arcAngleMax, color);
			_fillArcOffsetted(cx, cy, r-th, 1, 0, aend, color);
		}
	}
	else {
		_fillArcOffsetted(cx, cy, r, th, astart, aend, fillcolor);
		if (f) {
			_fillArcOffsetted(cx, cy, r, 1, astart, aend, color);
			_fillArcOffsetted(cx, cy, r-th, 1, astart, aend, color);
		}
	}
	if (f) {
		_drawLine(cx + (r-th) * cos(astart * DEG_TO_RAD), cy + (r-th) * sin(astart * DEG_TO_RAD),
			cx + (r-1) * cos(astart * DEG_TO_RAD), cy + (r-1) * sin(astart * DEG_TO_RAD), color);
		_drawLine(cx + (r-th) * cos(aend * DEG_TO_RAD), cy + (r-th) * sin(aend * DEG_TO_RAD),
			cx + (r-1) * cos(aend * DEG_TO_RAD), cy + (r-1) * sin(aend * DEG_TO_RAD), color);
	}
}

//=============================================================================================================
void EPD_drawPolygon(int cx, int cy, int sides, int diameter, color_t color, color_t fill, int rot, uint8_t th)
{
	cx += dispWin.x1;
	cy += dispWin.y1;

	int deg = rot - _angleOffset;
	int f = EPD_compare_colors(fill, color);

	if (sides < MIN_POLIGON_SIDES) sides = MIN_POLIGON_SIDES;	// This ensures the minimum side number
	if (sides > MAX_POLIGON_SIDES) sides = MAX_POLIGON_SIDES;	// This ensures the maximum side number

	int Xpoints[sides], Ypoints[sides];							// Set the arrays based on the number of sides entered
	int rads = 360 / sides;										// This equally spaces the points.

	for (int idx = 0; idx < sides; idx++) {
		Xpoints[idx] = cx + sin((float)(idx*rads + deg) * deg_to_rad) * diameter;
		Ypoints[idx] = cy + cos((float)(idx*rads + deg) * deg_to_rad) * diameter;
	}

	// Draw the polygon on the screen.
	if (f) {
		for(int idx = 0; idx < sides; idx++) {
			if((idx+1) < sides) _fillTriangle(cx,cy,Xpoints[idx],Ypoints[idx],Xpoints[idx+1],Ypoints[idx+1], fill);
			else _fillTriangle(cx,cy,Xpoints[idx],Ypoints[idx],Xpoints[0],Ypoints[0], fill);
		}
	}

	if (th) {
		for (int n=0; n<th; n++) {
			if (n > 0) {
				for (int idx = 0; idx < sides; idx++) {
					Xpoints[idx] = cx + sin((float)(idx*rads + deg) * deg_to_rad) * (diameter-n);
					Ypoints[idx] = cy + cos((float)(idx*rads + deg) * deg_to_rad) * (diameter-n);
				}
			}
			for(int idx = 0; idx < sides; idx++) {
				if( (idx+1) < sides)
					_drawLine(Xpoints[idx],Ypoints[idx],Xpoints[idx+1],Ypoints[idx+1], color); // draw the lines
				else
					_drawLine(Xpoints[idx],Ypoints[idx],Xpoints[0],Ypoints[0], color); // finishes the last line to close up the polygon.
			}
		}
	}
}

/*
// Similar to the Polygon function.
//=====================================================================================
void EPD_drawStar(int cx, int cy, int diameter, color_t color, bool fill, float factor)
{
	cx += dispWin.x1;
	cy += dispWin.y1;

	factor = constrain(factor, 1.0, 4.0);
	uint8_t sides = 5;
	uint8_t rads = 360 / sides;

	int Xpoints_O[sides], Ypoints_O[sides], Xpoints_I[sides], Ypoints_I[sides];//Xpoints_T[5], Ypoints_T[5];

	for(int idx = 0; idx < sides; idx++) {
		// makes the outer points
		Xpoints_O[idx] = cx + sin((float)(idx*rads + 72) * deg_to_rad) * diameter;
		Ypoints_O[idx] = cy + cos((float)(idx*rads + 72) * deg_to_rad) * diameter;
		// makes the inner points
		Xpoints_I[idx] = cx + sin((float)(idx*rads + 36) * deg_to_rad) * ((float)(diameter)/factor);
		// 36 is half of 72, and this will allow the inner and outer points to line up like a triangle.
		Ypoints_I[idx] = cy + cos((float)(idx*rads + 36) * deg_to_rad) * ((float)(diameter)/factor);
	}

	for(int idx = 0; idx < sides; idx++) {
		if((idx+1) < sides) {
			if(fill) {// this part below should be self explanatory. It fills in the star.
				_fillTriangle(cx,cy,Xpoints_I[idx],Ypoints_I[idx],Xpoints_O[idx],Ypoints_O[idx], color);
				_fillTriangle(cx,cy,Xpoints_O[idx],Ypoints_O[idx],Xpoints_I[idx+1],Ypoints_I[idx+1], color);
			}
			else {
				_drawLine(Xpoints_O[idx],Ypoints_O[idx],Xpoints_I[idx+1],Ypoints_I[idx+1], color);
				_drawLine(Xpoints_I[idx],Ypoints_I[idx],Xpoints_O[idx],Ypoints_O[idx], color);
			}
		}
		else {
			if(fill) {
				_fillTriangle(cx,cy,Xpoints_I[0],Ypoints_I[0],Xpoints_O[idx],Ypoints_O[idx], color);
				_fillTriangle(cx,cy,Xpoints_O[idx],Ypoints_O[idx],Xpoints_I[idx],Ypoints_I[idx], color);
			}
			else {
				_drawLine(Xpoints_O[idx],Ypoints_O[idx],Xpoints_I[idx],Ypoints_I[idx], color);
				_drawLine(Xpoints_I[0],Ypoints_I[0],Xpoints_O[idx],Ypoints_O[idx], color);
			}
		}
	}
}
*/

// ================ Font and string functions ==================================

//--------------------------------------------------------
static int load_file_font(const char * fontfile, int info)
{
	int err = 0;
	char err_msg[256] = {'\0'};

	if (userfont != NULL) {
		free(userfont);
		userfont = NULL;
	}

    struct stat sb;

    // Open the file
    FILE *fhndl = fopen(fontfile, "r");
    if (!fhndl) {
    	sprintf(err_msg, "Error opening font file '%s'", fontfile);
		err = 1;
		goto exit;
    }

	// Get file size
    if (stat(fontfile, &sb) != 0) {
    	sprintf(err_msg, "Error getting font file size");
		err = 2;
		goto exit;
    }
	int fsize = sb.st_size;
	if (fsize < 30) {
		sprintf(err_msg, "Error getting font file size");
		err = 3;
		goto exit;
	}

	userfont = malloc(fsize+4);
	if (userfont == NULL) {
		sprintf(err_msg, "Font memory allocation error");
		fclose(fhndl);
		err = 4;
		goto exit;
	}

	int read = fread(userfont, 1, fsize, fhndl);

	fclose(fhndl);

	if (read != fsize) {
		sprintf(err_msg, "Font read error");
		err = 5;
		goto exit;
	}

	userfont[read] = 0;
	if (strstr((char *)(userfont+read-8), "RPH_font") == NULL) {
		sprintf(err_msg, "Font ID not found");
		err = 6;
		goto exit;
	}

	// Check size
	int size = 0;
	int numchar = 0;
	int width = userfont[0];
	int height = userfont[1];
	uint8_t first = 255;
	uint8_t last = 0;
	//int offst = 0;
	int pminwidth = 255;
	int pmaxwidth = 0;

	if (width != 0) {
		// Fixed font
		numchar = userfont[3];
		first = userfont[2];
		last = first + numchar - 1;
		size = ((width * height * numchar) / 8) + 4;
	}
	else {
		// Proportional font
		size = 4; // point at first char data
		uint8_t charCode;
		int charwidth;

		do {
		    charCode = userfont[size];
		    charwidth = userfont[size+2];

		    if (charCode != 0xFF) {
		    	numchar++;
		    	if (charwidth != 0) size += ((((charwidth * userfont[size+3])-1) / 8) + 7);
		    	else size += 6;

		    	if (info) {
	    			if (charwidth > pmaxwidth) pmaxwidth = charwidth;
	    			if (charwidth < pminwidth) pminwidth = charwidth;
	    			if (charCode < first) first = charCode;
	    			if (charCode > last) last = charCode;
	    		}
		    }
		    else size++;
		  } while ((size < (read-8)) && (charCode != 0xFF));
	}

	if (size != (read-8)) {
		sprintf(err_msg, "Font size error: found %d expected %d)", size, (read-8));
		err = 7;
		goto exit;
	}

	if (info) {
		if (width != 0) {
			printf("Fixed width font:\r\n  size: %d  width: %d  height: %d  characters: %d (%d~%d)",
					size, width, height, numchar, first, last);
		}
		else {
			printf("Proportional font:\r\n  size: %d  width: %d~%d  height: %d  characters: %d (%d~%d)\n",
					size, pminwidth, pmaxwidth, height, numchar, first, last);
		}
	}

exit:
	if (err) {
		if (userfont) {
			free(userfont);
			userfont = NULL;
		}
		if (info) printf("Error: %d [%s]\r\n", err, err_msg);
	}
	return err;
}

//------------------------------------------------
int compile_font_file(char *fontfile, uint8_t dbg)
{
	int err = 0;
	char err_msg[128] = {'\0'};
	char outfile[128] = {'\0'};
	size_t len;
    struct stat sb;
    FILE *ffd = NULL;
    FILE *ffd_out = NULL;
    char *sourcebuf = NULL;

    len = strlen(fontfile);

	// check here that filename end with ".c".
	if ((len < 3) || (len > 125) || (strcmp(fontfile + len - 2, ".c") != 0)) {
		sprintf(err_msg, "not a .c file");
		err = 1;
		goto exit;
	}

	sprintf(outfile, "%s", fontfile);
	sprintf(outfile+strlen(outfile)-1, "fon");

	// Open the source file
    if (stat(fontfile, &sb) != 0) {
    	sprintf(err_msg, "Error opening source file '%s'", fontfile);
    	err = 2;
		goto exit;
    }
    // Open the file
    ffd = fopen(fontfile, "rb");
    if (!ffd) {
    	sprintf(err_msg, "Error opening source file '%s'", fontfile);
    	err = 3;
		goto exit;
    }

	// Open the font file
    ffd_out= fopen(outfile, "wb");
	if (!ffd_out) {
		sprintf(err_msg, "error opening destination file");
		err = 4;
		goto exit;
	}

	// Get file size
	int fsize = sb.st_size;
	if (fsize <= 0) {
		sprintf(err_msg, "source file size error");
		err = 5;
		goto exit;
	}

	sourcebuf = malloc(fsize+4);
	if (sourcebuf == NULL) {
		sprintf(err_msg, "memory allocation error");
		err = 6;
		goto exit;
	}
	char *fbuf = sourcebuf;

	int rdsize = fread(fbuf, 1, fsize, ffd);
	fclose(ffd);
	ffd = NULL;

	if (rdsize != fsize) {
		sprintf(err_msg, "error reading from source file");
		err = 7;
		goto exit;
	}

	*(fbuf+rdsize) = '\0';

	fbuf = strchr(fbuf, '{');			// beginning of font data
	char *fend = strstr(fbuf, "};");	// end of font data

	if ((fbuf == NULL) || (fend == NULL) || ((fend-fbuf) < 22)) {
		sprintf(err_msg, "wrong source file format");
		err = 8;
		goto exit;
	}

	fbuf++;
	*fend = '\0';
	char hexstr[5] = {'\0'};
	int lastline = 0;

	fbuf = strstr(fbuf, "0x");
	int size = 0;
	char *nextline;
	char *numptr;

	int bptr = 0;

	while ((fbuf != NULL) && (fbuf < fend) && (lastline == 0)) {
		nextline = strchr(fbuf, '\n'); // beginning of the next line
		if (nextline == NULL) {
			nextline = fend-1;
			lastline++;
		}
		else nextline++;

		while (fbuf < nextline) {
			numptr = strstr(fbuf, "0x");
			if ((numptr == NULL) || ((fbuf+4) > nextline)) numptr = strstr(fbuf, "0X");
			if ((numptr != NULL) && ((numptr+4) <= nextline)) {
				fbuf = numptr;
				if (bptr >= 128) {
					// buffer full, write to file
                    if (fwrite(outfile, 1, 128, ffd_out) != 128) goto error;
					bptr = 0;
					size += 128;
				}
				memcpy(hexstr, fbuf, 4);
				hexstr[4] = 0;
				outfile[bptr++] = (uint8_t)strtol(hexstr, NULL, 0);
				fbuf += 4;
			}
			else fbuf = nextline;
		}
		fbuf = nextline;
	}

	if (bptr > 0) {
		size += bptr;
        if (fwrite(outfile, 1, bptr, ffd_out) != bptr) goto error;
	}

	// write font ID
	sprintf(outfile, "RPH_font");
    if (fwrite(outfile, 1, 8, ffd_out) != 8) goto error;

	// === Test compiled font ===
	sprintf(outfile, "%s", fontfile);
	sprintf(outfile+strlen(outfile)-1, "fon");

	uint8_t *uf = userfont; // save userfont pointer
	userfont = NULL;
	if (load_file_font(outfile, 1) == 0) {
		sprintf(err_msg, "Error compiling file!");
	}
	else {
		free(userfont);
		sprintf(err_msg, "File compiled successfully.");
	}
	userfont = uf; // restore userfont

	goto exit;

error:
	sprintf(err_msg, "error writing to destination file");
	err = 9;

exit:
	if (sourcebuf) free(sourcebuf);
	if (ffd) fclose(ffd);
	if (ffd_out) fclose(ffd_out);

	if (dbg) printf("%s\r\n", err_msg);

	return err;
}


// -----------------------------------------------------------------------------------------
// Individual Proportional Font Character Format:
// -----------------------------------------------------------------------------------------
// Character Code
// yOffset				(start Y of visible pixels)
// Width				(width of the visible pixels)
// Height				(height of the visible pixels)
// xOffset				(start X of visible pixels)
// xDelta				(the distance to move the cursor. Effective width of the character.)
// Data[n]
// -----------------------------------------------------------------------------------------

//---------------------------------------------------------------------------------------------
// Character drawing rectangle is (0, 0) (xDelta-1, cfont.y_size-1)
// Character visible pixels rectangle is (xOffset, yOffset) (xOffset+Width-1, yOffset+Height-1)
//---------------------------------------------------------------------------------------------

//----------------------------------
void getFontCharacters(uint8_t *buf)
{
    if (cfont.bitmap == 2) {
    	//For 7 segment font only characters 0,1,2,3,4,5,6,7,8,9, . , - , : , / are available.
		for (uint8_t n=0; n < 11; n++) {
			buf[n] = n + 0x30;
		}
		buf[11] = '.';
		buf[12] = '-';
		buf[13] = '/';
		buf[14] = '\0';
    	return;
    }

    if (cfont.x_size > 0) {
		for (uint8_t n=0; n < cfont.numchars; n++) {
			buf[n] = cfont.offset + n;
		}
		buf[cfont.numchars] = '\0';
		return;
	}

	uint16_t tempPtr = 4; // point at first char data
	uint8_t cc, cw, ch, n;

	n = 0;
    cc = cfont.font[tempPtr++];
    while (cc != 0xFF)  {
    	cfont.numchars++;
        tempPtr++;
        cw = cfont.font[tempPtr++];
        ch = cfont.font[tempPtr++];
        tempPtr++;
        tempPtr++;
		if (cw != 0) {
			// packed bits
			tempPtr += (((cw * ch)-1) / 8) + 1;
		}
		buf[n++] = cc;
	    cc = cfont.font[tempPtr++];
	}
	buf[n] = '\0';
}

// Set max width & height of the proportional font
//-----------------------------
static void getMaxWidthHeight()
{
	uint16_t tempPtr = 4; // point at first char data
	uint8_t cc, cw, ch, cd, cy;

	cfont.numchars = 0;
	cfont.max_x_size = 0;

    cc = cfont.font[tempPtr++];
    while (cc != 0xFF)  {
    	cfont.numchars++;
        cy = cfont.font[tempPtr++];
        cw = cfont.font[tempPtr++];
        ch = cfont.font[tempPtr++];
        tempPtr++;
        cd = cfont.font[tempPtr++];
        cy += ch;
		if (cw > cfont.max_x_size) cfont.max_x_size = cw;
		if (cd > cfont.max_x_size) cfont.max_x_size = cd;
		if (ch > cfont.y_size) cfont.y_size = ch;
		if (cy > cfont.y_size) cfont.y_size = cy;
		if (cw != 0) {
			// packed bits
			tempPtr += (((cw * ch)-1) / 8) + 1;
		}
	    cc = cfont.font[tempPtr++];
	}
    cfont.size = tempPtr;
}

// Return the Glyph data for an individual character in the proportional font
//------------------------------------
static uint8_t getCharPtr(uint8_t c) {
  uint16_t tempPtr = 4; // point at first char data

  do {
	fontChar.charCode = cfont.font[tempPtr++];
    if (fontChar.charCode == 0xFF) return 0;

    fontChar.adjYOffset = cfont.font[tempPtr++];
    fontChar.width = cfont.font[tempPtr++];
    fontChar.height = cfont.font[tempPtr++];
    fontChar.xOffset = cfont.font[tempPtr++];
    fontChar.xOffset = fontChar.xOffset < 0x80 ? fontChar.xOffset : -(0xFF - fontChar.xOffset);
    fontChar.xDelta = cfont.font[tempPtr++];

    if (c != fontChar.charCode && fontChar.charCode != 0xFF) {
      if (fontChar.width != 0) {
        // packed bits
        tempPtr += (((fontChar.width * fontChar.height)-1) / 8) + 1;
      }
    }
  } while ((c != fontChar.charCode) && (fontChar.charCode != 0xFF));

  fontChar.dataPtr = tempPtr;
  if (c == fontChar.charCode) {
    if (font_forceFixed > 0) {
      // fix width & offset for forced fixed width
      fontChar.xDelta = cfont.max_x_size;
      fontChar.xOffset = (fontChar.xDelta - fontChar.width) / 2;
    }
  }
  else return 0;

  return 1;
}

/*
//-----------------------
static void _testFont() {
  if (cfont.x_size) {
	  printf("FONT TEST: fixed font\r\n");
	  return;
  }
  uint16_t tempPtr = 4; // point at first char data
  uint8_t c = 0x20;
  for (c=0x20; c <0xFF; c++) {
	fontChar.charCode = cfont.font[tempPtr++];
    if (fontChar.charCode == 0xFF) break;
    if (fontChar.charCode != c) {
    	printf("FONT TEST: last sequential char: %d, expected %d\r\n", fontChar.charCode, c);
    	break;
    }
    c = fontChar.charCode;
    fontChar.adjYOffset = cfont.font[tempPtr++];
    fontChar.width = cfont.font[tempPtr++];
    fontChar.height = cfont.font[tempPtr++];
    fontChar.xOffset = cfont.font[tempPtr++];
    fontChar.xOffset = fontChar.xOffset < 0x80 ? fontChar.xOffset : -(0xFF - fontChar.xOffset);
    fontChar.xDelta = cfont.font[tempPtr++];

    if (fontChar.charCode != 0xFF) {
      if (fontChar.width != 0) {
        // packed bits
        tempPtr += (((fontChar.width * fontChar.height)-1) / 8) + 1;
      }
    }
  }
  printf("FONT TEST: W=%d  H=%d last char: %d [%c]; length: %d\r\n", cfont.max_x_size, cfont.y_size, c, c, tempPtr);
}
*/

//===================================================
void EPD_setFont(uint8_t font, const char *font_file)
{
  cfont.font = NULL;

  if (font == FONT_7SEG) {
    cfont.bitmap = 2;
    cfont.x_size = 24;
    cfont.y_size = 6;
    cfont.offset = 0;
    cfont.color  = _fg;
  }
  else {
	  if (font == USER_FONT) {
		  if (load_file_font(font_file, 0) != 0) cfont.font = tft_DefaultFont;
		  else cfont.font = userfont;
	  }
	  else if (font == DEJAVU18_FONT) cfont.font = tft_Dejavu18;
	  else if (font == DEJAVU24_FONT) cfont.font = tft_Dejavu24;
	  else if (font == UBUNTU16_FONT) cfont.font = tft_Ubuntu16;
	  else if (font == COMIC24_FONT) cfont.font = tft_Comic24;
	  else if (font == MINYA24_FONT) cfont.font = tft_minya24;
	  else if (font == TOONEY32_FONT) cfont.font = tft_tooney32;
	  else if (font == SMALL_FONT) cfont.font = tft_SmallFont;
	  else cfont.font = tft_DefaultFont;

	  cfont.bitmap = 1;
	  cfont.x_size = cfont.font[0];
	  cfont.y_size = cfont.font[1];
	  if (cfont.x_size > 0) {
		  cfont.offset = cfont.font[2];
		  cfont.numchars = cfont.font[3];
		  cfont.size = cfont.x_size * cfont.y_size * cfont.numchars;
	  }
	  else {
		  cfont.offset = 4;
		  getMaxWidthHeight();
	  }
	  //_testFont();
  }
}

// -----------------------------------------------------------------------------------------
// Individual Proportional Font Character Format:
// -----------------------------------------------------------------------------------------
// Character Code
// yOffset				(start Y of visible pixels)
// Width				(width of the visible pixels)
// Height				(height of the visible pixels)
// xOffset				(start X of visible pixels)
// xDelta				(the distance to move the cursor. Effective width of the character.)
// Data[n]
// -----------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------
// Character drawing rectangle is (0, 0) (xDelta-1, cfont.y_size-1)
// Character visible pixels rectangle is (xOffset, yOffset) (xOffset+Width-1, yOffset+Height-1)
//---------------------------------------------------------------------------------------------

// print non-rotated proportional character
// character is already in fontChar
//----------------------------------------------
static int printProportionalChar(int x, int y) {
	uint8_t ch = 0;
	int i, j, char_width;

	char_width = ((fontChar.width > fontChar.xDelta) ? fontChar.width : fontChar.xDelta);
	int cx, cy;

	if (!font_transparent) _fillRect(x, y, char_width+1, cfont.y_size, _bg);

	// draw Glyph
	uint8_t mask = 0x80;
	for (j=0; j < fontChar.height; j++) {
		for (i=0; i < fontChar.width; i++) {
			if (((i + (j*fontChar.width)) % 8) == 0) {
				mask = 0x80;
				ch = cfont.font[fontChar.dataPtr++];
			}

			if ((ch & mask) !=0) {
				cx = (uint16_t)(x+fontChar.xOffset+i);
				cy = (uint16_t)(y+j+fontChar.adjYOffset);
				_drawPixel(cx, cy, _fg);
			}
			mask >>= 1;
		}
	}

	return char_width;
}

// non-rotated fixed width character
//----------------------------------------------
static void printChar(uint8_t c, int x, int y) {
	uint8_t i, j, ch, fz, mask;
	uint16_t k, temp, cx, cy;

	// fz = bytes per char row
	fz = cfont.x_size/8;
	if (cfont.x_size % 8) fz++;

	// get character position in buffer
	temp = ((c-cfont.offset)*((fz)*cfont.y_size))+4;

	if (!font_transparent) _fillRect(x, y, cfont.x_size, cfont.y_size, _bg);

	for (j=0; j<cfont.y_size; j++) {
		for (k=0; k < fz; k++) {
			ch = cfont.font[temp+k];
			mask=0x80;
			for (i=0; i<8; i++) {
				if ((ch & mask) !=0) {
					cx = (uint16_t)(x+i+(k*8));
					cy = (uint16_t)(y+j);
					_drawPixel(cx, cy, _fg);
				}
				mask >>= 1;
			}
		}
		temp += (fz);
	}
}

// print rotated proportional character
// character is already in fontChar
//---------------------------------------------------
static int rotatePropChar(int x, int y, int offset) {
  uint8_t ch = 0;
  double radian = font_rotate * DEG_TO_RAD;
  float cos_radian = cos(radian);
  float sin_radian = sin(radian);

  uint8_t mask = 0x80;
  for (int j=0; j < fontChar.height; j++) {
    for (int i=0; i < fontChar.width; i++) {
      if (((i + (j*fontChar.width)) % 8) == 0) {
        mask = 0x80;
        ch = cfont.font[fontChar.dataPtr++];
      }

      int newX = (int)(x + (((offset + i) * cos_radian) - ((j+fontChar.adjYOffset)*sin_radian)));
      int newY = (int)(y + (((j+fontChar.adjYOffset) * cos_radian) + ((offset + i) * sin_radian)));

      if ((ch & mask) != 0) _drawPixel(newX,newY,_fg);
      else if (!font_transparent) _drawPixel(newX,newY,_bg);

      mask >>= 1;
    }
  }

  return fontChar.xDelta+1;
}

// rotated fixed width character
//--------------------------------------------------------
static void rotateChar(uint8_t c, int x, int y, int pos) {
  uint8_t i,j,ch,fz,mask;
  uint16_t temp;
  int newx,newy;
  double radian = font_rotate*0.0175;
  float cos_radian = cos(radian);
  float sin_radian = sin(radian);
  int zz;

  if( cfont.x_size < 8 ) fz = cfont.x_size;
  else fz = cfont.x_size/8;
  temp=((c-cfont.offset)*((fz)*cfont.y_size))+4;

  for (j=0; j<cfont.y_size; j++) {
    for (zz=0; zz<(fz); zz++) {
      ch = cfont.font[temp+zz];
      mask = 0x80;
      for (i=0; i<8; i++) {
        newx=(int)(x+(((i+(zz*8)+(pos*cfont.x_size))*cos_radian)-((j)*sin_radian)));
        newy=(int)(y+(((j)*cos_radian)+((i+(zz*8)+(pos*cfont.x_size))*sin_radian)));

        if ((ch & mask) != 0) _drawPixel(newx,newy,_fg);
        else if (!font_transparent) _drawPixel(newx,newy,_bg);
        mask >>= 1;
      }
    }
    temp+=(fz);
  }
  // calculate x,y for the next char
  EPD_X = (int)(x + ((pos+1) * cfont.x_size * cos_radian));
  EPD_Y = (int)(y + ((pos+1) * cfont.x_size * sin_radian));
}

//----------------------
static int _7seg_width()
{
	return (2 * (2 * cfont.y_size + 1)) + cfont.x_size;
}

//-----------------------
static int _7seg_height()
{
	return (3 * (2 * cfont.y_size + 1)) + (2 * cfont.x_size);
}

// Returns the string width in pixels.
// Useful for positions strings on the screen.
//===============================
int EPD_getStringWidth(char* str)
{
    int strWidth = 0;

	if (cfont.bitmap == 2) strWidth = ((_7seg_width()+2) * strlen(str)) - 2;	// 7-segment font
	else if (cfont.x_size != 0) strWidth = strlen(str) * cfont.x_size;			// fixed width font
	else {
		// calculate the width of the string of proportional characters
		char* tempStrptr = str;
		while (*tempStrptr != 0) {
			if (getCharPtr(*tempStrptr++)) {
				strWidth += (((fontChar.width > fontChar.xDelta) ? fontChar.width : fontChar.xDelta) + 1);
			}
		}
		strWidth--;
	}
	return strWidth;
}

//===============================================
void EPD_clearStringRect(int x, int y, char *str)
{
	int w = EPD_getStringWidth(str);
	int h = EPD_getfontheight();
	EPD_fillRect(x+dispWin.x1, y+dispWin.y1, w, h, _bg);
}

//==============================================================================
/**
 * bit-encoded bar position of all digits' bcd segments
 *
 *           6
 * 		  +-----+
 * 		3 |  .	| 2
 * 		  +--5--+
 * 		1 |  .	| 0
 * 		  +--.--+
 * 		     4
 */
static const uint16_t font_bcd[] = {
  0x200, // 0010 0000 0000  // -
  0x080, // 0000 1000 0000  // .
  0x06C, // 0100 0110 1100  // /, degree
  0x05f, // 0000 0101 1111, // 0
  0x005, // 0000 0000 0101, // 1
  0x076, // 0000 0111 0110, // 2
  0x075, // 0000 0111 0101, // 3
  0x02d, // 0000 0010 1101, // 4
  0x079, // 0000 0111 1001, // 5
  0x07b, // 0000 0111 1011, // 6
  0x045, // 0000 0100 0101, // 7
  0x07f, // 0000 0111 1111, // 8
  0x07d, // 0000 0111 1101  // 9
  0x900  // 1001 0000 0000  // :
};

//-----------------------------------------------------------------------------------------------
static void barVert(int16_t x, int16_t y, int16_t w, int16_t l, color_t color, color_t outline) {
  _fillTriangle(x+1, y+2*w, x+w, y+w+1, x+2*w-1, y+2*w, color);
  _fillTriangle(x+1, y+2*w+l+1, x+w, y+3*w+l, x+2*w-1, y+2*w+l+1, color);
  _fillRect(x, y+2*w+1, 2*w+1, l, color);
  if (cfont.offset) {
    _drawTriangle(x+1, y+2*w, x+w, y+w+1, x+2*w-1, y+2*w, outline);
    _drawTriangle(x+1, y+2*w+l+1, x+w, y+3*w+l, x+2*w-1, y+2*w+l+1, outline);
    _drawRect(x, y+2*w+1, 2*w+1, l, outline);
  }
}

//----------------------------------------------------------------------------------------------
static void barHor(int16_t x, int16_t y, int16_t w, int16_t l, color_t color, color_t outline) {
  _fillTriangle(x+2*w, y+2*w-1, x+w+1, y+w, x+2*w, y+1, color);
  _fillTriangle(x+2*w+l+1, y+2*w-1, x+3*w+l, y+w, x+2*w+l+1, y+1, color);
  _fillRect(x+2*w+1, y, l, 2*w+1, color);
  if (cfont.offset) {
    _drawTriangle(x+2*w, y+2*w-1, x+w+1, y+w, x+2*w, y+1, outline);
    _drawTriangle(x+2*w+l+1, y+2*w-1, x+3*w+l, y+w, x+2*w+l+1, y+1, outline);
    _drawRect(x+2*w+1, y, l, 2*w+1, outline);
  }
}

//--------------------------------------------------------------------------------------------
static void _draw7seg(int16_t x, int16_t y, int8_t num, int16_t w, int16_t l, color_t color) {
  /* TODO: clipping */
  if (num < 0x2D || num > 0x3A) return;

  int16_t c = font_bcd[num-0x2D];
  int16_t d = 2*w+l+1;

  // === Clear unused segments ===
  /*
  if (!(c & 0x001)) barVert(x+d, y+d, w, l, _bg, _bg);
  if (!(c & 0x002)) barVert(x,   y+d, w, l, _bg, _bg);
  if (!(c & 0x004)) barVert(x+d, y, w, l, _bg, _bg);
  if (!(c & 0x008)) barVert(x,   y, w, l, _bg, _bg);
  if (!(c & 0x010)) barHor(x, y+2*d, w, l, _bg, _bg);
  if (!(c & 0x020)) barHor(x, y+d, w, l, _bg, _bg);
  if (!(c & 0x040)) barHor(x, y, w, l, _bg, _bg);

  if (!(c & 0x080)) {
    // low point
    _fillRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, _bg);
    if (cfont.offset) _drawRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, _bg);
  }
  if (!(c & 0x100)) {
    // down middle point
    _fillRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, _bg);
    if (cfont.offset) _drawRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, _bg);
  }
  if (!(c & 0x800)) {
	// up middle point
    _fillRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, _bg);
    if (cfont.offset) _drawRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, _bg);
  }
  if (!(c & 0x200)) {
    // middle, minus
    _fillRect(x+2*w+1, y+d, l, 2*w+1, _bg);
    if (cfont.offset) _drawRect(x+2*w+1, y+d, l, 2*w+1, _bg);
  }
  */
  barVert(x+d, y+d, w, l, _bg, _bg);
  barVert(x,   y+d, w, l, _bg, _bg);
  barVert(x+d, y, w, l, _bg, _bg);
  barVert(x,   y, w, l, _bg, _bg);
  barHor(x, y+2*d, w, l, _bg, _bg);
  barHor(x, y+d, w, l, _bg, _bg);
  barHor(x, y, w, l, _bg, _bg);

  _fillRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, _bg);
  _drawRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, _bg);
  _fillRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, _bg);
  _drawRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, _bg);
  _fillRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, _bg);
  _drawRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, _bg);
  _fillRect(x+2*w+1, y+d, l, 2*w+1, _bg);
  _drawRect(x+2*w+1, y+d, l, 2*w+1, _bg);

  // === Draw used segments ===
  if (c & 0x001) barVert(x+d, y+d, w, l, color, cfont.color);	// down right
  if (c & 0x002) barVert(x,   y+d, w, l, color, cfont.color);	// down left
  if (c & 0x004) barVert(x+d, y, w, l, color, cfont.color);		// up right
  if (c & 0x008) barVert(x,   y, w, l, color, cfont.color);		// up left
  if (c & 0x010) barHor(x, y+2*d, w, l, color, cfont.color);	// down
  if (c & 0x020) barHor(x, y+d, w, l, color, cfont.color);		// middle
  if (c & 0x040) barHor(x, y, w, l, color, cfont.color);		// up

  if (c & 0x080) {
    // low point
    _fillRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, color);
    if (cfont.offset) _drawRect(x+(d/2), y+2*d, 2*w+1, 2*w+1, cfont.color);
  }
  if (c & 0x100) {
    // down middle point
    _fillRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, color);
    if (cfont.offset) _drawRect(x+(d/2), y+d+2*w+1, 2*w+1, l/2, cfont.color);
  }
  if (c & 0x800) {
	// up middle point
    _fillRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, color);
    if (cfont.offset) _drawRect(x+(d/2), y+(2*w)+1+(l/2), 2*w+1, l/2, cfont.color);
  }
  if (c & 0x200) {
    // middle, minus
    _fillRect(x+2*w+1, y+d, l, 2*w+1, color);
    if (cfont.offset) _drawRect(x+2*w+1, y+d, l, 2*w+1, cfont.color);
  }
}
//==============================================================================

//======================================
void EPD_print(char *st, int x, int y) {
	int stl, i, tmpw, tmph, fh;
	uint8_t ch;

	if (cfont.bitmap == 0) return; // wrong font selected

	// ** Rotated strings cannot be aligned
	if ((font_rotate != 0) && ((x <= CENTER) || (y <= CENTER))) return;

	if ((x < LASTX) || (font_rotate == 0)) EPD_OFFSET = 0;

	if ((x >= LASTX) && (x < LASTY)) x = EPD_X + (x-LASTX);
	else if (x > CENTER) x += dispWin.x1;

	if (y >= LASTY) y = EPD_Y + (y-LASTY);
	else if (y > CENTER) y += dispWin.y1;

	// ** Get number of characters in string to print
	stl = strlen(st);

	// ** Calculate CENTER, RIGHT or BOTTOM position
	tmpw = EPD_getStringWidth(st);	// string width in pixels
	fh = cfont.y_size;			// font height
	if ((cfont.x_size != 0) && (cfont.bitmap == 2)) {
		// 7-segment font
		fh = (3 * (2 * cfont.y_size + 1)) + (2 * cfont.x_size);  // 7-seg character height
	}

	if (x == RIGHT) x = dispWin.x2 - tmpw + dispWin.x1;
	else if (x == CENTER) x = (((dispWin.x2 - dispWin.x1 + 1) - tmpw) / 2) + dispWin.x1;

	if (y == BOTTOM) y = dispWin.y2 - fh + dispWin.y1;
	else if (y==CENTER) y = (((dispWin.y2 - dispWin.y1 + 1) - (fh/2)) / 2) + dispWin.y1;

	if (x < dispWin.x1) x = dispWin.x1;
	if (y < dispWin.y1) y = dispWin.y1;
	if ((x > dispWin.x2) || (y > dispWin.y2)) return;

	 EPD_X = x;
	 EPD_Y = y;

	// ** Adjust y position
	tmph = cfont.y_size; // font height
	// for non-proportional fonts, char width is the same for all chars
	tmpw = cfont.x_size;
	if (cfont.x_size != 0) {
		if (cfont.bitmap == 2) {	// 7-segment font
			tmpw = _7seg_width();	// character width
			tmph = _7seg_height();	// character height
		}
	}
	else EPD_OFFSET = 0;	// fixed font; offset not needed

	if (( EPD_Y + tmph - 1) > dispWin.y2) return;

	int offset = EPD_OFFSET;

	for (i=0; i<stl; i++) {
		ch = st[i]; // get string character

		if (ch == 0x0D) { // === '\r', erase to eol ====
			if ((!font_transparent) && (font_rotate==0)) _fillRect( EPD_X, EPD_Y,  dispWin.x2+1- EPD_X, tmph, _bg);
		}

		else if (ch == 0x0A) { // ==== '\n', new line ====
			if (cfont.bitmap == 1) {
				 EPD_Y += tmph + font_line_space;
				if ( EPD_Y > (dispWin.y2-tmph)) break;
				 EPD_X = dispWin.x1;
			}
		}

		else { // ==== other characters ====
			if (cfont.x_size == 0) {
				// for proportional font get character data to 'fontChar'
				if (getCharPtr(ch)) tmpw = fontChar.xDelta;
				else continue;
			}

			// check if character can be displayed in the current line
			if (( EPD_X+tmpw) > (dispWin.x2)) {
				if (text_wrap == 0) break;
				 EPD_Y += tmph + font_line_space;
				if ( EPD_Y > (dispWin.y2-tmph)) break;
				 EPD_X = dispWin.x1;
			}

			// Let's print the character
			if (cfont.x_size == 0) {
				// == proportional font
				if (font_rotate == 0) EPD_X += printProportionalChar( EPD_X, EPD_Y) + 1;
				else {
					// rotated proportional font
					offset += rotatePropChar(x, y, offset);
					EPD_OFFSET = offset;
				}
			}
			else {
				if (cfont.bitmap == 1) {
					// == fixed font
					if ((ch < cfont.offset) || ((ch-cfont.offset) > cfont.numchars)) ch = cfont.offset;
					if (font_rotate == 0) {
						printChar(ch, EPD_X, EPD_Y);
						 EPD_X += tmpw;
					}
					else rotateChar(ch, x, y, i);
				}
				else if (cfont.bitmap == 2) {
					// == 7-segment font ==
					_draw7seg( EPD_X, EPD_Y, ch, cfont.y_size, cfont.x_size, _fg);
					 EPD_X += (tmpw + 2);
				}
			}
		}
	}
}


// ================ Service functions ==========================================

//=====================================================================
void EPD_setclipwin(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
	dispWin.x1 = x1;
	dispWin.y1 = y1;
	dispWin.x2 = x2;
	dispWin.y2 = y2;

	if (dispWin.x2 >= EPD_DISPLAY_WIDTH) dispWin.x2 = EPD_DISPLAY_WIDTH-1;
	if (dispWin.y2 >= EPD_DISPLAY_HEIGHT) dispWin.y2 = EPD_DISPLAY_HEIGHT-1;
	if (dispWin.x1 > dispWin.x2) dispWin.x1 = dispWin.x2;
	if (dispWin.y1 > dispWin.y2) dispWin.y1 = dispWin.y2;
}

//=====================
void EPD_resetclipwin()
{
	dispWin.x2 = EPD_DISPLAY_WIDTH-1;
	dispWin.y2 = EPD_DISPLAY_HEIGHT-1;
	dispWin.x1 = 0;
	dispWin.y1 = 0;
}

//==========================================================================
void set_7seg_font_atrib(uint8_t l, uint8_t w, int outline, color_t color) {
	if (cfont.bitmap != 2) return;

	if (l < 6) l = 6;
    if (l > 40) l = 40;
    if (w < 1) w = 1;
    if (w > (l/2)) w = l/2;
    if (w > 12) w = 12;

    cfont.x_size = l;
	cfont.y_size = w;
	cfont.offset = outline;
	cfont.color  = color;
}

//==========================================
int EPD_getfontsize(int *width, int* height)
{
  if (cfont.bitmap == 1) {
    if (cfont.x_size != 0) *width = cfont.x_size;	// fixed width font
    else *width = cfont.max_x_size;					// proportional font
    *height = cfont.y_size;
  }
  else if (cfont.bitmap == 2) {
	// 7-segment font
    *width = _7seg_width();
    *height = _7seg_height();
  }
  else {
    *width = 0;
    *height = 0;
    return 0;
  }
  return 1;
}

//=====================
int EPD_getfontheight()
{
  if (cfont.bitmap == 1) return cfont.y_size;			// Bitmap font
  else if (cfont.bitmap == 2) return _7seg_height();	// 7-segment font
  return 0;
}

//====================
void EPD_saveClipWin()
{
	dispWinTemp.x1 = dispWin.x1;
	dispWinTemp.y1 = dispWin.y1;
	dispWinTemp.x2 = dispWin.x2;
	dispWinTemp.y2 = dispWin.y2;
}

//=======================
void EPD_restoreClipWin()
{
	dispWin.x1 = dispWinTemp.x1;
	dispWin.y1 = dispWinTemp.y1;
	dispWin.x2 = dispWinTemp.x2;
	dispWin.y2 = dispWinTemp.y2;
}


// ================ JPG SUPPORT ================================================

// RGB to GRAYSCALE constants
// 0.2989  0.5870  0.1140
#define GS_FACT_R 0.2989
#define GS_FACT_G 0.4870
#define GS_FACT_B 0.2140

// User defined device identifier
typedef struct {
	FILE		*fhndl;			// File handler for input function
    int			x;				// image top left point X position
    int			y;				// image top left point Y position
    uint8_t		*membuff;		// memory buffer containing the image
    uint32_t	bufsize;		// size of the memory buffer
    uint32_t	bufptr;			// memory buffer current position
} JPGIODEV;


// User defined call-back function to input JPEG data from file
//---------------------
static UINT tjd_input (
	JDEC* jd,		// Decompression object
	BYTE* buff,		// Pointer to the read buffer (NULL:skip)
	UINT nd			// Number of bytes to read/skip from input stream
)
{
	int rb = 0;
	// Device identifier for the session (5th argument of jd_prepare function)
	JPGIODEV *dev = (JPGIODEV*)jd->device;

	if (buff) {	// Read nd bytes from the input strem
		rb = fread(buff, 1, nd, dev->fhndl);
		return rb;	// Returns actual number of bytes read
	}
	else {	// Remove nd bytes from the input stream
		if (fseek(dev->fhndl, nd, SEEK_CUR) >= 0) return nd;
		else return 0;
	}
}

// User defined call-back function to input JPEG data from memory buffer
//-------------------------
static UINT tjd_buf_input (
	JDEC* jd,		// Decompression object
	BYTE* buff,		// Pointer to the read buffer (NULL:skip)
	UINT nd			// Number of bytes to read/skip from input stream
)
{
	// Device identifier for the session (5th argument of jd_prepare function)
	JPGIODEV *dev = (JPGIODEV*)jd->device;
	if (!dev->membuff) return 0;
	if (dev->bufptr >= (dev->bufsize + 2)) return 0; // end of stream

	if ((dev->bufptr + nd) > (dev->bufsize + 2)) nd = (dev->bufsize + 2) - dev->bufptr;

	if (buff) {	// Read nd bytes from the input strem
		memcpy(buff, dev->membuff + dev->bufptr, nd);
		dev->bufptr += nd;
		return nd;	// Returns number of bytes read
	}
	else {	// Remove nd bytes from the input stream
		dev->bufptr += nd;
		return nd;
	}
}

// User defined call-back function to output RGB bitmap to display device
//----------------------
static UINT tjd_output (
	JDEC* jd,		// Decompression object of current session
	void* bitmap,	// Bitmap data to be output
	JRECT* rect		// Rectangular region to output
)
{
	// Device identifier for the session (5th argument of jd_prepare function)
	JPGIODEV *dev = (JPGIODEV*)jd->device;

	// ** Put the rectangular into the display device **
	int x;
	int y;
	int dleft, dtop, dright, dbottom;
	BYTE *src = (BYTE*)bitmap;

	int left = rect->left + dev->x;
	int top = rect->top + dev->y;
	int right = rect->right + dev->x;
	int bottom = rect->bottom + dev->y;

	if ((left > dispWin.x2) || (top > dispWin.y2)) return 1;	// out of screen area, return
	if ((right < dispWin.x1) || (bottom < dispWin.y1)) return 1;// out of screen area, return

	if (left < dispWin.x1) dleft = dispWin.x1;
	else dleft = left;
	if (top < dispWin.y1) dtop = dispWin.y1;
	else dtop = top;
	if (right > dispWin.x2) dright = dispWin.x2;
	else dright = right;
	if (bottom > dispWin.y2) dbottom = dispWin.y2;
	else dbottom = bottom;

	if ((dleft > dispWin.x2) || (dtop > dispWin.y2)) return 1;		// out of screen area, return
	if ((dright < dispWin.x1) || (dbottom < dispWin.y1)) return 1;	// out of screen area, return

	uint32_t len = ((dright-dleft+1) * (dbottom-dtop+1));	// calculate length of data

	float gs_clr = 0;
	uint8_t rgb_color[3];
	uint8_t last_lvl, i;
	uint8_t pix;
	if ((len > 0) && (len <= JPG_IMAGE_LINE_BUF_SIZE)) {
		for (y = top; y <= bottom; y++) {
			for (x = left; x <= right; x++) {
				// Clip to display area
				if ((x >= dleft) && (y >= dtop) && (x <= dright) && (y <= dbottom)) {
					// Directly convert color to 4-bit gray scale
					pix = 0;
					pix |= ((*src++) >> 4) & 0x08;
					pix |= ((*src++) >> 5) & 0x06;
					pix |= ((*src++) >> 7);
					pix ^= 0x0F;


					/* Convert rgb color to gray scale
					memcpy(rgb_color, src, 3);
					src += 3;
				    gs_clr = (GS_FACT_R * rgb_color[0]) + (GS_FACT_G * rgb_color[1]) + (GS_FACT_B * rgb_color[2]);
				    if (gs_clr > 255) gs_clr = 255;
				    // Use only 4 bits & invert
				    //pix = ((uint8_t)gs_clr >> 4) ^ 0x0F;
				    pix = (uint8_t)gs_clr;

				    // Using gray scale lookup table
				    last_lvl = 0;
				    i = 0;
				    for (i=0; i<16; i++) {
				    	if ((pix > last_lvl) && (pix <= lvl_buf_jpg[i])) {
				    		pix = 15 - i;
					        last_lvl = lvl_buf[i];
					        break;
				        }
				        last_lvl = lvl_buf[i];
				    }
					*/
				    gs_disp_buffer[(y * EPD_DISPLAY_WIDTH) + x] = pix;
		    		gs_used_shades |= (1 << pix);
				}
				else src += 3; // skip
			}
		}
	}
	else {
		printf("Data size error: %d jpg: (%d,%d,%d,%d) disp: (%d,%d,%d,%d)\r\n", len, left,top,right,bottom, dleft,dtop,dright,dbottom);
		return 0;  // stop decompression
	}

	return 1;	// Continue to decompression
}

// X & Y can be < 0 !
//=================================================================================
int EPD_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int size)
{
	JPGIODEV dev;
    struct stat sb;
	char *work = NULL;		// Pointer to the working buffer (must be 4-byte aligned)
	UINT sz_work = 3800;	// Size of the working buffer (must be power of 2)
	JDEC jd;				// Decompression object (70 bytes)
	JRESULT rc;
	int res = -10;

    if (fname == NULL) {
    	// image from buffer
    	dev.fhndl = NULL;
        dev.membuff = buf;
        dev.bufsize = size;
        dev.bufptr = 0;
    }
    else {
    	// image from file
        dev.membuff = NULL;
        dev.bufsize = 0;
        dev.bufptr = 0;

        if (stat(fname, &sb) != 0) {
        	if (image_debug) printf("File error: %ss\r\n", strerror(errno));
        	res = -11;
            goto exit;
        }

        dev.fhndl = fopen(fname, "r");
        if (!dev.fhndl) {
        	if (image_debug) printf("Error opening file: %s\r\n", strerror(errno));
        	res = -12;
            goto exit;
        }
    }

	if (scale > 3) scale = 3;

	work = malloc(sz_work);
	if (work) {
		if (dev.membuff) rc = jd_prepare(&jd, tjd_buf_input, (void *)work, sz_work, &dev);
		else rc = jd_prepare(&jd, tjd_input, (void *)work, sz_work, &dev);
		if (rc == JDR_OK) {
			if (x == CENTER) x = ((dispWin.x2 - dispWin.x1 + 1 - (int)(jd.width >> scale)) / 2) + dispWin.x1;
			else if (x == RIGHT) x = dispWin.x2 + 1 - (int)(jd.width >> scale);

			if (y == CENTER) y = ((dispWin.y2 - dispWin.y1 + 1 - (int)(jd.height >> scale)) / 2) + dispWin.y1;
			else if (y == BOTTOM) y = dispWin.y2 + 1 - (int)(jd.height >> scale);

			if (x < ((dispWin.x2-1) * -1)) x = (dispWin.x2-1) * -1;
			if (y < ((dispWin.y2-1)) * -1) y = (dispWin.y2-1) * -1;
			if (x > (dispWin.x2-1)) x = dispWin.x2 - 1;
			if (y > (dispWin.y2-1)) y = dispWin.y2-1;

			dev.x = x;
			dev.y = y;

			// Start to decode the JPEG file
			rc = jd_decomp(&jd, tjd_output, scale);

			if (rc != JDR_OK) {
				if (image_debug) printf("jpg decompression error %d\r\n", rc);
				res = rc * -1;
			}
			res = 0;
			if (image_debug) printf("Jpg size: %dx%d, position; %d,%d, scale: %d, bytes used: %d\r\n", jd.width, jd.height, x, y, scale, jd.sz_pool);
		}
		else {
			if (image_debug) printf("jpg prepare error %d\r\n", rc);
			res = rc * -1;
		}
	}
	else {
		if (image_debug) printf("work buffer allocation error\r\n");
		res = -13;
	}

exit:
	if (work) free(work);  // free work buffer
    if (dev.fhndl) fclose(dev.fhndl);  // close input file
    return res;
}



================================================
FILE: components/epaper/EPD.h
================================================
/*
 * High level EPD functions
 * Author:  LoBo 06/2017, https://github/loboris
 * 
 */

#ifndef _EPD_H_
#define _EPD_H_

#include <stdlib.h>
#include "EPDspi.h"

typedef uint8_t color_t;

typedef struct {
	uint16_t        x1;
	uint16_t        y1;
	uint16_t        x2;
	uint16_t        y2;
} dispWin_t;

typedef struct {
	uint8_t 	*font;
	uint8_t 	x_size;
	uint8_t 	y_size;
	uint8_t	    offset;
	uint16_t	numchars;
    uint16_t	size;
	uint8_t 	max_x_size;
    uint8_t     bitmap;
	color_t     color;
} Font_t;



//==========================================================================================
// ==== Global variables ===================================================================
//==========================================================================================
uint8_t   orientation;		// current screen orientation
uint16_t  font_rotate;   	// current font font_rotate angle (0~395)
uint8_t   font_transparent;	// if not 0 draw fonts transparent
uint8_t   font_forceFixed;  // if not zero force drawing proportional fonts with fixed width
uint8_t   font_buffered_char;
uint8_t   font_line_space;	// additional spacing between text lines; added to font height
uint8_t   text_wrap;        // if not 0 wrap long text to the new line, else clip
color_t   _fg;            	// current foreground color for fonts
color_t   _bg;            	// current background for non transparent fonts
dispWin_t dispWin;			// display clip window
float	  _angleOffset;		// angle offset for arc, polygon and line by angle functions

Font_t cfont;					// Current font structure
uint8_t image_debug;

int	EPD_X;					// X position of the next character after EPD_print() function
int	EPD_Y;					// Y position of the next character after EPD_print() function
// =========================================================================================


// Buffer is created during jpeg decode for sending data
// Total size of the buffer is  2 * (JPG_IMAGE_LINE_BUF_SIZE * 3)
// The size must be multiple of 256 bytes !!
#define JPG_IMAGE_LINE_BUF_SIZE 512

// --- Constants for ellipse function ---
#define EPD_ELLIPSE_UPPER_RIGHT 0x01
#define EPD_ELLIPSE_UPPER_LEFT  0x02
#define EPD_ELLIPSE_LOWER_LEFT  0x04
#define EPD_ELLIPSE_LOWER_RIGHT 0x08

// Constants for Arc function
// number representing the maximum angle (e.g. if 100, then if you pass in start=0 and end=50, you get a half circle)
// this can be changed with setArcParams function at runtime
#define DEFAULT_ARC_ANGLE_MAX 360
// rotational offset in degrees defining position of value 0 (-90 will put it at the top of circle)
// this can be changed with setAngleOffset function at runtime
#define DEFAULT_ANGLE_OFFSET -90

#define PI 3.14159265359

#define MIN_POLIGON_SIDES	3
#define MAX_POLIGON_SIDES	60

// === Color names constants ===
#define EPD_BLACK 15
#define EPD_WHITE 0

// === Color invert constants ===
#define INVERT_ON		1
#define INVERT_OFF		0

// === Screen orientation constants ===
#define LANDSCAPE_0		1
#define LANDSCAPE_180	2

// === Special coordinates constants ===
#define CENTER	-9003
#define RIGHT	-9004
#define BOTTOM	-9004

#define LASTX	7000
#define LASTY	8000

// === Embedded fonts constants ===
#define DEFAULT_FONT	0
#define DEJAVU18_FONT	1
#define DEJAVU24_FONT	2
#define UBUNTU16_FONT	3
#define COMIC24_FONT	4
#define MINYA24_FONT	5
#define TOONEY32_FONT	6
#define SMALL_FONT		7
#define FONT_7SEG		8
#define USER_FONT		9  // font will be read from file



// ===== PUBLIC FUNCTIONS =========================================================================

/*
 * Draw pixel at given x,y coordinates
 * 
 * Params:
 *       x: horizontal position
 *       y: vertical position
 *   color: pixel color
*/
//------------------------------------------------------
void EPD_drawPixel(int16_t x, int16_t y, color_t color);

/*
 * Read pixel color value from display GRAM at given x,y coordinates
 * 
 * Params:
 *       x: horizontal position
 *       y: vertical position
 * 
 * Returns:
 *      pixel color at x,y
*/
//------------------------------------------
color_t EPD_readPixel(int16_t x, int16_t y);

/*
 * Draw vertical line at given x,y coordinates
 * 
 * Params:
 *       x: horizontal start position
 *       y: vertical start position
 *       h: line height in pixels
 *   color: line color
*/
//---------------------------------------------------------------------
void EPD_drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color);

/*
 * Draw horizontal line at given x,y coordinates
 * 
 * Params:
 *       x: horizontal start position
 *       y: vertical start position
 *       w: line width in pixels
 *   color: line color
*/
//---------------------------------------------------------------------
void EPD_drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color);

/*
 * Draw line on screen
 * 
 * Params:
 *       x0: horizontal start position
 *       y0: vertical start position
 *       x1: horizontal end position
 *       y1: vertical end position
 *   color: line color
*/
//-------------------------------------------------------------------------------
void EPD_drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_t color);


/*
 * Draw line on screen from (x,y) point at given angle
 * Line drawing angle starts at lower right quadrant of the screen and is offseted by
 * '_angleOffset' global variable (default: -90 degrees)
 *
 * Params:
 *       x: horizontal start position
 *       y: vertical start position
 *   start: start offset from (x,y)
 *     len: length of the line
 *   angle: line angle in degrees
 *   color: line color
*/
//-----------------------------------------------------------------------------------------------------------
void EPD_drawLineByAngle(uint16_t x, uint16_t y, uint16_t start, uint16_t len, uint16_t angle, color_t color);

/*
 * Fill given rectangular screen region with color
 * 
 * Params:
 *       x: horizontal rect start position
 *       y: vertical rect start position
 *       w: rectangle width
 *       h: rectangle height
 *   color: fill color
*/
//---------------------------------------------------------------------------
void EPD_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t color);

/*
 * Draw rectangle on screen
 * 
 * Params:
 *       x: horizontal rect start position
 *       y: vertical rect start position
 *       w: rectangle width
 *       h: rectangle height
 *   color: rect line color
*/
//------------------------------------------------------------------------------
void EPD_drawRect(uint16_t x1,uint16_t y1,uint16_t w,uint16_t h, color_t color);

/*
 * Draw rectangle with rounded corners on screen
 * 
 * Params:
 *       x: horizontal rect start position
 *       y: vertical rect start position
 *       w: rectangle width
 *       h: rectangle height
 *       r: corner radius
 *   color: rectangle color
*/
//----------------------------------------------------------------------------------------------
void EPD_drawRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, color_t color);

/*
 * Fill given rectangular screen region with rounded corners with color
 * 
 * Params:
 *       x: horizontal rect start position
 *       y: vertical rect start position
 *       w: rectangle width
 *       h: rectangle height
 *       r: corner radius
 *   color: fill color
*/
//----------------------------------------------------------------------------------------------
void EPD_fillRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t r, color_t color);

/*
 * Fill the whole screen with color
 * 
 * Params:
 *   color: fill color
*/
//--------------------------------
void EPD_fillScreen(color_t color);

/*
 * Fill the current clip window with color
 *
 * Params:
 *   color: fill color
*/
//---------------------------------
void EPD_fillWindow(color_t color);

/*
 * Draw triangle on screen
 * 
 * Params:
 *       x0: first triangle point x position
 *       y0: first triangle point y position
 *       x0: second triangle point x position
 *       y0: second triangle point y position
 *       x0: third triangle point x position
 *       y0: third triangle point y position
 *   color: triangle color
*/
//-----------------------------------------------------------------------------------------------------------------
void EPD_drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color);

/*
 * Fill triangular screen region with color
 * 
 * Params:
 *       x0: first triangle point x position
 *       y0: first triangle point y position
 *       x0: second triangle point x position
 *       y0: second triangle point y position
 *       x0: third triangle point x position
 *       y0: third triangle point y position
 *   color: fill color
*/
//-----------------------------------------------------------------------------------------------------------------
void EPD_fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, color_t color);

/*
 * Draw circle on screen
 * 
 * Params:
 *       x: circle center x position
 *       y: circle center x position
 *       r: circle radius
 *   color: circle color
*/
//-------------------------------------------------------------------
void EPD_drawCircle(int16_t x, int16_t y, int radius, color_t color);

/*
 * Fill circle on screen with color
 * 
 * Params:
 *       x: circle center x position
 *       y: circle center x position
 *       r: circle radius
 *   color: circle fill color
*/
//-------------------------------------------------------------------
void EPD_fillCircle(int16_t x, int16_t y, int radius, color_t color);

/*
 * Draw ellipse on screen
 * 
 * Params:
 *       x0: ellipse center x position
 *       y0: ellipse center x position
 *       rx: ellipse horizontal radius
 *       ry: ellipse vertical radius
 *   option: drawing options, multiple options can be combined
                1 (TFT_ELLIPSE_UPPER_RIGHT) draw upper right corner
                2 (TFT_ELLIPSE_UPPER_LEFT)  draw upper left corner
                4 (TFT_ELLIPSE_LOWER_LEFT)  draw lower left corner
                8 (TFT_ELLIPSE_LOWER_RIGHT) draw lower right corner
             to draw the whole ellipse use option value 15 (1 | 2 | 4 | 8)
 * 
 *   color: circle color
*/
//------------------------------------------------------------------------------------------------------
void EPD_drawEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, color_t color, uint8_t option);

/*
 * Fill elliptical region on screen
 * 
 * Params:
 *       x0: ellipse center x position
 *       y0: ellipse center x position
 *       rx: ellipse horizontal radius
 *       ry: ellipse vertical radius
 *   option: drawing options, multiple options can be combined
                1 (TFT_ELLIPSE_UPPER_RIGHT) fill upper right corner
                2 (TFT_ELLIPSE_UPPER_LEFT)  fill upper left corner
                4 (TFT_ELLIPSE_LOWER_LEFT)  fill lower left corner
                8 (TFT_ELLIPSE_LOWER_RIGHT) fill lower right corner
             to fill the whole ellipse use option value 15 (1 | 2 | 4 | 8)
 * 
 *   color: fill color
*/
//------------------------------------------------------------------------------------------------------
void EPD_fillEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry, color_t color, uint8_t option);


/*
 * Draw circle arc on screen
 * Arc drawing angle starts at lower right quadrant of the screen and is offseted by
 * '_angleOffset' global variable (default: -90 degrees)
 *
 * Params:
 *        cx: arc center X position
 *        cy: arc center Y position
 *        th: thickness of the drawn arc
 *        ry: arc vertical radius
 *     start: arc start angle in degrees
 *       end: arc end angle in degrees
 *     color: arc outline color
 * fillcolor: arc fill color
*/
//----------------------------------------------------------------------------------------------------------------------------
void EPD_drawArc(uint16_t cx, uint16_t cy, uint16_t r, uint16_t th, float start, float end, color_t color, color_t fillcolor);


/*
 * Draw polygon on screen
 *
 * Params:
 *        cx: polygon center X position
 *        cy: arc center Y position
 *     sides: number of polygon sides; MAX_POLIGON_SIDES ~ MAX_POLIGON_SIDES (3 ~ 60)
 *  diameter: diameter of the circle inside which the polygon is drawn
 *     color: polygon outline color
 *      fill: polygon fill color; if same as color, polygon is not filled
 *       deg: polygon rotation angle; 0 ~ 360
 *        th: thickness of the polygon outline
*/
//--------------------------------------------------------------------------------------------------------------
void EPD_drawPolygon(int cx, int cy, int sides, int diameter, color_t color, color_t fill, int deg, uint8_t th);


//--------------------------------------------------------------------------------------
//void EPD_drawStar(int cx, int cy, int diameter, color_t color, bool fill, float factor);


/*
 * Set the font used for writing the text to display.
 *
 * ------------------------------------------------------------------------------------
 * For 7 segment font only characters 0,1,2,3,4,5,6,7,8,9, . , - , : , / are available.
 *   Character ‘/‘ draws the degree sign.
 * ------------------------------------------------------------------------------------
 *
 * Params:
 *			 font: font number; use defined font names
 *		font_file: pointer to font file name; NULL for embeded fonts
 */
//----------------------------------------------------
void EPD_setFont(uint8_t font, const char *font_file);

/*
 * Returns current font height & width in pixels.
 *
 * Params:
 *		 width: pointer to returned font width
 *		height: pointer to returned font height
 */
//-------------------------------------------
int EPD_getfontsize(int *width, int* height);


/*
 * Returns current font height in pixels.
 *
 */
//----------------------
int EPD_getfontheight();

/*
 * Write text to display.
 *
 * Rotation of the displayed text depends on 'font_rotate' variable (0~360)
 * if 'font_transparent' variable is set to 1, no background pixels will be printed
 *
 * If the text does not fit the screen width it will be clipped (if text_wrap=0),
 * or continued on next line (if text_wrap=1)
 *
 * Two special characters are allowed in strings:
 * 		‘\r’ CR (0x0D), clears the display to EOL
 * 		‘\n’ LF (ox0A), continues to the new line, x=0
 *
 * Params:
 *	   st:	pointer to null terminated string to be printed
 *		x:	horizontal position of the upper left point in pixels
 *				Special values can be entered:
 *					CENTER, centers the text
 *					RIGHT, right justifies the text
 *					LASTX, continues from last X position; offset can be used: LASTX+n
 *		y: vertical position of the upper left point in pixels
 *				Special values can be entered:
 *					CENTER, centers the text
 *					BOTTOM, bottom justifies the text
 *					LASTY, continues from last Y position; offset can be used: LASTY+n
 *
 */
//-------------------------------------
void EPD_print(char *st, int x, int y);

/*
 * Set atributes for 7 segment vector font
 * == 7 segment font must be the current font to this function to have effect ==
 *
 * Params:
 *	   	   l:	6~40; distance between bars in pixels
 *	   	   w:	1~12, max l/2;  bar width in pixels
 *   outline:	draw font outline if set to 1
 *	   color:	font outline color, only used if outline=1
 *
 */
//-------------------------------------------------------------------------
void set_7seg_font_atrib(uint8_t l, uint8_t w, int outline, color_t color);

/*
 * Sets the clipping area coordinates.
 * All writing to screen is clipped to that area.
 * Starting x & y in all functions will be adjusted to the clipping area.
 *
 * Params:
 *		x1,y1:	upper left point of the clipping area
 *		x2,y2:	bottom right point of the clipping area
 *
 */
//----------------------------------------------------------------------
void EPD_setclipwin(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);

/*
 * Resets the clipping area to full screen (0,0),(_wodth,_height)
 *
 */
//----------------------
void EPD_resetclipwin();

/*
 * Save current clipping area to temporary variable
 *
 */
//---------------------
void EPD_saveClipWin();

/*
 * Restore current clipping area from temporary variable
 *
 */
//------------------------
void EPD_restoreClipWin();

/*
 * returns the string width in pixels.
 * Useful for positions strings on the screen.
 */
//--------------------------------
int EPD_getStringWidth(char* str);


/*
 * Fills the rectangle occupied by string with current background color
 */
void EPD_clearStringRect(int x, int y, char *str);


/*
 * Compile font c source file to .fnt file
 * which can be used in EPD_setFont() function to select external font
 * Created file have the same name as source file and extension .fnt
 *
 * Params:
 *		fontfile: pointer to c source font file name; must have .c extension
 *			 dbg: if set to 1, prints debug information
 *
 * Returns:
 * 		0 on success
 * 		err no on error
 *
 */
//------------------------------------------------
int compile_font_file(char *fontfile, uint8_t dbg);

/*
 * Get all font's characters to buffer
 */
void getFontCharacters(uint8_t *buf);

/*
 * Decodes and displays JPG image. RGB colors are converted to 4-bit Gray scale
 * Limits:
 * 		Baseline only. Progressive and Lossless JPEG format are not supported.
 *		Image size: Up to 65520 x 65520 pixels
 *		Color space: YCbCr three components only. Gray scale image is not supported.
 *		Sampling factor: 4:4:4, 4:2:2 or 4:2:0.
 *
 * Params:
 *       x: image left position; constants CENTER & RIGHT can be used; negative value is accepted
 *       y: image top position;  constants CENTER & BOTTOM can be used; negative value is accepted
 *   scale: image scale factor: 0~3; if scale>0, image is scaled by factor 1/(2^scale) (1/2, 1/4 or 1/8)
 *   fname: pointer to the name of the file from which the image will be read
 *   		if set to NULL, image will be read from memory buffer pointed to by 'buf'
 *     buf: pointer to the memory buffer from which the image will be read; used if fname=NULL
 *    size: size of the memory buffer from which the image will be read; used if fname=NULL & buf!=NULL
 *
 */
int EPD_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf, int size);

#endif


================================================
FILE: components/epaper/EPDspi.c
================================================
/*
 *  Author: LoBo (loboris@gmail.com, loboris.github)
 *
 *  Module supporting SPI ePaper displays
 *
 * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS
 * USING DIRECT or DMA SPI TRANSFER MODEs
 *
*/


#include "spi_master_lobo.h"
#include <errno.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_alloc_caps.h"
#include "soc/spi_reg.h"
#include "EPDspi.h"

#define EPD_DEBUG 1

#define EPD2X9 1

	#define xDot 128
	#define yDot 296
	#define DELAYTIME 1500

static uint8_t GDOControl[] = {0x01, (yDot-1)%256, (yDot-1)/256, 0x00};
static uint8_t softstart[4] = {0x0c, 0xd7, 0xd6, 0x9d};
static uint8_t VCOMVol[2] = {0x2c, 0xa8};			// VCOM 7c
static uint8_t DummyLine[2] = {0x3a, 0x1a};			// 4 dummy line per gate
static uint8_t Gatetime[2] = {0x3b, 0x08};			// 2us per line
static uint8_t RamDataEntryMode[2] = {0x11, 0x01};	// Ram data entry mode
static uint8_t Border[2] = {0x3c, 0x61};			// Border control ( 0x61: white border; 0x51: black border

/*
There are totally 20 phases for programmable Source waveform of different phase length.
The phase period defined as TP [n] * T FRAME , where TP [n] range from 0 to 15.
TP [n] = 0 indicates phase skipped
Source Voltage Level: VS [n-XY] is constant in each phase
VS [n-XY] indicates the voltage in phase n for transition from GS X to GS Y
 00 – VSS
 01 – VSH
 10 – VSL
 11 – NA
VS [n-XY] and TP[n] are stored in waveform lookup table register [LUT].

VS coding: VS[0-11] VS[0-10] VS[0-01] VS[0-00]

*/
//                                   ---                                             VS                                             ----  ----           TP                            ----
//uint8_t LUTDefault_full[31] = {0x32, 0x02,0x02,0x01,0x11,0x12,0x12,0x22,0x22,0x66,0x69,0x69,0x59,0x58,0x99,0x99,0x88,0x00,0x00,0x00,0x00, 0xF8,0xB4,0x13,0x51,0x35,0x51,0x51,0x19,0x01,0x00};
uint8_t LUTDefault_full[31] = {0x32, 0x11,0x11,0x10,0x02,0x02,0x22,0x22,0x22,0x22,0x22,0x51,0x51,0x55,0x88,0x08,0x08,0x88,0x88,0x00,0x00, 0x34,0x23,0x12,0x21,0x24,0x28,0x22,0x21,0xA1,0x01};
uint8_t LUTDefault_part[31] = {0x32, 0x10,0x18,0x18,0x08,0x18,0x18,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x13,0x14,0x44,0x12,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t LUT_gs[31]			= {0x32, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t LUTFastest[31]		= {0x32, 0x99,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

uint8_t lvl_buf[16] = {32,70,110,150,185,210,220,225,230,235,240,243,248,251,253,255};
uint8_t lvl_buf_jpg[16] = {4,8,12,16,22,30,40,60,80,110,140,180,220,240,250,255};

uint8_t *LUT_part = LUTDefault_part;
spi_lobo_device_handle_t disp_spi = NULL;
uint8_t *gs_disp_buffer = NULL;
uint8_t *disp_buffer = NULL;
uint8_t *drawBuff = NULL;
uint8_t *gs_drawBuff = NULL;
int _width = EPD_DISPLAY_WIDTH;
int _height = EPD_DISPLAY_HEIGHT;
uint8_t _gs = 0;

uint16_t gs_used_shades = 0;

//-----------------------------------------------------------
static void IRAM_ATTR _dma_send(uint8_t *data, uint32_t size)
{
    //Fill DMA descriptors
    spi_lobo_dmaworkaround_transfer_active(disp_spi->host->dma_chan); //mark channel as active
    spi_lobo_setup_dma_desc_links(disp_spi->host->dmadesc_tx, size, data, false);
    disp_spi->host->hw->user.usr_mosi_highpart=0;
    disp_spi->host->hw->dma_out_link.addr=(int)(&disp_spi->host->dmadesc_tx[0]) & 0xFFFFF;
    disp_spi->host->hw->dma_out_link.start=1;
    disp_spi->host->hw->user.usr_mosi_highpart=0;

	disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = (size * 8) - 1;

	// Start transfer
	disp_spi->host->hw->cmd.usr = 1;
	// Wait for SPI bus ready
	while (disp_spi->host->hw->cmd.usr);

	//Tell common code DMA workaround that our DMA channel is idle. If needed, the code will do a DMA reset.
    if (disp_spi->host->dma_chan) spi_lobo_dmaworkaround_idle(disp_spi->host->dma_chan);

    // Reset DMA
	disp_spi->host->hw->dma_conf.val |= SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST;
	disp_spi->host->hw->dma_out_link.start=0;
	disp_spi->host->hw->dma_in_link.start=0;
	disp_spi->host->hw->dma_conf.val &= ~(SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST);
	disp_spi->host->hw->dma_conf.out_data_burst_en=1;
}

//--------------------------------------------------------------------------
static void IRAM_ATTR _direct_send(uint8_t *data, uint32_t len, uint8_t rep)
{
	uint32_t cidx = 0;	// buffer index
	uint32_t wd = 0;
	int idx = 0;
	int bits = 0;
	int wbits = 0;

    taskDISABLE_INTERRUPTS();

	while (len) {

		wd |= (uint32_t)data[idx] << wbits;
		wbits += 8;
		if (wbits == 32) {
			bits += wbits;
			wbits = 0;
			disp_spi->host->hw->data_buf[idx++] = wd;
			wd = 0;
		}
    	len--;					// Decrement data counter
        if (rep == 0) cidx++;	// if not repeating data, increment buffer index
    }
	if (bits) {
		while (disp_spi->host->hw->cmd.usr);						// Wait for SPI bus ready
		// Load send buffer
		disp_spi->host->hw->user.usr_mosi_highpart = 0;
		disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = bits-1;
		disp_spi->host->hw->user.usr_mosi = 1;
		disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0;
		disp_spi->host->hw->user.usr_miso = 0;
        disp_spi->host->hw->cmd.usr = 1;							// Start transfer
	}
	// Wait for SPI bus ready
	while (disp_spi->host->hw->cmd.usr);
    taskENABLE_INTERRUPTS();
}

// ================================================================
// === Main function to send data to display ======================
// If  rep==true:  repeat sending data to display 'len' times
// If rep==false:  send 'len' data bytes from buffer to display
// ** Device must already be selected and address window set **
// ================================================================
//---------------------------------------------------------------------------
static void IRAM_ATTR SPI_send_data(uint8_t *data, uint32_t len, uint8_t rep)
{
	if (len == 0) return;

	if ((len*8) <= 512) _direct_send(data, len, rep);
	else if (rep == 0)  _dma_send(data, len);
	else {
		// ==== Repeat data, more than 512 bits total ====
		uint8_t *transbuf = pvPortMallocCaps(len, MALLOC_CAP_DMA);
		if (transbuf == NULL) return;

		memset(transbuf, data[0], len);
		_dma_send(transbuf, len);
		free(transbuf);
	}
}

// Send one byte to display
//-------------------------------------
void IRAM_ATTR SPI_Write(uint8_t value)
{
	disp_spi->host->hw->data_buf[0] = (uint32_t)value;
	// Load send buffer
	disp_spi->host->hw->user.usr_mosi_highpart = 0;
	disp_spi->host->hw->mosi_dlen.usr_mosi_dbitlen = 7;
	disp_spi->host->hw->user.usr_mosi = 1;
	disp_spi->host->hw->miso_dlen.usr_miso_dbitlen = 0;
	disp_spi->host->hw->user.usr_miso = 0;
	// Start transfer
	disp_spi->host->hw->cmd.usr = 1;
	// Wait for SPI bus ready
	while (disp_spi->host->hw->cmd.usr);
}

// Check display busy line and wait while busy
//-----------------------
static uint8_t ReadBusy()
{
	for (int i=0; i<400; i++){
		if (isEPD_BUSY == EPD_BUSY_LEVEL) return 1;
		vTaskDelay(10 / portTICK_RATE_MS);
	}
	return 0;
}

//-----------------------
static uint8_t WaitBusy()
{
	if (isEPD_BUSY != EPD_BUSY_LEVEL) return 1;
	vTaskDelay(10 / portTICK_RATE_MS);
	if (isEPD_BUSY != EPD_BUSY_LEVEL) return 1;
	return 0;
}

// Write one command without parameters
//---------------------------------------
static void EPD_WriteCMD(uint8_t command)
{
	spi_lobo_device_select(disp_spi, 0);
	EPD_DC_0;		// command write
	SPI_Write(command);
}

// Write command with one paramet
//---------------------------------------
static void EPD_WriteCMD_p1(uint8_t command,uint8_t para)
{
	spi_lobo_device_select(disp_spi, 0);
	//ReadBusy();
	EPD_DC_0;		// command write
	SPI_Write(command);
	EPD_DC_1;		// data write
	SPI_Write(para);
	spi_lobo_device_deselect(disp_spi);
}

//----------------
void EPD_PowerOn()
{
	EPD_WriteCMD_p1(0x22,0xc0);
	EPD_WriteCMD(0x20);
	//EPD_WriteCMD(0xff);
	spi_lobo_device_deselect(disp_spi);
#if EPD_DEBUG
	if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
	if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
#else
	WaitBusy();
	ReadBusy();
#endif
}

//-----------------
void EPD_PowerOff()
{
	EPD_WriteCMD_p1(0x22,0x03);
	EPD_WriteCMD(0x20);
	//EPD_WriteCMD(0xff);
	spi_lobo_device_deselect(disp_spi);
#if EPD_DEBUG
	if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
	if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
#else
	WaitBusy();
	ReadBusy();
#endif
#if POWER_Pin
	gpio_set_level(DC_Pin, 0);
	gpio_set_level(MOSI_Pin, 0);
	gpio_set_level(SCK_Pin, 0);
	gpio_set_level(RST_Pin, 0);
	gpio_set_level(CS_Pin, 0);
	gpio_set_level(POWER_Pin, 0);
#endif
}

// Send command with multiple parameters
//----------------------------------------------------
static void EPD_Write(uint8_t *value, uint8_t datalen)
{
	uint8_t i = 0;
	uint8_t *ptemp;

	ptemp = value;
	spi_lobo_device_select(disp_spi, 0);
	//ReadBusy();
	EPD_DC_0;			// When DC is 0, write command
	SPI_Write(*ptemp);	//The first byte is written with the command value
	ptemp++;
	EPD_DC_1;			// When DC is 1, write data
	for(i= 0;i<datalen-1;i++){	// sub the data
		SPI_Write(*ptemp);
		ptemp++;
	}
	spi_lobo_device_deselect(disp_spi);
}

// Send data buffer to display
//----------------------------------------------------------------------------
static void EPD_WriteDispRam(uint8_t XSize, uint16_t YSize,	uint8_t *Dispbuff)
{
	if (XSize%8 != 0) XSize = XSize+(8-XSize%8);
	XSize = XSize/8;

	spi_lobo_device_select(disp_spi, 0);
	//ReadBusy();
	EPD_DC_0;		//command write
	SPI_Write(0x24);
	EPD_DC_1;		//data write
	SPI_send_data(Dispbuff, XSize*YSize, 0);
	spi_lobo_device_deselect(disp_spi);
}

// Fill the display with value
//-------------------------------------------------------------------------------
static void EPD_WriteDispRamMono(uint8_t XSize, uint16_t YSize,	uint8_t dispdata)
{
	if (XSize%8 != 0) XSize = XSize+(8-XSize%8);
	XSize = XSize/8;

	spi_lobo_device_select(disp_spi, 0);
	//ReadBusy();
	EPD_DC_0;		// command write
	SPI_Write(0x24);
	EPD_DC_1;		// data write
	SPI_send_data(&dispdata, XSize*YSize, 1);
	spi_lobo_device_deselect(disp_spi);
}

/*
  === Set RAM X - Address Start / End Position (44h) ===
  Specify the start/end positions of the window address in the X direction by 8 times address unit.
  Data is written to the RAM within the area determined by the addresses specified by XSA [4:0] and XEA [4:0].
  These addresses must be set before the RAM write. It allows on XEA [4:0] ≤ XSA [4:0].
  The settings follow the condition on 00h ≤ XSA [4:0], XEA [4:0] ≤ 1Dh.
  The windows is followed by the control setting of Data Entry Setting (R11h)

  === Set RAM Y - Address Start / End Position (45h) ===
  Specify the start/end positions of the window address in the Y direction by an address unit.
  Data is written to the RAM within the area determined by the addresses specified by YSA [8:0] and YEA [8:0].
  These addresses must be set before the RAM write.
  It allows YEA [8:0] ≤ YSA [8:0].
  The settings follow the condition on 00h ≤ YSA [8:0], YEA [8:0] ≤ 13Fh.
  The windows is followed by the control setting of Data Entry Setting (R11h)
 */
//--------------------------------------------------------------------------------------
static void EPD_SetRamArea(uint8_t Xstart, uint8_t Xend, uint16_t Ystart, uint16_t Yend)
{
    uint8_t RamAreaX[3];	// X start and end
	uint8_t RamAreaY[5]; 	// Y start and end
	RamAreaX[0] = 0x44;	// command
	RamAreaX[1] = Xstart;
	RamAreaX[2] = Xend;
	RamAreaY[0] = 0x45;	// command
	RamAreaY[1] = Ystart & 0xFF;
	RamAreaY[2] = Ystart >> 8;
	RamAreaY[3] = Yend & 0xFF;
    RamAreaY[4] = Yend >> 8;
	EPD_Write(RamAreaX, sizeof(RamAreaX));
	EPD_Write(RamAreaY, sizeof(RamAreaY));
}

//Set RAM X and Y address counter
/*
  === Set RAM Address Counter (4Eh-4Fh) ===
  adrX[4:0]: Make initial settings for the RAM X address in the address counter (AC).
  adrY[8:0]: Make initial settings for the RAM Y address in the address counter (AC).
  After RAM data is written, the address counter is automatically updated according to the settings with AM, ID
   bits and setting for a new RAM address is not required in the address counter.
  Therefore, data is written consecutively without setting an address.
  The address counter is not automatically updated when data is read out from the RAM.
  RAM address setting cannot be made during the standby mode.
  The address setting should be made within the area designated with window addresses which is controlled
   by the Data Entry Setting (R11h) {AM, ID[1:0]} ; RAM Address XStart / XEnd Position (R44h) and RAM Address Ystart /Yend Position (R45h).
   Otherwise undesirable image will be displayed on the Panel.
*/
//----------------------------------------------------------
static void EPD_SetRamPointer(uint8_t addrX, uint16_t addrY)
{
    uint8_t RamPointerX[2];	// default (0,0)
	uint8_t RamPointerY[3];
	//Set RAM X address counter
	RamPointerX[0] = 0x4e;
	RamPointerX[1] = addrX;
	//Set RAM Y address counter
	RamPointerY[0] = 0x4f;
	RamPointerY[1] = addrY & 0xFF;
	RamPointerY[2] = addrY >> 8;

	EPD_Write(RamPointerX, sizeof(RamPointerX));
	EPD_Write(RamPointerY, sizeof(RamPointerY));
}


//Set RAM X and Y address Start / End position
//Set RAM X and Y address counter
//----------------------------------------------------------------------------------------------
static void part_display(uint8_t RAM_XST, uint8_t RAM_XEND ,uint16_t RAM_YST, uint16_t RAM_YEND)
{
	EPD_SetRamArea(RAM_XST, RAM_XEND, RAM_YST, RAM_YEND);
    EPD_SetRamPointer (RAM_XST, RAM_YST);
}

//Initialize the display
//--------------------
static void EPD_Init()
{
#if POWER_Pin
	gpio_set_level(POWER_Pin, 1);
	vTaskDelay(100 / portTICK_RATE_MS);
#else
	vTaskDelay(10 / portTICK_RATE_MS);
#endif
	// reset
	EPD_RST_0;
	vTaskDelay(10 / portTICK_RATE_MS);
#if EPD_DEBUG
	uint32_t t1 = clock();
#endif
	EPD_RST_1;
	for (int n=0; n<50; n++) {
		vTaskDelay(10 / portTICK_RATE_MS);
		if (isEPD_BUSY == EPD_BUSY_LEVEL) break;
	}

	SPI_Write(0x12); // software reset
	vTaskDelay(10 / portTICK_RATE_MS);
	ReadBusy();

	// set registers
	EPD_Write(GDOControl, sizeof(GDOControl));	// Panel configuration, Gate selection
	EPD_Write(softstart, sizeof(softstart));	// X decrease, Y decrease
	EPD_Write(VCOMVol, sizeof(VCOMVol));		// VCOM setting
	EPD_Write(DummyLine, sizeof(DummyLine));	// dummy line per gate
	EPD_Write(Gatetime, sizeof(Gatetime));		// Gate time setting
	EPD_Write(Border, sizeof(Border));
	EPD_Write(RamDataEntryMode, sizeof(RamDataEntryMode));	// X increase, Y decrease

	EPD_SetRamArea(0x00, (xDot-1)/8, yDot-1, 0);
	EPD_SetRamPointer(0x00, yDot-1);
#if EPD_DEBUG
	t1 = clock() - t1;
	printf("[EPD] Init: %u ms\r\n", t1);
#endif
}

//------------------------------
static void EPD_UpdateFull(void)
{
	/*
	+ Enable Clock Signal,
	+ Then Enable CP
	- Then Load Temperature value
	- Then Load LUT
	- Then INITIAL DISPLAY
	+ Then PATTERN DISPLAY
	+ Then Disable CP
	+ Then Disable OSC
	*/
	EPD_WriteCMD_p1(0x22,0xC7);
	EPD_WriteCMD(0x20);
	//EPD_WriteCMD(0xff);
	spi_lobo_device_deselect(disp_spi);

#if EPD_DEBUG
	if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
	if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
#else
	WaitBusy();
	ReadBusy();
#endif
}

//-------------------------------
static void EPD_Update_Part(void)
{
	/*
	- Enable Clock Signal,
	- Then Enable CP
	- Then Load Temperature value
	- Then Load LUT
	- Then INITIAL DISPLAY
	+ Then PATTERN DISPLAY
	- Then Disable CP
	- Then Disable OSC
	*/
	EPD_WriteCMD_p1(0x22,0x04);
	EPD_WriteCMD(0x20);
	//EPD_WriteCMD(0xff);
	spi_lobo_device_deselect(disp_spi);

#if EPD_DEBUG
	if (!WaitBusy()) printf("[EPD] NOT BUSY\r\n");
	if (!ReadBusy()) printf("[EPD] NOT READY\r\n");
#else
	WaitBusy();
	ReadBusy();
#endif
}

/*******************************************************************************
Full screen initialization
********************************************************************************/
static void EPD_init_Full(void)
{
	EPD_Init();			// Reset and set register
	EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));

	EPD_PowerOn();
}

/*******************************************************************************
Part screen initialization
********************************************************************************/
static void EPD_init_Part(void)
{
	EPD_Init();			// display
	EPD_Write((uint8_t *)LUT_part, 31);
	EPD_PowerOn();
}
/********************************************************************************
parameter:
	Label  :
       		=1 Displays the contents of the DisBuffer
	   		=0 Displays the contents of the first byte in DisBuffer,
********************************************************************************/
static void EPD_Dis_Full(uint8_t *DisBuffer,uint8_t type)
{
    EPD_SetRamPointer(0x00, yDot-1);	// set ram pointer
	if (type == 0){
		// Fill screen with white
		EPD_WriteDispRamMono(xDot, yDot, 0xff);
	}
	else {
		// Fill screen from buffer
		EPD_WriteDispRam(xDot, yDot, (uint8_t *)DisBuffer);
	}
	EPD_UpdateFull();

}

/********************************************************************************
WARNING: X is smaller screen dimension (0~127) !
         Y is larger screen dimension (0~295) !
parameter:
		xStart :   X direction Start coordinate
		xEnd   :   X direction end coordinate
		yStart :   Y direction Start coordinate
		yEnd   :   Y direction end coordinate
		DisBuffer : Display content
		type  :
       		=1 Displays the contents of the DisBuffer
	   		=0 Displays the contents of the first byte in DisBuffer,
********************************************************************************/
static void EPD_Dis_Part(uint8_t xStart, uint8_t xEnd, uint16_t yStart, uint16_t yEnd, uint8_t *DisBuffer, uint8_t type)
{
	if (type == 0) {
		// Repeated color
		part_display(xStart/8, xEnd/8, yEnd, yStart);
		EPD_WriteDispRamMono(xEnd-xStart+1, yEnd-yStart+1, DisBuffer[0]);
 		EPD_Update_Part();
		part_display(xStart/8, xEnd/8, yEnd, yStart);
		EPD_WriteDispRamMono(xEnd-xStart+1, yEnd-yStart+1, DisBuffer[0]);
	}
	else {
		// From buffer
		part_display(xStart/8, xEnd/8, yEnd, yStart);
		EPD_WriteDispRam(xEnd-xStart+1, yEnd-yStart+1,DisBuffer);
		EPD_Update_Part();
		part_display(xStart/8, xEnd/8, yEnd, yStart);
		EPD_WriteDispRam(xEnd-xStart+1, yEnd-yStart+1,DisBuffer);
	}
}

//======================================================================================================================================

// Clear full screen
//=========================
void EPD_DisplayClearFull()
{
	uint8_t m;
	EPD_init_Full();

#if EPD_DEBUG
	uint32_t t1 = clock();
#endif
	m = 0x00;
	EPD_Dis_Full(&m, 0);  //all black
#if EPD_DEBUG
	t1 = clock() - t1;
	printf("[EPD] Clear black: %u ms\r\n", t1);
	t1 = clock();
#endif
	m = 0xff;
	EPD_Dis_Full(&m, 0);  //all white
#if EPD_DEBUG
	t1 = clock() - t1;
	printf("[EPD] Clear white: %u ms\r\n", t1);
#endif
}

// Partial clear screen
//=========================
void EPD_DisplayClearPart()
{
	uint8_t m = 0xFF;
	EPD_init_Part();
#if EPD_DEBUG
	uint32_t t1 = clock();
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all white
	m = 0x00;
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all black
	m = 0xFF;
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all white
	t1 = clock() - t1;
	printf("[EPD] Part Clear: %u ms\r\n", t1);
#else
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all white
	m = 0x00;
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all black
	m = 0xFF;
	EPD_Dis_Part(0, xDot-1, 0, yDot-1, &m, 0);	//all white
#endif
}

//==================================
void EPD_DisplaySetFull(uint8_t val)
{
	EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));
#if EPD_DEBUG
	uint32_t t1 = clock();
	EPD_Dis_Full(&val, 0);
	t1 = clock() - t1;
	printf("[EPD] Display Set Full: %u ms [%02x]\r\n", t1, val);
#else
	EPD_Dis_Full(&val, 0);
#endif
}

//======================================================================================
void EPD_DisplaySetPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t val)
{
	EPD_Write((uint8_t *)LUT_part, 31);
#if EPD_DEBUG
	uint32_t t1 = clock();
	EPD_Dis_Part(yStart,yEnd,xStart,xEnd, &val,0);
	t1 = clock() - t1;
	printf("[EPD] Display Set Part: %u ms [%02x]\r\n", t1, val);
#else
	EPD_Dis_Part(yStart,yEnd,xStart,xEnd, &val,0);
#endif
}

//======================================
void EPD_DisplayFull(uint8_t *DisBuffer)
{
	EPD_Write((uint8_t *)LUTDefault_full,sizeof(LUTDefault_full));
#if EPD_DEBUG
	uint32_t t1 = clock();
	EPD_Dis_Full((uint8_t *)DisBuffer,1);
	t1 = clock() - t1;
	printf("[EPD] Display Full: %u ms\r\n", t1);
#else
	EPD_Dis_Full((uint8_t *)DisBuffer,1);
#endif
}

//==========================================================================================
void EPD_DisplayPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t *DisBuffer)
{
	EPD_Write((uint8_t *)LUT_part, 31);
#if EPD_DEBUG
	uint32_t t1 = clock();
	EPD_Dis_Part(yStart,yEnd,xStart,xEnd,(uint8_t *)DisBuffer,1);
	t1 = clock() - t1;
	printf("[EPD] Display Part: %u ms [%02x:%02x]\r\n", t1, LUT_gs[1], LUT_gs[21]);
#else
	EPD_Dis_Part(yStart,yEnd,xStart,xEnd,(uint8_t *)DisBuffer,1);
#endif
}

//============
void EPD_Cls()
{
	EPD_DisplaySetPart(0, EPD_DISPLAY_WIDTH-1, 0, EPD_DISPLAY_HEIGHT-1, 0xFF);
	memset(disp_buffer, 0xFF, _width * (_height/8));
	memset(gs_disp_buffer, 0, _width * _height);
	gs_used_shades = 0;
}

//-------------------------------------------------------------------------------
void EPD_gsUpdate(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t gs)
{
	uint8_t val, buf_val, new_val;
	int count=0, changed=0;
	int x;
	uint8_t y;
	for (x=xStart; x<=xEnd; x++) {
		for (y=yStart; y<=yEnd; y++) {
			val = gs_drawBuff[(y * (xEnd-xStart+1)) + x];
			if (val > 15) val >>= 4;
			if (val == gs) {
				buf_val = drawBuff[(x * ((yEnd-yStart+1)>>3)) + (y>>3)];
				new_val = buf_val;
				if (gs > 0) new_val &= (0x80 >> (y % 8)) ^ 0xFF;
				else new_val |= (0x80 >> (y % 8));
				if (new_val != buf_val) {
					drawBuff[(x * (_height>>3)) + (y>>3)] = new_val;
					changed++;
				}
				count++;
			}
		}
	}

	if (changed) {
		#if EPD_DEBUG
		printf("[EPD] GS Update %02x, count=%d changed=%d\r\n", gs, count, changed);
		#endif
		uint8_t *_lutPart = LUT_part;
		memset(LUT_gs+1, 0, 30);
		if (gs > 0) {
			if (gs > 0) {
				LUT_gs[1] = 0x18;
				LUT_gs[21] = gs;
			}
		}
		else {
			LUT_gs[1] = 0x28;
			LUT_gs[2] = 0x00;
			LUT_gs[21] = 15;
		}
		LUT_part = LUT_gs;
		EPD_DisplayPart(xStart, xEnd, yStart, yEnd, drawBuff);

		LUT_part = _lutPart;
	}
}

//-----------------------------------------------------------------------
void EPD_Update(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd)
{
	if (_gs == 0) EPD_DisplayPart(xStart, xEnd, yStart, yEnd, drawBuff);
	else {
		for (int n=0; n<16; n++) {
			if (gs_used_shades & (1<<n)) EPD_gsUpdate(xStart, xEnd, yStart, yEnd, n);
		}
	}
}

//-------------------
void EPD_UpdateScreen()
{
	EPD_Update(0, EPD_DISPLAY_WIDTH-1, 0, EPD_DISPLAY_HEIGHT-1);
}

//------------------------
void EPD_wait(uint32_t ms)
{
	if (ms < 100) ms = 100;
	uint32_t n = 0;
	while (n < ms) {
		vTaskDelay(100 / portTICK_RATE_MS);
		n += 100;
	}
}




================================================
FILE: components/epaper/EPDspi.h
================================================
/*
 *  Author: LoBo (loboris@gmail.com, loboris.github)
 *
 *  Module supporting SPI ePaper displays
 *
 * HIGH SPEED LOW LEVEL DISPLAY FUNCTIONS
 * USING DIRECT or DMA SPI TRANSFER MODEs
 *
*/


#ifndef _EPDSPI_H_
#define _EPDSPI_H_

#include <stdint.h>
#include "spi_master_lobo.h"

#define EPD_DISPLAY_WIDTH	296
#define EPD_DISPLAY_HEIGHT	128

#define SCK_Pin		18
#define MOSI_Pin	23
//#define MISO_Pin	19
#define DC_Pin		26
#define BUSY_Pin	32
#define RST_Pin		27
#define CS_Pin		5
// ePaper display can be powered from GPIO
// if powered directly from Vcc, set this to 0
#define POWER_Pin	22

#define DC_VAL (1 << DC_Pin)

#define EPD_CS_0	gpio_set_level(CS_Pin, 0)
#define EPD_CS_1	gpio_set_level(CS_Pin, 1)
#define isEPD_CS	gpio_get_level(CS_Pin)

#define EPD_RST_0	gpio_set_level(RST_Pin, 0)
#define EPD_RST_1	gpio_set_level(RST_Pin, 1)
#define isEPD_RST	gpio_get_level(RST_Pin)

#define EPD_DC_0	gpio_set_level(DC_Pin, 0)
#define EPD_DC_1	gpio_set_level(DC_Pin, 1)

#define isEPD_BUSY  gpio_get_level(BUSY_Pin)

#define EPD_BUSY_LEVEL 0

// ==================================================
// Define which spi bus to use VSPI_HOST or HSPI_HOST
#define SPI_BUS VSPI_HOST
// ==================================================

spi_lobo_device_handle_t disp_spi;
uint8_t *gs_disp_buffer;
uint8_t *disp_buffer;
uint8_t *gs_drawBuff;
uint8_t *drawBuff;
int _width;
int _height;
uint16_t gs_used_shades;
uint8_t _gs;
uint8_t *LUT_part;
uint8_t LUTDefault_fastest[31];
uint8_t LUTDefault_part[31];
uint8_t LUT_gs[31];
uint8_t LUTDefault_full[31];
uint8_t lvl_buf[16];
uint8_t lvl_buf_jpg[16];

void EPD_wait(uint32_t ms);
void EPD_DisplaySetFull(uint8_t val);
void EPD_DisplaySetPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t val);
void EPD_DisplayClearFull();
void EPD_DisplayClearPart();
void EPD_DisplayFull(uint8_t *DisBuffer);
void EPD_DisplayPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t *DisBuffer);
void EPD_gsUpdate(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, uint8_t gs);
void EPD_Update(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd);
void EPD_UpdateScreen();
void EPD_Cls();
void EPD_PowerOn();
void EPD_PowerOff();


#endif


================================================
FILE: components/epaper/SmallFont.c
================================================
// SmallFont.c
// Font type    : Full (95 characters)
// Font size    : 8x12 pixels
// Memory usage : 1144 bytes

#if defined(__AVR__)
	#include <avr/pgmspace.h>
	#define fontdatatype const uint8_t
#elif defined(__PIC32MX__)
	#define PROGMEM
	#define fontdatatype const unsigned char
#elif defined(__arm__)
	#define PROGMEM
	#define fontdatatype const unsigned char
#endif

const unsigned char tft_SmallFont[1144] =
{
0x08,0x0C,0x20,0x5F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // <space>
0x00,0x00,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00,  // !
0x00,0x28,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // "
0x00,0x00,0x28,0x28,0xFC,0x28,0x50,0xFC,0x50,0x50,0x00,0x00,  // #
0x00,0x20,0x78,0xA8,0xA0,0x60,0x30,0x28,0xA8,0xF0,0x20,0x00,  // $
0x00,0x00,0x48,0xA8,0xB0,0x50,0x28,0x34,0x54,0x48,0x00,0x00,  // %
0x00,0x00,0x20,0x50,0x50,0x78,0xA8,0xA8,0x90,0x6C,0x00,0x00,  // &
0x00,0x40,0x40,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // '
0x00,0x04,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x04,0x00,  // (
0x00,0x40,0x20,0x10,0x10,0x10,0x10,0x10,0x10,0x20,0x40,0x00,  // )
0x00,0x00,0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00,0x00,0x00,  // *
0x00,0x00,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,0x00,0x00,0x00,  // +
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x40,0x80,  // ,
0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,  // -
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,  // .
0x00,0x08,0x10,0x10,0x10,0x20,0x20,0x40,0x40,0x40,0x80,0x00,  // /

0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00,  // 0
0x00,0x00,0x20,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,  // 1
0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x40,0x80,0xF8,0x00,0x00,  // 2
0x00,0x00,0x70,0x88,0x08,0x30,0x08,0x08,0x88,0x70,0x00,0x00,  // 3
0x00,0x00,0x10,0x30,0x50,0x50,0x90,0x78,0x10,0x18,0x00,0x00,  // 4
0x00,0x00,0xF8,0x80,0x80,0xF0,0x08,0x08,0x88,0x70,0x00,0x00,  // 5
0x00,0x00,0x70,0x90,0x80,0xF0,0x88,0x88,0x88,0x70,0x00,0x00,  // 6
0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x20,0x20,0x20,0x00,0x00,  // 7
0x00,0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x88,0x70,0x00,0x00,  // 8
0x00,0x00,0x70,0x88,0x88,0x88,0x78,0x08,0x48,0x70,0x00,0x00,  // 9
0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x20,0x00,0x00,  // :
0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x20,0x00,  // ;
0x00,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x00,0x00,  // <
0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,  // =
0x00,0x40,0x20,0x10,0x08,0x04,0x08,0x10,0x20,0x40,0x00,0x00,  // >
0x00,0x00,0x70,0x88,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00,  // ?

0x00,0x00,0x70,0x88,0x98,0xA8,0xA8,0xB8,0x80,0x78,0x00,0x00,  // @
0x00,0x00,0x20,0x20,0x30,0x50,0x50,0x78,0x48,0xCC,0x00,0x00,  // A
0x00,0x00,0xF0,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,0x00,0x00,  // B
0x00,0x00,0x78,0x88,0x80,0x80,0x80,0x80,0x88,0x70,0x00,0x00,  // C
0x00,0x00,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,0x00,0x00,  // D
0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x48,0xF8,0x00,0x00,  // E
0x00,0x00,0xF8,0x48,0x50,0x70,0x50,0x40,0x40,0xE0,0x00,0x00,  // F
0x00,0x00,0x38,0x48,0x80,0x80,0x9C,0x88,0x48,0x30,0x00,0x00,  // G
0x00,0x00,0xCC,0x48,0x48,0x78,0x48,0x48,0x48,0xCC,0x00,0x00,  // H
0x00,0x00,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00,  // I
0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x90,0xE0,0x00,  // J
0x00,0x00,0xEC,0x48,0x50,0x60,0x50,0x50,0x48,0xEC,0x00,0x00,  // K
0x00,0x00,0xE0,0x40,0x40,0x40,0x40,0x40,0x44,0xFC,0x00,0x00,  // L
0x00,0x00,0xD8,0xD8,0xD8,0xD8,0xA8,0xA8,0xA8,0xA8,0x00,0x00,  // M
0x00,0x00,0xDC,0x48,0x68,0x68,0x58,0x58,0x48,0xE8,0x00,0x00,  // N
0x00,0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00,  // O

0x00,0x00,0xF0,0x48,0x48,0x70,0x40,0x40,0x40,0xE0,0x00,0x00,  // P
0x00,0x00,0x70,0x88,0x88,0x88,0x88,0xE8,0x98,0x70,0x18,0x00,  // Q
0x00,0x00,0xF0,0x48,0x48,0x70,0x50,0x48,0x48,0xEC,0x00,0x00,  // R
0x00,0x00,0x78,0x88,0x80,0x60,0x10,0x08,0x88,0xF0,0x00,0x00,  // S
0x00,0x00,0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00,  // T
0x00,0x00,0xCC,0x48,0x48,0x48,0x48,0x48,0x48,0x30,0x00,0x00,  // U
0x00,0x00,0xCC,0x48,0x48,0x50,0x50,0x30,0x20,0x20,0x00,0x00,  // V
0x00,0x00,0xA8,0xA8,0xA8,0x70,0x50,0x50,0x50,0x50,0x00,0x00,  // W
0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x50,0x50,0xD8,0x00,0x00,  // X
0x00,0x00,0xD8,0x50,0x50,0x20,0x20,0x20,0x20,0x70,0x00,0x00,  // Y
0x00,0x00,0xF8,0x90,0x10,0x20,0x20,0x40,0x48,0xF8,0x00,0x00,  // Z
0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x38,0x00,  // [
0x00,0x40,0x40,0x40,0x20,0x20,0x10,0x10,0x10,0x08,0x00,0x00,  // <backslash>
0x00,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,0x00,  // ]
0x00,0x20,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // ^
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,  // _

0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // `
0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x38,0x48,0x3C,0x00,0x00,  // a
0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0x70,0x00,0x00,  // b
0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x40,0x40,0x38,0x00,0x00,  // c
0x00,0x00,0x18,0x08,0x08,0x38,0x48,0x48,0x48,0x3C,0x00,0x00,  // d
0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x78,0x40,0x38,0x00,0x00,  // e
0x00,0x00,0x1C,0x20,0x20,0x78,0x20,0x20,0x20,0x78,0x00,0x00,  // f
0x00,0x00,0x00,0x00,0x00,0x3C,0x48,0x30,0x40,0x78,0x44,0x38,  // g
0x00,0x00,0xC0,0x40,0x40,0x70,0x48,0x48,0x48,0xEC,0x00,0x00,  // h
0x00,0x00,0x20,0x00,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x00,  // i
0x00,0x00,0x10,0x00,0x00,0x30,0x10,0x10,0x10,0x10,0x10,0xE0,  // j
0x00,0x00,0xC0,0x40,0x40,0x5C,0x50,0x70,0x48,0xEC,0x00,0x00,  // k
0x00,0x00,0xE0,0x20,0x20,0x20,0x20,0x20,0x20,0xF8,0x00,0x00,  // l
0x00,0x00,0x00,0x00,0x00,0xF0,0xA8,0xA8,0xA8,0xA8,0x00,0x00,  // m
0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0xEC,0x00,0x00,  // n
0x00,0x00,0x00,0x00,0x00,0x30,0x48,0x48,0x48,0x30,0x00,0x00,  // o

0x00,0x00,0x00,0x00,0x00,0xF0,0x48,0x48,0x48,0x70,0x40,0xE0,  // p
0x00,0x00,0x00,0x00,0x00,0x38,0x48,0x48,0x48,0x38,0x08,0x1C,  // q
0x00,0x00,0x00,0x00,0x00,0xD8,0x60,0x40,0x40,0xE0,0x00,0x00,  // r
0x00,0x00,0x00,0x00,0x00,0x78,0x40,0x30,0x08,0x78,0x00,0x00,  // s
0x00,0x00,0x00,0x20,0x20,0x70,0x20,0x20,0x20,0x18,0x00,0x00,  // t
0x00,0x00,0x00,0x00,0x00,0xD8,0x48,0x48,0x48,0x3C,0x00,0x00,  // u
0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x00,0x00,  // v
0x00,0x00,0x00,0x00,0x00,0xA8,0xA8,0x70,0x50,0x50,0x00,0x00,  // w
0x00,0x00,0x00,0x00,0x00,0xD8,0x50,0x20,0x50,0xD8,0x00,0x00,  // x
0x00,0x00,0x00,0x00,0x00,0xEC,0x48,0x50,0x30,0x20,0x20,0xC0,  // y
0x00,0x00,0x00,0x00,0x00,0x78,0x10,0x20,0x20,0x78,0x00,0x00,  // z
0x00,0x18,0x10,0x10,0x10,0x20,0x10,0x10,0x10,0x10,0x18,0x00,  // {
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,  // |
0x00,0x60,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x60,0x00,  // }
0x40,0xA4,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,  // ~
};


================================================
FILE: components/epaper/Ubuntu16.c
================================================
// This comes with no warranty, implied or otherwise

// This data structure was designed to support Proportional fonts
// on Arduinos. It can however handle any ttf font that has been converted
// using the conversion program. These could be fixed width or proportional 
// fonts. Individual characters do not have to be multiples of 8 bits wide. 
// Any width is fine and does not need to be fixed.

// The data bits are packed to minimize data requirements, but the tradeoff
// is that a header is required per character.

// Ubuntu16.c
// Point Size   : 16
// Memory usage : 1433 bytes
// # characters : 95

// Header Format (to make Arduino UTFT Compatible):
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

const unsigned char tft_Ubuntu16[] =
{
0x00, 0x10, 0x00, 0x00,

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset
// Width
// Height
// xOffset
// xDelta (the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.

// ' '
0x20,0x0D,0x00,0x00,0x00,0x04,

// '!'
0x21,0x02,0x01,0x0B,0x01,0x04,
0xFC,0x60,
// '"'
0x22,0x00,0x04,0x04,0x01,0x07,
0x99,0x99,
// '#'
0x23,0x02,0x09,0x0B,0x01,0x0B,
0x11,0x08,0x84,0x5F,0xF2,0x21,0x10,0x89,0xFF,0x44,0x22,0x11,0x00,
// '$'
0x24,0x00,0x07,0x10,0x01,0x09,
0x10,0x20,0xF6,0x08,0x10,0x18,0x08,0x0C,0x0C,0x08,0x3F,0xC2,0x04,0x00,
// '%'
0x25,0x02,0x0C,0x0B,0x01,0x0E,
0x70,0x4D,0x88,0x89,0x08,0x90,0xDA,0x07,0x4E,0x05,0xB0,0x91,0x09,0x11,0x1B,0x20,0xE0,
// '&'
0x26,0x02,0x0A,0x0B,0x01,0x0B,
0x3C,0x18,0x84,0x21,0x08,0x2C,0x0C,0x04,0x8A,0x10,0x83,0x30,0xC7,0xC8,
// '''
0x27,0x00,0x01,0x04,0x01,0x04,
0xF0,
// '('
0x28,0x00,0x04,0x10,0x01,0x05,
0x02,0x44,0x48,0x88,0x88,0x84,0x44,0x20,
// ')'
0x29,0x00,0x04,0x10,0x00,0x05,
0x04,0x22,0x21,0x11,0x11,0x12,0x22,0x40,
// '*'
0x2A,0x02,0x09,0x06,0x00,0x08,
0x08,0x24,0x8F,0x83,0x81,0x41,0x10,
// '+'
0x2B,0x05,0x07,0x07,0x01,0x09,
0x10,0x20,0x47,0xF1,0x02,0x04,0x00,
// ','
0x2C,0x0B,0x02,0x05,0x00,0x04,
0x54,0x80,
// '-'
0x2D,0x08,0x04,0x01,0x01,0x06,
0xF0,
// '.'
0x2E,0x0B,0x01,0x02,0x01,0x04,
0xC0,
// '/'
0x2F,0x00,0x07,0x10,0x00,0x06,
0x02,0x08,0x10,0x20,0x81,0x02,0x08,0x10,0x40,0x81,0x04,0x08,0x10,0x40,
// '0'
0x30,0x02,0x07,0x0B,0x01,0x09,
0x38,0x8B,0x1C,0x18,0x30,0x60,0xC1,0x86,0x88,0xE0,
// '1'
0x31,0x02,0x04,0x0B,0x01,0x09,
0x13,0x59,0x11,0x11,0x11,0x10,
// '2'
0x32,0x02,0x06,0x0B,0x01,0x09,
0x7A,0x30,0x41,0x08,0x21,0x08,0x42,0x0F,0xC0,
// '3'
0x33,0x02,0x07,0x0B,0x01,0x09,
0x78,0x08,0x08,0x10,0x47,0x01,0x01,0x02,0x0B,0xE0,
// '4'
0x34,0x02,0x07,0x0B,0x01,0x09,
0x04,0x18,0x51,0x22,0x48,0xA1,0x7F,0x04,0x08,0x10,
// '5'
0x35,0x02,0x07,0x0B,0x01,0x09,
0x7E,0x81,0x02,0x07,0x81,0x80,0x81,0x02,0x0B,0xE0,
// '6'
0x36,0x02,0x07,0x0B,0x01,0x09,
0x1C,0x61,0x00,0x0F,0x90,0xA0,0xC1,0x82,0x88,0xE0,
// '7'
0x37,0x02,0x07,0x0B,0x01,0x09,
0xFE,0x04,0x10,0x40,0x82,0x04,0x08,0x20,0x40,0x80,
// '8'
0x38,0x02,0x07,0x0B,0x01,0x09,
0x39,0x8A,0x0C,0x14,0x47,0x11,0x41,0x83,0x89,0xE0,
// '9'
0x39,0x02,0x07,0x0B,0x01,0x09,
0x38,0x8A,0x0C,0x18,0x28,0x4F,0x81,0x04,0x11,0xC0,
// ':'
0x3A,0x05,0x01,0x08,0x01,0x04,
0xC3,
// ';'
0x3B,0x05,0x02,0x0B,0x00,0x04,
0x50,0x05,0x48,
// '<'
0x3C,0x05,0x08,0x07,0x01,0x09,
0x02,0x0C,0x30,0x60,0x30,0x0C,0x02,
// '='
0x3D,0x06,0x07,0x04,0x01,0x09,
0xFE,0x00,0x07,0xF0,
// '>'
0x3E,0x05,0x09,0x07,0x00,0x09,
0x40,0x1C,0x01,0x80,0x70,0x61,0xC1,0x00,
// '?'
0x3F,0x02,0x06,0x0B,0x01,0x07,
0x78,0x30,0x41,0x18,0xC2,0x00,0x00,0x82,0x00,
// '@'
0x40,0x02,0x0D,0x0D,0x01,0x0F,
0x0F,0x81,0x83,0x10,0x0C,0x8F,0xA8,0x84,0xC8,0x26,0x41,0x32,0x09,0x88,0x5A,0x3F,0x90,0x00,0x60,0x00,0xFC,0x00,
// 'A'
0x41,0x02,0x0B,0x0B,0x00,0x0B,
0x04,0x01,0xC0,0x28,0x08,0x81,0x10,0x61,0x08,0x21,0xFC,0x60,0x48,0x0B,0x00,0x80,
// 'B'
0x42,0x02,0x08,0x0B,0x01,0x0A,
0xF8,0x86,0x82,0x82,0x86,0xFC,0x82,0x81,0x81,0x82,0xFC,
// 'C'
0x43,0x02,0x09,0x0B,0x01,0x0B,
0x1F,0x10,0x10,0x10,0x08,0x04,0x02,0x01,0x00,0x40,0x30,0x07,0xC0,
// 'D'
0x44,0x02,0x09,0x0B,0x01,0x0B,
0xFC,0x41,0x20,0x50,0x18,0x0C,0x06,0x03,0x01,0x81,0x41,0x3F,0x00,
// 'E'
0x45,0x02,0x07,0x0B,0x01,0x09,
0xFF,0x02,0x04,0x08,0x1F,0xA0,0x40,0x81,0x03,0xF8,
// 'F'
0x46,0x02,0x07,0x0B,0x01,0x09,
0xFF,0x02,0x04,0x08,0x1F,0xA0,0x40,0x81,0x02,0x00,
// 'G'
0x47,0x02,0x09,0x0B,0x01,0x0B,
0x1F,0x10,0x10,0x10,0x08,0x04,0x02,0x03,0x01,0x40,0xB0,0x47,0xE0,
// 'H'
0x48,0x02,0x09,0x0B,0x01,0x0B,
0x80,0xC0,0x60,0x30,0x18,0x0F,0xFE,0x03,0x01,0x80,0xC0,0x60,0x20,
// 'I'
0x49,0x02,0x01,0x0B,0x01,0x03,
0xFF,0xE0,
// 'J'
0x4A,0x02,0x07,0x0B,0x00,0x08,
0x02,0x04,0x08,0x10,0x20,0x40,0x81,0x02,0x09,0xE0,
// 'K'
0x4B,0x02,0x09,0x0B,0x01,0x0A,
0x81,0x41,0x23,0x12,0x0A,0x06,0x02,0xC1,0x10,0x86,0x40,0xA0,0x20,
// 'L'
0x4C,0x02,0x07,0x0B,0x01,0x08,
0x81,0x02,0x04,0x08,0x10,0x20,0x40,0x81,0x03,0xF8,
// 'M'
0x4D,0x02,0x0B,0x0B,0x01,0x0D,
0x40,0x4C,0x19,0x01,0x28,0xA5,0x14,0x94,0xB2,0x9C,0x33,0x84,0x30,0x06,0x00,0x80,
// 'N'
0x4E,0x02,0x09,0x0B,0x01,0x0B,
0x80,0xE0,0x68,0x32,0x19,0x0C,0x46,0x13,0x05,0x82,0xC0,0xE0,0x20,
// 'O'
0x4F,0x02,0x0B,0x0B,0x01,0x0D,
0x1F,0x04,0x11,0x01,0x40,0x18,0x03,0x00,0x60,0x0C,0x01,0x40,0x44,0x10,0x7C,0x00,
// 'P'
0x50,0x02,0x08,0x0B,0x01,0x0A,
0xFC,0x82,0x81,0x81,0x81,0x82,0xFC,0x80,0x80,0x80,0x80,
// 'Q'
0x51,0x02,0x0B,0x0E,0x01,0x0D,
0x1F,0x04,0x11,0x01,0x40,0x18,0x03,0x00,0x60,0x0C,0x01,0x40,0x44,0x10,0x78,0x02,0x00,0x30,0x01,0x80,
// 'R'
0x52,0x02,0x09,0x0B,0x01,0x0A,
0xFC,0x41,0x20,0x50,0x28,0x14,0x13,0xF1,0x08,0x82,0x40,0xA0,0x20,
// 'S'
0x53,0x02,0x08,0x0B,0x01,0x09,
0x3C,0xC2,0x80,0x80,0x40,0x1C,0x06,0x02,0x02,0x06,0x78,
// 'T'
0x54,0x02,0x09,0x0B,0x00,0x09,
0xFF,0x84,0x02,0x01,0x00,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,
// 'U'
0x55,0x02,0x09,0x0B,0x01,0x0B,
0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x80,0xA0,0x8F,0x80,
// 'V'
0x56,0x02,0x09,0x0B,0x00,0x09,
0x80,0xE0,0xD0,0x48,0x26,0x21,0x10,0x88,0x28,0x14,0x0E,0x02,0x00,
// 'W'
0x57,0x02,0x0D,0x0B,0x00,0x0D,
0x80,0x0E,0x10,0xD0,0x84,0x8E,0x24,0x51,0x22,0x88,0xA2,0x85,0x14,0x38,0xE0,0xC2,0x04,0x10,
// 'X'
0x58,0x02,0x09,0x0B,0x00,0x09,
0xC1,0xA0,0x88,0x86,0xC1,0x40,0x60,0x70,0x6C,0x22,0x20,0xB0,0x60,
// 'Y'
0x59,0x02,0x09,0x0B,0x00,0x09,
0x80,0xA0,0x90,0x44,0x41,0x40,0xA0,0x20,0x10,0x08,0x04,0x02,0x00,
// 'Z'
0x5A,0x02,0x07,0x0B,0x01,0x09,
0xFE,0x04,0x10,0x41,0x02,0x08,0x00,0x41,0x03,0xF8,
// '['
0x5B,0x00,0x03,0x10,0x02,0x05,
0xF2,0x49,0x24,0x92,0x49,0x27,
// '\'
0x5C,0x00,0x07,0x10,0x00,0x06,
0x80,0x81,0x02,0x02,0x04,0x08,0x08,0x10,0x10,0x20,0x40,0x40,0x81,0x01,
// ']'
0x5D,0x00,0x03,0x10,0x00,0x05,
0xE4,0x92,0x49,0x24,0x92,0x4F,
// '^'
0x5E,0x02,0x07,0x06,0x01,0x09,
0x10,0x70,0xA2,0x24,0x50,0x40,
// '_'
0x5F,0x0F,0x08,0x01,0x00,0x08,
0xFF,
// '`'
0x60,0x01,0x04,0x03,0x01,0x06,
0x86,0x10,
// 'a'
0x61,0x05,0x06,0x08,0x01,0x08,
0x78,0x30,0x5F,0xC6,0x18,0x5F,
// 'b'
0x62,0x01,0x07,0x0C,0x01,0x09,
0x81,0x02,0x04,0x0F,0x90,0xA0,0xC1,0x83,0x06,0x17,0xC0,
// 'c'
0x63,0x05,0x06,0x08,0x01,0x08,
0x3D,0x08,0x20,0x82,0x04,0x0F,
// 'd'
0x64,0x01,0x07,0x0C,0x01,0x09,
0x02,0x04,0x08,0x13,0xE8,0x60,0xC1,0x83,0x05,0x09,0xF0,
// 'e'
0x65,0x05,0x07,0x08,0x01,0x09,
0x3C,0x8A,0x0F,0xF8,0x10,0x10,0x1E,
// 'f'
0x66,0x01,0x05,0x0C,0x01,0x06,
0x7E,0x21,0x0F,0xC2,0x10,0x84,0x21,0x00,
// 'g'
0x67,0x05,0x07,0x0B,0x01,0x09,
0x3E,0x86,0x0C,0x18,0x30,0x50,0x9F,0x02,0x0B,0xE0,
// 'h'
0x68,0x01,0x07,0x0C,0x01,0x09,
0x81,0x02,0x04,0x0F,0x90,0xE0,0xC1,0x83,0x06,0x0C,0x10,
// 'i'
0x69,0x01,0x03,0x0C,0x00,0x03,
0x48,0x04,0x92,0x49,0x20,
// 'j'
0x6A,0x01,0x04,0x0F,0xFF,0x03,
0x22,0x00,0x22,0x22,0x22,0x22,0x22,0xC0,
// 'k'
0x6B,0x01,0x06,0x0C,0x01,0x08,
0x82,0x08,0x20,0x8A,0x4A,0x30,0xA2,0x48,0xA1,
// 'l'
0x6C,0x01,0x04,0x0C,0x01,0x04,
0x88,0x88,0x88,0x88,0x88,0x86,
// 'm'
0x6D,0x05,0x0B,0x08,0x01,0x0D,
0xFB,0xD1,0x8E,0x10,0xC2,0x18,0x43,0x08,0x61,0x0C,0x21,
// 'n'
0x6E,0x05,0x07,0x08,0x01,0x09,
0xFD,0x0E,0x0C,0x18,0x30,0x60,0xC1,
// 'o'
0x6F,0x05,0x08,0x08,0x01,0x0A,
0x3C,0x42,0x81,0x81,0x81,0x81,0x42,0x3C,
// 'p'
0x70,0x05,0x07,0x0B,0x01,0x09,
0xF9,0x0A,0x0C,0x18,0x30,0x61,0x7C,0x81,0x02,0x00,
// 'q'
0x71,0x05,0x07,0x0B,0x01,0x09,
0x3E,0x86,0x0C,0x18,0x30,0x50,0x9F,0x02,0x04,0x08,
// 'r'
0x72,0x05,0x05,0x08,0x01,0x06,
0xFC,0x21,0x08,0x42,0x10,
// 's'
0x73,0x05,0x05,0x08,0x01,0x07,
0x7C,0x20,0xC3,0x04,0x3E,
// 't'
0x74,0x02,0x05,0x0B,0x01,0x07,
0x84,0x21,0xF8,0x42,0x10,0x84,0x1E,
// 'u'
0x75,0x05,0x07,0x08,0x01,0x09,
0x83,0x06,0x0C,0x18,0x30,0x50,0xBF,
// 'v'
0x76,0x05,0x07,0x08,0x00,0x07,
0x83,0x05,0x12,0x22,0x85,0x0E,0x08,
// 'w'
0x77,0x05,0x0D,0x08,0x00,0x0D,
0x82,0x0C,0x10,0x51,0xC4,0x8A,0x26,0x5B,0x14,0x50,0xE3,0x82,0x08,
// 'x'
0x78,0x05,0x08,0x08,0x00,0x08,
0xC3,0x66,0x24,0x18,0x18,0x24,0x42,0xC3,
// 'y'
0x79,0x05,0x07,0x0B,0x00,0x07,
0x82,0x89,0x12,0x22,0x85,0x04,0x08,0x10,0x43,0x00,
// 'z'
0x7A,0x05,0x06,0x08,0x01,0x08,
0xFC,0x10,0x84,0x21,0x08,0x3F,
// '{'
0x7B,0x00,0x05,0x10,0x00,0x05,
0x19,0x08,0x42,0x10,0x98,0x61,0x08,0x42,0x10,0x83,
// '|'
0x7C,0x00,0x01,0x10,0x02,0x05,
0xFF,0xFF,
// '}'
0x7D,0x00,0x05,0x10,0x00,0x05,
0xC1,0x08,0x42,0x10,0x83,0x31,0x08,0x42,0x10,0x98,
// '~'
0x7E,0x07,0x07,0x02,0x01,0x09,
0x73,0x18,

// Terminator
0xFF
};


================================================
FILE: components/epaper/comic24.c
================================================
// This comes with no warranty, implied or otherwise

// This data structure was designed to support Proportional fonts
// on Arduinos. It can however handle any ttf font that has been converted
// using the conversion program. These could be fixed width or proportional 
// fonts. Individual characters do not have to be multiples of 8 bits wide. 
// Any width is fine and does not need to be fixed.

// The data bits are packed to minimize data requirements, but the tradeoff
// is that a header is required per character.

// comic.c
// Point Size   : 24
// Memory usage : 2814 bytes
// # characters : 95

// Header Format (to make Arduino UTFT Compatible):
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

unsigned char tft_Comic24[] = 
{
0x00, 0x19, 0x00, 0x00,

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset
// Width
// Height
// xOffset
// xDelta (the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.

// ' '
0x20,0x15,0x00,0x00,0x00,0x07,

// '!'
0x21,0x02,0x02,0x14,0x01,0x06,
0xFF,0xFF,0xFF,0xFC,0x2D,
// '"'
0x22,0x03,0x06,0x08,0x02,0x0A,
0xCF,0x3C,0xF3,0xCF,0x3C,0xF3,
// '#'
0x23,0x03,0x14,0x12,0x01,0x14,
0x01,0x81,0x80,0x18,0x18,0x01,0x81,0x80,0x30,0x30,0x03,0x03,0x07,0xFF,0xFF,0x7F,0xFF,0xF0,0x60,0x60,0x06,0x06,0x00,0xC0,0xC0,0x0C,0x0C,0x0F,0xFF,0xFE,0xFF,0xFF,0xE1,0x81,0x80,0x18,0x18,0x03,0x83,0x00,0x30,0x30,0x03,0x03,0x00,
// '$'
0x24,0x00,0x0B,0x19,0x02,0x11,
0x0C,0x01,0x80,0x30,0x0F,0x83,0xFC,0xD9,0xBB,0x06,0x60,0xCC,0x19,0x83,0xB0,0x3F,0x83,0xFC,0x1B,0x83,0x18,0x63,0x0C,0x71,0x9F,0x37,0x7F,0xC3,0xF0,0x18,0x03,0x00,0x60,0x0C,0x00,
// '%'
0x25,0x01,0x11,0x14,0x02,0x14,
0x00,0x00,0x00,0x0C,0x0E,0x0E,0x0F,0x86,0x0C,0x67,0x06,0x33,0x03,0x19,0x80,0xF9,0x80,0x38,0xC0,0x00,0xE0,0x00,0x60,0x00,0x70,0x00,0x31,0xE0,0x39,0xF8,0x19,0xCE,0x1C,0xC3,0x0C,0x61,0x86,0x39,0xC6,0x0F,0xC3,0x03,0xC0,
// '&'
0x26,0x03,0x0F,0x13,0x01,0x10,
0x01,0xC0,0x07,0xC0,0x19,0x80,0x33,0x00,0x6E,0x00,0xF8,0x01,0xE0,0x07,0x80,0x1F,0x8C,0x73,0x19,0xC3,0x37,0x07,0xEC,0x07,0xD8,0x07,0x30,0x0E,0x38,0x7E,0x3F,0xEC,0x3F,0x0C,0x00,0x18,
// '''
0x27,0x03,0x02,0x06,0x03,0x09,
0xFF,0xF0,
// '('
0x28,0x02,0x07,0x18,0x01,0x09,
0x06,0x1C,0x71,0xC3,0x0E,0x18,0x30,0xE1,0x83,0x06,0x0C,0x18,0x30,0x60,0xE0,0xC1,0x83,0x83,0x83,0x87,0x83,
// ')'
0x29,0x02,0x06,0x18,0x02,0x09,
0xC3,0x86,0x0C,0x30,0x61,0x86,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0x61,0x86,0x31,0xCE,0x30,
// '*'
0x2A,0x03,0x0B,0x09,0x01,0x0D,
0x0C,0x01,0x83,0xBF,0xFF,0xF3,0xFC,0x3C,0x0F,0xC3,0x9C,0x61,0x80,
// '+'
0x2B,0x09,0x0A,0x0A,0x00,0x0C,
0x0C,0x03,0x00,0xC0,0x30,0xFF,0xFF,0xF0,0xC0,0x30,0x0C,0x03,0x00,
// ','
0x2C,0x13,0x04,0x06,0x02,0x07,
0x37,0x66,0xEC,
// '-'
0x2D,0x0E,0x08,0x02,0x01,0x0A,
0xFF,0xFF,
// '.'
0x2E,0x12,0x03,0x03,0x02,0x06,
0xFF,0x80,
// '/'
0x2F,0x01,0x0A,0x15,0x01,0x0C,
0x00,0x00,0x30,0x0C,0x06,0x01,0x80,0x60,0x30,0x0C,0x06,0x01,0x80,0xC0,0x30,0x18,0x06,0x03,0x00,0xC0,0x60,0x18,0x0E,0x03,0x00,0xC0,0x00,
// '0'
0x30,0x03,0x0D,0x12,0x01,0x0F,
0x0F,0x80,0xFF,0x0E,0x18,0xE0,0x66,0x03,0x70,0x0F,0x00,0x78,0x03,0xC0,0x1E,0x00,0xF0,0x07,0x80,0x3C,0x03,0xB0,0x19,0x81,0xC7,0x1C,0x3F,0xC0,0x7C,0x00,
// '1'
0x31,0x03,0x06,0x12,0x03,0x0B,
0x10,0xC7,0x3C,0xB0,0xC3,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0xFF,0xF0,
// '2'
0x32,0x03,0x0B,0x12,0x02,0x0F,
0x1F,0x07,0xFB,0xC3,0xE0,0x30,0x06,0x00,0xC0,0x38,0x0E,0x07,0x81,0xE0,0xF8,0x3C,0x07,0x01,0xC0,0x30,0x06,0x00,0xFF,0xDF,0xFC,
// '3'
0x33,0x03,0x0B,0x12,0x02,0x0F,
0x1F,0x0F,0xF9,0xC3,0x80,0x30,0x06,0x00,0xC0,0x78,0x7E,0x0F,0x80,0x78,0x03,0x80,0x30,0x06,0x00,0xF0,0x1F,0x0E,0x7F,0x83,0xE0,
// '4'
0x34,0x03,0x0D,0x12,0x02,0x0F,
0x01,0xC0,0x0E,0x00,0xF0,0x0F,0x80,0x6C,0x07,0x60,0x33,0x03,0x98,0x38,0xC1,0x86,0x1C,0x31,0xFF,0xFF,0xFF,0x80,0x60,0x03,0x00,0x18,0x00,0xC0,0x06,0x00,
// '5'
0x35,0x02,0x0C,0x13,0x02,0x0F,
0x00,0x0F,0xFE,0xFF,0xE6,0x00,0x60,0x0E,0x00,0xEF,0x8F,0xFC,0xF8,0x6E,0x07,0xC0,0x30,0x03,0x00,0x30,0x03,0x00,0x7C,0x06,0xE1,0xE7,0xFC,0x3F,0x00,
// '6'
0x36,0x03,0x0C,0x12,0x01,0x0F,
0x03,0x00,0x70,0x0E,0x01,0xC0,0x38,0x03,0x00,0x60,0x06,0xF8,0xFF,0xEE,0x0E,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0x60,0x77,0x0E,0x3F,0xC1,0xF8,
// '7'
0x37,0x02,0x0D,0x13,0x01,0x0F,
0x00,0x07,0xFF,0xFF,0xFE,0x00,0xE0,0x0E,0x00,0x60,0x06,0x00,0x30,0x03,0x80,0x18,0x01,0xC0,0x0C,0x00,0x60,0x07,0x00,0x30,0x03,0x80,0x18,0x00,0xC0,0x04,0x00,
// '8'
0x38,0x02,0x0C,0x13,0x01,0x0F,
0x00,0x00,0xFC,0x3F,0xE3,0x07,0x60,0x36,0x03,0x60,0x37,0x8F,0x3F,0xE1,0xFE,0x38,0xE7,0x07,0x60,0x36,0x03,0x60,0x36,0x03,0x30,0x63,0xFE,0x0F,0x80,
// '9'
0x39,0x03,0x0D,0x13,0x01,0x0F,
0x0F,0x01,0xFE,0x1C,0x38,0xC0,0xCC,0x07,0x60,0x1B,0x00,0xD8,0x06,0xE0,0x73,0x87,0x8F,0xF8,0x3E,0xC0,0x0E,0x00,0x60,0x07,0x00,0xF0,0x1F,0x03,0xE0,0x1C,0x00,
// ':'
0x3A,0x09,0x03,0x0B,0x02,0x07,
0xFF,0x80,0x00,0xFF,0x80,
// ';'
0x3B,0x09,0x04,0x0E,0x02,0x07,
0xEE,0xE0,0x00,0x00,0x03,0x7E,0xCC,
// '<'
0x3C,0x09,0x07,0x0A,0x01,0x09,
0x06,0x1C,0x71,0xC7,0x1E,0x1E,0x0E,0x0E,0x0C,
// '='
0x3D,0x0A,0x09,0x09,0x01,0x0C,
0xFF,0xFF,0xC0,0x00,0x00,0x00,0x03,0xFF,0xFF,0x00,0x00,
// '>'
0x3E,0x08,0x08,0x0B,0x01,0x0A,
0x60,0x70,0x38,0x3C,0x1E,0x0F,0x06,0x0C,0x38,0x70,0xC0,
// '?'
0x3F,0x04,0x0B,0x12,0x01,0x0D,
0x1E,0x0F,0xE3,0xC6,0x60,0x60,0x06,0x00,0xC0,0x18,0x07,0x01,0xE0,0xF8,0x3E,0x0F,0x01,0x80,0x00,0x00,0x01,0x80,0x30,0x06,0x00,
// '@'
0x40,0x02,0x13,0x14,0x01,0x16,
0x03,0xF8,0x01,0xFF,0xC0,0x78,0x3C,0x1C,0x01,0xC3,0x00,0x1C,0xC1,0xC1,0x98,0xF8,0x1E,0x3C,0x03,0xC6,0x30,0x79,0x8E,0x0F,0x31,0xC1,0xE6,0x78,0x6C,0x7F,0xFC,0xC7,0x3E,0x18,0x00,0x01,0x80,0x00,0x38,0x00,0x03,0xC0,0xE0,0x1F,0xFC,0x00,0xFE,0x00,
// 'A'
0x41,0x03,0x0E,0x12,0x01,0x11,
0x00,0x80,0x07,0x00,0x1C,0x00,0xF0,0x03,0xC0,0x1D,0x80,0x76,0x03,0x98,0x0E,0x20,0x70,0xC1,0xFF,0x0F,0xFC,0x7C,0x19,0xC0,0x67,0x01,0xB8,0x07,0xE0,0x0F,0x00,0x30,
// 'B'
0x42,0x03,0x0B,0x13,0x03,0x0F,
0x7C,0x1F,0xE3,0x0E,0x60,0xEC,0x0D,0x81,0xB0,0x36,0x0E,0xC3,0x9F,0xE3,0xFC,0x61,0xEC,0x0F,0x80,0xF0,0x1E,0x0E,0xC7,0xDF,0xE3,0xF0,0x00,
// 'C'
0x43,0x03,0x0D,0x12,0x01,0x0E,
0x01,0xF8,0x3F,0xC3,0xC6,0x38,0x31,0x80,0x1C,0x01,0xC0,0x0C,0x00,0x60,0x06,0x00,0x30,0x01,0x80,0x0C,0x00,0x60,0x19,0x81,0xCE,0x3C,0x3F,0xC0,0xF8,0x00,
// 'D'
0x44,0x03,0x0D,0x12,0x02,0x11,
0x60,0x07,0xC0,0x37,0x81,0x8F,0x0C,0x1C,0x60,0x73,0x01,0xD8,0x06,0xC0,0x1E,0x00,0xF0,0x07,0x80,0x3C,0x01,0xE0,0x1B,0x01,0xDC,0x1C,0xFF,0xC1,0xF8,0x00,
// 'E'
0x45,0x03,0x0D,0x12,0x02,0x0F,
0xFF,0xF7,0xFF,0xF0,0x01,0x80,0x0C,0x00,0x60,0x03,0x00,0x18,0x7E,0xFF,0xF7,0xE0,0x30,0x01,0x80,0x0C,0x00,0x60,0x03,0x00,0x18,0x00,0x7F,0xF1,0xFF,0x80,
// 'F'
0x46,0x03,0x0C,0x12,0x02,0x0F,
0xFF,0xCF,0xFF,0xC0,0x7C,0x00,0xC0,0x0C,0x00,0xC0,0x0D,0xFE,0xFF,0xEF,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0x00,0xC0,0x0C,0x00,
// 'G'
0x47,0x03,0x0F,0x12,0x01,0x10,
0x03,0xE0,0x0F,0xF0,0x38,0xE0,0xE0,0x03,0x80,0x06,0x00,0x18,0x00,0x30,0x00,0x61,0xFF,0x9F,0xFF,0x3C,0x36,0x00,0x6C,0x01,0x98,0x07,0x30,0x0C,0x30,0x70,0x7F,0xC0,0x3E,0x00,
// 'H'
0x48,0x03,0x0F,0x12,0x02,0x12,
0xC0,0x03,0x80,0x0F,0x00,0x1E,0x00,0x3C,0x00,0x78,0x00,0xF0,0x01,0xE0,0x03,0xC0,0xFF,0xFF,0xFF,0xFC,0x1E,0x00,0x3C,0x00,0x78,0x00,0xF0,0x01,0xE0,0x03,0xC0,0x07,0x80,0x0C,
// 'I'
0x49,0x03,0x0C,0x12,0x00,0x0D,
0xFF,0xEF,0xFF,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0xFF,0xFF,0xFF,
// 'J'
0x4A,0x03,0x0E,0x12,0x01,0x10,
0x1F,0xFC,0x7F,0xF0,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x00,0x0C,0x00,0x30,0xC0,0xC3,0x06,0x0E,0x18,0x1C,0x60,0x3F,0x80,0x3C,0x00,
// 'K'
0x4B,0x03,0x0C,0x12,0x03,0x0F,
0xC0,0x6C,0x0E,0xC1,0xCC,0x38,0xC7,0x0C,0xE0,0xDC,0x0F,0x80,0xF0,0x0F,0x00,0xF8,0x0F,0xC0,0xDE,0x0C,0xF0,0xC7,0x8C,0x1E,0xC0,0xFC,0x07,
// 'L'
0x4C,0x03,0x0B,0x12,0x01,0x0D,
0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xFF,0xEF,0xFC,
// 'M'
0x4D,0x03,0x13,0x13,0x01,0x15,
0x0C,0x06,0x01,0x80,0xC0,0x78,0x3C,0x0F,0x07,0x81,0xE0,0xF0,0x3C,0x1E,0x07,0x83,0xC1,0xD8,0xEC,0x3B,0x1D,0x87,0x63,0xB0,0xCC,0xE6,0x38,0xDC,0x47,0x1B,0x8C,0xE3,0xF1,0xB8,0x3C,0x37,0x07,0x86,0xE0,0xF0,0x7C,0x1E,0x0F,0x01,0x81,0x80,
// 'N'
0x4E,0x03,0x11,0x12,0x01,0x13,
0x60,0x01,0x38,0x00,0xDE,0x00,0x6F,0x00,0x37,0xC0,0x1B,0x70,0x0D,0x9C,0x06,0xCF,0x03,0x63,0x81,0xB0,0xE0,0xD8,0x38,0x6C,0x0E,0x36,0x03,0x9B,0x00,0xED,0x80,0x3E,0xC0,0x0F,0x60,0x03,0xB0,0x00,0xC0,
// 'O'
0x4F,0x03,0x11,0x12,0x01,0x13,
0x01,0xF8,0x03,0xFF,0x07,0x81,0xC3,0x00,0x63,0x00,0x1B,0x80,0x0D,0x80,0x07,0xC0,0x03,0xC0,0x01,0xE0,0x00,0xF0,0x00,0xF8,0x00,0x6C,0x00,0x33,0x00,0x31,0xC0,0x38,0x70,0x78,0x1F,0xF8,0x03,0xF0,0x00,
// 'P'
0x50,0x03,0x0B,0x12,0x01,0x0D,
0xFE,0x1F,0xF3,0x0F,0x60,0x7C,0x07,0x80,0xF0,0x1E,0x06,0xC3,0xDF,0xF3,0xF8,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x00,
// 'Q'
0x51,0x03,0x14,0x17,0x01,0x15,
0x01,0xF8,0x00,0x7F,0xE0,0x1E,0x07,0x03,0x80,0x18,0x30,0x01,0xC6,0x00,0x0C,0x60,0x00,0xEC,0x00,0x06,0xC0,0x00,0x6C,0x00,0x06,0xC0,0x00,0x6C,0x00,0x06,0x60,0xE0,0xE7,0x0F,0x0C,0x38,0x79,0xC1,0xC3,0xF8,0x0F,0xFF,0x00,0x3F,0x78,0x00,0x03,0xC0,0x00,0x1E,0x00,0x00,0xF0,0x00,0x07,0x00,0x00,0x20,
// 'R'
0x52,0x02,0x0D,0x13,0x01,0x0F,
0x00,0x03,0xE0,0x3F,0xC1,0x8F,0x0C,0x0E,0x60,0x33,0x00,0xD8,0x06,0xC0,0x36,0x03,0xB0,0x79,0xFF,0x8F,0xF0,0x7F,0x83,0x1F,0x18,0x3C,0xC0,0xF6,0x01,0xF0,0x06,
// 'S'
0x53,0x03,0x0F,0x13,0x01,0x11,
0x01,0xF0,0x07,0xF8,0x18,0x70,0x60,0x01,0x80,0x03,0x00,0x06,0x00,0x0E,0x00,0x0F,0xF0,0x07,0xF0,0x00,0xF0,0x00,0x70,0x00,0x60,0x00,0xD8,0x01,0xB8,0x06,0x78,0x3C,0x7F,0xE0,0x3F,0x00,
// 'T'
0x54,0x02,0x0F,0x13,0x01,0x10,
0x00,0x01,0xFF,0xFD,0xFF,0xF8,0x18,0x00,0x30,0x00,0x60,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00,0x0C,0x00,
// 'U'
0x55,0x03,0x11,0x12,0x01,0x12,
0x60,0x03,0x30,0x01,0x98,0x00,0xCC,0x00,0x66,0x00,0x33,0x00,0x19,0x80,0x0C,0xC0,0x06,0x60,0x03,0x30,0x01,0x98,0x01,0xCC,0x00,0xC7,0x00,0x61,0x80,0x70,0xE0,0x30,0x38,0x38,0x0F,0xF8,0x01,0xF0,0x00,
// 'V'
0x56,0x03,0x0E,0x13,0x02,0x10,
0x80,0x0F,0x00,0x3C,0x01,0xB0,0x06,0x60,0x31,0x80,0xC6,0x03,0x0C,0x18,0x30,0x60,0xC1,0x81,0x8C,0x06,0x30,0x0D,0x80,0x36,0x00,0xF8,0x01,0xC0,0x07,0x00,0x08,0x00,0x00,0x00,
// 'W'
0x57,0x03,0x17,0x12,0x01,0x19,
0xC0,0x20,0x0F,0xC0,0x60,0x19,0x81,0xC0,0x23,0x03,0x80,0xC6,0x07,0x01,0x86,0x1E,0x03,0x0C,0x36,0x0C,0x18,0x6C,0x18,0x11,0x98,0x60,0x33,0x30,0xC0,0x66,0x61,0x80,0xD8,0x66,0x01,0xB0,0xCC,0x01,0xC1,0xB0,0x03,0x83,0x60,0x07,0x07,0x80,0x0C,0x07,0x00,0x08,0x0E,0x00,
// 'X'
0x58,0x03,0x10,0x12,0x01,0x11,
0x60,0x03,0x70,0x07,0x38,0x0E,0x1C,0x1C,0x0C,0x1C,0x0E,0x38,0x07,0x70,0x03,0xE0,0x01,0xC0,0x03,0xC0,0x07,0xE0,0x07,0x70,0x0E,0x38,0x1C,0x18,0x38,0x1C,0x70,0x0E,0xE0,0x07,0xC0,0x03,
// 'Y'
0x59,0x03,0x0F,0x13,0x00,0x10,
0x60,0x06,0xE0,0x1D,0xC0,0x31,0xC0,0xE1,0xC1,0x83,0x83,0x03,0x8C,0x07,0x18,0x07,0x70,0x0F,0xC0,0x0F,0x80,0x0F,0x00,0x1C,0x00,0x38,0x00,0x60,0x01,0xC0,0x03,0x00,0x06,0x00,0x08,0x00,
// 'Z'
0x5A,0x03,0x0F,0x12,0x01,0x11,
0xFF,0xFF,0xFF,0xFC,0x00,0xF0,0x03,0x80,0x0E,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x07,0x00,0x1E,0x00,0x38,0x00,0xE0,0x03,0xC0,0x07,0x00,0x1C,0x00,0x70,0x00,0xFF,0xFF,0xFF,0xFC,
// '['
0x5B,0x01,0x07,0x1A,0x01,0x09,
0x00,0xFD,0xFB,0x06,0x0C,0x18,0x30,0x60,0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xC1,0x83,0x06,0x0C,0x18,0x3F,0x7E,0x00,
// '\'
0x5C,0x03,0x0B,0x14,0x02,0x0D,
0xC0,0x18,0x01,0x80,0x30,0x03,0x00,0x60,0x06,0x00,0xC0,0x0C,0x01,0x80,0x18,0x03,0x00,0x20,0x06,0x00,0xC0,0x0C,0x01,0x80,0x18,0x03,0x00,0x60,
// ']'
0x5D,0x01,0x07,0x1A,0x02,0x09,
0x01,0xFB,0xF0,0x60,0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xC1,0x83,0x7E,0xFC,0x00,
// '^'
0x5E,0x02,0x0A,0x06,0x02,0x0E,
0x0C,0x07,0x83,0xF1,0xCE,0xE1,0xF0,0x30,
// '_'
0x5F,0x16,0x0F,0x04,0x00,0x0F,
0x00,0x01,0xFF,0xFF,0xFF,0xF8,0x00,0x00,
// '`'
0x60,0x02,0x05,0x06,0x02,0x0D,
0xC7,0x1C,0x63,0x8C,
// 'a'
0x61,0x09,0x0B,0x0C,0x01,0x0C,
0x0F,0x87,0xF9,0xE3,0x30,0x6E,0x0D,0x81,0xB0,0x36,0x06,0xC0,0xCC,0x39,0xFF,0x9F,0x30,
// 'b'
0x62,0x02,0x0C,0x13,0x01,0x0E,
0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x78,0x7F,0xC7,0x8E,0x60,0x76,0x03,0x60,0x36,0x03,0x60,0x36,0x06,0x70,0xE7,0xFC,0x7F,0x00,
// 'c'
0x63,0x09,0x0A,0x0C,0x01,0x0C,
0x0F,0x07,0xF3,0x0D,0x80,0x60,0x30,0x0C,0x03,0x00,0xC0,0x1C,0x33,0xFC,0x7C,
// 'd'
0x64,0x02,0x0C,0x13,0x01,0x0E,
0x00,0x20,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x61,0xF6,0x3F,0xE7,0x0E,0x60,0x6C,0x06,0xC0,0x6C,0x06,0xC0,0x6E,0x06,0x70,0xE3,0xFE,0x1F,0x60,
// 'e'
0x65,0x09,0x0B,0x0C,0x01,0x0D,
0x1F,0x07,0xF9,0xC7,0x30,0xEC,0x79,0xBE,0x3E,0x07,0x00,0xC0,0x6E,0x1D,0xFF,0x0F,0x80,
// 'f'
0x66,0x02,0x0A,0x14,0x01,0x0C,
0x03,0x83,0xE0,0xE0,0x70,0x18,0x06,0x01,0x83,0xFF,0xFF,0xC6,0x01,0x80,0x60,0x18,0x06,0x01,0x80,0x60,0x18,0x06,0x01,0x80,0x60,
// 'g'
0x67,0x09,0x0A,0x13,0x02,0x0D,
0x0F,0x0F,0xF7,0x0D,0x83,0xC0,0xF0,0x3C,0x1F,0x07,0xC1,0xD8,0xF7,0xEC,0xF3,0x00,0xC0,0x30,0x18,0x06,0x03,0xBF,0xC7,0xE0,
// 'h'
0x68,0x02,0x0B,0x13,0x01,0x0E,
0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x03,0x1E,0x6F,0xEF,0x8D,0xE1,0xB8,0x36,0x06,0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0x80,
// 'i'
0x69,0x04,0x02,0x11,0x03,0x07,
0xF0,0x3F,0xFF,0xFF,0xC0,
// 'j'
0x6A,0x04,0x08,0x18,0x00,0x0A,
0x03,0x03,0x00,0x00,0x00,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0xC3,0xE3,0x77,0x7E,0x1C,
// 'k'
0x6B,0x03,0x0B,0x13,0x02,0x0E,
0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x36,0x0E,0xC7,0x99,0xE3,0x70,0x7E,0x0F,0xE1,0xCE,0x30,0xE6,0x0E,0xC0,0xF8,0x08,0x00,0x00,
// 'l'
0x6C,0x02,0x02,0x13,0x03,0x07,
0xFF,0xFF,0xFF,0xFF,0xFC,
// 'm'
0x6D,0x09,0x10,0x0C,0x01,0x12,
0x67,0x3C,0x6F,0xFE,0x7D,0xEE,0x79,0x86,0x71,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,0x61,0x86,
// 'n'
0x6E,0x09,0x0B,0x0C,0x01,0x0D,
0x63,0x8D,0xF9,0xF1,0xBC,0x37,0x06,0xE0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x30,
// 'o'
0x6F,0x09,0x0C,0x0C,0x01,0x0D,
0x0F,0x81,0xFC,0x38,0xC3,0x06,0x60,0x66,0x06,0x60,0x66,0x06,0x60,0xE3,0x1C,0x1F,0x80,0xF0,
// 'p'
0x70,0x08,0x0A,0x14,0x02,0x0D,
0xC0,0x33,0xCF,0xFB,0xC6,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x7C,0x1B,0xFC,0xFE,0x30,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,
// 'q'
0x71,0x08,0x0A,0x14,0x01,0x0C,
0x00,0x03,0xF3,0xFD,0xE3,0x60,0xF8,0x3C,0x0F,0x03,0xC0,0xF0,0x76,0x1D,0xFF,0x1F,0x80,0x60,0x18,0x06,0x01,0x80,0x60,0x18,0x06,
// 'r'
0x72,0x09,0x09,0x0C,0x01,0x0B,
0xCF,0x6F,0xFE,0x7C,0x3C,0x1E,0x03,0x01,0x80,0xC0,0x60,0x30,0x18,0x00,
// 's'
0x73,0x09,0x09,0x0C,0x02,0x0C,
0x03,0x9F,0xDE,0x7C,0x3E,0x07,0xF0,0xFC,0x07,0x01,0xE0,0xFF,0xC7,0xC0,
// 't'
0x74,0x05,0x0A,0x10,0x00,0x0A,
0x0C,0x03,0x00,0xC0,0x30,0xFF,0xFF,0xF0,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,
// 'u'
0x75,0x09,0x0B,0x0C,0x01,0x0C,
0xC0,0xD8,0x1B,0x03,0x60,0x6C,0x0D,0x81,0xB0,0x36,0x06,0xC0,0xD8,0x19,0xFF,0x1F,0x60,
// 'v'
0x76,0x09,0x0B,0x0D,0x01,0x0C,
0xC0,0x78,0x1F,0x83,0x30,0x67,0x1C,0x63,0x0C,0xE0,0xD8,0x1E,0x03,0xC0,0x30,0x06,0x00,0x00,
// 'w'
0x77,0x09,0x0F,0x0D,0x01,0x11,
0xC1,0x87,0x83,0x0F,0x0E,0x1E,0x1C,0x66,0x7C,0xCC,0xD9,0x99,0x36,0x36,0x6C,0x7C,0xD8,0x70,0xE0,0xE1,0xC0,0x83,0x80,0x00,0x00,
// 'x'
0x78,0x09,0x0D,0x0D,0x01,0x0E,
0x60,0x1B,0x81,0xCE,0x1C,0x39,0xC0,0xFC,0x03,0xC0,0x3C,0x03,0xF0,0x39,0xC3,0x87,0x38,0x1D,0x80,0x70,0x01,0x80,
// 'y'
0x79,0x09,0x0C,0x13,0x00,0x0D,
0xC0,0x3E,0x07,0x60,0x67,0x0C,0x30,0xC3,0x98,0x19,0x81,0xD8,0x0F,0x00,0xF0,0x06,0x00,0x60,0x0C,0x00,0xC0,0x18,0x01,0x80,0x30,0x03,0x00,0x30,0x00,
// 'z'
0x7A,0x09,0x0B,0x0C,0x01,0x0D,
0xFF,0xFF,0xFC,0x07,0x00,0xC0,0x30,0x0C,0x03,0x80,0xE0,0x38,0x0E,0x03,0xFF,0xFF,0xF0,
// '{'
0x7B,0x02,0x08,0x18,0x01,0x09,
0x0F,0x1F,0x38,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xE0,0xE0,0x70,0x30,0x30,0x30,0x30,0x30,0x38,0x18,0x1F,0x07,
// '|'
0x7C,0x01,0x02,0x18,0x04,0x0A,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
// '}'
0x7D,0x02,0x08,0x18,0x01,0x09,
0x70,0xF8,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x06,0x07,0x07,0x0E,0x0C,0x0C,0x0C,0x0C,0x0C,0x1C,0x18,0xF8,0xE0,
// '~'
0x7E,0x0B,0x0C,0x05,0x01,0x0E,
0x38,0x37,0xE3,0xE7,0x7C,0x3E,0x01,0xC0,

// Terminator
0xFF
};


================================================
FILE: components/epaper/component.mk
================================================
#
# Main Makefile. This is basically the same as a component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

COMPONENT_SRCDIRS := . 
COMPONENT_ADD_INCLUDEDIRS := .


================================================
FILE: components/epaper/dejavuX.c
================================================
// This comes with no warranty, implied or otherwise

// This data structure was designed to support Proportional fonts
// on Arduinos. It can however handle any ttf font that has been converted
// using the conversion program. These could be fixed width or proportional 
// fonts. Individual characters do not have to be multiples of 8 bits wide. 
// Any width is fine and does not need to be fixed.

// The data bits are packed to minimize data requirements, but the tradeoff
// is that a header is required per character.

// dejavuX.c
// Point Size   : 18
// Memory usage : 4676 bytes
// # characters : 224

// Header Format (to make Arduino UTFT Compatible):
// ------------------------------------------------
// Character Width (Used as a marker to indicate use this format. i.e.: = 0x00)
// Character Height
// First Character (Reserved. 0x00)
// Number Of Characters (Reserved. 0x00)

const unsigned char tft_Dejavu18[] =
{
0x00, 0x12, 0x00, 0x00,

// Individual Character Format:
// ----------------------------
// Character Code
// Adjusted Y Offset
// Width
// Height
// xOffset
// xDelta (the distance to move the cursor. Effective width of the character.)
// Data[n]

// NOTE: You can remove any of these characters if they are not needed in
// your application. The first character number in each Glyph indicates
// the ASCII character code. Therefore, these do not have to be sequential.
// Just remove all the content for a particular character to save space.

// ' '
0x20,0x11,0x00,0x00,0x00,0x06,

// '!'
0x21,0x04,0x02,0x0D,0x03,0x07,
0xFF,0xFF,0xC3,0xC0,
// '"'
0x22,0x04,0x06,0x05,0x01,0x08,
0xCF,0x3C,0xF3,0xCC,
// '#'
0x23,0x03,0x0C,0x0E,0x01,0x0F,
0x04,0x40,0x44,0x0C,0xC0,0xC8,0x7F,0xF7,0xFF,0x09,0x81,0x90,0xFF,0xEF,0xFE,0x13,0x03,0x30,0x32,0x02,0x20,
// '$'
0x24,0x03,0x0A,0x11,0x01,0x0B,
0x08,0x02,0x03,0xE1,0xFC,0xE9,0x32,0x0F,0x81,0xF8,0x0F,0x02,0x60,0x9A,0x2E,0xFF,0x1F,0x80,0x80,0x20,0x08,0x00,
// '%'
0x25,0x04,0x0F,0x0D,0x01,0x11,
0x78,0x10,0x90,0x43,0x31,0x86,0x62,0x0C,0xC8,0x19,0x10,0x1E,0x4F,0x01,0x12,0x02,0x66,0x08,0xCC,0x31,0x98,0x41,0x21,0x03,0xC0,
// '&'
0x26,0x04,0x0C,0x0D,0x01,0x0D,
0x0F,0x01,0xF8,0x30,0x83,0x00,0x38,0x03,0xC0,0x7E,0x6C,0x76,0xC3,0xCC,0x18,0xE1,0xC7,0xFE,0x3E,0x70,
// '''
0x27,0x04,0x02,0x05,0x01,0x04,
0xFF,0xC0,
// '('
0x28,0x03,0x04,0x10,0x02,0x07,
0x32,0x66,0x4C,0xCC,0xCC,0xC4,0x66,0x23,
// ')'
0x29,0x03,0x04,0x10,0x01,0x07,
0xC4,0x66,0x23,0x33,0x33,0x32,0x66,0x4C,
// '*'
0x2A,0x04,0x07,0x08,0x01,0x09,
0x11,0x25,0x51,0xC3,0x8A,0xA4,0x88,
// '+'
0x2B,0x05,0x0C,0x0C,0x02,0x0F,
0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x0F,0xFF,0xFF,0xF0,0x60,0x06,0x00,0x60,0x06,0x00,0x60,
// ','
0x2C,0x0F,0x03,0x04,0x01,0x06,
0x6D,0x40,
// '-'
0x2D,0x0B,0x05,0x02,0x01,0x07,
0xFF,0xC0,
// '.'
0x2E,0x0F,0x02,0x02,0x02,0x06,
0xF0,
// '/'
0x2F,0x04,0x06,0x0F,0x00,0x06,
0x0C,0x31,0x86,0x18,0xE3,0x0C,0x31,0xC6,0x18,0x63,0x0C,0x00,
// '0'
0x30,0x04,0x09,0x0D,0x01,0x0B,
0x3E,0x3F,0x98,0xD8,0x3C,0x1E,0x0F,0x07,0x83,0xC1,0xE0,0xD8,0xCF,0xE3,0xE0,
// '1'
0x31,0x04,0x08,0x0D,0x02,0x0B,
0x38,0xF8,0xD8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xFF,
// '2'
0x32,0x04,0x09,0x0D,0x01,0x0B,
0x7C,0x7F,0x21,0xC0,0x60,0x30,0x30,0x18,0x18,0x18,0x18,0x18,0x1F,0xEF,0xF0,
// '3'
0x33,0x04,0x09,0x0D,0x01,0x0B,
0x7E,0x7F,0xA0,0xE0,0x30,0x39,0xF0,0xFC,0x07,0x01,0x80,0xE0,0xFF,0xE7,0xE0,
// '4'
0x34,0x04,0x0A,0x0D,0x01,0x0B,
0x07,0x01,0xC0,0xB0,0x6C,0x13,0x08,0xC6,0x31,0x0C,0xFF,0xFF,0xF0,0x30,0x0C,0x03,0x00,
// '5'
0x35,0x04,0x08,0x0D,0x01,0x0B,
0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x47,0x03,0x03,0x03,0x87,0xFE,0x7C,
// '6'
0x36,0x04,0x09,0x0D,0x01,0x0B,
0x1E,0x1F,0x9C,0x5C,0x0C,0x06,0xF3,0xFD,0xC7,0xC1,0xE0,0xD8,0xEF,0xE1,0xE0,
// '7'
0x37,0x04,0x08,0x0D,0x01,0x0B,
0xFF,0xFF,0x06,0x06,0x06,0x0E,0x0C,0x0C,0x1C,0x18,0x18,0x38,0x30,
// '8'
0x38,0x04,0x09,0x0D,0x01,0x0B,
0x3E,0x3F,0xB8,0xF8,0x3E,0x39,0xF1,0xFD,0xC7,0xC1,0xE0,0xF8,0xEF,0xE3,0xE0,
// '9'
0x39,0x04,0x09,0x0D,0x01,0x0B,
0x3C,0x3F,0xB8,0xD8,0x3C,0x1F,0x1D,0xFE,0x7B,0x01,0x81,0xD1,0xCF,0xC3,0xC0,
// ':'
0x3A,0x08,0x02,0x09,0x02,0x06,
0xF0,0x03,0xC0,
// ';'
0x3B,0x08,0x03,0x0B,0x01,0x06,
0x6C,0x00,0x03,0x6A,0x00,
// '<'
0x3C,0x07,0x0B,0x0A,0x02,0x0F,
0x00,0x20,0x3C,0x1F,0x1F,0x0F,0x81,0xF0,0x0F,0x80,0x3E,0x01,0xE0,0x04,
// '='
0x3D,0x08,0x0B,0x06,0x02,0x0F,
0xFF,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0xC0,
// '>'
0x3E,0x07,0x0B,0x0A,0x02,0x0F,
0x80,0x1E,0x01,0xF0,0x07,0xC0,0x3E,0x07,0xC3,0xE3,0xE0,0xF0,0x10,0x00,
// '?'
0x3F,0x04,0x07,0x0D,0x01,0x0A,
0x79,0xFA,0x38,0x30,0x61,0x86,0x18,0x30,0x60,0x01,0x83,0x00,
// '@'
0x40,0x04,0x10,0x10,0x01,0x12,
0x07,0xE0,0x1F,0xF8,0x3C,0x1C,0x70,0x06,0x60,0x07,0xE3,0x63,0xC7,0xE3,0xC6,0x63,0xC6,0x66,0xC7,0xFC,0xE3,0x70,0x60,0x00,0x70,0x00,0x3C,0x30,0x1F,0xF0,0x07,0xC0,
// 'A'
0x41,0x04,0x0C,0x0D,0x00,0x0C,
0x06,0x00,0x60,0x0F,0x00,0xF0,0x19,0x81,0x98,0x19,0x83,0x0C,0x3F,0xC7,0xFE,0x60,0x66,0x06,0xC0,0x30,
// 'B'
0x42,0x04,0x09,0x0D,0x02,0x0C,
0xFC,0x7F,0xB0,0xD8,0x6C,0x37,0xF3,0xF9,0x86,0xC1,0xE0,0xF0,0xFF,0xEF,0xE0,
// 'C'
0x43,0x04,0x0B,0x0D,0x01,0x0D,
0x0F,0xC7,0xFD,0xC0,0xB0,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x0C,0x01,0xC0,0x9F,0xF0,0xFC,
// 'D'
0x44,0x04,0x0B,0x0D,0x02,0x0E,
0xFE,0x1F,0xF3,0x07,0x60,0x6C,0x07,0x80,0xF0,0x1E,0x03,0xC0,0x78,0x1B,0x07,0x7F,0xCF,0xE0,
// 'E'
0x45,0x04,0x08,0x0D,0x02,0x0B,
0xFF,0xFF,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,
// 'F'
0x46,0x04,0x08,0x0D,0x02,0x0A,
0xFF,0xFF,0xC0,0xC0,0xC0,0xFE,0xFE,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,
// 'G'
0x47,0x04,0x0B,0x0D,0x01,0x0E,
0x0F,0xC7,0xFD,0xC0,0xB0,0x0C,0x01,0x87,0xF0,0xFE,0x03,0xC0,0x6C,0x0D,0xC1,0x9F,0xE0,0xF8,
// 'H'
0x48,0x04,0x0A,0x0D,0x02,0x0E,
0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xFF,0xFF,0xFF,0x03,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xC0,
// 'I'
0x49,0x04,0x02,0x0D,0x02,0x06,
0xFF,0xFF,0xFF,0xC0,
// 'J'
0x4A,0x04,0x05,0x11,0xFF,0x06,
0x18,0xC6,0x31,0x8C,0x63,0x18,0xC6,0x31,0x8C,0xFE,0xE0,
// 'K'
0x4B,0x04,0x0B,0x0D,0x02,0x0C,
0xC1,0x98,0x63,0x18,0x66,0x0D,0x81,0xE0,0x3C,0x06,0xC0,0xCC,0x18,0xC3,0x0C,0x60,0xCC,0x0C,
// 'L'
0x4C,0x04,0x08,0x0D,0x02,0x0A,
0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,
// 'M'
0x4D,0x04,0x0C,0x0D,0x02,0x10,
0xE0,0x7F,0x0F,0xF0,0xFD,0x8B,0xD9,0xBD,0x9B,0xCF,0x3C,0xF3,0xC6,0x3C,0x63,0xC0,0x3C,0x03,0xC0,0x30,
// 'N'
0x4E,0x04,0x0A,0x0D,0x02,0x0E,
0xE0,0xF8,0x3F,0x0F,0xC3,0xD8,0xF6,0x3C,0xCF,0x1B,0xC6,0xF0,0xFC,0x3F,0x07,0xC1,0xC0,
// 'O'
0x4F,0x04,0x0C,0x0D,0x01,0x0E,
0x1F,0x83,0xFC,0x70,0xE6,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x70,0xE3,0xFC,0x1F,0x80,
// 'P'
0x50,0x04,0x08,0x0D,0x02,0x0B,
0xFC,0xFE,0xC7,0xC3,0xC3,0xC7,0xFE,0xFC,0xC0,0xC0,0xC0,0xC0,0xC0,
// 'Q'
0x51,0x04,0x0C,0x0F,0x01,0x0E,
0x1F,0x83,0xFC,0x70,0xE6,0x06,0xC0,0x3C,0x03,0xC0,0x3C,0x03,0xC0,0x36,0x06,0x70,0xE3,0xFC,0x1F,0x80,0x18,0x00,0xC0,
// 'R'
0x52,0x04,0x0A,0x0D,0x02,0x0D,
0xFC,0x3F,0x8C,0x73,0x0C,0xC3,0x31,0xCF,0xE3,0xF0,0xC6,0x30,0xCC,0x33,0x06,0xC1,0xC0,
// 'S'
0x53,0x04,0x0A,0x0D,0x01,0x0B,
0x3E,0x1F,0xCE,0x13,0x00,0xC0,0x1F,0x03,0xF0,0x0E,0x01,0x80,0x68,0x3B,0xFC,0x7E,0x00,
// 'T'
0x54,0x04,0x0C,0x0D,0x00,0x0C,
0xFF,0xFF,0xFF,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,
// 'U'
0x55,0x04,0x0A,0x0D,0x02,0x0E,
0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x3C,0x0F,0x03,0xC0,0xF0,0x36,0x19,0xFE,0x1E,0x00,
// 'V'
0x56,0x04,0x0C,0x0D,0x00,0x0C,
0xC0,0x36,0x06,0x60,0x66,0x06,0x30,0xC3,0x0C,0x19,0x81,0x98,0x19,0x80,0xF0,0x0F,0x00,0x60,0x06,0x00,
// 'W'
0x57,0x04,0x11,0x0D,0x01,0x13,
0xC1,0xC1,0xE0,0xE0,0xD8,0xF8,0xCC,0x6C,0x66,0x36,0x33,0x1B,0x18,0xD8,0xD8,0x6C,0x6C,0x36,0x36,0x1F,0x1F,0x07,0x07,0x03,0x83,0x81,0xC1,0xC0,
// 'X'
0x58,0x04,0x0B,0x0D,0x01,0x0D,
0x70,0xE6,0x18,0xE6,0x0D,0xC0,0xF0,0x1C,0x03,0x80,0x78,0x1B,0x07,0x30,0xC7,0x30,0x6E,0x0E,
// 'Y'
0x59,0x04,0x0C,0x0D,0x00,0x0C,
0xE0,0x76,0x06,0x30,0xC1,0x98,0x19,0x80,0xF0,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,0x60,0x06,0x00,
// 'Z'
0x5A,0x04,0x0B,0x0D,0x01,0x0D,
0xFF,0xFF,0xFC,0x07,0x01,0xC0,0x30,0x0E,0x03,0x80,0xE0,0x18,0x06,0x01,0xC0,0x7F,0xFF,0xFE,
// '['
0x5B,0x03,0x04,0x10,0x01,0x07,
0xFF,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFF,
// '\'
0x5C,0x04,0x06,0x0F,0x00,0x06,
0xC3,0x06,0x18,0x61,0xC3,0x0C,0x30,0xE1,0x86,0x18,0x30,0xC0,
// ']'
0x5D,0x03,0x04,0x10,0x02,0x07,
0xFF,0x33,0x33,0x33,0x33,0x33,0x33,0xFF,
// '^'
0x5E,0x04,0x0B,0x05,0x02,0x0F,
0x0E,0x03,0xE0,0xC6,0x30,0x6C,0x06,
// '_'
0x5F,0x13,0x09,0x02,0x00,0x09,
0xFF,0xFF,0xC0,
// '`'
0x60,0x03,0x04,0x03,0x02,0x09,
0xC6,0x30,
// 'a'
0x61,0x07,0x08,0x0A,0x01,0x0A,
0x3C,0x7E,0x47,0x03,0x3F,0xFF,0xC3,0xC7,0xFF,0x7B,
// 'b'
0x62,0x03,0x09,0x0E,0x02,0x0B,
0xC0,0x60,0x30,0x18,0x0D,0xE7,0xFB,0x8F,0x83,0xC1,0xE0,0xF0,0x7C,0x7F,0xF6,0xF0,
// 'c'
0x63,0x07,0x08,0x0A,0x01,0x09,
0x1E,0x7F,0x61,0xC0,0xC0,0xC0,0xC0,0x61,0x7F,0x1E,
// 'd'
0x64,0x03,0x09,0x0E,0x01,0x0B,
0x01,0x80,0xC0,0x60,0x33,0xDB,0xFF,0x8F,0x83,0xC1,0xE0,0xF0,0x7C,0x77,0xF9,0xEC,
// 'e'
0x65,0x07,0x0A,0x0A,0x01,0x0B,
0x1F,0x1F,0xE6,0x1F,0x03,0xFF,0xFF,0xFC,0x01,0x81,0x7F,0xC7,0xE0,
// 'f'
0x66,0x03,0x07,0x0E,0x00,0x06,
0x1E,0x7C,0xC1,0x8F,0xFF,0xCC,0x18,0x30,0x60,0xC1,0x83,0x06,0x00,
// 'g'
0x67,0x07,0x09,0x0E
Download .txt
gitextract_tqp4d6q6/

├── .gitignore
├── Makefile
├── README.md
├── components/
│   ├── epaper/
│   │   ├── DefaultFont.c
│   │   ├── DejaVuSans18.c
│   │   ├── DejaVuSans24.c
│   │   ├── EPD.c
│   │   ├── EPD.h
│   │   ├── EPDspi.c
│   │   ├── EPDspi.h
│   │   ├── SmallFont.c
│   │   ├── Ubuntu16.c
│   │   ├── comic24.c
│   │   ├── component.mk
│   │   ├── dejavuX.c
│   │   ├── minya24.c
│   │   └── tooney32.c
│   ├── mkspiffs/
│   │   ├── .travis.yml
│   │   ├── Makefile.projbuild
│   │   ├── component.mk
│   │   └── src/
│   │       ├── Makefile
│   │       ├── Makefile.original
│   │       ├── README.md
│   │       ├── appveyor.yml
│   │       ├── main.cpp
│   │       ├── mkspiffs
│   │       ├── spiffs/
│   │       │   ├── esp_spiffs.c
│   │       │   ├── esp_spiffs.h
│   │       │   ├── spiffs.h
│   │       │   ├── spiffs_cache.c
│   │       │   ├── spiffs_check.c
│   │       │   ├── spiffs_config.h
│   │       │   ├── spiffs_gc.c
│   │       │   ├── spiffs_hydrogen.c
│   │       │   ├── spiffs_nucleus.c
│   │       │   └── spiffs_nucleus.h
│   │       └── tclap/
│   │           ├── Arg.h
│   │           ├── ArgException.h
│   │           ├── ArgTraits.h
│   │           ├── COPYING
│   │           ├── CmdLine.h
│   │           ├── CmdLineInterface.h
│   │           ├── CmdLineOutput.h
│   │           ├── Constraint.h
│   │           ├── DocBookOutput.h
│   │           ├── HelpVisitor.h
│   │           ├── IgnoreRestVisitor.h
│   │           ├── MultiArg.h
│   │           ├── MultiSwitchArg.h
│   │           ├── OptionalUnlabeledTracker.h
│   │           ├── StandardTraits.h
│   │           ├── StdOutput.h
│   │           ├── SwitchArg.h
│   │           ├── UnlabeledMultiArg.h
│   │           ├── UnlabeledValueArg.h
│   │           ├── ValueArg.h
│   │           ├── ValuesConstraint.h
│   │           ├── VersionVisitor.h
│   │           ├── Visitor.h
│   │           ├── XorHandler.h
│   │           └── ZshCompletionOutput.h
│   ├── spidriver/
│   │   ├── component.mk
│   │   ├── spi_master_lobo.c
│   │   └── spi_master_lobo.h
│   ├── spiffs/
│   │   ├── component.mk
│   │   ├── esp_spiffs.c
│   │   ├── esp_spiffs.h
│   │   ├── list.c
│   │   ├── list.h
│   │   ├── mutex.c
│   │   ├── mutex.h
│   │   ├── spiffs.h
│   │   ├── spiffs_cache.c
│   │   ├── spiffs_check.c
│   │   ├── spiffs_config.h
│   │   ├── spiffs_gc.c
│   │   ├── spiffs_hydrogen.c
│   │   ├── spiffs_nucleus.c
│   │   ├── spiffs_nucleus.h
│   │   ├── spiffs_vfs.c
│   │   └── spiffs_vfs.h
│   └── spiffs_image/
│       ├── Makefile.projbuild
│       ├── component.mk
│       ├── image/
│       │   ├── fonts/
│       │   │   ├── BigFont.fon
│       │   │   ├── DejaVuSans12.fon
│       │   │   ├── DejaVuSans18.fon
│       │   │   ├── DejaVuSans24.fon
│       │   │   ├── DotMatrix_M.fon
│       │   │   ├── Grotesk24x48.fon
│       │   │   ├── SmallFont.fon
│       │   │   ├── Ubuntu.fon
│       │   │   ├── arial_bold.fon
│       │   │   ├── ocrfont.c
│       │   │   └── swiss721_outline.fon
│       │   └── spiffs.info
│       └── spiffs_image.img
├── main/
│   ├── Kconfig.projbuild
│   ├── component.mk
│   ├── ePaper.c
│   ├── ePaper.h
│   ├── img1.h
│   ├── img2.h
│   ├── img3.h
│   └── img_hacking.c
├── partitions_example.csv
└── sdkconfig.defaults
Download .txt
SYMBOL INDEX (619 symbols across 54 files)

FILE: components/epaper/EPD.c
  type propFont (line 86) | typedef struct {
  function drawPixel (line 107) | static void drawPixel(int x, int y, uint8_t val)
  function EPD_pushColorRep (line 132) | static void EPD_pushColorRep(int x1, int y1, int x2, int y2, color_t color)
  function EPD_compare_colors (line 169) | int EPD_compare_colors(color_t c1, color_t c2)
  function _drawPixel (line 178) | static void _drawPixel(int16_t x, int16_t y, color_t color) {
  function EPD_drawPixel (line 185) | void EPD_drawPixel(int16_t x, int16_t y, color_t color) {
  function _drawFastVLine (line 191) | static void _drawFastVLine(int16_t x, int16_t y, int16_t h, color_t colo...
  function _drawFastHLine (line 205) | static void _drawFastHLine(int16_t x, int16_t y, int16_t w, color_t colo...
  function EPD_drawFastVLine (line 220) | void EPD_drawFastVLine(int16_t x, int16_t y, int16_t h, color_t color) {
  function EPD_drawFastHLine (line 225) | void EPD_drawFastHLine(int16_t x, int16_t y, int16_t w, color_t color) {
  function _drawLine (line 232) | static void _drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, co...
  function EPD_drawLine (line 292) | void EPD_drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, color_...
  function _fillRect (line 299) | static void _fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_...
  function EPD_fillRect (line 322) | void EPD_fillRect(int16_t x, int16_t y, int16_t w, int16_t h, color_t co...
  function EPD_fillScreen (line 327) | void EPD_fillScreen(color_t color) {
  function EPD_fillWindow (line 335) | void EPD_fillWindow(color_t color) {
  function _drawRect (line 345) | static void _drawRect(uint16_t x1,uint16_t y1,uint16_t w,uint16_t h, col...
  function EPD_drawRect (line 353) | void EPD_drawRect(uint16_t x1,uint16_t y1,uint16_t w,uint16_t h, color_t...
  function drawCircleHelper (line 358) | static void drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t ...
  function fillCircleHelper (line 396) | static void fillCircleHelper(int16_t x0, int16_t y0, int16_t r,	uint8_t ...
  function EPD_drawRoundRect (line 427) | void EPD_drawRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uin...
  function EPD_fillRoundRect (line 447) | void EPD_fillRoundRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uin...
  function _drawLineByAngle (line 464) | static void _drawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16...
  function _DrawLineByAngle (line 474) | static void _DrawLineByAngle(int16_t x, int16_t y, int16_t angle, uint16...
  function EPD_drawLineByAngle (line 484) | void EPD_drawLineByAngle(uint16_t x, uint16_t y, uint16_t start, uint16_...
  function _drawTriangle (line 496) | static void _drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_...
  function EPD_drawTriangle (line 504) | void EPD_drawTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1...
  function _fillTriangle (line 520) | static void _fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_...
  function EPD_fillTriangle (line 597) | void EPD_fillTriangle(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1...
  function EPD_drawCircle (line 607) | void EPD_drawCircle(int16_t x, int16_t y, int radius, color_t color) {
  function EPD_fillCircle (line 641) | void EPD_fillCircle(int16_t x, int16_t y, int radius, color_t color) {
  function _draw_ellipse_section (line 650) | static void _draw_ellipse_section(uint16_t x, uint16_t y, uint16_t x0, u...
  function EPD_drawEllipse (line 663) | void EPD_drawEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry,...
  function _draw_filled_ellipse_section (line 750) | static void _draw_filled_ellipse_section(uint16_t x, uint16_t y, uint16_...
  function EPD_fillEllipse (line 763) | void EPD_fillEllipse(uint16_t x0, uint16_t y0, uint16_t rx, uint16_t ry,...
  function _fillArcOffsetted (line 853) | static void _fillArcOffsetted(uint16_t cx, uint16_t cy, uint16_t radius,...
  function EPD_drawArc (line 894) | void EPD_drawArc(uint16_t cx, uint16_t cy, uint16_t r, uint16_t th, floa...
  function EPD_drawPolygon (line 941) | void EPD_drawPolygon(int cx, int cy, int sides, int diameter, color_t co...
  function load_file_font (line 1038) | static int load_file_font(const char * fontfile, int info)
  function compile_font_file (line 1169) | int compile_font_file(char *fontfile, uint8_t dbg)
  function getFontCharacters (line 1351) | void getFontCharacters(uint8_t *buf)
  function getMaxWidthHeight (line 1397) | static void getMaxWidthHeight()
  function getCharPtr (line 1429) | static uint8_t getCharPtr(uint8_t c) {
  function EPD_setFont (line 1500) | void EPD_setFont(uint8_t font, const char *font_file)
  function printProportionalChar (line 1560) | static int printProportionalChar(int x, int y) {
  function printChar (line 1592) | static void printChar(uint8_t c, int x, int y) {
  function rotatePropChar (line 1625) | static int rotatePropChar(int x, int y, int offset) {
  function rotateChar (line 1654) | static void rotateChar(uint8_t c, int x, int y, int pos) {
  function _7seg_width (line 1688) | static int _7seg_width()
  function _7seg_height (line 1694) | static int _7seg_height()
  function EPD_getStringWidth (line 1702) | int EPD_getStringWidth(char* str)
  function EPD_clearStringRect (line 1722) | void EPD_clearStringRect(int x, int y, char *str)
  function barVert (line 1759) | static void barVert(int16_t x, int16_t y, int16_t w, int16_t l, color_t ...
  function barHor (line 1771) | static void barHor(int16_t x, int16_t y, int16_t w, int16_t l, color_t c...
  function _draw7seg (line 1783) | static void _draw7seg(int16_t x, int16_t y, int8_t num, int16_t w, int16...
  function EPD_print (line 1871) | void EPD_print(char *st, int x, int y) {
  function EPD_setclipwin (line 1992) | void EPD_setclipwin(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
  function EPD_resetclipwin (line 2006) | void EPD_resetclipwin()
  function set_7seg_font_atrib (line 2015) | void set_7seg_font_atrib(uint8_t l, uint8_t w, int outline, color_t colo...
  function EPD_getfontsize (line 2031) | int EPD_getfontsize(int *width, int* height)
  function EPD_getfontheight (line 2052) | int EPD_getfontheight()
  function EPD_saveClipWin (line 2060) | void EPD_saveClipWin()
  function EPD_restoreClipWin (line 2069) | void EPD_restoreClipWin()
  type JPGIODEV (line 2087) | typedef struct {
  function UINT (line 2099) | static UINT tjd_input (
  function UINT (line 2121) | static UINT tjd_buf_input (
  function UINT (line 2147) | static UINT tjd_output (
  function EPD_jpg_image (line 2239) | int EPD_jpg_image(int x, int y, uint8_t scale, char *fname, uint8_t *buf...

FILE: components/epaper/EPD.h
  type color_t (line 13) | typedef uint8_t color_t;
  type dispWin_t (line 15) | typedef struct {
  type Font_t (line 22) | typedef struct {

FILE: components/epaper/EPDspi.c
  function _dma_send (line 78) | static void IRAM_ATTR _dma_send(uint8_t *data, uint32_t size)
  function _direct_send (line 107) | static void IRAM_ATTR _direct_send(uint8_t *data, uint32_t len, uint8_t ...
  function SPI_send_data (line 152) | static void IRAM_ATTR SPI_send_data(uint8_t *data, uint32_t len, uint8_t...
  function SPI_Write (line 171) | void IRAM_ATTR SPI_Write(uint8_t value)
  function ReadBusy (line 188) | static uint8_t ReadBusy()
  function WaitBusy (line 198) | static uint8_t WaitBusy()
  function EPD_WriteCMD (line 208) | static void EPD_WriteCMD(uint8_t command)
  function EPD_WriteCMD_p1 (line 217) | static void EPD_WriteCMD_p1(uint8_t command,uint8_t para)
  function EPD_PowerOn (line 229) | void EPD_PowerOn()
  function EPD_PowerOff (line 245) | void EPD_PowerOff()
  function EPD_Write (line 270) | static void EPD_Write(uint8_t *value, uint8_t datalen)
  function EPD_WriteDispRam (line 291) | static void EPD_WriteDispRam(uint8_t XSize, uint16_t YSize,	uint8_t *Dis...
  function EPD_WriteDispRamMono (line 307) | static void EPD_WriteDispRamMono(uint8_t XSize, uint16_t YSize,	uint8_t ...
  function EPD_SetRamArea (line 338) | static void EPD_SetRamArea(uint8_t Xstart, uint8_t Xend, uint16_t Ystart...
  function EPD_SetRamPointer (line 369) | static void EPD_SetRamPointer(uint8_t addrX, uint16_t addrY)
  function part_display (line 389) | static void part_display(uint8_t RAM_XST, uint8_t RAM_XEND ,uint16_t RAM...
  function EPD_Init (line 397) | static void EPD_Init()
  function EPD_UpdateFull (line 439) | static void EPD_UpdateFull(void)
  function EPD_Update_Part (line 466) | static void EPD_Update_Part(void)
  function EPD_init_Full (line 495) | static void EPD_init_Full(void)
  function EPD_init_Part (line 506) | static void EPD_init_Part(void)
  function EPD_Dis_Full (line 518) | static void EPD_Dis_Full(uint8_t *DisBuffer,uint8_t type)
  function EPD_Dis_Part (line 546) | static void EPD_Dis_Part(uint8_t xStart, uint8_t xEnd, uint16_t yStart, ...
  function EPD_DisplayClearFull (line 570) | void EPD_DisplayClearFull()
  function EPD_DisplayClearPart (line 595) | void EPD_DisplayClearPart()
  function EPD_DisplaySetFull (line 618) | void EPD_DisplaySetFull(uint8_t val)
  function EPD_DisplaySetPart (line 632) | void EPD_DisplaySetPart(int xStart, int xEnd, uint8_t yStart, uint8_t yE...
  function EPD_DisplayFull (line 646) | void EPD_DisplayFull(uint8_t *DisBuffer)
  function EPD_DisplayPart (line 660) | void EPD_DisplayPart(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd,...
  function EPD_Cls (line 674) | void EPD_Cls()
  function EPD_gsUpdate (line 683) | void EPD_gsUpdate(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd, ui...
  function EPD_Update (line 732) | void EPD_Update(int xStart, int xEnd, uint8_t yStart, uint8_t yEnd)
  function EPD_UpdateScreen (line 743) | void EPD_UpdateScreen()
  function EPD_wait (line 749) | void EPD_wait(uint32_t ms)

FILE: components/mkspiffs/src/main.cpp
  type Action (line 41) | enum Action { ACTION_NONE, ACTION_PACK, ACTION_UNPACK, ACTION_LIST, ACTI...
  function s32_t (line 51) | static s32_t api_spiffs_read(u32_t addr, u32_t size, u8_t *dst){
  function s32_t (line 56) | static s32_t api_spiffs_write(u32_t addr, u32_t size, u8_t *src){
  function s32_t (line 61) | static s32_t api_spiffs_erase(u32_t addr, u32_t size){
  function spiffsTryMount (line 72) | int spiffsTryMount(){
  function spiffsMount (line 98) | bool spiffsMount(){
  function spiffsFormat (line 105) | bool spiffsFormat(){
  function spiffsUnmount (line 114) | void spiffsUnmount(){
  function addDir (line 120) | int addDir(const char* name) {
  function addFile (line 156) | int addFile(char* name, const char* path) {
  function addFiles (line 221) | int addFiles(const char* dirname, const char* subPath) {
  function listFiles (line 293) | void listFiles() {
  function dirExists (line 316) | bool dirExists(const char* path) {
  function unpackFile (line 361) | bool unpackFile(spiffs_dirent *spiffsFile, const char *destPath) {
  function unpackFiles (line 396) | bool unpackFiles(std::string sDest) {
  function actionPack (line 469) | int actionPack() {
  function actionUnpack (line 499) | int actionUnpack(void) {
  function actionList (line 531) | int actionList() {
  function actionVisualize (line 551) | int actionVisualize() {
  function processArgs (line 575) | void processArgs(int argc, const char** argv) {
  function main (line 619) | int main(int argc, const char * argv[]) {

FILE: components/mkspiffs/src/spiffs/esp_spiffs.c
  function s32_t (line 39) | s32_t esp32_spi_flash_read(u32_t addr, u32_t size, u8_t *dst) {
  function s32_t (line 83) | s32_t esp32_spi_flash_write(u32_t addr, u32_t size, const u8_t *src) {
  function s32_t (line 132) | s32_t IRAM_ATTR esp32_spi_flash_erase(u32_t addr, u32_t size) {

FILE: components/mkspiffs/src/spiffs/spiffs.h
  type s16_t (line 69) | typedef s16_t spiffs_file;
  type u16_t (line 71) | typedef u16_t spiffs_flags;
  type u16_t (line 73) | typedef u16_t spiffs_mode;
  type u8_t (line 75) | typedef u8_t spiffs_obj_type;
  type spiffs_t (line 77) | struct spiffs_t
  type s32_t (line 82) | typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size...
  type s32_t (line 84) | typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t siz...
  type s32_t (line 86) | typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
  type s32_t (line 91) | typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
  type s32_t (line 93) | typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
  type s32_t (line 95) | typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
  type spiffs_check_type (line 99) | typedef enum {
  type spiffs_check_report (line 106) | typedef enum {
  type spiffs_t (line 118) | struct spiffs_t
  type spiffs_fileop_type (line 126) | typedef enum {
  type spiffs_t (line 136) | struct spiffs_t
  type spiffs_config (line 197) | typedef struct {
  type spiffs (line 228) | typedef struct spiffs_t {
  type spiffs_stat (line 294) | typedef struct {
  type spiffs_dirent (line 305) | struct spiffs_dirent {
  type spiffs_DIR (line 316) | typedef struct {
  type spiffs_ix_map (line 324) | typedef struct {
  type spiffs_dirent (line 432) | struct spiffs_dirent
  type spiffs_dirent (line 587) | struct spiffs_dirent
  type spiffs_dirent (line 587) | struct spiffs_dirent

FILE: components/mkspiffs/src/spiffs/spiffs_cache.c
  function spiffs_cache_page (line 14) | static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_...
  function s32_t (line 33) | static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
  function s32_t (line 59) | static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask,...
  function spiffs_cache_page (line 89) | static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
  function spiffs_cache_drop_page (line 110) | void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) {
  function s32_t (line 120) | s32_t spiffs_phys_rd(
  function s32_t (line 180) | s32_t spiffs_phys_wr(
  function spiffs_cache_page (line 223) | spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
  function spiffs_cache_page (line 246) | spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_f...
  function spiffs_cache_fd_release (line 263) | void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
  function spiffs_cache_init (line 281) | void spiffs_cache_init(spiffs *fs) {

FILE: components/mkspiffs/src/spiffs/spiffs_check.c
  function s32_t (line 46) | static s32_t spiffs_object_get_data_page_index_reference(
  function s32_t (line 77) | static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spi...
  function s32_t (line 91) | static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spif...
  function s32_t (line 156) | static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
  function s32_t (line 173) | static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_o...
  function s32_t (line 445) | static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spi...
  function s32_t (line 475) | s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
  function s32_t (line 509) | static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
  function s32_t (line 851) | s32_t spiffs_page_consistency_check(spiffs *fs) {
  function spiffs_object_index_search (line 866) | static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
  function s32_t (line 878) | static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_...
  function s32_t (line 973) | s32_t spiffs_object_index_consistency_check(spiffs *fs) {

FILE: components/mkspiffs/src/spiffs/spiffs_config.h
  type s32_t (line 23) | typedef signed int s32_t;
  type u32_t (line 24) | typedef unsigned int u32_t;
  type s16_t (line 25) | typedef signed short s16_t;
  type u16_t (line 26) | typedef unsigned short u16_t;
  type s8_t (line 27) | typedef signed char s8_t;
  type u8_t (line 28) | typedef unsigned char u8_t;
  type u16_t (line 348) | typedef u16_t spiffs_block_ix;
  type u16_t (line 351) | typedef u16_t spiffs_page_ix;
  type u16_t (line 355) | typedef u16_t spiffs_obj_id;
  type u16_t (line 359) | typedef u16_t spiffs_span_ix;

FILE: components/mkspiffs/src/spiffs/spiffs_gc.c
  function s32_t (line 9) | static s32_t spiffs_gc_erase_block(
  function s32_t (line 32) | s32_t spiffs_gc_quick(
  function s32_t (line 109) | s32_t spiffs_gc_check(
  function s32_t (line 199) | s32_t spiffs_gc_erase_page_stats(
  function s32_t (line 236) | s32_t spiffs_gc_find_candidate(
  type spiffs_gc_clean_state (line 347) | typedef enum {
  type spiffs_gc (line 354) | typedef struct {
  function s32_t (line 377) | s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {

FILE: components/mkspiffs/src/spiffs/spiffs_hydrogen.c
  function u32_t (line 24) | u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
  function u32_t (line 28) | u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
  function u8_t (line 34) | u8_t SPIFFS_mounted(spiffs *fs) {
  function s32_t (line 38) | s32_t SPIFFS_format(spiffs *fs) {
  function s32_t (line 71) | s32_t SPIFFS_probe_fs(spiffs_config *config) {
  function s32_t (line 78) | s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
  function SPIFFS_unmount (line 150) | void SPIFFS_unmount(spiffs *fs) {
  function s32_t (line 169) | s32_t SPIFFS_errno(spiffs *fs) {
  function SPIFFS_clearerr (line 173) | void SPIFFS_clearerr(spiffs *fs) {
  function s32_t (line 177) | s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
  function spiffs_file (line 201) | spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags...
  function spiffs_file (line 281) | spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, s...
  function spiffs_file (line 313) | spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spif...
  function s32_t (line 359) | static s32_t spiffs_hydro_read(spiffs *fs, spiffs_file fh, void *buf, s3...
  function s32_t (line 413) | s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
  function s32_t (line 423) | static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u3...
  function s32_t (line 446) | s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
  function s32_t (line 574) | s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
  function s32_t (line 623) | s32_t SPIFFS_remove(spiffs *fs, const char *path) {
  function s32_t (line 665) | s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
  function s32_t (line 699) | static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file...
  function s32_t (line 725) | s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
  function s32_t (line 746) | s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
  function s32_t (line 772) | static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
  function s32_t (line 805) | s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
  function s32_t (line 821) | s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
  function s32_t (line 841) | s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_pa...
  function s32_t (line 896) | s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta) {
  function s32_t (line 933) | s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta) {
  function spiffs_DIR (line 967) | spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
  function s32_t (line 986) | static s32_t spiffs_read_dir_v(
  type spiffs_dirent (line 1023) | struct spiffs_dirent
  type spiffs_dirent (line 1023) | struct spiffs_dirent
  type spiffs_dirent (line 1033) | struct spiffs_dirent
  function s32_t (line 1057) | s32_t SPIFFS_closedir(spiffs_DIR *d) {
  function s32_t (line 1063) | s32_t SPIFFS_check(spiffs *fs) {
  function s32_t (line 1086) | s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
  function s32_t (line 1110) | s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
  function s32_t (line 1129) | s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
  function s32_t (line 1147) | s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
  function s32_t (line 1170) | s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
  function s32_t (line 1193) | s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_...
  function s32_t (line 1202) | s32_t SPIFFS_ix_map(spiffs *fs,  spiffs_file fh, spiffs_ix_map *map,
  function s32_t (line 1235) | s32_t SPIFFS_ix_unmap(spiffs *fs,  spiffs_file fh) {
  function s32_t (line 1257) | s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) {
  function s32_t (line 1319) | s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) {
  function s32_t (line 1325) | s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entri...
  function s32_t (line 1333) | s32_t SPIFFS_vis(spiffs *fs) {

FILE: components/mkspiffs/src/spiffs/spiffs_nucleus.c
  function s32_t (line 4) | static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_pa...
  function s32_t (line 33) | static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_p...
  function s32_t (line 64) | s32_t spiffs_phys_rd(
  function s32_t (line 72) | s32_t spiffs_phys_wr(
  function s32_t (line 83) | s32_t spiffs_phys_cpy(
  function s32_t (line 124) | s32_t spiffs_obj_lu_find_entry_visitor(
  function s32_t (line 226) | s32_t spiffs_erase_block(
  function s32_t (line 268) | s32_t spiffs_probe(
  function s32_t (line 320) | static s32_t spiffs_obj_lu_scan_v(
  function s32_t (line 348) | s32_t spiffs_obj_lu_scan(
  function s32_t (line 449) | s32_t spiffs_obj_lu_find_free(
  function s32_t (line 485) | s32_t spiffs_obj_lu_find_id(
  function s32_t (line 501) | static s32_t spiffs_obj_lu_find_id_and_span_v(
  function s32_t (line 527) | s32_t spiffs_obj_lu_find_id_and_span(
  function s32_t (line 566) | s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
  function spiffs_update_ix_map (line 606) | static void spiffs_update_ix_map(spiffs *fs,
  type spiffs_ix_map_populate_state (line 658) | typedef struct {
  function s32_t (line 665) | static s32_t spiffs_populate_ix_map_v(
  function s32_t (line 712) | s32_t spiffs_populate_ix_map(spiffs *fs, spiffs_fd *fd, u32_t vec_entry_...
  function s32_t (line 753) | s32_t spiffs_page_allocate_data(
  function s32_t (line 812) | s32_t spiffs_page_move(
  function s32_t (line 876) | s32_t spiffs_page_delete(
  function s32_t (line 907) | s32_t spiffs_object_create(
  function s32_t (line 974) | s32_t spiffs_object_update_index_hdr(
  function spiffs_cb_object_event (line 1036) | void spiffs_cb_object_event(
  function s32_t (line 1117) | s32_t spiffs_object_open_by_id(
  function s32_t (line 1135) | s32_t spiffs_object_open_by_page(
  function s32_t (line 1175) | s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_...
  function s32_t (line 1422) | s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_...
  function s32_t (line 1624) | static s32_t spiffs_object_find_object_index_header_by_name_v(
  function s32_t (line 1654) | s32_t spiffs_object_find_object_index_header_by_name(
  function s32_t (line 1690) | s32_t spiffs_object_truncate(
  type spiffs_free_obj_id_state (line 2022) | typedef struct {
  function s32_t (line 2029) | static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_...
  function s32_t (line 2062) | static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs...
  function s32_t (line 2096) | s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, ...
  function u32_t (line 2193) | static u32_t spiffs_hash(spiffs *fs, const u8_t *name) {
  function s32_t (line 2205) | s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) {
  function s32_t (line 2283) | s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
  function s32_t (line 2299) | s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
  function spiffs_fd_temporal_cache_rehash (line 2312) | void spiffs_fd_temporal_cache_rehash(

FILE: components/mkspiffs/src/spiffs/spiffs_nucleus.h
  type spiffs_cache_page (line 376) | typedef struct {
  type spiffs_cache (line 404) | typedef struct {
  type spiffs_fd (line 416) | typedef struct {
  type spiffs_page_header (line 458) | typedef struct __attribute(( packed )) {
  type SPIFFS_ALIGNED_OBJECT_INDEX_TABLES (line 468) | struct __attribute(( packed ))
  type spiffs_page_object_ix (line 490) | typedef struct __attribute(( packed )) {
  type s32_t (line 496) | typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_b...

FILE: components/mkspiffs/src/tclap/Arg.h
  type std (line 43) | typedef std::istringstream istringstream;
  type std (line 46) | typedef std::istrstream istringstream;
  function namespace (line 57) | namespace TCLAP {
  function Arg (line 503) | inline Arg::~Arg() { }
  function a (line 546) | inline bool Arg::operator==(const Arg& a) const
  function setRequireLabel (line 585) | inline void Arg::setRequireLabel( const std::string& s)
  function argMatches (line 590) | inline bool Arg::argMatches( const std::string& argFlag ) const
  function trimFlag (line 620) | inline void Arg::trimFlag(std::string& flag, std::string& value) const
  function _hasBlanks (line 641) | inline bool Arg::_hasBlanks( const std::string& s ) const
  function forceRequired (line 650) | inline void Arg::forceRequired()
  function xorSet (line 655) | inline void Arg::xorSet()
  function addToList (line 664) | inline void Arg::addToList( std::list<Arg*>& argList ) const
  function allowMore (line 669) | inline bool Arg::allowMore()
  function acceptsMultipleValues (line 674) | inline bool Arg::acceptsMultipleValues()
  function reset (line 679) | inline void Arg::reset()

FILE: components/mkspiffs/src/tclap/ArgException.h
  function namespace (line 30) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/ArgTraits.h
  type StringLikeTrait (line 57) | struct StringLikeTrait {

FILE: components/mkspiffs/src/tclap/CmdLine.h
  function namespace (line 51) | namespace TCLAP {
  function _emptyCombined (line 511) | inline bool CmdLine::_emptyCombined(const std::string& s)
  function missingArgsException (line 523) | inline void CmdLine::missingArgsException()
  function deleteOnExit (line 550) | inline void CmdLine::deleteOnExit(Arg* ptr)
  function deleteOnExit (line 555) | inline void CmdLine::deleteOnExit(Visitor* ptr)
  function CmdLineOutput (line 560) | inline CmdLineOutput* CmdLine::getOutput()
  function setOutput (line 565) | inline void CmdLine::setOutput(CmdLineOutput* co)
  function std (line 573) | inline std::string& CmdLine::getVersion()
  function std (line 578) | inline std::string& CmdLine::getProgramName()
  function std (line 583) | inline std::list<Arg*>& CmdLine::getArgList()
  function XorHandler (line 588) | inline XorHandler& CmdLine::getXorHandler()
  function getDelimiter (line 593) | inline char CmdLine::getDelimiter()
  function std (line 598) | inline std::string& CmdLine::getMessage()
  function hasHelpAndVersion (line 603) | inline bool CmdLine::hasHelpAndVersion()
  function setExceptionHandling (line 608) | inline void CmdLine::setExceptionHandling(const bool state)
  function reset (line 618) | inline void CmdLine::reset()

FILE: components/mkspiffs/src/tclap/CmdLineInterface.h
  function namespace (line 33) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/CmdLineOutput.h
  function namespace (line 33) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/Constraint.h
  function namespace (line 32) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/DocBookOutput.h
  function namespace (line 37) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/HelpVisitor.h
  function namespace (line 29) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/IgnoreRestVisitor.h
  function namespace (line 29) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/MultiArg.h
  function namespace (line 32) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/MultiSwitchArg.h
  function namespace (line 33) | namespace TCLAP {
  function getValue (line 153) | inline int MultiSwitchArg::getValue() { return _value; }
  function processArg (line 155) | inline bool MultiSwitchArg::processArg(int *i, std::vector<std::string>&...
  function reset (line 204) | inline void

FILE: components/mkspiffs/src/tclap/OptionalUnlabeledTracker.h
  function namespace (line 29) | namespace TCLAP {
  function check (line 48) | inline void OptionalUnlabeledTracker::check( bool req, const std::string...

FILE: components/mkspiffs/src/tclap/StandardTraits.h
  function namespace (line 42) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/StdOutput.h
  function namespace (line 37) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/SwitchArg.h
  function namespace (line 32) | namespace TCLAP {
  function getValue (line 158) | inline bool SwitchArg::getValue() { return _value; }
  function lastCombined (line 160) | inline bool SwitchArg::lastCombined(std::string& combinedSwitches )
  function combinedSwitchesMatch (line 169) | inline bool SwitchArg::combinedSwitchesMatch(std::string& combinedSwitch...
  function commonProcessing (line 204) | inline void SwitchArg::commonProcessing()
  function processArg (line 223) | inline bool SwitchArg::processArg(int *i, std::vector<std::string>& args)
  function reset (line 255) | inline void SwitchArg::reset()

FILE: components/mkspiffs/src/tclap/UnlabeledMultiArg.h
  function namespace (line 32) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/UnlabeledValueArg.h
  function namespace (line 34) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/ValueArg.h
  function namespace (line 32) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/ValuesConstraint.h
  function virtual (line 65) | virtual ~ValuesConstraint() {}
  function virtual (line 70) | virtual std::string description() const;

FILE: components/mkspiffs/src/tclap/VersionVisitor.h
  function namespace (line 31) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/Visitor.h
  function namespace (line 26) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/XorHandler.h
  function namespace (line 32) | namespace TCLAP {

FILE: components/mkspiffs/src/tclap/ZshCompletionOutput.h
  function namespace (line 37) | namespace TCLAP {

FILE: components/spidriver/spi_master_lobo.c
  type spi_signal_conn_t (line 101) | typedef struct {
  function spi_lobo_setup_dma_desc_links (line 203) | void spi_lobo_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uin...
  function spi_lobo_dmaworkaround_req_reset (line 246) | bool IRAM_ATTR spi_lobo_dmaworkaround_req_reset(int dmachan, dmaworkarou...
  function spi_lobo_dmaworkaround_reset_in_progress (line 268) | bool IRAM_ATTR spi_lobo_dmaworkaround_reset_in_progress()
  function spi_lobo_dmaworkaround_idle (line 274) | void IRAM_ATTR spi_lobo_dmaworkaround_idle(int dmachan)
  function spi_lobo_dmaworkaround_transfer_active (line 291) | void IRAM_ATTR spi_lobo_dmaworkaround_transfer_active(int dmachan)
  function spi_lobo_periph_claim (line 300) | bool spi_lobo_periph_claim(spi_lobo_host_device_t host)
  function spi_lobo_periph_free (line 309) | bool spi_lobo_periph_free(spi_lobo_host_device_t host)
  function spi_lobo_dma_chan_claim (line 317) | bool spi_lobo_dma_chan_claim (int dma_chan)
  function spi_lobo_dma_chan_free (line 335) | bool spi_lobo_dma_chan_free(int dma_chan)
  function esp_err_t (line 356) | static esp_err_t spi_lobo_bus_initialize(spi_lobo_host_device_t host, sp...
  function esp_err_t (line 505) | static esp_err_t spi_lobo_bus_free(spi_lobo_host_device_t host, int dofree)
  function esp_err_t (line 534) | esp_err_t spi_lobo_bus_add_device(spi_lobo_host_device_t host, spi_lobo_...
  function esp_err_t (line 623) | esp_err_t spi_lobo_bus_remove_device(spi_lobo_device_handle_t handle)
  function spi_freq_for_pre_n (line 647) | static int IRAM_ATTR spi_freq_for_pre_n(int fapb, int pre, int n) {
  function spi_set_clock (line 656) | static int IRAM_ATTR spi_set_clock(spi_dev_t *hw, int fapb, int hz, int ...
  function esp_err_t (line 711) | esp_err_t IRAM_ATTR spi_lobo_device_select(spi_lobo_device_handle_t hand...
  function esp_err_t (line 827) | esp_err_t IRAM_ATTR spi_lobo_device_deselect(spi_lobo_device_handle_t ha...
  function esp_err_t (line 854) | esp_err_t IRAM_ATTR spi_lobo_device_TakeSemaphore(spi_lobo_device_handle...
  function spi_lobo_device_GiveSemaphore (line 861) | void IRAM_ATTR spi_lobo_device_GiveSemaphore(spi_lobo_device_handle_t ha...
  function spi_lobo_get_speed (line 867) | uint32_t spi_lobo_get_speed(spi_lobo_device_handle_t handle)
  function spi_lobo_set_speed (line 880) | uint32_t spi_lobo_set_speed(spi_lobo_device_handle_t handle, uint32_t sp...
  function spi_lobo_uses_native_pins (line 898) | bool spi_lobo_uses_native_pins(spi_lobo_device_handle_t handle)
  function spi_lobo_get_native_pins (line 904) | void spi_lobo_get_native_pins(int host, int *sdi, int *sdo, int *sck)
  function esp_err_t (line 921) | esp_err_t IRAM_ATTR spi_lobo_transfer_data(spi_lobo_device_handle_t hand...

FILE: components/spidriver/spi_master_lobo.h
  type spi_lobo_host_device_t (line 41) | typedef enum {
  type spi_lobo_bus_config_t (line 55) | typedef struct {
  type spi_lobo_transaction_t (line 75) | typedef struct spi_lobo_transaction_t spi_lobo_transaction_t;
  type spi_lobo_device_interface_config_t (line 81) | typedef struct {
  type spi_lobo_transaction_t (line 108) | struct spi_lobo_transaction_t {
  type spi_lobo_device_t (line 129) | typedef struct spi_lobo_device_t spi_lobo_device_t;
  type spi_lobo_host_t (line 131) | typedef struct {
  type spi_lobo_device_t (line 146) | struct spi_lobo_device_t {
  type spi_lobo_device_t (line 153) | typedef spi_lobo_device_t* spi_lobo_device_handle_t;
  type spi_lobo_host_t (line 154) | typedef spi_lobo_host_t* spi_lobo_host_handle_t;
  type spi_lobo_device_interface_config_t (line 155) | typedef spi_lobo_device_interface_config_t* spi_lobo_device_interface_co...

FILE: components/spiffs/esp_spiffs.c
  function s32_t (line 39) | s32_t IRAM_ATTR esp32_spi_flash_read(u32_t addr, u32_t size, u8_t *dst) {
  function s32_t (line 83) | s32_t IRAM_ATTR esp32_spi_flash_write(u32_t addr, u32_t size, const u8_t...
  function s32_t (line 132) | s32_t IRAM_ATTR esp32_spi_flash_erase(u32_t addr, u32_t size) {

FILE: components/spiffs/list.c
  function list_init (line 39) | void list_init(struct list *list, int first_index) {
  function list_add (line 53) | int list_add(struct list *list, void *item, int *item_index) {
  function list_get (line 112) | int IRAM_ATTR list_get(struct list *list, int index, void **item) {
  function list_remove (line 152) | int list_remove(struct list *list, int index, int destroy) {
  function list_first (line 188) | int IRAM_ATTR list_first(struct list *list) {
  function list_next (line 206) | int IRAM_ATTR list_next(struct list *list, int index) {
  function list_destroy (line 234) | void list_destroy(struct list *list, int items) {

FILE: components/spiffs/list.h
  type list (line 36) | struct list {
  type list_index (line 44) | struct list_index {
  type list (line 51) | struct list
  type list (line 52) | struct list
  type list (line 53) | struct list
  type list (line 54) | struct list
  type list (line 55) | struct list
  type list (line 56) | struct list
  type list (line 57) | struct list

FILE: components/spiffs/mutex.c
  function _mtx_init (line 45) | void _mtx_init() {
  function mtx_init (line 48) | void mtx_init(struct mtx *mutex, const char *name, const char *type, int...
  function mtx_lock (line 62) | void IRAM_ATTR mtx_lock(struct mtx *mutex) {
  function mtx_trylock (line 72) | int mtx_trylock(struct	mtx *mutex) {
  function mtx_unlock (line 80) | void IRAM_ATTR mtx_unlock(struct mtx *mutex) {
  function mtx_destroy (line 90) | void mtx_destroy(struct	mtx *mutex) {

FILE: components/spiffs/mutex.h
  type mtx (line 41) | struct mtx {
  type mtx (line 46) | struct mtx
  type mtx (line 47) | struct mtx
  type mtx (line 48) | struct	mtx
  type mtx (line 49) | struct mtx
  type mtx (line 50) | struct	mtx

FILE: components/spiffs/spiffs.h
  type s16_t (line 69) | typedef s16_t spiffs_file;
  type u16_t (line 71) | typedef u16_t spiffs_flags;
  type u16_t (line 73) | typedef u16_t spiffs_mode;
  type u8_t (line 75) | typedef u8_t spiffs_obj_type;
  type spiffs_t (line 77) | struct spiffs_t
  type s32_t (line 82) | typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size...
  type s32_t (line 84) | typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t siz...
  type s32_t (line 86) | typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
  type s32_t (line 91) | typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
  type s32_t (line 93) | typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
  type s32_t (line 95) | typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
  type spiffs_check_type (line 99) | typedef enum {
  type spiffs_check_report (line 106) | typedef enum {
  type spiffs_t (line 118) | struct spiffs_t
  type spiffs_fileop_type (line 126) | typedef enum {
  type spiffs_t (line 136) | struct spiffs_t
  type spiffs_config (line 197) | typedef struct {
  type spiffs (line 228) | typedef struct spiffs_t {
  type spiffs_stat (line 294) | typedef struct {
  type spiffs_dirent (line 305) | struct spiffs_dirent {
  type spiffs_DIR (line 316) | typedef struct {
  type spiffs_ix_map (line 324) | typedef struct {
  type spiffs_dirent (line 432) | struct spiffs_dirent
  type spiffs_dirent (line 587) | struct spiffs_dirent
  type spiffs_dirent (line 587) | struct spiffs_dirent

FILE: components/spiffs/spiffs_cache.c
  function spiffs_cache_page (line 14) | static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_...
  function s32_t (line 33) | static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
  function s32_t (line 59) | static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask,...
  function spiffs_cache_page (line 89) | static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
  function spiffs_cache_drop_page (line 110) | void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) {
  function s32_t (line 120) | s32_t spiffs_phys_rd(
  function s32_t (line 180) | s32_t spiffs_phys_wr(
  function spiffs_cache_page (line 223) | spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
  function spiffs_cache_page (line 246) | spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_f...
  function spiffs_cache_fd_release (line 263) | void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
  function spiffs_cache_init (line 281) | void spiffs_cache_init(spiffs *fs) {

FILE: components/spiffs/spiffs_check.c
  function s32_t (line 46) | static s32_t spiffs_object_get_data_page_index_reference(
  function s32_t (line 77) | static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spi...
  function s32_t (line 91) | static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spif...
  function s32_t (line 156) | static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
  function s32_t (line 173) | static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_o...
  function s32_t (line 445) | static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spi...
  function s32_t (line 475) | s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
  function s32_t (line 509) | static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
  function s32_t (line 851) | s32_t spiffs_page_consistency_check(spiffs *fs) {
  function spiffs_object_index_search (line 866) | static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
  function s32_t (line 878) | static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_...
  function s32_t (line 973) | s32_t spiffs_object_index_consistency_check(spiffs *fs) {

FILE: components/spiffs/spiffs_config.h
  type s32_t (line 27) | typedef signed int s32_t;
  type u32_t (line 28) | typedef unsigned int u32_t;
  type s16_t (line 29) | typedef signed short s16_t;
  type u16_t (line 30) | typedef unsigned short u16_t;
  type s8_t (line 31) | typedef signed char s8_t;
  type u8_t (line 32) | typedef unsigned char u8_t;
  type u16_t (line 354) | typedef u16_t spiffs_block_ix;
  type u16_t (line 357) | typedef u16_t spiffs_page_ix;
  type u16_t (line 361) | typedef u16_t spiffs_obj_id;
  type u16_t (line 365) | typedef u16_t spiffs_span_ix;

FILE: components/spiffs/spiffs_gc.c
  function s32_t (line 9) | static s32_t spiffs_gc_erase_block(
  function s32_t (line 32) | s32_t spiffs_gc_quick(
  function s32_t (line 109) | s32_t spiffs_gc_check(
  function s32_t (line 199) | s32_t spiffs_gc_erase_page_stats(
  function s32_t (line 236) | s32_t spiffs_gc_find_candidate(
  type spiffs_gc_clean_state (line 347) | typedef enum {
  type spiffs_gc (line 354) | typedef struct {
  function s32_t (line 377) | s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {

FILE: components/spiffs/spiffs_hydrogen.c
  function u32_t (line 24) | u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
  function u32_t (line 28) | u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
  function u8_t (line 34) | u8_t SPIFFS_mounted(spiffs *fs) {
  function s32_t (line 38) | s32_t SPIFFS_format(spiffs *fs) {
  function s32_t (line 71) | s32_t SPIFFS_probe_fs(spiffs_config *config) {
  function s32_t (line 78) | s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
  function SPIFFS_unmount (line 150) | void SPIFFS_unmount(spiffs *fs) {
  function s32_t (line 169) | s32_t SPIFFS_errno(spiffs *fs) {
  function SPIFFS_clearerr (line 173) | void SPIFFS_clearerr(spiffs *fs) {
  function s32_t (line 177) | s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
  function spiffs_file (line 201) | spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags...
  function spiffs_file (line 281) | spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, s...
  function spiffs_file (line 313) | spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spif...
  function s32_t (line 359) | static s32_t spiffs_hydro_read(spiffs *fs, spiffs_file fh, void *buf, s3...
  function s32_t (line 413) | s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
  function s32_t (line 423) | static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u3...
  function s32_t (line 446) | s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
  function s32_t (line 574) | s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
  function s32_t (line 623) | s32_t SPIFFS_remove(spiffs *fs, const char *path) {
  function s32_t (line 665) | s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
  function s32_t (line 699) | static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file...
  function s32_t (line 725) | s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
  function s32_t (line 746) | s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
  function s32_t (line 772) | static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
  function s32_t (line 805) | s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
  function s32_t (line 821) | s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
  function s32_t (line 841) | s32_t SPIFFS_rename(spiffs *fs, const char *old_path, const char *new_pa...
  function s32_t (line 896) | s32_t SPIFFS_update_meta(spiffs *fs, const char *name, const void *meta) {
  function s32_t (line 933) | s32_t SPIFFS_fupdate_meta(spiffs *fs, spiffs_file fh, const void *meta) {
  function spiffs_DIR (line 967) | spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
  function s32_t (line 986) | static s32_t spiffs_read_dir_v(
  type spiffs_dirent (line 1023) | struct spiffs_dirent
  type spiffs_dirent (line 1023) | struct spiffs_dirent
  type spiffs_dirent (line 1033) | struct spiffs_dirent
  function s32_t (line 1057) | s32_t SPIFFS_closedir(spiffs_DIR *d) {
  function s32_t (line 1063) | s32_t SPIFFS_check(spiffs *fs) {
  function s32_t (line 1086) | s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
  function s32_t (line 1110) | s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
  function s32_t (line 1129) | s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
  function s32_t (line 1147) | s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) {
  function s32_t (line 1170) | s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
  function s32_t (line 1193) | s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_...
  function s32_t (line 1202) | s32_t SPIFFS_ix_map(spiffs *fs,  spiffs_file fh, spiffs_ix_map *map,
  function s32_t (line 1235) | s32_t SPIFFS_ix_unmap(spiffs *fs,  spiffs_file fh) {
  function s32_t (line 1257) | s32_t SPIFFS_ix_remap(spiffs *fs, spiffs_file fh, u32_t offset) {
  function s32_t (line 1319) | s32_t SPIFFS_bytes_to_ix_map_entries(spiffs *fs, u32_t bytes) {
  function s32_t (line 1325) | s32_t SPIFFS_ix_map_entries_to_bytes(spiffs *fs, u32_t map_page_ix_entri...
  function s32_t (line 1333) | s32_t SPIFFS_vis(spiffs *fs) {

FILE: components/spiffs/spiffs_nucleus.c
  function s32_t (line 4) | static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_pa...
  function s32_t (line 33) | static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_p...
  function s32_t (line 64) | s32_t spiffs_phys_rd(
  function s32_t (line 72) | s32_t spiffs_phys_wr(
  function s32_t (line 83) | s32_t spiffs_phys_cpy(
  function s32_t (line 124) | s32_t spiffs_obj_lu_find_entry_visitor(
  function s32_t (line 226) | s32_t spiffs_erase_block(
  function s32_t (line 268) | s32_t spiffs_probe(
  function s32_t (line 320) | static s32_t spiffs_obj_lu_scan_v(
  function s32_t (line 348) | s32_t spiffs_obj_lu_scan(
  function s32_t (line 449) | s32_t spiffs_obj_lu_find_free(
  function s32_t (line 485) | s32_t spiffs_obj_lu_find_id(
  function s32_t (line 501) | static s32_t spiffs_obj_lu_find_id_and_span_v(
  function s32_t (line 527) | s32_t spiffs_obj_lu_find_id_and_span(
  function s32_t (line 566) | s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
  function spiffs_update_ix_map (line 606) | static void spiffs_update_ix_map(spiffs *fs,
  type spiffs_ix_map_populate_state (line 658) | typedef struct {
  function s32_t (line 665) | static s32_t spiffs_populate_ix_map_v(
  function s32_t (line 712) | s32_t spiffs_populate_ix_map(spiffs *fs, spiffs_fd *fd, u32_t vec_entry_...
  function s32_t (line 753) | s32_t spiffs_page_allocate_data(
  function s32_t (line 812) | s32_t spiffs_page_move(
  function s32_t (line 876) | s32_t spiffs_page_delete(
  function s32_t (line 907) | s32_t spiffs_object_create(
  function s32_t (line 974) | s32_t spiffs_object_update_index_hdr(
  function spiffs_cb_object_event (line 1036) | void spiffs_cb_object_event(
  function s32_t (line 1117) | s32_t spiffs_object_open_by_id(
  function s32_t (line 1135) | s32_t spiffs_object_open_by_page(
  function s32_t (line 1175) | s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_...
  function s32_t (line 1422) | s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_...
  function s32_t (line 1624) | static s32_t spiffs_object_find_object_index_header_by_name_v(
  function s32_t (line 1654) | s32_t spiffs_object_find_object_index_header_by_name(
  function s32_t (line 1690) | s32_t spiffs_object_truncate(
  type spiffs_free_obj_id_state (line 2022) | typedef struct {
  function s32_t (line 2029) | static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_...
  function s32_t (line 2062) | static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs...
  function s32_t (line 2096) | s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, ...
  function u32_t (line 2193) | static u32_t spiffs_hash(spiffs *fs, const u8_t *name) {
  function s32_t (line 2205) | s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd, const char *name) {
  function s32_t (line 2283) | s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
  function s32_t (line 2299) | s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
  function spiffs_fd_temporal_cache_rehash (line 2312) | void spiffs_fd_temporal_cache_rehash(

FILE: components/spiffs/spiffs_nucleus.h
  type spiffs_cache_page (line 376) | typedef struct {
  type spiffs_cache (line 404) | typedef struct {
  type spiffs_fd (line 416) | typedef struct {
  type spiffs_page_header (line 458) | typedef struct __attribute(( packed )) {
  type SPIFFS_ALIGNED_OBJECT_INDEX_TABLES (line 468) | struct __attribute(( packed ))
  type spiffs_page_object_ix (line 490) | typedef struct __attribute(( packed )) {
  type s32_t (line 496) | typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_b...

FILE: components/spiffs/spiffs_vfs.c
  type stat (line 53) | struct stat
  type vfs_spiffs_dir_t (line 57) | typedef struct {
  type vfs_spiffs_file_t (line 65) | typedef struct {
  type spiffs_metadata_t (line 71) | typedef struct {
  type list (line 79) | struct list
  function spiffs_fs_stat (line 94) | void spiffs_fs_stat(uint32_t *total, uint32_t *used) {
  function is_dir (line 107) | static int is_dir(const char *path) {
  function spiffs_result (line 140) | static int spiffs_result(int res) {
  function vfs_spiffs_getstat (line 163) | static int IRAM_ATTR vfs_spiffs_getstat(spiffs_file fd, spiffs_stat *st,...
  function vfs_spiffs_open (line 174) | static int IRAM_ATTR vfs_spiffs_open(const char *path, int flags, int mo...
  function vfs_spiffs_write (line 267) | static ssize_t IRAM_ATTR vfs_spiffs_write(int fd, const void *data, size...
  function vfs_spiffs_read (line 298) | static ssize_t IRAM_ATTR vfs_spiffs_read(int fd, void * dst, size_t size) {
  function vfs_spiffs_fstat (line 332) | static int IRAM_ATTR vfs_spiffs_fstat(int fd, struct stat * st) {
  function vfs_spiffs_close (line 375) | static int IRAM_ATTR vfs_spiffs_close(int fd) {
  function off_t (line 401) | static off_t IRAM_ATTR vfs_spiffs_lseek(int fd, off_t size, int mode) {
  function vfs_spiffs_stat (line 435) | static int IRAM_ATTR vfs_spiffs_stat(const char * path, struct stat * st) {
  function vfs_spiffs_unlink (line 446) | static int IRAM_ATTR vfs_spiffs_unlink(const char *path) {
  function vfs_spiffs_rename (line 504) | static int IRAM_ATTR vfs_spiffs_rename(const char *src, const char *dst) {
  function DIR (line 514) | static DIR* vfs_spiffs_opendir(const char* name) {
  type dirent (line 550) | struct dirent
  type spiffs_dirent (line 554) | struct spiffs_dirent
  type spiffs_dirent (line 555) | struct spiffs_dirent
  type dirent (line 557) | struct dirent
  type dirent (line 562) | struct dirent
  function vfs_piffs_closedir (line 663) | static int IRAM_ATTR vfs_piffs_closedir(DIR* pdir) {
  function vfs_spiffs_mkdir (line 683) | static int IRAM_ATTR vfs_spiffs_mkdir(const char *path, mode_t mode) {
  function spiffs_mount (line 719) | int spiffs_mount() {
  function vfs_spiffs_register (line 823) | void vfs_spiffs_register() {
  function spiffs_unmount (line 866) | int spiffs_unmount(int unreg) {

FILE: main/ePaper.c
  type tm (line 51) | struct tm
  function esp_err_t (line 70) | static esp_err_t event_handler(void *ctx, system_event_t *event)
  function initialise_wifi (line 92) | static void initialise_wifi(void)
  function initialize_sntp (line 113) | static void initialize_sntp(void)
  function obtain_time (line 122) | static int obtain_time(void)
  function app_main (line 160) | void app_main()
Condensed preview — 106 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,477K chars).
[
  {
    "path": ".gitignore",
    "chars": 244,
    "preview": ".config\n*.o\n*.pyc\n*.a\n*.d\n\n# gtags\nGTAGS\nGRTAGS\nGPATH\n\n# emacs\n.dir-locals.el\n\n# emacs temp file suffixes\n*~\n.#*\n\\#*#\n\ns"
  },
  {
    "path": "Makefile",
    "chars": 209,
    "preview": "#\n# This is a project Makefile. It is assumed the directory this Makefile resides in is a\n# project subdirectory.\n#\n\nPRO"
  },
  {
    "path": "README.md",
    "chars": 8466,
    "preview": "\n### ePaper library for ESP32\n\n---\n\n\n#### Features\n\n* Support for **GDEH029A1** / **SSD1608** based ePaper modules in 4-"
  },
  {
    "path": "components/epaper/DefaultFont.c",
    "chars": 8564,
    "preview": "// Default font\r\n\r\n// ========================================================================\r\n// This comes with no wa"
  },
  {
    "path": "components/epaper/DejaVuSans18.c",
    "chars": 11412,
    "preview": "// ============================================================================\r\n// Proportional font Header Format:\r\n//"
  },
  {
    "path": "components/epaper/DejaVuSans24.c",
    "chars": 16244,
    "preview": "// ========================================================================\r\n// This comes with no warranty, implied or "
  },
  {
    "path": "components/epaper/EPD.c",
    "chars": 66063,
    "preview": "/* EPD library\n *\n *  Author: LoBo (loboris@gmail.com, loboris.github)\n *\n *  Module supporting SPI ePaper displays\n*/\n\n"
  },
  {
    "path": "components/epaper/EPD.h",
    "chars": 18348,
    "preview": "/*\n * High level EPD functions\n * Author:  LoBo 06/2017, https://github/loboris\n * \n */\n\n#ifndef _EPD_H_\n#define _EPD_H_"
  },
  {
    "path": "components/epaper/EPDspi.c",
    "chars": 23259,
    "preview": "/*\n *  Author: LoBo (loboris@gmail.com, loboris.github)\n *\n *  Module supporting SPI ePaper displays\n *\n * HIGH SPEED LO"
  },
  {
    "path": "components/epaper/EPDspi.h",
    "chars": 2191,
    "preview": "/*\n *  Author: LoBo (loboris@gmail.com, loboris.github)\n *\n *  Module supporting SPI ePaper displays\n *\n * HIGH SPEED LO"
  },
  {
    "path": "components/epaper/SmallFont.c",
    "chars": 6948,
    "preview": "// SmallFont.c\r\n// Font type    : Full (95 characters)\r\n// Font size    : 8x12 pixels\r\n// Memory usage : 1144 bytes\r\n\r\n#"
  },
  {
    "path": "components/epaper/Ubuntu16.c",
    "chars": 9827,
    "preview": "// This comes with no warranty, implied or otherwise\r\n\r\n// This data structure was designed to support Proportional font"
  },
  {
    "path": "components/epaper/comic24.c",
    "chars": 16723,
    "preview": "// This comes with no warranty, implied or otherwise\r\n\r\n// This data structure was designed to support Proportional font"
  },
  {
    "path": "components/epaper/component.mk",
    "chars": 234,
    "preview": "#\n# Main Makefile. This is basically the same as a component makefile.\n#\n# (Uses default behaviour of compiling all sour"
  },
  {
    "path": "components/epaper/dejavuX.c",
    "chars": 27462,
    "preview": "// This comes with no warranty, implied or otherwise\r\n\r\n// This data structure was designed to support Proportional font"
  },
  {
    "path": "components/epaper/minya24.c",
    "chars": 16688,
    "preview": "// This comes with no warranty, implied or otherwise\r\n\r\n// This data structure was designed to support Proportional font"
  },
  {
    "path": "components/epaper/tooney32.c",
    "chars": 30006,
    "preview": "// This comes with no warranty, implied or otherwise\r\n\r\n// This data structure was designed to support Proportional font"
  },
  {
    "path": "components/mkspiffs/.travis.yml",
    "chars": 1099,
    "preview": "language: cpp\naddons:\n  apt:\n    sources:\n      - ubuntu-toolchain-r-test\n    packages:\n      - g++-4.8\nscript:\n  - expo"
  },
  {
    "path": "components/mkspiffs/Makefile.projbuild",
    "chars": 352,
    "preview": "MKSPIFFS_COMPONENT_PATH := $(COMPONENT_PATH)\nMKSPIFFS_BUILD_DIR=$(abspath $(MKSPIFFS_COMPONENT_PATH)/mkspiffs)\n\n# Custom"
  },
  {
    "path": "components/mkspiffs/component.mk",
    "chars": 78,
    "preview": "#\n# Component Makefile\n#\n\nCOMPONENT_SRCDIRS := \nCOMPONENT_ADD_INCLUDEDIRS := \n"
  },
  {
    "path": "components/mkspiffs/src/Makefile",
    "chars": 2297,
    "preview": "CFLAGS\t\t?= -std=gnu99 -Os -Wall\nCXXFLAGS\t?= -std=gnu++11 -Os -Wall\n\nifeq ($(OS),Windows_NT)\n\tTARGET_OS := WINDOWS\n\tDIST_"
  },
  {
    "path": "components/mkspiffs/src/Makefile.original",
    "chars": 2355,
    "preview": "CFLAGS\t\t?= -std=gnu99 -Os -Wall\nCXXFLAGS\t?= -std=gnu++11 -Os -Wall\n\nifeq ($(OS),Windows_NT)\n\tTARGET_OS := WINDOWS\n\tDIST_"
  },
  {
    "path": "components/mkspiffs/src/README.md",
    "chars": 1771,
    "preview": "# mkspiffs\nTool to build and unpack [SPIFFS](https://github.com/pellepl/spiffs) images.\n\n\n## Usage\n\n```\n\n   mkspiffs  {-"
  },
  {
    "path": "components/mkspiffs/src/appveyor.yml",
    "chars": 494,
    "preview": "version: 0.0.{build}\n\nplatform:\n    - x86\n\nskip_commits:\n  message: /\\[ci skip\\]/\n\nmatrix:\n    fast_finish: true\n\nbuild_"
  },
  {
    "path": "components/mkspiffs/src/main.cpp",
    "chars": 16531,
    "preview": "//\n//  main.cpp\n//  make_spiffs\n//\n//  Created by Ivan Grokhotkov on 13/05/15.\n//  Copyright (c) 2015 Ivan Grokhotkov. A"
  },
  {
    "path": "components/mkspiffs/src/spiffs/esp_spiffs.c",
    "chars": 3314,
    "preview": "/*\n * Lua RTOS, SPIFFS low access\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & CSS IBÉRICA"
  },
  {
    "path": "components/mkspiffs/src/spiffs/esp_spiffs.h",
    "chars": 1704,
    "preview": "/*\n * Lua RTOS, write syscall implementation\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & "
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs.h",
    "chars": 28607,
    "preview": "/*\n * spiffs.h\n *\n *  Created on: May 26, 2013\n *      Author: petera\n */\n\n#ifndef SPIFFS_H_\n#define SPIFFS_H_\n#if defin"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_cache.c",
    "chars": 9622,
    "preview": "/*\n * spiffs_cache.c\n *\n *  Created on: Jun 23, 2013\n *      Author: petera\n */\n\n#include \"spiffs.h\"\n#include \"spiffs_nu"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_check.c",
    "chars": 44837,
    "preview": "/*\n * spiffs_check.c\n *\n * Contains functionality for checking file system consistency\n * and mending problems.\n * Three"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_config.h",
    "chars": 13184,
    "preview": "/*\n * spiffs_config.h\n *\n *  Created on: Jul 3, 2013\n *      Author: petera\n */\n\n#ifndef SPIFFS_CONFIG_H_\n#define SPIFFS"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_gc.c",
    "chars": 25740,
    "preview": "#include \"spiffs.h\"\n#include \"spiffs_nucleus.h\"\n\n#if !SPIFFS_READ_ONLY\n\n// Erases a logical block and updates the erase "
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_hydrogen.c",
    "chars": 38890,
    "preview": "/*\n * spiffs_hydrogen.c\n *\n *  Created on: Jun 16, 2013\n *      Author: petera\n */\n\n#include \"spiffs.h\"\n#include \"spiffs"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_nucleus.c",
    "chars": 86571,
    "preview": "#include \"spiffs.h\"\n#include \"spiffs_nucleus.h\"\n\nstatic s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_p"
  },
  {
    "path": "components/mkspiffs/src/spiffs/spiffs_nucleus.h",
    "chars": 24216,
    "preview": "/*\n * spiffs_nucleus.h\n *\n *  Created on: Jun 15, 2013\n *      Author: petera\n */\n\n/* SPIFFS layout\n *\n * spiffs is desi"
  },
  {
    "path": "components/mkspiffs/src/tclap/Arg.h",
    "chars": 17417,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/ArgException.h",
    "chars": 5044,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/ArgTraits.h",
    "chars": 2627,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/COPYING",
    "chars": 1079,
    "preview": "\n\nCopyright (c) 2003 Michael E. Smoot \n\nPermission is hereby granted, free of charge, to any person \nobtaining a copy of"
  },
  {
    "path": "components/mkspiffs/src/tclap/CmdLine.h",
    "chars": 13914,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/CmdLineInterface.h",
    "chars": 3627,
    "preview": "\n/****************************************************************************** \n * \n *  file:  CmdLineInterface.h\n * \n"
  },
  {
    "path": "components/mkspiffs/src/tclap/CmdLineOutput.h",
    "chars": 1925,
    "preview": "\n\n/****************************************************************************** \n * \n *  file:  CmdLineOutput.h\n * \n *"
  },
  {
    "path": "components/mkspiffs/src/tclap/Constraint.h",
    "chars": 1800,
    "preview": "\n/******************************************************************************\n *\n *  file:  Constraint.h\n *\n *  Copyr"
  },
  {
    "path": "components/mkspiffs/src/tclap/DocBookOutput.h",
    "chars": 8334,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/HelpVisitor.h",
    "chars": 1926,
    "preview": "\n/****************************************************************************** \n * \n *  file:  HelpVisitor.h\n * \n *  C"
  },
  {
    "path": "components/mkspiffs/src/tclap/IgnoreRestVisitor.h",
    "chars": 1323,
    "preview": "\n/****************************************************************************** \n * \n *  file:  IgnoreRestVisitor.h\n * "
  },
  {
    "path": "components/mkspiffs/src/tclap/MultiArg.h",
    "chars": 12001,
    "preview": "/****************************************************************************** \n * \n *  file:  MultiArg.h\n * \n *  Copyr"
  },
  {
    "path": "components/mkspiffs/src/tclap/MultiSwitchArg.h",
    "chars": 5621,
    "preview": "\n/****************************************************************************** \n*\n*  file:  MultiSwitchArg.h\n*\n*  Copy"
  },
  {
    "path": "components/mkspiffs/src/tclap/OptionalUnlabeledTracker.h",
    "chars": 1721,
    "preview": "\n\n/****************************************************************************** \n * \n *  file:  OptionalUnlabeledTrack"
  },
  {
    "path": "components/mkspiffs/src/tclap/StandardTraits.h",
    "chars": 4525,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/StdOutput.h",
    "chars": 8430,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/SwitchArg.h",
    "chars": 7653,
    "preview": "\n/****************************************************************************** \n * \n *  file:  SwitchArg.h\n * \n *  Cop"
  },
  {
    "path": "components/mkspiffs/src/tclap/UnlabeledMultiArg.h",
    "chars": 9607,
    "preview": "\n/****************************************************************************** \n * \n *  file:  UnlabeledMultiArg.h\n * "
  },
  {
    "path": "components/mkspiffs/src/tclap/UnlabeledValueArg.h",
    "chars": 11433,
    "preview": "\n/****************************************************************************** \n * \n *  file:  UnlabeledValueArg.h\n * "
  },
  {
    "path": "components/mkspiffs/src/tclap/ValueArg.h",
    "chars": 14136,
    "preview": "/****************************************************************************** \n * \n *  file:  ValueArg.h\n * \n *  Copyr"
  },
  {
    "path": "components/mkspiffs/src/tclap/ValuesConstraint.h",
    "chars": 3195,
    "preview": "\n\n/****************************************************************************** \n * \n *  file:  ValuesConstraint.h\n * "
  },
  {
    "path": "components/mkspiffs/src/tclap/VersionVisitor.h",
    "chars": 2009,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/mkspiffs/src/tclap/Visitor.h",
    "chars": 1258,
    "preview": "\n/****************************************************************************** \n * \n *  file:  Visitor.h\n * \n *  Copyr"
  },
  {
    "path": "components/mkspiffs/src/tclap/XorHandler.h",
    "chars": 4352,
    "preview": "\n/****************************************************************************** \n * \n *  file:  XorHandler.h\n * \n *  Co"
  },
  {
    "path": "components/mkspiffs/src/tclap/ZshCompletionOutput.h",
    "chars": 7976,
    "preview": "// -*- Mode: c++; c-basic-offset: 4; tab-width: 4; -*-\n\n/***************************************************************"
  },
  {
    "path": "components/spidriver/component.mk",
    "chars": 234,
    "preview": "#\n# Main Makefile. This is basically the same as a component makefile.\n#\n# (Uses default behaviour of compiling all sour"
  },
  {
    "path": "components/spidriver/spi_master_lobo.c",
    "chars": 44889,
    "preview": "// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD\n//\n// Licensed under the Apache License, Version 2.0 (the \"L"
  },
  {
    "path": "components/spidriver/spi_master_lobo.h",
    "chars": 16182,
    "preview": "// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD\n//\n// Licensed under the Apache License, Version 2.0 (the \"L"
  },
  {
    "path": "components/spiffs/component.mk",
    "chars": 110,
    "preview": "#\n# Component Makefile\n#\n\nCOMPONENT_SRCDIRS := .\nCOMPONENT_ADD_INCLUDEDIRS := .\nCOMPONENT_PRIV_INCLUDEDIRS := "
  },
  {
    "path": "components/spiffs/esp_spiffs.c",
    "chars": 3334,
    "preview": "/*\n * Lua RTOS, SPIFFS low access\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & CSS IBÉRICA"
  },
  {
    "path": "components/spiffs/esp_spiffs.h",
    "chars": 1704,
    "preview": "/*\n * Lua RTOS, write syscall implementation\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & "
  },
  {
    "path": "components/spiffs/list.c",
    "chars": 5973,
    "preview": "/*\n * Lua RTOS, list data structure\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & CSS IBÉRI"
  },
  {
    "path": "components/spiffs/list.h",
    "chars": 1929,
    "preview": "/*\n * Lua RTOS, list data structure\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALES, S.L. & CSS IBÉRI"
  },
  {
    "path": "components/spiffs/mutex.c",
    "chars": 3370,
    "preview": "/*\n * Lua RTOS, mutex api implementation over FreeRTOS\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALE"
  },
  {
    "path": "components/spiffs/mutex.h",
    "chars": 1745,
    "preview": "/*\n * Lua RTOS, mutex api implementation over FreeRTOS\n *\n * Copyright (C) 2015 - 2017\n * IBEROXARXA SERVICIOS INTEGRALE"
  },
  {
    "path": "components/spiffs/spiffs.h",
    "chars": 28607,
    "preview": "/*\n * spiffs.h\n *\n *  Created on: May 26, 2013\n *      Author: petera\n */\n\n#ifndef SPIFFS_H_\n#define SPIFFS_H_\n#if defin"
  },
  {
    "path": "components/spiffs/spiffs_cache.c",
    "chars": 9622,
    "preview": "/*\n * spiffs_cache.c\n *\n *  Created on: Jun 23, 2013\n *      Author: petera\n */\n\n#include \"spiffs.h\"\n#include \"spiffs_nu"
  },
  {
    "path": "components/spiffs/spiffs_check.c",
    "chars": 44837,
    "preview": "/*\n * spiffs_check.c\n *\n * Contains functionality for checking file system consistency\n * and mending problems.\n * Three"
  },
  {
    "path": "components/spiffs/spiffs_config.h",
    "chars": 13375,
    "preview": "/*\n * spiffs_config.h\n *\n *  Created on: Jul 3, 2013\n *      Author: petera\n */\n\n#ifndef SPIFFS_CONFIG_H_\n#define SPIFFS"
  },
  {
    "path": "components/spiffs/spiffs_gc.c",
    "chars": 25740,
    "preview": "#include \"spiffs.h\"\n#include \"spiffs_nucleus.h\"\n\n#if !SPIFFS_READ_ONLY\n\n// Erases a logical block and updates the erase "
  },
  {
    "path": "components/spiffs/spiffs_hydrogen.c",
    "chars": 38890,
    "preview": "/*\n * spiffs_hydrogen.c\n *\n *  Created on: Jun 16, 2013\n *      Author: petera\n */\n\n#include \"spiffs.h\"\n#include \"spiffs"
  },
  {
    "path": "components/spiffs/spiffs_nucleus.c",
    "chars": 86571,
    "preview": "#include \"spiffs.h\"\n#include \"spiffs_nucleus.h\"\n\nstatic s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_p"
  },
  {
    "path": "components/spiffs/spiffs_nucleus.h",
    "chars": 24216,
    "preview": "/*\n * spiffs_nucleus.h\n *\n *  Created on: Jun 15, 2013\n *      Author: petera\n */\n\n/* SPIFFS layout\n *\n * spiffs is desi"
  },
  {
    "path": "components/spiffs/spiffs_vfs.c",
    "chars": 20187,
    "preview": "/*\n * spiffs VFS operations\n *\n * Author: LoBo (loboris@gmail.com / https://github.com/loboris)\n *\n * Part of this code "
  },
  {
    "path": "components/spiffs/spiffs_vfs.h",
    "chars": 588,
    "preview": "/*\n * spiffs VFS public function\n *\n * Author: LoBo (loboris@gmail.com / https://github.com/loboris)\n *\n * Part of this "
  },
  {
    "path": "components/spiffs_image/Makefile.projbuild",
    "chars": 1126,
    "preview": "SPIFFS_IMAGE_COMPONENT_PATH := $(COMPONENT_PATH)\nifeq ($(OS),Windows_NT)\n\tMKSPIFFS_BIN=\"mkspiffs.exe\"\nelse\n\tMKSPIFFS_BIN"
  },
  {
    "path": "components/spiffs_image/component.mk",
    "chars": 78,
    "preview": "#\n# Component Makefile\n#\n\nCOMPONENT_SRCDIRS := \nCOMPONENT_ADD_INCLUDEDIRS := \n"
  },
  {
    "path": "components/spiffs_image/image/fonts/ocrfont.c",
    "chars": 24057,
    "preview": "// OCR_A_Extended_M.c\r\n// Font type    : Full (95 characters)\r\n// Font size    : 16x24 pixels\r\n// Memory usage : 4564 by"
  },
  {
    "path": "components/spiffs_image/image/spiffs.info",
    "chars": 405,
    "preview": "INTRODUCTION\n\nSpiffs is a file system intended for SPI NOR flash devices on embedded targets.\nSpiffs is designed with fo"
  },
  {
    "path": "main/Kconfig.projbuild",
    "chars": 1145,
    "preview": "menu \"ePaper Display DEMO Configuration\"\n\nconfig SPIFFS_BASE_ADDR\n    hex \"SPIFFS Base address\"\n    range 0x100000 0x1FF"
  },
  {
    "path": "main/component.mk",
    "chars": 234,
    "preview": "#\n# Main Makefile. This is basically the same as a component makefile.\n#\n# (Uses default behaviour of compiling all sour"
  },
  {
    "path": "main/ePaper.c",
    "chars": 19177,
    "preview": "/* ePaper demo\n *\n *  Author: LoBo (loboris@gmail.com, loboris.github)\n*/\n\n#include <time.h>\n#include <errno.h>\n#include"
  },
  {
    "path": "main/ePaper.h",
    "chars": 2818,
    "preview": "/**\r\n  ******************************************************************************\r\n  * File Name          : main.h\r\n"
  },
  {
    "path": "main/img1.h",
    "chars": 24356,
    "preview": "const unsigned char gImage_img1[4736] = { /* 0X01,0X01,0X28,0X01,0X80,0X00, */\r\n0XCC,0XCE,0XEC,0XBA,0XCC,0XB3,0XCD,0X10,"
  },
  {
    "path": "main/img2.h",
    "chars": 24356,
    "preview": "const unsigned char gImage_img2[4736] = { /* 0X01,0X01,0X28,0X01,0X80,0X00, */\r\n0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,"
  },
  {
    "path": "main/img3.h",
    "chars": 24356,
    "preview": "const unsigned char gImage_img3[4736] = { /* 0X01,0X01,0X28,0X01,0X80,0X00, */\r\n0X20,0XC4,0X34,0X40,0X44,0X40,0X00,0X00,"
  },
  {
    "path": "main/img_hacking.c",
    "chars": 201656,
    "preview": "#include <stdint.h>\n\n/*\n * original image found on https://www.flickr.com/photos/adulau/9464930917/\n * (Alexandre Dulaun"
  },
  {
    "path": "partitions_example.csv",
    "chars": 320,
    "preview": "# Name,   Type, SubType, Offset,  Size, Flags\n# Note: if you change the phy_init or app partition offset, make sure to c"
  },
  {
    "path": "sdkconfig.defaults",
    "chars": 386,
    "preview": "CONFIG_PARTITION_TABLE_CUSTOM=y\nCONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions_example.csv\"\nCONFIG_PARTITION_TABLE_C"
  }
]

// ... and 12 more files (download for full content)

About this extraction

This page contains the full source code of the loboris/ESP32_ePaper_example GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 106 files (1.3 MB), approximately 635.9k tokens, and a symbol index with 619 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!