From 3ad082039061a9620171493e0cc666857c7fbfd1 Mon Sep 17 00:00:00 2001 From: Shawn A Date: Mon, 30 Jul 2018 12:08:02 -0500 Subject: [PATCH 01/94] adds support for 160x80 ebay module unknown module 160x80 BGR inverted, offset 26 differs from adafruit of same size --- TFT_Drivers/ST7735_Defines.h | 5 +++++ TFT_Drivers/ST7735_Init.h | 7 +++++++ TFT_Drivers/ST7735_Rotation.h | 16 ++++++++++++++++ User_Setups/SetupX_Template.h | 2 ++ 4 files changed, 30 insertions(+) diff --git a/TFT_Drivers/ST7735_Defines.h b/TFT_Drivers/ST7735_Defines.h index 5fe2662..35e9659 100644 --- a/TFT_Drivers/ST7735_Defines.h +++ b/TFT_Drivers/ST7735_Defines.h @@ -15,6 +15,7 @@ #define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display #define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen #define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1 #define INITB 0xB @@ -38,6 +39,10 @@ #define TAB_COLOUR INITR_GREENTAB128 #define CGRAM_OFFSET +#elif defined (ST7735_GREENTAB160x80) + #define TAB_COLOUR INITR_GREENTAB160x80 + #define CGRAM_OFFSET + #elif defined (ST7735_REDTAB) #define TAB_COLOUR INITR_REDTAB diff --git a/TFT_Drivers/ST7735_Init.h b/TFT_Drivers/ST7735_Init.h index 0df152c..3eef1d9 100644 --- a/TFT_Drivers/ST7735_Init.h +++ b/TFT_Drivers/ST7735_Init.h @@ -173,6 +173,13 @@ colstart = 0; rowstart = 32; } + else if (tabcolor == INITR_GREENTAB160x80) + { + commandList(Rcmd2green); + writecommand(TFT_INVON); + colstart = 26; + rowstart = 1; + } else if (tabcolor == INITR_REDTAB) { commandList(Rcmd2red); diff --git a/TFT_Drivers/ST7735_Rotation.h b/TFT_Drivers/ST7735_Rotation.h index b9476a1..89701f7 100644 --- a/TFT_Drivers/ST7735_Rotation.h +++ b/TFT_Drivers/ST7735_Rotation.h @@ -20,6 +20,10 @@ writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); colstart = 0; rowstart = 32; + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); + colstart = 26; + rowstart = 1; } else if(tabcolor == INITB) { writedata(TFT_MAD_MX | TFT_MAD_RGB); } else { @@ -43,6 +47,10 @@ writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 32; rowstart = 0; + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); + colstart = 1; + rowstart = 26; } else if(tabcolor == INITB) { writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); } else { @@ -66,6 +74,10 @@ writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_BGR); + colstart = 0; + rowstart = 0; } else if(tabcolor == INITB) { writedata(TFT_MAD_MY | TFT_MAD_RGB); } else { @@ -89,6 +101,10 @@ writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 0; rowstart = 0; + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); + colstart = 1; + rowstart = 26; } else if(tabcolor == INITB) { writedata(TFT_MAD_MV | TFT_MAD_RGB); } else { diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 8b22cbc..f321517 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -24,6 +24,7 @@ //#define M5STACK // For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 80 //#define TFT_WIDTH 128 //#define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -40,6 +41,7 @@ //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 //#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) //#define ST7735_REDTAB //#define ST7735_BLACKTAB From d8684840aa5014bd2fd909633c74e9da59a6cc12 Mon Sep 17 00:00:00 2001 From: Shawn A Date: Mon, 30 Jul 2018 12:10:42 -0500 Subject: [PATCH 02/94] update user_setup --- User_Setup.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/User_Setup.h b/User_Setup.h index 139f0e9..dca9207 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -30,8 +30,9 @@ //#define M5STACK // For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 +// #define TFT_WIDTH 80 +// #define TFT_WIDTH 128 +// #define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 // For ST7735 ONLY, define the type of display, originally this was based on the @@ -41,12 +42,13 @@ // Comment out ALL BUT ONE of these options for a ST7735 display driver, save this // this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB +// #define ST7735_INITB +// #define ST7735_GREENTAB +// #define ST7735_GREENTAB2 +// #define ST7735_GREENTAB3 +// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) +// #define ST7735_REDTAB //#define ST7735_BLACKTAB // ################################################################################## From 8eefc6f26e77710973a3a414bf963749b97cf346 Mon Sep 17 00:00:00 2001 From: Andriy Makukha Date: Wed, 1 Aug 2018 21:36:15 +0800 Subject: [PATCH 03/94] Added ST7789 initialization --- TFT_Drivers/ST7789_Defines.h | 90 +++++++++++++++++++++--- TFT_Drivers/ST7789_Init.h | 132 ++++++++++++++++++++++++++++++----- TFT_eSPI.h | 6 +- 3 files changed, 197 insertions(+), 31 deletions(-) diff --git a/TFT_Drivers/ST7789_Defines.h b/TFT_Drivers/ST7789_Defines.h index 99d35db..5a0d1be 100644 --- a/TFT_Drivers/ST7789_Defines.h +++ b/TFT_Drivers/ST7789_Defines.h @@ -1,7 +1,11 @@ // Change the width and height if required (defined in portrait mode) // or use the constructor to over-ride defaults -#define TFT_WIDTH 240 -#define TFT_HEIGHT 240 +#ifndef TFT_WIDTH + #define TFT_WIDTH 240 +#endif +#ifndef TFT_HEIGHT + #define TFT_HEIGHT 320 +#endif #define CGRAM_OFFSET @@ -15,25 +19,20 @@ #define TFT_SLPIN 0x10 #define TFT_SLPOUT 0x11 - #define TFT_NORON 0x13 #define TFT_INVOFF 0x20 #define TFT_INVON 0x21 - #define TFT_DISPOFF 0x28 #define TFT_DISPON 0x29 - #define TFT_CASET 0x2A #define TFT_PASET 0x2B #define TFT_RAMWR 0x2C - #define TFT_RAMRD 0x2E - #define TFT_MADCTL 0x36 - #define TFT_COLMOD 0x3A +// Flags for TFT_MADCTL #define TFT_MAD_MY 0x80 #define TFT_MAD_MX 0x40 #define TFT_MAD_MV 0x20 @@ -46,4 +45,79 @@ #define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read +// ST7789 specific commands used in init +#define ST7789_NOP 0x00 +#define ST7789_SWRESET 0x01 +#define ST7789_RDDID 0x04 +#define ST7789_RDDST 0x09 + +#define ST7789_RDDPM 0x0A // Read display power mode +#define ST7789_RDD_MADCTL 0x0B // Read display MADCTL +#define ST7789_RDD_COLMOD 0x0C // Read display pixel format +#define ST7789_RDDIM 0x0D // Read display image mode +#define ST7789_RDDSM 0x0E // Read display signal mode +#define ST7789_RDDSR 0x0F // Read display self-diagnostic result (ST7789V) + +#define ST7789_SLPIN 0x10 +#define ST7789_SLPOUT 0x11 +#define ST7789_PTLON 0x12 +#define ST7789_NORON 0x13 + +#define ST7789_INVOFF 0x20 +#define ST7789_INVON 0x21 +#define ST7789_GAMSET 0x26 // Gamma set +#define ST7789_DISPOFF 0x28 +#define ST7789_DISPON 0x29 +#define ST7789_CASET 0x2A +#define ST7789_RASET 0x2B +#define ST7789_RAMWR 0x2C +#define ST7789_RGBSET 0x2D // Color setting for 4096, 64K and 262K colors +#define ST7789_RAMRD 0x2E + +#define ST7789_PTLAR 0x30 +#define ST7789_VSCRDEF 0x33 // Vertical scrolling definition (ST7789V) +#define ST7789_TEOFF 0x34 // Tearing effect line off +#define ST7789_TEON 0x35 // Tearing effect line on +#define ST7789_MADCTL 0x36 // Memory data access control +#define ST7789_IDMOFF 0x38 // Idle mode off +#define ST7789_IDMON 0x39 // Idle mode on +#define ST7789_RAMWRC 0x3C // Memory write continue (ST7789V) +#define ST7789_RAMRDC 0x3E // Memory read continue (ST7789V) +#define ST7789_COLMOD 0x3A + +#define ST7789_RAMCTRL 0xB0 // RAM control +#define ST7789_RGBCTRL 0xB1 // RGB control +#define ST7789_PORCTRL 0xB2 // Porch control +#define ST7789_FRCTRL1 0xB3 // Frame rate control +#define ST7789_PARCTRL 0xB5 // Partial mode control +#define ST7789_GCTRL 0xB7 // Gate control +#define ST7789_GTADJ 0xB8 // Gate on timing adjustment +#define ST7789_DGMEN 0xBA // Digital gamma enable +#define ST7789_VCOMS 0xBB // VCOMS setting +#define ST7789_LCMCTRL 0xC0 // LCM control +#define ST7789_IDSET 0xC1 // ID setting +#define ST7789_VDVVRHEN 0xC2 // VDV and VRH command enable +#define ST7789_VRHS 0xC3 // VRH set +#define ST7789_VDVSET 0xC4 // VDV setting +#define ST7789_VCMOFSET 0xC5 // VCOMS offset set +#define ST7789_FRCTR2 0xC6 // FR Control 2 +#define ST7789_CABCCTRL 0xC7 // CABC control +#define ST7789_REGSEL1 0xC8 // Register value section 1 +#define ST7789_REGSEL2 0xCA // Register value section 2 +#define ST7789_PWMFRSEL 0xCC // PWM frequency selection +#define ST7789_PWCTRL1 0xD0 // Power control 1 +#define ST7789_VAPVANEN 0xD2 // Enable VAP/VAN signal output +#define ST7789_CMD2EN 0xDF // Command 2 enable +#define ST7789_PVGAMCTRL 0xE0 // Positive voltage gamma control +#define ST7789_NVGAMCTRL 0xE1 // Negative voltage gamma control +#define ST7789_DGMLUTR 0xE2 // Digital gamma look-up table for red +#define ST7789_DGMLUTB 0xE3 // Digital gamma look-up table for blue +#define ST7789_GATECTRL 0xE4 // Gate control +#define ST7789_SPI2EN 0xE7 // SPI2 enable +#define ST7789_PWCTRL2 0xE8 // Power control 2 +#define ST7789_EQCTRL 0xE9 // Equalize time control +#define ST7789_PROMCTRL 0xEC // Program control +#define ST7789_PROMEN 0xFA // Program mode enable +#define ST7789_NVMSET 0xFC // NVM setting +#define ST7789_PROMACT 0xFE // Program action diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index d5ba408..9b69cb4 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -1,24 +1,120 @@ // This is the command sequence that initialises the ST7789 driver - -// Configure ST7789 display +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format { -static const uint8_t PROGMEM - st7789[] = { - 9, - TFT_SWRST, TFT_INIT_DELAY, 150, - TFT_SLPOUT, TFT_INIT_DELAY, 255, - TFT_COLMOD, 1+TFT_INIT_DELAY, 0x55, 10, - TFT_MADCTL, 1, TFT_MAD_RGB, - TFT_CASET, 4, 0x00, 0x00, 0x00, 0xF0, - TFT_PASET, 4, 0x00, 0x00, 0x00, 0xF0, - TFT_INVON, TFT_INIT_DELAY, 10, - TFT_NORON, TFT_INIT_DELAY, 10, - TFT_DISPON, TFT_INIT_DELAY, 255 - }; + writecommand(ST7789_SLPOUT); // Sleep out + delay(120); - commandList(st7789); + writecommand(ST7789_NORON); // Normal display mode on + + //------------------------------display and color format setting--------------------------------// + writecommand(ST7789_MADCTL); + writedata(0x00); + writedata(0x48); + + // JLX240 display datasheet + writecommand(0xB6); + writedata(0x0A); + writedata(0x82); + + writecommand(ST7789_COLMOD); + writedata(0x55); + + //--------------------------------ST7789V Frame rate setting----------------------------------// + writecommand(ST7789_PORCTRL); + writedata(0x0c); + writedata(0x0c); + writedata(0x00); + writedata(0x33); + writedata(0x33); + + writecommand(ST7789_GCTRL); // Voltages: VGH / VGL + writedata(0x35); + + //---------------------------------ST7789V Power setting--------------------------------------// + writecommand(ST7789_VCOMS); + writedata(0x28); // JLX240 display datasheet + + writecommand(ST7789_LCMCTRL); + writedata(0x0C); + + writecommand(ST7789_VDVVRHEN); + writedata(0x01); + writedata(0xFF); + + writecommand(ST7789_VRHS); // voltage VRHS + writedata(0x10); + + writecommand(ST7789_VDVSET); + writedata(0x20); + + writecommand(ST7789_FRCTR2); + writedata(0x0f); + + writecommand(ST7789_PWCTRL1); + writedata(0xa4); + writedata(0xa1); + + //--------------------------------ST7789V gamma setting---------------------------------------// + writecommand(ST7789_PVGAMCTRL); + writedata(0xd0); + writedata(0x00); + writedata(0x02); + writedata(0x07); + writedata(0x0a); + writedata(0x28); + writedata(0x32); + writedata(0x44); + writedata(0x42); + writedata(0x06); + writedata(0x0e); + writedata(0x12); + writedata(0x14); + writedata(0x17); + + writecommand(ST7789_NVGAMCTRL); + writedata(0xd0); + writedata(0x00); + writedata(0x02); + writedata(0x07); + writedata(0x0a); + writedata(0x28); + writedata(0x31); + writedata(0x54); + writedata(0x47); + writedata(0x0e); + writedata(0x1c); + writedata(0x17); + writedata(0x1b); + writedata(0x1e); + + writecommand(ST7789_INVOFF); + + writecommand(ST7789_CASET); // Column address set + writedata(0x00); + writedata(0x00); + writedata(0x00); + writedata(0xE5); // 239 + + writecommand(ST7789_RASET); // Row address set + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); // 319 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + spi_end(); + delay(120); + spi_begin(); + + writecommand(ST7789_DISPON); //Display on + + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); } -// End of ST7789 display configuration - diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 5729a37..3be13f5 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -35,11 +35,7 @@ #define SPI_READ_FREQUENCY SPI_FREQUENCY #endif -#ifdef ST7789_DRIVER - #define TFT_SPI_MODE SPI_MODE3 -#else - #define TFT_SPI_MODE SPI_MODE0 -#endif +#define TFT_SPI_MODE SPI_MODE0 // If the frequency is not defined, set a default #ifndef SPI_TOUCH_FREQUENCY From 7d48498f455dfb892ebcb8fb1e75357cea8bcfcc Mon Sep 17 00:00:00 2001 From: Andriy Makukha Date: Thu, 2 Aug 2018 16:32:20 +0800 Subject: [PATCH 04/94] Returned SPI_MODE3 for the ST7789 driver --- TFT_eSPI.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 3be13f5..5729a37 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -35,7 +35,11 @@ #define SPI_READ_FREQUENCY SPI_FREQUENCY #endif -#define TFT_SPI_MODE SPI_MODE0 +#ifdef ST7789_DRIVER + #define TFT_SPI_MODE SPI_MODE3 +#else + #define TFT_SPI_MODE SPI_MODE0 +#endif // If the frequency is not defined, set a default #ifndef SPI_TOUCH_FREQUENCY From 59f4b17ed36551db6dd80740efd9f3a14bf6bfeb Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 2 Aug 2018 22:49:30 +0100 Subject: [PATCH 05/94] Add note about SDO line (leave TFT SDO disconnected if other SPI devices share MISO) --- User_Setups/Setup20_ILI9488.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/User_Setups/Setup20_ILI9488.h b/User_Setups/Setup20_ILI9488.h index 1a20ffd..ada2eee 100644 --- a/User_Setups/Setup20_ILI9488.h +++ b/User_Setups/Setup20_ILI9488.h @@ -53,7 +53,7 @@ // We must use hardware SPI, a minimum of 3 GPIO pins is needed. // Typical setup for ESP8266 NodeMCU ESP-12 is : // -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display SDO/MISO to NodeMCU pin D6 (leave TFT SDO disconnected if other SPI devices share MISO) // Display LED to NodeMCU pin VIN (or 5V, see below) // Display SCK to NodeMCU pin D5 // Display SDI/MOSI to NodeMCU pin D7 @@ -114,7 +114,7 @@ // For ESP32 Dev board (only tested with ILI9341 display) // The hardware SPI can be mapped to any pins -//#define TFT_MISO 19 +//#define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) //#define TFT_MOSI 23 //#define TFT_SCLK 18 //#define TFT_CS 15 // Chip select control pin From 2f4c48ee72cf1b919b7b020fcad58e7b696af8d0 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 2 Aug 2018 22:51:25 +0100 Subject: [PATCH 06/94] Add note about SDO (leave TFT SDO disconnected if other SPI devices share MISO) --- User_Setups/Setup21_ILI9488.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h index 9b74048..07e1f8f 100644 --- a/User_Setups/Setup21_ILI9488.h +++ b/User_Setups/Setup21_ILI9488.h @@ -53,7 +53,7 @@ // We must use hardware SPI, a minimum of 3 GPIO pins is needed. // Typical setup for ESP8266 NodeMCU ESP-12 is : // -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display SDO/MISO to NodeMCU pin D6 (leave TFT SDO disconnected if other SPI devices share MISO) // Display LED to NodeMCU pin VIN (or 5V, see below) // Display SCK to NodeMCU pin D5 // Display SDI/MOSI to NodeMCU pin D7 @@ -114,7 +114,7 @@ // For ESP32 Dev board (only tested with ILI9341 display) // The hardware SPI can be mapped to any pins -#define TFT_MISO 19 +#define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) #define TFT_MOSI 23 #define TFT_SCLK 18 #define TFT_CS 15 // Chip select control pin From a9c4351c64c9f3ffccb76838da8379cc480d5e6a Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 26 Aug 2018 23:17:58 +0100 Subject: [PATCH 07/94] Allow more settle time for raw values read from touch controller --- Extensions/Touch.cpp | 7 ++++++- library.json | 2 +- library.properties | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 8a3efa8..87fa182 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -22,8 +22,13 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ T_CS_L; + // Dummy transfer + SPI.transfer(0xd0); + SPI.transfer(0); + SPI.transfer(0); + // Start bit + YP sample request for x position - tmp = SPI.transfer(0xd0); + SPI.transfer(0xd0); tmp = SPI.transfer(0); tmp = tmp <<5; tmp |= 0x1f & (SPI.transfer(0)>>3); diff --git a/library.json b/library.json index 5265998..8e644b2 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.0.0", + "version": "1.0.1", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index e789025..c9eba93 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.0.0 +version=1.0.1 author=Bodmer maintainer=Bodmer sentence=A fast TFT library for ESP8266 processors and the Arduino IDE From 641ac9f51eb2860b483fa4d7e083d00eb4e97e9c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 17 Sep 2018 23:37:14 +0100 Subject: [PATCH 08/94] Load via library manager now available. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b4d3d2e..bb2dfd5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # TFT_eSPI -An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D and ST7789 based TFT displays that support SPI. +An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D and ST7789 based TFT displays that support SPI. The library can be loaded using the Arduino IDE's Library Manager. 8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with an ESP32. From a38efa53300d7767db414e7bef070b6d2817a8d4 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 10 Oct 2018 22:52:21 +0100 Subject: [PATCH 09/94] Add missing image files --- .../Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg | Bin 0 -> 24384 bytes .../Generic/ESP32_SDcard_jpeg/Data/EagleEye.jpg | Bin 0 -> 20838 bytes .../Generic/ESP32_SDcard_jpeg/Data/Mouse480.jpg | Bin 0 -> 6609 bytes .../Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg | Bin 0 -> 19414 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg create mode 100644 examples/Generic/ESP32_SDcard_jpeg/Data/EagleEye.jpg create mode 100644 examples/Generic/ESP32_SDcard_jpeg/Data/Mouse480.jpg create mode 100644 examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a53afef096cf4bf6f52bf4d61b7dbc01e75f3a74 GIT binary patch literal 24384 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 YW~f|Ki9z^Vev_5~>SWvk+wuJW0_vjI>Hq)$ literal 0 HcmV?d00001 diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg new file mode 100644 index 0000000000000000000000000000000000000000..183b98f58d5c787ecf37aa1da0f5240f32de61a9 GIT binary patch literal 19414 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 *a1q*4*KSYhyn^A!GwaWgA@QrM;-$|$nj86D*d zi*j_1%|!}h)%trhM(=l-HG)y(jf9OtslzEGs;c734|}a#F@`iWbX3UHBf%4bbC)I* z3n{Zj5vfwOlnW9LUTCu7kkJDXJ189yIw+BHfKD|LruRb~S4S$su9LCKbraX zhi?2%DBtBJeR4KO6(=CstBdlI#?5q(kkql!vO8?za{h`{6!xNPgKkBMUc??-PfEjU zfphgFt4c_tmXvkuJuJOi(F-W4ENX*(7bCtl(^L}2W{UcRDdFH%@K{K2e=X7RNQ`_s zyu6YNIDa=)s5W{y#1$@V+|iBwThOQQm>VTi80joSuN#L@f(Wgni0USUXh+8%^$55< zob#OXM%>LliIA_MhgX_nX{)1i&CG3m^$R~z(-hBRopXK4(&G_BTW7&$)ka4Vz1CiQ z&T}v315}JK_C?-AGDDxLBb#kr(gNTkU^69dhg%(@hc`C;v{vx&>Dih`G+T02JWi@` z%Fa+xqr;?^__8_I?78NzwsgU@(jBeG7~986(FXuqRbJcS|R#Xf2piCzw0Vl;3z7FY`=+o$$W4Y%}D1wp$iv=C`^Ey{p8?4%8@fr)CmGzu-= z>OktTj)9>ImQx?}uN8q{ve|U0SwwEJjLKTUM3qIKo>B- zQ|MM&W8!rqD;w@LT##M22oS$ZCL7Gu^mN#~k%O%Ufq?JA5{5SBw0ph4A(uvHB5B)y(1nuDgnq1w0F&B1*THv4}NV5a*mbG zKZGb!(U9k6K2v3FPRyhQ%aV1Zc4EdFo|p?=IM~3{1qi_EQQ9mQBW;~YBz1!5g4(FG zSgCc@Erjj<%b-|`t_>8eq6Q|?yXsV1qLJBS626LCp|#psPj!q*r$VJ=7OvjNigw(~ zg}ar}vXIm)0y%YE14Z7tuK<7<6&?lsZG$(R=^N~_FvUB=b%7 literal 0 HcmV?d00001 From 1fd8d4cd6d8562ff1cf2fecf3c92ef96d44fa151 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 11 Oct 2018 23:46:19 +0100 Subject: [PATCH 10/94] Fix issue #216 --- TFT_eSPI.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index d19d0c6..b50d4ee 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4156,17 +4156,17 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) uint16_t cheight = 8 * textsize; #ifdef LOAD_GFXFF - if (font == 1) { - if(gfxFont) { - cheight = glyph_ab * textsize; - poY += cheight; // Adjust for baseline datum of free fonts - baseline = cheight; - padding =101; // Different padding method used for Free Fonts + bool freeFont = (font == 1 && gfxFont && !fontLoaded); - // We need to make an adjustment for the bottom of the string (eg 'y' character) - if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) { - cheight += glyph_bb * textsize; - } + if (freeFont) { + cheight = glyph_ab * textsize; + poY += cheight; // Adjust for baseline datum of free fonts + baseline = cheight; + padding =101; // Different padding method used for Free Fonts + + // We need to make an adjustment for the bottom of the string (eg 'y' character) + if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) { + cheight += glyph_bb * textsize; } } #endif @@ -4250,7 +4250,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) int8_t xo = 0; #ifdef LOAD_GFXFF - if ((font == 1) && (gfxFont) && (textcolor!=textbgcolor)) + if (freeFont && (textcolor!=textbgcolor)) { cheight = (glyph_ab + glyph_bb) * textsize; // Get the offset for the first character only to allow for negative offsets @@ -4306,7 +4306,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) { int16_t padXc = poX+cwidth+xo; #ifdef LOAD_GFXFF - if ((font == 1) && (gfxFont)) + if (freeFont) { poX +=xo; // Adjust for negative offset start character poY -= glyph_ab * textsize; From 22177cf29a84235e5fb02996e7954d5f21841fce Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 11 Oct 2018 23:48:25 +0100 Subject: [PATCH 11/94] Raise version --- library.json | 2 +- library.properties | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library.json b/library.json index 8e644b2..15bfb8b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.0.1", + "version": "1.0.2", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index c9eba93..dd9055a 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,10 @@ name=TFT_eSPI -version=1.0.1 +version=1.0.2 author=Bodmer maintainer=Bodmer -sentence=A fast TFT library for ESP8266 processors and the Arduino IDE +sentence=A fast TFT library for ESP8266 and ESP32 processors for the Arduino IDE paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI. category=Display -url=http://www.instructables.com/id/Arduino-TFT-display-and-font-library/ +url=https://github.com/Bodmer/TFT_eSPI architectures=esp8266,esp32 includes=TFT_eSPI.h From 1a0b37097a58d29f09955e0d7a5a0eb472152f2b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 21 Oct 2018 17:53:27 +0100 Subject: [PATCH 12/94] Add new anti-aliased (smooth) font examples + bug fixes Four new examples have been added to show different methods of rendering the anta-aliased fonts. A few minor bugs have been corrected associated with the font rendering. drawNumber and drawFloat handle fixed width mono fonts with no digit movement. --- Extensions/Smooth_font.cpp | 2 +- Extensions/Smooth_font.h | 3 +- Extensions/Sprite.cpp | 13 +- TFT_eSPI.cpp | 61 +++-- TFT_eSPI.h | 10 +- User_Setup.h | 3 +- User_Setup_Select.h | 2 + User_Setups/Setup1_ILI9341.h | 6 +- User_Setups/Setup21_ILI9488.h | 3 + .../Smooth Fonts/Font_Demo_1/Font_Demo_1.ino | 170 ++++++++++++++ examples/Smooth Fonts/Font_Demo_1/Notes.ino | 56 +++++ .../Font_Demo_1/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_1/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth Fonts/Font_Demo_2/Font_Demo_2.ino | 219 ++++++++++++++++++ examples/Smooth Fonts/Font_Demo_2/Notes.ino | 56 +++++ .../Font_Demo_2/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_2/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Smooth Fonts/Font_Demo_3/Font_Demo_3.ino | 218 +++++++++++++++++ examples/Smooth Fonts/Font_Demo_3/Notes.ino | 61 +++++ .../Font_Demo_3/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_3/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes .../Font_Demo_3/data/NotoSansMonoSCB20.vlw | Bin 0 -> 15382 bytes .../Smooth Fonts/Font_Demo_4/Font_Demo_4.ino | 128 ++++++++++ examples/Smooth Fonts/Font_Demo_4/Notes.ino | 56 +++++ .../Font_Demo_4/data/NotoSansBold15.vlw | Bin 0 -> 10766 bytes .../Font_Demo_4/data/NotoSansBold36.vlw | Bin 0 -> 44169 bytes keywords.txt | 1 + library.json | 2 +- library.properties | 6 +- 29 files changed, 1034 insertions(+), 42 deletions(-) create mode 100644 examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino create mode 100644 examples/Smooth Fonts/Font_Demo_1/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino create mode 100644 examples/Smooth Fonts/Font_Demo_2/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino create mode 100644 examples/Smooth Fonts/Font_Demo_3/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino create mode 100644 examples/Smooth Fonts/Font_Demo_4/Notes.ino create mode 100644 examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw create mode 100644 examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 7ec2340..7d573be 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -424,7 +424,7 @@ void TFT_eSPI::drawGlyph(uint16_t code) uint8_t pbuffer[gWidth[gNum]]; - uint16_t xs = 0; + int16_t xs = 0; uint32_t dl = 0; int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h index 6ab09fc..2c7faa2 100644 --- a/Extensions/Smooth_font.h +++ b/Extensions/Smooth_font.h @@ -13,7 +13,8 @@ uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); - void drawGlyph(uint16_t code); + virtual void drawGlyph(uint16_t code); + void showFont(uint32_t td); fs::File fontFile; diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index fb94747..acfc315 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -1473,10 +1473,10 @@ void TFT_eSprite::drawGlyph(uint16_t code) if (code == '\n') { if (_created) { - this->cursor_x = 0; - this->cursor_y += this->gFont.yAdvance; - if (this->cursor_y >= _height) this->cursor_y = 0; - return; + this->cursor_x = 0; + this->cursor_y += this->gFont.yAdvance; + if (this->cursor_y >= _height) this->cursor_y = 0; + return; } else { @@ -1511,7 +1511,7 @@ void TFT_eSprite::drawGlyph(uint16_t code) uint8_t pbuffer[this->gWidth[gNum]]; - uint16_t xs = 0; + int16_t xs = 0; uint16_t dl = 0; for (int y = 0; y < this->gHeight[gNum]; y++) @@ -1525,7 +1525,8 @@ void TFT_eSprite::drawGlyph(uint16_t code) if (pixel != 0xFF) { if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } - if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); + if (_bpp != 1) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); + else if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], fg); } else { diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index b50d4ee..aeb0766 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -172,6 +172,7 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) textcolor = bitmap_fg = 0xFFFF; // White textbgcolor = bitmap_bg = 0x0000; // Black padX = 0; // No padding + isDigits = false; // No bounding box adjustment textwrapX = true; // Wrap text at end of line when using print stream textwrapY = false; // Wrap text at bottom of screen when using print stream textdatum = TL_DATUM; // Top Left text alignment is default @@ -1548,7 +1549,7 @@ void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t corne ** Function name: drawEllipse ** Description: Draw a ellipse outline ***************************************************************************************/ -void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color) +void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { if (rx<2) return; if (ry<2) return; @@ -1603,7 +1604,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 ** Function name: fillEllipse ** Description: draw a filled ellipse ***************************************************************************************/ -void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color) +void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { if (rx<2) return; if (ry<2) return; @@ -2102,13 +2103,14 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) if (found) { if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; - if (*string) str_width += gxAdvance[gNum]; + if (*string || isDigits) str_width += gxAdvance[gNum]; else str_width += (gdX[gNum] + gWidth[gNum]); } else str_width += gFont.spaceWidth + 1; } } } + isDigits = false; return str_width; } #endif @@ -2141,8 +2143,8 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) { uniCode -= pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); - // If this is not the last character then use xAdvance - if (*string) str_width += pgm_read_byte(&glyph->xAdvance); + // If this is not the last character or is a digit then use xAdvance + if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance); // Else use the offset plus width since this can be bigger than xAdvance else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width)); } @@ -2156,6 +2158,7 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) #endif } } + isDigits = false; return str_width * textsize; } @@ -3715,11 +3718,11 @@ size_t TFT_eSPI::write(uint8_t utf8) //fontFile = SPIFFS.open( _gFontFilename, "r" ); - if(!fontFile) - { - fontLoaded = false; - return 0; - } + //if(!fontFile) + //{ + // fontLoaded = false; + // return 0; + //} drawGlyph(unicode); @@ -4147,6 +4150,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY) { return drawString(string, poX, poY, textfont); } + // With font number int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) { @@ -4171,23 +4175,23 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) } #endif + + // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font +#ifdef SMOOTH_FONT + if(fontLoaded) { + baseline = gFont.maxAscent; + cheight = fontHeight(); + } + else +#endif + if (font!=1) { + baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; + cheight = fontHeight(font); + } + if (textdatum || padX) { - // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font -#ifdef SMOOTH_FONT - if(fontLoaded) { - baseline = gFont.maxAscent; - cheight = fontHeight(0); - } - - else -#endif - if (font!=1) { - baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; - cheight = fontHeight(font); - } - switch(textdatum) { case TC_DATUM: poX -= cwidth/2; @@ -4418,6 +4422,7 @@ int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) ***************************************************************************************/ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY) { + isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); return drawString(str, poX, poY, textfont); @@ -4425,6 +4430,7 @@ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY) int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font) { + isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); return drawString(str, poX, poY, font); @@ -4444,6 +4450,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY) int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int font) { + isDigits = true; char str[14]; // Array to contain decimal string uint8_t ptr = 0; // Initialise pointer for array int8_t digits = 1; // Count the digits to avoid array overflow @@ -4572,7 +4579,7 @@ void TFT_eSPI::setTextFont(uint8_t f) /*************************************************************************************** -** Function name: spiBlockWrite +** Function name: writeBlock ** Description: Write a block of pixels of the same colour ***************************************************************************************/ //Clear screen test 76.8ms theoretical. 81.5ms TFT_eSPI, 967ms Adafruit_ILI9341 @@ -4964,6 +4971,10 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) #include "Extensions/Sprite.cpp" +// #ifdef ESP32 +// #include "Extensions/pSprite.cpp" +// #endif + #ifdef SMOOTH_FONT #include "Extensions/Smooth_font.cpp" #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 5729a37..2c93392 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -562,8 +562,8 @@ class TFT_eSPI : public Print { fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color), fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), - drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color), - fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color), + drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), + fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), fillTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), @@ -719,6 +719,7 @@ class TFT_eSPI : public Print { uint8_t glyph_ab, // glyph height above baseline glyph_bb; // glyph height below baseline + bool isDigits; // adjust bounding box for numbers to reduce visual jiggling bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display bool _swapBytes; // Swap the byte order for TFT pushImage() bool locked, inTransaction; // Transaction and mutex lock flags for ESP32 @@ -749,4 +750,9 @@ class TFT_eSPI : public Print { // Load the Sprite Class #include "Extensions/Sprite.h" +// #ifdef ESP32 +// // Load the Sprite Class +// #include "Extensions/pSprite.h" +// #endif + #endif diff --git a/User_Setup.h b/User_Setup.h index 139f0e9..24e2873 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -236,7 +236,8 @@ // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 -#define SPI_READ_FREQUENCY 20000000 // Optional reduced SPI frequency for reading TFT +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 20000000 // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 00b6013..dee02cf 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -43,6 +43,8 @@ //#include // Setup file for ESP8266 and ILI9488 SPI bus TFT //#include // Setup file for ESP32 and ILI9488 SPI bus TFT +//#include // Setup file configured for my ST7735S 80x160 + //#include diff --git a/User_Setups/Setup1_ILI9341.h b/User_Setups/Setup1_ILI9341.h index 7eb6fba..1f02b38 100644 --- a/User_Setups/Setup1_ILI9341.h +++ b/User_Setups/Setup1_ILI9341.h @@ -197,10 +197,12 @@ // #define SPI_FREQUENCY 5000000 // #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +#define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +#define SPI_READ_FREQUENCY 20000000 + // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h index 07e1f8f..b00d02a 100644 --- a/User_Setups/Setup21_ILI9488.h +++ b/User_Setups/Setup21_ILI9488.h @@ -19,6 +19,9 @@ //#define ILI9163_DRIVER //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9486_DRIVER #define ILI9488_DRIVER // For M5Stack ESP32 module with integrated display ONLY, remove // in line below diff --git a/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino new file mode 100644 index 0000000..0d24af9 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino @@ -0,0 +1,170 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 1, using tft.print() and tft.println() calls. + + In some cases the sketch shows what can go wrong too, so read the comments! + + The font is rendered WITHOUT a background, but a background colour needs to be + set so the anti-aliasing of the character is performed correctly. This is because + characters are drawn one by one. + + This method is good for static text that does not change often because changing + values may flicker. The text appears at the tft cursor coordinates. + + It is also possible to "print" text directly into a created sprite, for example using + spr.println("Hello"); and then push the sprite to the screen. That method is not + demonstrated in this sketch. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(0); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); +} + + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour AND the background colour + // so the anti-aliasing works + + tft.setCursor(0, 0); // Set cursor at top left of screen + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL); // Must load the font first + + tft.println("Small 15pt font"); // println moves cursor down for a new line + + tft.println(); // New line + + tft.print("ABC"); // print leaves cursor at end of line + + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("1234"); // Added to line after ABC + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + // print stream formatting can be used,see: + // https://www.arduino.cc/en/Serial/Print + int ivalue = 1234; + tft.println(ivalue); // print as an ASCII-encoded decimal + tft.println(ivalue, DEC); // print as an ASCII-encoded decimal + tft.println(ivalue, HEX); // print as an ASCII-encoded hexadecimal + tft.println(ivalue, OCT); // print as an ASCII-encoded octal + tft.println(ivalue, BIN); // print as an ASCII-encoded binary + + tft.println(); // New line + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + float fvalue = 1.23456; + tft.println(fvalue, 0); // no decimal places + tft.println(fvalue, 1); // 1 decimal place + tft.println(fvalue, 2); // 2 decimal places + tft.println(fvalue, 5); // 5 decimal places + + delay(5000); + + // Get ready for the next demo while we have this font loaded + tft.fillScreen(TFT_BLACK); + tft.setCursor(0, 0); // Set cursor at top left of screen + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Wrong and right ways to"); + tft.println("print changing values..."); + + tft.unloadFont(); // Remove the font to recover memory used + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE); // Load another different font + + //tft.fillScreen(TFT_BLACK); + + // Draw changing numbers - does not work unless a filled rectangle is drawn over the old text + for (int i = 0; i <= 20; i++) + { + tft.setCursor(50, 50); + tft.print(" "); // Overprinting old number with spaces DOES NOT WORK! + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 50); + tft.print(i / 10.0, 1); + + tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 90); + tft.print(i / 10.0, 1); + + delay (200); + } + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font text wrapping + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Change the font colour and the background colour + + tft.setCursor(0, 0); // Set cursor at top left of screen + + tft.println("Large font!"); + + tft.setTextWrap(true); // Wrap on width + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("Long lines wrap to the next line"); + + tft.setTextWrap(false, false); // Wrap on width and height switched off + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + tft.println("Unless text wrap is switched off"); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/Font_Demo_1/Notes.ino b/examples/Smooth Fonts/Font_Demo_1/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 zcmcgx4@hHOcE6jZsh!Q*iin7aTWhUrT|2F{*4os%wXU_UO|!MBwRSqq)=urzZ|d4w zYo{^{f($aqAi^Lrh)6)fLnMe01`!bv1{p*|1d$*?LO>*h5W=IUzu$d%vsu@1zpsTJ zeea%k&;4`mx#!=#QA#~hN_`#AFW@1#@i_7PQXbB4wy~iK$j{<&;rTf{q?^lhwZ{R7w^YeH(mkqxHgx{nW;>qtG#_?+FkQC-!ta# z+%sm&J+$8ijrwQHG=Gm;QP1_>Mf*L}v#l*pj$wlb2=~mUv9#g$fqbrC8)%d#?Zmbf zpc?)FZ|b}KiNxweB{%njeL@xzxF@P)v?~D0oCBen{92K$nW=OsOLO)_4DQW-L;1A=lXC= zdmn&m_;bANwX-jA8~T87uDfLY7pP}j(rh|V4Su{yqrCa#kNKCm@4Nc-=h1HS@>e+; z>u=KrP)E7Y{`B6WwD;k!fph-5bYc+oxBH<=!{6X-@4@Z)7~kl3sS_^fk)X8UZ-LO) zk`F$VpAC=uE6$roY;^p5^&pGlRd}svYKD)1q8y>2a~%S*k)IwQ4w1H|oSxXJ;y$QsE61 zx>9a8{{j6$M^}(jsI_agk|Lrm40W&x#tcI)3^Qu97DPVE;h`Kx5SNFfazN^oY7gvY z13PA5Pz9;zfCOYXVzUFdHQ$aX{u8KZ>MhDWBmRkq`vj5gw3?_i*~n|lMlghWhKe%94$I=DqD>ki@IVF24qJ82lnFU&EEe znd0TZO&&d=Xyl1i(U6rJQ-<_MK!WO-tZ2MX_TAe;dxJ!eB_$hrajNb_kQ61Hv{dRmGJ+GgQg7q}Goiq7cSu`T%6dAC+~+5SJU=5kjHV z&DmLagUZljbgJUSnM1u0FnDRYRh3{VURj2k$lKhj8;q(VIYZ|UQbozVAet&ws@z}O zXmHODGa&e60qmz!;N1}H`vRpt1b(s3$4V^;_Gm}yRgoE0YD^}S`|7+vRr=8t;Ds&| zHj{Xjw>g4`s=i@BQqfpk7V91_i$nrYsz~DW46F~!ivf9!mflh|%mu31q_x6%LFsV0 z7R2px`Kd4>$;SElV_BG=MLSK;D;vDvSG_eF9cI?mf~7x7wqUSi(l?VxB)qrn3vHdD zHN5*|74I$Sg#MZ_pkp$F_YrmPp&S66qf{M`sEVxVF}y79(-?p?0dDD_gHZt+rQ zR=kc~ndz1^CH`?hj+N??Oh8~89U_C!J=H0uS0EXmTosy91K9@EJGl%CtiI5|3NaOT znQKvHD@L7ai;H+hOjw*J9Bsh6s04u>+wvverPJHdP`gsK7y|&V!*45H5$Y8u7!|rJ zz#%q~@LJ9aSWZc-g5{)K=yF_+O8DIkvxY>Iu0cJXV2gT#M<=0f)nJMVtM;m)PKRq> zi&Uv)c?GlSf0aEf#>^s7u!8UBajkjW{8SnFcrEe4v=Q7DdEq(7$XAo7bh#hkO{h00 zbg+DsOJ}Ar6DyizRwD(c7ZnU)=rn>e#elzb@gObd=H{~6yGgS_!kWmA& zjnD*9*GaYldIRMONo*}8Faq~7#J-^I#i3PZSTDseoQs-Q5ofgruq0cWTL-+OMh4_m zm)QAXjdqUYKC$gdXqKGB$D8vVP4H$oOu1sMY z0P(VJxv4GKl(!S)qerfXDUUvpW|0MGlF-N<=GO`~_rW zD^x?fa%H908Aoh$+B$|#w*s*GTsuy1%gwL~P_5s!L3+O0proc%?V7|V3*iN1g1c0? zW@Z<4T&bK*$>C$Re=vH^_JmHjH^Qv#?%@73v;;N0^U?T{$yk}*azyCMQH@paO3cEV z*5%5=YWL*=iyk_Z%klEpNjV&3kTKwT!H2cAs%B;@7JdZhXJ$l(8wZ_g+!Ek~4n1R% zY@ic3uScJ2Q@elxDmIqKixY$yogb8^P5tTCEl}SuwHlo7U<>75mDu{)sk{fxv6~!Z zoiByxG%DRC3$g3>!y`zDF1H=W$>)z`#c94Pm$5#?R+lWPWUx#80qMX*3o5hRB1ko! zf}y1*8E|HU@V3cJM6!DhwPdz9dIqYMuMYw#IZwanC~WpEX_YQ|lcpveTKcUV54)Md zXz+x?lR0!5mZ{^9a;CFu3~_*d+3;HeQS0)=Z88MFXr&w?8v;5c@jxI%g;d*|15mEu zipBzgz!~y@F^PhtX5~J6P7taLL@685ncdFFCI?o#^@ zEWu$)uSVcpti3`+>C`pqCYQv(pf6#Hj%rmNm+ax>Tjy=kvw;A zBde|lcM0f4f&0_2^TvoCb6PG-hJmKyTtHws_jbmENwabh{Bb=grkF(X~V!4NJH zI}LZnV~sdqFFnL@YEmjLFNx1F-=3B0T4an#d5$dLLd@-5Q%GqqxH?DOq@z}( zQgd=HiBZPpx^rayj7Y9$F)Oc7?gLq_XKV_|vRAIx;YB(dkYfwBz~01hIwU|VEJuUC z&g0pW8IOlD2=mxV_`e|I27`SA(rN<-3+?J$UmXkSxPl{;7>WgZ zsAIl+Mni$+Tc`X5qm5tiIdACtmAVq2N7C^5t%79bk~T2QtB2RLm@|g+7Ky8RNur60 zif0NI3z(IcyS!K6iD}2YCQ&I!TSqTCIDINuHkwiWPS5$uXbZ^{PM|^$=*UXLFi)|_ zOD}o4N~&6(Lsn&9s*&V?w}dpQtJE;Eq7dB`JXMW^T0u$i$_aNQ0eR*~U)S=kN!7^Z ziZsI2P1wsi#AqYJI}yMtVg=9M!Xr3spCckAxx#zEz)G2a_ZP>Rqddkr8f@K^x*;17 zHe~e`ImKxpDLg_E-UxLRP=UHDoJD!wpL?%Qse=-8S7qR3N)q%^Q`*_{wB$O+PzK{{ zone&qNgC=D;@Ra8nMu8v;LRhMGD8OwjJG9eWJ>To;2TCsSe68x1YnS1MZ-NFM&0;pNd~lvS&dyr`l(OWQw@7x?DPAZUKlkP_?bQ%mgrj&NV*eMJ}pGYb(RZ#qm$xhB%6R^ z+-@i}p(S5tUXB>X>UhLVV&0$n)OfN-7_8 z-{}#Wp5nfyA8D7DaYUV-s#*`Vy~^XZPEfVTb^s-%fdEuvRQ8ebw?}7?KXiM$f%hRu zFtI7w3V1iIgw4tOn(kc^k~Jc)x^dR@Q~RGt63Oi1ToQC>SiJiX3v)fdbgE;piUqD3 z$wq$JU)I~g??qfDtfNd%VUq$8?qo>TbbG}32s4#&2}gMN*pror$o3wx&`7p7CfRX4 zrW@=68ofR6C1rGqX0bYuvynGTFfdvjudA{wK9$u>GZj|8E2&TzYbf17612l6IhRAU zf3SjuQb{ZL=8(eP4j7?Vd2Vo=I06!tvr#xLZzE^J-LTp#GFjU8~90d?z z^d;SwDpV2VQ0*zU~)sVvs zYqT72^REUw3Yr4LM6YR&f)4koHMaO{7vfsjL!SO1ctZRoO}c=h&`C%`tID~oXFut(R&Kehv7F0#Z@DZO zMQcQ6;Ig=b1Bxz7OG$5=wda=1p*elBE3|=sX;Kf;wq4P` zRN+)O8@27~$6Xlb`Bd{}@gc-t*jp9JHpS&pL{h0R*!=({kLX0iV)ZBANML$9^)S0A(B9Gmrv{(nso3H#G7qxi@$|hpIVw14swk`T;HlMI2JvHnBQ1#1K^gbsvI?mxyn9j_3Qf~J zF5}{DVv4sX-f*H=UXRnvr(`-6RA*Zu?q@U3z$0oUd69Ktj${_0<*`^S;6&nJ#yAEq z<$-TNC=2rHxX%B94%w1N|^b1>a2@kgZIK&eafAZ4~Ud)a)TWx zzS8IFb)CmQ5!p11E(O-{3btzs=9D{SPR~G)({i literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino new file mode 100644 index 0000000..7eca0be --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino @@ -0,0 +1,219 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 2, using graphics calls plotting direct to the TFT: + tft.drawString(string, x, y); + tft.drawNumber(integer, x, y); + tft.drawFloat(float, dp, x, y); // dp = number of decimal places + + setTextDatum() and setTextPadding() functions work with those draw functions. + + This method is good for static text that does not change often because changing + values may flicker. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 10; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL); // Must load the font first + + tft.drawString("Small 15pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + + // If the string does not fit the screen width, then the next character will wrap to a new line + tft.drawString("Ode To A Small Lump Of Green Putty I Found In My Armpit One Midsummer Morning", xpos, ypos); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Background colour does not match the screen background! + tft.drawString("Anti-aliasing causes odd looking shadow effects if the text and screen background colours are not the same!", xpos, ypos + 60); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE); // Load another different font + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour + + tft.drawString("36pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + // Set text padding to 100 pixels wide area to over-write old values on screen + tft.setTextPadding(100); + + // Draw changing numbers - likely to flicker using this plot method! + for (int i = 0; i <= 20; i++) { + tft.drawFloat(i / 10.0, 1, xpos, ypos); + delay (200); + } + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Setting the 12 datum positions works with free fonts + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + // Integer numbers, floats and strings can be drawn relative to a x,y datum, e.g.: + // tft.drawNumber( 123, x, y); + // tft.drawFloat( 1.23, dp, x, y); // Where dp is number of decimal places to show + // tft.drawString( "Abc", x, y); + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_DARKGREY, TFT_BLACK); + + // Use middle of screen as datum + xpos = tft.width() /2; + ypos = tft.height()/2; + + tft.loadFont(AA_FONT_SMALL); + tft.setTextDatum(TL_DATUM); + tft.drawString("[Top left]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TC_DATUM); + tft.drawString("[Top centre]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TR_DATUM); + tft.drawString("[Top right]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(ML_DATUM); + tft.drawString("[Middle left]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MC_DATUM); + tft.drawString("[Middle centre]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MR_DATUM); + tft.drawString("[Middle right]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BL_DATUM); + tft.drawString("[Bottom left]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BC_DATUM); + tft.drawString("[Bottom centre]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BR_DATUM); + tft.drawString("[Bottom right]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(L_BASELINE); + tft.drawString("[Left baseline]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(C_BASELINE); + tft.drawString("[Centre baseline]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(R_BASELINE); + tft.drawString("[Right baseline]", xpos, ypos); + drawDatumMarker(160,120); + delay(1000); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(4000); + +} + +// Draw a + mark centred on x,y +void drawDatumMarker(int x, int y) +{ + tft.drawLine(x - 5, y, x + 5, y, TFT_GREEN); + tft.drawLine(x, y - 5, x, y + 5, TFT_GREEN); +} diff --git a/examples/Smooth Fonts/Font_Demo_2/Notes.ino b/examples/Smooth Fonts/Font_Demo_2/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino new file mode 100644 index 0000000..5214264 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino @@ -0,0 +1,218 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 3, the font characters are first plotted in a Sprite, then the + Sprite is pushed to the screen. This method is very flexible and the Sprite can be + created, deleted, resized as needed. To render anit-aliased fonts well the Sprite + needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there + will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful + to use the extended Unicode range in fonts on mono displays like ePaper. + + A single Sprite can be re-used for plotting different values and graphics to + different positions on the screen. This makes this method a very powerful display tool, + for example round buttons can be created, making use of transparent colour plotting. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" +#define AA_FONT_MONO "NotoSansMonoSCB20" // NotoSansMono-SemiCondensedBold 20pt +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); +} + +void loop() { + + tft.fillScreen(TFT_DARKGREY); + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class + + spr.createSprite(100, 50); // Create a sprite 100 pixels wide and 50 high + + spr.fillSprite(TFT_BLUE); + + spr.drawRect(0, 0, 100, 50, TFT_WHITE); // Draw sprite border outline (so we see extent) + + spr.setTextColor(TFT_YELLOW, TFT_DARKGREY); // Set the sprite font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("15pt font", 50, 25 ); // Coords of middle of 100 x 50 Sprite + + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.pushSprite(10, 70, TFT_BLUE); // Push to TFT screen, TFT_BLUE is transparent + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + // Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded + // in the tft and sprite instances, so load the font in the class instance you use! + // In this example this means the spr. instance. + + spr.loadFont(AA_FONT_LARGE); // Load another different font into the sprite instance + + // 100 x 50 sprite was created above and still exists... + + spr.fillSprite(TFT_GREEN); + + spr.setTextColor(TFT_BLACK, TFT_GREEN); // Set the font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("Fits", 50, 25); // Make sure text fits in the Sprite! + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.fillSprite(TFT_RED); + spr.setTextColor(TFT_WHITE, TFT_RED); // Set the font colour and the background colour + + spr.drawString("Too big", 50, 25); // Text is too big to all fit in the Sprite! + spr.pushSprite(10, 70); // Push to TFT screen coord 10, 70 + + // Draw changing numbers - no flicker using this plot method! + + // >>>> Note: it is best to use drawNumber() and drawFloat() for numeric values <<<< + // >>>> this reduces digit position movement when the value changes <<<< + // >>>> drawNumber() and drawFloat() functions behave like drawString() and are <<<< + // >>>> supported by setTextDatum() and setTextPadding() <<<< + + spr.setTextDatum(TC_DATUM); // Top Centre datum + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + for (int i = 0; i <= 200; i++) { + spr.fillSprite(TFT_BLUE); + spr.drawFloat(i / 100.0, 2, 50, 10); // draw with 2 decimal places at 50,10 in sprite + spr.pushSprite(10, 130); // Push to TFT screen coord 10, 130 + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + spr.deleteSprite(); // Recover memory + + delay(1000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Mono spaced font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed intercharacter gaps to + // aid formatting + int bnum = 1; + + // Example of drawing buttons + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + int x = 120 + k * 45; + int y = 40 + j * 30; + button(x, y, bnum++); + } + } + + for (int i = 0; i < 100; i++) + { + button(120, 160, i); + delay(50); + } + + spr.unloadFont(); + + delay(8000); +} + +// ######################################################################### +// Draw a number in a rounded rectangle with some transparent pixels +// Load the font before calling +// ######################################################################### +void button(int x, int y, int num ) +{ + + // Size of sprite + #define IWIDTH 40 + #define IHEIGHT 25 + + // Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) + spr.setColorDepth(16); + spr.createSprite(IWIDTH, IHEIGHT); + + // Fill it with black (this will be the transparent colour this time) + spr.fillSprite(TFT_BLACK); + + // Draw a background for the numbers + spr.fillRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_RED); + spr.drawRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_WHITE); + + // Set the font parameters + + // Set text coordinate datum to middle centre + spr.setTextDatum(MC_DATUM); + + // Set the font colour and the background colour + spr.setTextColor(TFT_WHITE, TFT_RED); + + // Draw the number + spr.drawNumber(num, IWIDTH/2, 1 + IHEIGHT/2); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // All black pixels will not be drawn hence will show as "transparent" + spr.pushSprite(x, y, TFT_BLACK); + + // Delete sprite to free up the RAM + spr.deleteSprite(); +} diff --git a/examples/Smooth Fonts/Font_Demo_3/Notes.ino b/examples/Smooth Fonts/Font_Demo_3/Notes.ino new file mode 100644 index 0000000..bdab3d0 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Notes.ino @@ -0,0 +1,61 @@ +/* + +Information notes only: +====================== + +Note: it is best to use drawNumber() and drawFloat() for numeric values + this reduces digit position movement when the value changes + drawNumber() and drawFloat() functions behave like drawString() and are + supported by setTextDatum() and setTextPadding() + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw new file mode 100644 index 0000000000000000000000000000000000000000..4045c621230f1d184991a5a74bf14d0785e2b913 GIT binary patch literal 15382 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 + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class + + spr.setTextColor(TFT_YELLOW, TFT_BLACK); // Set the sprite font colour and the background colour + + tft.setCursor(xpos - 50, ypos); // Set the tft cursor position, yes tft position! + spr.printToSprite("Small 15pt font"); // Prints to tft cursor position, tft cursor NOT moved + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + spr.loadFont(AA_FONT_LARGE); // Load another different font + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + tft.setCursor(xpos - 90, ypos); // Set the tft cursor position + spr.printToSprite("36pt font"); // Text is rendered via a minimally sized sprite + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + // Draw changing numbers - no flicker using this plot method! + for (int i = 0; i <= 200; i++) { + tft.setCursor(10, 10); + // Number is converted to String type by (String) (number) + spr.printToSprite(" " + (String) (i / 100.0) + " "); // Space padding helps over-write old numbers + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/Font_Demo_4/Notes.ino b/examples/Smooth Fonts/Font_Demo_4/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_4/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw new file mode 100644 index 0000000000000000000000000000000000000000..803a1bd9748c922e455e4952f08368ce634f96f4 GIT binary patch literal 10766 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 literal 0 HcmV?d00001 diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw new file mode 100644 index 0000000000000000000000000000000000000000..66003f6e1c9915e71f571ade912b9eb899323db6 GIT binary patch literal 44169 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 K_&W^#+W!ZD7G}`^ literal 0 HcmV?d00001 diff --git a/keywords.txt b/keywords.txt index 53b0825..b197c5a 100644 --- a/keywords.txt +++ b/keywords.txt @@ -36,6 +36,7 @@ getCursorY KEYWORD2 setTextColor KEYWORD2 setTextSize KEYWORD2 setTextFont KEYWORD2 +setFreeFont KEYWORD2 setTextWrap KEYWORD2 setTextDatum KEYWORD2 setTextPadding KEYWORD2 diff --git a/library.json b/library.json index 15bfb8b..ceaa20f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.0.2", + "version": "1.1.0", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index dd9055a..8e9b396 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=TFT_eSPI -version=1.0.2 +version=1.1.0 author=Bodmer maintainer=Bodmer -sentence=A fast TFT library for ESP8266 and ESP32 processors for the Arduino IDE -paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI. +sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE +paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI or 8 bit parallel. category=Display url=https://github.com/Bodmer/TFT_eSPI architectures=esp8266,esp32 From 9666314eb6bf4831070405d89aee0611b85fec29 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 21 Oct 2018 21:22:20 +0100 Subject: [PATCH 13/94] Support for ESP32 PSRAM added If PSRAM is fitted and enabled the Sprites are now created in PSRAM. This makes multiple full screen buffers possible! --- Extensions/Sprite.cpp | 16 +++++++++++++++- README.md | 2 ++ library.json | 2 +- library.properties | 2 +- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index acfc315..73285da 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -67,7 +67,13 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) // hence will run faster in normal circumstances. if (_bpp == 16) { + +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) _img8_1 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint16_t)); + else +#endif _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); + _img8_2 = _img8_1; _img = (uint16_t*) _img8_1; @@ -80,6 +86,10 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) else if (_bpp == 8) { +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) _img8_1 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); + else +#endif _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); if (_img8_1) @@ -103,7 +113,11 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) if (frames > 2) frames = 2; // Currently restricted to 2 frame buffers if (frames < 1) frames = 1; - _img8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); // extra pixel added +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) _img8 = ( uint8_t*) ps_calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); + else +#endif + _img8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); if (_img8) { diff --git a/README.md b/README.md index bb2dfd5..b61fc76 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ Drawing graphics into a sprite is very fast, for those familiar with the Adafrui Sprites can be plotted to the TFT with one colour being specified as "transparent", see Transparent_Sprite_Demo example. +IF an ESP32 board with SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. + The XPT2046 touch screen controller is supported. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. The Button class from Adafruit_GFX is incorporated, with the enhancement that the button labels can be in any font. diff --git a/library.json b/library.json index ceaa20f..81f4046 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.0", + "version": "1.1.1", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 8e9b396..6b18d6b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.0 +version=1.1.1 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 2ba492c1d30bc66f9acd53fa34907c7e0bf72735 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 21 Oct 2018 21:23:40 +0100 Subject: [PATCH 14/94] Correct typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b61fc76..4f91bca 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Drawing graphics into a sprite is very fast, for those familiar with the Adafrui Sprites can be plotted to the TFT with one colour being specified as "transparent", see Transparent_Sprite_Demo example. -IF an ESP32 board with SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. +If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. The XPT2046 touch screen controller is supported. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. From d12a68a49dcff9baf75ed23636f374c69a6c10c4 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 21 Oct 2018 21:57:30 +0100 Subject: [PATCH 15/94] Add checks in examples for missing font files --- examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino | 12 ++++++++++++ examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino | 12 ++++++++++++ examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino | 13 +++++++++++++ examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino | 12 ++++++++++++ 4 files changed, 49 insertions(+) diff --git a/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino index 0d24af9..e38a5ee 100644 --- a/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino +++ b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino @@ -59,6 +59,18 @@ void setup(void) { while (1) yield(); // Stay here twiddling thumbs waiting } Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); } diff --git a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino index 7eca0be..a2ef436 100644 --- a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino +++ b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino @@ -53,6 +53,18 @@ void setup(void) { while (1) yield(); // Stay here twiddling thumbs waiting } Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); } void loop() { diff --git a/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino index 5214264..ebc2055 100644 --- a/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino +++ b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino @@ -57,6 +57,19 @@ void setup(void) { while (1) yield(); // Stay here twiddling thumbs waiting } Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansMonoSCB20.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); } void loop() { diff --git a/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino index f8ce4c1..edad83c 100644 --- a/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino +++ b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino @@ -68,6 +68,18 @@ void setup(void) { while (1) yield(); // Stay here twiddling thumbs waiting } Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); } void loop() { From b93a40a54fd8a530cc31abf60b6f8696ba1d1fb5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 23 Oct 2018 14:20:45 +0100 Subject: [PATCH 16/94] Correct datum marker for different screen sizes datum marker was not in correct position on screens that are not 320x240 pixels --- .../Smooth Fonts/Font_Demo_2/Font_Demo_2.ino | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino index a2ef436..6dbf769 100644 --- a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino +++ b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino @@ -148,73 +148,73 @@ void loop() { tft.loadFont(AA_FONT_SMALL); tft.setTextDatum(TL_DATUM); tft.drawString("[Top left]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(TC_DATUM); tft.drawString("[Top centre]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(TR_DATUM); tft.drawString("[Top right]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(ML_DATUM); tft.drawString("[Middle left]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(MC_DATUM); tft.drawString("[Middle centre]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(MR_DATUM); tft.drawString("[Middle right]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(BL_DATUM); tft.drawString("[Bottom left]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(BC_DATUM); tft.drawString("[Bottom centre]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(BR_DATUM); tft.drawString("[Bottom right]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(L_BASELINE); tft.drawString("[Left baseline]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(C_BASELINE); tft.drawString("[Centre baseline]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.fillScreen(TFT_BLACK); tft.setTextDatum(R_BASELINE); tft.drawString("[Right baseline]", xpos, ypos); - drawDatumMarker(160,120); + drawDatumMarker(xpos, ypos); delay(1000); tft.unloadFont(); // Remove the font to recover memory used From 1e1525010e4469cabd92e93272253be8ae4cc140 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 24 Oct 2018 09:58:20 +0100 Subject: [PATCH 17/94] Fix issue #225 --- TFT_eSPI.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index aeb0766..afaedd1 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4160,7 +4160,11 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) uint16_t cheight = 8 * textsize; #ifdef LOAD_GFXFF - bool freeFont = (font == 1 && gfxFont && !fontLoaded); + #ifdef SMOOTH_FONT + bool freeFont = (font == 1 && gfxFont && !fontLoaded); + #else + bool freeFont = (font == 1 && gfxFont); + #endif if (freeFont) { cheight = glyph_ab * textsize; From d18a5a0c8fb6d9bbcf44d9080f81d47bf9d14c4b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 24 Oct 2018 09:59:26 +0100 Subject: [PATCH 18/94] Revert "Fix issue #225" This reverts commit 1e1525010e4469cabd92e93272253be8ae4cc140. --- TFT_eSPI.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index afaedd1..aeb0766 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4160,11 +4160,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) uint16_t cheight = 8 * textsize; #ifdef LOAD_GFXFF - #ifdef SMOOTH_FONT - bool freeFont = (font == 1 && gfxFont && !fontLoaded); - #else - bool freeFont = (font == 1 && gfxFont); - #endif + bool freeFont = (font == 1 && gfxFont && !fontLoaded); if (freeFont) { cheight = glyph_ab * textsize; From 3d5ff73690edb48f29c1a46cc88bd4a41e0b4e33 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 24 Oct 2018 10:00:33 +0100 Subject: [PATCH 19/94] Fix issue #224 --- TFT_eSPI.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index aeb0766..afaedd1 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4160,7 +4160,11 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) uint16_t cheight = 8 * textsize; #ifdef LOAD_GFXFF - bool freeFont = (font == 1 && gfxFont && !fontLoaded); + #ifdef SMOOTH_FONT + bool freeFont = (font == 1 && gfxFont && !fontLoaded); + #else + bool freeFont = (font == 1 && gfxFont); + #endif if (freeFont) { cheight = glyph_ab * textsize; From 38d99a53dd96c8892cd7ce30ebee000e2f5abe94 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 4 Nov 2018 20:41:10 +0000 Subject: [PATCH 20/94] Issue #232 --- TFT_Drivers/ST7789_Rotation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 34ba394..94be726 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -22,13 +22,13 @@ _width = _init_width; _height = _init_height; colstart = 0; - rowstart = 80; + rowstart = 0; break; case 3: // Inverted landscape writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_height; _height = _init_width; - colstart = 80; + colstart = 0; rowstart = 0; break; } From ffef37a22d43fee55791cd1a3295e59f7130cbe6 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 4 Nov 2018 20:46:39 +0000 Subject: [PATCH 21/94] Revert "Issue #232" This reverts commit 38d99a53dd96c8892cd7ce30ebee000e2f5abe94. --- TFT_Drivers/ST7789_Rotation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 94be726..34ba394 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -22,13 +22,13 @@ _width = _init_width; _height = _init_height; colstart = 0; - rowstart = 0; + rowstart = 80; break; case 3: // Inverted landscape writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_height; _height = _init_width; - colstart = 0; + colstart = 80; rowstart = 0; break; } From d5f582cbbb46ed446e62cb09d3de1c557ac0ef61 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 5 Nov 2018 22:34:15 +0000 Subject: [PATCH 22/94] Version not raised for #224 change --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 6b18d6b..b8383c8 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.1 +version=1.1.2 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 8d29c396e3568e95a9c961489c8b233853ef9924 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 5 Nov 2018 22:34:45 +0000 Subject: [PATCH 23/94] Version not raised for #224 change --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 81f4046..350069f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.1", + "version": "1.1.2", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": From cbc2e66dfd43207267909945be13de33bbe6fe81 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 6 Nov 2018 00:41:14 +0000 Subject: [PATCH 24/94] Update for WROVER to address #232 The library supported 240x240 ST7789 displays only which require an 80 pixel offset in rotation 2 and 3 The library now also supports the 240x320 display which has a different RGB colour order. --- TFT_Drivers/ST7789_Defines.h | 4 +- TFT_Drivers/ST7789_Init.h | 9 +++- TFT_Drivers/ST7789_Rotation.h | 26 ++++++---- User_Setup.h | 23 ++++++--- User_Setups/SetupX_Template.h | 91 ++++++++++++++++++++++++++--------- library.json | 2 +- library.properties | 2 +- 7 files changed, 112 insertions(+), 45 deletions(-) diff --git a/TFT_Drivers/ST7789_Defines.h b/TFT_Drivers/ST7789_Defines.h index 5a0d1be..06f2a39 100644 --- a/TFT_Drivers/ST7789_Defines.h +++ b/TFT_Drivers/ST7789_Defines.h @@ -7,7 +7,9 @@ #define TFT_HEIGHT 320 #endif -#define CGRAM_OFFSET +#if (TFT_HEIGHT == 240) && (TFT_WIDTH == 240) + #define CGRAM_OFFSET +#endif // Delay between some initialisation commands #define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index 9b69cb4..4afd2cc 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -14,7 +14,12 @@ //------------------------------display and color format setting--------------------------------// writecommand(ST7789_MADCTL); writedata(0x00); - writedata(0x48); +#ifdef CGRAM_OFFSET + writedata(0x48); // BGR colour order for 240 x 240 TFT +#else + writedata(0x40); // RGB colour order for 240 x 320 TFT (Issue #232) +#endif + // JLX240 display datasheet writecommand(0xB6); @@ -114,7 +119,9 @@ writecommand(ST7789_DISPON); //Display on +#ifdef TFT_BL // Turn on the back-light LED digitalWrite(TFT_BL, HIGH); pinMode(TFT_BL, OUTPUT); +#endif } diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 34ba394..8c526ad 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -7,28 +7,36 @@ writedata(TFT_MAD_RGB); _width = _init_width; _height = _init_height; +#ifdef CGRAM_OFFSET colstart = 0; rowstart = 0; +#endif break; case 1: // Landscape (Portrait + 90) writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); _width = _init_height; _height = _init_width; - colstart = 0; - rowstart = 0; - break; +#ifdef CGRAM_OFFSET + colstart = 0; + rowstart = 0; +#endif + break; case 2: // Inverter portrait writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_width; _height = _init_height; - colstart = 0; - rowstart = 80; - break; +#ifdef CGRAM_OFFSET + colstart = 0; + rowstart = 80; +#endif + break; case 3: // Inverted landscape writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_height; _height = _init_width; - colstart = 80; - rowstart = 0; - break; +#ifdef CGRAM_OFFSET + colstart = 80; + rowstart = 0; +#endif + break; } diff --git a/User_Setup.h b/User_Setup.h index a91a719..dd3d42a 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -24,16 +24,19 @@ //#define ILI9481_DRIVER //#define ILI9486_DRIVER //#define ILI9488_DRIVER -//#define ST7789_DRIVER +//#define ST7789_DRIVER // Define the screen size below for this display // For M5Stack ESP32 module with integrated display ONLY, remove // in line below //#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation // #define TFT_WIDTH 80 // #define TFT_WIDTH 128 +// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 // #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 +// #define TFT_HEIGHT 128 +// #define TFT_HEIGHT 240 // ST7789 240 x 240 +// #define TFT_HEIGHT 320 // ST7789 240 x 320 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -46,10 +49,10 @@ // #define ST7735_GREENTAB // #define ST7735_GREENTAB2 // #define ST7735_GREENTAB3 -// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB128 // For 128 x 128 display // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) // #define ST7735_REDTAB -//#define ST7735_BLACKTAB +// #define ST7735_BLACKTAB // ################################################################################## // @@ -94,7 +97,9 @@ #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) //#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen @@ -124,10 +129,12 @@ //#define TFT_MISO 19 //#define TFT_MOSI 23 //#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin +//#define TFT_CS 15 // Chip select control pin //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) + // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -136,7 +143,7 @@ //#define TFT_CS 14 // Chip select control pin //#define TFT_DC 27 // Data Command control pin //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light +//#define TFT_BL 32 // LED back-light (required for M5Stack) //#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index f321517..dd3d42a 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -6,6 +6,7 @@ // // If this file is edited correctly then all the library example sketches should // run without the need to make any more changes for a particular hardware setup! +// Note that some sketches are designed for a particular TFT pixel width/height // ################################################################################## // @@ -19,15 +20,23 @@ //#define ILI9163_DRIVER //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9486_DRIVER +//#define ILI9488_DRIVER +//#define ST7789_DRIVER // Define the screen size below for this display // For M5Stack ESP32 module with integrated display ONLY, remove // in line below //#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 80 -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 +// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// #define TFT_WIDTH 80 +// #define TFT_WIDTH 128 +// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 +// #define TFT_HEIGHT 160 +// #define TFT_HEIGHT 128 +// #define TFT_HEIGHT 240 // ST7789 240 x 240 +// #define TFT_HEIGHT 320 // ST7789 240 x 320 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -36,14 +45,14 @@ // Comment out ALL BUT ONE of these options for a ST7735 display driver, save this // this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB +// #define ST7735_INITB +// #define ST7735_GREENTAB +// #define ST7735_GREENTAB2 +// #define ST7735_GREENTAB3 +// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) +// #define ST7735_REDTAB +// #define ST7735_BLACKTAB // ################################################################################## // @@ -88,9 +97,11 @@ #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen +//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) + +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen //#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only @@ -118,14 +129,12 @@ //#define TFT_MISO 19 //#define TFT_MOSI 23 //#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin +//#define TFT_CS 15 // Chip select control pin //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) -//#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -134,8 +143,40 @@ //#define TFT_CS 14 // Chip select control pin //#define TFT_DC 27 // Data Command control pin //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light +//#define TFT_BL 32 // LED back-light (required for M5Stack) +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 // ################################################################################## // @@ -167,9 +208,9 @@ #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts // Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded @@ -202,9 +243,11 @@ // #define SPI_FREQUENCY 20000000 #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 53400000 // #define SPI_FREQUENCY 80000000 +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 20000000 + // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 @@ -219,4 +262,4 @@ // Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) // so changing it here has no effect -// #define SUPPORT_TRANSACTIONS +//#define SUPPORT_TRANSACTIONS diff --git a/library.json b/library.json index 350069f..70c37a9 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.2", + "version": "1.1.3", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index b8383c8..ac3cd85 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.2 +version=1.1.3 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From d4ff3c8dce57e2269c6c5784d4ea7be73ba850d2 Mon Sep 17 00:00:00 2001 From: Gavin Smalley Date: Wed, 7 Nov 2018 14:56:27 +0000 Subject: [PATCH 25/94] Add support for red-tabbed 80x160 screen. --- TFT_Drivers/ST7735_Defines.h | 5 +++++ TFT_Drivers/ST7735_Init.h | 6 ++++++ TFT_Drivers/ST7735_Rotation.h | 16 ++++++++++++++++ User_Setup.h | 1 + 4 files changed, 28 insertions(+) diff --git a/TFT_Drivers/ST7735_Defines.h b/TFT_Drivers/ST7735_Defines.h index 35e9659..82a3c30 100644 --- a/TFT_Drivers/ST7735_Defines.h +++ b/TFT_Drivers/ST7735_Defines.h @@ -16,6 +16,7 @@ #define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen #define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 #define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html #define INITB 0xB @@ -42,6 +43,10 @@ #elif defined (ST7735_GREENTAB160x80) #define TAB_COLOUR INITR_GREENTAB160x80 #define CGRAM_OFFSET + +#elif defined (ST7735_REDTAB160x80) + #define TAB_COLOUR INITR_REDTAB160x80 + #define CGRAM_OFFSET #elif defined (ST7735_REDTAB) #define TAB_COLOUR INITR_REDTAB diff --git a/TFT_Drivers/ST7735_Init.h b/TFT_Drivers/ST7735_Init.h index 3eef1d9..a528785 100644 --- a/TFT_Drivers/ST7735_Init.h +++ b/TFT_Drivers/ST7735_Init.h @@ -180,6 +180,12 @@ colstart = 26; rowstart = 1; } + else if (tabcolor == INITR_REDTAB160x80) + { + commandList(Rcmd2green); + colstart = 24; + rowstart = 0; + } else if (tabcolor == INITR_REDTAB) { commandList(Rcmd2red); diff --git a/TFT_Drivers/ST7735_Rotation.h b/TFT_Drivers/ST7735_Rotation.h index 89701f7..fba6419 100644 --- a/TFT_Drivers/ST7735_Rotation.h +++ b/TFT_Drivers/ST7735_Rotation.h @@ -24,6 +24,10 @@ writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); colstart = 26; rowstart = 1; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); + colstart = 24; + rowstart = 0; } else if(tabcolor == INITB) { writedata(TFT_MAD_MX | TFT_MAD_RGB); } else { @@ -51,6 +55,10 @@ writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 1; rowstart = 26; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); + colstart = 0; + rowstart = 24; } else if(tabcolor == INITB) { writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); } else { @@ -78,6 +86,10 @@ writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_BGR); + colstart = 0; + rowstart = 0; } else if(tabcolor == INITB) { writedata(TFT_MAD_MY | TFT_MAD_RGB); } else { @@ -105,6 +117,10 @@ writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 1; rowstart = 26; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); + colstart = 0; + rowstart = 24; } else if(tabcolor == INITB) { writedata(TFT_MAD_MV | TFT_MAD_RGB); } else { diff --git a/User_Setup.h b/User_Setup.h index dd3d42a..9b2359c 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -53,6 +53,7 @@ // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) // #define ST7735_REDTAB // #define ST7735_BLACKTAB +// #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) // ################################################################################## // From 8d3a4d09bd77313f5f191726b6feef6f23cc658a Mon Sep 17 00:00:00 2001 From: Gavin Smalley Date: Wed, 7 Nov 2018 15:29:29 +0000 Subject: [PATCH 26/94] Correct rotation 2 for red-tabbed 80x160 screen. --- TFT_Drivers/ST7735_Rotation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_Drivers/ST7735_Rotation.h b/TFT_Drivers/ST7735_Rotation.h index fba6419..6163abb 100644 --- a/TFT_Drivers/ST7735_Rotation.h +++ b/TFT_Drivers/ST7735_Rotation.h @@ -88,7 +88,7 @@ rowstart = 0; } else if(tabcolor == INITR_REDTAB160x80) { writedata(TFT_MAD_BGR); - colstart = 0; + colstart = 24; rowstart = 0; } else if(tabcolor == INITB) { writedata(TFT_MAD_MY | TFT_MAD_RGB); From 2aeb09db38d0ff6ddd9e56c6b87d9de96130dde3 Mon Sep 17 00:00:00 2001 From: Gavin Smalley Date: Thu, 8 Nov 2018 10:32:40 +0000 Subject: [PATCH 27/94] Bump version and add option for red-tabbed 160x80 screen support to SetupX_Template.h --- User_Setups/SetupX_Template.h | 1 + library.json | 2 +- library.properties | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index dd3d42a..9b2359c 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -53,6 +53,7 @@ // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) // #define ST7735_REDTAB // #define ST7735_BLACKTAB +// #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) // ################################################################################## // diff --git a/library.json b/library.json index 70c37a9..496bd2e 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.3", + "version": "1.1.4", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index ac3cd85..fd62f0e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.3 +version=1.1.4 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From beb9bb3360ccd1d8ae5b4ac0429f1d11b12495c0 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 9 Nov 2018 09:17:13 +0000 Subject: [PATCH 28/94] Add link for UNO style boards with touch screen display --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 4f91bca..a010d0c 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,8 @@ IO32 wired to IO36 ![Example](https://i.imgur.com/pUZn6lF.jpg) +If the display board is fitted with a resistance based touch screen then this can be used by performing the modifications described here and the fork of the Adafruit library: +https://github.com/s60sc/Adafruit_TouchScreen # ePaper displays From 21811b1751f0c6d0edc1a42564bc9a923b2aecfa Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 11 Nov 2018 10:44:12 +0000 Subject: [PATCH 29/94] Correct colour oder for ST7789 240x320 TFT --- TFT_Drivers/ST7789_Rotation.h | 52 +++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 8c526ad..74a5b9f 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -3,40 +3,50 @@ writecommand(TFT_MADCTL); rotation = m % 4; switch (rotation) { - case 0: // Portrait - writedata(TFT_MAD_RGB); - _width = _init_width; - _height = _init_height; -#ifdef CGRAM_OFFSET - colstart = 0; - rowstart = 0; -#endif - break; - case 1: // Landscape (Portrait + 90) - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); - _width = _init_height; - _height = _init_width; + case 0: // Portrait #ifdef CGRAM_OFFSET + writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; +#else + writedata(TFT_MAD_RGB); #endif - break; - case 2: // Inverter portrait - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_width; _height = _init_height; + break; + + case 1: // Landscape (Portrait + 90) #ifdef CGRAM_OFFSET + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 0; - rowstart = 80; + rowstart = 0; +#else + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); #endif - break; - case 3: // Inverted landscape - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); _width = _init_height; _height = _init_width; + break; + + case 2: // Inverter portrait #ifdef CGRAM_OFFSET + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); + colstart = 0; + rowstart = 80; +#else + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); +#endif + _width = _init_width; + _height = _init_height; + break; + case 3: // Inverted landscape +#ifdef CGRAM_OFFSET + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 80; rowstart = 0; +#else + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); #endif - break; + _width = _init_height; + _height = _init_width; + break; } From 7a3d6bcab9c1ef906e17a9b80ab4da19425d4eb1 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 14 Nov 2018 01:05:16 +0000 Subject: [PATCH 30/94] Minor performance improvements for ESP32 Remove legacy changes for double buffered SPI Eliminate unecessary ESP32 SPI read/modify write Eliminate two stage control bit changes (may impact some diplays with setup/hold timing and show ESP32 hardware register bug?) Add single register write for CS and DC command Make setAddrWindow smarter (as used in previous AVR library) Improve compatibility with GFX sketches Re-arrange comments slightly to improve positioning --- Extensions/Smooth_font.cpp | 7 +- TFT_Drivers/ST7735_Defines.h | 16 +-- TFT_eSPI.cpp | 238 ++++++++++++++++++++-------------- TFT_eSPI.h | 130 ++++++++++++++----- User_Setup.h | 12 +- User_Setups/SetupX_Template.h | 23 ++-- keywords.txt | 3 + library.json | 2 +- library.properties | 2 +- 9 files changed, 275 insertions(+), 158 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 7d573be..fe77885 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -78,6 +78,12 @@ void TFT_eSPI::loadFont(String fontName) _gFontFilename = "/" + fontName + ".vlw"; + // Avoid a crash on the ESP32 if the file does not exist + if (SPIFFS.exists(_gFontFilename) == false) { + Serial.println("Font file " + fontName + " not found!"); + return; + } + fontFile = SPIFFS.open( _gFontFilename, "r"); if(!fontFile) return; @@ -479,7 +485,6 @@ void TFT_eSPI::drawGlyph(uint16_t code) void TFT_eSPI::showFont(uint32_t td) { if(!fontLoaded) return; -// fontFile = SPIFFS.open( _gFontFilename, "r" ); if(!fontFile) { diff --git a/TFT_Drivers/ST7735_Defines.h b/TFT_Drivers/ST7735_Defines.h index 82a3c30..494c673 100644 --- a/TFT_Drivers/ST7735_Defines.h +++ b/TFT_Drivers/ST7735_Defines.h @@ -9,15 +9,15 @@ // Enumerate the different configurations -#define INITR_GREENTAB 0x0 -#define INITR_REDTAB 0x1 -#define INITR_BLACKTAB 0x2 -#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display -#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen -#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_GREENTAB 0x0 +#define INITR_REDTAB 0x1 +#define INITR_BLACKTAB 0x2 // Display with no offsets +#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display +#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen +#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 #define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1 -#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html -#define INITB 0xB +#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html +#define INITB 0xB // Setup the tab color that will be used by the library setRotation() and setup command list diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index afaedd1..10f9bb3 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -185,8 +185,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) _booted = true; - addr_row = 0xFFFF; - addr_col = 0xFFFF; + ys_row = ye_row = addr_row = 0xFFFF; + xs_col = xe_col = addr_col = 0xFFFF; #ifdef LOAD_GLCD fontsloaded = 0x0002; // Bit 1 set @@ -530,7 +530,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) CS_L; tft_Write_8(cmd_function); DC_D; - reg = tft_Write_8(0); + reg = tft_Read_8(0); CS_H; spi_end_read(); @@ -628,15 +628,15 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - uint8_t r = tft_Write_8(0); - uint8_t g = tft_Write_8(0); - uint8_t b = tft_Write_8(0); + uint8_t r = tft_Read_8(0); + uint8_t g = tft_Read_8(0); + uint8_t b = tft_Read_8(0); #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left - uint8_t r = (tft_Write_8(0)&0x7E)<<1; - uint8_t g = (tft_Write_8(0)&0x7E)<<1; - uint8_t b = (tft_Write_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8(0)&0x7E)<<1; + uint8_t g = (tft_Read_8(0)&0x7E)<<1; + uint8_t b = (tft_Read_8(0)&0x7E)<<1; #endif CS_H; @@ -768,15 +768,15 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - uint8_t r = tft_Write_8(0); - uint8_t g = tft_Write_8(0); - uint8_t b = tft_Write_8(0); + uint8_t r = tft_Read_8(0); + uint8_t g = tft_Read_8(0); + uint8_t b = tft_Read_8(0); #else // The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left - uint8_t r = (tft_Write_8(0)&0x7E)<<1; - uint8_t g = (tft_Write_8(0)&0x7E)<<1; - uint8_t b = (tft_Write_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8(0)&0x7E)<<1; + uint8_t g = (tft_Read_8(0)&0x7E)<<1; + uint8_t b = (tft_Read_8(0)&0x7E)<<1; #endif // Swapped colour byte order for compatibility with pushRect() @@ -1354,15 +1354,15 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - *data++ = tft_Write_8(0); - *data++ = tft_Write_8(0); - *data++ = tft_Write_8(0); + *data++ = tft_Read_8(0); + *data++ = tft_Read_8(0); + *data++ = tft_Read_8(0); #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left - *data++ = (tft_Write_8(0)&0x7E)<<1; - *data++ = (tft_Write_8(0)&0x7E)<<1; - *data++ = (tft_Write_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; + *data++ = (tft_Read_8(0)&0x7E)<<1; #endif } @@ -2473,7 +2473,7 @@ void TFT_eSPI::setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) // Chip select stays low, use setWindow() from sketches #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER) -inline void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { //spi_begin(); @@ -2563,8 +2563,8 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t xBin[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; + SPI.writePattern(&xb[0], 8, 1); // Row addr set DC_C; @@ -2577,8 +2577,8 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t yBin[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; + SPI.writePattern(&yb[0], 8, 1); // write to RAM DC_C; @@ -2596,7 +2596,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #else #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2673,7 +2673,7 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t #else // This is for the ESP32 -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2687,42 +2687,48 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; -#endif + CS_L_DC_C; - // Column addr set - DC_C; - CS_L; + // No need to send x if it has not changed (small speed-up of complex transparent Sprites and bitmaps) + // Nb: caller must fill the set address area so that setting same area again will fill from xs, ys + if (xs_col != x0 || xe_col != x1) { + // Column addr set - tft_Write_8(TFT_CASET); + tft_Write_8(TFT_CASET); - DC_D; + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; + SPI.writePattern(&xb[0], 8, 1); #else - tft_Write_32(xaw); + tft_Write_32(SPI_32(x0, x1)); #endif - // Row addr set - DC_C; - tft_Write_8(TFT_PASET); + DC_C; + xs_col = x0; xe_col = x1; + } - DC_D; + // No need to send y if it has not changed + if (ys_row != y0 || ye_row != y1) { + + // Row addr set + tft_Write_8(TFT_PASET); + + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; + SPI.writePattern(&yb[0], 8, 1); #else - tft_Write_32(yaw); + tft_Write_32(SPI_32(y0, y1)); #endif + DC_C; + ys_row = y0; ye_row = y1; + } + // write to RAM - DC_C; - tft_Write_8(TFT_RAMWR); DC_D; @@ -2819,19 +2825,15 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) y1+=rowstart; #endif - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; - // Column addr set - DC_C; - CS_L; + CS_L_DC_C; tft_Write_8(TFT_CASET); DC_D; - tft_Write_32(xaw); + tft_Write_32(SPI_32(x0, x1)); // Row addr set DC_C; @@ -2840,7 +2842,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; - tft_Write_32(yaw); + tft_Write_32(SPI_32(y0, y1)); DC_C; tft_Write_8(TFT_RAMRD); // Read CGRAM command @@ -3053,52 +3055,49 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) y+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x << 16) | x; - uint32_t yaw = ((uint32_t)y << 16) | y; -#endif - - CS_L; + CS_L_DC_C; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { - DC_C; - tft_Write_8(TFT_CASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; + SPI.writePattern(&xb[0], 8, 1); #else - tft_Write_32(xaw); + tft_Write_32(SPI_32(x, x)); #endif - + + DC_C; + addr_col = x; + xs_col = xe_col = x; + } // No need to send y if it has not changed (speeds things up) if (addr_row != y) { - DC_C; - tft_Write_8(TFT_PASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; + SPI.writePattern(&yb[0], 8, 1); #else - tft_Write_32(yaw); + tft_Write_32(SPI_32(y, y)); #endif + DC_C; + addr_row = y; + ys_row = ye_row = y; } - DC_C; tft_Write_8(TFT_RAMWR); @@ -3159,6 +3158,48 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) spi_end(); } +/*************************************************************************************** +** Function name: startWrite +** Description: begin transaction with CS low, MUST later call endWrite +***************************************************************************************/ +void TFT_eSPI::startWrite(void) +{ + spi_begin(); + + CS_L; +} + +/*************************************************************************************** +** Function name: endWrite +** Description: end transaction with CS high +***************************************************************************************/ +void TFT_eSPI::endWrite(void) +{ + + CS_H; + + spi_end(); +} + +/*************************************************************************************** +** Function name: writeColor (use startWrite() and endWrite() before & after) +** Description: raw write of "len" pixels avoiding transaction check +***************************************************************************************/ +void TFT_eSPI::writeColor(uint16_t color, uint32_t len) +{ +#ifdef RPI_WRITE_STROBE + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; + while(len--) {WR_L; WR_H;} +#else + #if defined (ESP32_PARALLEL) + while (len--) {tft_Write_16(color);} + #else + writeBlock(color, len); + #endif +#endif +} + /*************************************************************************************** ** Function name: pushColors ** Description: push an array of pixels for 16 bit raw image drawing @@ -4655,7 +4696,7 @@ void writeBlock(uint16_t color, uint32_t repeat) #elif defined (ILI9488_DRIVER) #ifdef ESP8266 -void writeBlock(uint16_t color, uint32_t repeat) +void TFT_eSPI::writeBlock(uint16_t color, uint32_t repeat) { uint32_t mask = ~(SPIMMOSI << SPILMOSI); @@ -4722,9 +4763,6 @@ void writeBlock(uint16_t color, uint32_t repeat) } #else // Now the code for ESP32 and ILI9488 -#include "soc/spi_reg.h" -#define SPI_NUM 0x3 - void writeBlock(uint16_t color, uint32_t repeat) { // Split out the colours @@ -4795,38 +4833,46 @@ void writeBlock(uint16_t color, uint32_t repeat) #else // Low level register based ESP32 code for 16 bit colour SPI TFTs -#include "soc/spi_reg.h" -#define SPI_NUM 0x3 - - void writeBlock(uint16_t color, uint32_t repeat) { - uint16_t color16 = (color >> 8) | (color << 8); - uint32_t color32 = color16 | color16 << 16; + uint32_t color32 = SPI_32(color, color); - if (repeat > 15) + if (repeat > 31) // Revert legacy toggle buffer change { - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 255, SPI_USR_MOSI_DBITLEN_S); - - while(repeat>15) + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 511); + while(repeat>31) { while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - for (uint32_t i=0; i<8; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), color32); + WRITE_PERI_REG(SPI_W15_REG(SPI_NUM), color32); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - repeat -= 16; + repeat -= 32; } while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); } if (repeat) { - repeat = (repeat << 4) - 1; - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, repeat, SPI_USR_MOSI_DBITLEN_S); - for (uint32_t i=0; i<8; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); + // Revert toggle buffer change + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), (repeat << 4) - 1); + for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); } - } #endif @@ -4975,10 +5021,6 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) #include "Extensions/Sprite.cpp" -// #ifdef ESP32 -// #include "Extensions/pSprite.cpp" -// #endif - #ifdef SMOOTH_FONT #include "Extensions/Smooth_font.cpp" #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 2c93392..456b066 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -103,6 +103,11 @@ #include +#ifdef ESP32 + #include "soc/spi_reg.h" + #define SPI_NUM 0x3 +#endif + #ifdef SMOOTH_FONT // Call up the SPIFFS FLASH filing system for the anti-aliased fonts #define FS_NO_GLOBALS @@ -127,16 +132,16 @@ #else #if TFT_DC >= 32 - #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); //\ + //GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); //\ + //GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #else #if TFT_DC >= 0 - #define DC_C GPIO.out_w1ts = (1 << TFT_DC); \ - GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ - GPIO.out_w1ts = (1 << TFT_DC) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC); //\ + //GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC); //\ + //GPIO.out_w1ts = (1 << TFT_DC) #else #define DC_C #define DC_D @@ -166,14 +171,14 @@ #define CS_H #else #if TFT_CS >= 32 - #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ - GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); //\ + //GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); //\ + //GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #else #if TFT_CS >= 0 - #define CS_L GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1ts = (1 << TFT_CS) + #define CS_L GPIO.out_w1tc = (1 << TFT_CS); //GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS); //GPIO.out_w1ts = (1 << TFT_CS) #else #define CS_L #define CS_H @@ -186,6 +191,18 @@ #endif #endif +// Use single register write for CS_L and DC_C if pins are both in range 0-31 +#ifdef ESP32 + #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); //\ + //GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #else + #define CS_L_DC_C CS_L; DC_C + #endif +#else // ESP8266 + #define CS_L_DC_C CS_L; DC_C +#endif + // chip select signal for touchscreen #ifndef TOUCH_CS #define T_CS_L // No macro allocated so it generates no code @@ -206,6 +223,14 @@ #endif #endif +#ifdef ESP8266 + // Concatenate two 16 bit values for the SPI 32 bit register write + #define SPI_32(H,L) ( (H)<<16 | (L) ) +#else + // Swap byte order for concatenated 16 bit window address or colors + // AB CD -> DCBA for SPI 32 bit register write + #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) +#endif #if defined (ESP32) && defined (ESP32_PARALLEL) // Mask for the 8 data bits to set pin directions @@ -253,34 +278,75 @@ #elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB // Write 8 bits to TFT - #define tft_Write_8(C) SPI.transfer(C) + #define tft_Write_8(C) SPI.transfer(C) // Convert 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ - SPI.transfer((C & 0x07E0)>>3); \ - SPI.transfer((C & 0x001F)<<3) + #define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ + SPI.transfer((C & 0x07E0)>>3); \ + SPI.transfer((C & 0x001F)<<3) // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes #define tft_Write_16S(C) SPI.transfer(C & 0xF8); \ SPI.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \ SPI.transfer((C & 0x1F00)>>5) // Write 32 bits to TFT - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_32(C) SPI.write32(C) #elif defined (RPI_ILI9486_DRIVER) - #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) - #define tft_Write_16(C) SPI.write16(C) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_16S(C) SPI.write16(C<<8 | C>>8) + #define tft_Write_32(C) SPI.write32(C) -#else +#elif defined ESP8266 - #define tft_Write_8(C) SPI.transfer(C) - #define tft_Write_16(C) SPI.write16(C) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) SPI.write(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_32(C) SPI.write32(C) + +#else // ESP32 using SPI with 16 bit color display + + // ESP32 low level SPI writes for 8, 16 and 32 bit values + // to avoid the function call overhead + + // Write 8 bits + #define tft_Write_8(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 8-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 16 bits with corrected endianess for 16 bit colours + #define tft_Write_16(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C<<8 | C>>8); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 16 bits (used for ESP32_PARALLEL or ILI9488_DRIVER) + #define tft_Write_16S(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + + // Write 32 bits + #define tft_Write_32(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 32-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); #endif + +#ifndef ESP32_PARALLEL + // Support SPI TFT reads (not all displays support this) + #define tft_Read_8(C) SPI.transfer(C) +#endif + + #ifdef LOAD_GFXFF // We can include all the free fonts and they will only be built into // the sketch if they are used @@ -406,6 +472,7 @@ template static inline void swap_coord(T& a, T& b) { T t = a; a = b; b = t; } #ifndef min + // Return minimum of two numbers, may already be defined #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif @@ -667,6 +734,10 @@ class TFT_eSPI : public Print { void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + // These 3 functions are used together, for every startWrite() there must be an endWrite() + void startWrite(void); // Begin SPI transaction + void writeColor(uint16_t color, uint32_t len); // Write a colour without transaction overhead + void endWrite(void); // End SPI transaction size_t write(uint8_t); @@ -713,6 +784,8 @@ class TFT_eSPI : public Print { uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation() uint32_t _width, _height; // Display w/h as modified by current rotation uint32_t addr_row, addr_col; + uint32_t xs_col, xe_col; + uint32_t ys_row, ye_row; uint32_t fontsloaded; @@ -750,9 +823,4 @@ class TFT_eSPI : public Print { // Load the Sprite Class #include "Extensions/Sprite.h" -// #ifdef ESP32 -// // Load the Sprite Class -// #include "Extensions/pSprite.h" -// #endif - #endif diff --git a/User_Setup.h b/User_Setup.h index 9b2359c..e8a5d79 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -113,14 +113,15 @@ // but saves pins for other functions. // Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + // In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 //#define TFT_CS PIN_D3 //#define TFT_DC PIN_D5 // Data Command control pin //#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### @@ -136,6 +137,9 @@ //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST //#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -146,10 +150,6 @@ //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) //#define TFT_BL 32 // LED back-light (required for M5Stack) -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### // The library supports 8 bit parallel TFTs with the ESP32, the pin diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 9b2359c..900da04 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -102,7 +102,7 @@ //#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) -//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen //#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only @@ -113,14 +113,15 @@ // but saves pins for other functions. // Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + // In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 //#define TFT_CS PIN_D3 //#define TFT_DC PIN_D5 // Data Command control pin //#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### @@ -134,8 +135,10 @@ //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) +//#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -144,11 +147,7 @@ //#define TFT_CS 14 // Chip select control pin //#define TFT_DC 27 // Data Command control pin //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light (required for M5Stack) - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only +//#define TFT_BL 32 // LED back-light (if needed) // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### @@ -209,9 +208,9 @@ #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. -#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts // Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded @@ -263,4 +262,4 @@ // Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) // so changing it here has no effect -//#define SUPPORT_TRANSACTIONS +// #define SUPPORT_TRANSACTIONS diff --git a/keywords.txt b/keywords.txt index b197c5a..9fb1758 100644 --- a/keywords.txt +++ b/keywords.txt @@ -6,6 +6,9 @@ drawChar KEYWORD2 setAddrWindow KEYWORD2 setWindow KEYWORD2 readAddrWindow KEYWORD2 +startWrite KEYWORD2 +writeColor KEYWORD2 +endWrite KEYWORD2 pushColor KEYWORD2 pushColors KEYWORD2 fillScreen KEYWORD2 diff --git a/library.json b/library.json index 496bd2e..0867346 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.1.4", + "version": "1.2.0", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index fd62f0e..eb7a239 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.1.4 +version=1.2.0 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From ac7a2293016a6f4140b18fb7d6fc51db399f50af Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 16 Nov 2018 00:54:51 +0000 Subject: [PATCH 31/94] Remove setAddressWindow change for ESP32 Corner case caused missed graphics. --- TFT_eSPI.cpp | 45 +++++++++++++++------------------------------ TFT_eSPI.h | 2 -- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 10f9bb3..45e8219 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -185,8 +185,8 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) _booted = true; - ys_row = ye_row = addr_row = 0xFFFF; - xs_col = xe_col = addr_col = 0xFFFF; + addr_row = 0xFFFF; + addr_col = 0xFFFF; #ifdef LOAD_GLCD fontsloaded = 0x0002; // Bit 1 set @@ -2689,44 +2689,32 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) CS_L_DC_C; - // No need to send x if it has not changed (small speed-up of complex transparent Sprites and bitmaps) - // Nb: caller must fill the set address area so that setting same area again will fill from xs, ys - if (xs_col != x0 || xe_col != x1) { - // Column addr set + tft_Write_8(TFT_CASET); - tft_Write_8(TFT_CASET); - - DC_D; + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; - SPI.writePattern(&xb[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; + SPI.writePattern(&xb[0], 8, 1); #else - tft_Write_32(SPI_32(x0, x1)); + tft_Write_32(SPI_32(x0, x1)); #endif - DC_C; - xs_col = x0; xe_col = x1; - } + DC_C; - // No need to send y if it has not changed - if (ys_row != y0 || ye_row != y1) { + // Row addr set + tft_Write_8(TFT_PASET); - // Row addr set - tft_Write_8(TFT_PASET); - - DC_D; + DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; - SPI.writePattern(&yb[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; + SPI.writePattern(&yb[0], 8, 1); #else - tft_Write_32(SPI_32(y0, y1)); + tft_Write_32(SPI_32(y0, y1)); #endif - DC_C; - ys_row = y0; ye_row = y1; - } + DC_C; // write to RAM tft_Write_8(TFT_RAMWR); @@ -3074,8 +3062,6 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; addr_col = x; - xs_col = xe_col = x; - } // No need to send y if it has not changed (speeds things up) @@ -3095,7 +3081,6 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; addr_row = y; - ys_row = ye_row = y; } diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 456b066..187dc23 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -784,8 +784,6 @@ class TFT_eSPI : public Print { uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation() uint32_t _width, _height; // Display w/h as modified by current rotation uint32_t addr_row, addr_col; - uint32_t xs_col, xe_col; - uint32_t ys_row, ye_row; uint32_t fontsloaded; From c51ec3751c2b98eb17a4020e8f35bfb1157c228f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 16 Nov 2018 00:55:58 +0000 Subject: [PATCH 32/94] Raise version --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 0867346..941dd07 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.2.0", + "version": "1.2.1", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index eb7a239..483c231 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.2.0 +version=1.2.1 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 419a7ef8de7c3f2710fdfe579da84983ae420e53 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 19 Nov 2018 23:49:32 +0000 Subject: [PATCH 33/94] Add option for different RGB colour order with ST7789 // For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red --- TFT_Drivers/ST7789_Defines.h | 14 ++++++++++++++ TFT_Drivers/ST7789_Init.h | 7 +------ TFT_Drivers/ST7789_Rotation.h | 20 ++++++++------------ User_Setup.h | 4 ++++ User_Setup_Select.h | 6 ++++++ User_Setups/SetupX_Template.h | 5 +++++ library.json | 2 +- library.properties | 2 +- 8 files changed, 40 insertions(+), 20 deletions(-) diff --git a/TFT_Drivers/ST7789_Defines.h b/TFT_Drivers/ST7789_Defines.h index 06f2a39..2695336 100644 --- a/TFT_Drivers/ST7789_Defines.h +++ b/TFT_Drivers/ST7789_Defines.h @@ -45,6 +45,20 @@ #define TFT_MAD_SS 0x02 #define TFT_MAD_GS 0x01 +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #ifdef CGRAM_OFFSET + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #endif +#endif + #define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read // ST7789 specific commands used in init diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index 4afd2cc..c72b51d 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -14,12 +14,7 @@ //------------------------------display and color format setting--------------------------------// writecommand(ST7789_MADCTL); writedata(0x00); -#ifdef CGRAM_OFFSET - writedata(0x48); // BGR colour order for 240 x 240 TFT -#else - writedata(0x40); // RGB colour order for 240 x 320 TFT (Issue #232) -#endif - + writedata(TFT_MAD_COLOR_ORDER); // JLX240 display datasheet writecommand(0xB6); diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 74a5b9f..d490279 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -5,47 +5,43 @@ switch (rotation) { case 0: // Portrait #ifdef CGRAM_OFFSET - writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; -#else - writedata(TFT_MAD_RGB); #endif + writedata(TFT_MAD_COLOR_ORDER); + _width = _init_width; _height = _init_height; break; case 1: // Landscape (Portrait + 90) #ifdef CGRAM_OFFSET - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 0; rowstart = 0; -#else - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); #endif + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + _width = _init_height; _height = _init_width; break; case 2: // Inverter portrait #ifdef CGRAM_OFFSET - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); colstart = 0; rowstart = 80; -#else - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); #endif + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + _width = _init_width; _height = _init_height; break; case 3: // Inverted landscape #ifdef CGRAM_OFFSET - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 80; rowstart = 0; -#else - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); #endif + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + _width = _init_height; _height = _init_width; break; diff --git a/User_Setup.h b/User_Setup.h index e8a5d79..53bbd60 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -29,6 +29,10 @@ // For M5Stack ESP32 module with integrated display ONLY, remove // in line below //#define M5STACK +// For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + // For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation // #define TFT_WIDTH 80 // #define TFT_WIDTH 128 diff --git a/User_Setup_Select.h b/User_Setup_Select.h index dee02cf..be58b13 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -60,6 +60,11 @@ ///////////////////////////////////////////////////////////////////////////////////// +// Identical looking TFT displays may have a different colour ordering in the 16 bit colour +#define TFT_BGR 0 // Colour order Blue-Green-Red +#define TFT_RGB 1 // Colour order Red-Green-Blue + + // Load the right driver definition - do not tinker here ! #if defined (ILI9341_DRIVER) #include @@ -101,6 +106,7 @@ #define TFT_DRIVER 0x0000 #endif + // These are the pins for all ESP8266 boards // Name GPIO Function #define PIN_D0 16 // WAKE diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 900da04..26ccf8a 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -26,6 +26,11 @@ //#define ILI9488_DRIVER //#define ST7789_DRIVER // Define the screen size below for this display +// For ST7789 ONLY, define the colour order if the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + // For M5Stack ESP32 module with integrated display ONLY, remove // in line below //#define M5STACK diff --git a/library.json b/library.json index 941dd07..1bba1a1 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.2.1", + "version": "1.2.2", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 483c231..a2a1260 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.2.1 +version=1.2.2 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From d14a09e947caafb55f902daf6054537392196023 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 21 Nov 2018 02:30:13 +0000 Subject: [PATCH 34/94] Update notes --- Extensions/Touch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 87fa182..36a183a 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -12,7 +12,7 @@ /*************************************************************************************** ** Function name: getTouchRaw -** Description: read raw touch position. Return false if not pressed. +** Description: read raw touch position. Always returns true. ***************************************************************************************/ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ uint16_t tmp; From 1cf2305e4d6d20292796ce43fb9ccc7531bd4f5e Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 23 Nov 2018 03:09:07 +0000 Subject: [PATCH 35/94] Add capability to read TFT SDA bi-directional pin Tested on an ESP32 with ST7789V display SDA read is very slow on an ESP8266 (to be investigated) Added new setup #define TFT_SDA_READ Add new ESP32 and ESP8266 compatible in example/Generic folder to test capture of TFT screen --- Extensions/Touch.cpp | 2 +- TFT_eSPI.cpp | 164 +++++- TFT_eSPI.h | 14 +- User_Setup.h | 5 + User_Setups/Setup18_ST7789.h | 6 + .../TFT_Screen_Capture/TFT_Screen_Capture.ino | 207 +++++++ .../TFT_Screen_Capture/processing_sketch.ino | 535 ++++++++++++++++++ .../TFT_Screen_Capture/screenServer.ino | 196 +++++++ 8 files changed, 1117 insertions(+), 12 deletions(-) create mode 100644 examples/Generic/TFT_Screen_Capture/TFT_Screen_Capture.ino create mode 100644 examples/Generic/TFT_Screen_Capture/processing_sketch.ino create mode 100644 examples/Generic/TFT_Screen_Capture/screenServer.ino diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 87fa182..1b0192d 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -12,7 +12,7 @@ /*************************************************************************************** ** Function name: getTouchRaw -** Description: read raw touch position. Return false if not pressed. +** Description: read raw touch position. Always returns true. ***************************************************************************************/ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ uint16_t tmp; diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 45e8219..86029f9 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -253,6 +253,10 @@ void TFT_eSPI::init(uint8_t tc) wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR); #endif + #ifdef TFT_SCLK + sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK); + #endif + #ifdef TFT_SPI_OVERLAP // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss); @@ -620,35 +624,68 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) spi_begin_read(); + #ifdef ST7789_DRIVER + writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required) + writedata(0x66); + #endif + readAddrWindow(x0, y0, x0, y0); // Sets CS low + #ifdef TFT_SDA_READ + // To be investigated: spi_end_read() is VERY slow on the ESP8266 here + spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32 + SPI.end(); // Disconnect the SPI peripheral to release the pins + digitalWrite(TFT_SCLK, HIGH); // Set clock pin high + pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output + pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input + #endif + // Dummy read to throw away don't care value - tft_Write_8(0); + tft_Read_8(0); // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) + uint8_t r = tft_Read_8(0); uint8_t g = tft_Read_8(0); uint8_t b = tft_Read_8(0); + #else + // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left uint8_t r = (tft_Read_8(0)&0x7E)<<1; uint8_t g = (tft_Read_8(0)&0x7E)<<1; uint8_t b = (tft_Read_8(0)&0x7E)<<1; + #endif CS_H; +#ifdef TFT_SDA_READ + #ifdef ESP32 + SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); + #else + #ifdef TFT_SPI_OVERLAP + SPI.pins(6, 7, 8, 0); + #else + SPI.begin(); + #endif + #endif + #ifdef ST7789_DRIVER + writecommand(ST7789_COLMOD); + writedata(0x55); + #endif +#else spi_end_read(); - +#endif + return color565(r, g, b); #endif } - /*************************************************************************************** ** Function name: read byte - supports class functions ** Description: Read a byte from ESP32 8 bit data port @@ -756,10 +793,24 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t spi_begin_read(); + #ifdef ST7789_DRIVER + writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required) + writedata(0x66); + #endif + readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low + #ifdef TFT_SDA_READ + // To be investigated: spi_end_read() is VERY slow on the ESP8266 here + spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32 + SPI.end(); // Disconnect the SPI peripheral to release the pins + digitalWrite(TFT_SCLK, HIGH); // Set clock pin high + pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output + pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input + #endif + // Dummy read to throw away don't care value - tft_Write_8(0); + tft_Read_8(0); // Read window pixel 24 bit RGB values uint32_t len = w * h; @@ -768,15 +819,19 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) + uint8_t r = tft_Read_8(0); uint8_t g = tft_Read_8(0); uint8_t b = tft_Read_8(0); + #else + // The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left uint8_t r = (tft_Read_8(0)&0x7E)<<1; uint8_t g = (tft_Read_8(0)&0x7E)<<1; uint8_t b = (tft_Read_8(0)&0x7E)<<1; + #endif // Swapped colour byte order for compatibility with pushRect() @@ -785,10 +840,64 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t CS_H; +#ifdef TFT_SDA_READ + #ifdef ESP32 + SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); + #else + #ifdef TFT_SPI_OVERLAP + SPI.pins(6, 7, 8, 0); + #else + SPI.begin(); + #endif + #endif + #ifdef ST7789_DRIVER + writecommand(ST7789_COLMOD); + writedata(0x55); + #endif +#else spi_end_read(); #endif + +#endif } +/*************************************************************************************** +** Function name: tft_Read_8 +** Description: Software SPI to read bidirectional SDA line +***************************************************************************************/ +// For the ST7789 the tft_Read_8() macro is replaced by a function +#ifdef TFT_SDA_READ + #ifdef ESP32 + #define SCLK_L GPIO.out_w1tc = (1 << TFT_SCLK) + #define SCLK_H GPIO.out_w1ts = (1 << TFT_SCLK) + #else // ESP8266 + #define SCLK_L GPOC=sclkpinmask + #define SCLK_H GPOS=sclkpinmask + #endif +uint8_t TFT_eSPI::tft_Read_8(uint8_t dummy) +{ + uint8_t ret = 0; + uint32_t reg = 0; + + for (uint8_t i = 0; i < 8; i++) { // read results + ret <<= 1; + #ifdef ESP32 // bit bangs at around 1MHz + SCLK_L; + //SCLK_L; + reg = gpio_input_get(); // SDA must connect to ESP32 pin in range 0-31 + SCLK_H; + if (reg&(1<>>> NOTE: NOT ALL TFTs SUPPORT READING THE CGRAM (pixel) MEMORY <<<< + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Created by: Bodmer 5/3/17 +// Updated by: Bodmer 10/3/17 +// Updated by: Bodmer 23/11/18 to support SDA reads and the ESP32 +// Version: 0.07 + +// MIT licence applies, all text above must be included in derivative works + +#include // Hardware-specific library +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +unsigned long targetTime = 0; +byte red = 0x1F; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each + +void setup(void) { + Serial.begin(921600); // Set to a high rate for fast image transfer to a PC + + tft.init(); + tft.setRotation(0); + tft.fillScreen(TFT_BLACK); + + randomSeed(analogRead(A0)); + + targetTime = millis() + 1000; +} + +#define RGB_TEST false // true produces a simple RGB color test screen + +void loop() { + + if (targetTime < millis()) { + if (!RGB_TEST) + { + targetTime = millis() + 1500; // Wait a minimum of 1.5s + + tft.setRotation(random(4)); + rainbow_fill(); // Fill the screen with rainbow colours + + tft.setTextColor(TFT_BLACK); // Text background is not defined so it is transparent + tft.setTextDatum(TC_DATUM); // Top Centre datum + int xpos = tft.width() / 2; // Centre of screen + + tft.setTextFont(0); // Select font 0 which is the Adafruit font + tft.drawString("Original Adafruit font!", xpos, 5); + + // The new larger fonts do not need to use the .setCursor call, coords are embedded + tft.setTextColor(TFT_BLACK); // Do not plot the background colour + + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + tft.drawString("Font size 2", xpos, 14, 2); // Draw text centre at position xpos, 14 using font 2 + tft.drawString("Font size 4", xpos, 30, 4); // Draw text centre at position xpos, 30 using font 4 + tft.drawString("12.34", xpos, 54, 6); // Draw text centre at position xpos, 54 using font 6 + + tft.drawString("12.34 is in font size 6", xpos, 92, 2); // Draw text centre at position xpos, 92 using font 2 + // Note the x position is the top of the font! + + // draw a floating point number + float pi = 3.1415926; // Value to print + int precision = 3; // Number of digits after decimal point + + int ypos = 110; // y position + + tft.setTextDatum(TR_DATUM); // Top Right datum so text butts neatly to xpos (right justified) + + tft.drawFloat(pi, precision, xpos, ypos, 2); // Draw rounded number and return new xpos delta for next print position + + tft.setTextDatum(TL_DATUM); // Top Left datum so text butts neatly to xpos (left justified) + + tft.drawString(" is pi", xpos, ypos, 2); + + tft.setTextSize(1); // We are using a font size multiplier of 1 + tft.setTextDatum(TC_DATUM); // Top Centre datum + tft.setTextColor(TFT_BLACK); // Set text colour to black, no background (so transparent) + + tft.drawString("Transparent...", xpos, 125, 4); // Font 4 + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text colour to white and background to black + tft.drawString("White on black", xpos, 150, 4); // Font 4 + + tft.setTextColor(TFT_GREEN, TFT_BLACK); // This time we will use green text on a black background + + tft.setTextFont(2); // Select font 2, now we do not need to specify the font in drawString() + + // An easier way to position text and blank old text is to set the datum and use width padding + tft.setTextDatum(BC_DATUM); // Bottom centre for text datum + tft.setTextPadding(tft.width() + 1); // Pad text to full screen width + 1 spare for +/-1 position rounding + + tft.drawString("Ode to a Small Lump of Green Putty", xpos, 230 - 32); + tft.drawString("I Found in My Armpit One Midsummer", xpos, 230 - 16); + tft.drawString("Morning", xpos, 230); + + tft.setTextDatum(TL_DATUM); // Reset to top left for text datum + tft.setTextPadding(0); // Reset text padding to 0 pixels + + // Now call the screen server to send a copy of the TFT screen to the PC running the Processing client sketch + screenServer(); + } + else + { + tft.fillScreen(TFT_BLACK); + tft.fillRect( 0, 0, 16, 16, TFT_RED); + tft.fillRect(16, 0, 16, 16, TFT_GREEN); + tft.fillRect(32, 0, 16, 16, TFT_BLUE); + screenServer(); + } + } +} + +// Fill screen with a rainbow pattern +void rainbow_fill() +{ + // The colours and state are not initialised so the start colour changes each time the funtion is called + int rotation = tft.getRotation(); + tft.setRotation(random(4)); + for (int i = tft.height() - 1; i >= 0; i--) { + // This is a "state machine" that ramps up/down the colour brightnesses in sequence + switch (state) { + case 0: + green ++; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green --; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + // Draw a line 1 pixel wide in the selected colour + tft.drawFastHLine(0, i, tft.width(), colour); // tft.width() returns the pixel width of the display + } + tft.setRotation(rotation); +} diff --git a/examples/Generic/TFT_Screen_Capture/processing_sketch.ino b/examples/Generic/TFT_Screen_Capture/processing_sketch.ino new file mode 100644 index 0000000..3e71f41 --- /dev/null +++ b/examples/Generic/TFT_Screen_Capture/processing_sketch.ino @@ -0,0 +1,535 @@ +// This is a copy of the processing sketch that can be used to capture the images +// Copy the sketch below and remove the /* and */ at the beginning and end. + +// The sketch runs in Processing version 3.3 on a PC, it can be downloaded here: +// https://processing.org/download/ + +/* + +// This is a Processing sketch, see https://processing.org/ to download the IDE + +// The sketch is a client that requests TFT screenshots from an Arduino board. +// The Arduino must call a screenshot server function to respond with pixels. + +// It has been created to work with the TFT_eSPI library here: +// https://github.com/Bodmer/TFT_eSPI + +// The sketch must only be run when the designated serial port is available and enumerated +// otherwise the screenshot window may freeze and that process will need to be terminated +// This is a limitation of the Processing environment and not the sketch. +// If anyone knows how to determine if a serial port is available at start up the PM me +// on (Bodmer) the Arduino forum. + +// The block below contains variables that the user may need to change for a particular setup +// As a minimum set the serial port and baud rate must be defined. The capture window is +// automatically resized for landscape, portrait and different TFT resolutions. + +// Captured images are stored in the sketch folder, use the Processing IDE "Sketch" menu +// option "Show Sketch Folder" or press Ctrl+K + +// Created by: Bodmer 5/3/17 +// Updated by: Bodmer 12/3/17 +// Version: 0.07 + +// MIT licence applies, all text above must be included in derivative works + + +// ########################################################################################### +// # These are the values to change for a particular setup # +// # +int serial_port = 0; // Use enumerated value from list provided when sketch is run # +// # +// On an Arduino Due Programming Port use a baud rate of:115200) # +// On an Arduino Due Native USB Port use a baud rate of any value # +int serial_baud_rate = 921600; // # +// # +// Change the image file type saved here, comment out all but one # +//String image_type = ".jpg"; // # +String image_type = ".png"; // Lossless compression # +//String image_type = ".bmp"; // # +//String image_type = ".tif"; // # +// # +boolean save_border = true; // Save the image with a border # +int border = 5; // Border pixel width # +boolean fade = false; // Fade out image after saving # +// # +int max_images = 100; // Maximum of numbered file images before over-writing files # +// # +int max_allowed = 1000; // Maximum number of save images allowed before a restart # +// # +// # End of the values to change for a particular setup # +// ########################################################################################### + +// These are default values, this sketch obtains the actual values from the Arduino board +int tft_width = 480; // default TFT width (automatic - sent by Arduino) +int tft_height = 480; // default TFT height (automatic - sent by Arduino) +int color_bytes = 2; // 2 for 16 bit, 3 for three RGB bytes (automatic - sent by Arduino) + +import processing.serial.*; + +Serial serial; // Create an instance called serial + +int serialCount = 0; // Count of colour bytes arriving + +// Stage window graded background colours +color bgcolor1 = color(0, 100, 104); // Arduino IDE style background color 1 +color bgcolor2 = color(77, 183, 187); // Arduino IDE style background color 2 +//color bgcolor2 = color(255, 255, 255); // White + +// TFT image frame greyscale value (dark grey) +color frameColor = 42; + +color buttonStopped = color(255, 0, 0); +color buttonRunning = color(128, 204, 206); +color buttonDimmed = color(180, 0, 0); +boolean dimmed = false; +boolean running = true; +boolean mouseClick = false; + +int[] rgb = new int[3]; // Buffer for the colour bytes +int indexRed = 0; // Colour byte index in the array +int indexGreen = 1; +int indexBlue = 2; + +int n = 0; + +int x_offset = (500 - tft_width) /2; // Image offsets in the window +int y_offset = 20; + +int xpos = 0, ypos = 0; // Current pixel position + +int beginTime = 0; +int pixelWaitTime = 1000; // Maximum 1000ms wait for image pixels to arrive +int lastPixelTime = 0; // Time that "image send" command was sent + +int requestTime = 0; +int requestCount = 0; + +int state = 0; // State machine current state + +int progress_bar = 0; // Console progress bar dot count +int pixel_count = 0; // Number of pixels read for 1 screen +float percentage = 0; // Percentage of pixels received + +int saved_image_count = 0; // Stats - number of images processed +int bad_image_count = 0; // Stats - number of images that had lost pixels +String filename = ""; + +int drawLoopCount = 0; // Used for the fade out + +void setup() { + + size(500, 540); // Stage size, can handle 480 pixels wide screen + noStroke(); // No border on the next thing drawn + noSmooth(); // No anti-aliasing to avoid adjacent pixel colour merging + + // Graded background and title + drawWindow(); + + frameRate(2000); // High frame rate so draw() loops fast + + // Print a list of the available serial ports + println("-----------------------"); + println("Available Serial Ports:"); + println("-----------------------"); + printArray(Serial.list()); + println("-----------------------"); + + print("Port currently used: ["); + print(serial_port); + println("]"); + + String portName = Serial.list()[serial_port]; + + serial = new Serial(this, portName, serial_baud_rate); + + state = 99; +} + +void draw() { + + if (mouseClick) buttonClicked(); + + switch(state) { + + case 0: // Init varaibles, send start request + if (running) { + tint(0, 0, 0, 255); + flushBuffer(); + println(""); + print("Ready: "); + + xpos = 0; + ypos = 0; + serialCount = 0; + progress_bar = 0; + pixel_count = 0; + percentage = 0; + drawLoopCount = frameCount; + lastPixelTime = millis() + 1000; + + state = 1; + } else { + if (millis() > beginTime) { + beginTime = millis() + 500; + dimmed = !dimmed; + if (dimmed) drawButton(buttonDimmed); + else drawButton(buttonStopped); + } + } + break; + + case 1: // Console message, give server some time + print("requesting image "); + serial.write("S"); + delay(10); + beginTime = millis(); + requestTime = millis() + 1000; + requestCount = 1; + state = 2; + break; + + case 2: // Get size and set start time for rendering duration report + if (millis() > requestTime) { + requestCount++; + print("*"); + serial.clear(); + serial.write("S"); + if (requestCount > 32) { + requestCount = 0; + System.err.println(" - no response!"); + state = 0; + } + requestTime = millis() + 1000; + } + if ( getSize() == true ) { // Go to next state when we have the size and bits per pixel + getFilename(); + flushBuffer(); // Precaution in case image header size increases in later versions + lastPixelTime = millis() + 1000; + beginTime = millis(); + state = 3; + } + break; + + case 3: // Request pixels and render returned RGB values + state = renderPixels(); // State will change when all pixels are rendered + + // Request more pixels, changing the number requested allows the average transfer rate to be controlled + // The pixel transfer rate is dependant on four things: + // 1. The frame rate defined in this Processing sketch in setup() + // 2. The baud rate of the serial link (~10 bit periods per byte) + // 3. The number of request bytes 'R' sent in the lines below + // 4. The number of pixels sent in a burst by the server sketch (defined via NPIXELS) + + //serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); // 32 x NPIXELS more + serial.write("RRRRRRRRRRRRRRRR"); // 16 x NPIXELS more + //serial.write("RRRRRRRR"); // 8 x NPIXELS more + //serial.write("RRRR"); // 4 x NPIXELS more + //serial.write("RR"); // 2 x NPIXELS more + //serial.write("R"); // 1 x NPIXELS more + if (!running) state = 4; + break; + + case 4: // Pixel receive time-out, flush serial buffer + flushBuffer(); + state = 6; + break; + + case 5: // Save the image to the sketch folder (Ctrl+K to access) + saveScreenshot(); + saved_image_count++; + println("Saved image count = " + saved_image_count); + if (bad_image_count > 0) System.err.println(" Bad image count = " + bad_image_count); + drawLoopCount = frameCount; // Reset value ready for counting in step 6 + state = 6; + break; + + case 6: // Fade the old image if enabled + if ( fadedImage() == true ) state = 0; // Go to next state when image has faded + break; + + case 99: // Draw image viewer window + drawWindow(); + delay(50); // Delay here seems to be required for the IDE console to get ready + state = 0; + break; + + default: + println(""); + System.err.println("Error state reached - check sketch!"); + break; + } +} + +void drawWindow() +{ + // Graded background in Arduino colours + for (int i = 0; i < height - 25; i++) { + float inter = map(i, 0, height - 25, 0, 1); + color c = lerpColor(bgcolor1, bgcolor2, inter); + stroke(c); + line(0, i, 500, i); + } + fill(bgcolor2); + rect( 0, height-25, width-1, 24); + textAlign(CENTER); + textSize(20); + fill(0); + text("Bodmer's TFT image viewer", width/2, height-6); + + if (running) drawButton(buttonRunning); + else drawButton(buttonStopped); +} + +void flushBuffer() +{ + //println("Clearing serial pipe after a time-out"); + int clearTime = millis() + 50; + while ( millis() < clearTime ) serial.clear(); +} + +boolean getSize() +{ + if ( serial.available() > 6 ) { + println(); + char code = (char)serial.read(); + if (code == 'W') { + tft_width = serial.read()<<8 | serial.read(); + } + code = (char)serial.read(); + if (code == 'H') { + tft_height = serial.read()<<8 | serial.read(); + } + code = (char)serial.read(); + if (code == 'Y') { + int bits_per_pixel = (char)serial.read(); + if (bits_per_pixel == 24) color_bytes = 3; + else color_bytes = 2; + } + code = (char)serial.read(); + if (code == '?') { + drawWindow(); + + x_offset = (500 - tft_width) /2; + tint(0, 0, 0, 255); + noStroke(); + fill(frameColor); + rect((width - tft_width)/2 - border, y_offset - border, tft_width + 2 * border, tft_height + 2 * border); + return true; + } + } + return false; +} + +void saveScreenshot() +{ + println(); + if (saved_image_count < max_allowed) + { + if (filename == "") filename = "tft_screen_" + (n++); + filename = filename + image_type; + println("Saving image as \"" + filename + "\""); + if (save_border) + { + PImage partialSave = get(x_offset - border, y_offset - border, tft_width + 2*border, tft_height + 2*border); + partialSave.save(filename); + } else { + PImage partialSave = get(x_offset, y_offset, tft_width, tft_height); + partialSave.save(filename); + } + + if (n>=max_images) n = 0; + } + else + { + System.err.println(max_allowed + " saved image count exceeded, restart the sketch"); + } +} + +void getFilename() +{ + int readTime = millis() + 20; + int inByte = 0; + filename = ""; + while ( serial.available() > 0 && millis() < readTime && inByte != '.') + { + inByte = serial.read(); + if (inByte == ' ') inByte = '_'; + if ( unicodeCheck(inByte) ) filename += (char)inByte; + } + + inByte = serial.read(); + if (inByte == '@') filename += "_" + timeCode(); + else if (inByte == '#') filename += "_" + saved_image_count%100; + else if (inByte == '%') filename += "_" + millis(); + else if (inByte != '*') filename = ""; + + inByte = serial.read(); + if (inByte == 'j') image_type =".jpg"; + else if (inByte == 'b') image_type =".bmp"; + else if (inByte == 'p') image_type =".png"; + else if (inByte == 't') image_type =".tif"; +} + +boolean unicodeCheck(int unicode) +{ + if ( unicode >= '0' && unicode <= '9' ) return true; + if ( (unicode >= 'A' && unicode <= 'Z' ) || (unicode >= 'a' && unicode <= 'z')) return true; + if ( unicode == '_' || unicode == '/' ) return true; + return false; +} + +String timeCode() +{ + String timeCode = (int)year() + "_" + (int)month() + "_" + (int)day() + "_"; + timeCode += (int)hour() + "_" + (int)minute() + "_" + (int)second(); + return timeCode; +} + +int renderPixels() +{ + if ( serial.available() > 0 ) { + + // Add the latest byte from the serial port to array: + while (serial.available()>0) + { + rgb[serialCount++] = serial.read(); + + // If we have 3 colour bytes: + if ( serialCount >= color_bytes ) { + serialCount = 0; + pixel_count++; + if (color_bytes == 3) + { + stroke(rgb[indexRed], rgb[indexGreen], rgb[indexBlue], 1000); + } else + { // Can cater for various byte orders + //stroke( (rgb[0] & 0x1F)<<3, (rgb[0] & 0xE0)>>3 | (rgb[1] & 0x07)<<5, (rgb[1] & 0xF8)); + //stroke( (rgb[1] & 0x1F)<<3, (rgb[1] & 0xE0)>>3 | (rgb[0] & 0x07)<<5, (rgb[0] & 0xF8)); + stroke( (rgb[0] & 0xF8), (rgb[1] & 0xE0)>>3 | (rgb[0] & 0x07)<<5, (rgb[1] & 0x1F)<<3); + //stroke( (rgb[1] & 0xF8), (rgb[0] & 0xE0)>>3 | (rgb[1] & 0x07)<<5, (rgb[0] & 0x1F)<<3); + } + // We get some pixel merge aliasing if smooth() is defined, so draw pixel twice + point(xpos + x_offset, ypos + y_offset); + //point(xpos + x_offset, ypos + y_offset); + + lastPixelTime = millis(); + xpos++; + if (xpos >= tft_width) { + xpos = 0; + progressBar(); + ypos++; + if (ypos>=tft_height) { + ypos = 0; + if ((int)percentage <100) { + while (progress_bar++ < 64) print(" "); + percent(100); + } + println("Image fetch time = " + (millis()-beginTime)/1000.0 + " s"); + return 5; + } + } + } + } + } else + { + if (millis() > (lastPixelTime + pixelWaitTime)) + { + println(""); + System.err.println(pixelWaitTime + "ms time-out for pixels exceeded..."); + if (pixel_count > 0) { + bad_image_count++; + System.err.print("Pixels missing = " + (tft_width * tft_height - pixel_count)); + System.err.println(", corrupted image not saved"); + System.err.println("Good image count = " + saved_image_count); + System.err.println(" Bad image count = " + bad_image_count); + } + return 4; + } + } + return 3; +} + +void progressBar() +{ + progress_bar++; + print("."); + if (progress_bar >63) + { + progress_bar = 0; + percentage = 0.5 + 100 * pixel_count/(0.001 + tft_width * tft_height); + percent(percentage); + } +} + +void percent(float percentage) +{ + if (percentage > 100) percentage = 100; + println(" [ " + (int)percentage + "% ]"); + textAlign(LEFT); + textSize(16); + noStroke(); + fill(bgcolor2); + rect(10, height - 25, 70, 20); + fill(0); + text(" [ " + (int)percentage + "% ]", 10, height-8); +} + +boolean fadedImage() +{ + int opacity = frameCount - drawLoopCount; // So we get increasing fade + if (fade) + { + tint(255, opacity); + //image(tft_img, x_offset, y_offset); + noStroke(); + fill(50, 50, 50, opacity); + rect( (width - tft_width)/2, y_offset, tft_width, tft_height); + delay(10); + } + if (opacity > 50) // End fade after 50 cycles + { + return true; + } + return false; +} + +void drawButton(color buttonColor) +{ + stroke(0); + fill(buttonColor); + rect(500 - 100, 540 - 26, 80, 24); + textAlign(CENTER); + textSize(20); + fill(0); + if (running) text(" Pause ", 500 - 60, height-7); + else text(" Run ", 500 - 60, height-7); +} + +void buttonClicked() +{ + mouseClick = false; + if (running) { + running = false; + drawButton(buttonStopped); + System.err.println(""); + System.err.println("Stopped - click 'Run' button: "); + //noStroke(); + //fill(50); + //rect( (width - tft_width)/2, y_offset, tft_width, tft_height); + beginTime = millis() + 500; + dimmed = false; + state = 4; + } else { + running = true; + drawButton(buttonRunning); + } +} + +void mousePressed() { + if (mouseX > (500 - 100) && mouseX < (500 - 20) && mouseY > (540 - 26) && mouseY < (540 - 2)) { + mouseClick = true; + } +} + +*/ diff --git a/examples/Generic/TFT_Screen_Capture/screenServer.ino b/examples/Generic/TFT_Screen_Capture/screenServer.ino new file mode 100644 index 0000000..2924947 --- /dev/null +++ b/examples/Generic/TFT_Screen_Capture/screenServer.ino @@ -0,0 +1,196 @@ +// Reads a screen image off the TFT and send it to a processing client sketch +// over the serial port. Use a high baud rate, e.g. for an ESP8266: +// Serial.begin(921600); + +// At 921600 baud a 320 x 240 image with 16 bit colour transfers can be sent to the +// PC client in ~1.67s and 24 bit colour in ~2.5s which is close to the theoretical +// minimum transfer time. + +// This sketch has been created to work with the TFT_eSPI library here: +// https://github.com/Bodmer/TFT_eSPI + +// Created by: Bodmer 27/1/17 +// Updated by: Bodmer 10/3/17 +// Updated by: Bodmer 23/11/18 to support SDA reads and the ESP32 +// Version: 0.08 + +// MIT licence applies, all text above must be included in derivative works + +//==================================================================================== +// Definitions +//==================================================================================== +#define PIXEL_TIMEOUT 100 // 100ms Time-out between pixel requests +#define START_TIMEOUT 10000 // 10s Maximum time to wait at start transfer + +#define BITS_PER_PIXEL 16 // 24 for RGB colour format, 16 for 565 colour format + +// File names must be alpha-numeric characters (0-9, a-z, A-Z) or "/" underscore "_" +// other ascii characters are stripped out by client, including / generates +// sub-directories +#define DEFAULT_FILENAME "tft_screenshots/screenshot" // In case none is specified +#define FILE_TYPE "png" // jpg, bmp, png, tif are valid + +// Filename extension +// '#' = add incrementing number, '@' = add timestamp, '%' add millis() timestamp, +// '*' = add nothing +// '@' and '%' will generate new unique filenames, so beware of cluttering up your +// hard drive with lots of images! The PC client sketch is set to limit the number of +// saved images to 1000 and will then prompt for a restart. +#define FILE_EXT '@' + +// Number of pixels to send in a burst (minimum of 1), no benefit above 8 +// NPIXELS values and render times: +// NPIXELS 1 = use readPixel() = >5s and 16 bit pixels only +// NPIXELS >1 using rectRead() 2 = 1.75s, 4 = 1.68s, 8 = 1.67s +#define NPIXELS 8 // Must be integer division of both TFT width and TFT height + +//==================================================================================== +// Screen server call with no filename +//==================================================================================== +// Start a screen dump server (serial or network) - no filename specified +boolean screenServer(void) +{ + // With no filename the screenshot will be saved with a default name e.g. tft_screen_#.xxx + // where # is a number 0-9 and xxx is a file type specified below + return screenServer(DEFAULT_FILENAME); +} + +//==================================================================================== +// Screen server call with filename +//==================================================================================== +// Start a screen dump server (serial or network) - filename specified +boolean screenServer(String filename) +{ + delay(0); // Equivalent to yield() for ESP8266; + + boolean result = serialScreenServer(filename); // Screenshot serial port server + //boolean result = wifiScreenServer(filename); // Screenshot WiFi UDP port server (WIP) + + delay(0); // Equivalent to yield() + + //Serial.println(); + //if (result) Serial.println(F("Screen dump passed :-)")); + //else Serial.println(F("Screen dump failed :-(")); + + return result; +} + +//==================================================================================== +// Serial server function that sends the data to the client +//==================================================================================== +boolean serialScreenServer(String filename) +{ + // Precautionary receive buffer garbage flush for 50ms + uint32_t clearTime = millis() + 50; + while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; + + boolean wait = true; + uint32_t lastCmdTime = millis(); // Initialise start of command time-out + + // Wait for the starting flag with a start time-out + while (wait) + { + delay(0); // Equivalent to yield() for ESP8266; + // Check serial buffer + if (Serial.available() > 0) { + // Read the command byte + uint8_t cmd = Serial.read(); + // If it is 'S' (start command) then clear the serial buffer for 100ms and stop waiting + if ( cmd == 'S' ) { + // Precautionary receive buffer garbage flush for 50ms + clearTime = millis() + 50; + while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; + + wait = false; // No need to wait anymore + lastCmdTime = millis(); // Set last received command time + + // Send screen size etc using a simple header with delimiters for client checks + sendParameters(filename); + } + } + else + { + // Check for time-out + if ( millis() > lastCmdTime + START_TIMEOUT) return false; + } + } + + uint8_t color[3 * NPIXELS]; // RGB and 565 format color buffer for N pixels + + // Send all the pixels on the whole screen + for ( uint32_t y = 0; y < tft.height(); y++) + { + // Increment x by NPIXELS as we send NPIXELS for every byte received + for ( uint32_t x = 0; x < tft.width(); x += NPIXELS) + { + delay(0); // Equivalent to yield() for ESP8266; + + // Wait here for serial data to arrive or a time-out elapses + while ( Serial.available() == 0 ) + { + if ( millis() > lastCmdTime + PIXEL_TIMEOUT) return false; + delay(0); // Equivalent to yield() for ESP8266; + } + + // Serial data must be available to get here, read 1 byte and + // respond with N pixels, i.e. N x 3 RGB bytes or N x 2 565 format bytes + if ( Serial.read() == 'X' ) { + // X command byte means abort, so clear the buffer and return + clearTime = millis() + 50; + while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; + return false; + } + // Save arrival time of the read command (for later time-out check) + lastCmdTime = millis(); + +#if defined BITS_PER_PIXEL && BITS_PER_PIXEL >= 24 && NPIXELS > 1 + // Fetch N RGB pixels from x,y and put in buffer + tft.readRectRGB(x, y, NPIXELS, 1, color); + // Send buffer to client + Serial.write(color, 3 * NPIXELS); // Write all pixels in the buffer +#else + // Fetch N 565 format pixels from x,y and put in buffer + if (NPIXELS > 1) tft.readRect(x, y, NPIXELS, 1, (uint16_t *)color); + else + { + uint16_t c = tft.readPixel(x, y); + color[0] = c>>8; + color[1] = c & 0xFF; // Swap bytes + } + // Send buffer to client + Serial.write(color, 2 * NPIXELS); // Write all pixels in the buffer +#endif + } + } + + Serial.flush(); // Make sure all pixel bytes have been despatched + + return true; +} + +//==================================================================================== +// Send screen size etc using a simple header with delimiters for client checks +//==================================================================================== +void sendParameters(String filename) +{ + Serial.write('W'); // Width + Serial.write(tft.width() >> 8); + Serial.write(tft.width() & 0xFF); + + Serial.write('H'); // Height + Serial.write(tft.height() >> 8); + Serial.write(tft.height() & 0xFF); + + Serial.write('Y'); // Bits per pixel (16 or 24) + if (NPIXELS > 1) Serial.write(BITS_PER_PIXEL); + else Serial.write(16); // readPixel() only provides 16 bit values + + Serial.write('?'); // Filename next + Serial.print(filename); + + Serial.write('.'); // End of filename marker + + Serial.write(FILE_EXT); // Filename extension identifier + + Serial.write(*FILE_TYPE); // First character defines file type j,b,p,t +} From d13f84e4a6b05dc5326495072cc29a9aa852f16f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 24 Nov 2018 01:30:41 +0000 Subject: [PATCH 36/94] Re-work the support for bi-directional SDA line Tested on ESP32 and ST7789V display only. It may not work with other displays! Use: #define TFT_SDA_READ in setup file to use bi-directional SDA pin support. --- README.md | 4 +- TFT_eSPI.cpp | 220 ++++++++++++++-------------------- TFT_eSPI.h | 23 ++-- User_Setups/SetupX_Template.h | 5 + 4 files changed, 112 insertions(+), 140 deletions(-) diff --git a/README.md b/README.md index a010d0c..beffc09 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ The Button class from Adafruit_GFX is incorporated, with the enhancement that th The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. -The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported and in the case any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. +The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266/ESP32 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. -Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting a configuration in the library "User_Setup_Selet,h" file. Fonts and features can easily be disabled by commenting out lines. +Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file. Fonts and features can easily be enabled/disabled by commenting out lines. # Anti-aliased Fonts diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 86029f9..260e324 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -534,7 +534,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) CS_L; tft_Write_8(cmd_function); DC_D; - reg = tft_Read_8(0); + reg = tft_Read_8(); CS_H; spi_end_read(); @@ -624,62 +624,40 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) spi_begin_read(); - #ifdef ST7789_DRIVER - writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required) - writedata(0x66); - #endif - readAddrWindow(x0, y0, x0, y0); // Sets CS low #ifdef TFT_SDA_READ - // To be investigated: spi_end_read() is VERY slow on the ESP8266 here - spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32 - SPI.end(); // Disconnect the SPI peripheral to release the pins - digitalWrite(TFT_SCLK, HIGH); // Set clock pin high - pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output - pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input + begin_SDA_Read(); #endif // Dummy read to throw away don't care value - tft_Read_8(0); + tft_Read_8(); + + #if !defined (ILI9488_DRIVER) // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits - #if !defined (ILI9488_DRIVER) - - uint8_t r = tft_Read_8(0); - uint8_t g = tft_Read_8(0); - uint8_t b = tft_Read_8(0); + uint8_t r = tft_Read_8(); + uint8_t g = tft_Read_8(); + uint8_t b = tft_Read_8(); #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left - uint8_t r = (tft_Read_8(0)&0x7E)<<1; - uint8_t g = (tft_Read_8(0)&0x7E)<<1; - uint8_t b = (tft_Read_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8()&0x7E)<<1; + uint8_t g = (tft_Read_8()&0x7E)<<1; + uint8_t b = (tft_Read_8()&0x7E)<<1; #endif CS_H; -#ifdef TFT_SDA_READ - #ifdef ESP32 - SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); - #else - #ifdef TFT_SPI_OVERLAP - SPI.pins(6, 7, 8, 0); - #else - SPI.begin(); - #endif + #ifdef TFT_SDA_READ + end_SDA_Read(); #endif - #ifdef ST7789_DRIVER - writecommand(ST7789_COLMOD); - writedata(0x55); - #endif -#else + spi_end_read(); -#endif return color565(r, g, b); @@ -793,44 +771,34 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t spi_begin_read(); - #ifdef ST7789_DRIVER - writecommand(ST7789_COLMOD); // Switch from 16 bit colour to 18 bit (required) - writedata(0x66); - #endif - readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low #ifdef TFT_SDA_READ - // To be investigated: spi_end_read() is VERY slow on the ESP8266 here - spi_end_read(); // Releasing the HAL mutex is mandatory for the ESP32 - SPI.end(); // Disconnect the SPI peripheral to release the pins - digitalWrite(TFT_SCLK, HIGH); // Set clock pin high - pinMode(TFT_SCLK, OUTPUT); // Set the SCLK pin to output - pinMode(TFT_MOSI, INPUT_PULLUP); // Set the MOSI pin to input + begin_SDA_Read(); #endif // Dummy read to throw away don't care value - tft_Read_8(0); + tft_Read_8(); // Read window pixel 24 bit RGB values uint32_t len = w * h; while (len--) { - // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte - // as the TFT stores colours as 18 bits #if !defined (ILI9488_DRIVER) - uint8_t r = tft_Read_8(0); - uint8_t g = tft_Read_8(0); - uint8_t b = tft_Read_8(0); + // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte + // as the TFT stores colours as 18 bits + uint8_t r = tft_Read_8(); + uint8_t g = tft_Read_8(); + uint8_t b = tft_Read_8(); #else // The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left - uint8_t r = (tft_Read_8(0)&0x7E)<<1; - uint8_t g = (tft_Read_8(0)&0x7E)<<1; - uint8_t b = (tft_Read_8(0)&0x7E)<<1; + uint8_t r = (tft_Read_8()&0x7E)<<1; + uint8_t g = (tft_Read_8()&0x7E)<<1; + uint8_t b = (tft_Read_8()&0x7E)<<1; #endif @@ -840,23 +808,11 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t CS_H; -#ifdef TFT_SDA_READ - #ifdef ESP32 - SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); - #else - #ifdef TFT_SPI_OVERLAP - SPI.pins(6, 7, 8, 0); - #else - SPI.begin(); - #endif + #ifdef TFT_SDA_READ + end_SDA_Read(); #endif - #ifdef ST7789_DRIVER - writecommand(ST7789_COLMOD); - writedata(0x55); - #endif -#else + spi_end_read(); -#endif #endif } @@ -865,40 +821,66 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t ** Function name: tft_Read_8 ** Description: Software SPI to read bidirectional SDA line ***************************************************************************************/ -// For the ST7789 the tft_Read_8() macro is replaced by a function -#ifdef TFT_SDA_READ - #ifdef ESP32 - #define SCLK_L GPIO.out_w1tc = (1 << TFT_SCLK) - #define SCLK_H GPIO.out_w1ts = (1 << TFT_SCLK) - #else // ESP8266 - #define SCLK_L GPOC=sclkpinmask - #define SCLK_H GPOS=sclkpinmask - #endif -uint8_t TFT_eSPI::tft_Read_8(uint8_t dummy) +#if defined (ESP8266) && defined (TFT_SDA_READ) +uint8_t TFT_eSPI::tft_Read_8(void) { uint8_t ret = 0; uint32_t reg = 0; for (uint8_t i = 0; i < 8; i++) { // read results ret <<= 1; - #ifdef ESP32 // bit bangs at around 1MHz - SCLK_L; - //SCLK_L; - reg = gpio_input_get(); // SDA must connect to ESP32 pin in range 0-31 - SCLK_H; - if (reg&(1< Date: Sat, 24 Nov 2018 02:38:49 +0000 Subject: [PATCH 37/94] Fix issue #250 --- Extensions/Sprite.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 73285da..6463b59 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -946,11 +946,14 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t { if (!_created ) return; + if ((x >= _iwidth) || (y >= _iheight)) return; + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } - if ((x < 0) || (y < 0) || (x >= _iwidth) || (y >= _iheight)) return; if ((x + w) > _iwidth) w = _iwidth - x; if ((y + h) > _iheight) h = _iheight - y; + if ((w < 1) || (h < 1)) return; int32_t yp = _iwidth * y + x; From 329b794950ce974b4374f1c95f26c5e8afb761e5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 24 Nov 2018 02:49:13 +0000 Subject: [PATCH 38/94] Update version and ReadMe Added notes about reading from the display. --- README.md | 2 ++ library.json | 2 +- library.properties | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index beffc09..bb3dadb 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 proce The library supports TFT displays designed for the Raspberry Pi that are based on a ILI9486 driver chip with a 480 x 320 pixel screen. This display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral). +Some displays permit the internal TFT screen RAM to be read. The library supports reading from ILI9341, ST7789 and ILI9488 SPI displays for the ESP32 and ESP8266. The 8 bit parallel displays used with the ESP32 can usually can be read too. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation. + Support has been added recently for Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is currently relatively immature and thus only one example has been provided. Further examples will be added soon. The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed. diff --git a/library.json b/library.json index 1bba1a1..7c1f70b 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.2.2", + "version": "1.3.0", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index a2a1260..a4d6b9b 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.2.2 +version=1.3.0 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From b0d56ce39483e4fef972d2f6c28d197e38d2b4a5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 24 Nov 2018 23:30:40 +0000 Subject: [PATCH 39/94] Add ability to scroll 1bpp Sprites New example added: Sprite_scroll_1bit --- Extensions/Sprite.cpp | 16 +- .../Sprite_scroll_1bit/Sprite_scroll_1bit.ino | 147 ++++++++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-) create mode 100644 examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 6463b59..aef6010 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -657,7 +657,21 @@ void TFT_eSprite::scroll(int16_t dx, int16_t dy) fyp += iw; } } - else return; // TODO add scroll for 1 bpp + else if (_bpp == 1) + { + if (dx > 0) { tx += w; fx += w; } // Start from right edge + while (h--) + { // move pixels one by one + for (uint16_t xp = 0; xp < w; xp++) + { + if (dx <= 0) drawPixel(tx + xp, ty, readPixel(fx + xp, fy)); + if (dx > 0) drawPixel(tx - xp, ty, readPixel(fx - xp, fy)); + } + if (dy <= 0) { ty++; fy++; } + else { ty--; fy--; } + } + } + else return; // Not 1, 8 or 16 bpp // Fill the gap left by the scrolling if (dx > 0) fillRect(_sx, _sy, dx, _sh, _scolor); diff --git a/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino new file mode 100644 index 0000000..671d7b6 --- /dev/null +++ b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino @@ -0,0 +1,147 @@ +/* + Sketch to show scrolling of the graphics in sprites. + + This sketch scrolls a 1 bit per pixel (1 bpp) Sprite. + + In a 1 bit Sprite any colour except TFT_BLACK turns a pixel "ON" + TFT_BLACK turns a pixel "OFF". + + The 1 bpp Sprite has a unique property that other bit depth Sprites + do not have, your can set the rotation of the coordinate frame e.g.: + spr.setRotation(1); + + This is similar to screen rotations, so for example text can + be drawn rotated: + Rotation 0: Normal orientation + Rotation 1: Coordinate frame rotated clockwise 90 degrees + Rotation 2: Coordinate frame rotated clockwise 180 degrees (upside down) + Rotation 3: Coordinate frame rotated clockwise 270 degrees + + When pushSprite is used the sprite is drawn with the width and height + staying as created, so the created Sprite itself is not rotated during + rendering. See stext2 sprite example below at line 83. + + ON and OFF pixels can be set to any two colours before + rendering to the screen with pushSprite, for example: + tft.setBitmapColor(ON_COLOR, OFF_COLOR); + + Scrolling moves the pixels in a defined rectangle within + the Sprite. By defalt the whole sprite is scrolled. + The gap left by scrolling is filled with a defined colour. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 1 bit Sprite occupies (width * height)/8 bytes in RAM. + +*/ + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1 + +TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1 + +TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2 + +int graphVal = 1; +int delta = 1; +int grid = 0; +int tcount = 0; + +//========================================================================================== +void setup() { + tft.init(); + tft.fillScreen(TFT_BLACK); + + // Create a sprite for the graph + graph1.setColorDepth(1); + graph1.createSprite(128, 61); + graph1.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // The scroll area is set to the full sprite size upon creation of the sprite + // but we can change that by defining a smaller area using "setScrollRect()"if needed + // parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling + //graph1.setScrollRect(64, 0, 64, 61, TFT_BLACK); // Try this line to change the graph scroll area + + // Create a sprite for the scrolling numbers + stext1.setColorDepth(1); + stext1.createSprite(32, 64); + stext1.fillSprite(TFT_BLACK); // Fill sprite with blue + stext1.setScrollRect(0, 0, 32, 64, TFT_BLACK); // here we set scroll gap fill color to blue + stext1.setTextColor(TFT_WHITE); // White text, no background + stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum + + // Create a sprite for Hello World + stext2.setColorDepth(1); + stext2.createSprite(16, 80); // Narrow and tall + stext2.setRotation(1); // Plot with 90 deg. clockwise rotation + stext2.fillSprite(TFT_BLACK); + stext2.setScrollRect(0, 0, 40, 16, TFT_BLACK); // Scroll the "Hello" in the first 40 pixels + stext2.setTextColor(TFT_WHITE); // White text, no background +} + +//========================================================================================== +void loop() { + // Draw point in graph1 sprite at far right edge (this will scroll left later) + graph1.drawFastVLine(127,60-graphVal,2,TFT_WHITE); // draw 2 pixel point on graph + + // Draw number in stext1 sprite at 31,63 (bottom right datum set) + stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2 + + // Push the sprites onto the TFT at specied coordinates + tft.setBitmapColor(TFT_WHITE, TFT_BLUE); // Specify the colours of the ON and OFF pixels + graph1.pushSprite(0, 0); + + tft.setBitmapColor(TFT_GREEN, TFT_BLACK); + stext1.pushSprite(0, 64); + + tft.setBitmapColor(TFT_BLACK, TFT_YELLOW); + stext2.pushSprite(60, 70); + + // Change the value to plot + graphVal+=delta; + + // If the value reaches a limit, then change delta of value + if (graphVal >= 60) delta = -1; // ramp down value + else if (graphVal <= 1) delta = +1; // ramp up value + + delay(50); // wait so things do not scroll too fast + + // Now scroll the sprites scroll(dt, dy) where: + // dx is pixels to scroll, left = negative value, right = positive value + // dy is pixels to scroll, up = negative value, down = positive value + graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down + stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up + stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0 + + // Draw the grid on far right edge of sprite as graph has now moved 1 pixel left + grid++; + if (grid >= 10) + { // Draw a vertical line if we have scrolled 10 times (10 pixels) + grid = 0; + graph1.drawFastVLine(127, 0, 61, TFT_WHITE); // draw line on graph + } + else + { // Otherwise draw points spaced 10 pixels for the horizontal grid lines + for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, TFT_WHITE); + } + + tcount--; + if (tcount <=0) + { // If we have scrolled 40 pixels the redraw text + tcount = 40; + stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2 + } + +} // Loop back and do it all again +//========================================================================================== From ee7d18f7f975d4cab7bed6957e0547699afe8292 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 24 Nov 2018 23:32:00 +0000 Subject: [PATCH 40/94] Raise version --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 7c1f70b..65e6a5a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.0", + "version": "1.3.1", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index a4d6b9b..16f3333 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.0 +version=1.3.1 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From a0e2bc97d60fa9c71684d0fdcffad4bf32ada1fb Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sat, 24 Nov 2018 23:45:31 +0000 Subject: [PATCH 41/94] Comment typo --- examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino index 671d7b6..ab4a53e 100644 --- a/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino +++ b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino @@ -7,7 +7,7 @@ TFT_BLACK turns a pixel "OFF". The 1 bpp Sprite has a unique property that other bit depth Sprites - do not have, your can set the rotation of the coordinate frame e.g.: + do not have, you can set the rotation of the coordinate frame e.g.: spr.setRotation(1); This is similar to screen rotations, so for example text can From 5e62875ff548a2214500ffc05f06a93010548fd0 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 03:15:16 +0000 Subject: [PATCH 42/94] Fix issue #256 Parallel compatibility lost during recent updates. Now working again. --- TFT_eSPI.cpp | 2 +- TFT_eSPI.h | 8 +++++--- library.json | 2 +- library.properties | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 260e324..92873da 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4928,7 +4928,7 @@ void writeBlock(uint16_t color, uint32_t repeat) void writeBlock(uint16_t color, uint32_t repeat) { - uint32_t color32 = SPI_32(color, color); + uint32_t color32 = COL_32(color, color); if (repeat > 31) // Revert legacy toggle buffer change { diff --git a/TFT_eSPI.h b/TFT_eSPI.h index fae8068..2af6786 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -226,10 +226,12 @@ #ifdef ESP8266 // Concatenate two 16 bit values for the SPI 32 bit register write #define SPI_32(H,L) ( (H)<<16 | (L) ) + #define COL_32(H,L) ( (H)<<16 | (L) ) #else - // Swap byte order for concatenated 16 bit window address or colors - // AB CD -> DCBA for SPI 32 bit register write - #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) + #define SPI_32(H,L) ( (H)<<16 | (L) ) + // Swap byte order for concatenated 16 bit colors + // AB CD -> DCBA for 32 bit register write + #define COL_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) #endif #if defined (ESP32) && defined (ESP32_PARALLEL) diff --git a/library.json b/library.json index 65e6a5a..7540093 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.1", + "version": "1.3.2", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 16f3333..fd3be61 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.1 +version=1.3.2 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From e01ea43baf5c75bfe9e4217909c2d1d94b811b4c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 03:47:54 +0000 Subject: [PATCH 43/94] Fix SPI incompatibility I fixed the parallel and broke the SPI, now both work! --- TFT_eSPI.h | 6 +++++- library.json | 2 +- library.properties | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 2af6786..8f31f29 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -228,7 +228,11 @@ #define SPI_32(H,L) ( (H)<<16 | (L) ) #define COL_32(H,L) ( (H)<<16 | (L) ) #else - #define SPI_32(H,L) ( (H)<<16 | (L) ) + #ifdef ESP32_PARALLEL + #define SPI_32(H,L) ( (H)<<16 | (L) ) + #else + #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) + #endif // Swap byte order for concatenated 16 bit colors // AB CD -> DCBA for 32 bit register write #define COL_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) diff --git a/library.json b/library.json index 7540093..786075d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.2", + "version": "1.3.3", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index fd3be61..a9e0071 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.2 +version=1.3.3 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From eb08c17b24b665f86335f779d4ac4935c9575a7c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 16:54:31 +0000 Subject: [PATCH 44/94] Raise version Arduino library manager picked up the wrong release. This version raise is to forece a new release to be recognised. Releases 1.3.2 and 1.3.3 have been deleted. --- library.json | 2 +- library.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library.json b/library.json index 786075d..94d5340 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.3", + "version": "1.3.4", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index a9e0071..b8b5f01 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.3 +version=1.3.4 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 0f630b375bf93edb88a4ee438a47499df53c3fe5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 17:20:40 +0000 Subject: [PATCH 45/94] Add TTGO boards --- User_Setup_Select.h | 3 +++ User_Setups/Setup22_TTGO_T4.h | 28 ++++++++++++++++++++++++++++ User_Setups/Setup23_TTGO_TM.h | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 User_Setups/Setup22_TTGO_T4.h create mode 100644 User_Setups/Setup23_TTGO_TM.h diff --git a/User_Setup_Select.h b/User_Setup_Select.h index be58b13..bd31358 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -43,6 +43,9 @@ //#include // Setup file for ESP8266 and ILI9488 SPI bus TFT //#include // Setup file for ESP32 and ILI9488 SPI bus TFT +//#include // Setup file for ESP32 and TTGO T4 (BTC) ILI9341 SPI bus TFT +//#include // Setup file for ESP32 and TTGO TM ST7789 SPI bus TFT + //#include // Setup file configured for my ST7735S 80x160 //#include diff --git a/User_Setups/Setup22_TTGO_T4.h b/User_Setups/Setup22_TTGO_T4.h new file mode 100644 index 0000000..fa04323 --- /dev/null +++ b/User_Setups/Setup22_TTGO_T4.h @@ -0,0 +1,28 @@ +// Setup for the TTGO T4 ("Bitcoin Tracker") ESP32 board with 2.2" ILI9341 display + +#define ILI9341_DRIVER + +#define TFT_MISO 12 +#define TFT_MOSI 23 +#define TFT_SCLK 18 + +#define TFT_CS 27 +#define TFT_DC 26 +#define TFT_RST 5 + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF + +#define SMOOTH_FONT + +//#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 + #define SPI_FREQUENCY 40000000 // Maximum for ILI9341 + +#define SPI_TOUCH_FREQUENCY 2500000 + +#define SPI_READ_FREQUENCY 10000000 diff --git a/User_Setups/Setup23_TTGO_TM.h b/User_Setups/Setup23_TTGO_TM.h new file mode 100644 index 0000000..74c9a05 --- /dev/null +++ b/User_Setups/Setup23_TTGO_TM.h @@ -0,0 +1,34 @@ +// Setup for the TTGO TM (Music) ESP32 board with 2.4" ST7789V display + +#define ST7789_DRIVER + +#define TFT_SDA_READ // Read from display, it only provides an SDA pin + +#define TFT_MISO 19 // Must be defined even though it is not used +#define TFT_MOSI 23 // Connected to display SDA line +#define TFT_SCLK 18 + +#define TFT_CS 05 +#define TFT_DC 16 +#define TFT_RST 17 + +#define TFT_WIDTH 240 +#define TFT_HEIGHT 320 + +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF + +#define SMOOTH_FONT + +#define SPI_FREQUENCY 40000000 // The display also seems to work reliably at 80MHz + +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V + From 046e48f8c33a3f6412f01475a8a510b61a5c3d33 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 18:08:29 +0000 Subject: [PATCH 46/94] Delete legacy example --- .../TFT_Screen_Capture/TFT_Screen_Capture.ino | 188 ------ .../TFT_Screen_Capture/processing_sketch.ino | 535 ------------------ .../TFT_Screen_Capture/screenServer.ino | 194 ------- 3 files changed, 917 deletions(-) delete mode 100644 examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino delete mode 100644 examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino delete mode 100644 examples/320 x 240/TFT_Screen_Capture/screenServer.ino diff --git a/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino b/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino deleted file mode 100644 index d791b0f..0000000 --- a/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino +++ /dev/null @@ -1,188 +0,0 @@ -/* - This sketch has been written to test the Processing screenshot client. - - It has been created to work with the TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - It sends screenshots to a PC running a Processing client sketch. - - The Processing IDE that will run the client sketch can be downloaded - here: https://processing.org/ - - The Processing sketch needed is contained within a tab attached to this - Arduino sketch. Cut and copy that tab into the Processing IDE and run. - - This sketch uses the GLCD, 2, 4, 6 fonts only. - - Make sure all the display driver and pin comnenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. - - Maximum recommended SPI clock rate is 27MHz when reading pixels, 40MHz - seems to be OK with ILI9341 displays but this is above the manufacturers - specifed maximum clock rate. - - ######################################################################### - ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### - ######################################################################### -*/ - -// Created by: Bodmer 5/3/17 -// Updated by: Bodmer 10/3/17 -// Version: 0.06 - -// MIT licence applies, all text above must be included in derivative works - -#include // Hardware-specific library -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height - -unsigned long targetTime = 0; -byte red = 31; -byte green = 0; -byte blue = 0; -byte state = 0; -unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each - -void setup(void) { - Serial.begin(921600); - - tft.init(); - tft.setRotation(0); - tft.fillScreen(TFT_BLACK); - - randomSeed(analogRead(A0)); - - targetTime = millis() + 1000; -} - -void loop() { - - if (targetTime < millis()) { - targetTime = millis() + 1500; // Wait a minimum of 1.5s - - tft.setRotation(random(4)); - rainbow_fill(); // Fill the screen with rainbow colours - - tft.setTextColor(TFT_BLACK); // Text background is not defined so it is transparent - tft.setTextDatum(TC_DATUM); // Top Centre datum - int xpos = tft.width()/2; // Centre of screen - - tft.setTextFont(0); // Select font 0 which is the Adafruit font - tft.drawString("Original Adafruit font!", xpos, 5); - - // The new larger fonts do not need to use the .setCursor call, coords are embedded - tft.setTextColor(TFT_BLACK); // Do not plot the background colour - - // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) - tft.drawString("Font size 2", xpos, 14, 2); // Draw text centre at position xpos, 14 using font 2 - tft.drawString("Font size 4", xpos, 30, 4); // Draw text centre at position xpos, 30 using font 4 - tft.drawString("12.34", xpos, 54, 6); // Draw text centre at position xpos, 54 using font 6 - - tft.drawString("12.34 is in font size 6", xpos, 92, 2); // Draw text centre at position xpos, 92 using font 2 - // Note the x position is the top of the font! - - // draw a floating point number - float pi = 3.1415926; // Value to print - int precision = 3; // Number of digits after decimal point - - int ypos = 110; // y position - - tft.setTextDatum(TR_DATUM); // Top Right datum so text butts neatly to xpos (right justified) - - tft.drawFloat(pi, precision, xpos, ypos, 2); // Draw rounded number and return new xpos delta for next print position - - tft.setTextDatum(TL_DATUM); // Top Left datum so text butts neatly to xpos (left justified) - - tft.drawString(" is pi", xpos, ypos, 2); - - tft.setTextSize(1); // We are using a font size multiplier of 1 - tft.setTextDatum(TC_DATUM); // Top Centre datum - tft.setTextColor(TFT_BLACK); // Set text colour to black, no background (so transparent) - - tft.drawString("Transparent...", xpos, 125, 4); // Font 4 - - tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text colour to white and background to black - tft.drawString("White on black", xpos, 150, 4); // Font 4 - - tft.setTextColor(TFT_GREEN, TFT_BLACK); // This time we will use green text on a black background - - tft.setTextFont(2); // Select font 2, now we do not need to specify the font in drawString() - - // An easier way to position text and blank old text is to set the datum and use width padding - tft.setTextDatum(BC_DATUM); // Bottom centre for text datum - tft.setTextPadding(tft.width() + 1); // Pad text to full screen width + 1 spare for +/-1 position rounding - - tft.drawString("Ode to a Small Lump of Green Putty", xpos, 230 - 32); - tft.drawString("I Found in My Armpit One Midsummer", xpos, 230 - 16); - tft.drawString("Morning", xpos, 230); - - tft.setTextDatum(TL_DATUM); // Reset to top left for text datum - tft.setTextPadding(0); // Reset text padding to 0 pixels - - // Now call the screen server to send a copy of the TFT screen to the PC running the Processing client sketch - screenServer(); - } -} - -// Fill screen with a rainbow pattern -void rainbow_fill() -{ - // The colours and state are not initialised so the start colour changes each time the funtion is called - int rotation = tft.getRotation(); - tft.setRotation(random(4)); - for (int i = tft.height() - 1; i >= 0; i--) { - // This is a "state machine" that ramps up/down the colour brightnesses in sequence - switch (state) { - case 0: - green ++; - if (green == 64) { - green = 63; - state = 1; - } - break; - case 1: - red--; - if (red == 255) { - red = 0; - state = 2; - } - break; - case 2: - blue ++; - if (blue == 32) { - blue = 31; - state = 3; - } - break; - case 3: - green --; - if (green == 255) { - green = 0; - state = 4; - } - break; - case 4: - red ++; - if (red == 32) { - red = 31; - state = 5; - } - break; - case 5: - blue --; - if (blue == 255) { - blue = 0; - state = 0; - } - break; - } - colour = red << 11 | green << 5 | blue; - // Draw a line 1 pixel wide in the selected colour - tft.drawFastHLine(0, i, tft.width(), colour); // in this example tft.width() returns the pixel width of the display - } - tft.setRotation(rotation); -} - - - diff --git a/examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino b/examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino deleted file mode 100644 index 3e71f41..0000000 --- a/examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino +++ /dev/null @@ -1,535 +0,0 @@ -// This is a copy of the processing sketch that can be used to capture the images -// Copy the sketch below and remove the /* and */ at the beginning and end. - -// The sketch runs in Processing version 3.3 on a PC, it can be downloaded here: -// https://processing.org/download/ - -/* - -// This is a Processing sketch, see https://processing.org/ to download the IDE - -// The sketch is a client that requests TFT screenshots from an Arduino board. -// The Arduino must call a screenshot server function to respond with pixels. - -// It has been created to work with the TFT_eSPI library here: -// https://github.com/Bodmer/TFT_eSPI - -// The sketch must only be run when the designated serial port is available and enumerated -// otherwise the screenshot window may freeze and that process will need to be terminated -// This is a limitation of the Processing environment and not the sketch. -// If anyone knows how to determine if a serial port is available at start up the PM me -// on (Bodmer) the Arduino forum. - -// The block below contains variables that the user may need to change for a particular setup -// As a minimum set the serial port and baud rate must be defined. The capture window is -// automatically resized for landscape, portrait and different TFT resolutions. - -// Captured images are stored in the sketch folder, use the Processing IDE "Sketch" menu -// option "Show Sketch Folder" or press Ctrl+K - -// Created by: Bodmer 5/3/17 -// Updated by: Bodmer 12/3/17 -// Version: 0.07 - -// MIT licence applies, all text above must be included in derivative works - - -// ########################################################################################### -// # These are the values to change for a particular setup # -// # -int serial_port = 0; // Use enumerated value from list provided when sketch is run # -// # -// On an Arduino Due Programming Port use a baud rate of:115200) # -// On an Arduino Due Native USB Port use a baud rate of any value # -int serial_baud_rate = 921600; // # -// # -// Change the image file type saved here, comment out all but one # -//String image_type = ".jpg"; // # -String image_type = ".png"; // Lossless compression # -//String image_type = ".bmp"; // # -//String image_type = ".tif"; // # -// # -boolean save_border = true; // Save the image with a border # -int border = 5; // Border pixel width # -boolean fade = false; // Fade out image after saving # -// # -int max_images = 100; // Maximum of numbered file images before over-writing files # -// # -int max_allowed = 1000; // Maximum number of save images allowed before a restart # -// # -// # End of the values to change for a particular setup # -// ########################################################################################### - -// These are default values, this sketch obtains the actual values from the Arduino board -int tft_width = 480; // default TFT width (automatic - sent by Arduino) -int tft_height = 480; // default TFT height (automatic - sent by Arduino) -int color_bytes = 2; // 2 for 16 bit, 3 for three RGB bytes (automatic - sent by Arduino) - -import processing.serial.*; - -Serial serial; // Create an instance called serial - -int serialCount = 0; // Count of colour bytes arriving - -// Stage window graded background colours -color bgcolor1 = color(0, 100, 104); // Arduino IDE style background color 1 -color bgcolor2 = color(77, 183, 187); // Arduino IDE style background color 2 -//color bgcolor2 = color(255, 255, 255); // White - -// TFT image frame greyscale value (dark grey) -color frameColor = 42; - -color buttonStopped = color(255, 0, 0); -color buttonRunning = color(128, 204, 206); -color buttonDimmed = color(180, 0, 0); -boolean dimmed = false; -boolean running = true; -boolean mouseClick = false; - -int[] rgb = new int[3]; // Buffer for the colour bytes -int indexRed = 0; // Colour byte index in the array -int indexGreen = 1; -int indexBlue = 2; - -int n = 0; - -int x_offset = (500 - tft_width) /2; // Image offsets in the window -int y_offset = 20; - -int xpos = 0, ypos = 0; // Current pixel position - -int beginTime = 0; -int pixelWaitTime = 1000; // Maximum 1000ms wait for image pixels to arrive -int lastPixelTime = 0; // Time that "image send" command was sent - -int requestTime = 0; -int requestCount = 0; - -int state = 0; // State machine current state - -int progress_bar = 0; // Console progress bar dot count -int pixel_count = 0; // Number of pixels read for 1 screen -float percentage = 0; // Percentage of pixels received - -int saved_image_count = 0; // Stats - number of images processed -int bad_image_count = 0; // Stats - number of images that had lost pixels -String filename = ""; - -int drawLoopCount = 0; // Used for the fade out - -void setup() { - - size(500, 540); // Stage size, can handle 480 pixels wide screen - noStroke(); // No border on the next thing drawn - noSmooth(); // No anti-aliasing to avoid adjacent pixel colour merging - - // Graded background and title - drawWindow(); - - frameRate(2000); // High frame rate so draw() loops fast - - // Print a list of the available serial ports - println("-----------------------"); - println("Available Serial Ports:"); - println("-----------------------"); - printArray(Serial.list()); - println("-----------------------"); - - print("Port currently used: ["); - print(serial_port); - println("]"); - - String portName = Serial.list()[serial_port]; - - serial = new Serial(this, portName, serial_baud_rate); - - state = 99; -} - -void draw() { - - if (mouseClick) buttonClicked(); - - switch(state) { - - case 0: // Init varaibles, send start request - if (running) { - tint(0, 0, 0, 255); - flushBuffer(); - println(""); - print("Ready: "); - - xpos = 0; - ypos = 0; - serialCount = 0; - progress_bar = 0; - pixel_count = 0; - percentage = 0; - drawLoopCount = frameCount; - lastPixelTime = millis() + 1000; - - state = 1; - } else { - if (millis() > beginTime) { - beginTime = millis() + 500; - dimmed = !dimmed; - if (dimmed) drawButton(buttonDimmed); - else drawButton(buttonStopped); - } - } - break; - - case 1: // Console message, give server some time - print("requesting image "); - serial.write("S"); - delay(10); - beginTime = millis(); - requestTime = millis() + 1000; - requestCount = 1; - state = 2; - break; - - case 2: // Get size and set start time for rendering duration report - if (millis() > requestTime) { - requestCount++; - print("*"); - serial.clear(); - serial.write("S"); - if (requestCount > 32) { - requestCount = 0; - System.err.println(" - no response!"); - state = 0; - } - requestTime = millis() + 1000; - } - if ( getSize() == true ) { // Go to next state when we have the size and bits per pixel - getFilename(); - flushBuffer(); // Precaution in case image header size increases in later versions - lastPixelTime = millis() + 1000; - beginTime = millis(); - state = 3; - } - break; - - case 3: // Request pixels and render returned RGB values - state = renderPixels(); // State will change when all pixels are rendered - - // Request more pixels, changing the number requested allows the average transfer rate to be controlled - // The pixel transfer rate is dependant on four things: - // 1. The frame rate defined in this Processing sketch in setup() - // 2. The baud rate of the serial link (~10 bit periods per byte) - // 3. The number of request bytes 'R' sent in the lines below - // 4. The number of pixels sent in a burst by the server sketch (defined via NPIXELS) - - //serial.write("RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR"); // 32 x NPIXELS more - serial.write("RRRRRRRRRRRRRRRR"); // 16 x NPIXELS more - //serial.write("RRRRRRRR"); // 8 x NPIXELS more - //serial.write("RRRR"); // 4 x NPIXELS more - //serial.write("RR"); // 2 x NPIXELS more - //serial.write("R"); // 1 x NPIXELS more - if (!running) state = 4; - break; - - case 4: // Pixel receive time-out, flush serial buffer - flushBuffer(); - state = 6; - break; - - case 5: // Save the image to the sketch folder (Ctrl+K to access) - saveScreenshot(); - saved_image_count++; - println("Saved image count = " + saved_image_count); - if (bad_image_count > 0) System.err.println(" Bad image count = " + bad_image_count); - drawLoopCount = frameCount; // Reset value ready for counting in step 6 - state = 6; - break; - - case 6: // Fade the old image if enabled - if ( fadedImage() == true ) state = 0; // Go to next state when image has faded - break; - - case 99: // Draw image viewer window - drawWindow(); - delay(50); // Delay here seems to be required for the IDE console to get ready - state = 0; - break; - - default: - println(""); - System.err.println("Error state reached - check sketch!"); - break; - } -} - -void drawWindow() -{ - // Graded background in Arduino colours - for (int i = 0; i < height - 25; i++) { - float inter = map(i, 0, height - 25, 0, 1); - color c = lerpColor(bgcolor1, bgcolor2, inter); - stroke(c); - line(0, i, 500, i); - } - fill(bgcolor2); - rect( 0, height-25, width-1, 24); - textAlign(CENTER); - textSize(20); - fill(0); - text("Bodmer's TFT image viewer", width/2, height-6); - - if (running) drawButton(buttonRunning); - else drawButton(buttonStopped); -} - -void flushBuffer() -{ - //println("Clearing serial pipe after a time-out"); - int clearTime = millis() + 50; - while ( millis() < clearTime ) serial.clear(); -} - -boolean getSize() -{ - if ( serial.available() > 6 ) { - println(); - char code = (char)serial.read(); - if (code == 'W') { - tft_width = serial.read()<<8 | serial.read(); - } - code = (char)serial.read(); - if (code == 'H') { - tft_height = serial.read()<<8 | serial.read(); - } - code = (char)serial.read(); - if (code == 'Y') { - int bits_per_pixel = (char)serial.read(); - if (bits_per_pixel == 24) color_bytes = 3; - else color_bytes = 2; - } - code = (char)serial.read(); - if (code == '?') { - drawWindow(); - - x_offset = (500 - tft_width) /2; - tint(0, 0, 0, 255); - noStroke(); - fill(frameColor); - rect((width - tft_width)/2 - border, y_offset - border, tft_width + 2 * border, tft_height + 2 * border); - return true; - } - } - return false; -} - -void saveScreenshot() -{ - println(); - if (saved_image_count < max_allowed) - { - if (filename == "") filename = "tft_screen_" + (n++); - filename = filename + image_type; - println("Saving image as \"" + filename + "\""); - if (save_border) - { - PImage partialSave = get(x_offset - border, y_offset - border, tft_width + 2*border, tft_height + 2*border); - partialSave.save(filename); - } else { - PImage partialSave = get(x_offset, y_offset, tft_width, tft_height); - partialSave.save(filename); - } - - if (n>=max_images) n = 0; - } - else - { - System.err.println(max_allowed + " saved image count exceeded, restart the sketch"); - } -} - -void getFilename() -{ - int readTime = millis() + 20; - int inByte = 0; - filename = ""; - while ( serial.available() > 0 && millis() < readTime && inByte != '.') - { - inByte = serial.read(); - if (inByte == ' ') inByte = '_'; - if ( unicodeCheck(inByte) ) filename += (char)inByte; - } - - inByte = serial.read(); - if (inByte == '@') filename += "_" + timeCode(); - else if (inByte == '#') filename += "_" + saved_image_count%100; - else if (inByte == '%') filename += "_" + millis(); - else if (inByte != '*') filename = ""; - - inByte = serial.read(); - if (inByte == 'j') image_type =".jpg"; - else if (inByte == 'b') image_type =".bmp"; - else if (inByte == 'p') image_type =".png"; - else if (inByte == 't') image_type =".tif"; -} - -boolean unicodeCheck(int unicode) -{ - if ( unicode >= '0' && unicode <= '9' ) return true; - if ( (unicode >= 'A' && unicode <= 'Z' ) || (unicode >= 'a' && unicode <= 'z')) return true; - if ( unicode == '_' || unicode == '/' ) return true; - return false; -} - -String timeCode() -{ - String timeCode = (int)year() + "_" + (int)month() + "_" + (int)day() + "_"; - timeCode += (int)hour() + "_" + (int)minute() + "_" + (int)second(); - return timeCode; -} - -int renderPixels() -{ - if ( serial.available() > 0 ) { - - // Add the latest byte from the serial port to array: - while (serial.available()>0) - { - rgb[serialCount++] = serial.read(); - - // If we have 3 colour bytes: - if ( serialCount >= color_bytes ) { - serialCount = 0; - pixel_count++; - if (color_bytes == 3) - { - stroke(rgb[indexRed], rgb[indexGreen], rgb[indexBlue], 1000); - } else - { // Can cater for various byte orders - //stroke( (rgb[0] & 0x1F)<<3, (rgb[0] & 0xE0)>>3 | (rgb[1] & 0x07)<<5, (rgb[1] & 0xF8)); - //stroke( (rgb[1] & 0x1F)<<3, (rgb[1] & 0xE0)>>3 | (rgb[0] & 0x07)<<5, (rgb[0] & 0xF8)); - stroke( (rgb[0] & 0xF8), (rgb[1] & 0xE0)>>3 | (rgb[0] & 0x07)<<5, (rgb[1] & 0x1F)<<3); - //stroke( (rgb[1] & 0xF8), (rgb[0] & 0xE0)>>3 | (rgb[1] & 0x07)<<5, (rgb[0] & 0x1F)<<3); - } - // We get some pixel merge aliasing if smooth() is defined, so draw pixel twice - point(xpos + x_offset, ypos + y_offset); - //point(xpos + x_offset, ypos + y_offset); - - lastPixelTime = millis(); - xpos++; - if (xpos >= tft_width) { - xpos = 0; - progressBar(); - ypos++; - if (ypos>=tft_height) { - ypos = 0; - if ((int)percentage <100) { - while (progress_bar++ < 64) print(" "); - percent(100); - } - println("Image fetch time = " + (millis()-beginTime)/1000.0 + " s"); - return 5; - } - } - } - } - } else - { - if (millis() > (lastPixelTime + pixelWaitTime)) - { - println(""); - System.err.println(pixelWaitTime + "ms time-out for pixels exceeded..."); - if (pixel_count > 0) { - bad_image_count++; - System.err.print("Pixels missing = " + (tft_width * tft_height - pixel_count)); - System.err.println(", corrupted image not saved"); - System.err.println("Good image count = " + saved_image_count); - System.err.println(" Bad image count = " + bad_image_count); - } - return 4; - } - } - return 3; -} - -void progressBar() -{ - progress_bar++; - print("."); - if (progress_bar >63) - { - progress_bar = 0; - percentage = 0.5 + 100 * pixel_count/(0.001 + tft_width * tft_height); - percent(percentage); - } -} - -void percent(float percentage) -{ - if (percentage > 100) percentage = 100; - println(" [ " + (int)percentage + "% ]"); - textAlign(LEFT); - textSize(16); - noStroke(); - fill(bgcolor2); - rect(10, height - 25, 70, 20); - fill(0); - text(" [ " + (int)percentage + "% ]", 10, height-8); -} - -boolean fadedImage() -{ - int opacity = frameCount - drawLoopCount; // So we get increasing fade - if (fade) - { - tint(255, opacity); - //image(tft_img, x_offset, y_offset); - noStroke(); - fill(50, 50, 50, opacity); - rect( (width - tft_width)/2, y_offset, tft_width, tft_height); - delay(10); - } - if (opacity > 50) // End fade after 50 cycles - { - return true; - } - return false; -} - -void drawButton(color buttonColor) -{ - stroke(0); - fill(buttonColor); - rect(500 - 100, 540 - 26, 80, 24); - textAlign(CENTER); - textSize(20); - fill(0); - if (running) text(" Pause ", 500 - 60, height-7); - else text(" Run ", 500 - 60, height-7); -} - -void buttonClicked() -{ - mouseClick = false; - if (running) { - running = false; - drawButton(buttonStopped); - System.err.println(""); - System.err.println("Stopped - click 'Run' button: "); - //noStroke(); - //fill(50); - //rect( (width - tft_width)/2, y_offset, tft_width, tft_height); - beginTime = millis() + 500; - dimmed = false; - state = 4; - } else { - running = true; - drawButton(buttonRunning); - } -} - -void mousePressed() { - if (mouseX > (500 - 100) && mouseX < (500 - 20) && mouseY > (540 - 26) && mouseY < (540 - 2)) { - mouseClick = true; - } -} - -*/ diff --git a/examples/320 x 240/TFT_Screen_Capture/screenServer.ino b/examples/320 x 240/TFT_Screen_Capture/screenServer.ino deleted file mode 100644 index 962d561..0000000 --- a/examples/320 x 240/TFT_Screen_Capture/screenServer.ino +++ /dev/null @@ -1,194 +0,0 @@ -// Reads a screen image off the TFT and send it to a processing client sketch -// over the serial port. Use a high baud rate, e.g. for an ESP8266: -// Serial.begin(921600); - -// At 921600 baud a 320 x 240 image with 16 bit colour transfers can be sent to the -// PC client in ~1.67s and 24 bit colour in ~2.5s which is close to the theoretical -// minimum transfer time. - -// This sketch has been created to work with the TFT_eSPI library here: -// https://github.com/Bodmer/TFT_eSPI - -// Created by: Bodmer 27/1/17 -// Updated by: Bodmer 10/3/17 -// Version: 0.07 - -// MIT licence applies, all text above must be included in derivative works - -//==================================================================================== -// Definitions -//==================================================================================== -#define BAUD_RATE 250000 // Maximum Serial Monitor rate for other messages -#define DUMP_BAUD_RATE 921600 // Rate used for screen dumps - -#define PIXEL_TIMEOUT 100 // 100ms Time-out between pixel requests -#define START_TIMEOUT 10000 // 10s Maximum time to wait at start transfer - -#define BITS_PER_PIXEL 16 // 24 for RGB colour format, 16 for 565 colour format - -// File names must be alpha-numeric characters (0-9, a-z, A-Z) or "/" underscore "_" -// other ascii characters are stripped out by client, including / generates -// sub-directories -#define DEFAULT_FILENAME "tft_screenshots/screenshot" // In case none is specified -#define FILE_TYPE "png" // jpg, bmp, png, tif are valid - -// Filename extension -// '#' = add 0-9, '@' = add timestamp, '%' add millis() timestamp, '*' = add nothing -// '@' and '%' will generate new unique filenames, so beware of cluttering up your -// hard drive with lots of images! The PC client sketch is set to limit the number of -// saved images to 1000 and will then prompt for a restart. -#define FILE_EXT '%' - -// Number of pixels to send in a burst (minimum of 1), no benefit above 8 -// NPIXELS values and render times: 1 = 5.0s, 2 = 1.75s, 4 = 1.68s, 8 = 1.67s -#define NPIXELS 8 // Must be integer division of both TFT width and TFT height - -//==================================================================================== -// Screen server call with no filename -//==================================================================================== -// Start a screen dump server (serial or network) - no filename specified -boolean screenServer(void) -{ - // With no filename the screenshot will be saved with a default name e.g. tft_screen_#.xxx - // where # is a number 0-9 and xxx is a file type specified below - return screenServer(DEFAULT_FILENAME); -} - -//==================================================================================== -// Screen server call with filename -//==================================================================================== -// Start a screen dump server (serial or network) - filename specified -boolean screenServer(String filename) -{ - Serial.end(); // Stop the serial port (clears buffers too) - Serial.begin(DUMP_BAUD_RATE); // Force baud rate to be high - delay(0); // Equivalent to yield() for ESP8266; - - boolean result = serialScreenServer(filename); // Screenshot serial port server - //boolean result = wifiScreenServer(filename); // Screenshot WiFi UDP port server (WIP) - - Serial.end(); // Stop the serial port (clears buffers too) - Serial.begin(BAUD_RATE); // Return baud rate to normal - delay(0); // Equivalent to yield() for ESP8266; - - //Serial.println(); - //if (result) Serial.println(F("Screen dump passed :-)")); - //else Serial.println(F("Screen dump failed :-(")); - - return result; -} - -//==================================================================================== -// Serial server function that sends the data to the client -//==================================================================================== -boolean serialScreenServer(String filename) -{ - // Precautionary receive buffer garbage flush for 50ms - uint32_t clearTime = millis() + 50; - while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; - - boolean wait = true; - uint32_t lastCmdTime = millis(); // Initialise start of command time-out - - // Wait for the starting flag with a start time-out - while (wait) - { - delay(0); // Equivalent to yield() for ESP8266; - // Check serial buffer - if (Serial.available() > 0) { - // Read the command byte - uint8_t cmd = Serial.read(); - // If it is 'S' (start command) then clear the serial buffer for 100ms and stop waiting - if ( cmd == 'S' ) { - // Precautionary receive buffer garbage flush for 50ms - clearTime = millis() + 50; - while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; - - wait = false; // No need to wait anymore - lastCmdTime = millis(); // Set last received command time - - // Send screen size etc using a simple header with delimiters for client checks - sendParameters(filename); - } - } - else - { - // Check for time-out - if ( millis() > lastCmdTime + START_TIMEOUT) return false; - } - } - - uint8_t color[3 * NPIXELS]; // RGB and 565 format color buffer for N pixels - - // Send all the pixels on the whole screen - for ( uint32_t y = 0; y < tft.height(); y++) - { - // Increment x by NPIXELS as we send NPIXELS for every byte received - for ( uint32_t x = 0; x < tft.width(); x += NPIXELS) - { - delay(0); // Equivalent to yield() for ESP8266; - - // Wait here for serial data to arrive or a time-out elapses - while ( Serial.available() == 0 ) - { - if ( millis() > lastCmdTime + PIXEL_TIMEOUT) return false; - delay(0); // Equivalent to yield() for ESP8266; - } - - // Serial data must be available to get here, read 1 byte and - // respond with N pixels, i.e. N x 3 RGB bytes or N x 2 565 format bytes - if ( Serial.read() == 'X' ) { - // X command byte means abort, so clear the buffer and return - clearTime = millis() + 50; - while ( millis() < clearTime && Serial.read() >= 0) delay(0); // Equivalent to yield() for ESP8266; - return false; - } - // Save arrival time of the read command (for later time-out check) - lastCmdTime = millis(); - -#if defined BITS_PER_PIXEL && BITS_PER_PIXEL >= 24 - // Fetch N RGB pixels from x,y and put in buffer - tft.readRectRGB(x, y, NPIXELS, 1, color); - // Send buffer to client - Serial.write(color, 3 * NPIXELS); // Write all pixels in the buffer -#else - // Fetch N 565 format pixels from x,y and put in buffer - tft.readRect(x, y, NPIXELS, 1, (uint16_t *)color); - // Send buffer to client - Serial.write(color, 2 * NPIXELS); // Write all pixels in the buffer -#endif - } - } - - Serial.flush(); // Make sure all pixel bytes have been despatched - - return true; -} - -//==================================================================================== -// Send screen size etc using a simple header with delimiters for client checks -//==================================================================================== -void sendParameters(String filename) -{ - Serial.write('W'); // Width - Serial.write(tft.width() >> 8); - Serial.write(tft.width() & 0xFF); - - Serial.write('H'); // Height - Serial.write(tft.height() >> 8); - Serial.write(tft.height() & 0xFF); - - Serial.write('Y'); // Bits per pixel (16 or 24) - Serial.write(BITS_PER_PIXEL); - - Serial.write('?'); // Filename next - Serial.print(filename); - - Serial.write('.'); // End of filename marker - - Serial.write(FILE_EXT); // Filename extension identifier - - Serial.write(*FILE_TYPE); // First character defines file type j,b,p,t -} - - From beda811a3aed4bcaa6a53a98716fd28c80725179 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 25 Nov 2018 19:41:29 +0000 Subject: [PATCH 47/94] Add R61581 driver as detailed in #238 Not tested by Bodmer, tested by s60sc as in #238 --- TFT_Drivers/R61581_Defines.h | 42 ++++++++++++++++++ TFT_Drivers/R61581_Init.h | 80 +++++++++++++++++++++++++++++++++++ TFT_Drivers/R61581_Rotation.h | 27 ++++++++++++ TFT_eSPI.cpp | 6 +++ TFT_eSPI.h | 2 +- User_Setup.h | 1 + User_Setup_Select.h | 18 +++++--- User_Setups/SetupX_Template.h | 1 + library.json | 2 +- library.properties | 2 +- 10 files changed, 171 insertions(+), 10 deletions(-) create mode 100644 TFT_Drivers/R61581_Defines.h create mode 100644 TFT_Drivers/R61581_Init.h create mode 100644 TFT_Drivers/R61581_Rotation.h diff --git a/TFT_Drivers/R61581_Defines.h b/TFT_Drivers/R61581_Defines.h new file mode 100644 index 0000000..bd5fb88 --- /dev/null +++ b/TFT_Drivers/R61581_Defines.h @@ -0,0 +1,42 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/R61581_Init.h b/TFT_Drivers/R61581_Init.h new file mode 100644 index 0000000..929d680 --- /dev/null +++ b/TFT_Drivers/R61581_Init.h @@ -0,0 +1,80 @@ + +// This is the command sequence that initialises the R61581 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure R61581 display + + writecommand(TFT_SLPOUT); + delay(20); + + writecommand(0xB0); + writedata(0x00); + + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x18); + + writecommand(0xD1); + writedata(0x00); + writedata(0x07); + writedata(0x10); + + writecommand(0xD2); + writedata(0x01); + writedata(0x02); + + writecommand(0xC0); + writedata(0x12); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x11); + + writecommand(0xC5); + writedata(0x03); + + writecommand(0xC8); + writedata(0x00); + writedata(0x32); + writedata(0x36); + writedata(0x45); + writedata(0x06); + writedata(0x16); + writedata(0x37); + writedata(0x75); + writedata(0x77); + writedata(0x54); + writedata(0x0C); + writedata(0x00); + + writecommand(TFT_MADCTL); + writedata(0x0A); + + writecommand(0x3A); + writedata(0x55); + + writecommand(TFT_CASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(TFT_PASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDF); + + delay(120); + writecommand(TFT_DISPON); + + delay(25); +// End of R61581 display configuration + + + diff --git a/TFT_Drivers/R61581_Rotation.h b/TFT_Drivers/R61581_Rotation.h new file mode 100644 index 0000000..4d7dc61 --- /dev/null +++ b/TFT_Drivers/R61581_Rotation.h @@ -0,0 +1,27 @@ + // This is the command sequence that rotates the R61581 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_BGR | TFT_MAD_MX); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_BGR); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_BGR | TFT_MAD_GS); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MV | TFT_MAD_BGR | TFT_MAD_MX | TFT_MAD_GS); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } + \ No newline at end of file diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 92873da..0b9fc21 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -361,6 +361,9 @@ void TFT_eSPI::init(uint8_t tc) #elif defined (ST7789_DRIVER) #include "TFT_Drivers/ST7789_Init.h" +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Init.h" + #endif spi_end(); @@ -409,6 +412,9 @@ void TFT_eSPI::setRotation(uint8_t m) #elif defined (ST7789_DRIVER) #include "TFT_Drivers/ST7789_Rotation.h" +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Rotation.h" + #endif delayMicroseconds(10); diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 8f31f29..1dcb28c 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -330,7 +330,7 @@ SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - // Write 16 bits (used for ESP32_PARALLEL or ILI9488_DRIVER) + // Write 16 bits #define tft_Write_16S(C) \ WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ diff --git a/User_Setup.h b/User_Setup.h index 49107c0..5c48d70 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -25,6 +25,7 @@ //#define ILI9486_DRIVER //#define ILI9488_DRIVER //#define ST7789_DRIVER // Define the screen size below for this display +//#define R61581_DRIVER // Some displays support SPI reads via the MISO pin, if the display has a single // bi-directional SDA pin the library will try to use bit banging to read the line diff --git a/User_Setup_Select.h b/User_Setup_Select.h index bd31358..69d27a0 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -25,13 +25,14 @@ //#include // Setup file configured for my ST7735 //#include // Setup file configured for my ILI9163 //#include // Setup file configured for my S6D02A1 -//#include // Setup file configured for my stock RPi TFT -//#include // Setup file configured for my modified RPi TFT -//#include // Setup file configured for my ST7735 128x128 display -//#include // Setup file configured for my ILI9163 128x128 display -//#include // Setup file configured for my ST7735 -//#include // Setup file configured for ESP8266 and RPi TFT with touch -//#include // Setup file configured for ESP32 and RPi TFT with touch +//#include // Setup file configured for my stock RPi TFT +//#include // Setup file configured for my modified RPi TFT +//#include // Setup file configured for my ST7735 128x128 display +//#include // Setup file configured for my ILI9163 128x128 display +//#include // Setup file configured for my ST7735 +//#include // Setup file configured for ESP8266 and RPi TFT with touch + +//#include // Setup file configured for ESP32 and RPi TFT with touch //#include // Setup file for the ESP32 based M5Stack //#include // Setup file for the ESP32 with parallel bus TFT //#include // Setup file for the ESP32 with parallel bus TFT @@ -102,6 +103,9 @@ #elif defined (ST7789_DRIVER) #include "TFT_Drivers/ST7789_Defines.h" #define TFT_DRIVER 0x7789 +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Defines.h" + #define TFT_DRIVER 0x6158 #elif defined (XYZZY_DRIVER) // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE #include "TFT_Drivers/XYZZY_Defines.h" #define TFT_DRIVER 0x0000 diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 3052b69..11cf2ab 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -25,6 +25,7 @@ //#define ILI9486_DRIVER //#define ILI9488_DRIVER //#define ST7789_DRIVER // Define the screen size below for this display +//#define R61581_DRIVER // Some displays support SPI reads via the MISO pin, if the display has a single // bi-directional SDA pin the library will try to use bit banging to read the line diff --git a/library.json b/library.json index 94d5340..83de892 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.4", + "version": "1.3.5", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index b8b5f01..9f33bfb 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.4 +version=1.3.5 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 467d1dc3c51f4ede6ac2cdf82a2c493d5eb6c243 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 26 Nov 2018 19:50:52 +0000 Subject: [PATCH 48/94] Fix issue #260 --- TFT_eSPI.h | 2 +- library.json | 2 +- library.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 1dcb28c..78c1816 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -228,7 +228,7 @@ #define SPI_32(H,L) ( (H)<<16 | (L) ) #define COL_32(H,L) ( (H)<<16 | (L) ) #else - #ifdef ESP32_PARALLEL + #ifdef ESP32_PARALLEL || defined (ILI9488_DRIVER) #define SPI_32(H,L) ( (H)<<16 | (L) ) #else #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) diff --git a/library.json b/library.json index 83de892..6eaff8a 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.5", + "version": "1.3.6", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 9f33bfb..b3ab068 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.5 +version=1.3.6 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From ff691f82030b77a6f322d0af3c5c74671e641ece Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 26 Nov 2018 21:39:42 +0000 Subject: [PATCH 49/94] Add News --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index bb3dadb..523f307 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,12 @@ + +# News + +1. androdlang has published a really nice companion library to extend the graphics capabilities of TFT_eSPI, you can find this here: +https://github.com/androdlang/TFTShape + +2. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: +https://github.com/Bodmer/TFT_eFX + # TFT_eSPI An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D and ST7789 based TFT displays that support SPI. The library can be loaded using the Arduino IDE's Library Manager. From 47e5a15604809e5bd6d25adffad4d0c136e2319c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 27 Nov 2018 21:18:01 +0000 Subject: [PATCH 50/94] Add news --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 523f307..220212e 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ https://github.com/androdlang/TFTShape 2. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: https://github.com/Bodmer/TFT_eFX +3. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. This is enabled with a #define TFT_SDA_READ in the setup file. + +4. ST7789V displays are manufactured in two variants that have the red and green pixels swapped, this is catered for by a new option in the setup file: + //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue + //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + # TFT_eSPI An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D and ST7789 based TFT displays that support SPI. The library can be loaded using the Arduino IDE's Library Manager. From 5d496ca7ee493afa100d70edf6e3b3eec5c36efb Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 27 Nov 2018 21:19:40 +0000 Subject: [PATCH 51/94] State SDA read constraint is only for ESP32 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 220212e..2d557b2 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ https://github.com/androdlang/TFTShape 2. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: https://github.com/Bodmer/TFT_eFX -3. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. This is enabled with a #define TFT_SDA_READ in the setup file. +3. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. At the moment this **ONLY** works with an ESP32. It is enabled with a #define TFT_SDA_READ in the setup file. 4. ST7789V displays are manufactured in two variants that have the red and green pixels swapped, this is catered for by a new option in the setup file: //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue From d23f0b00c0efcafcfe9d919a6995012b89a0ea94 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 01:02:15 +0000 Subject: [PATCH 52/94] Correct typo causing error message --- TFT_eSPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 78c1816..26169f9 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -228,7 +228,7 @@ #define SPI_32(H,L) ( (H)<<16 | (L) ) #define COL_32(H,L) ( (H)<<16 | (L) ) #else - #ifdef ESP32_PARALLEL || defined (ILI9488_DRIVER) + #if defined (ESP32_PARALLEL) || defined (ILI9488_DRIVER) #define SPI_32(H,L) ( (H)<<16 | (L) ) #else #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) From 436476e9bd24e2dc75fe6a747317afc226e23217 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 01:02:54 +0000 Subject: [PATCH 53/94] Update --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index b3ab068..6585c47 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.6 +version=1.3.7 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From fa808ed8110f543196768f0fad3f0a18d736f80f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 01:03:16 +0000 Subject: [PATCH 54/94] Update --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index 6eaff8a..cee476f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.6", + "version": "1.3.7", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": From e0aa312dfa65ba65d7869c573366575beb252f5e Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 22:23:45 +0000 Subject: [PATCH 55/94] Slow down the RPi strobes but keep fast for other displays --- TFT_eSPI.h | 58 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 26169f9..68bec74 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -132,16 +132,26 @@ #else #if TFT_DC >= 32 - #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); //\ - //GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); //\ - //GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower DC change + #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #else + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #endif #else #if TFT_DC >= 0 - #define DC_C GPIO.out_w1tc = (1 << TFT_DC); //\ - //GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC); //\ - //GPIO.out_w1ts = (1 << TFT_DC) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower DC change + #define DC_C GPIO.out_w1ts = (1 << TFT_DC); \ + GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) + #else + #define DC_C GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC) + #endif #else #define DC_C #define DC_D @@ -171,14 +181,24 @@ #define CS_H #else #if TFT_CS >= 32 - #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); //\ - //GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); //\ - //GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CS change + #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #else + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #endif #else #if TFT_CS >= 0 - #define CS_L GPIO.out_w1tc = (1 << TFT_CS); //GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS); //GPIO.out_w1ts = (1 << TFT_CS) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CS change + #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) + #else + #define CS_L GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS) + #endif #else #define CS_L #define CS_H @@ -194,8 +214,12 @@ // Use single register write for CS_L and DC_C if pins are both in range 0-31 #ifdef ESP32 #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) - #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); //\ - //GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CD and DC change + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); \ + GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #else + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #endif #else #define CS_L_DC_C CS_L; DC_C #endif @@ -261,7 +285,7 @@ #define tft_Write_16(C) WR_L;GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H #else #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 8)); WR_H; \ - GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H #endif // 16 bit write with swapped bytes From 057fceb7147546f1755c88d41161d6b9950d0342 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 22:31:47 +0000 Subject: [PATCH 56/94] Raise version --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 6585c47..664863a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.7 +version=1.3.8 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From b3d16984b099d2099e795b335641f99f59bd6a43 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 28 Nov 2018 22:32:14 +0000 Subject: [PATCH 57/94] Raise version --- library.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.json b/library.json index cee476f..af139eb 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.7", + "version": "1.3.8", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": From 1a5e34b6bbe08d0e63bc0ae3bc09552ba953913b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 29 Nov 2018 20:29:20 +0000 Subject: [PATCH 58/94] Correct typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d557b2..dad0286 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ https://github.com/Bodmer/TFT_eFX 3. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. At the moment this **ONLY** works with an ESP32. It is enabled with a #define TFT_SDA_READ in the setup file. -4. ST7789V displays are manufactured in two variants that have the red and green pixels swapped, this is catered for by a new option in the setup file: +4. ST7789V displays are manufactured in two variants that have the red and blue pixels swapped, this is catered for by a new option in the setup file: //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red From 41dea61bfdf78233ef024c122c662b053b6c6d56 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 30 Nov 2018 23:27:10 +0000 Subject: [PATCH 59/94] Correct #263, add setup file for 160x80 TFT, add invert option Fixed bug where wrong wodth was returned for 1bpp Sprite Improved speed for copying a 1bpp Sprite into another 1bpp Sprite ( affects Sprite pushImage() function only) Added option to setup for colour inversion --- Extensions/Sprite.cpp | 15 ++- TFT_eSPI.cpp | 8 ++ User_Setup.h | 5 + User_Setups/Setup43_ST7735.h | 228 +++++++++++++++++++++++++++++++++++ library.json | 2 +- library.properties | 2 +- 6 files changed, 250 insertions(+), 10 deletions(-) create mode 100644 User_Setups/Setup43_ST7735.h diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index aef6010..322cbeb 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -340,17 +340,16 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 y = _dheight - tx - 1; } - uint8_t* pdata = (uint8_t*) data; + uint8_t* pdata = (uint8_t* ) data; uint32_t ww = (w+7) & 0xFFF8; for (int32_t yp = 0; yp>3; + uint32_t yyp = y + yp; + for (int32_t xp = 0; xp>3) + yw] & (0x80 >> (xp & 0x7)) ); + drawPixel(x+xp, yyp, readPixel); } } } @@ -732,7 +731,7 @@ int16_t TFT_eSprite::width(void) if (_rotation == 1 || _rotation == 3) return _dheight; - return _bitwidth; + return _dwidth; } diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 0b9fc21..4f47950 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -366,6 +366,14 @@ void TFT_eSPI::init(uint8_t tc) #endif +#ifdef TFT_INVERSION_ON + writecommand(TFT_INVON); +#endif + +#ifdef TFT_INVERSION_OFF + writecommand(TFT_INVOFF); +#endif + spi_end(); setRotation(rotation); diff --git a/User_Setup.h b/User_Setup.h index 5c48d70..b27e1a7 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -65,6 +65,11 @@ // #define ST7735_BLACKTAB // #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + // ################################################################################## // // Section 1. Define the pins that are used to interface with the display here diff --git a/User_Setups/Setup43_ST7735.h b/User_Setups/Setup43_ST7735.h new file mode 100644 index 0000000..efe20f3 --- /dev/null +++ b/User_Setups/Setup43_ST7735.h @@ -0,0 +1,228 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER +#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +#define TFT_WIDTH 80 +//#define TFT_WIDTH 128 +#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +#define ST7735_GREENTAB160x80 +//#define ST7735_REDTAB160x80 + +// If colours are inverted (white shows as black) then uncomment one of these +// Try both options, one of the options should correct the inversion. +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +//#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 15 // Chip select control pin +#define TFT_DC 2 // Data Command control pin +#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 +// #define SPI_FREQUENCY 20000000 + #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +// #define SUPPORT_TRANSACTIONS diff --git a/library.json b/library.json index af139eb..6684cb1 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.8", + "version": "1.3.9", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 664863a..c3dbd0f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.8 +version=1.3.9 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 2a02c81c692e015534ca3579b31b25418431e759 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 3 Dec 2018 21:09:54 +0000 Subject: [PATCH 60/94] Fix #267 --- TFT_eSPI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 4f47950..6daac3a 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4803,7 +4803,7 @@ void writeBlock(uint16_t color, uint32_t repeat) #elif defined (ILI9488_DRIVER) #ifdef ESP8266 -void TFT_eSPI::writeBlock(uint16_t color, uint32_t repeat) +void writeBlock(uint16_t color, uint32_t repeat) { uint32_t mask = ~(SPIMMOSI << SPILMOSI); From 71a222f704768f450c07c5a9251d64b300c0c22f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 26 Dec 2018 16:46:54 +0000 Subject: [PATCH 61/94] Fix #276 Fixes warning/error that is only reported with certain compiler warning flag settings ("All" in Arduino IDE). --- TFT_eSPI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 6daac3a..2513076 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -1251,7 +1251,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * //else drawPixel((dw-len)+xp,h-dh,bitmap_bg); xp++; } - *ptr++; + ptr++; len -= 8; } @@ -1400,7 +1400,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * px++; xp++; } - *ptr++; + ptr++; len -= 8; } if (np) pushColor(bitmap_fg, np); From e8c201db5e7be8bf7c14cdc90c20151e6ae1f268 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 1 Jan 2019 23:56:08 +0000 Subject: [PATCH 62/94] Update touch handler Added new function that sketch can call to convert raw ADC x and y values to calibrated screen coordinates: tft.convertRawXY(&x, &y); Redunced required number of SPI transfers needed to read raw values. Changed mode so PENIRQ pin is enabled so users sketch can read this signal (if needed). See issue #279. --- Extensions/Touch.cpp | 65 ++++++++++++++++++++++++-------------------- Extensions/Touch.h | 19 +++++++++---- library.json | 2 +- library.properties | 2 +- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 1b0192d..ab76771 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -22,24 +22,18 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ T_CS_L; - // Dummy transfer - SPI.transfer(0xd0); - SPI.transfer(0); - SPI.transfer(0); - - // Start bit + YP sample request for x position - SPI.transfer(0xd0); - tmp = SPI.transfer(0); + // Start YP sample request for x position + SPI.transfer(0xd0); // Start new YP conversion + tmp = SPI.transfer(0); // Read first 8 bits tmp = tmp <<5; - tmp |= 0x1f & (SPI.transfer(0)>>3); + tmp |= 0x1f & (SPI.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion *x = tmp; - // Start bit + XP sample request for y position - SPI.transfer(0x90); - tmp = SPI.transfer(0); + // Start XP sample request for y position + tmp = SPI.transfer(0); // Read first 8 bits tmp = tmp <<5; - tmp |= 0x1f & (SPI.transfer(0)>>3); + tmp |= 0x1f & (SPI.transfer(0)>>3); // Read last 8 bits *y = tmp; @@ -61,12 +55,12 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ T_CS_L; - // Z sample request + // Calculate Z int16_t tz = 0xFFF; - SPI.transfer(0xb1); - tz += SPI.transfer16(0xc1) >> 3; - tz -= SPI.transfer16(0x91) >> 3; - + SPI.transfer(0xb0); // Start new Z1 conversion + tz += SPI.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion + tz -= SPI.transfer16(0x00) >> 3; // Read Z2 + T_CS_H; spi_end_touch(); @@ -78,11 +72,11 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ ** Function name: validTouch ** Description: read validated position. Return false if not pressed. ***************************************************************************************/ -#define _RAWERR 10 // Deadband in position samples +#define _RAWERR 10 // Deadband error allowed in successive position samples uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ uint16_t x_tmp, y_tmp, x_tmp2, y_tmp2; - // Wait until pressure stops increasing + // Wait until pressure stops increasing to debounce pressure uint16_t z1 = 1; uint16_t z2 = 0; while (z1 > z2) @@ -125,7 +119,7 @@ uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ ***************************************************************************************/ #define Z_THRESHOLD 350 // Touch pressure threshold for validating touches uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ - uint16_t x_tmp, y_tmp, xx, yy; + uint16_t x_tmp, y_tmp; if (threshold<20) threshold = 20; if (_pressTime > millis()) threshold=20; @@ -141,6 +135,25 @@ uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ _pressTime = millis() + 50; + convertRawXY(&x_tmp, &y_tmp); + + if (x_tmp >= _width || y_tmp >= _height) return valid; + + _pressX = x_tmp; + _pressY = y_tmp; + *x = _pressX; + *y = _pressY; + return valid; +} + +/*************************************************************************************** +** Function name: convertRawXY +** Description: convert raw touch x,y values to screen coordinates +***************************************************************************************/ +void TFT_eSPI::convertRawXY(uint16_t *x, uint16_t *y) +{ + uint16_t x_tmp = *x, y_tmp = *y, xx, yy; + if(!touchCalibration_rotate){ xx=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1; yy=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1; @@ -156,14 +169,8 @@ uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ if(touchCalibration_invert_y) yy = _height - yy; } - - if (xx >= _width || yy >= _height) return valid; - - _pressX = xx; - _pressY = yy; - *x = _pressX; - *y = _pressY; - return valid; + *x = xx; + *y = yy; } /*************************************************************************************** diff --git a/Extensions/Touch.h b/Extensions/Touch.h index 7f3b22a..de4ade7 100644 --- a/Extensions/Touch.h +++ b/Extensions/Touch.h @@ -2,23 +2,32 @@ // This is part of the TFT_eSPI class and is associated with the Touch Screen handlers public: - + // Get raw x,y ADC values from touch controller uint8_t getTouchRaw(uint16_t *x, uint16_t *y); + // Get raw z (i.e. pressure) ADC value from touch controller uint16_t getTouchRawZ(void); + // Convert raw x,y values to calibrated and correctly rotated screen coordinates + void convertRawXY(uint16_t *x, uint16_t *y); + // Get the screen touch coordinates, returns true if screen has been touched + // if the touch cordinates are off screen then x and y are not updated uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + // Run screen calibration and test, report calibration values to the serial port void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size); + // Set the screen calibration values void setTouch(uint16_t *data); private: - + // Handlers for the SPI settings and clock speed change inline void spi_begin_touch() __attribute__((always_inline)); inline void spi_end_touch() __attribute__((always_inline)); - // These are associated with the Touch Screen handlers + // Private function to validate a touch, allow settle time and reduce spurious coordinates uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + // Initialise with example calibration values so processor does not crash if setTouch() not called in setup() uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600; uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0; - uint32_t _pressTime; - uint16_t _pressX, _pressY; + + uint32_t _pressTime; // Press and hold time-out + uint16_t _pressX, _pressY; // For future use (last sampled calibrated coordinates) diff --git a/library.json b/library.json index 6684cb1..5d937f3 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.9", + "version": "1.3.10", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index c3dbd0f..8517311 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.9 +version=1.3.10 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 96228cbf449b1a6c63cd6c8cbb7974afc31f95d7 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 6 Jan 2019 01:14:10 +0000 Subject: [PATCH 63/94] Add Sprite rotation and examples Sprites can be rendered rotated with defined pivot points, 3 new examples have been added "Rotated_Sprite_1/2/3". The FLASH bitmap example has been moved to the Generic examples folder. Boundary checks have been added to pushImage() A new scrolling and wrapping in a Sprite example has been added. --- Extensions/Sprite.cpp | 398 +++++++++++++++--- Extensions/Sprite.h | 29 +- README.md | 13 +- TFT_eSPI.cpp | 49 ++- TFT_eSPI.h | 22 +- User_Setups/SetupX_Template.h | 5 + examples/160 x 128/Flash_Bitmap2/Alert.h | 42 -- examples/160 x 128/Flash_Bitmap2/Close.h | 41 -- .../160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino | 110 ----- examples/160 x 128/Flash_Bitmap2/Info.h | 41 -- .../TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino | 106 ----- examples/480 x 320/Flash_Bitmap/Alert.h | 42 -- examples/480 x 320/Flash_Bitmap/Close.h | 41 -- .../480 x 320/Flash_Bitmap/Flash_Bitmap.ino | 113 ----- examples/480 x 320/Flash_Bitmap/Info.h | 41 -- .../TFT_Flash_Bitmap/Alert.h | 1 - .../TFT_Flash_Bitmap/Close.h | 0 .../TFT_Flash_Bitmap/Info.h | 0 .../TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino | 72 ++++ .../One_bit_Sprite_Demo.ino} | 0 .../One_bit_Yin_Yang.ino} | 0 .../Rotated_Sprite_1/Rotated_Sprite_1.ino | 182 ++++++++ .../Rotated_Sprite_2/Rotated_Sprite_2.ino | 181 ++++++++ .../Rotated_Sprite_3/Rotated_Sprite_3.ino | 140 ++++++ .../Sprite/Rotated_Sprite_3/data/EagleEye.jpg | Bin 0 -> 20838 bytes .../Rotated_Sprite_3/data/Eye_80x64.jpg | Bin 0 -> 9978 bytes .../Sprite_scroll_wrap_1bit.ino | 139 ++++++ keywords.txt | 8 +- library.json | 2 +- library.properties | 2 +- 30 files changed, 1164 insertions(+), 656 deletions(-) delete mode 100644 examples/160 x 128/Flash_Bitmap2/Alert.h delete mode 100644 examples/160 x 128/Flash_Bitmap2/Close.h delete mode 100644 examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino delete mode 100644 examples/160 x 128/Flash_Bitmap2/Info.h delete mode 100644 examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino delete mode 100644 examples/480 x 320/Flash_Bitmap/Alert.h delete mode 100644 examples/480 x 320/Flash_Bitmap/Close.h delete mode 100644 examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino delete mode 100644 examples/480 x 320/Flash_Bitmap/Info.h rename examples/{320 x 240 => Generic}/TFT_Flash_Bitmap/Alert.h (99%) rename examples/{320 x 240 => Generic}/TFT_Flash_Bitmap/Close.h (100%) rename examples/{320 x 240 => Generic}/TFT_Flash_Bitmap/Info.h (100%) create mode 100644 examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino rename examples/Sprite/{1_bit_Sprite_Demo/1_bit_Sprite_Demo.ino => One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino} (100%) rename examples/Sprite/{1_bit_Yin_Yang/1_bit_Yin_Yang.ino => One_bit_Yin_Yang/One_bit_Yin_Yang.ino} (100%) create mode 100644 examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino create mode 100644 examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino create mode 100644 examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino create mode 100644 examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg create mode 100644 examples/Sprite/Rotated_Sprite_3/data/Eye_80x64.jpg create mode 100644 examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 322cbeb..e74864b 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -33,6 +33,9 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) _xptr = 0; // pushColor coordinate _yptr = 0; + _xpivot = 0; + _ypivot = 0; + this->cursor_y = this->cursor_x = 0; // Text cursor position } @@ -62,43 +65,61 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) _sh = h; _scolor = TFT_BLACK; + _xpivot = w/2; + _ypivot = h/2; + + _img8 = (uint8_t*) callocSprite(w, h, frames); + _img8_1 = _img8; + _img8_2 = _img8; + _img = (uint16_t*) _img8; + + // This is to make it clear what pointer size is expected to be used + // but casting in the user sketch is needed due to the use of void* + if (_bpp == 1) + { + w = (w+7) & 0xFFF8; + _img8_2 = _img8 + ( (w>>3) * h + 1 ); + } + + if (_img8) + { + _created = true; + return _img8; + } + + return NULL; +} + + +/*************************************************************************************** +** Function name: callocSprite +** Description: Allocate a memory area for the Sprite and return pointer +*************************************************************************************x*/ + +void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) +{ // Add one extra "off screen" pixel to point out-of-bounds setWindow() coordinates // this means push/writeColor functions do not need additional bounds checks and // hence will run faster in normal circumstances. + uint8_t* ptr8 = NULL; + if (_bpp == 16) { #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) _img8_1 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint16_t)); + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint16_t)); else #endif - _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); - - _img8_2 = _img8_1; - _img = (uint16_t*) _img8_1; - - if (_img) - { - _created = true; - return _img; - } + ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); } else if (_bpp == 8) { #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) _img8_1 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); else #endif - _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); - - if (_img8_1) - { - _img8 = _img8_1; - _img8_2 = _img8_1; - _created = true; - return _img8; - } + ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); } else // Must be 1 bpp @@ -114,21 +135,13 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) if (frames > 2) frames = 2; // Currently restricted to 2 frame buffers if (frames < 1) frames = 1; #if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) - if ( psramFound() ) _img8 = ( uint8_t*) ps_calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); else #endif - _img8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); - - if (_img8) - { - _created = true; - _img8_1 = _img8; - _img8_2 = _img8 + ( (w>>3) * h + 1 ); - return _img8_1; - } + ptr8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); } - - return NULL; + + return ptr8; } /*************************************************************************************** @@ -151,8 +164,8 @@ void* TFT_eSprite::frameBuffer(int8_t f) } /*************************************************************************************** -** Function name: setDepth -** Description: Set bits per pixel for colour (8 or 16) +** Function name: setColorDepth +** Description: Set bits per pixel for colour (1, 8 or 16) *************************************************************************************x*/ void* TFT_eSprite::setColorDepth(int8_t b) @@ -175,6 +188,19 @@ void* TFT_eSprite::setColorDepth(int8_t b) return NULL; } + +/*************************************************************************************** +** Function name: getColorDepth +** Description: Get bits per pixel for colour (1, 8 or 16) +*************************************************************************************x*/ + +int8_t TFT_eSprite::getColorDepth(void) +{ + if (_created) return _bpp; + else return 0; +} + + /*************************************************************************************** ** Function name: setBitmapColor ** Description: Set the foreground foreground and background colour @@ -201,6 +227,232 @@ void TFT_eSprite::deleteSprite(void) } +/*************************************************************************************** +** Function name: setPivot +** Description: Set the pivot point in this Sprite +*************************************************************************************x*/ +void TFT_eSprite::setPivot(int16_t x, int16_t y) +{ + _xpivot = x; + _ypivot = y; +} + + +/*************************************************************************************** +** Function name: getPivotX +** Description: Get the x pivot position +***************************************************************************************/ +int16_t TFT_eSprite::getPivotX(void) +{ + return _xpivot; +} + + +/*************************************************************************************** +** Function name: getPivotY +** Description: Get the y pivot position +***************************************************************************************/ +int16_t TFT_eSprite::getPivotY(void) +{ + return _ypivot; +} + + +/*************************************************************************************** +** Function name: pushRotated +** Description: Push a rotated copy of the Sprite to TFT screen +*************************************************************************************x*/ +bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) +{ + if ( !_created ) return false; + + // Trig values for the rotation + float radAngle = -angle * 0.0174532925; // Convert degrees to radians + float sinra = sin(radAngle); + float cosra = cos(radAngle); + + // Bounding box parameters + int16_t min_x; + int16_t min_y; + int16_t max_x; + int16_t max_y; + + // Get the bounding box of this rotated source Sprite relative to Sprite pivot + getRotatedBounds(sinra, cosra, width(), height(), _xpivot, _ypivot, &min_x, &min_y, &max_x, &max_y); + + // Move bounding box so source Sprite pivot coincides with TFT pivot + min_x += _tft->_xpivot; + max_x += _tft->_xpivot; + min_y += _tft->_ypivot; + max_y += _tft->_ypivot; + + // Test only to show bounding box on TFT + // _tft->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); + + // Return if bounding box is outside of TFT area + if (min_x > _tft->width()) return true; + if (min_y > _tft->height()) return true; + if (max_x < 0) return true; + if (max_y < 0) return true; + + // Clip bounding box to be within TFT area + if (min_x < 0) min_x = 0; + if (min_y < 0) min_y = 0; + if (max_x > _tft->width()) max_x = _tft->width(); + if (max_y > _tft->height()) max_y = _tft->height(); + + + // Scan destination bounding box and fetch transformed pixels from source Sprite + for (int32_t x = min_x; x <= max_x; x++) { + int32_t xt = x - _tft->_xpivot; + float cxt = cosra * xt + _xpivot; + float sxt = sinra * xt + _ypivot; + bool column_drawn = false; + for (int32_t y = min_y; y <= max_y; y++) { + int32_t yt = y - _tft->_ypivot; + int32_t xs = (int32_t)round(cxt - sinra * yt); + // Do not calculate ys unless xs is in bounds + if (xs >= 0 && xs < width()) + { + int32_t ys = (int32_t)round(sxt + cosra * yt); + // Check if ys is in bounds + if (ys >= 0 && ys < height()) { + int32_t rp = readPixel(xs, ys); + if (rp != transp) _tft->drawPixel(x, y, rp); + column_drawn = true; + } + } + else if (column_drawn) y = max_y; // Skip remaining column pixels + } + } + + return true; +} + + +/*************************************************************************************** +** Function name: pushRotated +** Description: Push a rotated copy of the Sprite to another Sprite +*************************************************************************************x*/ +bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) +{ + if ( !_created ) return false; // Check this Sprite is created + if ( !spr->_created ) return false; // Ckeck destination Sprite is created + + // Trig values for the rotation + float radAngle = -angle * 0.0174532925; // Convert degrees to radians + float sinra = sin(radAngle); + float cosra = cos(radAngle); + + // Bounding box parameters + int16_t min_x; + int16_t min_y; + int16_t max_x; + int16_t max_y; + + // Get the bounding box of this rotated source Sprite + getRotatedBounds(sinra, cosra, width(), height(), _xpivot, _ypivot, &min_x, &min_y, &max_x, &max_y); + + // Move bounding box so source Sprite pivot coincides with destination Sprite pivot + min_x += spr->_xpivot; + max_x += spr->_xpivot; + min_y += spr->_ypivot; + max_y += spr->_ypivot; + + // Test only to show bounding box + // spr->fillSprite(TFT_BLACK); + // spr->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); + + // Return if bounding box is completely outside of destination Sprite + if (min_x > spr->width()) return true; + if (min_y > spr->height()) return true; + if (max_x < 0) return true; + if (max_y < 0) return true; + + // Clip bounding box if it is partially within destination Sprite + if (min_x < 0) min_x = 0; + if (min_y < 0) min_y = 0; + if (max_x > spr->width()) max_x = spr->width(); + if (max_y > spr->height()) max_y = spr->height(); + + // Scan destination bounding box and fetch transformed pixels from source Sprite + for (int32_t x = min_x; x <= max_x; x++) + { + int32_t xt = x - spr->_xpivot; + float cxt = cosra * xt + _xpivot; + float sxt = sinra * xt + _ypivot; + bool column_drawn = false; + for (int32_t y = min_y; y <= max_y; y++) + { + int32_t yt = y - spr->_ypivot; + int32_t xs = (int32_t)round(cxt - sinra * yt); + // Do not calculate ys unless xs is in bounds + if (xs >= 0 && xs < width()) + { + int32_t ys = (int32_t)round(sxt + cosra * yt); + // Check if ys is in bounds + if (ys >= 0 && ys < height()) + { + int32_t rp = readPixel(xs, ys); + if (rp != transp) spr->drawPixel(x, y, rp); + column_drawn = true; + } + } + else if (column_drawn) y = max_y; // Skip the remaining pixels below the Sprite + } + } + + return true; +} + + +/*************************************************************************************** +** Function name: rotatedBounds +** Description: Get bounding box of a rotated Sprite wrt pivot +*************************************************************************************x*/ +void TFT_eSprite::getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y) +{ + w -= xp; // w is now right edge coordinate relative to xp + h -= yp; // h is now bottom edge coordinate relative to yp + + // Calculate new corner coordinates + int16_t x0 = -xp * cosa - yp * sina; + int16_t y0 = xp * sina - yp * cosa; + + int16_t x1 = w * cosa - yp * sina; + int16_t y1 = -w * sina - yp * cosa; + + int16_t x2 = h * sina + w * cosa; + int16_t y2 = h * cosa - w * sina; + + int16_t x3 = h * sina - xp * cosa; + int16_t y3 = h * cosa + xp * sina; + + // Find bounding box extremes, enlarge box to accomodate rounding errors + *min_x = x0-2; + if (x1 < *min_x) *min_x = x1-2; + if (x2 < *min_x) *min_x = x2-2; + if (x3 < *min_x) *min_x = x3-2; + + *max_x = x0+2; + if (x1 > *max_x) *max_x = x1+2; + if (x2 > *max_x) *max_x = x2+2; + if (x3 > *max_x) *max_x = x3+2; + + *min_y = y0-2; + if (y1 < *min_y) *min_y = y1-2; + if (y2 < *min_y) *min_y = y2-2; + if (y3 < *min_y) *min_y = y3-2; + + *max_y = y0+2; + if (y1 > *max_y) *max_y = y1+2; + if (y2 > *max_y) *max_y = y2+2; + if (y3 > *max_y) *max_y = y3+2; + +} + + /*************************************************************************************** ** Function name: pushSprite ** Description: Push the sprite to the TFT at x, y @@ -289,33 +541,53 @@ uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) ** Function name: pushImage ** Description: push 565 colour image into a defined area of a sprite *************************************************************************************x*/ -// TODO Need to add more area boundary checks void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) { if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; + + int32_t xo = 0; + int32_t yo = 0; + + int32_t xs = x; + int32_t ys = y; + + uint32_t ws = w; + uint32_t hs = h; + + if (x < 0) { xo = -x; xs = 0; } + if (y < 0) { yo = -y; ys = 0; } + + if (xs + w >= _iwidth) ws = _iwidth - xs; + if (ys + h >= _iheight) hs = _iheight - ys; if (_bpp == 16) { - for (uint32_t yp = y; yp < y + h; yp++) + for (uint32_t yp = yo; yp < yo + hs; yp++) { - for (uint32_t xp = x; xp < x + w; xp++) + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { - uint16_t color = *data++; + uint16_t color = data[xp + yp * w]; if(!_iswapBytes) color = color<<8 | color>>8; - _img[xp + yp * _iwidth] = color; + _img[x + ys * _iwidth] = color; + x++; } + ys++; } } else if (_bpp == 8) { - for (uint32_t yp = y; yp < y + h; yp++) + for (uint32_t yp = yo; yp < yo + hs; yp++) { - for (uint32_t xp = x; xp < x + w; xp++) + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { - uint16_t color = *data++; + uint16_t color = data[xp + yp * w]; if(_iswapBytes) color = color<<8 | color>>8; - _img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); } + ys++; } } @@ -360,34 +632,54 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 ** Function name: pushImage ** Description: push 565 colour FLASH (PROGMEM) image into a defined area *************************************************************************************x*/ -// TODO Need to add more area boundary checks void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) { if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; + + int32_t xo = 0; + int32_t yo = 0; + + int32_t xs = x; + int32_t ys = y; + + uint32_t ws = w; + uint32_t hs = h; + + if (x < 0) { xo = -x; xs = 0; } + if (y < 0) { yo = -y; ys = 0; } + + if (xs + w >= _iwidth) ws = _iwidth - xs; + if (ys + h >= _iheight) hs = _iheight - ys; if (_bpp == 16) { - for (uint32_t yp = y; yp < y + h; yp++) + for (uint32_t yp = yo; yp < yo + hs; yp++) { - for (uint32_t xp = x; xp < x + w; xp++) + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { - uint16_t color = pgm_read_word(data++); + uint16_t color = pgm_read_word(data + xp + yp * w); if(!_iswapBytes) color = color<<8 | color>>8; - _img[xp + yp * _iwidth] = color; + _img[x + ys * _iwidth] = color; + x++; } + ys++; } } else if (_bpp == 8) { - for (uint32_t yp = y; yp < y + h; yp++) + for (uint32_t yp = yo; yp < yo + hs; yp++) { - for (uint32_t xp = x; xp < x + w; xp++) + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) { - uint16_t color = pgm_read_word(data++); + uint16_t color = pgm_read_word(data + xp + yp * w); if(_iswapBytes) color = color<<8 | color>>8; - _img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); } + ys++; } } diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h index 1ea7645..57db847 100644 --- a/Extensions/Sprite.h +++ b/Extensions/Sprite.h @@ -22,9 +22,10 @@ class TFT_eSprite : public TFT_eSPI { // Select the frame buffer for graphics void* frameBuffer(int8_t f); - // Set the colour depth to 8 or 16 bits. Can be used to change depth an existing + // Set or get the colour depth to 8 or 16 bits. Can be used to change depth an existing // sprite, but clears it to black, returns a new pointer if sprite is re-created. void* setColorDepth(int8_t b); + int8_t getColorDepth(void); void setBitmapColor(uint16_t c, uint16_t b); @@ -34,7 +35,7 @@ class TFT_eSprite : public TFT_eSPI { fillSprite(uint32_t color), - // Define a window to push 16 bit colour pixels into is a raster order + // Define a window to push 16 bit colour pixels into in a raster order // Colours are converted to 8 bit if depth is set to 8 setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), pushColor(uint32_t color), @@ -59,9 +60,23 @@ class TFT_eSprite : public TFT_eSPI { // Set the sprite text cursor position for print class (does not change the TFT screen cursor) //setCursor(int16_t x, int16_t y); + // Set the rotation of the Sprite (for 1bpp Sprites only) void setRotation(uint8_t rotation); uint8_t getRotation(void); + // Push a rotated copy of Sprite to TFT with optional transparent colour + bool pushRotated(int16_t angle, int32_t transp = -1); + // Push a rotated copy of Sprite to another different Sprite with optional transparent colour + bool pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp = -1); + // Set and get the pivot point for this Sprite + void setPivot(int16_t x, int16_t y); + int16_t getPivotX(void), + getPivotY(void); + + // Get the bounding box for a rotated copy of this Sprite + void getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y); + // Read the colour of a pixel at x,y and return value in 565 format uint16_t readPixel(int32_t x0, int32_t y0); @@ -98,15 +113,21 @@ class TFT_eSprite : public TFT_eSPI { TFT_eSPI *_tft; + // Reserve memory for the Sprite and return a pointer + void* callocSprite(int16_t width, int16_t height, uint8_t frames = 1); + protected: - uint8_t _bpp; + uint8_t _bpp; // bits per pixel (1, 8 or 16) uint16_t *_img; // pointer to 16 bit sprite uint8_t *_img8; // pointer to 8 bit sprite uint8_t *_img8_1; // pointer to frame 1 uint8_t *_img8_2; // pointer to frame 2 - bool _created; // created and bits per pixel depth flags + int16_t _xpivot; // x pivot point coordinate + int16_t _ypivot; // y pivot point coordinate + + bool _created; // A Sprite has been created and memory reserved bool _gFont = false; // int32_t _icursor_x, _icursor_y; diff --git a/README.md b/README.md index dad0286..2befb58 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,20 @@ # News -1. androdlang has published a really nice companion library to extend the graphics capabilities of TFT_eSPI, you can find this here: +1. Sprites can now by pushed to the screen (or another Sprite) with a rotation angle. The new function is pushRotated(). Three new examples (Rotate_Sprite_1/2/3) have been added to show how the functions can be used to rotate text, images and to draw animated dials with moving needles. + +2. A new TFT_eFEX support library has been created which includes extra functions such as drawing a BMP or Jpeg to the screen. This library will simplify the examples. It will be expanded at a future date to include meters, dials and GUI elements like progress bars, graphs and animated buttons: +https://github.com/Bodmer/TFT_eFEX + +3. androdlang has published a really nice companion library to extend the graphics capabilities of TFT_eSPI, you can find this here: https://github.com/androdlang/TFTShape -2. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: +4. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: https://github.com/Bodmer/TFT_eFX -3. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. At the moment this **ONLY** works with an ESP32. It is enabled with a #define TFT_SDA_READ in the setup file. +5. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. At the moment this **ONLY** works with an ESP32. It is enabled with a #define TFT_SDA_READ in the setup file. -4. ST7789V displays are manufactured in two variants that have the red and blue pixels swapped, this is catered for by a new option in the setup file: +6. ST7789V displays are manufactured in two variants that have the red and blue pixels swapped, this is catered for by a new option in the setup file: //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 2513076..a20cee4 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -188,6 +188,9 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) addr_row = 0xFFFF; addr_col = 0xFFFF; + _xpivot = 0; + _ypivot = 0; + #ifdef LOAD_GLCD fontsloaded = 0x0002; // Bit 1 set #endif @@ -1062,7 +1065,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin for (int j = 0; j < 64; j++) { pix_buffer[j] = pgm_read_word(&data[i * 64 + j]); } - pushColors(pix_buffer, 64, !_swapBytes); + pushColors(pix_buffer, 64, _swapBytes); } // Work out number of pixels not yet sent @@ -1074,7 +1077,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin { pix_buffer[i] = pgm_read_word(&data[nb * 64 + i]); } - pushColors(pix_buffer, np, !_swapBytes); + pushColors(pix_buffer, np, _swapBytes); } CS_H; @@ -1115,7 +1118,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin uint16_t lineBuf[dw]; - if (_swapBytes) transp = transp >> 8 | transp << 8; + if (!_swapBytes) transp = transp >> 8 | transp << 8; while (dh--) { @@ -1140,14 +1143,14 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin move = true; if (np) { - pushColors(lineBuf, np, !_swapBytes); + pushColors(lineBuf, np, _swapBytes); np = 0; } } px++; ptr++; } - if (np) pushColors(lineBuf, np, !_swapBytes); + if (np) pushColors(lineBuf, np, _swapBytes); y++; data += w; @@ -2097,6 +2100,37 @@ void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) } +/*************************************************************************************** +** Function name: setPivot +** Description: Set the pivot point on the TFT +*************************************************************************************x*/ +void TFT_eSPI::setPivot(int16_t x, int16_t y) +{ + _xpivot = x; + _ypivot = y; +} + + +/*************************************************************************************** +** Function name: getPivotX +** Description: Get the x pivot position +***************************************************************************************/ +int16_t TFT_eSPI::getPivotX(void) +{ + return _xpivot; +} + + +/*************************************************************************************** +** Function name: getPivotY +** Description: Get the y pivot position +***************************************************************************************/ +int16_t TFT_eSPI::getPivotY(void) +{ + return _ypivot; +} + + /*************************************************************************************** ** Function name: setBitmapColor ** Description: Set the foreground foreground and background colour @@ -3272,7 +3306,7 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) void TFT_eSPI::startWrite(void) { spi_begin(); - + inTransaction = true; CS_L; } @@ -3282,9 +3316,8 @@ void TFT_eSPI::startWrite(void) ***************************************************************************************/ void TFT_eSPI::endWrite(void) { - CS_H; - + inTransaction = false; spi_end(); } diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 68bec74..48b9f48 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -213,12 +213,16 @@ // Use single register write for CS_L and DC_C if pins are both in range 0-31 #ifdef ESP32 - #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) - #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CD and DC change - #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); \ - GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #ifdef TFT_CS + #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CD and DC change + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); \ + GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #else + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #endif #else - #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #define CS_L_DC_C CS_L; DC_C #endif #else #define CS_L_DC_C CS_L; DC_C @@ -676,7 +680,7 @@ class TFT_eSPI : public Print { drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color), drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), setBitmapColor(uint16_t fgcolor, uint16_t bgcolor), // For 1bpp sprites - + setPivot(int16_t x, int16_t y), setCursor(int16_t x, int16_t y), setCursor(int16_t x, int16_t y, uint8_t font), setTextColor(uint16_t color), @@ -741,6 +745,9 @@ class TFT_eSPI : public Print { int16_t getCursorX(void), getCursorY(void); + int16_t getPivotX(void), + getPivotY(void); + uint16_t fontsLoaded(void), color565(uint8_t red, uint8_t green, uint8_t blue), // Convert 8 bit red, green and blue to 16 bits color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits @@ -798,6 +805,9 @@ class TFT_eSPI : public Print { textdatum, // Text reference datum rotation; // Display rotation (0-3) + int16_t _xpivot; // x pivot point coordinate + int16_t _ypivot; // x pivot point coordinate + private: inline void spi_begin() __attribute__((always_inline)); diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 11cf2ab..7d6ef8b 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -66,6 +66,11 @@ // #define ST7735_BLACKTAB // #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + // ################################################################################## // // Section 1. Define the pins that are used to interface with the display here diff --git a/examples/160 x 128/Flash_Bitmap2/Alert.h b/examples/160 x 128/Flash_Bitmap2/Alert.h deleted file mode 100644 index 54d013d..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Alert.h +++ /dev/null @@ -1,42 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t alertWidth = 32; -const uint16_t alertHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short alert[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1080,0xAC66,0xEDE8,0xFE69,0xC4C6,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xBCC6,0xFE68,0xFE68,0xFE6A,0xFE68,0xEDE8,0x18A1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8344,0xFE48,0xFE8C,0xFFDD,0xFFFF,0xFEF0,0xFE48,0xB466,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1880,0xEDC7,0xFE48,0xFF99,0xFFBC,0xFF9B,0xFFBD,0xFE6A,0xFE48,0x5A23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BE5,0xFE28,0xFED0,0xFFBC,0xFF7A,0xFF9A,0xFF9B,0xFF35,0xFE28,0xBCA6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3962,0xFE28,0xFE28,0xFF9A,0xFF79,0xFF9A,0xFF9B,0xFF9A,0xFFBD,0xFE6B,0xFE28,0x72E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xB465,0xFE28,0xFEF2,0xFF7A,0xFF79,0xFF7A,0xFF9A,0xFF7A,0xFF7A,0xFF78,0xFE28,0xDD67,0x0860,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5A22,0xFE07,0xFE29,0xFF9B,0xFF37,0xFF58,0xFF79,0xFF79,0xFF79,0xFF58,0xFF9B,0xFEAE,0xFE07,0x93A4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xC4A5,0xFE07,0xFF15,0xFF37,0xFF36,0xAD11,0x2965,0x2965,0xCDF4,0xFF37,0xFF37,0xFF79,0xFE07,0xFE07,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7B03,0xFDE7,0xFE4B,0xFF79,0xFEF4,0xFF15,0xB552,0x2945,0x2945,0xDE55,0xFF16,0xFF15,0xFF58,0xFED1,0xFDE7,0xAC25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0xDD26,0xFDE7,0xFF57,0xFED3,0xFED2,0xFEF4,0xBD93,0x2124,0x2124,0xDE75,0xFF14,0xFED3,0xFED3,0xFF7A,0xFE08,0xFDE7,0x49A2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 11, 384 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BA4,0xFDC6,0xFE6E,0xFF36,0xFE90,0xFEB1,0xFED3,0xC592,0x2124,0x2124,0xE675,0xFED3,0xFEB2,0xFEB1,0xFEF3,0xFEF3,0xFDC6,0xBC45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 12, 416 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3141,0xF5C6,0xF5C7,0xFF58,0xFE90,0xFE6F,0xFE8F,0xFEB1,0xCDB2,0x2104,0x2104,0xF6B4,0xFEB1,0xFE90,0xFE8F,0xFE90,0xFF58,0xFE0A,0xF5C6,0x72A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 13, 448 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xABE4,0xF5A6,0xFEB1,0xFED3,0xFE4E,0xFE6E,0xFE6F,0xFE90,0xD5F2,0x18E3,0x18E3,0xFED4,0xFE90,0xFE6F,0xFE6F,0xFE6E,0xFE91,0xFF36,0xF5A6,0xCCA5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 14, 480 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x5202,0xF5A6,0xF5C7,0xFF58,0xFE4D,0xFE4D,0xFE4D,0xFE4E,0xFE6F,0xDE11,0x18C3,0x18C3,0xFED3,0xFE6F,0xFE6E,0xFE4E,0xFE4D,0xFE4D,0xFF16,0xFE2C,0xF5A6,0x9363,0x0000,0x0000,0x0000,0x0000,0x0000, // row 15, 512 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0xBC44,0xF585,0xFED3,0xFE6F,0xFE2C,0xFE2C,0xFE2D,0xFE4D,0xFE4E,0xE630,0x10A2,0x2104,0xFED1,0xFE4E,0xFE4D,0xFE4D,0xFE2D,0xFE2C,0xFE4D,0xFF37,0xF586,0xF585,0x28E1,0x0000,0x0000,0x0000,0x0000, // row 16, 544 pixels -0x0000,0x0000,0x0000,0x0000,0x7282,0xF565,0xF5EA,0xFF16,0xFE0B,0xFE0B,0xFE0B,0xFE2C,0xFE2C,0xFE4D,0xF670,0x1082,0x2924,0xFEB0,0xFE2D,0xFE2C,0xFE2C,0xFE2C,0xFE0B,0xFE0B,0xFEB2,0xFE6F,0xF565,0xA383,0x0000,0x0000,0x0000,0x0000, // row 17, 576 pixels -0x0000,0x0000,0x0000,0x0840,0xD4C4,0xF565,0xFEF5,0xFE0C,0xFDE9,0xFDEA,0xFE0A,0xFE0B,0xFE0B,0xFE2C,0xFE8F,0x0861,0x2964,0xFE8F,0xFE2C,0xFE0B,0xFE0B,0xFE0B,0xFE0A,0xFDEA,0xFE0B,0xFF37,0xF586,0xF565,0x4181,0x0000,0x0000,0x0000, // row 18, 608 pixels -0x0000,0x0000,0x0000,0x9343,0xF545,0xF60C,0xFED3,0xFDC8,0xFDC8,0xFDC9,0xFDE9,0xFDEA,0xFDEA,0xFE0B,0xFE8E,0x0861,0x3184,0xFE6D,0xFE0B,0xFE0A,0xFDEA,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFE4E,0xFEB2,0xF545,0xB3E3,0x0000,0x0000,0x0000, // row 19, 640 pixels -0x0000,0x0000,0x28E0,0xF544,0xF545,0xFF17,0xFDC8,0xFDA7,0xFDA7,0xFDC8,0xFDC8,0xFDC9,0xFDC9,0xFDE9,0xFE6C,0x10A2,0x39C4,0xFE4C,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFDC8,0xFDC8,0xFDA7,0xFDA8,0xFF16,0xF588,0xF544,0x6222,0x0000,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xA383,0xF524,0xF64E,0xFE4E,0xFD86,0xFD86,0xFD87,0xFDA7,0xFDA7,0xFDA8,0xFDC8,0xFDC8,0xFE2A,0xA469,0xB4EA,0xFE2A,0xFDC9,0xFDC8,0xFDC8,0xFDA8,0xFDA7,0xFDA7,0xFD87,0xFD86,0xFDEA,0xFED3,0xF524,0xC443,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x51C1,0xF504,0xF546,0xFF16,0xF565,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDA7,0xFDA7,0xFDE8,0xFE6A,0xFE4A,0xFDE8,0xFDA7,0xFDA7,0xFDA7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFEB2,0xF5CA,0xF504,0x8AE2,0x0000, // row 22, 736 pixels -0x0000,0xB3A2,0xED03,0xFE92,0xFDC9,0xF543,0xF544,0xFD44,0xFD65,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDC7,0xFDC7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFD65,0xFD44,0xF544,0xFD86,0xFEF5,0xED03,0xE4C3,0x1880, // row 23, 768 pixels -0x7241,0xECE3,0xF567,0xFED3,0xF523,0xF523,0xF523,0xF543,0xF544,0xF544,0xFD65,0xFD65,0xFD65,0xFD65,0xD4E6,0x39C5,0x39A5,0xD4E6,0xFD86,0xFD65,0xFD65,0xFD65,0xFD65,0xF544,0xF544,0xF543,0xF523,0xF523,0xFE2E,0xF5EC,0xECE3,0x9B42, // row 24, 800 pixels -0xD443,0xECE3,0xFED4,0xF565,0xF502,0xF502,0xF522,0xF523,0xF523,0xF543,0xF544,0xF544,0xF544,0xFD65,0x8B64,0x18C3,0x18C3,0x8344,0xFD85,0xFD44,0xF544,0xF544,0xF544,0xF543,0xF523,0xF523,0xF522,0xF502,0xF523,0xFEF5,0xED04,0xECE3, // row 25, 832 pixels -0xECC3,0xF5AB,0xFE6F,0xF501,0xF4E1,0xF501,0xF502,0xF502,0xF522,0xF522,0xF523,0xF523,0xF523,0xFD84,0xC504,0x20E1,0x18E1,0xC4E4,0xFD84,0xF543,0xF523,0xF523,0xF523,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xFDC9,0xF62F,0xECC3, // row 26, 864 pixels -0xECC2,0xFE92,0xF523,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF502,0xF502,0xF522,0xF522,0xF543,0xFDE3,0xFEA5,0xF6A4,0xFE04,0xF543,0xF522,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E1,0xFED4,0xECC2, // row 27, 896 pixels -0xECA2,0xF5EC,0xF4E0,0xF4C0,0xF4E0,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF501,0xF502,0xF502,0xF542,0xFDA2,0xFDA2,0xF542,0xF502,0xF502,0xF502,0xF501,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E0,0xF4E0,0xF4C0,0xF5A9,0xECA2, // row 28, 928 pixels -0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels -0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels -0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/160 x 128/Flash_Bitmap2/Close.h b/examples/160 x 128/Flash_Bitmap2/Close.h deleted file mode 100644 index ce676c9..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Close.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t closeWidth = 32; -const uint16_t closeHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short closeX[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x58E3,0xC228,0xFC10,0xFD34,0xFE18,0xFE59,0xFE79,0xFE9A,0xFE9A,0xFE9A,0xFE9A,0xFE59,0xFD75,0xFC51,0xC28A,0x5904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2041,0x8945,0xF34D,0xFD34,0xFDB6,0xFD75,0xFD55,0xFD55,0xFD96,0xFDD7,0xFDF7,0xFDF7,0xFDB6,0xFDB6,0xFDD7,0xFDF7,0xFD75,0xF38E,0x8965,0x2041,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x4082,0xE208,0xF410,0xFD34,0xFC92,0xFBEF,0xFBAE,0xFBEF,0xFC71,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC92,0xFC51,0xFC71,0xFCF3,0xFD75,0xFC30,0xEA28,0x40A2,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x3861,0xE1E7,0xF451,0xFC92,0xFB4D,0xFA49,0xFA49,0xFAEB,0xFBAE,0xFC71,0xFD34,0xFDB6,0xFE18,0xFDB6,0xFD34,0xFC71,0xFBAE,0xFB0C,0xFAEB,0xFBAE,0xFCD3,0xFC71,0xE208,0x4082,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x1020,0xD986,0xF430,0xFC30,0xFA28,0xF924,0xF965,0xFA8A,0xFB0C,0xFBAE,0xFC51,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC51,0xFC71,0xFBEF,0xFA28,0xF9C7,0xFA8A,0xFC51,0xF430,0xD9A6,0x1020,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x78A2,0xEB6D,0xFC30,0xF9C7,0xF861,0xF8A2,0xFA08,0xFEDB,0xFD55,0xFB4D,0xFC10,0xFC92,0xFD14,0xFD34,0xFD14,0xFC92,0xFCB2,0xFF7D,0xFF7D,0xFB2C,0xF945,0xF8E3,0xF9E7,0xFC30,0xEB8E,0x78C3,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x3841,0xD9E7,0xF492,0xF208,0xF041,0xF800,0xF945,0xFE9A,0xFFFF,0xFFFF,0xFD75,0xFB8E,0xFC10,0xFC51,0xFC71,0xFC51,0xFCB2,0xFF7D,0xFFFF,0xFFFF,0xFF3C,0xFA8A,0xF882,0xF841,0xFA08,0xFC92,0xDA08,0x3841,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x88A2,0xEBCF,0xF2EB,0xF061,0xF000,0xF8E3,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD75,0xFB4D,0xFBAE,0xFBAE,0xFC71,0xFF7D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFEFB,0xFA28,0xF800,0xF061,0xF2EB,0xEBEF,0x90C3,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x2820,0xD1C7,0xF410,0xE945,0xE800,0xF000,0xFE9A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD34,0xFAEB,0xFBCF,0xFF5D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFF1C,0xF986,0xF000,0xF145,0xF410,0xD1E7,0x2820,0x0000, // row 10, 352 pixels -0x0000,0x6841,0xDB2C,0xEACB,0xE041,0xE800,0xF000,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD14,0xFF1C,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFBCF,0xF082,0xF000,0xE841,0xEACB,0xE34D,0x7061,0x0000, // row 11, 384 pixels -0x0000,0x9861,0xE3CF,0xE186,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE986,0xEBCF,0xA082,0x0000, // row 12, 416 pixels -0x0800,0xB8A2,0xE3AE,0xD8A2,0xD800,0xE000,0xE800,0xE800,0xF145,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE0A2,0xEBAE,0xC0C3,0x0800, // row 13, 448 pixels -0x1800,0xC124,0xE30C,0xD020,0xD800,0xE000,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD820,0xE30C,0xC124,0x1800, // row 14, 480 pixels -0x2800,0xC165,0xDAAA,0xC800,0xD000,0xD800,0xE000,0xE000,0xE800,0xE800,0xF124,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB6D,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xDAAA,0xC165,0x2800, // row 15, 512 pixels -0x2000,0xB924,0xD269,0xC800,0xD000,0xD000,0xD800,0xE000,0xE000,0xE800,0xE924,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF36D,0xE800,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xD000,0xDA69,0xC145,0x2800, // row 16, 544 pixels -0x1000,0xB0A2,0xD28A,0xC000,0xC800,0xD000,0xD000,0xD800,0xD800,0xE165,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF3AE,0xE000,0xE000,0xD800,0xD800,0xD000,0xD000,0xC800,0xD28A,0xB8C3,0x1000, // row 17, 576 pixels -0x0000,0xA800,0xD2AA,0xB800,0xC000,0xC800,0xC800,0xD000,0xD965,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBAE,0xD800,0xD800,0xD000,0xC800,0xC800,0xC000,0xD2AA,0xB020,0x0000, // row 18, 608 pixels -0x0000,0x8000,0xCA69,0xB841,0xB800,0xC000,0xC800,0xD186,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBCF,0xD000,0xC800,0xC800,0xC000,0xC041,0xCA69,0x8000,0x0000, // row 19, 640 pixels -0x0000,0x4800,0xC1C7,0xB8E3,0xB800,0xB800,0xC000,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBEF,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE410,0xC841,0xC000,0xB800,0xC0E3,0xC1C7,0x4800,0x0000, // row 20, 672 pixels -0x0000,0x1000,0xB061,0xC1E7,0xB000,0xB000,0xB800,0xD269,0xFFBE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xD000,0xD965,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xC020,0xB800,0xB000,0xC1E7,0xB061,0x1000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x6000,0xB9C7,0xB061,0xB000,0xB000,0xB800,0xCA49,0xFF9E,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xC800,0xC800,0xC800,0xD186,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xB800,0xB800,0xB000,0xB061,0xC1C7,0x6000,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x1800,0xB041,0xB986,0xA800,0xA800,0xB000,0xB000,0xCA49,0xFF7D,0xFFFF,0xDB8E,0xC000,0xC000,0xC000,0xC000,0xC000,0xC986,0xF6DB,0xFFFF,0xFFFF,0xD30C,0xB800,0xB000,0xB000,0xA800,0xB986,0xB041,0x1800,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x5800,0xB0E3,0xA8C3,0xA800,0xA800,0xA800,0xB000,0xCACB,0xD38E,0xB000,0xB800,0xB800,0xB800,0xB800,0xB800,0xB800,0xC145,0xF6DB,0xD34D,0xB000,0xB000,0xA800,0xA800,0xB0C3,0xB0E3,0x5800,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x6000,0xB124,0xA882,0xA000,0xA800,0xA800,0xA800,0xA800,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xA800,0xA800,0xA800,0xA800,0xA882,0xB124,0x6000,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB104,0xA882,0xA000,0xA000,0xA000,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA000,0xA000,0xA882,0xB104,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB0A2,0xA8C3,0xA020,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA020,0xA8C3,0xB0A2,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4800,0xA800,0xB0C3,0xA0A2,0x9800,0x9800,0x9800,0x9800,0xA000,0xA000,0xA000,0x9800,0x9800,0x9800,0xA082,0xB0E3,0xA800,0x4800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5800,0xA800,0xB0A2,0xA8E3,0xA0A2,0xA041,0x9800,0x9800,0xA041,0xA0A2,0xA8E3,0xB0A2,0xA800,0x5800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3000,0x6000,0x8800,0xA000,0xA800,0xA800,0xA000,0x8800,0x6000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino b/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino deleted file mode 100644 index 42099e9..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino +++ /dev/null @@ -1,110 +0,0 @@ -// Code partly derived from ILI9341_Due library example - -// Draws the 3 icons across the middle of the screen and pauses. -// Then draws 300 icons at random locations, clears screen and repeats -// -// This demonstrates drawing icons from FLASH - -// Icons are stored in tabs, e.g. Alert.h etc -// more than one icon can be in a header file. - -// Original sketch header follow: -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - This sketch does not use/need any fonts at all... - - Arrays containing FLASH images can be created with UTFT library tool: - (libraries\UTFT\Tools\ImageConverter565.exe) - Convert to .c format then copy into a new tab - - The number and size of icons is limited by available FLASH memory. The icon array will - use width x height x 2 bytes of FLASH, i.e. 32 x 32 icon uses ~2048 bytes - -*/ -#include // Graphics and font library for ST7735 driver chip -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h - -// Include the header files that contain the icons -#include "Alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.init(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, (tft.width() - infoWidth)/2 - 50, (tft.height() - infoHeight)/2, infoWidth, infoHeight); - drawIcon(alert, (tft.width() - alertWidth)/2, (tft.height() - alertHeight)/2, alertWidth, alertHeight); - drawIcon(closeX, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(4000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setAddrWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/160 x 128/Flash_Bitmap2/Info.h b/examples/160 x 128/Flash_Bitmap2/Info.h deleted file mode 100644 index c4ee633..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Info.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t infoWidth = 32; -const uint16_t infoHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short info[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0861,0x4A69,0x8C71,0xA514,0xBDF7,0xBDF7,0xA514,0x8C71,0x4A69,0x0861,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x39E7,0x9CF3,0xEF7D,0xF79E,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xF79E,0xEF7D,0x9CF3,0x39E7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2965,0x9492,0xF79E,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xF79E,0x9492,0x2965,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xD75F,0xB6BF,0x9E5F,0x963F,0x963F,0x9E5F,0xB6BF,0xD75F,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xEF7D,0xFFDF,0xFFFF,0xFFDF,0xBEDF,0x7DBF,0x7DBF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x7DBE,0xBEBF,0xFFDF,0xFFFF,0xFFDF,0xEF7D,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFFF,0xFFFF,0xE77F,0x7DBE,0x759E,0x759F,0x7DBF,0x7DDF,0x7DDF,0x85FF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x759E,0x6D7E,0x7DBE,0xDF7F,0xFFFF,0xFFFF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x31A6,0xEF5D,0xFFDF,0xFFFF,0xCF1E,0x6D7E,0x6D7E,0x759E,0x759F,0x7DBF,0x7DDF,0x8E1F,0xBEDF,0xC6FF,0x8DFF,0x75BF,0x759F,0x759E,0x6D7E,0x655E,0x655D,0xCF1E,0xFFFF,0xFFDF,0xEF5D,0x31A6,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x94B2,0xF7BE,0xFFFF,0xDF5E,0x655D,0x655D,0x6D7E,0x6D7E,0x759E,0x75BF,0x759F,0xEFBF,0xFFFF,0xFFFF,0xEFBF,0x759F,0x759E,0x6D7E,0x6D7E,0x655D,0x653D,0x653D,0xDF5E,0xFFFF,0xF7BE,0x94B2,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x4228,0xEF7D,0xFFFF,0xF7BF,0x6D5D,0x653D,0x655D,0x6D5E,0x6D7E,0x759E,0x759E,0x85DF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8DFE,0x6D7E,0x6D7E,0x6D5E,0x655D,0x653D,0x5D1D,0x6D5D,0xF7BF,0xFFFF,0xEF7D,0x4228,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0xA534,0xFFDF,0xFFDF,0xA65D,0x5D1D,0x5D1D,0x653D,0x655E,0x6D7E,0x6D7E,0x6D7E,0x651E,0xE77F,0xFFFF,0xFFFF,0xF7BF,0x5CFE,0x6D7E,0x6D7E,0x655E,0x653D,0x5D1D,0x5D1D,0x54FC,0xA65D,0xFFDF,0xFFDF,0xA534,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x18E3,0xEF5D,0xFFFF,0xEF9E,0x5CFC,0x54FC,0x5D1D,0x5D3D,0x653D,0x655E,0x6D7E,0x6D7E,0x653E,0x6D3E,0xB67E,0xBEBE,0x755E,0x5D1E,0x6D5E,0x655E,0x653D,0x5D3D,0x5D1D,0x54FC,0x54DC,0x54FC,0xEF9E,0xFFFF,0xEF5D,0x18E3,0x0000, // row 11, 384 pixels -0x0000,0x630C,0xEF7D,0xFFDF,0xB69D,0x54DC,0x54FC,0x5CFC,0x5D1D,0x653D,0x653D,0x655E,0x6D5E,0x655E,0x5CFE,0x4C9D,0x4C7D,0x54DD,0x653E,0x655E,0x653D,0x653D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0xB69D,0xFFDF,0xEF7D,0x630C,0x0000, // row 12, 416 pixels -0x0000,0x94B2,0xF7BE,0xFFDF,0x85BC,0x4CBC,0x54DC,0x54FC,0x5CFD,0x5D1D,0x5D3D,0x653D,0x655D,0x653D,0x85DE,0xC6FE,0xC6FE,0x85BE,0x653D,0x653D,0x5D3D,0x5D1D,0x5CFD,0x54FC,0x54DC,0x4CBC,0x4CBB,0x85BC,0xFFDF,0xF7BE,0x94B2,0x0000, // row 13, 448 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x651C,0x4CBB,0x4CBC,0x54DC,0x54FC,0x5CFC,0x5D1D,0x5D1D,0x653D,0x5D1D,0xE77E,0xFFDF,0xFFDF,0xEF9E,0x5CFD,0x5D1D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x651B,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 14, 480 pixels -0x0000,0xC638,0xFFDF,0xF7BE,0x54DB,0x449B,0x4CBB,0x4CBC,0x54DC,0x54FC,0x54FC,0x5D1D,0x5D1D,0x7D7D,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x7D7D,0x5CFD,0x54FC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x447B,0x54BB,0xF7BE,0xFFDF,0xC638,0x0000, // row 15, 512 pixels -0x0000,0xC638,0xFFDF,0xF79E,0x4CBB,0x449B,0x449B,0x4CBB,0x4CBC,0x54DC,0x54DC,0x54FC,0x54DC,0x753C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x753C,0x54DC,0x54DC,0x54DC,0x4CBC,0x4CBB,0x449B,0x449B,0x3C7B,0x4C9B,0xF79E,0xFFDF,0xC638,0x0000, // row 16, 544 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x5CFB,0x3C7B,0x447B,0x449B,0x4CBB,0x4CBC,0x4CBC,0x4CDC,0x4CBC,0x6D1C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x6CFC,0x4CBC,0x4CBC,0x4CBC,0x4CBB,0x449B,0x447B,0x3C7B,0x3C5A,0x54DB,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 17, 576 pixels -0x0000,0x94B2,0xF7BE,0xF7BE,0x755B,0x3C5A,0x3C7B,0x447B,0x449B,0x449B,0x4CBB,0x4CBB,0x4C9B,0x6CFB,0xF79E,0xF79E,0xF79E,0xF79E,0x64FB,0x449B,0x4CBB,0x449B,0x449B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x753B,0xF7BE,0xF7BE,0x9CD3,0x0000, // row 18, 608 pixels -0x0000,0x6B4D,0xEF7D,0xF7BE,0xA61C,0x3C5A,0x3C5A,0x3C7B,0x447B,0x447B,0x449B,0x449B,0x447B,0x64DB,0xF79E,0xF79E,0xF79E,0xF79E,0x64DB,0x447B,0x449B,0x447B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x343A,0xA61C,0xF7BE,0xEF7D,0x6B4D,0x0000, // row 19, 640 pixels -0x0000,0x2124,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x3C5A,0x3C5A,0x3C7B,0x3C7B,0x447B,0x3C5B,0x64BA,0xF79E,0xF79E,0xF79E,0xF79E,0x64BA,0x3C5B,0x3C7B,0x3C7B,0x3C5A,0x3C5A,0x343A,0x343A,0x343A,0xDF3D,0xFFDF,0xE71C,0x2124,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xAD75,0xF7BE,0xF79E,0x859B,0x343A,0x343A,0x345A,0x3C5A,0x3C5A,0x3C5A,0x3C5A,0x5C9A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x5C9A,0x3C3A,0x3C5A,0x3C5A,0x345A,0x343A,0x343A,0x341A,0x859B,0xF79E,0xF7BE,0xAD75,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x528A,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x343A,0x343A,0x343A,0x3C5A,0x343A,0x4C5A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x4C59,0x343A,0x343A,0x343A,0x343A,0x343A,0x341A,0x3C5A,0xDF3D,0xFFDF,0xE71C,0x528A,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x0000,0x9CD3,0xF79E,0xF7BE,0xBE7C,0x3419,0x341A,0x341A,0x343A,0x343A,0x341A,0x2B99,0xC69C,0xEF7D,0xEF7D,0xD6DC,0x2398,0x341A,0x343A,0x341A,0x341A,0x2C19,0x2C19,0xBE7C,0xF7BE,0xF79E,0x9CD3,0x0000,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x39E7,0xDEDB,0xFFDF,0xF79E,0x9DFB,0x2C19,0x2C19,0x2C1A,0x341A,0x341A,0x2BB9,0x2B57,0x6459,0x74B9,0x2337,0x2BB9,0x341A,0x2C1A,0x2C19,0x2C19,0x2C19,0x9DFB,0xF79E,0xFFDF,0xDEDB,0x39E7,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x632C,0xDEFB,0xFFDF,0xEF7D,0xB65C,0x3C39,0x2BF9,0x2C19,0x2C19,0x2BF9,0x2398,0x1B58,0x1B37,0x2398,0x2BF9,0x2C19,0x2BF9,0x2BF9,0x3439,0xB65C,0xEF7D,0xFFDF,0xDEFB,0x632C,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xDEFB,0xF7BE,0xF79E,0xDF1C,0x7D5A,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x23D9,0x23D9,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x7D5A,0xDF1C,0xF79E,0xF7BE,0xDEFB,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x632C,0xDEDB,0xF79E,0xFFDF,0xEF7D,0xD6FC,0x9DFB,0x5CDA,0x4C9A,0x3419,0x3419,0x4C9A,0x5CDA,0x9DFB,0xD6FC,0xEF7D,0xFFDF,0xF79E,0xDEDB,0x632C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x94B2,0xDEFB,0xF7BE,0xFFDF,0xF7BE,0xF79E,0xEF7D,0xEF5D,0xEF5D,0xEF7D,0xF79E,0xF7BE,0xFFDF,0xF7BE,0xDEFB,0x94B2,0x4208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x528A,0xA534,0xDEDB,0xE73C,0xF79E,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0xF79E,0xE73C,0xDEDB,0xA534,0x528A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x18C3,0x5AEB,0x8C71,0xAD55,0xBDD7,0xBDD7,0xAD55,0x8C71,0x5AEB,0x18C3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino b/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino deleted file mode 100644 index 82e09eb..0000000 --- a/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino +++ /dev/null @@ -1,106 +0,0 @@ -// Icons are stored in tabs ^ e.g. Alert.h etc above this line -// more than one icon can be in a header file - -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - Works with TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - This sketch does not use/need any fonts at all... - - Code derived from ILI9341_due example - - Make sure all the display driver and pin comnenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. - - ######################################################################### - ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### - ######################################################################### -*/ - -#include // Hardware-specific library - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library - -// Include the header files that contain the icons -#include "Alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.begin(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, 100, 100, infoWidth, infoHeight); - drawIcon(alert, 140, 100, alertWidth, alertHeight); - drawIcon(closeX, 180, 100, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(2000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - //Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/480 x 320/Flash_Bitmap/Alert.h b/examples/480 x 320/Flash_Bitmap/Alert.h deleted file mode 100644 index 54d013d..0000000 --- a/examples/480 x 320/Flash_Bitmap/Alert.h +++ /dev/null @@ -1,42 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t alertWidth = 32; -const uint16_t alertHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short alert[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1080,0xAC66,0xEDE8,0xFE69,0xC4C6,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xBCC6,0xFE68,0xFE68,0xFE6A,0xFE68,0xEDE8,0x18A1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8344,0xFE48,0xFE8C,0xFFDD,0xFFFF,0xFEF0,0xFE48,0xB466,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1880,0xEDC7,0xFE48,0xFF99,0xFFBC,0xFF9B,0xFFBD,0xFE6A,0xFE48,0x5A23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BE5,0xFE28,0xFED0,0xFFBC,0xFF7A,0xFF9A,0xFF9B,0xFF35,0xFE28,0xBCA6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3962,0xFE28,0xFE28,0xFF9A,0xFF79,0xFF9A,0xFF9B,0xFF9A,0xFFBD,0xFE6B,0xFE28,0x72E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xB465,0xFE28,0xFEF2,0xFF7A,0xFF79,0xFF7A,0xFF9A,0xFF7A,0xFF7A,0xFF78,0xFE28,0xDD67,0x0860,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5A22,0xFE07,0xFE29,0xFF9B,0xFF37,0xFF58,0xFF79,0xFF79,0xFF79,0xFF58,0xFF9B,0xFEAE,0xFE07,0x93A4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xC4A5,0xFE07,0xFF15,0xFF37,0xFF36,0xAD11,0x2965,0x2965,0xCDF4,0xFF37,0xFF37,0xFF79,0xFE07,0xFE07,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7B03,0xFDE7,0xFE4B,0xFF79,0xFEF4,0xFF15,0xB552,0x2945,0x2945,0xDE55,0xFF16,0xFF15,0xFF58,0xFED1,0xFDE7,0xAC25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0xDD26,0xFDE7,0xFF57,0xFED3,0xFED2,0xFEF4,0xBD93,0x2124,0x2124,0xDE75,0xFF14,0xFED3,0xFED3,0xFF7A,0xFE08,0xFDE7,0x49A2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 11, 384 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BA4,0xFDC6,0xFE6E,0xFF36,0xFE90,0xFEB1,0xFED3,0xC592,0x2124,0x2124,0xE675,0xFED3,0xFEB2,0xFEB1,0xFEF3,0xFEF3,0xFDC6,0xBC45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 12, 416 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3141,0xF5C6,0xF5C7,0xFF58,0xFE90,0xFE6F,0xFE8F,0xFEB1,0xCDB2,0x2104,0x2104,0xF6B4,0xFEB1,0xFE90,0xFE8F,0xFE90,0xFF58,0xFE0A,0xF5C6,0x72A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 13, 448 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xABE4,0xF5A6,0xFEB1,0xFED3,0xFE4E,0xFE6E,0xFE6F,0xFE90,0xD5F2,0x18E3,0x18E3,0xFED4,0xFE90,0xFE6F,0xFE6F,0xFE6E,0xFE91,0xFF36,0xF5A6,0xCCA5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 14, 480 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x5202,0xF5A6,0xF5C7,0xFF58,0xFE4D,0xFE4D,0xFE4D,0xFE4E,0xFE6F,0xDE11,0x18C3,0x18C3,0xFED3,0xFE6F,0xFE6E,0xFE4E,0xFE4D,0xFE4D,0xFF16,0xFE2C,0xF5A6,0x9363,0x0000,0x0000,0x0000,0x0000,0x0000, // row 15, 512 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0xBC44,0xF585,0xFED3,0xFE6F,0xFE2C,0xFE2C,0xFE2D,0xFE4D,0xFE4E,0xE630,0x10A2,0x2104,0xFED1,0xFE4E,0xFE4D,0xFE4D,0xFE2D,0xFE2C,0xFE4D,0xFF37,0xF586,0xF585,0x28E1,0x0000,0x0000,0x0000,0x0000, // row 16, 544 pixels -0x0000,0x0000,0x0000,0x0000,0x7282,0xF565,0xF5EA,0xFF16,0xFE0B,0xFE0B,0xFE0B,0xFE2C,0xFE2C,0xFE4D,0xF670,0x1082,0x2924,0xFEB0,0xFE2D,0xFE2C,0xFE2C,0xFE2C,0xFE0B,0xFE0B,0xFEB2,0xFE6F,0xF565,0xA383,0x0000,0x0000,0x0000,0x0000, // row 17, 576 pixels -0x0000,0x0000,0x0000,0x0840,0xD4C4,0xF565,0xFEF5,0xFE0C,0xFDE9,0xFDEA,0xFE0A,0xFE0B,0xFE0B,0xFE2C,0xFE8F,0x0861,0x2964,0xFE8F,0xFE2C,0xFE0B,0xFE0B,0xFE0B,0xFE0A,0xFDEA,0xFE0B,0xFF37,0xF586,0xF565,0x4181,0x0000,0x0000,0x0000, // row 18, 608 pixels -0x0000,0x0000,0x0000,0x9343,0xF545,0xF60C,0xFED3,0xFDC8,0xFDC8,0xFDC9,0xFDE9,0xFDEA,0xFDEA,0xFE0B,0xFE8E,0x0861,0x3184,0xFE6D,0xFE0B,0xFE0A,0xFDEA,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFE4E,0xFEB2,0xF545,0xB3E3,0x0000,0x0000,0x0000, // row 19, 640 pixels -0x0000,0x0000,0x28E0,0xF544,0xF545,0xFF17,0xFDC8,0xFDA7,0xFDA7,0xFDC8,0xFDC8,0xFDC9,0xFDC9,0xFDE9,0xFE6C,0x10A2,0x39C4,0xFE4C,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFDC8,0xFDC8,0xFDA7,0xFDA8,0xFF16,0xF588,0xF544,0x6222,0x0000,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xA383,0xF524,0xF64E,0xFE4E,0xFD86,0xFD86,0xFD87,0xFDA7,0xFDA7,0xFDA8,0xFDC8,0xFDC8,0xFE2A,0xA469,0xB4EA,0xFE2A,0xFDC9,0xFDC8,0xFDC8,0xFDA8,0xFDA7,0xFDA7,0xFD87,0xFD86,0xFDEA,0xFED3,0xF524,0xC443,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x51C1,0xF504,0xF546,0xFF16,0xF565,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDA7,0xFDA7,0xFDE8,0xFE6A,0xFE4A,0xFDE8,0xFDA7,0xFDA7,0xFDA7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFEB2,0xF5CA,0xF504,0x8AE2,0x0000, // row 22, 736 pixels -0x0000,0xB3A2,0xED03,0xFE92,0xFDC9,0xF543,0xF544,0xFD44,0xFD65,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDC7,0xFDC7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFD65,0xFD44,0xF544,0xFD86,0xFEF5,0xED03,0xE4C3,0x1880, // row 23, 768 pixels -0x7241,0xECE3,0xF567,0xFED3,0xF523,0xF523,0xF523,0xF543,0xF544,0xF544,0xFD65,0xFD65,0xFD65,0xFD65,0xD4E6,0x39C5,0x39A5,0xD4E6,0xFD86,0xFD65,0xFD65,0xFD65,0xFD65,0xF544,0xF544,0xF543,0xF523,0xF523,0xFE2E,0xF5EC,0xECE3,0x9B42, // row 24, 800 pixels -0xD443,0xECE3,0xFED4,0xF565,0xF502,0xF502,0xF522,0xF523,0xF523,0xF543,0xF544,0xF544,0xF544,0xFD65,0x8B64,0x18C3,0x18C3,0x8344,0xFD85,0xFD44,0xF544,0xF544,0xF544,0xF543,0xF523,0xF523,0xF522,0xF502,0xF523,0xFEF5,0xED04,0xECE3, // row 25, 832 pixels -0xECC3,0xF5AB,0xFE6F,0xF501,0xF4E1,0xF501,0xF502,0xF502,0xF522,0xF522,0xF523,0xF523,0xF523,0xFD84,0xC504,0x20E1,0x18E1,0xC4E4,0xFD84,0xF543,0xF523,0xF523,0xF523,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xFDC9,0xF62F,0xECC3, // row 26, 864 pixels -0xECC2,0xFE92,0xF523,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF502,0xF502,0xF522,0xF522,0xF543,0xFDE3,0xFEA5,0xF6A4,0xFE04,0xF543,0xF522,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E1,0xFED4,0xECC2, // row 27, 896 pixels -0xECA2,0xF5EC,0xF4E0,0xF4C0,0xF4E0,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF501,0xF502,0xF502,0xF542,0xFDA2,0xFDA2,0xF542,0xF502,0xF502,0xF502,0xF501,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E0,0xF4E0,0xF4C0,0xF5A9,0xECA2, // row 28, 928 pixels -0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels -0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels -0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/480 x 320/Flash_Bitmap/Close.h b/examples/480 x 320/Flash_Bitmap/Close.h deleted file mode 100644 index ce676c9..0000000 --- a/examples/480 x 320/Flash_Bitmap/Close.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t closeWidth = 32; -const uint16_t closeHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short closeX[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x58E3,0xC228,0xFC10,0xFD34,0xFE18,0xFE59,0xFE79,0xFE9A,0xFE9A,0xFE9A,0xFE9A,0xFE59,0xFD75,0xFC51,0xC28A,0x5904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2041,0x8945,0xF34D,0xFD34,0xFDB6,0xFD75,0xFD55,0xFD55,0xFD96,0xFDD7,0xFDF7,0xFDF7,0xFDB6,0xFDB6,0xFDD7,0xFDF7,0xFD75,0xF38E,0x8965,0x2041,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x4082,0xE208,0xF410,0xFD34,0xFC92,0xFBEF,0xFBAE,0xFBEF,0xFC71,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC92,0xFC51,0xFC71,0xFCF3,0xFD75,0xFC30,0xEA28,0x40A2,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x3861,0xE1E7,0xF451,0xFC92,0xFB4D,0xFA49,0xFA49,0xFAEB,0xFBAE,0xFC71,0xFD34,0xFDB6,0xFE18,0xFDB6,0xFD34,0xFC71,0xFBAE,0xFB0C,0xFAEB,0xFBAE,0xFCD3,0xFC71,0xE208,0x4082,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x1020,0xD986,0xF430,0xFC30,0xFA28,0xF924,0xF965,0xFA8A,0xFB0C,0xFBAE,0xFC51,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC51,0xFC71,0xFBEF,0xFA28,0xF9C7,0xFA8A,0xFC51,0xF430,0xD9A6,0x1020,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x78A2,0xEB6D,0xFC30,0xF9C7,0xF861,0xF8A2,0xFA08,0xFEDB,0xFD55,0xFB4D,0xFC10,0xFC92,0xFD14,0xFD34,0xFD14,0xFC92,0xFCB2,0xFF7D,0xFF7D,0xFB2C,0xF945,0xF8E3,0xF9E7,0xFC30,0xEB8E,0x78C3,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x3841,0xD9E7,0xF492,0xF208,0xF041,0xF800,0xF945,0xFE9A,0xFFFF,0xFFFF,0xFD75,0xFB8E,0xFC10,0xFC51,0xFC71,0xFC51,0xFCB2,0xFF7D,0xFFFF,0xFFFF,0xFF3C,0xFA8A,0xF882,0xF841,0xFA08,0xFC92,0xDA08,0x3841,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x88A2,0xEBCF,0xF2EB,0xF061,0xF000,0xF8E3,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD75,0xFB4D,0xFBAE,0xFBAE,0xFC71,0xFF7D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFEFB,0xFA28,0xF800,0xF061,0xF2EB,0xEBEF,0x90C3,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x2820,0xD1C7,0xF410,0xE945,0xE800,0xF000,0xFE9A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD34,0xFAEB,0xFBCF,0xFF5D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFF1C,0xF986,0xF000,0xF145,0xF410,0xD1E7,0x2820,0x0000, // row 10, 352 pixels -0x0000,0x6841,0xDB2C,0xEACB,0xE041,0xE800,0xF000,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD14,0xFF1C,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFBCF,0xF082,0xF000,0xE841,0xEACB,0xE34D,0x7061,0x0000, // row 11, 384 pixels -0x0000,0x9861,0xE3CF,0xE186,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE986,0xEBCF,0xA082,0x0000, // row 12, 416 pixels -0x0800,0xB8A2,0xE3AE,0xD8A2,0xD800,0xE000,0xE800,0xE800,0xF145,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE0A2,0xEBAE,0xC0C3,0x0800, // row 13, 448 pixels -0x1800,0xC124,0xE30C,0xD020,0xD800,0xE000,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD820,0xE30C,0xC124,0x1800, // row 14, 480 pixels -0x2800,0xC165,0xDAAA,0xC800,0xD000,0xD800,0xE000,0xE000,0xE800,0xE800,0xF124,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB6D,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xDAAA,0xC165,0x2800, // row 15, 512 pixels -0x2000,0xB924,0xD269,0xC800,0xD000,0xD000,0xD800,0xE000,0xE000,0xE800,0xE924,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF36D,0xE800,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xD000,0xDA69,0xC145,0x2800, // row 16, 544 pixels -0x1000,0xB0A2,0xD28A,0xC000,0xC800,0xD000,0xD000,0xD800,0xD800,0xE165,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF3AE,0xE000,0xE000,0xD800,0xD800,0xD000,0xD000,0xC800,0xD28A,0xB8C3,0x1000, // row 17, 576 pixels -0x0000,0xA800,0xD2AA,0xB800,0xC000,0xC800,0xC800,0xD000,0xD965,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBAE,0xD800,0xD800,0xD000,0xC800,0xC800,0xC000,0xD2AA,0xB020,0x0000, // row 18, 608 pixels -0x0000,0x8000,0xCA69,0xB841,0xB800,0xC000,0xC800,0xD186,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBCF,0xD000,0xC800,0xC800,0xC000,0xC041,0xCA69,0x8000,0x0000, // row 19, 640 pixels -0x0000,0x4800,0xC1C7,0xB8E3,0xB800,0xB800,0xC000,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBEF,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE410,0xC841,0xC000,0xB800,0xC0E3,0xC1C7,0x4800,0x0000, // row 20, 672 pixels -0x0000,0x1000,0xB061,0xC1E7,0xB000,0xB000,0xB800,0xD269,0xFFBE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xD000,0xD965,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xC020,0xB800,0xB000,0xC1E7,0xB061,0x1000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x6000,0xB9C7,0xB061,0xB000,0xB000,0xB800,0xCA49,0xFF9E,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xC800,0xC800,0xC800,0xD186,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xB800,0xB800,0xB000,0xB061,0xC1C7,0x6000,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x1800,0xB041,0xB986,0xA800,0xA800,0xB000,0xB000,0xCA49,0xFF7D,0xFFFF,0xDB8E,0xC000,0xC000,0xC000,0xC000,0xC000,0xC986,0xF6DB,0xFFFF,0xFFFF,0xD30C,0xB800,0xB000,0xB000,0xA800,0xB986,0xB041,0x1800,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x5800,0xB0E3,0xA8C3,0xA800,0xA800,0xA800,0xB000,0xCACB,0xD38E,0xB000,0xB800,0xB800,0xB800,0xB800,0xB800,0xB800,0xC145,0xF6DB,0xD34D,0xB000,0xB000,0xA800,0xA800,0xB0C3,0xB0E3,0x5800,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x6000,0xB124,0xA882,0xA000,0xA800,0xA800,0xA800,0xA800,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xA800,0xA800,0xA800,0xA800,0xA882,0xB124,0x6000,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB104,0xA882,0xA000,0xA000,0xA000,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA000,0xA000,0xA882,0xB104,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB0A2,0xA8C3,0xA020,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA020,0xA8C3,0xB0A2,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4800,0xA800,0xB0C3,0xA0A2,0x9800,0x9800,0x9800,0x9800,0xA000,0xA000,0xA000,0x9800,0x9800,0x9800,0xA082,0xB0E3,0xA800,0x4800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5800,0xA800,0xB0A2,0xA8E3,0xA0A2,0xA041,0x9800,0x9800,0xA041,0xA0A2,0xA8E3,0xB0A2,0xA800,0x5800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3000,0x6000,0x8800,0xA000,0xA800,0xA800,0xA000,0x8800,0x6000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino b/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino deleted file mode 100644 index d3ca697..0000000 --- a/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino +++ /dev/null @@ -1,113 +0,0 @@ -// Code partly derived from ILI9341_due library example - -// Draws the 3 icons across the middle of the screen and pauses. -// Then draws 300 icons at random locations, clears screen and repeats -// -// This demonstrates drawing icons from FLASH - -// Icons are stored in tabs, e.g. Alert.h etc -// more than one icon can be in a header file. - -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - Works with TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - This sketch does not use/need any fonts at all... - - Arrays containing FLASH images can be created with UTFT library tool: - (libraries\UTFT\Tools\ImageConverter565.exe) - Convert to .c format then copy into a new tab - - The number and size of icons is limited by available FLASH memory. The icon array will - use width x height x 2 bytes of FLASH, i.e. 32 x 32 icon uses ~2048 bytes - -*/ - -#include // Hardware-specific library -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height - -// Include the header files that contain the icons -#include "Alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.begin(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, (tft.width() - infoWidth)/2 - 50, (tft.height() - infoHeight)/2, infoWidth, infoHeight); - drawIcon(alert, (tft.width() - alertWidth)/2, (tft.height() - alertHeight)/2, alertWidth, alertHeight); - drawIcon(closeX, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(4000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/480 x 320/Flash_Bitmap/Info.h b/examples/480 x 320/Flash_Bitmap/Info.h deleted file mode 100644 index c4ee633..0000000 --- a/examples/480 x 320/Flash_Bitmap/Info.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t infoWidth = 32; -const uint16_t infoHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short info[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0861,0x4A69,0x8C71,0xA514,0xBDF7,0xBDF7,0xA514,0x8C71,0x4A69,0x0861,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x39E7,0x9CF3,0xEF7D,0xF79E,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xF79E,0xEF7D,0x9CF3,0x39E7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2965,0x9492,0xF79E,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xF79E,0x9492,0x2965,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xD75F,0xB6BF,0x9E5F,0x963F,0x963F,0x9E5F,0xB6BF,0xD75F,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xEF7D,0xFFDF,0xFFFF,0xFFDF,0xBEDF,0x7DBF,0x7DBF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x7DBE,0xBEBF,0xFFDF,0xFFFF,0xFFDF,0xEF7D,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFFF,0xFFFF,0xE77F,0x7DBE,0x759E,0x759F,0x7DBF,0x7DDF,0x7DDF,0x85FF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x759E,0x6D7E,0x7DBE,0xDF7F,0xFFFF,0xFFFF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x31A6,0xEF5D,0xFFDF,0xFFFF,0xCF1E,0x6D7E,0x6D7E,0x759E,0x759F,0x7DBF,0x7DDF,0x8E1F,0xBEDF,0xC6FF,0x8DFF,0x75BF,0x759F,0x759E,0x6D7E,0x655E,0x655D,0xCF1E,0xFFFF,0xFFDF,0xEF5D,0x31A6,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x94B2,0xF7BE,0xFFFF,0xDF5E,0x655D,0x655D,0x6D7E,0x6D7E,0x759E,0x75BF,0x759F,0xEFBF,0xFFFF,0xFFFF,0xEFBF,0x759F,0x759E,0x6D7E,0x6D7E,0x655D,0x653D,0x653D,0xDF5E,0xFFFF,0xF7BE,0x94B2,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x4228,0xEF7D,0xFFFF,0xF7BF,0x6D5D,0x653D,0x655D,0x6D5E,0x6D7E,0x759E,0x759E,0x85DF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8DFE,0x6D7E,0x6D7E,0x6D5E,0x655D,0x653D,0x5D1D,0x6D5D,0xF7BF,0xFFFF,0xEF7D,0x4228,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0xA534,0xFFDF,0xFFDF,0xA65D,0x5D1D,0x5D1D,0x653D,0x655E,0x6D7E,0x6D7E,0x6D7E,0x651E,0xE77F,0xFFFF,0xFFFF,0xF7BF,0x5CFE,0x6D7E,0x6D7E,0x655E,0x653D,0x5D1D,0x5D1D,0x54FC,0xA65D,0xFFDF,0xFFDF,0xA534,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x18E3,0xEF5D,0xFFFF,0xEF9E,0x5CFC,0x54FC,0x5D1D,0x5D3D,0x653D,0x655E,0x6D7E,0x6D7E,0x653E,0x6D3E,0xB67E,0xBEBE,0x755E,0x5D1E,0x6D5E,0x655E,0x653D,0x5D3D,0x5D1D,0x54FC,0x54DC,0x54FC,0xEF9E,0xFFFF,0xEF5D,0x18E3,0x0000, // row 11, 384 pixels -0x0000,0x630C,0xEF7D,0xFFDF,0xB69D,0x54DC,0x54FC,0x5CFC,0x5D1D,0x653D,0x653D,0x655E,0x6D5E,0x655E,0x5CFE,0x4C9D,0x4C7D,0x54DD,0x653E,0x655E,0x653D,0x653D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0xB69D,0xFFDF,0xEF7D,0x630C,0x0000, // row 12, 416 pixels -0x0000,0x94B2,0xF7BE,0xFFDF,0x85BC,0x4CBC,0x54DC,0x54FC,0x5CFD,0x5D1D,0x5D3D,0x653D,0x655D,0x653D,0x85DE,0xC6FE,0xC6FE,0x85BE,0x653D,0x653D,0x5D3D,0x5D1D,0x5CFD,0x54FC,0x54DC,0x4CBC,0x4CBB,0x85BC,0xFFDF,0xF7BE,0x94B2,0x0000, // row 13, 448 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x651C,0x4CBB,0x4CBC,0x54DC,0x54FC,0x5CFC,0x5D1D,0x5D1D,0x653D,0x5D1D,0xE77E,0xFFDF,0xFFDF,0xEF9E,0x5CFD,0x5D1D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x651B,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 14, 480 pixels -0x0000,0xC638,0xFFDF,0xF7BE,0x54DB,0x449B,0x4CBB,0x4CBC,0x54DC,0x54FC,0x54FC,0x5D1D,0x5D1D,0x7D7D,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x7D7D,0x5CFD,0x54FC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x447B,0x54BB,0xF7BE,0xFFDF,0xC638,0x0000, // row 15, 512 pixels -0x0000,0xC638,0xFFDF,0xF79E,0x4CBB,0x449B,0x449B,0x4CBB,0x4CBC,0x54DC,0x54DC,0x54FC,0x54DC,0x753C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x753C,0x54DC,0x54DC,0x54DC,0x4CBC,0x4CBB,0x449B,0x449B,0x3C7B,0x4C9B,0xF79E,0xFFDF,0xC638,0x0000, // row 16, 544 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x5CFB,0x3C7B,0x447B,0x449B,0x4CBB,0x4CBC,0x4CBC,0x4CDC,0x4CBC,0x6D1C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x6CFC,0x4CBC,0x4CBC,0x4CBC,0x4CBB,0x449B,0x447B,0x3C7B,0x3C5A,0x54DB,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 17, 576 pixels -0x0000,0x94B2,0xF7BE,0xF7BE,0x755B,0x3C5A,0x3C7B,0x447B,0x449B,0x449B,0x4CBB,0x4CBB,0x4C9B,0x6CFB,0xF79E,0xF79E,0xF79E,0xF79E,0x64FB,0x449B,0x4CBB,0x449B,0x449B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x753B,0xF7BE,0xF7BE,0x9CD3,0x0000, // row 18, 608 pixels -0x0000,0x6B4D,0xEF7D,0xF7BE,0xA61C,0x3C5A,0x3C5A,0x3C7B,0x447B,0x447B,0x449B,0x449B,0x447B,0x64DB,0xF79E,0xF79E,0xF79E,0xF79E,0x64DB,0x447B,0x449B,0x447B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x343A,0xA61C,0xF7BE,0xEF7D,0x6B4D,0x0000, // row 19, 640 pixels -0x0000,0x2124,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x3C5A,0x3C5A,0x3C7B,0x3C7B,0x447B,0x3C5B,0x64BA,0xF79E,0xF79E,0xF79E,0xF79E,0x64BA,0x3C5B,0x3C7B,0x3C7B,0x3C5A,0x3C5A,0x343A,0x343A,0x343A,0xDF3D,0xFFDF,0xE71C,0x2124,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xAD75,0xF7BE,0xF79E,0x859B,0x343A,0x343A,0x345A,0x3C5A,0x3C5A,0x3C5A,0x3C5A,0x5C9A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x5C9A,0x3C3A,0x3C5A,0x3C5A,0x345A,0x343A,0x343A,0x341A,0x859B,0xF79E,0xF7BE,0xAD75,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x528A,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x343A,0x343A,0x343A,0x3C5A,0x343A,0x4C5A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x4C59,0x343A,0x343A,0x343A,0x343A,0x343A,0x341A,0x3C5A,0xDF3D,0xFFDF,0xE71C,0x528A,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x0000,0x9CD3,0xF79E,0xF7BE,0xBE7C,0x3419,0x341A,0x341A,0x343A,0x343A,0x341A,0x2B99,0xC69C,0xEF7D,0xEF7D,0xD6DC,0x2398,0x341A,0x343A,0x341A,0x341A,0x2C19,0x2C19,0xBE7C,0xF7BE,0xF79E,0x9CD3,0x0000,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x39E7,0xDEDB,0xFFDF,0xF79E,0x9DFB,0x2C19,0x2C19,0x2C1A,0x341A,0x341A,0x2BB9,0x2B57,0x6459,0x74B9,0x2337,0x2BB9,0x341A,0x2C1A,0x2C19,0x2C19,0x2C19,0x9DFB,0xF79E,0xFFDF,0xDEDB,0x39E7,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x632C,0xDEFB,0xFFDF,0xEF7D,0xB65C,0x3C39,0x2BF9,0x2C19,0x2C19,0x2BF9,0x2398,0x1B58,0x1B37,0x2398,0x2BF9,0x2C19,0x2BF9,0x2BF9,0x3439,0xB65C,0xEF7D,0xFFDF,0xDEFB,0x632C,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xDEFB,0xF7BE,0xF79E,0xDF1C,0x7D5A,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x23D9,0x23D9,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x7D5A,0xDF1C,0xF79E,0xF7BE,0xDEFB,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x632C,0xDEDB,0xF79E,0xFFDF,0xEF7D,0xD6FC,0x9DFB,0x5CDA,0x4C9A,0x3419,0x3419,0x4C9A,0x5CDA,0x9DFB,0xD6FC,0xEF7D,0xFFDF,0xF79E,0xDEDB,0x632C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x94B2,0xDEFB,0xF7BE,0xFFDF,0xF7BE,0xF79E,0xEF7D,0xEF5D,0xEF5D,0xEF7D,0xF79E,0xF7BE,0xFFDF,0xF7BE,0xDEFB,0x94B2,0x4208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x528A,0xA534,0xDEDB,0xE73C,0xF79E,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0xF79E,0xE73C,0xDEDB,0xA534,0x528A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x18C3,0x5AEB,0x8C71,0xAD55,0xBDD7,0xBDD7,0xAD55,0x8C71,0x5AEB,0x18C3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Alert.h b/examples/Generic/TFT_Flash_Bitmap/Alert.h similarity index 99% rename from examples/320 x 240/TFT_Flash_Bitmap/Alert.h rename to examples/Generic/TFT_Flash_Bitmap/Alert.h index 44196a9..0e5a895 100644 --- a/examples/320 x 240/TFT_Flash_Bitmap/Alert.h +++ b/examples/Generic/TFT_Flash_Bitmap/Alert.h @@ -38,4 +38,3 @@ const unsigned short alert[1024] PROGMEM={ 0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels 0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels 0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Close.h b/examples/Generic/TFT_Flash_Bitmap/Close.h similarity index 100% rename from examples/320 x 240/TFT_Flash_Bitmap/Close.h rename to examples/Generic/TFT_Flash_Bitmap/Close.h diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Info.h b/examples/Generic/TFT_Flash_Bitmap/Info.h similarity index 100% rename from examples/320 x 240/TFT_Flash_Bitmap/Info.h rename to examples/Generic/TFT_Flash_Bitmap/Info.h diff --git a/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino b/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino new file mode 100644 index 0000000..54ac4e7 --- /dev/null +++ b/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino @@ -0,0 +1,72 @@ +// Icon images are stored in tabs ^ e.g. Alert.h etc above this line +// more than one icon can be in a header file + +// Arrays containing FLASH images can be created with UTFT library tool: +// (libraries\UTFT\Tools\ImageConverter565.exe) +// Convert to .c format then copy into a new tab + +/* + This sketch demonstrates loading images from arrays stored in program (FLASH) memory. + + Works with TFT_eSPI library here: + https://github.com/Bodmer/TFT_eSPI + + This sketch does not use/need any fonts at all... + + Code derived from ILI9341_due library example + + Make sure all the display driver and pin comnenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +// Include the header files that contain the icons +#include "Alert.h" +#include "Close.h" +#include "Info.h" + +long count = 0; // Loop count + +void setup() +{ + Serial.begin(115200); + tft.begin(); + tft.setRotation(1); // landscape + + tft.fillScreen(TFT_BLACK); + + // Swap the colour byte order when rendering + tft.setSwapBytes(true); + + // Draw the icons + tft.pushImage(100, 100, infoWidth, infoHeight, info); + tft.pushImage(140, 100, alertWidth, alertHeight, alert); + tft.pushImage(180, 100, closeWidth, closeHeight, closeX); + + // Pause here to admire the icons! + delay(2000); + +} + +void loop() +{ + // Loop filling and clearing screen + tft.pushImage(random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight, info); + tft.pushImage(random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight, alert); + tft.pushImage(random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight, closeX); + + // Clear screen after 100 x 3 = 300 icons drawn + if (1000 == count++) { + count = 1; + tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! + tft.fillScreen(TFT_BLACK); + tft.setRotation(1); + } +} diff --git a/examples/Sprite/1_bit_Sprite_Demo/1_bit_Sprite_Demo.ino b/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino similarity index 100% rename from examples/Sprite/1_bit_Sprite_Demo/1_bit_Sprite_Demo.ino rename to examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino diff --git a/examples/Sprite/1_bit_Yin_Yang/1_bit_Yin_Yang.ino b/examples/Sprite/One_bit_Yin_Yang/One_bit_Yin_Yang.ino similarity index 100% rename from examples/Sprite/1_bit_Yin_Yang/1_bit_Yin_Yang.ino rename to examples/Sprite/One_bit_Yin_Yang/One_bit_Yin_Yang.ino diff --git a/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino b/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino new file mode 100644 index 0000000..b789b50 --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino @@ -0,0 +1,182 @@ +// This example plots a rotated Sprite to the screen using the pushRotated() +// function. It is written for a 240 x 320 TFT screen. + +// Two rotation pivot points must be set, one for the Sprite and one for the TFT +// using setPivot(). These pivot points do not need to be within the visible screen +// or Sprite boundary. + +// When the Sprite is rotated and pushed to the TFT with pushRotated(angle) it will be +// drawn so that the two pivot points coincide. This makes rotation about a point on the +// screen very simple. The rotation is clockwise with increasing angle. The angle is in +// degrees, an angle of 0 means no Sprite rotation. + +// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. + +// The original Sprite is unchanged so can be plotted again at a different angle. + +// Optionally a transparent colour can be defined, pixels of this colour will +// not be plotted to the TFT. + +// For 1 bpp Sprites the foreground and background colours are defined with the +// function spr.setBitmapColor(foregroundColor, backgroundColor). + +// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +#include + +TFT_eSPI tft = TFT_eSPI(); // TFT object + +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite object + +// ======================================================================================= +// Setup +// ======================================================================================= + +void setup() { + Serial.begin(250000); // Debug only + + tft.begin(); // initialize + tft.setRotation(0); +} + +// ======================================================================================= +// Loop +// ======================================================================================= + +void loop() { + + int xw = tft.width()/2; // xw, yh is midle of screen + int yh = tft.height()/2; + + + showMessage("90 degree angles"); + tft.setPivot(xw, yh); // Set pivot to middle of TFT screen + drawX(xw, yh); // Show where screen pivot is + + // Create the Sprite + spr.setColorDepth(8); // Create an 8bpp Sprite of 60x30 pixels + spr.createSprite(64, 30); // 8bpp requires 64 * 30 = 1920 bytes + spr.setPivot(32, 55); // Set pivot relative to top left corner of Sprite + spr.fillSprite(TFT_BLACK); // Fill the Sprite with black + + spr.setTextColor(TFT_GREEN); // Green text + spr.setTextDatum(MC_DATUM); // Middle centre datum + spr.drawString("Hello", 32, 15, 4); // Plot text, font 4, in Sprite at 30, 15 + + spr.pushRotated(0); + spr.pushRotated(90); + spr.pushRotated(180); + spr.pushRotated(270); + + delay(2000); + + + showMessage("45 degree angles"); + drawX(xw, yh); // Show where screen pivot is + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Moved Sprite pivot point"); + drawX(xw, yh); // Show where screen pivot is + + spr.setPivot(-20, 15); // Change just the Sprite pivot point + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Moved TFT pivot point"); + tft.setPivot(100, 100); // Change just the TFT pivot point + drawX(100, 100); // Show where pivot is + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Transparent rotations"); + tft.fillCircle(xw, yh, 70, TFT_DARKGREY); // Draw a filled circle + + tft.setPivot(xw, yh); // Set pivot to middle of screen + drawX(xw, yh); // Show where pivot is + + spr.deleteSprite(); + + spr.setColorDepth(8); // Create a 8bpp Sprite + spr.createSprite(40, 30); // Create a new Sprite 40x30 + spr.setPivot(20, 70); // Set Sprite pivot at 20,80 + + spr.setTextColor(TFT_RED); // Red text in Sprite + spr.setTextDatum(MC_DATUM); // Middle centre datum + + int num = 1; + + for (int16_t angle = 30; angle <= 360; angle += 30) + { + spr.fillSprite(TFT_BLACK); // Clear the Sprite + spr.drawNumber(num, 20, 15, 4); // Plot number, in Sprite at 15,15 and with font 4 + spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent + num++; + } + + spr.setTextColor(TFT_WHITE); // White text in Sprite + spr.setPivot(-75, 15); // Set Sprite pivot at -75,15 + + for (int16_t angle = -90; angle < 270; angle += 30) + { + spr.fillSprite(TFT_BLACK); // Clear the Sprite + spr.drawNumber(angle+90, 15, 15, 4); // Plot number, in Sprite at 15,15 and with font 4 + spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent + num++; + } + + delay(8000); // Pause so we see it + + spr.deleteSprite(); + +} + +// ======================================================================================= +// Draw an X centered on x,y +// ======================================================================================= + +void drawX(int x, int y) +{ + tft.drawLine(x-5, y-5, x+5, y+5, TFT_WHITE); + tft.drawLine(x-5, y+5, x+5, y-5, TFT_WHITE); +} + +// ======================================================================================= +// Show a message at the top of the screen +// ======================================================================================= + +void showMessage(String msg) +{ + // Clear the screen areas + tft.fillRect(0, 0, tft.width(), 20, TFT_BLACK); + tft.fillRect(0, 20, tft.width(), tft.height()-20, TFT_BLUE); + + uint8_t td = tft.getTextDatum(); // Get current datum + + tft.setTextDatum(TC_DATUM); // Set new datum + + tft.drawString(msg, tft.width()/2, 2, 2); // Message in font 2 + + tft.setTextDatum(td); // Restore old datum +} + +// ======================================================================================= diff --git a/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino b/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino new file mode 100644 index 0000000..1dc5da7 --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino @@ -0,0 +1,181 @@ +// This example plots a rotated Sprite into another Sprite and then the resultant composited +// Sprite is pushed to the TFT screen. This example is for a 240 x 320 screen. + +// The motivation for developing this capability is that animated dials can be drawn easily +// and the complex calculations involved are handled by the TFT_eSPI library. To create a dial +// with a moving needle a graphic of a meter needle is plotted at a specified angle into another +// Sprite that contains the dial face. When the needle Sprite is pushed to the dial Sprite the +// plotting ensures two pivot points for each Sprite coincide with pixel level accuracy. + +// Two rotation pivot points must be set, one for the first Sprite and one for the second +// Sprite using setPivot(). These pivot points do not need to be within the Sprite boundaries. + +// In this example a needle graphic is also be plotted direct to a defined TFT pivot point. + +// The rotation angle is in degrees, an angle of 0 means no Sprite rotation. + +// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. + +// For 1 bpp Sprites the foreground and background colours are defined with the +// member function setBitmapColor(foregroundColor, backgroundColor). + +// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite dial = TFT_eSprite(&tft); // Sprite object for dial +TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle + +uint32_t startMillis; + +int16_t angle = 0; + +// ======================================================================================= +// Setup +// ======================================================================================= + +void setup() { + Serial.begin(250000); // Debug only + + tft.begin(); + tft.setRotation(1); + + // Clear TFT screen + tft.fillScreen(TFT_NAVY); + + // Create the dial Sprite and dial (this temporarily hijacks the use of the needle Sprite) + createDialScale(-120, 120, 30); // create scale (start angle, end angle, increment angle) + drawEmptyDial("Label", 12345); // draw the centre of dial in the Sprite + + dial.pushSprite(110, 0); // push a copy of the dial to the screen so we can see it + + // Create the needle Sprite + createNeedle(); // draw the needle graphic + needle.pushSprite(95, 7); // push a copy of the needle to the screen so we can see it +} + +// ======================================================================================= +// Loop +// ======================================================================================= + +void loop() { + + // Push the needle sprite to the dial Sprite at different angles and then push the dial to the screen + // Use angle increments in range 1 to 6 for smoother or faster movement + for (int16_t angle = -120; angle <= 120; angle += 2) { + plotDial(0, 0, angle, "RPM", angle + 120); + delay(25); + yield(); // Avoid a watchdog time-out + } + + delay(1000); // Pause + + // Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay + for (int16_t angle = 120; angle >= -120; angle -= 2) { + plotDial(0, 0, angle, "RPM", angle + 120); + yield(); // Avoid a watchdog time-out + } + + // Now show plotting of the rotated needle direct to the TFT + tft.setPivot(45, 150); // Set the TFT pivot point that the needle will rotate around + + // The needle graphic has a black border so if the angle increment is small + // (6 degrees or less in this case) it wipes the last needle position when + // it is rotated and hence it clears the swept area to black + for (int16_t angle = 0; angle <= 360; angle += 5) + { + needle.pushRotated(angle); // Plot direct to TFT at specifed angle + yield(); // Avoid a watchdog time-out + } +} + +// ======================================================================================= +// Create the dial sprite, the dial outer and place scale markers +// ======================================================================================= + +void createDialScale(int16_t start_angle, int16_t end_angle, int16_t increment) +{ + // Create the dial Sprite + dial.setColorDepth(8); // Size is odd (i.e. 91) so there is a centre pixel at 45,45 + dial.createSprite(91, 91); // 8bpp requires 91 * 91 = 8281 bytes + dial.setPivot(45, 45); // set pivot in middle of dial Sprite + + // Draw dial outline + dial.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour + dial.fillCircle(45, 45, 43, TFT_DARKGREY); // Draw dial outer + + // Hijack the use of the needle Sprite since that has not been used yet! + needle.createSprite(3, 3); // 3 pixels wide, 3 high + needle.fillSprite(TFT_WHITE); // Fill with white + needle.setPivot(1, 43); // Set pivot point x to the Sprite centre and y to marker radius + + for (int16_t angle = start_angle; angle <= end_angle; angle += increment) { + needle.pushRotated(&dial, angle); // Sprite is used to make scale markers + yield(); // Avoid a watchdog time-out + } + + needle.deleteSprite(); // Delete the hijacked Sprite +} + + +// ======================================================================================= +// Add the empty dial face with label and value +// ======================================================================================= + +void drawEmptyDial(String label, int16_t val) +{ + // Draw black face + dial.fillCircle(45, 45, 40, TFT_BLACK); + dial.drawPixel(45, 45, TFT_WHITE); // For demo only, mark pivot point with a while pixel + + dial.setTextDatum(TC_DATUM); // Draw dial text + dial.drawString(label, 45, 15, 2); + dial.drawNumber(val, 45, 60, 2); +} + +// ======================================================================================= +// Update the dial and plot to screen with needle at defined angle +// ======================================================================================= + +void plotDial(int16_t x, int16_t y, int16_t angle, String label, uint16_t val) +{ + // Draw the blank dial in the Sprite, add label and number + drawEmptyDial(label, val); + + // Push a rotated needle Sprite to the dial Sprite, with black as transparent colour + needle.pushRotated(&dial, angle, TFT_BLACK); // dial is the destination Sprite + + // Push the resultant dial Sprite to the screen, with transparent colour + dial.pushSprite(x, y, TFT_TRANSPARENT); +} + +// ======================================================================================= +// Create the needle Sprite and the image of the needle +// ======================================================================================= + +void createNeedle(void) +{ + needle.setColorDepth(8); + needle.createSprite(11, 49); // create the needle Sprite 11 pixels wide by 49 high + + needle.fillSprite(TFT_BLACK); // Fill with black + + // Define needle pivot point + uint16_t piv_x = needle.width() / 2; // x pivot of Sprite (middle) + uint16_t piv_y = needle.height() - 10; // y pivot of Sprite (10 pixels from bottom) + needle.setPivot(piv_x, piv_y); // Set pivot point in this Sprite + + // Draw the red needle with a yellow tip + // Keep needle tip 1 pixel inside dial circle to avoid leaving stray pixels + needle.fillRect(piv_x - 1, 2, 3, piv_y + 8, TFT_RED); + needle.fillRect(piv_x - 1, 2, 3, 5, TFT_YELLOW); + + // Draw needle centre boss + needle.fillCircle(piv_x, piv_y, 5, TFT_MAROON); + needle.drawPixel( piv_x, piv_y, TFT_WHITE); // Mark needle pivot point with a white pixel +} + +// ======================================================================================= diff --git a/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino new file mode 100644 index 0000000..835b1e2 --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino @@ -0,0 +1,140 @@ +/*==================================================================================== + + This example draws a jpeg image in a Sprite then plots a rotated copy of the Sprite + to the TFT. + + The jpeg used is in the sketch Data folder (presss Ctrl+K to see folder) + + The jpeg must be uploaded to the ESP8266 or ESP32 SPIFFS by using the Tools menu + sketch data upload option of the Arduino IDE. If you do not have that option it can + be added. Close the Serial Monitor window before uploading to avoid an error message! + + To add the upload option for the ESP8266 see: + http://www.esp8266.com/viewtopic.php?f=32&t=10081 + https://github.com/esp8266/arduino-esp8266fs-plugin/releases + + To add the upload option for the ESP32 see: + https://github.com/me-no-dev/arduino-esp32fs-plugin + + Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: + https://github.com/Bodmer/TFT_eSPI + + Extension funtions in the TFT_eFEX library are used to list SPIFFS files and render + the jpeg to the TFT and to the Sprite: + https://github.com/Bodmer/TFT_eFEX + + To render the Jpeg image the JPEGDecoder library is needed, this can be obtained + with the IDE library manager, or downloaded from here: + https://github.com/Bodmer/JPEGDecoder + + ==================================================================================*/ + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the SPIFFS FLASH filing system, this is part of the ESP Core +#define FS_NO_GLOBALS +#include + +#ifdef ESP32 +#include "SPIFFS.h" // Needed for ESP32 only +#endif + +// https://github.com/Bodmer/TFT_eSPI +#include // Hardware-specific library +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library +TFT_eSprite spr = TFT_eSprite(&tft); // Create Sprite object "spr" with pointer to "tft" object + +// https://github.com/Bodmer/TFT_eFEX +#include // Include the function extension library +TFT_eFEX fex = TFT_eFEX(&tft); // Create TFT_eFX object "fex" with pointer to "tft" object + + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(250000); // Used for messages + + tft.begin(); + tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape + tft.fillScreen(TFT_BLACK); + + // Create a sprite to hold the jpeg (or part of it) + spr.createSprite(80, 64); + + // Initialise SPIFFS + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nInitialisation done.\r\n"); + + // Lists the files so you can see what is in the SPIFFS + fex.listSPIFFS(); + + // Note the / before the SPIFFS file name must be present, this means the file is in + // the root directory of the SPIFFS, e.g. "/tiger.jpg" for a file called "tiger.jpg" + + // Send jpeg info to serial port + fex.jpegInfo("/Eye_80x64.jpg"); + + // Draw jpeg iamge in Sprite spr at 0,0 + fex.drawJpeg("/Eye_80x64.jpg", 0 , 0, &spr); +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + + tft.fillScreen(random(0xFFFF)); + + + // Set the TFT pivot point to the centre of the screen + tft.setPivot(tft.width() / 2, tft.height() / 2); + + // Set Sprite pivot point to centre of Sprite + spr.setPivot(spr.width() / 2, spr.height() / 2); + + // Push Sprite to the TFT at 0,0 (not rotated) + spr.pushSprite(0, 0); + + delay(1000); + + // Push copies of Sprite rotated through increasing angles 0-360 degrees + // with 45 fegree increments + for (int16_t angle = 0; angle <= 360; angle += 45) { + spr.pushRotated(angle); + delay(500); + } + + delay(2000); + + // Move Sprite pivot to a point above the image at 40,-60 + // (Note: Top left corner is Sprite coordinate 0,0) + // The TFT pivot point has already been set to middle of screen. + /* .Pivot point at 40,-60 + ^ + | + -60 + < 40 >| + ______V______ + | | + | Sprite | + |_____________| + */ + spr.setPivot(40, -60); + + // Push Sprite to screen rotated about the new pivot points + // negative angle rotates Sprite anticlockwise + for (int16_t angle = 330; angle >= 0; angle -= 30) { + spr.pushRotated(angle); + yield(); // Stop watchdog triggering + } + + delay(5000); +} +//==================================================================================== diff --git a/examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg b/examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg new file mode 100644 index 0000000000000000000000000000000000000000..240b7ef29a6c51eb18625778679b6bdac47be74f GIT binary patch literal 20838 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 literal 0 HcmV?d00001 diff --git a/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino new file mode 100644 index 0000000..b3bc967 --- /dev/null +++ b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino @@ -0,0 +1,139 @@ +// This **ONLY** works for 1 and 16 bpp Sprites due to lack of bounds checking in the +// Sprite pushImage() function for 8 bit Sprites (it is on the TO DO list) + +// Wrapping scroll example by Bodmer for the TFT_eSPI library + +//========================================================================================== + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite gfx = TFT_eSprite(&tft); // Sprite object for graphics write + +TFT_eSprite fb = TFT_eSprite(&tft); // Sprite object for frame buffer + +// Width and height of the Sprite +#define WIDTH 60 +#define HEIGHT 60 + +// Define scroll increment in x and y directions +// positive numbers = right, down +// negative numbers = left, up +#define XDELTA 1 +#define YDELTA 1 + +int16_t scroll_x = 0; // Keep track of the scrolled position, this is where the origin +int16_t scroll_y = 0; // (top left) of the gfx Sprite will be + +int16_t radius = 5; // radius of circle + +bool grow = true; // grow or shrink circle + +uint16_t *gfxPtr; // Pointer to start of graphics sprite memory area + +//========================================================================================== +//========================================================================================== + +void setup() { + Serial.begin(115200); + tft.init(); + tft.fillScreen(TFT_BLACK); + + tft.setRotation(1); + + //tft.invertDisplay(true); + + // Create a 1bpp sprite for the graphics + gfx.setColorDepth(1); + gfxPtr = (uint16_t*) gfx.createSprite(WIDTH, HEIGHT); // 480 bytes needed + gfx.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // Create a 1bpp sprite for the frame buffer + fb.setColorDepth(1); + fb.createSprite(WIDTH, HEIGHT); // 480 bytes needed + fb.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // Text colour and alignment in graphics Sprite + gfx.setTextColor(TFT_WHITE, TFT_BLACK); + gfx.setTextDatum(MC_DATUM); + + // Text colour and alignment in frame buffer + fb.setTextColor(TFT_WHITE, TFT_BLACK); + fb.setTextDatum(MC_DATUM); + + // Next 3 lines are for test only to see what we have drawn + drawGraphics(); // draw the graphics in the gfx sprite and copy to buffer + gfx.pushSprite(0, 0); // Plot to screen so we see what it looks like + delay(2000); +} + +//========================================================================================== +//========================================================================================== + +void loop() { +uint32_t tnow = millis(); + drawGraphics(); // Not needed if scrolling graphics are static + + wrappingScroll(XDELTA, YDELTA); + + // Plot two copies without "Hello", then one in the middle with "Hello" + //fb.setBitmapColor(TFT_WHITE, TFT_RED ); + fb.pushSprite(0, 0); // Plot frame buffer onto the TFT screen + //fb.setBitmapColor(TFT_WHITE, TFT_BLUE ); + fb.pushSprite(120, 0); // Plot frame buffer onto the TFT screen + + fb.drawString("Hello", 30, 20, 2); // Plot hello in frame buffer + //fb.setBitmapColor(TFT_BLACK, TFT_GREEN); + fb.pushSprite(60, 0); // Plot frame buffer in middle of other two + + //Serial.println(millis() - tnow); + delay(20); +} + +//========================================================================================== +// Draw graphics in the master Sprite +//========================================================================================== + +void drawGraphics(void) +{ + gfx.fillSprite(TFT_BLACK); // Clear sprite each time and completely redraw + + //gfx.drawRect(0,0,60,60,TFT_WHITE); // Test to check alignment + + gfx.drawCircle( 30 , 30, radius, TFT_WHITE); + if (grow) radius++; + else radius--; + + if ( radius > 25 ) grow = false; + if ( radius < 1 ) grow = true; + + gfx.drawString("World", 30, 40, 2); // Plot hello in frame buffer +} + +//========================================================================================== +// This function scrolls and wraps the graphic in a 1 bit per pixel Sprite, dy and dy +// control the scroll direction. Pixels that scroll off one side appear on the other. +// Scrolling is achieved by plotting one Sprite inside another with an offset. This has +// to be done by plotting 4 times into a second frame buffer Sprite. +//========================================================================================== +void wrappingScroll(int16_t dx, int16_t dy) +{ + // Position the quadrants so they overlap all areas of the buffer + scroll_x += dx; + if (scroll_x < -WIDTH) scroll_x += WIDTH; + if (scroll_x > 0) scroll_x -= WIDTH; + + scroll_y += dy; + if (scroll_y < -HEIGHT) scroll_y += HEIGHT; + if (scroll_y > 0) scroll_y -= HEIGHT; + + // push the 4 quadrants of gfx. sprite into the fb. sprite + // pushImage will do the cropping + fb.pushImage(scroll_x, scroll_y, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x + WIDTH, scroll_y, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x + WIDTH, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr); +} + +//========================================================================================== diff --git a/keywords.txt b/keywords.txt index 9fb1758..f89d981 100644 --- a/keywords.txt +++ b/keywords.txt @@ -74,11 +74,11 @@ textWidth KEYWORD2 fontHeight KEYWORD2 getTouchRaw KEYWORD2 +convertRawXY KEYWORD2 getTouchRawZ KEYWORD2 getTouch KEYWORD2 calibrateTouch KEYWORD2 setTouch KEYWORD2 -validTouch KEYWORD2 TFT_eSPI_Button KEYWORD1 @@ -97,7 +97,13 @@ TFT_eSprite KEYWORD1 createSprite KEYWORD2 setColorDepth KEYWORD2 +getColorDepth KEYWORD2 deleteSprite KEYWORD2 +pushRotated KEYWORD2 +rotatedBounds KEYWORD2 +setPivot KEYWORD2 +getPivotX KEYWORD2 +getPivotY KEYWORD2 fillSprite KEYWORD2 pushBitmap KEYWORD2 pushSprite KEYWORD2 diff --git a/library.json b/library.json index 5d937f3..705fcb9 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.10", + "version": "1.3.11", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 8517311..82d9492 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.10 +version=1.3.11 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 05359a4dffbe3999b1fd6a800479119e34eede03 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 6 Jan 2019 17:45:06 +0000 Subject: [PATCH 64/94] Misc updates Speed up Sprite rotation on an ESP32 Update utf8 serial decoder to handle illegal format strings Remove need for D0_USED_FOR_xx (issue #271) Clean up setup files Correct various comment typos --- Extensions/Smooth_font.cpp | 11 +- Extensions/Sprite.cpp | 3 +- TFT_eSPI.h | 4 +- User_Setup.h | 44 ++-- User_Setups/Setup10_RPi_touch_ILI9486.h | 189 +------------- User_Setups/Setup11_RPi_touch_ILI9486.h | 191 +------------- User_Setups/Setup12_M5Stack.h | 195 +-------------- User_Setups/Setup13_ILI9481_Parallel.h | 66 +---- User_Setups/Setup14_ILI9341_Parallel.h | 64 +---- User_Setups/Setup15_HX8357D.h | 194 +-------------- User_Setups/Setup16_ILI9488_Parallel.h | 64 +---- User_Setups/Setup17_ePaper.h | 56 +---- User_Setups/Setup18_ST7789.h | 233 +----------------- User_Setups/Setup1_ILI9341.h | 197 +-------------- User_Setups/Setup20_ILI9488.h | 195 +-------------- User_Setups/Setup21_ILI9488.h | 198 +-------------- User_Setups/Setup22_TTGO_T4.h | 7 +- User_Setups/Setup23_TTGO_TM.h | 6 +- User_Setups/Setup2_ST7735.h | 187 +------------- User_Setups/Setup3_ILI9163.h | 188 +------------- User_Setups/Setup43_ST7735.h | 199 +-------------- User_Setups/Setup4_S6D02A1.h | 192 +-------------- User_Setups/Setup5_RPi_ILI9486.h | 193 +-------------- User_Setups/Setup6_RPi_Wr_ILI9486.h | 189 +------------- User_Setups/Setup7_ST7735_128x128.h | 185 +------------- User_Setups/Setup8_ILI9163_128x128.h | 185 +------------- User_Setups/Setup9_ST7735_Overlap.h | 181 +------------- User_Setups/SetupX_Template.h | 44 ++-- User_Setups/User_Custom_Fonts.h | 5 +- .../Rotated_Sprite_3/Rotated_Sprite_3.ino | 4 +- .../Sprite_scroll_wrap_1bit.ino | 12 +- library.json | 2 +- library.properties | 2 +- 33 files changed, 123 insertions(+), 3562 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index fe77885..3dc2cb0 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -282,11 +282,15 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c) { #ifdef DECODE_UTF8 + + // 7 bit Unicode + if ((c & 0x80) == 0x00) { + decoderState = 0; + return (uint16_t)c; + } + if (decoderState == 0) { - // 7 bit Unicode - if ((c & 0x80) == 0x00) return (uint16_t)c; - // 11 bit Unicode if ((c & 0xE0) == 0xC0) { @@ -322,6 +326,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c) } #endif + decoderState = 0; return (uint16_t)c; // fall-back to extended ASCII } diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index e74864b..0102320 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -301,7 +301,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) if (max_x > _tft->width()) max_x = _tft->width(); if (max_y > _tft->height()) max_y = _tft->height(); - + _tft->startWrite(); // Scan destination bounding box and fetch transformed pixels from source Sprite for (int32_t x = min_x; x <= max_x; x++) { int32_t xt = x - _tft->_xpivot; @@ -325,6 +325,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) else if (column_drawn) y = max_y; // Skip remaining column pixels } } + _tft->endWrite(); return true; } diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 48b9f48..1422fb4 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -122,7 +122,7 @@ #define DC_C // No macro allocated so it generates no code #define DC_D // No macro allocated so it generates no code #else - #if defined (ESP8266) && defined (D0_USED_FOR_DC) + #if defined (ESP8266) && (TFT_DC == 16) #define DC_C digitalWrite(TFT_DC, LOW) #define DC_D digitalWrite(TFT_DC, HIGH) #elif defined (ESP32) @@ -172,7 +172,7 @@ #define CS_L // No macro allocated so it generates no code #define CS_H // No macro allocated so it generates no code #else - #if defined (ESP8266) && defined (D0_USED_FOR_CS) + #if defined (ESP8266) && (TFT_CS == 16) #define CS_L digitalWrite(TFT_CS, LOW) #define CS_H digitalWrite(TFT_CS, HIGH) #elif defined (ESP32) diff --git a/User_Setup.h b/User_Setup.h index b27e1a7..e43b749 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -8,9 +8,10 @@ // run without the need to make any more changes for a particular hardware setup! // Note that some sketches are designed for a particular TFT pixel width/height + // ################################################################################## // -// Section 0. Call up the right driver file and any options for it +// Section 1. Call up the right driver file and any options for it // // ################################################################################## @@ -32,13 +33,14 @@ // To use the SDA line for reading data from the TFT uncomment the following line: // #define TFT_SDA_READ -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - // For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + // For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation // #define TFT_WIDTH 80 // #define TFT_WIDTH 128 @@ -70,9 +72,10 @@ //#define TFT_INVERSION_ON //#define TFT_INVERSION_OFF + // ################################################################################## // -// Section 1. Define the pins that are used to interface with the display here +// Section 2. Define the pins that are used to interface with the display here // // ################################################################################## @@ -150,6 +153,7 @@ //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + //#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) //#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen @@ -179,11 +183,11 @@ // The ESP32 and TFT the pins used for testing are: //#define TFT_CS 33 // Chip select control pin (library pulls permanently low -//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 //#define TFT_RST 32 // Reset pin, toggles on startup -//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 -//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 +//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin //#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus //#define TFT_D1 13 // so a single register write sets/clears all bits. @@ -194,20 +198,6 @@ //#define TFT_D6 27 //#define TFT_D7 14 -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS // ################################################################################## // @@ -233,16 +223,10 @@ // this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - // ################################################################################## // -// Section 5. Other options +// Section 4. Other options // // ################################################################################## @@ -278,4 +262,4 @@ // Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) // so changing it here has no effect -//#define SUPPORT_TRANSACTIONS +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup10_RPi_touch_ILI9486.h b/User_Setups/Setup10_RPi_touch_ILI9486.h index bbfe895..8e59a6b 100644 --- a/User_Setups/Setup10_RPi_touch_ILI9486.h +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -1,86 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -90,75 +11,6 @@ #define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -166,53 +18,14 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup11_RPi_touch_ILI9486.h b/User_Setups/Setup11_RPi_touch_ILI9486.h index cbb489b..e2edbb3 100644 --- a/User_Setups/Setup11_RPi_touch_ILI9486.h +++ b/User_Setups/Setup11_RPi_touch_ILI9486.h @@ -1,117 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 -//#define TFT_DC PIN_D3 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins #define TFT_MISO 19 #define TFT_MOSI 23 @@ -123,43 +13,6 @@ #define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen -//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -167,53 +20,11 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup12_M5Stack.h b/User_Setups/Setup12_M5Stack.h index 3439512..d4b50b8 100644 --- a/User_Setups/Setup12_M5Stack.h +++ b/User_Setups/Setup12_M5Stack.h @@ -1,131 +1,11 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below + #define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 -//#define TFT_DC PIN_D3 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines #define TFT_MISO 19 #define TFT_MOSI 23 #define TFT_SCLK 18 @@ -134,31 +14,6 @@ #define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) #define TFT_BL 32 // LED back-light -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -166,53 +21,9 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 - -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: -#define SPI_TOUCH_FREQUENCY 2500000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS +#define SPI_FREQUENCY 27000000 diff --git a/User_Setups/Setup13_ILI9481_Parallel.h b/User_Setups/Setup13_ILI9481_Parallel.h index 0de1ebd..1758420 100644 --- a/User_Setups/Setup13_ILI9481_Parallel.h +++ b/User_Setups/Setup13_ILI9481_Parallel.h @@ -1,37 +1,17 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Parallel bus is only supported on ESP32 -// Use ESP32 Parallel interface instead of SPI #define ESP32_PARALLEL -// Only define one driver, the other ones must be commented out + #define ILI9481_DRIVER -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// ESP32 pins used +// ESP32 pins used for UNO format board #define TFT_CS 33 // Chip select control pin -#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 #define TFT_RST 32 // Reset pin -#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 #define TFT_RD 2 #define TFT_D0 12 // Must use pins in the range 0-31 for the data bus @@ -44,48 +24,12 @@ #define TFT_D7 14 -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT - -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - - diff --git a/User_Setups/Setup14_ILI9341_Parallel.h b/User_Setups/Setup14_ILI9341_Parallel.h index d777264..d19a827 100644 --- a/User_Setups/Setup14_ILI9341_Parallel.h +++ b/User_Setups/Setup14_ILI9341_Parallel.h @@ -1,37 +1,17 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Parallel bus is only supported on ESP32 -// Use ESP32 Parallel interface instead of SPI #define ESP32_PARALLEL -// Only define one driver, the other ones must be commented out + #define ILI9341_DRIVER -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## // ESP32 pins used for the parallel interface TFT #define TFT_CS 33 // Chip select control pin -#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 #define TFT_RST 32 // Reset pin -#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 #define TFT_RD 2 #define TFT_D0 12 // Must use pins in the range 0-31 for the data bus @@ -44,48 +24,12 @@ #define TFT_D7 14 -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT - -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - - diff --git a/User_Setups/Setup15_HX8357D.h b/User_Setups/Setup15_HX8357D.h index 99ae1d6..f4ee614 100644 --- a/User_Setups/Setup15_HX8357D.h +++ b/User_Setups/Setup15_HX8357D.h @@ -1,87 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI #define HX8357D_DRIVER -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -89,77 +9,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -167,53 +16,16 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup16_ILI9488_Parallel.h b/User_Setups/Setup16_ILI9488_Parallel.h index bcaca48..5d3cb58 100644 --- a/User_Setups/Setup16_ILI9488_Parallel.h +++ b/User_Setups/Setup16_ILI9488_Parallel.h @@ -1,37 +1,17 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Parallel bus is only supported on ESP32 -// Use ESP32 Parallel interface instead of SPI #define ESP32_PARALLEL -// Only define one driver, the other ones must be commented out + #define ILI9488_DRIVER -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## // ESP32 pins used #define TFT_CS 33 // Chip select control pin -#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 #define TFT_RST 32 // Reset pin -#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 #define TFT_RD 2 #define TFT_D0 12 // Must use pins in the range 0-31 for the data bus @@ -44,48 +24,12 @@ #define TFT_D7 14 -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT - -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - - diff --git a/User_Setups/Setup17_ePaper.h b/User_Setups/Setup17_ePaper.h index 3704cc5..86d0e65 100644 --- a/User_Setups/Setup17_ePaper.h +++ b/User_Setups/Setup17_ePaper.h @@ -1,26 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! - -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## +// See SetupX_Template.h for all options available #define EPD_DRIVER // ePaper driver -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - // READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS // Install the ePaper library for your own display size and type @@ -48,47 +29,12 @@ /////////////////////////////////////////////////////////////////// -// ################################################################################## -// -// Section 2. Not used -// -// ################################################################################## - - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 below, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT - -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - - -// ################################################################################## -// -// Section 5. Not used -// -// ################################################################################## - diff --git a/User_Setups/Setup18_ST7789.h b/User_Setups/Setup18_ST7789.h index 6a6f5ac..25d57a3 100644 --- a/User_Setups/Setup18_ST7789.h +++ b/User_Setups/Setup18_ST7789.h @@ -1,204 +1,17 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! -// Note that some sketches are designed for a particular TFT pixel width/height +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -//#define HX8357D_DRIVER -//#define ILI9481_DRIVER -//#define ILI9488_DRIVER #define ST7789_DRIVER -// Some displays support SPI reads via the MISO pin, if the display has a single -// bi-directional SDA pin the library will try to use bit banging to read the line -// To use the SDA line for reading data from the TFT uncomment the following line: + #define TFT_SDA_READ -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### +// My ST7789 display has TCT_CS wired permananently low so the pin is not defined here // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### - -// The library supports 8 bit parallel TFTs with the ESP32, the pin -// selection below is compatible with ESP32 boards in UNO format. -// Wemos D32 boards need to be modified, see diagram in Tools folder. -// Only ILI9481 and ILI9341 based displays have been tested! - -// Parallel bus is only supported on ESP32 -// Uncomment line below to use ESP32 Parallel interface instead of SPI - -//#define ESP32_PARALLEL - -// The ESP32 and TFT the pins used for testing are: -//#define TFT_CS 33 // Chip select control pin (library pulls permanently low -//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 -//#define TFT_RST 32 // Reset pin, toggles on startup - -//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 -//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 - -//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus -//#define TFT_D1 13 // so a single register write sets/clears all bits. -//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect -//#define TFT_D3 25 // TFT screen update performance. -//#define TFT_D4 17 -//#define TFT_D5 16 -//#define TFT_D6 27 -//#define TFT_D7 14 - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -206,53 +19,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - //#define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup1_ILI9341.h b/User_Setups/Setup1_ILI9341.h index 1f02b38..82d69c5 100644 --- a/User_Setups/Setup1_ILI9341.h +++ b/User_Setups/Setup1_ILI9341.h @@ -1,164 +1,13 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI - -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -166,55 +15,19 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH + #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -#define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 27000000 +#define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 #define SPI_READ_FREQUENCY 20000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup20_ILI9488.h b/User_Setups/Setup20_ILI9488.h index ada2eee..7d1eaf1 100644 --- a/User_Setups/Setup20_ILI9488.h +++ b/User_Setups/Setup20_ILI9488.h @@ -1,87 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI #define ILI9488_DRIVER -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (leave TFT SDO disconnected if other SPI devices share MISO) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -89,77 +9,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -167,53 +16,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 + -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h index b00d02a..1a39a02 100644 --- a/User_Setups/Setup21_ILI9488.h +++ b/User_Setups/Setup21_ILI9488.h @@ -1,121 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -//#define HX8357D_DRIVER -//#define ILI9481_DRIVER -//#define ILI9486_DRIVER #define ILI9488_DRIVER -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (leave TFT SDO disconnected if other SPI devices share MISO) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 -//#define TFT_DC PIN_D3 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins #define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) #define TFT_MOSI 23 @@ -123,46 +9,7 @@ #define TFT_CS 15 // Chip select control pin #define TFT_DC 2 // Data Command control pin #define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -170,53 +17,14 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup22_TTGO_T4.h b/User_Setups/Setup22_TTGO_T4.h index fa04323..cfed5b5 100644 --- a/User_Setups/Setup22_TTGO_T4.h +++ b/User_Setups/Setup22_TTGO_T4.h @@ -1,5 +1,7 @@ // Setup for the TTGO T4 ("Bitcoin Tracker") ESP32 board with 2.2" ILI9341 display +// See SetupX_Template.h for all options available + #define ILI9341_DRIVER #define TFT_MISO 12 @@ -20,9 +22,8 @@ #define SMOOTH_FONT -//#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +//#define SPI_FREQUENCY 27000000 #define SPI_FREQUENCY 40000000 // Maximum for ILI9341 -#define SPI_TOUCH_FREQUENCY 2500000 -#define SPI_READ_FREQUENCY 10000000 +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V diff --git a/User_Setups/Setup23_TTGO_TM.h b/User_Setups/Setup23_TTGO_TM.h index 74c9a05..58468d5 100644 --- a/User_Setups/Setup23_TTGO_TM.h +++ b/User_Setups/Setup23_TTGO_TM.h @@ -1,5 +1,7 @@ // Setup for the TTGO TM (Music) ESP32 board with 2.4" ST7789V display +// See SetupX_Template.h for all options available + #define ST7789_DRIVER #define TFT_SDA_READ // Read from display, it only provides an SDA pin @@ -28,7 +30,7 @@ #define SMOOTH_FONT -#define SPI_FREQUENCY 40000000 // The display also seems to work reliably at 80MHz +#define SPI_FREQUENCY 40000000 // This display also seems to work reliably at 80MHz +#define SPI_FREQUENCY 80000000 #define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V - diff --git a/User_Setups/Setup2_ST7735.h b/User_Setups/Setup2_ST7735.h index 7f79ca8..b9e618f 100644 --- a/User_Setups/Setup2_ST7735.h +++ b/User_Setups/Setup2_ST7735.h @@ -1,164 +1,21 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display #define ST7735_REDTAB -//#define ST7735_BLACKTAB -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +26,14 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup3_ILI9163.h b/User_Setups/Setup3_ILI9163.h index e8bd1b2..f9b2656 100644 --- a/User_Setups/Setup3_ILI9163.h +++ b/User_Setups/Setup3_ILI9163.h @@ -1,86 +1,11 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER #define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -88,77 +13,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +23,14 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup43_ST7735.h b/User_Setups/Setup43_ST7735.h index efe20f3..8865f54 100644 --- a/User_Setups/Setup43_ST7735.h +++ b/User_Setups/Setup43_ST7735.h @@ -1,127 +1,16 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// Setup for ESP32 and ST7735 80 x 160 TFT -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## +// See SetupX_Template.h for all options available -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 80 -//#define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB #define ST7735_GREENTAB160x80 -//#define ST7735_REDTAB160x80 -// If colours are inverted (white shows as black) then uncomment one of these -// Try both options, one of the options should correct the inversion. -//#define TFT_INVERSION_ON -//#define TFT_INVERSION_OFF - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 -//#define TFT_DC PIN_D3 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins #define TFT_MISO 19 #define TFT_MOSI 23 @@ -131,44 +20,6 @@ #define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -179,50 +30,8 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 - -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: -#define SPI_TOUCH_FREQUENCY 2500000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS +//#define SPI_FREQUENCY 20000000 + #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 diff --git a/User_Setups/Setup4_S6D02A1.h b/User_Setups/Setup4_S6D02A1.h index 0a1530b..233117c 100644 --- a/User_Setups/Setup4_S6D02A1.h +++ b/User_Setups/Setup4_S6D02A1.h @@ -1,86 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER #define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -88,77 +9,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +19,14 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup5_RPi_ILI9486.h b/User_Setups/Setup5_RPi_ILI9486.h index c21e181..ba21c31 100644 --- a/User_Setups/Setup5_RPi_ILI9486.h +++ b/User_Setups/Setup5_RPi_ILI9486.h @@ -1,164 +1,14 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -166,53 +16,14 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup6_RPi_Wr_ILI9486.h b/User_Setups/Setup6_RPi_Wr_ILI9486.h index e5c9303..abeaddb 100644 --- a/User_Setups/Setup6_RPi_Wr_ILI9486.h +++ b/User_Setups/Setup6_RPi_Wr_ILI9486.h @@ -1,86 +1,7 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK - -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -88,131 +9,23 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - #define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup7_ST7735_128x128.h b/User_Setups/Setup7_ST7735_128x128.h index 3bb32cf..6821f47 100644 --- a/User_Setups/Setup7_ST7735_128x128.h +++ b/User_Setups/Setup7_ST7735_128x128.h @@ -1,86 +1,14 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 #define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -88,77 +16,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +26,14 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH + #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup8_ILI9163_128x128.h b/User_Setups/Setup8_ILI9163_128x128.h index 05b7cb6..da42ec3 100644 --- a/User_Setups/Setup8_ILI9163_128x128.h +++ b/User_Setups/Setup8_ILI9163_128x128.h @@ -1,86 +1,11 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER #define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 @@ -88,77 +13,6 @@ #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -// In ESP8266 overlap mode the following must be defined -//#define TFT_SPI_OVERLAP - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +23,13 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup9_ST7735_Overlap.h b/User_Setups/Setup9_ST7735_Overlap.h index 57f9019..2237893 100644 --- a/User_Setups/Setup9_ST7735_Overlap.h +++ b/User_Setups/Setup9_ST7735_Overlap.h @@ -1,103 +1,14 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display #define ST7735_REDTAB -//#define ST7735_BLACKTAB -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -//#define TFT_CS PIN_D8 // Chip select control pin D8 -//#define TFT_DC PIN_D3 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. -// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode // In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 #define TFT_CS PIN_D3 @@ -108,57 +19,6 @@ // In ESP8266 overlap mode the following must be defined #define TFT_SPI_OVERLAP -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -169,50 +29,13 @@ //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. -// The RPi typically only works at 20MHz maximum. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 7d6ef8b..59eef66 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -8,9 +8,10 @@ // run without the need to make any more changes for a particular hardware setup! // Note that some sketches are designed for a particular TFT pixel width/height + // ################################################################################## // -// Section 0. Call up the right driver file and any options for it +// Section 1. Call up the right driver file and any options for it // // ################################################################################## @@ -71,9 +72,10 @@ //#define TFT_INVERSION_ON //#define TFT_INVERSION_OFF + // ################################################################################## // -// Section 1. Define the pins that are used to interface with the display here +// Section 2. Define the pins that are used to interface with the display here // // ################################################################################## @@ -152,9 +154,11 @@ //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -//#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen +//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) -//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only // For the M5Stack module use these #define lines //#define TFT_MISO 19 @@ -163,7 +167,7 @@ //#define TFT_CS 14 // Chip select control pin //#define TFT_DC 27 // Data Command control pin //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light (if needed) +//#define TFT_BL 32 // LED back-light (required for M5Stack) // ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### @@ -178,12 +182,12 @@ //#define ESP32_PARALLEL // The ESP32 and TFT the pins used for testing are: -//#define TFT_CS 33 // Chip select control pin (library pulls permanently low -//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low) +//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 //#define TFT_RST 32 // Reset pin, toggles on startup -//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 -//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 +//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin //#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus //#define TFT_D1 13 // so a single register write sets/clears all bits. @@ -194,20 +198,6 @@ //#define TFT_D6 27 //#define TFT_D7 14 -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS // ################################################################################## // @@ -225,20 +215,14 @@ #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts // Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded // this will save ~20kbytes of FLASH #define SMOOTH_FONT -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## - // ################################################################################## // diff --git a/User_Setups/User_Custom_Fonts.h b/User_Setups/User_Custom_Fonts.h index ef9e0ae..f2dc3d3 100644 --- a/User_Setups/User_Custom_Fonts.h +++ b/User_Setups/User_Custom_Fonts.h @@ -13,9 +13,10 @@ ^^^^ */ -// When font files are placed in the Custom folder then they must also be #included here: +// When font files are placed in the Custom folder (TFT_eSPI\Fonts\Custom) then they must +// also be #included here: -// The comment added is a shorthand reference but this is not essential +// The CF_OL24 etc are a shorthand reference, but this is not essential to use the fonts #ifdef LOAD_GFXFF diff --git a/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino index 835b1e2..8e8e72b 100644 --- a/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino +++ b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino @@ -1,9 +1,9 @@ /*==================================================================================== - This example draws a jpeg image in a Sprite then plots a rotated copy of the Sprite + This example draws a jpeg image in a Sprite then plot a rotated copy of the Sprite to the TFT. - The jpeg used is in the sketch Data folder (presss Ctrl+K to see folder) + The jpeg used in in the sketch Data folder (presss Ctrl+K to see folder) The jpeg must be uploaded to the ESP8266 or ESP32 SPIFFS by using the Tools menu sketch data upload option of the Arduino IDE. If you do not have that option it can diff --git a/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino index b3bc967..76fcfc6 100644 --- a/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino +++ b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino @@ -1,5 +1,5 @@ -// This **ONLY** works for 1 and 16 bpp Sprites due to lack of bounds checking in the -// Sprite pushImage() function for 8 bit Sprites (it is on the TO DO list) +// This **ONLY** works for 1 bpp Sprites due to lack of bounds checking in the +// Sprite pushImage() function for 8 and 16 bit Sprites (it is on the TO DO list) // Wrapping scroll example by Bodmer for the TFT_eSPI library @@ -44,14 +44,14 @@ void setup() { //tft.invertDisplay(true); - // Create a 1bpp sprite for the graphics + // Create a sprite for the graphics gfx.setColorDepth(1); - gfxPtr = (uint16_t*) gfx.createSprite(WIDTH, HEIGHT); // 480 bytes needed + gfxPtr = (uint16_t*) gfx.createSprite(WIDTH, HEIGHT); // 450 bytes needed gfx.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created - // Create a 1bpp sprite for the frame buffer + // Create a sprite for the frame buffer fb.setColorDepth(1); - fb.createSprite(WIDTH, HEIGHT); // 480 bytes needed + fb.createSprite(WIDTH, HEIGHT); // 450 bytes needed fb.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created // Text colour and alignment in graphics Sprite diff --git a/library.json b/library.json index 705fcb9..fec1a93 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.11", + "version": "1.3.12", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 82d9492..000edb4 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.11 +version=1.3.12 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 4e6736e5965d06865d3cab6631f9ed78f4690965 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 6 Jan 2019 19:03:31 +0000 Subject: [PATCH 65/94] Add backlight support The backlight control pin and ON state can be defined in the setup.h file. Addresses #229, #226, #221 Comments updated and ILI9488 warning added. --- TFT_Drivers/ILI9341_Init.h | 6 ----- TFT_eSPI.cpp | 11 ++++++++ User_Setup.h | 39 ++++++++++++++++++---------- User_Setups/SetupX_Template.h | 49 +++++++++++++++++++++-------------- library.json | 2 +- library.properties | 2 +- 6 files changed, 68 insertions(+), 41 deletions(-) diff --git a/TFT_Drivers/ILI9341_Init.h b/TFT_Drivers/ILI9341_Init.h index 124c849..404c3b9 100644 --- a/TFT_Drivers/ILI9341_Init.h +++ b/TFT_Drivers/ILI9341_Init.h @@ -121,10 +121,4 @@ writecommand(ILI9341_DISPON); //Display on -#ifdef M5STACK - // Turn on the back-light LED - digitalWrite(TFT_BL, HIGH); - pinMode(TFT_BL, OUTPUT); -#endif - } \ No newline at end of file diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index a20cee4..fae609a 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -327,6 +327,17 @@ void TFT_eSPI::init(uint8_t tc) writecommand(TFT_SWRST); // Software reset #endif +#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON) + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); + pinMode(TFT_BL, OUTPUT); +#else + #if defined (TFT_BL) && defined (M5STACK) + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); + #endif +#endif + spi_end(); delay(150); // Wait for reset to complete diff --git a/User_Setup.h b/User_Setup.h index e43b749..6a5531e 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -17,29 +17,32 @@ // Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER +//#define ST7735_DRIVER // Define additional parameters below for this display +//#define ILI9163_DRIVER // Define additional parameters below for this display //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI //#define HX8357D_DRIVER //#define ILI9481_DRIVER //#define ILI9486_DRIVER -//#define ILI9488_DRIVER -//#define ST7789_DRIVER // Define the screen size below for this display +//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) +//#define ST7789_DRIVER // Define additional parameters below for this display //#define R61581_DRIVER -// Some displays support SPI reads via the MISO pin, if the display has a single -// bi-directional SDA pin the library will try to use bit banging to read the line +// Some displays support SPI reads via the MISO pin, other displays have a single +// bi-directional SDA pin and the library will try to read this via the MOSI line. // To use the SDA line for reading data from the TFT uncomment the following line: -// #define TFT_SDA_READ + +// #define TFT_SDA_READ // This option if for ESP32 ONLY, tested with ST7789 display only // For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display // Try ONE option at a time to find the correct colour order for your display -//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue -//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below + +// #define M5STACK // For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation // #define TFT_WIDTH 80 @@ -65,13 +68,21 @@ // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) // #define ST7735_REDTAB // #define ST7735_BLACKTAB -// #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) +// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset // If colours are inverted (white shows as black) then uncomment one of the next // 2 lines try both options, one of the options should correct the inversion. -//#define TFT_INVERSION_ON -//#define TFT_INVERSION_OFF +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + +// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options // ################################################################################## // diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 59eef66..6a5531e 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -17,29 +17,32 @@ // Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER +//#define ST7735_DRIVER // Define additional parameters below for this display +//#define ILI9163_DRIVER // Define additional parameters below for this display //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI //#define HX8357D_DRIVER //#define ILI9481_DRIVER //#define ILI9486_DRIVER -//#define ILI9488_DRIVER -//#define ST7789_DRIVER // Define the screen size below for this display +//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) +//#define ST7789_DRIVER // Define additional parameters below for this display //#define R61581_DRIVER -// Some displays support SPI reads via the MISO pin, if the display has a single -// bi-directional SDA pin the library will try to use bit banging to read the line +// Some displays support SPI reads via the MISO pin, other displays have a single +// bi-directional SDA pin and the library will try to read this via the MOSI line. // To use the SDA line for reading data from the TFT uncomment the following line: -// #define TFT_SDA_READ -// For ST7789 ONLY, define the colour order if the blue and red are swapped on your display +// #define TFT_SDA_READ // This option if for ESP32 ONLY, tested with ST7789 display only + +// For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display // Try ONE option at a time to find the correct colour order for your display -//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue -//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red -// For M5Stack ESP32 module with integrated display ONLY, remove // in line below -//#define M5STACK +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below + +// #define M5STACK // For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation // #define TFT_WIDTH 80 @@ -65,13 +68,21 @@ // #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) // #define ST7735_REDTAB // #define ST7735_BLACKTAB -// #define ST7735_REDTAB160x80 // For 160 x 80 display (24 offset) (https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html) +// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset // If colours are inverted (white shows as black) then uncomment one of the next // 2 lines try both options, one of the options should correct the inversion. -//#define TFT_INVERSION_ON -//#define TFT_INVERSION_OFF +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + +// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options // ################################################################################## // @@ -120,7 +131,7 @@ //#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) -//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen //#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only @@ -182,7 +193,7 @@ //#define ESP32_PARALLEL // The ESP32 and TFT the pins used for testing are: -//#define TFT_CS 33 // Chip select control pin (library pulls permanently low) +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low //#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 //#define TFT_RST 32 // Reset pin, toggles on startup @@ -214,7 +225,7 @@ #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. //#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts @@ -226,7 +237,7 @@ // ################################################################################## // -// Section 5. Other options +// Section 4. Other options // // ################################################################################## diff --git a/library.json b/library.json index fec1a93..640cef0 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.12", + "version": "1.3.13", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 000edb4..7f4f52c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.12 +version=1.3.13 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From b5db54dc79cd5ee7b0ceb1d9f4be7042b3163ac9 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 22 Jan 2019 11:46:04 +0000 Subject: [PATCH 66/94] Fix #293 for ESP8266 core 2.4.2 and later UTFT8 encoded Unicode values were not being drawn on screen with versions after 2.4.1 of the ESP8266 core. --- TFT_eSPI.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index fae609a..f1fb2c4 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -3906,14 +3906,14 @@ size_t TFT_eSPI::write(uint8_t utf8) if(fontLoaded) { uint16_t unicode = decodeUTF8(utf8); - if (!unicode) return 0; + if (!unicode) return 1; //fontFile = SPIFFS.open( _gFontFilename, "r" ); //if(!fontFile) //{ // fontLoaded = false; - // return 0; + // return 1; //} drawGlyph(unicode); @@ -3925,7 +3925,7 @@ size_t TFT_eSPI::write(uint8_t utf8) uint8_t uniCode = utf8; // Work with a copy if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (utf8 < 32) return 0; + else if (utf8 < 32) return 1; uint16_t width = 0; uint16_t height = 0; @@ -3945,7 +3945,7 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { - if (utf8 > 127) return 0; + if (utf8 > 127) return 1; // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; @@ -3962,7 +3962,7 @@ size_t TFT_eSPI::write(uint8_t utf8) { if ((textfont>2) && (textfont<9)) { - if (utf8 > 127) return 0; + if (utf8 > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements // A tad slower than above but this is not significant and is more convenient for the RLE fonts width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); @@ -3978,7 +3978,7 @@ size_t TFT_eSPI::write(uint8_t utf8) height = 8; } #else - if (textfont==1) return 0; + if (textfont==1) return 1; #endif height = height * textsize; @@ -4009,8 +4009,8 @@ size_t TFT_eSPI::write(uint8_t utf8) cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } else { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 0; - if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 0; + if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; + if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); From 8cf85c89d33390107c1a879fbe6d83efab692390 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 22 Jan 2019 12:10:13 +0000 Subject: [PATCH 67/94] Fix #293 for Sprites --- Extensions/Sprite.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 0102320..615f2ab 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -1311,7 +1311,7 @@ size_t TFT_eSprite::write(uint8_t utf8) if(this->fontLoaded) { uint16_t unicode = decodeUTF8(utf8); - if (unicode < 32 && utf8 != '\n') return 0; + if (unicode < 32 && utf8 != '\n') return 1; //fontFile = SPIFFS.open( _gFontFilename, "r" ); //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); @@ -1319,22 +1319,22 @@ size_t TFT_eSprite::write(uint8_t utf8) //if(!fontFile) //{ // fontLoaded = false; - // return 0; + // return 1; //} //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); drawGlyph(unicode); //fontFile.close(); - return 0; + return 1; } #endif - if (!_created ) return 0; + if (!_created ) return 1; uint8_t uniCode = utf8; // Work with a copy if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (utf8 < 32) return 0; + else if (utf8 < 32) return 1; uint16_t width = 0; uint16_t height = 0; @@ -1354,7 +1354,7 @@ size_t TFT_eSprite::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { - if (utf8 > 127) return 0; + if (utf8 > 127) return 1; // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; @@ -1371,7 +1371,7 @@ size_t TFT_eSprite::write(uint8_t utf8) { if ((textfont>2) && (textfont<9)) { - if (utf8 > 127) return 0; + if (utf8 > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements // A tad slower than above but this is not significant and is more convenient for the RLE fonts width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); @@ -1387,7 +1387,7 @@ size_t TFT_eSprite::write(uint8_t utf8) height = 8; } #else - if (textfont==1) return 0; + if (textfont==1) return 1; #endif height = height * textsize; @@ -1418,8 +1418,8 @@ size_t TFT_eSprite::write(uint8_t utf8) this->cursor_x = 0; this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } else { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 0; - if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 0; + if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; + if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); From 0fdd25186ae65a132904fbac1d3cd9387572d20c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 22 Jan 2019 17:43:31 +0000 Subject: [PATCH 68/94] Fix #289 A 16 bit color image can now be plotted into an 8 bit Sprite. --- Extensions/Sprite.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 615f2ab..abf0163 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -587,6 +587,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 uint16_t color = data[xp + yp * w]; if(_iswapBytes) color = color<<8 | color>>8; _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + x++; } ys++; } @@ -679,6 +680,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t color = pgm_read_word(data + xp + yp * w); if(_iswapBytes) color = color<<8 | color>>8; _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + x++; } ys++; } From 054a824eb824771a5836dcd56499002eadaee6b2 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 22 Jan 2019 18:41:31 +0000 Subject: [PATCH 69/94] Add ESP32 VSPI or HSPI port option + others If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) then add or uncomment the following line in the setup header file: //#define USE_HSPI_PORT Minor performance tweaks for ESP32 to minimise the occurence of the slow transaction overhead. setAddrWindow now takes xstart, ystart, width and height as inputs Multi-sample raw touch x and y for noisy displays Example update for setAddrWindow change compatibility --- Extensions/Smooth_font.cpp | 5 +- Extensions/Sprite.cpp | 24 +- Extensions/Touch.cpp | 34 +- TFT_eSPI.cpp | 386 ++++++++++-------- TFT_eSPI.h | 84 ++-- User_Setup.h | 4 + User_Setups/SetupX_Template.h | 4 + examples/160 x 128/Pong_v3/Pong_v3.ino | 6 +- .../TFT_graphicstest_PDQ3.ino | 10 +- .../TFT_Mandlebrot/TFT_Mandlebrot.ino | 11 +- examples/320 x 240/TFT_Pong/TFT_Pong.ino | 6 +- .../TFT_graphicstest_PDQ.ino | 6 +- .../480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino | 7 +- .../TFT_ring_meter/TFT_ring_meter.ino | 6 +- library.json | 2 +- library.properties | 2 +- 16 files changed, 355 insertions(+), 242 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 3dc2cb0..1952add 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -441,6 +441,8 @@ void TFT_eSPI::drawGlyph(uint16_t code) int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; int16_t cx = cursor_x + gdX[gNum]; + startWrite(); // Avoid slow ESP32 transaction overhead for every pixel + for (int y = 0; y < gHeight[gNum]; y++) { fontFile.read(pbuffer, gWidth[gNum]); // _tft->width()) max_x = _tft->width(); if (max_y > _tft->height()) max_y = _tft->height(); - _tft->startWrite(); + _tft->startWrite(); // ESP32: avoid transaction overhead for every tft pixel + // Scan destination bounding box and fetch transformed pixels from source Sprite for (int32_t x = min_x; x <= max_x; x++) { int32_t xt = x - _tft->_xpivot; @@ -325,7 +326,8 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) else if (column_drawn) y = max_y; // Skip remaining column pixels } } - _tft->endWrite(); + + _tft->endWrite(); // ESP32: end transaction return true; } @@ -465,7 +467,6 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y) if (_bpp == 16) _tft->pushImage(x, y, _iwidth, _iheight, _img ); else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); - } @@ -562,7 +563,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 if (xs + w >= _iwidth) ws = _iwidth - xs; if (ys + h >= _iheight) hs = _iheight - ys; - if (_bpp == 16) + if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite { for (uint32_t yp = yo; yp < yo + hs; yp++) { @@ -577,7 +578,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 ys++; } } - else if (_bpp == 8) + else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite { for (uint32_t yp = yo; yp < yo + hs; yp++) { @@ -613,7 +614,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 x = y; y = _dheight - tx - 1; } - + // Plot a 1bpp image into a 1bpp Sprite uint8_t* pdata = (uint8_t* ) data; uint32_t ww = (w+7) & 0xFFF8; for (int32_t yp = 0; yp= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; @@ -654,7 +659,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const if (xs + w >= _iwidth) ws = _iwidth - xs; if (ys + h >= _iheight) hs = _iheight - ys; - if (_bpp == 16) + if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite { for (uint32_t yp = yo; yp < yo + hs; yp++) { @@ -670,7 +675,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const } } - else if (_bpp == 8) + else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite { for (uint32_t yp = yo; yp < yo + hs; yp++) { @@ -706,7 +711,7 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const x = y; y = _dheight - tx - 1; } - + // Plot a 1bpp image into a 1bpp Sprite const uint8_t* pdata = (const uint8_t* ) data; uint32_t ww = (w+7) & 0xFFF8; for (int32_t yp = 0; yp>3); // Read last 8 bits and start new XP conversion + tmp |= 0x1f & (spi.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion *x = tmp; - // Start XP sample request for y position - tmp = SPI.transfer(0); // Read first 8 bits + // Start XP sample request for y position, read 4 times and keep last sample + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + + tmp = spi.transfer(0); // Read first 8 bits tmp = tmp <<5; - tmp |= 0x1f & (SPI.transfer(0)>>3); // Read last 8 bits + tmp |= 0x1f & (spi.transfer(0)>>3); // Read last 8 bits *y = tmp; @@ -57,9 +71,9 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ // Calculate Z int16_t tz = 0xFFF; - SPI.transfer(0xb0); // Start new Z1 conversion - tz += SPI.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion - tz -= SPI.transfer16(0x00) >> 3; // Read Z2 + spi.transfer(0xb0); // Start new Z1 conversion + tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion + tz -= spi.transfer16(0x00) >> 3; // Read Z2 T_CS_H; diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index f1fb2c4..4df354b 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -15,10 +15,16 @@ #include "TFT_eSPI.h" -#include - -#ifndef ESP32_PARALLEL - #include +#if defined (ESP32) + #if !defined (ESP32_PARALLEL) + #ifdef USE_HSPI_PORT + SPIClass spi = SPIClass(HSPI); + #else // use default VSPI port + SPIClass spi = SPIClass(VSPI); + #endif + #endif +#else // ESP8266 + SPIClass spi = SPIClass(); #endif // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled @@ -48,32 +54,32 @@ void busDir(uint32_t mask, uint8_t mode); inline void TFT_eSPI::spi_begin(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} #endif } inline void TFT_eSPI::spi_end(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} + if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} #endif } inline void TFT_eSPI::spi_begin_read(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} #else #if !defined(ESP32_PARALLEL) - SPI.setFrequency(SPI_READ_FREQUENCY); + spi.setFrequency(SPI_READ_FREQUENCY); #endif #endif } inline void TFT_eSPI::spi_end_read(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} + if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} #else #if !defined(ESP32_PARALLEL) - SPI.setFrequency(SPI_FREQUENCY); + spi.setFrequency(SPI_FREQUENCY); #endif #endif } @@ -82,17 +88,17 @@ inline void TFT_eSPI::spi_end_read(void){ inline void TFT_eSPI::spi_begin_touch(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} #else - SPI.setFrequency(SPI_TOUCH_FREQUENCY); + spi.setFrequency(SPI_TOUCH_FREQUENCY); #endif } inline void TFT_eSPI::spi_end_touch(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} + if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} #else - SPI.setFrequency(SPI_FREQUENCY); + spi.setFrequency(SPI_FREQUENCY); #endif } @@ -263,17 +269,17 @@ void TFT_eSPI::init(uint8_t tc) #ifdef TFT_SPI_OVERLAP // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss); - //SPI.pins( 6, 7, 8, 0); - SPI.pins(6, 7, 8, 0); + //spi.pins( 6, 7, 8, 0); + spi.pins(6, 7, 8, 0); #endif - SPI.begin(); // This will set HMISO to input + spi.begin(); // This will set HMISO to input #else #if !defined(ESP32_PARALLEL) #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) - SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); + spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); #else - SPI.begin(); + spi.begin(); #endif #endif #endif @@ -284,9 +290,9 @@ void TFT_eSPI::init(uint8_t tc) // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled // so the code here is for ESP8266 only #if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(TFT_SPI_MODE); - SPI.setFrequency(SPI_FREQUENCY); + spi.setBitOrder(MSBFIRST); + spi.setDataMode(TFT_SPI_MODE); + spi.setFrequency(SPI_FREQUENCY); #endif #if defined(ESP32_PARALLEL) @@ -298,7 +304,7 @@ void TFT_eSPI::init(uint8_t tc) digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) pinMode(TFT_CS, OUTPUT); #else - SPI.setHwCs(1); // Use hardware SS toggling + spi.setHwCs(1); // Use hardware SS toggling #endif #endif @@ -611,7 +617,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) { #if defined(ESP32_PARALLEL) - readAddrWindow(x0, y0, x0, y0); // Sets CS low + readAddrWindow(x0, y0, 1, 1); // Sets CS low // Set masked pins D0- D7 to input busDir(dir_mask, INPUT); @@ -652,7 +658,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) spi_begin_read(); - readAddrWindow(x0, y0, x0, y0); // Sets CS low + readAddrWindow(x0, y0, 1, 1); // Sets CS low #ifdef TFT_SDA_READ begin_SDA_Read(); @@ -757,7 +763,7 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t #if defined(ESP32_PARALLEL) - readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low + readAddrWindow(x, y, w, h); // Sets CS low // Set masked pins D0- D7 to input busDir(dir_mask, INPUT); @@ -799,7 +805,7 @@ void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t spi_begin_read(); - readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low + readAddrWindow(x, y, w, h); // Sets CS low #ifdef TFT_SDA_READ begin_SDA_Read(); @@ -881,7 +887,7 @@ void TFT_eSPI::begin_SDA_Read(void) #ifdef TFT_SPI_OVERLAP // Reads in overlap mode not supported #else - SPI.end(); + spi.end(); #endif #endif } @@ -901,9 +907,9 @@ void TFT_eSPI::end_SDA_Read(void) pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false); #else #ifdef TFT_SPI_OVERLAP - SPI.pins(6, 7, 8, 0); + spi.pins(6, 7, 8, 0); #else - SPI.begin(); + spi.begin(); #endif #endif } @@ -946,7 +952,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t spi_begin(); inTransaction = true; - setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR + setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR data += dx + dy * w; @@ -1007,7 +1013,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t { if (transp != *ptr) { - if (move) { move = false; setAddrWindow(px, y, xe, ye); } + if (move) { move = false; setWindow(px, y, xe, ye); } lineBuf[np] = *ptr; np++; } @@ -1042,7 +1048,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) { - +#ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*)data); +#else + // Partitioned memory FLASH processor if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; int32_t dx = 0; @@ -1066,7 +1075,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin uint16_t buffer[64]; uint16_t* pix_buffer = buffer; - setAddrWindow(x, y, x + dw - 1, y + dh - 1); + setWindow(x, y, x + dw - 1, y + dh - 1); // Work out the number whole buffers to send uint16_t nb = (dw * dh) / 64; @@ -1095,6 +1104,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin inTransaction = false; spi_end(); +#endif // if ESP32 else ESP8266 check } @@ -1104,7 +1114,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin ***************************************************************************************/ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transp) { - +#ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*) data, transp); +#else + // Partitioned memory FLASH processor if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; int32_t dx = 0; @@ -1145,7 +1158,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin uint16_t color = pgm_read_word(ptr); if (transp != color) { - if (move) { move = false; setAddrWindow(px, y, xe, ye); } + if (move) { move = false; setWindow(px, y, xe, ye); } lineBuf[np] = color; np++; } @@ -1171,6 +1184,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin inTransaction = false; spi_end(); +#endif // if ESP32 else ESP8266 check } @@ -1198,7 +1212,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * spi_begin(); inTransaction = true; - setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR + setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR // Line buffer makes plotting faster uint16_t lineBuf[dw]; @@ -1339,7 +1353,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * { if (transp != *ptr) { - if (move) { move = false; setAddrWindow(px, y, xe, ye);} + if (move) { move = false; setWindow(px, y, xe, ye);} uint8_t color = *ptr; // Shifts are slow so check if colour has changed first @@ -1398,7 +1412,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * if (move) { move = false; - setAddrWindow(px, y, xe, ye); + setWindow(px, y, xe, ye); } np++; } @@ -1464,7 +1478,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ spi_begin_read(); - readAddrWindow(x0, y0, x0 + w - 1, y0 + h - 1); // Sets CS low + readAddrWindow(x0, y0, w, h); // Sets CS low #ifdef TFT_SDA_READ begin_SDA_Read(); @@ -2397,7 +2411,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u uint8_t mask = 0x1; spi_begin(); //inTransaction = true; - setAddrWindow(x, y, x+5, y+8); + setWindow(x, y, x+5, y+8); for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); column[5] = 0; @@ -2620,27 +2634,26 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u /*************************************************************************************** -** Function name: setWindow +** Function name: setAddrWindow ** Description: define an area to receive a stream of pixels ***************************************************************************************/ // Chip select is high at the end of this function -void TFT_eSPI::setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1) +void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h) { spi_begin(); - setAddrWindow(x0, y0, x1, y1); + setWindow(x0, y0, x0 + w - 1, y0 + h - 1); CS_H; spi_end(); } /*************************************************************************************** -** Function name: setAddrWindow +** Function name: setWindow ** Description: define an area to receive a stream of pixels ***************************************************************************************/ -// Chip select stays low, use setWindow() from sketches - +// Chip select stays low, call spi_begin first. Use setAddrWindow() from sketches #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER) -void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { //spi_begin(); @@ -2708,7 +2721,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #elif defined (ESP8266) && !defined (RPI_WRITE_STROBE) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { //spi_begin(); @@ -2731,7 +2744,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; - SPI.writePattern(&xb[0], 8, 1); + spi.writePattern(&xb[0], 8, 1); // Row addr set DC_C; @@ -2745,7 +2758,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; - SPI.writePattern(&yb[0], 8, 1); + spi.writePattern(&yb[0], 8, 1); // write to RAM DC_C; @@ -2763,7 +2776,7 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #else #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2840,7 +2853,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #else // This is for the ESP32 -void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); @@ -2862,7 +2875,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #if defined (RPI_ILI9486_DRIVER) uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; - SPI.writePattern(&xb[0], 8, 1); + spi.writePattern(&xb[0], 8, 1); #else tft_Write_32(SPI_32(x0, x1)); #endif @@ -2876,7 +2889,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #if defined (RPI_ILI9486_DRIVER) uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; - SPI.writePattern(&yb[0], 8, 1); + spi.writePattern(&yb[0], 8, 1); #else tft_Write_32(SPI_32(y0, y1)); #endif @@ -2900,10 +2913,13 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) ***************************************************************************************/ // Chip select stays low #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { //spi_begin(); + int32_t xe = xs + w - 1; + int32_t ye = ys + h - 1; + addr_col = 0xFFFF; addr_row = 0xFFFF; @@ -2966,10 +2982,13 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #else //ESP32 -void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { //spi_begin(); + int32_t xe = xs + w - 1; + int32_t ye = ys + h - 1; + addr_col = 0xFFFF; addr_row = 0xFFFF; @@ -2987,7 +3006,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; - tft_Write_32(SPI_32(x0, x1)); + tft_Write_32(SPI_32(xs, xe)); // Row addr set DC_C; @@ -2996,7 +3015,7 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; - tft_Write_32(SPI_32(y0, y1)); + tft_Write_32(SPI_32(ys, ye)); DC_C; @@ -3044,7 +3063,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)}; - SPI.writePattern(&cBin[0], 4, 2); + spi.writePattern(&cBin[0], 4, 2); #else SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go @@ -3072,7 +3091,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)}; - SPI.writePattern(&cBin[0], 4, 2); + spi.writePattern(&cBin[0], 4, 2); #else SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go @@ -3221,7 +3240,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; - SPI.writePattern(&xb[0], 8, 1); + spi.writePattern(&xb[0], 8, 1); #else tft_Write_32(SPI_32(x, x)); #endif @@ -3240,7 +3259,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; - SPI.writePattern(&yb[0], 8, 1); + spi.writePattern(&yb[0], 8, 1); #else tft_Write_32(SPI_32(y, y)); #endif @@ -3295,7 +3314,7 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; + if(len) spi.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else #if defined (ESP32_PARALLEL) @@ -3340,7 +3359,7 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len) { #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; + if(len) spi.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else #if defined (ESP32_PARALLEL) @@ -3355,7 +3374,7 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len) ** Function name: pushColors ** Description: push an array of pixels for 16 bit raw image drawing ***************************************************************************************/ -// Assumed that setWindow() has previously been called +// Assumed that setAddrWindow() has previously been called void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) { @@ -3364,8 +3383,8 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) CS_L; #if defined (RPI_WRITE_STROBE) - while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } - if (len) SPI.writePattern(data, len, 1); + while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } + if (len) spi.writePattern(data, len, 1); #else #ifdef ESP32_PARALLEL while (len--) {tft_Write_8(*data); data++;} @@ -3374,10 +3393,10 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) while (len>1) {color = (*data++) | ((*data++)<<8); tft_Write_16(color); len-=2;} #else #if (SPI_FREQUENCY == 80000000) - while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } - if (len) SPI.writePattern(data, len, 1); + while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } + if (len) spi.writePattern(data, len, 1); #else - SPI.writeBytes(data, len); + spi.writeBytes(data, len); #endif #endif #endif @@ -3403,8 +3422,8 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) if (swap) while ( len-- ) {tft_Write_16(*data); data++;} else while ( len-- ) {tft_Write_16S(*data); data++;} #else - if (swap) SPI.writePixels(data,len<<1); - else SPI.writeBytes((uint8_t*)data,len<<1); + if (swap) spi.writePixels(data,len<<1); + else spi.writeBytes((uint8_t*)data,len<<1); #endif #else @@ -3600,7 +3619,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x0 > x1) {spi_end(); return;} - setAddrWindow(y0, x0, y0, _height); + setWindow(y0, x0, y0, _height); SPI1U1 = mask; SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { @@ -3613,7 +3632,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if ((y0 < 0) || (y0 >= _width)) break; err += dx; while(SPI1CMD & SPIBUSY) {} - setAddrWindow(y0, x0+1, y0, _height); + setWindow(y0, x0+1, y0, _height); SPI1U1 = mask; SPI1W0 = swapped_color; } @@ -3634,7 +3653,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x0 > x1) {spi_end(); return;} - setAddrWindow(x0, y0, _width, y0); + setWindow(x0, y0, _width, y0); SPI1U1 = mask; SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { @@ -3647,7 +3666,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if ((y0 < 0) || (y0 >= _height)) break; err += dx; while(SPI1CMD & SPIBUSY) {} - setAddrWindow(x0+1, y0, _width, y0); + setWindow(x0+1, y0, _width, y0); SPI1U1 = mask; SPI1W0 = swapped_color; } @@ -3670,13 +3689,18 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (h < 1)) return; - if ((y + h - 1) >= _height) h = _height - y; + // Clipping + if ((x < 0) || (x >= _width) || (y >= _height)) return; + + if (y < 0) { h += y; y = 0; } + + if ((y + h) > _height) h = _height - y; + + if (h < 1) return; spi_begin(); - setAddrWindow(x, y, x, y + h - 1); + setWindow(x, y, x, y + h - 1); writeBlock(color, h); @@ -3689,17 +3713,22 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (h < 1)) return; - if ((y + h - 1) >= _height) h = _height - y; + // Clipping + if ((x < 0) || (x >= _width) || (y >= _height)) return; + + if (y < 0) { h += y; y = 0; } + + if ((y + h) > _height) h = _height - y; + + if (h < 1) return; spi_begin(); - setAddrWindow(x, y, x, y + h - 1); + setWindow(x, y, x, y + h - 1); #ifdef RPI_WRITE_STROBE #if defined (ESP8266) - // SPI1U1 will already be set to transfer 16 bits by setAddrWindow() + // SPI1U1 will already be set to transfer 16 bits by setWindow() SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -3729,13 +3758,18 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (w < 1)) return; - if ((x + w - 1) >= _width) w = _width - x; + // Clipping + if ((y < 0) || (x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + + if ((x + w) > _width) w = _width - x; + + if (w < 1) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y); + setWindow(x, y, x + w - 1, y); writeBlock(color, w); @@ -3753,11 +3787,11 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) if ((x + w - 1) >= _width) w = _width - x; spi_begin(); - setAddrWindow(x, y, x + w - 1, y); + setWindow(x, y, x + w - 1, y); #ifdef RPI_WRITE_STROBE #if defined (ESP8266) - // SPI1U1 will already be set to transfer 16 bits by setAddrWindow() + // SPI1U1 will already be set to transfer 16 bits by setWindow() SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -3787,13 +3821,19 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - // rudimentary clipping (drawChar w/big text requires this) - if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; - if ((x + w - 1) > _width) w = _width - x; - if ((y + h - 1) > _height) h = _height - y; + // Clipping + if ((x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _width) w = _width - x; + if ((y + h) > _height) h = _height - y; + + if ((w < 1) || (h < 1)) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y + h - 1); + setWindow(x, y, x + w - 1, y + h - 1); writeBlock(color, w * h); @@ -3806,13 +3846,19 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - // rudimentary clipping (drawChar w/big text requires this) - if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; - if ((x + w - 1) > _width) w = _width - x; - if ((y + h - 1) > _height) h = _height - y; + // Clipping + if ((x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _width) w = _width - x; + if ((y + h) > _height) h = _height - y; + + if ((w < 1) || (h < 1)) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y + h - 1); + setWindow(x, y, x + w - 1, y + h - 1); uint32_t n = (uint32_t)w * (uint32_t)h; @@ -3906,6 +3952,10 @@ size_t TFT_eSPI::write(uint8_t utf8) if(fontLoaded) { uint16_t unicode = decodeUTF8(utf8); + + //Serial.print("UniCode="); Serial.println(unicode); + //Serial.print("UTF8 ="); Serial.println(utf8); + if (!unicode) return 1; //fontFile = SPIFFS.open( _gFontFilename, "r" ); @@ -4176,7 +4226,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) // Faster drawing of characters and background using block write { spi_begin(); - setAddrWindow(x, y, (x + w * 8) - 1, y + height - 1); + setWindow(x, y, (x + w * 8) - 1, y + height - 1); uint8_t mask; for (int i = 0; i < height; i++) @@ -4238,7 +4288,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } while (line--) { // In this case the while(line--) is faster pc++; // This is faster than putting pc+=line before while()? - setAddrWindow(px, py, px + ts, py + ts); + setWindow(px, py, px + ts, py + ts); if (ts) { tnp = np; @@ -4267,7 +4317,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) // so use faster drawing of characters and background using block write { //spi_begin(); - setAddrWindow(x, y, x + width - 1, y + height - 1); + setWindow(x, y, x + width - 1, y + height - 1); #ifdef RPI_WRITE_STROBE uint8_t textcolorBin[] = { (uint8_t) (textcolor >> 8), (uint8_t) textcolor }; @@ -4282,7 +4332,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) line &= 0x7F; line++; w -= line; #ifdef RPI_WRITE_STROBE - SPI.writePattern(&textcolorBin[0], 2, 1); line--; + spi.writePattern(&textcolorBin[0], 2, 1); line--; while(line--) {WR_L; WR_H;} #else #ifdef ESP32_PARALLEL @@ -4295,7 +4345,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) else { line++; w -= line; #ifdef RPI_WRITE_STROBE - SPI.writePattern(&textbgcolorBin[0], 2, 1); line--; + spi.writePattern(&textbgcolorBin[0], 2, 1); line--; while(line--) {WR_L; WR_H;} #else #ifdef ESP32_PARALLEL @@ -4927,56 +4977,56 @@ void writeBlock(uint16_t color, uint32_t repeat) if (repeat > 19) { - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S); + SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S); while(repeat>19) { - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), r2); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); repeat -= 20; } - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } if (repeat) { - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S); - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), r2); + SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); if (repeat > 8 ) { - WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), r2); - WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), r0); - WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), r1); - WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), r2); + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); } - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } } @@ -4990,39 +5040,39 @@ void writeBlock(uint16_t color, uint32_t repeat) if (repeat > 31) // Revert legacy toggle buffer change { - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 511); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); while(repeat>31) { - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W1_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W2_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W3_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W4_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W5_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W6_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W7_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W8_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W9_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W10_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W11_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W12_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W13_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W14_REG(SPI_NUM), color32); - WRITE_PERI_REG(SPI_W15_REG(SPI_NUM), color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); repeat -= 32; } - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } if (repeat) { // Revert toggle buffer change - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), (repeat << 4) - 1); - for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (repeat << 4) - 1); + for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + (i << 2)), color32); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } } #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 1422fb4..5e471e9 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -105,7 +105,11 @@ #ifdef ESP32 #include "soc/spi_reg.h" - #define SPI_NUM 0x3 + #ifdef USE_HSPI_PORT + #define SPI_PORT HSPI + #else + #define SPI_PORT VSPI + #endif #endif #ifdef SMOOTH_FONT @@ -312,32 +316,32 @@ #elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB // Write 8 bits to TFT - #define tft_Write_8(C) SPI.transfer(C) + #define tft_Write_8(C) spi.transfer(C) // Convert 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16(C) SPI.transfer((C & 0xF800)>>8); \ - SPI.transfer((C & 0x07E0)>>3); \ - SPI.transfer((C & 0x001F)<<3) + #define tft_Write_16(C) spi.transfer((C & 0xF800)>>8); \ + spi.transfer((C & 0x07E0)>>3); \ + spi.transfer((C & 0x001F)<<3) // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes - #define tft_Write_16S(C) SPI.transfer(C & 0xF8); \ - SPI.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \ - SPI.transfer((C & 0x1F00)>>5) + #define tft_Write_16S(C) spi.transfer(C & 0xF8); \ + spi.transfer((C & 0xE0)>>11 | (C & 0x07)<<5); \ + spi.transfer((C & 0x1F00)>>5) // Write 32 bits to TFT - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_32(C) spi.write32(C) #elif defined (RPI_ILI9486_DRIVER) - #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) - #define tft_Write_16(C) SPI.write16(C) - #define tft_Write_16S(C) SPI.write16(C<<8 | C>>8) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) spi.transfer(0); spi.transfer(C) + #define tft_Write_16(C) spi.write16(C) + #define tft_Write_16S(C) spi.write16(C<<8 | C>>8) + #define tft_Write_32(C) spi.write32(C) #elif defined ESP8266 - #define tft_Write_8(C) SPI.write(C) - #define tft_Write_16(C) SPI.write16(C) - #define tft_Write_32(C) SPI.write32(C) + #define tft_Write_8(C) spi.write(C) + #define tft_Write_16(C) spi.write16(C) + #define tft_Write_32(C) spi.write32(C) #else // ESP32 using SPI with 16 bit color display @@ -346,31 +350,31 @@ // Write 8 bits #define tft_Write_8(C) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 8-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 8-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); // Write 16 bits with corrected endianess for 16 bit colours #define tft_Write_16(C) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C<<8 | C>>8); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C<<8 | C>>8); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); // Write 16 bits #define tft_Write_16S(C) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 16-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); // Write 32 bits #define tft_Write_32(C) \ - WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_NUM), 32-1); \ - WRITE_PERI_REG(SPI_W0_REG(SPI_NUM), C); \ - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); \ - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 32-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); #endif @@ -383,7 +387,7 @@ #define SCLK_H GPOS=sclkpinmask #else // Use a SPI read transfer - #define tft_Read_8() SPI.transfer(0) + #define tft_Read_8() spi.transfer(0) #endif #endif @@ -650,7 +654,7 @@ class TFT_eSPI : public Print { width(void); // The TFT_eSprite class inherits the following functions - void setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1), + void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye), pushColor(uint16_t color), pushColor(uint16_t color, uint32_t len), pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option @@ -776,12 +780,12 @@ class TFT_eSPI : public Print { fontHeight(int16_t font), fontHeight(void); - void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); - // These 3 functions are used together, for every startWrite() there must be an endWrite() - void startWrite(void); // Begin SPI transaction - void writeColor(uint16_t color, uint32_t len); // Write a colour without transaction overhead - void endWrite(void); // End SPI transaction + // Compatibility additions (non-essential) + void startWrite(void); // Begin SPI transaction (not normally needed) + void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead + void endWrite(void); // End SPI transaction size_t write(uint8_t); @@ -816,7 +820,7 @@ class TFT_eSPI : public Print { inline void spi_begin_read() __attribute__((always_inline)); inline void spi_end_read() __attribute__((always_inline)); - void readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); uint8_t tabcolor, colstart = 0, rowstart = 0; // some ST7735 displays need this changed diff --git a/User_Setup.h b/User_Setup.h index 6a5531e..b581333 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -262,6 +262,10 @@ // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 +// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. +// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) +// then uncomment the following line: +//#define USE_HSPI_PORT // Comment out the following #define if "SPI Transactions" do not need to be // supported. When commented out the code size will be smaller and sketches will diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 6a5531e..36a2372 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -262,6 +262,10 @@ // The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 +// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. +// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) +// then uncomment the following line to use the HSPI port: +//#define USE_HSPI_PORT // Comment out the following #define if "SPI Transactions" do not need to be // supported. When commented out the code size will be smaller and sketches will diff --git a/examples/160 x 128/Pong_v3/Pong_v3.ino b/examples/160 x 128/Pong_v3/Pong_v3.ino index 7c51299..318c851 100644 --- a/examples/160 x 128/Pong_v3/Pong_v3.ino +++ b/examples/160 x 128/Pong_v3/Pong_v3.ino @@ -107,13 +107,17 @@ void midline() { // If the ball is not on the line then don't redraw the line if ((ball_x dashline_x+dashline_w)) return; + tft.startWrite(); + // Quick way to draw a dashed line - tft.setAddrWindow(dashline_x,0,dashline_x+dashline_w-1,h); + tft.setAddrWindow(dashline_x, 0, dashline_w, h); for(int16_t i = 0; i < dashline_n; i+=2) { tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels } + + tft.endWrite(); } void lpaddle() { diff --git a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino index 325b9a4..148499e 100644 --- a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino +++ b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino @@ -308,14 +308,16 @@ uint32_t testHaD() 0x0a, 0x2b, 0x0b, 0x41, 0x0a, 0x29, 0x0b, 0x43, 0x0a, 0x27, 0x0a, 0x46, 0x0a, 0x25, 0x0a, 0x49, 0x09, 0x23, 0x08, 0x4e, 0x08, 0x96, 0x12 }; - + tft.fillScreen(TFT_BLACK); uint32_t start = micros_start(); - + + tft.startWrite(); + for (int i = 0; i < 0x10; i++) { - tft.setAddrWindow(0, 0, tft.width()-1, tft.height()-1); + tft.setAddrWindow(0, 0, tft.width(), tft.height()); uint16_t cnt = 0; uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); @@ -335,6 +337,8 @@ uint32_t testHaD() } } + tft.endWrite(); + uint32_t t = micros() - start; tft.setTextColor(TFT_YELLOW); diff --git a/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino b/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino index 73e0afc..2a04556 100644 --- a/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino +++ b/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino @@ -7,7 +7,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library -#define ILI9341_GREY 0x7BEF +#define TFT_GREY 0x7BEF unsigned long runTime = 0; @@ -16,8 +16,9 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0; void setup() { + Serial.begin(250000); //randomSeed(analogRead(A0)); - + Serial.println(); // Setup the LCD tft.init(); tft.setRotation(3); @@ -27,7 +28,8 @@ void loop() { runTime = millis(); - tft.fillScreen(ILI9341_BLACK); + tft.fillScreen(TFT_BLACK); + tft.startWrite(); for (int px = 1; px < 320; px++) { for (int py = 0; py < 240; py++) @@ -49,6 +51,9 @@ void loop() yield();tft.drawPixel(px, py, color); } } + tft.endWrite(); + + Serial.println(millis()-runTime); while(1) yield(); } diff --git a/examples/320 x 240/TFT_Pong/TFT_Pong.ino b/examples/320 x 240/TFT_Pong/TFT_Pong.ino index 6cf91f2..5bcd880 100644 --- a/examples/320 x 240/TFT_Pong/TFT_Pong.ino +++ b/examples/320 x 240/TFT_Pong/TFT_Pong.ino @@ -108,13 +108,17 @@ void midline() { // If the ball is not on the line then don't redraw the line if ((ball_x dashline_x+dashline_w)) return; + tft.startWrite(); + // Quick way to draw a dashed line - tft.setWindow(dashline_x,0,dashline_x+dashline_w-1,h); + tft.setAddrWindow(dashline_x, 0, dashline_w, h); for(int16_t i = 0; i < dashline_n; i+=2) { tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels } + + tft.endWrite(); } void lpaddle() { diff --git a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino index 7db002e..8e03ef5 100644 --- a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino +++ b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino @@ -336,10 +336,10 @@ uint32_t testHaD() tft.fillScreen(TFT_BLACK); uint32_t start = micros_start(); - + for (int i = 0; i < 0x10; i++) { - tft.setWindow(0, 0, 240-1, 320-1); + tft.setAddrWindow(0, 0, 240, 320); uint16_t cnt = 0; uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); @@ -347,6 +347,7 @@ uint32_t testHaD() const uint8_t *cmp = &HaD_240x320[0]; + tft.startWrite(); while (cmp < &HaD_240x320[sizeof(HaD_240x320)]) { cnt = pgm_read_byte(cmp++); @@ -354,6 +355,7 @@ uint32_t testHaD() tft.pushColor(curcolor, cnt); // PDQ_GFX has count curcolor ^= color; } + tft.endWrite(); } uint32_t t = micros() - start; diff --git a/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino b/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino index 5af0f13..f8ebcb1 100644 --- a/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino +++ b/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino @@ -171,11 +171,14 @@ void renderJPEG(int xpos, int ypos) { // calculate how many pixels must be drawn uint32_t mcu_pixels = win_w * win_h; + tft.startWrite(); + // draw image MCU block only if it will fit on the screen if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height()) { + // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1) - tft.setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); + tft.setAddrWindow(mcu_x, mcu_y, win_w, win_h); // Write all MCU pixels to the TFT window while (mcu_pixels--) { @@ -185,6 +188,8 @@ void renderJPEG(int xpos, int ypos) { } else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding + + tft.endWrite(); } // calculate how long it took to draw the image diff --git a/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino b/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino index ebed42b..d4d8c2f 100644 --- a/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino +++ b/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino @@ -251,8 +251,10 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) + tft.startWrite(); + // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); + tft.setAddrWindow(x, y, width, height); // Work out the number whole buffers to send uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; @@ -273,5 +275,7 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); tft.pushColors(pix_buffer, np); } + + tft.endWrite(); } diff --git a/library.json b/library.json index 640cef0..d32cf0c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.3.13", + "version": "1.4.0", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 7f4f52c..834703f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.3.13 +version=1.4.0 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 0460ab64d271c06ed8fbfcc548793d23b71b34fd Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 22 Jan 2019 19:09:18 +0000 Subject: [PATCH 70/94] Delete weather-station example Because Weather Underground will no longer support free API's --- .../weather-station/ArialRoundedMTBold_14.h | 224 ------- .../weather-station/ArialRoundedMTBold_36.h | 226 ------- examples/320 x 240/weather-station/GfxUi.cpp | 342 ---------- examples/320 x 240/weather-station/GfxUi.h | 60 -- .../weather-station/SPIFFS_Support.ino | 42 -- .../320 x 240/weather-station/WebResource.cpp | 105 ---- .../320 x 240/weather-station/WebResource.h | 46 -- examples/320 x 240/weather-station/settings.h | 72 --- .../weather-station/weather-station.ino | 595 ------------------ 9 files changed, 1712 deletions(-) delete mode 100644 examples/320 x 240/weather-station/ArialRoundedMTBold_14.h delete mode 100644 examples/320 x 240/weather-station/ArialRoundedMTBold_36.h delete mode 100644 examples/320 x 240/weather-station/GfxUi.cpp delete mode 100644 examples/320 x 240/weather-station/GfxUi.h delete mode 100644 examples/320 x 240/weather-station/SPIFFS_Support.ino delete mode 100644 examples/320 x 240/weather-station/WebResource.cpp delete mode 100644 examples/320 x 240/weather-station/WebResource.h delete mode 100644 examples/320 x 240/weather-station/settings.h delete mode 100644 examples/320 x 240/weather-station/weather-station.ino diff --git a/examples/320 x 240/weather-station/ArialRoundedMTBold_14.h b/examples/320 x 240/weather-station/ArialRoundedMTBold_14.h deleted file mode 100644 index b08d84f..0000000 --- a/examples/320 x 240/weather-station/ArialRoundedMTBold_14.h +++ /dev/null @@ -1,224 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -// Created by http://oleddisplay.squix.ch/ Consider a donation -// In case of problems make sure that you are using the font file with the correct version! - -// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected -// this avoids screen corruption if ~ is printer - -const uint8_t ArialRoundedMTBold_14Bitmaps[] PROGMEM = { - - // Bitmap Data: - 0x00, // ' ' - 0xFF,0xF8,0xF0, // '!' - 0xDE,0xF6, // '"' - 0x12,0x32,0x36,0xFF,0xFF,0x24,0xFF,0xFF,0x4C,0x48, // '#' - 0x10,0x61,0xF6,0xAD,0x7A,0x1E,0x0E,0xD7,0xAF,0x5B,0xE1,0x02,0x04,0x00, // '$' - 0x60,0x92,0x22,0x44,0x49,0x07,0x60,0x0B,0x82,0x48,0xC9,0x11,0x24,0x18, // '%' - 0x3C,0x19,0x82,0x60,0xF0,0x39,0x33,0x6C,0x73,0x1C,0xFF,0x8E,0x30, // '&' - 0xFC, // ''' - 0x32,0x64,0xCC,0xCC,0xC4,0x62,0x30, // '(' - 0xC4,0x62,0x33,0x33,0x32,0x64,0xC0, // ')' - 0x21,0x2A,0xE5,0x28, // '*' - 0x18,0x18,0x18,0xFF,0xFF,0x18,0x18, // '+' - 0xF6, // ',' - 0xFF, // '-' - 0xF0, // '.' - 0x33,0x32,0x66,0x4C,0xCC, // '/' - 0x38,0xFB,0x9E,0x3C,0x78,0xF1,0xF6,0x7C,0x70, // '0' - 0x19,0xDF,0xB1,0x8C,0x63,0x18,0xC0, // '1' - 0x38,0xFF,0x1E,0x30,0xC3,0x0C,0x30,0xFF,0xFC, // '2' - 0x79,0x9B,0x10,0x63,0xC7,0x81,0xC3,0xC6,0xF0, // '3' - 0x06,0x0E,0x1E,0x16,0x26,0x46,0xFF,0xFF,0x06,0x06, // '4' - 0x7E,0xFD,0x06,0x0F,0xD8,0xC1,0xC3,0xCC,0xF0, // '5' - 0x38,0xDB,0x1E,0x0F,0xD8,0xF1,0xE3,0x66,0x78, // '6' - 0xFF,0xFC,0x30,0x41,0x82,0x0C,0x18,0x30,0xC0, // '7' - 0x38,0xDB,0x1F,0x63,0x98,0xF1,0xE3,0xC6,0xF8, // '8' - 0x3C,0x66,0xC3,0xC3,0xE7,0x3F,0x03,0xC3,0x66,0x3C, // '9' - 0xF0,0x3C, // ':' - 0xF0,0x3D,0x80, // ';' - 0x02,0x1D,0xF7,0x0E,0x0F,0x83,0x81, // '<' - 0xFF,0xFC,0x07,0xFF,0xE0, // '=' - 0x81,0xC1,0xF0,0x70,0xEF,0xB8,0x40, // '>' - 0x3C,0xFF,0x1E,0x30,0xC7,0x0C,0x00,0x30,0x60, // '?' - 0x0F,0x83,0x06,0x60,0x24,0xED,0x99,0x9B,0x19,0xB1,0xBB,0x12,0xBF,0xE4,0xDC,0x40,0x13,0x06,0x0F,0xC0, // '@' - 0x1C,0x0E,0x05,0x06,0xC3,0x63,0x19,0xFC,0xFE,0xC1,0xE0,0xC0, // 'A' - 0xFC,0xFE,0xC7,0xC6,0xFE,0xFE,0xC3,0xC3,0xFF,0xFE, // 'B' - 0x3E,0x3F,0xB8,0xF8,0x3C,0x06,0x03,0x06,0xC7,0x7F,0x0F,0x00, // 'C' - 0xFE,0x7F,0xB0,0xF8,0x3C,0x1E,0x0F,0x07,0x87,0xFF,0x7F,0x00, // 'D' - 0xFE,0xFF,0xC0,0xC0,0xFE,0xFE,0xC0,0xC0,0xFF,0xFF, // 'E' - 0xFF,0xFF,0x06,0x0F,0xDF,0xB0,0x60,0xC1,0x80, // 'F' - 0x1E,0x3F,0x98,0xF8,0x2C,0x06,0x3F,0x1E,0xC3,0x7F,0x9F,0x00, // 'G' - 0xC1,0xE0,0xF0,0x78,0x3F,0xFF,0xFF,0x07,0x83,0xC1,0xE0,0xC0, // 'H' - 0xFF,0xFF,0xF0, // 'I' - 0x06,0x0C,0x18,0x30,0x60,0xF1,0xF3,0x7E,0x78, // 'J' - 0xC3,0x63,0xB3,0x9B,0x8F,0x87,0x63,0x19,0x8E,0xC3,0x60,0xC0, // 'K' - 0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xFF,0xFC, // 'L' - 0xE1,0xFC,0xFF,0x3F,0xCF,0xD2,0xF7,0xBD,0xEF,0x7B,0xCC,0xF3,0x30, // 'M' - 0xC1,0xF0,0xFC,0x7E,0x3D,0x9E,0x6F,0x3F,0x8F,0xC3,0xE0,0xC0, // 'N' - 0x1E,0x1F,0xE6,0x1B,0x03,0xC0,0xF0,0x3C,0x0D,0x86,0x7F,0x87,0x80, // 'O' - 0xFE,0xFF,0xC3,0xC3,0xFF,0xFE,0xC0,0xC0,0xC0,0xC0, // 'P' - 0x1E,0x0F,0xF1,0x87,0x60,0x6C,0x0D,0x81,0xB1,0x33,0x7C,0x7F,0x83,0xD8,0x01,0x80, // 'Q' - 0xFE,0xFF,0xC3,0xC3,0xFE,0xFC,0xCE,0xC6,0xC3,0xC3, // 'R' - 0x7C,0xFE,0xC7,0xC2,0x7C,0x0F,0xC3,0xC3,0x7E,0x3C, // 'S' - 0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 'T' - 0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x0F,0x07,0xC7,0x7F,0x1F,0x00, // 'U' - 0xC1,0xE0,0xD8,0xCC,0x66,0x31,0xB0,0xD8,0x6C,0x1C,0x0E,0x00, // 'V' - 0xC7,0x1E,0x38,0xF1,0x46,0xDB,0x66,0xDB,0x36,0xD9,0xA2,0xC7,0x1C,0x38,0xE1,0x83,0x00, // 'W' - 0xC3,0x66,0x7E,0x3C,0x18,0x3C,0x7E,0x66,0xC3,0xC3, // 'X' - 0xC3,0xC3,0x66,0x3E,0x3C,0x18,0x18,0x18,0x18,0x18, // 'Y' - 0x7F,0x3F,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0, // 'Z' - 0xFF,0xCC,0xCC,0xCC,0xCC,0xCF,0xF0, // '[' - 0xCC,0x44,0x66,0x22,0x33, // '\' - 0xFF,0x33,0x33,0x33,0x33,0x3F,0xF0, // ']' - 0x30,0xE7,0x9A,0xCF,0x30, // '^' - 0xFE, // '_' - 0xD0, // '`' - 0x7D,0x8C,0x7F,0x3C,0x79,0xDD,0x80, // 'a' - 0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xFF,0xB8, // 'b' - 0x3C,0xFF,0x1E,0x0C,0x6F,0xCF,0x00, // 'c' - 0x06,0x0C,0x1B,0xBF,0xF8,0xF1,0xE3,0xFE,0xEC, // 'd' - 0x3C,0xCF,0x1F,0xFC,0x0C,0xCF,0x00, // 'e' - 0x3B,0x19,0xF6,0x31,0x8C,0x63,0x00, // 'f' - 0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0xE3,0xC6,0xF8, // 'g' - 0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xC7,0x8C, // 'h' - 0xF3,0xFF,0xF0, // 'i' - 0x33,0x03,0x33,0x33,0x33,0x3F,0xE0, // 'j' - 0xC1,0x83,0x06,0x6D,0x9E,0x3E,0x66,0xCD,0x8C, // 'k' - 0xFF,0xFF,0xF0, // 'l' - 0xD9,0xDF,0xFF,0x31,0xE6,0x3C,0xC7,0x98,0xF3,0x18, // 'm' - 0xDD,0xFF,0x1E,0x3C,0x78,0xF1,0x80, // 'n' - 0x38,0xFB,0x1E,0x3C,0x6F,0x8E,0x00, // 'o' - 0xDD,0xFF,0x1E,0x3C,0x7F,0xF7,0x60,0xC1,0x80, // 'p' - 0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0x83,0x06,0x0C, // 'q' - 0xDF,0xF1,0x8C,0x63,0x00, // 'r' - 0x7B,0x3E,0x1E,0x0F,0x37,0x80, // 's' - 0x63,0x19,0xF6,0x31,0x8C,0x79,0xC0, // 't' - 0xC7,0x8F,0x1E,0x3C,0x7F,0xDD,0x80, // 'u' - 0xC7,0x8D,0x93,0x62,0x87,0x04,0x00, // 'v' - 0xC4,0x79,0xCD,0x29,0x35,0x67,0xBC,0x63,0x0C,0x60, // 'w' - 0xC6,0xD9,0xF1,0xC7,0xCD,0xB1,0x80, // 'x' - 0xC7,0x8D,0x93,0x62,0xC7,0x06,0x18,0xF1,0xC0, // 'y' - 0xFE,0x18,0x61,0x86,0x1F,0xFF,0x80, // 'z' - 0x19,0xCC,0x63,0x3B,0x8E,0x31,0x8C,0x71,0x80, // '{' - 0xFF,0xFF,0xFF,0xC0, // '|' - 0xC7,0x18,0xC6,0x38,0xEE,0x63,0x19,0xCC,0x00 // '}' -}; -const GFXglyph ArialRoundedMTBold_14Glyphs[] PROGMEM = { -// bitmapOffset, width, height, xAdvance, xOffset, yOffset - { 0, 1, 1, 5, 0, 0 }, // ' ' - { 1, 2, 10, 6, 1, -10 }, // '!' - { 4, 5, 3, 8, 1, -10 }, // '"' - { 6, 8, 10, 9, 0, -10 }, // '#' - { 16, 7, 15, 9, 1, -12 }, // '$' - { 30, 11, 10, 13, 0, -10 }, // '%' - { 44, 10, 10, 12, 1, -10 }, // '&' - { 57, 2, 3, 4, 1, -10 }, // ''' - { 58, 4, 13, 6, 1, -10 }, // '(' - { 65, 4, 13, 6, 0, -10 }, // ')' - { 72, 5, 6, 7, 1, -11 }, // '*' - { 76, 8, 7, 9, 0, -9 }, // '+' - { 83, 2, 4, 5, 1, -2 }, // ',' - { 84, 4, 2, 6, 0, -5 }, // '-' - { 85, 2, 2, 5, 1, -2 }, // '.' - { 86, 4, 10, 5, 0, -10 }, // '/' - { 91, 7, 10, 9, 1, -10 }, // '0' - { 100, 5, 10, 9, 1, -10 }, // '1' - { 107, 7, 10, 9, 1, -10 }, // '2' - { 116, 7, 10, 9, 1, -10 }, // '3' - { 125, 8, 10, 9, 0, -10 }, // '4' - { 135, 7, 10, 9, 1, -10 }, // '5' - { 144, 7, 10, 9, 1, -10 }, // '6' - { 153, 7, 10, 9, 1, -10 }, // '7' - { 162, 7, 10, 9, 1, -10 }, // '8' - { 171, 8, 10, 9, 0, -10 }, // '9' - { 181, 2, 7, 5, 1, -7 }, // ':' - { 183, 2, 9, 5, 1, -7 }, // ';' - { 186, 7, 8, 9, 1, -9 }, // '<' - { 193, 7, 5, 9, 1, -7 }, // '=' - { 198, 7, 8, 9, 1, -9 }, // '>' - { 205, 7, 10, 9, 1, -10 }, // '?' - { 214, 12, 13, 15, 1, -10 }, // '@' - { 234, 9, 10, 11, 1, -10 }, // 'A' - { 246, 8, 10, 11, 1, -10 }, // 'B' - { 256, 9, 10, 11, 1, -10 }, // 'C' - { 268, 9, 10, 11, 1, -10 }, // 'D' - { 280, 8, 10, 10, 1, -10 }, // 'E' - { 290, 7, 10, 9, 1, -10 }, // 'F' - { 299, 9, 10, 12, 1, -10 }, // 'G' - { 311, 9, 10, 12, 1, -10 }, // 'H' - { 323, 2, 10, 5, 1, -10 }, // 'I' - { 326, 7, 10, 9, 0, -10 }, // 'J' - { 335, 9, 10, 11, 1, -10 }, // 'K' - { 347, 7, 10, 9, 1, -10 }, // 'L' - { 356, 10, 10, 13, 1, -10 }, // 'M' - { 369, 9, 10, 12, 1, -10 }, // 'N' - { 381, 10, 10, 12, 1, -10 }, // 'O' - { 394, 8, 10, 10, 1, -10 }, // 'P' - { 404, 11, 11, 12, 1, -10 }, // 'Q' - { 420, 8, 10, 11, 1, -10 }, // 'R' - { 430, 8, 10, 10, 1, -10 }, // 'S' - { 440, 8, 10, 10, 0, -10 }, // 'T' - { 450, 9, 10, 12, 1, -10 }, // 'U' - { 462, 9, 10, 11, 0, -10 }, // 'V' - { 474, 13, 10, 14, 0, -10 }, // 'W' - { 491, 8, 10, 9, 0, -10 }, // 'X' - { 501, 8, 10, 10, 0, -10 }, // 'Y' - { 511, 9, 10, 10, 0, -10 }, // 'Z' - { 523, 4, 13, 6, 1, -10 }, // '[' - { 530, 4, 10, 5, 0, -10 }, // '\' - { 535, 4, 13, 6, 0, -10 }, // ']' - { 542, 6, 6, 9, 1, -10 }, // '^' - { 547, 7, 1, 8, 0, 1 }, // '_' - { 548, 2, 2, 6, 1, -10 }, // '`' - { 549, 7, 7, 9, 1, -7 }, // 'a' - { 556, 7, 10, 10, 1, -10 }, // 'b' - { 565, 7, 7, 9, 1, -7 }, // 'c' - { 572, 7, 10, 10, 1, -10 }, // 'd' - { 581, 7, 7, 9, 1, -7 }, // 'e' - { 588, 5, 10, 6, 0, -10 }, // 'f' - { 595, 7, 10, 10, 1, -7 }, // 'g' - { 604, 7, 10, 9, 1, -10 }, // 'h' - { 613, 2, 10, 5, 1, -10 }, // 'i' - { 616, 4, 13, 5, -1, -10 }, // 'j' - { 623, 7, 10, 9, 1, -10 }, // 'k' - { 632, 2, 10, 5, 1, -10 }, // 'l' - { 635, 11, 7, 13, 1, -7 }, // 'm' - { 645, 7, 7, 9, 1, -7 }, // 'n' - { 652, 7, 7, 9, 1, -7 }, // 'o' - { 659, 7, 10, 10, 1, -7 }, // 'p' - { 668, 7, 10, 10, 1, -7 }, // 'q' - { 677, 5, 7, 7, 1, -7 }, // 'r' - { 682, 6, 7, 9, 1, -7 }, // 's' - { 688, 5, 10, 6, 0, -10 }, // 't' - { 695, 7, 7, 9, 1, -7 }, // 'u' - { 702, 7, 7, 9, 0, -7 }, // 'v' - { 709, 11, 7, 12, 0, -7 }, // 'w' - { 719, 7, 7, 8, 0, -7 }, // 'x' - { 726, 7, 10, 9, 0, -7 }, // 'y' - { 735, 7, 7, 8, 0, -7 }, // 'z' - { 742, 5, 13, 6, 0, -10 }, // '{' - { 751, 2, 13, 5, 1, -10 }, // '|' - { 755, 5, 13, 6, 1, -10 } // '}' character 0x7D -}; -const GFXfont ArialRoundedMTBold_14 PROGMEM = { // Last character bug fixed 0x7E to 0x7D -(uint8_t *)ArialRoundedMTBold_14Bitmaps,(GFXglyph *)ArialRoundedMTBold_14Glyphs,0x20, 0x7D, 17}; - diff --git a/examples/320 x 240/weather-station/ArialRoundedMTBold_36.h b/examples/320 x 240/weather-station/ArialRoundedMTBold_36.h deleted file mode 100644 index a171dbe..0000000 --- a/examples/320 x 240/weather-station/ArialRoundedMTBold_36.h +++ /dev/null @@ -1,226 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -// Created by http://oleddisplay.squix.ch/ Consider a donation -// In case of problems make sure that you are using the font file with the correct version! - -// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected -// this avoids screen corruption if ~ is printed - -// Bodmer change: '`' changed to tiny degree symbol (typically this character is on top left key of a QWERTY keyboard) - -const uint8_t ArialRoundedMTBold_36Bitmaps[] PROGMEM = { - - // Bitmap Data: - 0x00, // ' ' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x39,0xCE,0x73,0x00,0x00,0x3B,0xFF,0xFB,0x80, // '!' - 0xFC,0xFF,0xF3,0xFF,0xCF,0xFF,0x3F,0xFC,0xFF,0xF3,0xFF,0xCF,0xDE,0x1E,0x78,0x78, // '"' - 0x01,0x83,0x80,0x78,0x70,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x0F,0x0F,0x01,0xE1,0xE3,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x07,0x87,0x80,0xF0,0xE0,0x1E,0x3C,0x07,0x87,0x80,0xF0,0xF0,0x7F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xE3,0xC3,0xC0,0x78,0x78,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x07,0x06,0x00, // '#' - 0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x7F,0xE0,0x3F,0xFE,0x0F,0xFF,0xE1,0xF3,0x7E,0x7C,0x67,0xCF,0x0C,0x79,0xE1,0x8F,0x3C,0x30,0xC7,0xC6,0x00,0xFE,0xC0,0x0F,0xF8,0x00,0xFF,0xE0,0x0F,0xFF,0x00,0x7F,0xF0,0x01,0xFF,0x00,0x37,0xE0,0x06,0x3E,0xE0,0xC3,0xFC,0x18,0x7F,0xC3,0x0F,0xF8,0x61,0xEF,0x8C,0x79,0xFD,0x9F,0x1F,0xFF,0xC1,0xFF,0xF0,0x0F,0xFC,0x00,0x38,0x00,0x03,0x00,0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x06,0x00, // '$' - 0x1F,0x00,0x06,0x03,0xFC,0x00,0x70,0x1C,0x70,0x03,0x01,0xC1,0x80,0x38,0x0E,0x0E,0x03,0x80,0x70,0x70,0x1C,0x03,0x83,0x81,0xC0,0x1C,0x1C,0x0C,0x00,0xE0,0xE0,0xE0,0x07,0x07,0x0E,0x00,0x1C,0x70,0x70,0x00,0xFF,0x87,0x00,0x03,0xF8,0x30,0x00,0x00,0x03,0x87,0xF0,0x00,0x38,0x7F,0xC0,0x01,0xC3,0x8E,0x00,0x1C,0x38,0x38,0x00,0xC1,0xC1,0xC0,0x0E,0x0E,0x0E,0x00,0xE0,0x70,0x70,0x07,0x03,0x83,0x80,0x70,0x1C,0x1C,0x07,0x00,0xE0,0xE0,0x38,0x03,0x8E,0x03,0x80,0x0F,0xE0,0x1C,0x00,0x3E,0x00,0xC0,0x00,0x00, // '%' - 0x00,0xFC,0x00,0x01,0xFF,0x80,0x01,0xFF,0xE0,0x01,0xF0,0xF0,0x00,0xF0,0x3C,0x00,0x78,0x1E,0x00,0x3C,0x0F,0x00,0x1F,0x0F,0x80,0x0F,0xDF,0x80,0x03,0xFF,0x80,0x00,0xFF,0x80,0x00,0xFF,0x00,0x00,0xFF,0xC1,0x81,0xFF,0xF0,0xE1,0xF9,0xF8,0xF8,0xF8,0x7E,0x78,0xF8,0x1F,0xFC,0x7C,0x07,0xFC,0x3E,0x01,0xFE,0x1F,0x00,0x7F,0x0F,0xC0,0x3F,0xC3,0xF0,0x7F,0xF1,0xFF,0xFF,0xFC,0x7F,0xFF,0x3F,0x0F,0xFE,0x0F,0x01,0xFC,0x03,0x80, // '&' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x78, // ''' - 0x03,0x81,0xC1,0xC1,0xE0,0xF0,0xF0,0xF8,0x78,0x3C,0x3E,0x1F,0x0F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x83,0xC1,0xF0,0xF8,0x3C,0x1E,0x0F,0x83,0xC0,0xF0,0x78,0x1C,0x07,0x01,0x80, // '(' - 0xE0,0x70,0x1C,0x0F,0x03,0x81,0xE0,0xF8,0x3C,0x1E,0x0F,0x87,0xC1,0xE0,0xF8,0x7C,0x3E,0x1F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x78,0x7C,0x3E,0x1E,0x0F,0x0F,0x87,0x83,0x83,0xC1,0xC1,0xC0,0xE0,0x00, // ')' - 0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x0E,0x38,0xFF,0x77,0xDF,0xFF,0x07,0xF0,0x07,0xC0,0x1D,0xC0,0x3B,0xC0,0xE3,0x83,0xC7,0x83,0x06,0x00, // '*' - 0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00, // '+' - 0x7B,0xEF,0xFF,0x7C,0x71,0xCE,0x7B,0xCE,0x00, // ',' - 0x7F,0xDF,0xFF,0xFF,0xBF,0xE0, // '-' - 0x77,0xFF,0xF7,0x00, // '.' - 0x03,0x81,0xC1,0xE0,0xF0,0x70,0x78,0x3C,0x1E,0x0E,0x07,0x07,0x83,0xC1,0xC0,0xE0,0xF0,0x78,0x38,0x1C,0x1E,0x0F,0x07,0x03,0x83,0xC1,0xE0,0xE0,0x70,0x00, // '/' - 0x03,0xF0,0x03,0xFF,0x01,0xFF,0xE0,0xFF,0xFC,0x3E,0x1F,0x1F,0x03,0xE7,0xC0,0xF9,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x79,0xF0,0x3E,0x7C,0x0F,0x8F,0x87,0xC3,0xFF,0xF0,0x7F,0xF8,0x0F,0xFC,0x00,0xFC,0x00, // '0' - 0x00,0x30,0x03,0xC0,0x3E,0x03,0xF0,0x3F,0x83,0xFC,0x7F,0xEF,0xDF,0xFC,0xFF,0xC7,0xD8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x03,0x80, // '1' - 0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0x9F,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0xF0,0x07,0xD8,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x1F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xF0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xF0, // '2' - 0x03,0xF0,0x07,0xFF,0x03,0xFF,0xE1,0xF0,0xFC,0x78,0x1F,0x1E,0x03,0xE7,0x00,0xF8,0x80,0x3E,0x00,0x1F,0x00,0x0F,0xC0,0x7F,0xE0,0x1F,0xF0,0x07,0xFE,0x01,0xFF,0xC0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xD8,0x01,0xFF,0x00,0x7F,0xE0,0x1F,0xF8,0x0F,0x9F,0x07,0xE7,0xFF,0xF0,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '3' - 0x00,0x0F,0x00,0x00,0xFC,0x00,0x07,0xE0,0x00,0x7F,0x00,0x07,0xF8,0x00,0x7F,0xC0,0x03,0xFE,0x00,0x3D,0xF0,0x03,0xCF,0x80,0x3C,0x7C,0x03,0xE3,0xE0,0x1E,0x1F,0x01,0xE0,0xF8,0x1E,0x07,0xC1,0xF0,0x3E,0x0F,0x01,0xF0,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE0,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x38,0x00, // '4' - 0x1F,0xFF,0x8F,0xFF,0xE3,0xFF,0xF8,0xFF,0xFC,0x3C,0x00,0x0F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x78,0x00,0x1E,0x7E,0x07,0xFF,0xE1,0xFF,0xFC,0xFF,0xFF,0xBF,0x07,0xE7,0x80,0xFC,0x80,0x1F,0x00,0x07,0xC0,0x01,0xF6,0x00,0x7F,0xC0,0x1F,0xF0,0x0F,0xBE,0x03,0xE7,0xC1,0xF1,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '5' - 0x03,0xF8,0x01,0xFF,0x81,0xFF,0xF0,0x7C,0x7C,0x3C,0x0F,0x9F,0x03,0xE7,0x80,0x71,0xE0,0x00,0xF8,0x00,0x3E,0x3E,0x0F,0xBF,0xE3,0xFF,0xFC,0xFE,0x1F,0xBF,0x03,0xEF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x7D,0xF0,0x1F,0x7C,0x0F,0x8F,0x87,0xE3,0xFF,0xF0,0x7F,0xFC,0x0F,0xFC,0x00,0xFC,0x00, // '6' - 0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x00,0x0F,0x80,0x07,0xC0,0x01,0xE0,0x00,0xF8,0x00,0x7C,0x00,0x1E,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x3E,0x00,0x0F,0x80,0x07,0xC0,0x01,0xF0,0x00,0x7C,0x00,0x3F,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x01,0xC0,0x00, // '7' - 0x03,0xF8,0x01,0xFF,0xC0,0x7F,0xFC,0x1F,0x0F,0xC7,0xC0,0xFC,0xF8,0x0F,0x9F,0x01,0xF3,0xE0,0x3E,0x7C,0x07,0xCF,0x80,0xF0,0xF8,0x7E,0x0F,0xFF,0x80,0xFF,0xE0,0x7F,0xFE,0x1F,0x83,0xF3,0xE0,0x3E,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0x80,0x3E,0xF8,0x0F,0x9F,0x83,0xF1,0xFF,0xFC,0x1F,0xFF,0x00,0x7F,0x00, // '8' - 0x03,0xF0,0x03,0xFF,0x03,0xFF,0xE0,0xFF,0xFC,0x7E,0x1F,0x1F,0x03,0xEF,0x80,0xFB,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x0F,0xDF,0x87,0xF3,0xFF,0xFC,0x7F,0xDF,0x07,0xC7,0xC0,0x01,0xF0,0x00,0x78,0xE0,0x1E,0x78,0x0F,0x9F,0x03,0xC3,0xE3,0xE0,0xFF,0xF8,0x1F,0xF8,0x01,0xF8,0x00, // '9' - 0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDF,0xFF,0xDC, // ':' - 0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDE,0xFF,0xFE,0x73,0x9B,0xDC,0xC0, // ';' - 0x00,0x00,0x40,0x00,0x70,0x00,0xFC,0x00,0xFF,0x00,0xFF,0xC1,0xFF,0xE1,0xFF,0xC1,0xFF,0xC0,0xFF,0x80,0x3F,0x80,0x0F,0xE0,0x03,0xFE,0x00,0x7F,0xF0,0x07,0xFF,0x00,0x7F,0xF8,0x03,0xFF,0x00,0x3F,0xC0,0x03,0xF0,0x00,0x1C,0x00,0x01, // '<' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, // '=' - 0x80,0x00,0x38,0x00,0x0F,0xC0,0x03,0xFC,0x00,0xFF,0xC0,0x1F,0xFE,0x00,0xFF,0xE0,0x0F,0xFE,0x00,0x7F,0xC0,0x07,0xF0,0x01,0xFC,0x01,0xFF,0x03,0xFF,0x83,0xFF,0x87,0xFF,0x83,0xFF,0x00,0xFF,0x00,0x3F,0x00,0x0E,0x00,0x02,0x00,0x00, // '>' - 0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0xBF,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0x70,0x07,0xC8,0x03,0xE0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x1F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x38,0x00, // '?' - 0x00,0x07,0xFE,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x0F,0xFF,0xFE,0x00,0x07,0xE0,0x0F,0xE0,0x07,0xC0,0x00,0x7C,0x03,0xE0,0x00,0x0F,0x00,0xE0,0x00,0x01,0xE0,0x70,0x1F,0x9F,0x3C,0x3C,0x1F,0xF7,0xC7,0x0E,0x0F,0xFF,0xE1,0xC7,0x07,0xE3,0xF8,0x39,0xC3,0xE0,0x7E,0x0E,0x70,0xF8,0x0F,0x83,0xB8,0x7C,0x03,0xE0,0xEE,0x1F,0x00,0xF0,0x3B,0x8F,0x80,0x3C,0x0E,0xE3,0xE0,0x1F,0x07,0xB8,0xF8,0x07,0xC1,0xCE,0x3E,0x01,0xE0,0xF3,0x8F,0x80,0xF8,0x78,0xE3,0xE0,0x3E,0x1E,0x1C,0x7C,0x1F,0x9F,0x07,0x1F,0xFF,0xFF,0x81,0xC3,0xFF,0xFF,0xC0,0x38,0x7F,0xBF,0xE0,0x0F,0x07,0x87,0xE0,0x01,0xE0,0x00,0x00,0x3C,0x3C,0x00,0x00,0x3E,0x07,0xC0,0x00,0x1F,0x00,0xFE,0x00,0x3F,0x80,0x1F,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x80,0x00,0x07,0xFF,0x00,0x00, // '@' - 0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x01,0xFF,0x00,0x01,0xFF,0x80,0x01,0xEF,0x80,0x03,0xE7,0xC0,0x03,0xE7,0xC0,0x07,0xC7,0xC0,0x07,0xC3,0xE0,0x07,0xC3,0xE0,0x0F,0x81,0xF0,0x0F,0x81,0xF0,0x1F,0x81,0xF8,0x1F,0x00,0xF8,0x1F,0xFF,0xF8,0x3F,0xFF,0xFC,0x3F,0xFF,0xFC,0x7F,0xFF,0xFE,0x7C,0x00,0x7E,0x7C,0x00,0x3E,0xFC,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x1F,0x70,0x00,0x0E, // 'A' - 0x7F,0xFF,0x07,0xFF,0xFC,0x3F,0xFF,0xF1,0xFF,0xFF,0xCF,0x80,0x7F,0x7C,0x01,0xFB,0xE0,0x07,0xDF,0x00,0x3E,0xF8,0x01,0xF7,0xC0,0x1F,0x3E,0x01,0xF9,0xFF,0xFF,0x8F,0xFF,0xF0,0x7F,0xFF,0xE3,0xFF,0xFF,0x9F,0x00,0x7E,0xF8,0x01,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x01,0xFB,0xFF,0xFF,0xDF,0xFF,0xFC,0xFF,0xFF,0xC3,0xFF,0xF8,0x00, // 'B' - 0x00,0xFF,0x00,0x07,0xFF,0x80,0x3F,0xFF,0xC0,0xFF,0xFF,0xC3,0xF8,0x1F,0xC7,0xE0,0x1F,0x9F,0x80,0x1F,0x3E,0x00,0x1F,0x7C,0x00,0x3D,0xF0,0x00,0x33,0xE0,0x00,0x07,0xC0,0x00,0x0F,0x80,0x00,0x1F,0x00,0x00,0x3E,0x00,0x00,0x7C,0x00,0x04,0xF8,0x00,0x1C,0xF8,0x00,0x7D,0xF0,0x00,0xFB,0xF0,0x03,0xE3,0xF0,0x0F,0xC7,0xF0,0x3F,0x07,0xFF,0xFE,0x07,0xFF,0xF8,0x03,0xFF,0xC0,0x01,0xFE,0x00, // 'C' - 0x7F,0xFE,0x03,0xFF,0xFE,0x0F,0xFF,0xFC,0x3F,0xFF,0xF8,0xF8,0x07,0xF3,0xE0,0x07,0xEF,0x80,0x1F,0xBE,0x00,0x3E,0xF8,0x00,0xFF,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x03,0xFF,0x80,0x0F,0xBE,0x00,0x7E,0xF8,0x01,0xFB,0xE0,0x1F,0xCF,0xFF,0xFE,0x3F,0xFF,0xF0,0xFF,0xFF,0x81,0xFF,0xF8,0x00, // 'D' - 0x7F,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFE,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xCF,0xFF,0xFC,0xFF,0xFF,0xCF,0xFF,0xFC,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFE, // 'E' - 0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xFF,0xF8,0xFF,0xFF,0x3F,0xFF,0xCF,0xFF,0xE3,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x1C,0x00,0x00, // 'F' - 0x00,0x7F,0x80,0x03,0xFF,0xF0,0x07,0xFF,0xF8,0x1F,0xFF,0xFC,0x1F,0xC1,0xFE,0x3F,0x00,0x7E,0x7E,0x00,0x3E,0x7C,0x00,0x3E,0x7C,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x07,0xFE,0xF8,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x07,0xFF,0xF8,0x00,0x1F,0x7C,0x00,0x1F,0x7C,0x00,0x1F,0x7E,0x00,0x1F,0x3F,0x00,0x3F,0x1F,0xC0,0xFF,0x1F,0xFF,0xFE,0x07,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0x7F,0x80, // 'G' - 0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'H' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'I' - 0x00,0x07,0x00,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x70,0x0F,0xFC,0x07,0xFE,0x03,0xFF,0x01,0xFF,0xC1,0xFB,0xF1,0xF9,0xFF,0xFC,0x7F,0xFC,0x1F,0xFC,0x03,0xF8,0x00, // 'J' - 0x70,0x00,0xE3,0xE0,0x07,0xCF,0x80,0x3F,0x3E,0x01,0xFC,0xF8,0x0F,0xE3,0xE0,0x7F,0x0F,0x83,0xF8,0x3E,0x1F,0xC0,0xF8,0xFE,0x03,0xE7,0xF0,0x0F,0xBF,0x80,0x3F,0xFF,0x00,0xFF,0xFC,0x03,0xFF,0xF8,0x0F,0xFB,0xF0,0x3F,0xCF,0xE0,0xFE,0x1F,0x83,0xE0,0x3F,0x0F,0x80,0xFE,0x3E,0x01,0xF8,0xF8,0x03,0xF3,0xE0,0x0F,0xEF,0x80,0x1F,0xBE,0x00,0x3F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'K' - 0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xE0, // 'L' - 0x7E,0x00,0x3F,0x7F,0x80,0x3F,0xFF,0xE0,0x1F,0xFF,0xF0,0x1F,0xFF,0xF8,0x0F,0xFF,0xFC,0x07,0xFF,0xFF,0x07,0xFF,0xFF,0x83,0xFF,0xFB,0xC1,0xEF,0xFD,0xE0,0xF7,0xFE,0xF8,0xFB,0xFF,0x7C,0x7D,0xFF,0x9E,0x3C,0xFF,0xCF,0x1E,0x7F,0xE7,0xDF,0x3F,0xF3,0xEF,0x9F,0xF8,0xF7,0x8F,0xFC,0x7B,0xC7,0xFE,0x3F,0xE3,0xFF,0x1F,0xF1,0xFF,0x87,0xF0,0xFF,0xC3,0xF8,0x7F,0xE1,0xFC,0x3F,0xF0,0x7C,0x1F,0xF8,0x3E,0x0F,0xB8,0x0E,0x03,0x80, // 'M' - 0x78,0x00,0x3B,0xF0,0x01,0xFF,0xC0,0x07,0xFF,0x80,0x1F,0xFF,0x00,0x7F,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xF0,0x1F,0xFF,0xE0,0x7F,0xEF,0x81,0xFF,0x9F,0x07,0xFE,0x7E,0x1F,0xF8,0xF8,0x7F,0xE1,0xF1,0xFF,0x87,0xE7,0xFE,0x0F,0x9F,0xF8,0x1F,0x7F,0xE0,0x7F,0xFF,0x80,0xFF,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xE0,0x0F,0xFF,0x80,0x1F,0xFE,0x00,0x7F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'N' - 0x00,0xFF,0x00,0x01,0xFF,0xF0,0x03,0xFF,0xFE,0x03,0xFF,0xFF,0x83,0xFC,0x1F,0xE1,0xF8,0x03,0xF1,0xF8,0x00,0xFC,0xF8,0x00,0x3E,0x7C,0x00,0x1F,0x7C,0x00,0x07,0xFE,0x00,0x03,0xFF,0x00,0x01,0xFF,0x80,0x00,0xFF,0xC0,0x00,0x7F,0xE0,0x00,0x3F,0xF0,0x00,0x1F,0xFC,0x00,0x0F,0xBE,0x00,0x0F,0x9F,0x00,0x07,0xCF,0xC0,0x07,0xE3,0xF0,0x07,0xE0,0xFE,0x0F,0xF0,0x7F,0xFF,0xF0,0x1F,0xFF,0xF0,0x03,0xFF,0xE0,0x00,0x3F,0xC0,0x00, // 'O' - 0x7F,0xFC,0x1F,0xFF,0xE3,0xFF,0xFE,0x7F,0xFF,0xEF,0x80,0xFD,0xF0,0x0F,0xFE,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFC,0x07,0xEF,0xFF,0xFD,0xFF,0xFF,0x3F,0xFF,0xC7,0xFF,0xE0,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'P' - 0x00,0xFF,0x00,0x00,0xFF,0xF8,0x00,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x3F,0xC1,0xFE,0x0F,0xC0,0x1F,0x87,0xE0,0x03,0xF1,0xF0,0x00,0x7C,0x7C,0x00,0x1F,0x3E,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0xBE,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0x9F,0x07,0x07,0xC7,0xC1,0xF1,0xF1,0xF8,0x3F,0xFC,0x3F,0x03,0xFE,0x07,0xF0,0x7F,0x81,0xFF,0xFF,0xC0,0x1F,0xFF,0xF8,0x03,0xFF,0xFF,0x80,0x1F,0xE3,0xF0,0x00,0x00,0x7C,0x00,0x00,0x07, // 'Q' - 0x7F,0xFF,0x07,0xFF,0xFE,0x3F,0xFF,0xF9,0xFF,0xFF,0xEF,0x80,0x3F,0xFC,0x00,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x0F,0xFE,0x00,0xFD,0xFF,0xFF,0xEF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x1F,0x07,0xE0,0xF8,0x1F,0x87,0xC0,0x7E,0x3E,0x01,0xF9,0xF0,0x0F,0xCF,0x80,0x3F,0x7C,0x00,0xFF,0xE0,0x07,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0xC0, // 'R' - 0x03,0xF8,0x01,0xFF,0xF0,0x3F,0xFF,0x87,0xFF,0xFC,0x7E,0x0F,0xCF,0xC0,0x7E,0xF8,0x03,0xEF,0x80,0x1E,0xFC,0x00,0xCF,0xF0,0x00,0x7F,0xF0,0x03,0xFF,0xE0,0x1F,0xFF,0x80,0x7F,0xFC,0x00,0x7F,0xE0,0x00,0x7F,0x60,0x03,0xFF,0x00,0x1F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xFF,0xE0,0x7E,0x7F,0xFF,0xC3,0xFF,0xFC,0x0F,0xFF,0x00,0x3F,0xC0, // 'S' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'T' - 0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF8,0x03,0xF7,0xC0,0x1F,0x3F,0x83,0xF8,0xFF,0xFF,0x83,0xFF,0xF8,0x0F,0xFF,0x80,0x1F,0xF0,0x00, // 'U' - 0x70,0x00,0x1D,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xE0,0x03,0xF7,0xC0,0x07,0xCF,0x80,0x0F,0x9F,0x80,0x3F,0x1F,0x00,0x7C,0x3F,0x00,0xF8,0x7E,0x03,0xE0,0x7C,0x07,0xC0,0xFC,0x0F,0x80,0xF8,0x3E,0x01,0xF0,0x7C,0x03,0xF0,0xF8,0x03,0xE3,0xE0,0x07,0xC7,0xC0,0x07,0xDF,0x00,0x0F,0xBE,0x00,0x1F,0x7C,0x00,0x1F,0xF0,0x00,0x3F,0xE0,0x00,0x7F,0x80,0x00,0x7F,0x00,0x00,0xFE,0x00,0x00,0x70,0x00, // 'V' - 0x70,0x03,0xC0,0x0E,0xF8,0x07,0xE0,0x1F,0xF8,0x07,0xE0,0x1F,0xF8,0x0F,0xF0,0x1F,0xF8,0x0F,0xF0,0x1F,0x7C,0x0F,0xF0,0x3E,0x7C,0x0F,0xF0,0x3E,0x7C,0x1F,0xF8,0x3E,0x7C,0x1E,0x78,0x3E,0x3E,0x1E,0x78,0x7C,0x3E,0x1E,0x78,0x7C,0x3E,0x3E,0x7C,0x7C,0x3E,0x3C,0x3C,0x7C,0x1E,0x3C,0x3C,0x78,0x1F,0x7C,0x3E,0xF8,0x1F,0x78,0x1E,0xF8,0x1F,0x78,0x1E,0xF8,0x0F,0x78,0x1E,0xF0,0x0F,0xF8,0x1F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xC0,0x03,0xC0, // 'W' - 0x38,0x00,0x73,0xE0,0x07,0x9F,0x00,0x7E,0xFC,0x07,0xE3,0xF0,0x3F,0x1F,0x83,0xF0,0x7E,0x3F,0x01,0xF9,0xF8,0x0F,0xDF,0x80,0x3F,0xF8,0x00,0xFF,0xC0,0x07,0xFC,0x00,0x1F,0xC0,0x00,0xFE,0x00,0x0F,0xF8,0x00,0xFF,0xE0,0x07,0xFF,0x80,0x7E,0xFC,0x07,0xE3,0xF0,0x7F,0x1F,0xC3,0xF0,0x7E,0x3F,0x01,0xFB,0xF0,0x07,0xFF,0x80,0x3F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'X' - 0x70,0x00,0x77,0xC0,0x07,0xFF,0x00,0x3E,0xF8,0x03,0xF7,0xE0,0x3F,0x1F,0x01,0xF0,0xFC,0x1F,0x83,0xF0,0xF8,0x0F,0x8F,0x80,0x7E,0xFC,0x01,0xF7,0xC0,0x07,0xFC,0x00,0x3F,0xE0,0x00,0xFE,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'Y' - 0x3F,0xFF,0xF8,0x7F,0xFF,0xF9,0xFF,0xFF,0xF1,0xFF,0xFF,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0x00,0x00,0xFC,0x00,0x03,0xF0,0x00,0x0F,0xE0,0x00,0x3F,0x80,0x00,0x7E,0x00,0x01,0xF8,0x00,0x07,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF8, // 'Z' - 0x7F,0xFF,0xFF,0xFF,0xFF,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3F,0xFF,0xFF,0xFF,0x7F,0xC0, // '[' - 0x70,0x3C,0x07,0x01,0xE0,0x78,0x1E,0x03,0x80,0xF0,0x3C,0x0F,0x01,0xC0,0x78,0x1E,0x07,0x80,0xE0,0x3C,0x0F,0x03,0xC0,0x70,0x1E,0x07,0x81,0xE0,0x38,0x0F,0x03,0xC0,0x60, // '\' - 0xFF,0xBF,0xFF,0xFF,0xFF,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x80, // ']' - 0x03,0xE0,0x01,0xF0,0x01,0xFC,0x00,0xFE,0x00,0x7F,0x80,0x7B,0xC0,0x3D,0xF0,0x3E,0xF8,0x1E,0x3C,0x1F,0x1F,0x0F,0x07,0x8F,0x83,0xE7,0xC1,0xF7,0xC0,0x7C, // '^' - 0xFF,0xFF,0xFF,0xFF,0xF0, // '_' - 0x0E,0x1B,0x11,0x1B,0x0E, // '`' Changed into a degree symbol - 0x03,0xFC,0x03,0xFF,0xE0,0xFF,0xFE,0x3F,0x07,0xC7,0xC0,0x7C,0xF0,0x0F,0x9C,0x01,0xF0,0x00,0xFE,0x01,0xFF,0xC3,0xFF,0xF8,0xFF,0x9F,0x3F,0x03,0xEF,0x80,0x7D,0xF0,0x0F,0xBE,0x03,0xF7,0xE1,0xFE,0x7F,0xFF,0xE7,0xFE,0x7C,0x3E,0x07,0x00, // 'a' - 0x70,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC7,0xE0,0xF9,0xFF,0x1F,0x7F,0xF3,0xFF,0xFF,0x7F,0x87,0xEF,0xE0,0x7D,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFE,0x03,0xFF,0xC0,0x7D,0xFE,0x1F,0xBF,0xFF,0xE7,0xDF,0xFC,0xF9,0xFF,0x0E,0x1F,0x80, // 'b' - 0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xFF,0xFE,0x7F,0x0F,0xDF,0x01,0xFF,0xC0,0x3F,0xE0,0x04,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x07,0xFC,0x03,0xDF,0x01,0xF7,0xF0,0xFC,0xFF,0xFE,0x1F,0xFF,0x83,0xFF,0x80,0x3F,0x80, // 'c' - 0x00,0x01,0xC0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x3F,0x1F,0x1F,0xF3,0xE7,0xFF,0x7D,0xFF,0xFF,0xBF,0x0F,0xF7,0xC0,0xFF,0xF8,0x0F,0xFE,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFE,0x03,0xF7,0xC0,0x7E,0xFC,0x3F,0xCF,0xFF,0xF9,0xFF,0xDF,0x1F,0xF3,0xE0,0xF8,0x38, // 'd' - 0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xF8,0x7E,0x7C,0x07,0x9F,0x01,0xFF,0x80,0x7F,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x77,0xC0,0x3C,0xFC,0x3F,0x1F,0xFF,0x83,0xFF,0xC0,0x3F,0x80, // 'e' - 0x01,0xF8,0x0F,0xF8,0x1F,0xF8,0x7F,0xE0,0xF8,0x01,0xF0,0x03,0xE0,0x3F,0xF8,0x7F,0xF9,0xFF,0xF1,0xFF,0xC0,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x3E,0x00,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x0E,0x00, // 'f' - 0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0xBF,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x8F,0x80,0x01,0xF7,0x00,0x7E,0xF0,0x0F,0x9F,0x83,0xF3,0xFF,0xFC,0x1F,0xFF,0x00,0xFF,0x80, // 'g' - 0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE3,0xF0,0xF9,0xFF,0x3E,0xFF,0xEF,0xFF,0xFB,0xF8,0x3F,0xFC,0x0F,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xDC,0x00,0xE0, // 'h' - 0x77,0xFF,0xF7,0x00,0x0E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'i' - 0x03,0x81,0xF0,0x7C,0x1F,0x03,0x80,0x00,0x00,0x0E,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFB,0xFE,0x7E,0x00, // 'j' - 0x70,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x1C,0xF8,0x1E,0x7C,0x1F,0x3E,0x1F,0x9F,0x1F,0x8F,0x9F,0x07,0xDF,0x03,0xFF,0x81,0xFF,0xE0,0xFF,0xF0,0x7F,0x7C,0x3F,0x1F,0x1F,0x0F,0x8F,0x83,0xE7,0xC1,0xFB,0xE0,0x7D,0xF0,0x1F,0xF8,0x0F,0xB8,0x03,0x80, // 'k' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'l' - 0x70,0xFC,0x0F,0x8F,0x3F,0xE3,0xFC,0xFF,0xFF,0x7F,0xEF,0xFF,0xFF,0xFE,0xFE,0x1F,0xE3,0xFF,0xC0,0xFC,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0x70,0x07,0x00,0xE0, // 'm' - 0x70,0xFC,0x3C,0x7F,0xCF,0xBF,0xFB,0xFF,0xFE,0xFE,0x0F,0xFF,0x03,0xFF,0xC0,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x00,0x38, // 'n' - 0x01,0xF8,0x00,0xFF,0xF0,0x1F,0xFF,0x83,0xFF,0xFC,0x7F,0x0F,0xE7,0xC0,0x3E,0xFC,0x03,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xF7,0xC0,0x3E,0x7F,0x0F,0xE3,0xFF,0xFC,0x1F,0xFF,0x80,0xFF,0xF0,0x01,0xF8,0x00, // 'o' - 0x70,0xFC,0x1F,0x3F,0xE3,0xEF,0xFE,0x7F,0xFF,0xCF,0xF0,0xFD,0xF8,0x0F,0xBF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7F,0xF8,0x0F,0xBF,0xC3,0xF7,0xFF,0xFC,0xFB,0xFF,0x9F,0x3F,0xE3,0xE3,0xF0,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'p' - 0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0x9F,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x38, // 'q' - 0x71,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xE1,0x7E,0x03,0xF0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x1C,0x00, // 'r' - 0x0F,0xF0,0x1F,0xFE,0x1F,0xFF,0x8F,0x87,0xEF,0x81,0xF7,0xC0,0x7B,0xF0,0x00,0xFF,0x80,0x3F,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x0F,0xF6,0x01,0xFF,0x80,0x7F,0xE0,0x3F,0xF8,0x3E,0x7F,0xFF,0x1F,0xFF,0x03,0xFC,0x00, // 's' - 0x0E,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x0F,0xFC,0xFF,0xF7,0xFF,0x9F,0xF8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7F,0xE3,0xFF,0x0F,0xF8,0x3F,0x80, // 't' - 0x70,0x03,0xBE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFF,0x03,0xFF,0xE3,0xFD,0xFF,0xFF,0x7F,0xF7,0xCF,0xF8,0xF0,0xF8,0x38, // 'u' - 0x70,0x03,0xBC,0x00,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x07,0x9F,0x03,0xE3,0xC0,0xF0,0xF8,0x7C,0x3E,0x1E,0x07,0x87,0x81,0xF3,0xE0,0x3C,0xF0,0x0F,0x3C,0x01,0xFE,0x00,0x7F,0x80,0x1F,0xE0,0x03,0xF0,0x00,0xFC,0x00,0x1E,0x00, // 'v' - 0x70,0x0F,0x00,0xEF,0x00,0xF0,0x0F,0xF8,0x1F,0x81,0xFF,0x81,0xF8,0x1F,0x78,0x1F,0x81,0xE7,0x83,0xFC,0x1E,0x7C,0x3F,0xC3,0xE3,0xC3,0xFC,0x3C,0x3C,0x79,0xE3,0xC3,0xE7,0x9E,0x7C,0x1E,0x79,0xE7,0x81,0xE7,0x0E,0x78,0x0E,0xF0,0xF7,0x00,0xFF,0x0F,0xF0,0x0F,0xE0,0x7F,0x00,0x7E,0x07,0xE0,0x07,0xE0,0x7E,0x00,0x7C,0x03,0xE0,0x03,0xC0,0x3C,0x00, // 'w' - 0x70,0x07,0x3C,0x07,0xBF,0x07,0xEF,0xC7,0xE3,0xE3,0xE0,0xFB,0xE0,0x7F,0xE0,0x1F,0xF0,0x07,0xF0,0x03,0xF8,0x03,0xFE,0x01,0xFF,0x01,0xF7,0xC1,0xF1,0xF1,0xF8,0xFC,0xF8,0x3E,0xF8,0x0F,0xFC,0x07,0xDC,0x01,0xC0, // 'x' - 0x38,0x01,0xCF,0x80,0x3D,0xF0,0x0F,0xBE,0x01,0xF3,0xE0,0x3C,0x7C,0x0F,0x87,0x81,0xE0,0xF8,0x7C,0x1F,0x0F,0x81,0xE1,0xE0,0x3E,0x7C,0x03,0xCF,0x00,0x7D,0xE0,0x07,0xFC,0x00,0xFF,0x00,0x1F,0xE0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x07,0xC0,0x1F,0xF8,0x07,0xFE,0x00,0x7F,0xC0,0x07,0xE0,0x00, // 'y' - 0x7F,0xFF,0x1F,0xFF,0xE7,0xFF,0xF9,0xFF,0xFE,0x00,0x3F,0x00,0x1F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF8, // 'z' - 0x01,0xF0,0x1F,0xC1,0xFE,0x1F,0xE0,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x0F,0x81,0xFC,0x1F,0xC0,0xF8,0x07,0xF0,0x1F,0xC0,0x3E,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x07,0xF8,0x1F,0xE0,0x7F,0x01,0xF0, // '{' - 0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60, // '|' - 0x7C,0x07,0xF0,0x3F,0xC0,0xFF,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x03,0xE0,0x1F,0xC0,0x7F,0x00,0xF8,0x1F,0xC1,0xFC,0x0F,0x80,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x3F,0xC3,0xFC,0x1F,0xC0,0x7C,0x00 // '}' -}; -const GFXglyph ArialRoundedMTBold_36Glyphs[] PROGMEM = { -// bitmapOffset, width, height, xAdvance, xOffset, yOffset - { 0, 1, 1, 10, 0, 0 }, // ' ' - { 1, 5, 26, 13, 4, -26 }, // '!' - { 18, 14, 9, 18, 2, -26 }, // '"' - { 34, 19, 26, 21, 0, -26 }, // '#' - { 96, 19, 37, 22, 1, -30 }, // '$' - { 184, 29, 27, 32, 1, -26 }, // '%' - { 282, 25, 26, 28, 2, -26 }, // '&' - { 364, 6, 9, 10, 1, -26 }, // ''' - { 371, 9, 33, 14, 2, -26 }, // '(' - { 409, 9, 33, 14, 2, -26 }, // ')' - { 447, 15, 14, 17, 0, -28 }, // '*' - { 474, 19, 18, 22, 1, -22 }, // '+' - { 517, 6, 11, 12, 3, -5 }, // ',' - { 526, 11, 4, 13, 1, -11 }, // '-' - { 532, 5, 5, 12, 3, -5 }, // '.' - { 536, 9, 26, 11, 1, -26 }, // '/' - { 566, 18, 26, 22, 2, -26 }, // '0' - { 625, 13, 26, 22, 2, -26 }, // '1' - { 668, 18, 26, 22, 2, -26 }, // '2' - { 727, 18, 26, 22, 2, -26 }, // '3' - { 786, 21, 26, 22, 0, -26 }, // '4' - { 855, 18, 26, 22, 2, -26 }, // '5' - { 914, 18, 26, 22, 2, -26 }, // '6' - { 973, 18, 26, 22, 3, -26 }, // '7' - { 1032, 19, 26, 22, 1, -26 }, // '8' - { 1094, 18, 26, 22, 1, -26 }, // '9' - { 1153, 5, 19, 12, 3, -19 }, // ':' - { 1165, 5, 25, 12, 3, -19 }, // ';' - { 1181, 18, 20, 22, 1, -23 }, // '<' - { 1226, 18, 13, 22, 2, -19 }, // '=' - { 1256, 18, 20, 22, 1, -23 }, // '>' - { 1301, 18, 26, 22, 1, -26 }, // '?' - { 1360, 34, 33, 36, 1, -26 }, // '@' - { 1501, 24, 26, 27, 1, -26 }, // 'A' - { 1579, 21, 26, 27, 3, -26 }, // 'B' - { 1648, 23, 26, 28, 2, -26 }, // 'C' - { 1723, 22, 26, 28, 3, -26 }, // 'D' - { 1795, 20, 26, 25, 3, -26 }, // 'E' - { 1860, 18, 26, 23, 3, -26 }, // 'F' - { 1919, 24, 26, 30, 2, -26 }, // 'G' - { 1997, 21, 26, 28, 3, -26 }, // 'H' - { 2066, 5, 26, 12, 3, -26 }, // 'I' - { 2083, 17, 26, 22, 1, -26 }, // 'J' - { 2139, 22, 26, 28, 3, -26 }, // 'K' - { 2211, 18, 26, 23, 3, -26 }, // 'L' - { 2270, 25, 26, 31, 3, -26 }, // 'M' - { 2352, 22, 26, 28, 3, -26 }, // 'N' - { 2424, 25, 26, 30, 2, -26 }, // 'O' - { 2506, 19, 26, 25, 3, -26 }, // 'P' - { 2568, 26, 28, 30, 2, -26 }, // 'Q' - { 2659, 21, 26, 27, 3, -26 }, // 'R' - { 2728, 20, 26, 25, 2, -26 }, // 'S' - { 2793, 21, 26, 24, 1, -26 }, // 'T' - { 2862, 21, 26, 28, 3, -26 }, // 'U' - { 2931, 23, 26, 26, 1, -26 }, // 'V' - { 3006, 32, 26, 35, 1, -26 }, // 'W' - { 3110, 21, 26, 23, 0, -26 }, // 'X' - { 3179, 21, 26, 24, 1, -26 }, // 'Y' - { 3248, 23, 26, 24, 0, -26 }, // 'Z' - { 3323, 10, 33, 14, 2, -26 }, // '[' - { 3365, 10, 26, 11, 0, -26 }, // '\' - { 3398, 10, 33, 14, 0, -26 }, // ']' - { 3440, 17, 14, 22, 2, -26 }, // '^' - { 3470, 18, 2, 19, 0, 3 }, // '_' - { 3475, 8, 5, 10, 0, -26 }, // '`' Changed to degree symbol - { 3480, 19, 19, 22, 1, -19 }, // 'a' - { 3526, 19, 26, 24, 2, -26 }, // 'b' - { 3588, 18, 19, 22, 1, -19 }, // 'c' - { 3631, 19, 26, 24, 1, -26 }, // 'd' - { 3693, 18, 19, 22, 2, -19 }, // 'e' - { 3736, 15, 26, 13, -1, -26 }, // 'f' - { 3785, 19, 26, 24, 1, -19 }, // 'g' - { 3847, 18, 26, 23, 2, -26 }, // 'h' - { 3906, 5, 26, 11, 2, -26 }, // 'i' - { 3923, 10, 33, 11, -3, -26 }, // 'j' - { 3965, 17, 26, 22, 3, -26 }, // 'k' - { 4021, 5, 26, 11, 2, -26 }, // 'l' - { 4038, 28, 19, 33, 2, -19 }, // 'm' - { 4105, 18, 19, 23, 2, -19 }, // 'n' - { 4148, 20, 19, 23, 1, -19 }, // 'o' - { 4196, 19, 26, 24, 2, -19 }, // 'p' - { 4258, 19, 26, 24, 1, -19 }, // 'q' - { 4320, 13, 19, 17, 2, -19 }, // 'r' - { 4351, 17, 19, 21, 1, -19 }, // 's' - { 4392, 13, 26, 14, 0, -26 }, // 't' - { 4435, 18, 19, 23, 2, -19 }, // 'u' - { 4478, 18, 19, 21, 1, -19 }, // 'v' - { 4521, 28, 19, 30, 1, -19 }, // 'w' - { 4588, 17, 19, 20, 1, -19 }, // 'x' - { 4629, 19, 26, 21, 0, -19 }, // 'y' - { 4691, 18, 19, 20, 1, -19 }, // 'z' - { 4734, 13, 33, 15, 1, -26 }, // '{' - { 4788, 4, 33, 11, 3, -26 }, // '|' - { 4805, 13, 33, 15, 0, -26 } // '}' character 0x7D -}; -const GFXfont ArialRoundedMTBold_36 PROGMEM = { // Last character bug fixed 0x7E to 0x7D -(uint8_t *)ArialRoundedMTBold_36Bitmaps,(GFXglyph *)ArialRoundedMTBold_36Glyphs,0x20, 0x7D, 43}; - diff --git a/examples/320 x 240/weather-station/GfxUi.cpp b/examples/320 x 240/weather-station/GfxUi.cpp deleted file mode 100644 index c425abb..0000000 --- a/examples/320 x 240/weather-station/GfxUi.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_eSPI library: -https://github.com/Bodmer/TFT_eSPI - -Bodmer: Functions no longer needed weeded out, Jpeg decoder functions added -Bodmer: drawBMP() updated to buffer in and out pixels and use screen CGRAM rotation for faster bottom up drawing (now ~2x faster) -*/ - -#include "GfxUi.h" - -GfxUi::GfxUi(TFT_eSPI *tft) { - _tft = tft; -} - -void GfxUi::drawProgressBar(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor) { - if (percentage == 0) { - _tft->fillRoundRect(x0, y0, w, h, 3, TFT_BLACK); - } - uint8_t margin = 2; - uint16_t barHeight = h - 2 * margin; - uint16_t barWidth = w - 2 * margin; - _tft->drawRoundRect(x0, y0, w, h, 3, frameColor); - _tft->fillRect(x0 + margin, y0 + margin, barWidth * percentage / 100.0, barHeight, barColor); -} - -// This drawBMP function contains code from: -// https://github.com/adafruit/Adafruit_ILI9341/blob/master/examples/spitftbitmap/spitftbitmap.ino -// Here is Bodmer's version: this uses the ILI9341 CGRAM coordinate rotation features inside the display and -// buffers both file and TFT pixel blocks, it typically runs about 2x faster for bottom up encoded BMP images - -//void GfxUi::drawBMP(String filename, uint8_t x, uint16_t y, boolean flip) { // Alernative for caller control of flip -void GfxUi::drawBmp(String filename, uint8_t x, uint16_t y) { - // Flips the TFT internal SGRAM coords to draw bottom up BMP images faster, in this application it can be fixed - boolean flip = 1; - - if ((x >= _tft->width()) || (y >= _tft->height())) return; - - fs::File bmpFile; - int16_t bmpWidth, bmpHeight; // Image W+H in pixels - uint32_t bmpImageoffset; // Start address of image data in file - uint32_t rowSize; // Not always = bmpWidth; may have padding - uint8_t sdbuffer[3 * BUFFPIXEL]; // file read pixel buffer (8 bits each R+G+B per pixel) - uint16_t tftbuffer[BUFFPIXEL]; // TFT pixel out buffer (16-bit per pixel) - uint8_t rgb_ptr = sizeof(sdbuffer); // read 24 bit RGB pixel data buffer pointer (8 bit so BUFF_SIZE must be less than 86) - boolean goodBmp = false; // Flag set to true on valid header parse - int16_t w, h, row, col; // to store width, height, row and column - uint8_t rotation; // to restore rotation - uint8_t tft_ptr = 0; // TFT 16 bit 565 format pixel data buffer pointer - - // Check file exists and open it - Serial.println(filename); - if ( !(bmpFile = SPIFFS.open(filename, "r")) ) { - Serial.println(F(" File not found")); // Can comment out if not needed - return; - } - - // Parse BMP header to get the information we need - if (read16(bmpFile) == 0x4D42) { // BMP file start signature check - read32(bmpFile); // Dummy read to throw away and move on - read32(bmpFile); // Read & ignore creator bytes - bmpImageoffset = read32(bmpFile); // Start of image data - read32(bmpFile); // Dummy read to throw away and move on - bmpWidth = read32(bmpFile); // Image width - bmpHeight = read32(bmpFile); // Image height - - // Only proceed if we pass a bitmap file check - // Number of image planes -- must be '1', depth 24 and 0 (uncompressed format) - if ((read16(bmpFile) == 1) && (read16(bmpFile) == 24) && (read32(bmpFile) == 0)) { - goodBmp = true; // Supported BMP format - // BMP rows are padded (if needed) to 4-byte boundary - rowSize = (bmpWidth * 3 + 3) & ~3; - // Crop area to be loaded - w = bmpWidth; - h = bmpHeight; - - // We might need to alter rotation to avoid tedious file pointer manipulation - // Save the current value so we can restore it later - rotation = _tft->getRotation(); - // Use TFT SGRAM coord rotation if flip is set for 25% faster rendering (new rotations 4-7 supported by library) - if (flip) _tft->setRotation((rotation + (flip<<2)) % 8); // Value 0-3 mapped to 4-7 - - // Calculate new y plot coordinate if we are flipping - switch (rotation) { - case 0: - if (flip) y = _tft->height() - y - h; break; - case 1: - y = _tft->height() - y - h; break; - break; - case 2: - if (flip) y = _tft->height() - y - h; break; - break; - case 3: - y = _tft->height() - y - h; break; - break; - } - - // Set TFT address window to image bounds - // Currently, image will not draw or will be corrputed if it does not fit - // TODO -> efficient clipping, but I don't need it to be idiot proof ;-) - _tft->setAddrWindow(x, y, x + w - 1, y + h - 1); - - // Finally we are ready to send rows of pixels, writing like this avoids slow 32 bit multiply in 8 bit processors - for (uint32_t pos = bmpImageoffset; pos < bmpImageoffset + h * rowSize ; pos += rowSize) { - // Seek if we need to on boundaries and arrange to dump buffer and start again - if (bmpFile.position() != pos) { - bmpFile.seek(pos, fs::SeekSet); - rgb_ptr = sizeof(sdbuffer); - //Serial.println("Seeking in file >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); - } - - // Fill the pixel buffer and plot - for (col = 0; col < w; col++) { // For each column... - // Time to read more pixel data? - if (rgb_ptr >= sizeof(sdbuffer)) { - // Push tft buffer to the display - if (tft_ptr) { - // Here we are sending a uint16_t array to the function - _tft->pushColors(tftbuffer, tft_ptr); - tft_ptr = 0; // tft_ptr and rgb_ptr are not always in sync... - } - // Finally reading bytes from SD Card - bmpFile.read(sdbuffer, sizeof(sdbuffer)); - rgb_ptr = 0; // Set buffer index to start - } - // Convert pixel from BMP 8+8+8 format to TFT compatible 16 bit word - // Blue 5 bits, green 6 bits and red 5 bits (16 bits total) - // Is is a long line but it is faster than calling a library fn for this - tftbuffer[tft_ptr] = (sdbuffer[rgb_ptr++] >> 3) ; - tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xFC) << 3); - tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xF8) << 8); - tft_ptr++; - } // Next row - } // All rows done - - // Write any partially full buffer to TFT - if (tft_ptr) _tft->pushColors(tftbuffer, tft_ptr); - - } // End of bitmap access - } // End of bitmap file check - - bmpFile.close(); - - if(!goodBmp) { - Serial.print(F("BMP format not recognised. File:")); - Serial.println(filename); - } - else - _tft->setRotation(rotation); // Put back original rotation -} - -// These read 16- and 32-bit types from the SD card file. -// BMP data is stored little-endian, Arduino is little-endian too. -// May need to reverse subscript order if porting elsewhere. - -uint16_t GfxUi::read16(fs::File &f) { - uint16_t result; - ((uint8_t *)&result)[0] = f.read(); // LSB - ((uint8_t *)&result)[1] = f.read(); // MSB - return result; -} - -uint32_t GfxUi::read32(fs::File &f) { - uint32_t result; - ((uint8_t *)&result)[0] = f.read(); // LSB - ((uint8_t *)&result)[1] = f.read(); - ((uint8_t *)&result)[2] = f.read(); - ((uint8_t *)&result)[3] = f.read(); // MSB - return result; -} - -/*==================================================================================== - This sketch support functions to render the Jpeg images. - - Created by Bodmer 15th Jan 2017 - ==================================================================================*/ - -// Return the minimum of two values a and b -#define minimum(a,b) (((a) < (b)) ? (a) : (b)) - -#define USE_SPI_BUFFER // Comment out to use slower 16 bit pushColor() - -//==================================================================================== -// Opens the image file and prime the Jpeg decoder -//==================================================================================== -void GfxUi::drawJpeg(const char *filename, int xpos, int ypos) { - - Serial.println("==========================="); - Serial.print("Drawing file: "); Serial.println(filename); - Serial.println("==========================="); - - // Open the named file (the Jpeg decoder library will close it after rendering image) - fs::File jpegFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS - // File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library - - if ( !jpegFile ) { - Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); - return; - } - - // Use one of the three following methods to initialise the decoder: - //boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder, - //boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder, - boolean decoded = JpegDec.decodeFsFile(filename); // or pass the filename (leading / distinguishes SPIFFS files) - // Note: the filename can be a String or character array type - if (decoded) { - // print information about the image to the serial port - jpegInfo(); - - // render the image onto the screen at given coordinates - jpegRender(xpos, ypos); - } - else { - Serial.println("Jpeg file format not supported!"); - } -} - -//==================================================================================== -// Decode and render the Jpeg image onto the TFT screen -//==================================================================================== -void GfxUi::jpegRender(int xpos, int ypos) { - - // retrieve infomration about the image - uint16_t *pImg; - uint16_t mcu_w = JpegDec.MCUWidth; - uint16_t mcu_h = JpegDec.MCUHeight; - uint32_t max_x = JpegDec.width; - uint32_t max_y = JpegDec.height; - - // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) - // Typically these MCUs are 16x16 pixel blocks - // Determine the width and height of the right and bottom edge image blocks - uint32_t min_w = minimum(mcu_w, max_x % mcu_w); - uint32_t min_h = minimum(mcu_h, max_y % mcu_h); - - // save the current image block size - uint32_t win_w = mcu_w; - uint32_t win_h = mcu_h; - - // record the current time so we can measure how long it takes to draw an image - uint32_t drawTime = millis(); - - // save the coordinate of the right and bottom edges to assist image cropping - // to the screen size - max_x += xpos; - max_y += ypos; - - // read each MCU block until there are no more -#ifdef USE_SPI_BUFFER - while( JpegDec.readSwappedBytes()){ // Swap byte order so the SPI buffer can be used -#else - while ( JpegDec.read()) { // Normal byte order read -#endif - // save a pointer to the image block - pImg = JpegDec.pImage; - - // calculate where the image block should be drawn on the screen - int mcu_x = JpegDec.MCUx * mcu_w + xpos; - int mcu_y = JpegDec.MCUy * mcu_h + ypos; - - // check if the image block size needs to be changed for the right edge - if (mcu_x + mcu_w <= max_x) win_w = mcu_w; - else win_w = min_w; - - // check if the image block size needs to be changed for the bottom edge - if (mcu_y + mcu_h <= max_y) win_h = mcu_h; - else win_h = min_h; - - // copy pixels into a contiguous block - if (win_w != mcu_w) - { - uint16_t *cImg; - int p = 0; - cImg = pImg + win_w; - for (int h = 1; h < win_h; h++) - { - p += mcu_w; - for (int w = 0; w < win_w; w++) - { - *cImg = *(pImg + w + p); - cImg++; - } - } - } - - // draw image MCU block only if it will fit on the screen - if ( ( mcu_x + win_w) <= _tft->width() && ( mcu_y + win_h) <= _tft->height()) - { - _tft->pushImage(mcu_x, mcu_y, win_w, win_h, pImg); - } - - else if ( ( mcu_y + win_h) >= _tft->height()) JpegDec.abort(); - - } - - // calculate how long it took to draw the image - drawTime = millis() - drawTime; // Calculate the time it took - - // print the results to the serial port - Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms"); - Serial.println("====================================="); - -} - -//==================================================================================== -// Print information decoded from the Jpeg image -//==================================================================================== -void GfxUi::jpegInfo() { - - Serial.println("==============="); - Serial.println("JPEG image info"); - Serial.println("==============="); - Serial.print ("Width :"); Serial.println(JpegDec.width); - Serial.print ("Height :"); Serial.println(JpegDec.height); - Serial.print ("Components :"); Serial.println(JpegDec.comps); - Serial.print ("MCU / row :"); Serial.println(JpegDec.MCUSPerRow); - Serial.print ("MCU / col :"); Serial.println(JpegDec.MCUSPerCol); - Serial.print ("Scan type :"); Serial.println(JpegDec.scanType); - Serial.print ("MCU width :"); Serial.println(JpegDec.MCUWidth); - Serial.print ("MCU height :"); Serial.println(JpegDec.MCUHeight); - Serial.println("==============="); - Serial.println(""); - -} -//==================================================================================== diff --git a/examples/320 x 240/weather-station/GfxUi.h b/examples/320 x 240/weather-station/GfxUi.h deleted file mode 100644 index f381129..0000000 --- a/examples/320 x 240/weather-station/GfxUi.h +++ /dev/null @@ -1,60 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_eSPI library: -https://github.com/Bodmer/TFT_eSPI - -*/ - - -#include // Hardware-specific library - -#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition -#include - -// JPEG decoder library -#include - -#ifndef _GFX_UI_H -#define _GFX_UI_H - -// Maximum of 85 for BUFFPIXEL as 3 x this value is stored in an 8 bit variable! -// 32 is an efficient size for SPIFFS due to SPI hardware pipeline buffer size -// A larger value of 80 is better for SD cards -#define BUFFPIXEL 32 - -class GfxUi { - public: - GfxUi(TFT_eSPI * tft); - void drawBmp(String filename, uint8_t x, uint16_t y); - void drawProgressBar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor); - void jpegInfo(); - void drawJpeg(const char *filename, int xpos, int ypos); - void jpegRender(int xpos, int ypos); - - private: - TFT_eSPI * _tft; - uint16_t read16(fs::File &f); - uint32_t read32(fs::File &f); - -}; - -#endif - diff --git a/examples/320 x 240/weather-station/SPIFFS_Support.ino b/examples/320 x 240/weather-station/SPIFFS_Support.ino deleted file mode 100644 index 37eefe1..0000000 --- a/examples/320 x 240/weather-station/SPIFFS_Support.ino +++ /dev/null @@ -1,42 +0,0 @@ -/*==================================================================================== - This sketch contains support functions for the ESP6266 SPIFFS filing system - - Created by Bodmer 15th Jan 2017 - ==================================================================================*/ - -//==================================================================================== -// Print a SPIFFS directory list (root directory) -//==================================================================================== - -void listFiles(void) { - Serial.println(); - Serial.println("SPIFFS files found:"); - - fs::Dir dir = SPIFFS.openDir("/"); // Root directory - String line = "====================================="; - uint32_t totalBytes = 0; - - Serial.println(line); - Serial.println(" File name Size"); - Serial.println(line); - - while (dir.next()) { - String fileName = dir.fileName(); - Serial.print(fileName); - int spaces = 25 - fileName.length(); // Tabulate nicely - while (spaces--) Serial.print(" "); - fs::File f = dir.openFile("r"); - Serial.print(f.size()); Serial.println(" bytes"); - totalBytes += f.size(); - } - Serial.println(); Serial.print("Total = "); - int spaces = 25 - 8; // Tabulate nicely - while (spaces--) Serial.print(" "); - Serial.print(totalBytes); Serial.println(" bytes"); - - Serial.println(line); - Serial.println(); - delay(1000); -} -//==================================================================================== - diff --git a/examples/320 x 240/weather-station/WebResource.cpp b/examples/320 x 240/weather-station/WebResource.cpp deleted file mode 100644 index 2020fd1..0000000 --- a/examples/320 x 240/weather-station/WebResource.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -#include "WebResource.h" - -WebResource::WebResource(){ - -} - -void WebResource::downloadFile(String url, String filename) { - downloadFile(url, filename, nullptr); -} - -void WebResource::downloadFile(String url, String filename, ProgressCallback progressCallback) { - - if (SPIFFS.exists(filename) == true) { - Serial.println("Found " + filename); - return; - } - else Serial.println("Downloading " + filename + " from " + url); - - // wait for WiFi connection - if((_wifiMulti.run() == WL_CONNECTED)) { - HTTPClient http; - - Serial.print("[HTTP] begin...\n"); - - // configure server and url - http.begin(url); - - Serial.print("[HTTP] GET...\n"); - // start connection and send HTTP header - int httpCode = http.GET(); - if(httpCode > 0) { - //SPIFFS.remove(filename); - fs::File f = SPIFFS.open(filename, "w+"); - if (!f) { - Serial.println("file open failed"); - return; - } - // HTTP header has been send and Server response header has been handled - Serial.printf("[HTTP] GET... code: %d\n", httpCode); - - // file found at server - if(httpCode == HTTP_CODE_OK) { - - // get length of document (is -1 when Server sends no Content-Length header) - int total = http.getSize(); - int len = total; - progressCallback(filename, 0,total); - // create buffer for read - uint8_t buff[128] = { 0 }; - - // get tcp stream - WiFiClient * stream = http.getStreamPtr(); - - // read all data from server - while(http.connected() && (len > 0 || len == -1)) { - // get available data size - size_t size = stream->available(); - - if(size) { - // read up to 128 byte - int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); - - // write it to Serial - f.write(buff, c); - - if(len > 0) { - len -= c; - } - progressCallback(filename, total - len,total); - } - delay(1); - } - - Serial.println(); - Serial.print("[HTTP] connection closed or file end.\n"); - - } - f.close(); - } else { - Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); - } - - http.end(); - } -} diff --git a/examples/320 x 240/weather-station/WebResource.h b/examples/320 x 240/weather-station/WebResource.h deleted file mode 100644 index acff084..0000000 --- a/examples/320 x 240/weather-station/WebResource.h +++ /dev/null @@ -1,46 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition -#include -#include -#include -#include -#include - -#ifndef _WEBRESOURCE_H -#define _WEBRESOURCE_H - -typedef void (*ProgressCallback)(String fileName, int16_t bytesDownloaded, int16_t bytesTotal); - -class WebResource { - public: - WebResource(); - void downloadFile(String url, String filename, ProgressCallback progressCallback); - void downloadFile(String url, String filename); - - - private: - ESP8266WiFiMulti _wifiMulti; - -}; - -#endif - diff --git a/examples/320 x 240/weather-station/settings.h b/examples/320 x 240/weather-station/settings.h deleted file mode 100644 index d4d97c2..0000000 --- a/examples/320 x 240/weather-station/settings.h +++ /dev/null @@ -1,72 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_ILI9341_ESP library: -https://github.com/Bodmer/TFT_eSPI - -Version 9 -*/ - -// *************************************************************************************** -// WARNING - READ THIS -// -// 3M Flash Size MUST be allocated to SPIFFS using the IDE Tools menu option or else the -// ESP8266 may crash or do strange things (due to lack of error checks in SPIFFS library?) -// *************************************************************************************** -// -// Setup -const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes - -// Pins for the TFT interface are defined in the User_Config.h file inside the TFT_eSPI library - -// TimeClient settings -const float UTC_OFFSET = 1; - -// Wunderground Settings, EDIT to suit your Wunderground key and location -const boolean IS_METRIC = true; // Temperature only? Wind speed units appear to stay in mph. To do: investigate <<<<<<<<<<<<<<<<<<<<<<<<< -//const String WUNDERGRROUND_API_KEY = "WUNDERGROUND KEY HERE"; - const String WUNDERGRROUND_API_KEY = "1c265fajf48s0a82"; // Random key example showing how the above line should look - -// For language codes see https://www.wunderground.com/weather/api/d/docs?d=language-support&_ga=1.55148395.1951311424.1484425551 -const String WUNDERGRROUND_LANGUAGE = "EN"; // Language EN = English - -// For a list of countries, states and cities see https://www.wunderground.com/about/faq/international_cities.asp -const String WUNDERGROUND_COUNTRY = "Peru"; // UK, US etc -const String WUNDERGROUND_CITY = "Base_Naval"; // City, "London", "FL/Boca_Raton" for Boca Raton in Florida (State/City) etc. Use underscore_for spaces) - -// Windspeed conversion, use 1 pair of #defines. To do: investigate a more convenient method <<<<<<<<<<<<<<<<<<<<< -//#define WIND_SPEED_SCALING 1.0 // mph -//#define WIND_SPEED_UNITS " mph" - -//#define WIND_SPEED_SCALING 0.868976 // mph to knots -//#define WIND_SPEED_UNITS " kn" - -#define WIND_SPEED_SCALING 1.60934 // mph to kph -#define WIND_SPEED_UNITS " kph" - -//Thingspeak Settings - not used, no need to populate this at the moment -const String THINGSPEAK_CHANNEL_ID = "CHANNEL_ID_HERE"; -const String THINGSPEAK_API_READ_KEY = "API_READ_KEY_HERE"; - -// List, so that the downloader knows what to fetch -String wundergroundIcons [] = {"chanceflurries","chancerain","chancesleet","chancesnow","clear","cloudy","flurries","fog","hazy","mostlycloudy","mostlysunny","partlycloudy","partlysunny","rain","sleet","snow","sunny","tstorms","unknown"}; - -/*************************** - * End Settings - **************************/ diff --git a/examples/320 x 240/weather-station/weather-station.ino b/examples/320 x 240/weather-station/weather-station.ino deleted file mode 100644 index ab3cfad..0000000 --- a/examples/320 x 240/weather-station/weather-station.ino +++ /dev/null @@ -1,595 +0,0 @@ -/**The MIT License (MIT) - Copyright (c) 2015 by Daniel Eichhorn - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYBR_DATUM HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - See more at http://blog.squix.ch - - Adapted by Bodmer to use the faster TFT_eSPI library: - https://github.com/Bodmer/TFT_eSPI - - Plus: - Minor changes to text placement and auto-blanking out old text with background colour padding - Moon phase text added - Forecast text lines are automatically split onto two lines at a central space (some are long!) - Time is printed with colons aligned to tidy display - Min and max forecast temperatures spaced out - The ` character has been changed to a degree symbol in the 36 point font - New smart WU splash startup screen and updated progress messages - Display does not need to be blanked between updates - Icons nudged about slightly to add wind direction + speed - Barometric pressure added -*/ - -#define SERIAL_MESSAGES - -#include - -#include -#include // Hardware-specific library - -// Additional UI functions -#include "GfxUi.h" - -// Fonts created by http://oleddisplay.squix.ch/ -#include "ArialRoundedMTBold_14.h" -#include "ArialRoundedMTBold_36.h" - -// Download helper -#include "WebResource.h" - -#include -#include -#include -#include -#include - -// Helps with connecting to internet -#include - -// check settings.h for adapting to your needs -#include "settings.h" -#include -#include -#include "TimeClient.h" - -// HOSTNAME for OTA update -#define HOSTNAME "ESP8266-OTA-" - -/***************************** - Important: see settings.h to configure your settings!!! - * ***************************/ - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library - -boolean booted = true; - -GfxUi ui = GfxUi(&tft); - -WebResource webResource; -TimeClient timeClient(UTC_OFFSET); - -// Set to false, if you prefere imperial/inches, Fahrenheit -WundergroundClient wunderground(IS_METRIC); - -//declaring prototypes -void configModeCallback (WiFiManager *myWiFiManager); -void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal); -ProgressCallback _downloadCallback = downloadCallback; -void downloadResources(); -void updateData(); -void drawProgress(uint8_t percentage, String text); -void drawTime(); -void drawCurrentWeather(); -void drawForecast(); -void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex); -String getMeteoconIcon(String iconText); -void drawAstronomy(); -void drawSeparator(uint16_t y); - -long lastDownloadUpdate = millis(); - -void setup() { -#ifdef SERIAL_MESSAGES - Serial.begin(250000); -#endif - tft.begin(); - tft.fillScreen(TFT_BLACK); - - tft.setFreeFont(&ArialRoundedMTBold_14); - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_DARKGREY, TFT_BLACK); - tft.drawString("Original by: blog.squix.org", 120, 240); - tft.drawString("Adapted by: Bodmer", 120, 260); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - SPIFFS.begin(); - //listFiles(); - //Uncomment if you want to erase SPIFFS and update all internet resources, this takes some time! - //tft.drawString("Formatting SPIFFS, so wait!", 120, 200); SPIFFS.format(); - - if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10); - if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56); // Image is 56 pixels high - delay(1000); - tft.drawString("Connecting to WiFi", 120, 200); - tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text - - //WiFiManager - //Local intialization. Once its business is done, there is no need to keep it around - WiFiManager wifiManager; - // Uncomment for testing wifi manager - //wifiManager.resetSettings(); - wifiManager.setAPCallback(configModeCallback); - - //or use this for auto generated name ESP + ChipID - wifiManager.autoConnect(); - - //Manual Wifi - //WiFi.begin(WIFI_SSID, WIFI_PWD); - - // OTA Setup - String hostname(HOSTNAME); - hostname += String(ESP.getChipId(), HEX); - WiFi.hostname(hostname); - ArduinoOTA.setHostname((const char *)hostname.c_str()); - ArduinoOTA.begin(); - - // download images from the net. If images already exist don't download - tft.drawString("Downloading to SPIFFS...", 120, 200); - tft.drawString(" ", 120, 240); // Clear line - tft.drawString(" ", 120, 260); // Clear line - downloadResources(); - //listFiles(); - tft.setTextDatum(BC_DATUM); - tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text - tft.drawString(" ", 120, 200); // Clear line above using set padding width - tft.drawString("Fetching weather data...", 120, 200); - //delay(500); - - // load the weather information - updateData(); -} - -long lastDrew = 0; -void loop() { - // Handle OTA update requests - ArduinoOTA.handle(); - - // Check if we should update the clock - if (millis() - lastDrew > 30000 && wunderground.getSeconds() == "00") { - drawTime(); - lastDrew = millis(); - } - - // Check if we should update weather information - if (millis() - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) { - updateData(); - lastDownloadUpdate = millis(); - } -} - -// Called if WiFi has not been configured yet -void configModeCallback (WiFiManager *myWiFiManager) { - tft.setTextDatum(BC_DATUM); - tft.setFreeFont(&ArialRoundedMTBold_14); - tft.setTextColor(TFT_ORANGE); - tft.drawString("Wifi Manager", 120, 28); - tft.drawString("Please connect to AP", 120, 42); - tft.setTextColor(TFT_WHITE); - tft.drawString(myWiFiManager->getConfigPortalSSID(), 120, 56); - tft.setTextColor(TFT_ORANGE); - tft.drawString("To setup Wifi Configuration", 120, 70); -} - -// callback called during download of files. Updates progress bar -void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal) { - Serial.println(String(bytesDownloaded) + " / " + String(bytesTotal)); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(240); - - int percentage = 100 * bytesDownloaded / bytesTotal; - if (percentage == 0) { - tft.drawString(filename, 120, 220); - } - if (percentage % 5 == 0) { - tft.setTextDatum(TC_DATUM); - tft.setTextPadding(tft.textWidth(" 888% ")); - tft.drawString(String(percentage) + "%", 120, 245); - ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE); - } - -} - -// Download the bitmaps -void downloadResources() { - // tft.fillScreen(TFT_BLACK); - tft.setFreeFont(&ArialRoundedMTBold_14); - char id[5]; - - // Download WU graphic jpeg first and display it, then the Earth view - webResource.downloadFile((String)"http://i.imgur.com/njl1pMj.jpg", (String)"/WU.jpg", _downloadCallback); - if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10); - - webResource.downloadFile((String)"http://i.imgur.com/v4eTLCC.jpg", (String)"/Earth.jpg", _downloadCallback); - if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56); - - //webResource.downloadFile((String)"http://i.imgur.com/IY57GSv.jpg", (String)"/Horizon.jpg", _downloadCallback); - //if (SPIFFS.exists("/Horizon.jpg") == true) ui.drawJpeg("/Horizon.jpg", 0, 320-160); - - //webResource.downloadFile((String)"http://i.imgur.com/jZptbtY.jpg", (String)"/Rainbow.jpg", _downloadCallback); - //if (SPIFFS.exists("/Rainbow.jpg") == true) ui.drawJpeg("/Rainbow.jpg", 0, 0); - - for (int i = 0; i < 19; i++) { - sprintf(id, "%02d", i); - webResource.downloadFile("http://www.squix.org/blog/wunderground/" + wundergroundIcons[i] + ".bmp", wundergroundIcons[i] + ".bmp", _downloadCallback); - } - for (int i = 0; i < 19; i++) { - sprintf(id, "%02d", i); - webResource.downloadFile("http://www.squix.org/blog/wunderground/mini/" + wundergroundIcons[i] + ".bmp", "/mini/" + wundergroundIcons[i] + ".bmp", _downloadCallback); - } - for (int i = 0; i < 24; i++) { - webResource.downloadFile("http://www.squix.org/blog/moonphase_L" + String(i) + ".bmp", "/moon" + String(i) + ".bmp", _downloadCallback); - } -} - -// Update the internet based information and update screen -void updateData() { - // booted = true; // Test only - // booted = false; // Test only - - if (booted) ui.drawJpeg("/WU.jpg", 0, 10); // May have already drawn this but it does not take long - else tft.drawCircle(22, 22, 18, TFT_DARKGREY); // Outer ring - optional - - if (booted) drawProgress(20, "Updating time..."); - else fillSegment(22, 22, 0, (int) (20 * 3.6), 16, TFT_NAVY); - - timeClient.updateTime(); - if (booted) drawProgress(50, "Updating conditions..."); - else fillSegment(22, 22, 0, (int) (50 * 3.6), 16, TFT_NAVY); - - wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - if (booted) drawProgress(70, "Updating forecasts..."); - else fillSegment(22, 22, 0, (int) (70 * 3.6), 16, TFT_NAVY); - - wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - if (booted) drawProgress(90, "Updating astronomy..."); - else fillSegment(22, 22, 0, (int) (90 * 3.6), 16, TFT_NAVY); - - wunderground.updateAstronomy(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - // lastUpdate = timeClient.getFormattedTime(); - // readyForWeatherUpdate = false; - if (booted) drawProgress(100, "Done..."); - else fillSegment(22, 22, 0, 360, 16, TFT_NAVY); - - if (booted) delay(2000); - - if (booted) tft.fillScreen(TFT_BLACK); - else fillSegment(22, 22, 0, 360, 22, TFT_BLACK); - - //tft.fillScreen(TFT_CYAN); // For text padding and update graphics over-write checking only - drawTime(); - drawCurrentWeather(); - drawForecast(); - drawAstronomy(); - booted = false; -} - -// Progress bar helper -void drawProgress(uint8_t percentage, String text) { - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(240); - tft.drawString(text, 120, 220); - - ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE); - - tft.setTextPadding(0); -} - -// draws the clock -void drawTime() { - - tft.setFreeFont(&ArialRoundedMTBold_36); - - String timeNow = timeClient.getHours() + ":" + timeClient.getMinutes(); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_YELLOW, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 44:44 ")); // String width + margin - tft.drawString(timeNow, 120, 53); - - tft.setFreeFont(&ArialRoundedMTBold_14); - - String date = wunderground.getDate(); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" Ddd, 44 Mmm 4444 ")); // String width + margin - tft.drawString(date, 120, 16); - - drawSeparator(54); - - tft.setTextPadding(0); -} - -// draws current weather information -void drawCurrentWeather() { - // Weather Icon - String weatherIcon = getMeteoconIcon(wunderground.getTodayIcon()); - //uint32_t dt = millis(); - ui.drawBmp(weatherIcon + ".bmp", 0, 59); - //Serial.print("Icon draw time = "); Serial.println(millis()-dt); - - // Weather Text - - String weatherText = wunderground.getWeatherText(); - //weatherText = "Heavy Thunderstorms with Small Hail"; // Test line splitting with longest(?) string - - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - int splitPoint = 0; - int xpos = 230; - splitPoint = splitIndex(weatherText); - if (splitPoint > 16) xpos = 235; - - tft.setTextPadding(tft.textWidth("Heavy Thunderstorms")); // Max anticipated string width - if (splitPoint) tft.drawString(weatherText.substring(0, splitPoint), xpos, 72); - tft.setTextPadding(tft.textWidth(" with Small Hail")); // Max anticipated string width + margin - tft.drawString(weatherText.substring(splitPoint), xpos, 87); - - tft.setFreeFont(&ArialRoundedMTBold_36); - - tft.setTextDatum(TR_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - // Font ASCII code 96 (0x60) modified to make "`" a degree symbol - tft.setTextPadding(tft.textWidth("-88`")); // Max width of vales - - weatherText = wunderground.getCurrentTemp(); - if (weatherText.indexOf(".")) weatherText = weatherText.substring(0, weatherText.indexOf(".")); // Make it integer temperature - if (weatherText == "") weatherText = "?"; // Handle null return - tft.drawString(weatherText + "`", 221, 100); - - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(TL_DATUM); - tft.setTextPadding(0); - if (IS_METRIC) tft.drawString("C ", 221, 100); - else tft.drawString("F ", 221, 100); - - //tft.drawString(wunderground.getPressure(), 180, 30); - - weatherText = ""; //wunderground.getWindDir() + " "; - weatherText += String((int)(wunderground.getWindSpeed().toInt() * WIND_SPEED_SCALING)) + WIND_SPEED_UNITS; - - tft.setTextDatum(TC_DATUM); - tft.setTextPadding(tft.textWidth(" 888 mph")); // Max string length? - tft.drawString(weatherText, 128, 136); - - weatherText = wunderground.getPressure(); - - tft.setTextDatum(TR_DATUM); - tft.setTextPadding(tft.textWidth(" 8888mb")); // Max string length? - tft.drawString(weatherText, 230, 136); - - weatherText = wunderground.getWindDir(); - - int windAngle = 0; - String compassCardinal = ""; - switch (weatherText.length()) { - case 1: - compassCardinal = "N E S W "; // Not used, see default below - windAngle = 90 * compassCardinal.indexOf(weatherText) / 2; - break; - case 2: - compassCardinal = "NE SE SW NW"; - windAngle = 45 + 90 * compassCardinal.indexOf(weatherText) / 3; - break; - case 3: - compassCardinal = "NNE ENE ESE SSE SSW WSW WNW NNW"; - windAngle = 22 + 45 * compassCardinal.indexOf(weatherText) / 4; // 22 should be 22.5 but accuracy is not needed! - break; - default: - if (weatherText == "Variable") windAngle = -1; - else { - // v23456v23456v23456v23456 character ruler - compassCardinal = "North East South West"; // Possible strings - windAngle = 90 * compassCardinal.indexOf(weatherText) / 6; - } - break; - } - - tft.fillCircle(128, 110, 23, TFT_BLACK); // Erase old plot, radius + 1 to delete stray pixels - tft.drawCircle(128, 110, 22, TFT_DARKGREY); // Outer ring - optional - if ( windAngle >= 0 ) fillSegment(128, 110, windAngle - 15, 30, 22, TFT_GREEN); // Might replace this with a bigger rotating arrow - tft.drawCircle(128, 110, 6, TFT_RED); - - drawSeparator(153); - - tft.setTextDatum(TL_DATUM); // Reset datum to normal - tft.setTextPadding(0); // Reset padding width to none -} - -// draws the three forecast columns -void drawForecast() { - drawForecastDetail(10, 171, 0); - drawForecastDetail(95, 171, 2); - drawForecastDetail(180, 171, 4); - drawSeparator(171 + 69); -} - -// helper for the forecast columns -void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex) { - tft.setFreeFont(&ArialRoundedMTBold_14); - - String day = wunderground.getForecastTitle(dayIndex).substring(0, 3); - day.toUpperCase(); - - tft.setTextDatum(BC_DATUM); - - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(tft.textWidth("WWW")); - tft.drawString(day, x + 25, y); - - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth("-88 -88")); - tft.drawString(wunderground.getForecastHighTemp(dayIndex) + " " + wunderground.getForecastLowTemp(dayIndex), x + 25, y + 14); - - String weatherIcon = getMeteoconIcon(wunderground.getForecastIcon(dayIndex)); - ui.drawBmp("/mini/" + weatherIcon + ".bmp", x, y + 15); - - tft.setTextPadding(0); // Reset padding width to none -} - -// draw moonphase and sunrise/set and moonrise/set -void drawAstronomy() { - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" Waxing Crescent ")); - tft.drawString(wunderground.getMoonPhase(), 120, 260 - 2); - - int moonAgeImage = 24 * wunderground.getMoonAge().toInt() / 30.0; - ui.drawBmp("/moon" + String(moonAgeImage) + ".bmp", 120 - 30, 260); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(0); // Reset padding width to none - tft.drawString("Sun", 40, 280); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 88:88 ")); - int dt = rightOffset(wunderground.getSunriseTime(), ":"); // Draw relative to colon to them aligned - tft.drawString(wunderground.getSunriseTime(), 40 + dt, 300); - - dt = rightOffset(wunderground.getSunsetTime(), ":"); - tft.drawString(wunderground.getSunsetTime(), 40 + dt, 315); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(0); // Reset padding width to none - tft.drawString("Moon", 200, 280); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 88:88 ")); - dt = rightOffset(wunderground.getMoonriseTime(), ":"); // Draw relative to colon to them aligned - tft.drawString(wunderground.getMoonriseTime(), 200 + dt, 300); - - dt = rightOffset(wunderground.getMoonsetTime(), ":"); - tft.drawString(wunderground.getMoonsetTime(), 200 + dt, 315); - - tft.setTextPadding(0); // Reset padding width to none -} - -// Helper function, should be part of the weather station library and should disappear soon -String getMeteoconIcon(String iconText) { - if (iconText == "F") return "chanceflurries"; - if (iconText == "Q") return "chancerain"; - if (iconText == "W") return "chancesleet"; - if (iconText == "V") return "chancesnow"; - if (iconText == "S") return "chancetstorms"; - if (iconText == "B") return "clear"; - if (iconText == "Y") return "cloudy"; - if (iconText == "F") return "flurries"; - if (iconText == "M") return "fog"; - if (iconText == "E") return "hazy"; - if (iconText == "Y") return "mostlycloudy"; - if (iconText == "H") return "mostlysunny"; - if (iconText == "H") return "partlycloudy"; - if (iconText == "J") return "partlysunny"; - if (iconText == "W") return "sleet"; - if (iconText == "R") return "rain"; - if (iconText == "W") return "snow"; - if (iconText == "B") return "sunny"; - if (iconText == "0") return "tstorms"; - - - return "unknown"; -} - -// if you want separators, uncomment the tft-line -void drawSeparator(uint16_t y) { - tft.drawFastHLine(10, y, 240 - 2 * 10, 0x4228); -} - -// determine the "space" split point in a long string -int splitIndex(String text) -{ - int index = 0; - while ( (text.indexOf(' ', index) >= 0) && ( index <= text.length() / 2 ) ) { - index = text.indexOf(' ', index) + 1; - } - if (index) index--; - return index; -} - -// Calculate coord delta from start of text String to start of sub String contained within that text -// Can be used to vertically right align text so for example a colon ":" in the time value is always -// plotted at same point on the screen irrespective of different proportional character widths, -// could also be used to align decimal points for neat formatting -int rightOffset(String text, String sub) -{ - int index = text.indexOf(sub); - return tft.textWidth(text.substring(index)); -} - -// Calculate coord delta from start of text String to start of sub String contained within that text -// Can be used to vertically left align text so for example a colon ":" in the time value is always -// plotted at same point on the screen irrespective of different proportional character widths, -// could also be used to align decimal points for neat formatting -int leftOffset(String text, String sub) -{ - int index = text.indexOf(sub); - return tft.textWidth(text.substring(0, index)); -} - -// Draw a segment of a circle, centred on x,y with defined start_angle and subtended sub_angle -// Angles are defined in a clockwise direction with 0 at top -// Segment has radius r and it is plotted in defined colour -// Can be used for pie charts etc, in this sketch it is used for wind direction -#define DEG2RAD 0.0174532925 // Degrees to Radians conversion factor -#define INC 2 // Minimum segment subtended angle and plotting angle increment (in degrees) -void fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned int colour) -{ - // Calculate first pair of coordinates for segment start - float sx = cos((start_angle - 90) * DEG2RAD); - float sy = sin((start_angle - 90) * DEG2RAD); - uint16_t x1 = sx * r + x; - uint16_t y1 = sy * r + y; - - // Draw colour blocks every INC degrees - for (int i = start_angle; i < start_angle + sub_angle; i += INC) { - - // Calculate pair of coordinates for segment end - int x2 = cos((i + 1 - 90) * DEG2RAD) * r + x; - int y2 = sin((i + 1 - 90) * DEG2RAD) * r + y; - - tft.fillTriangle(x1, y1, x2, y2, x, y, colour); - - // Copy segment end to sgement start for next segment - x1 = x2; - y1 = y2; - } -} From 11ef56d48c3c51e1b724684d2880ee5b62a06b20 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 23 Jan 2019 20:55:04 +0000 Subject: [PATCH 71/94] Test slower DC and CS lines for a user --- TFT_eSPI.cpp | 27 +++++++++++++++++---------- TFT_eSPI.h | 30 +++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 19 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 4df354b..e4cf7ad 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -345,6 +345,7 @@ void TFT_eSPI::init(uint8_t tc) #endif spi_end(); + delay(150); // Wait for reset to complete spi_begin(); @@ -506,13 +507,15 @@ void TFT_eSPI::spiwrite(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writecommand(uint8_t c) { - DC_C; - CS_L; - + //DC_C; + //CS_L; + digitalWrite(TFT_DC, LOW); + digitalWrite(TFT_CS, LOW); tft_Write_8(c); - - CS_H; - DC_D; + digitalWrite(TFT_CS, HIGH); + digitalWrite(TFT_DC, HIGH); + //CS_H; + //DC_D; } @@ -522,11 +525,11 @@ void TFT_eSPI::writecommand(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writedata(uint8_t d) { - CS_L; - + //CS_L; + digitalWrite(TFT_CS, LOW); tft_Write_8(d); - - CS_H; + digitalWrite(TFT_CS, HIGH); + //CS_H; } @@ -5084,6 +5087,7 @@ void writeBlock(uint16_t color, uint32_t repeat) ***************************************************************************************/ void TFT_eSPI::getSetup(setup_t &tft_settings) { +// tft_settings.version is set in header file #if defined (ESP8266) tft_settings.esp = 8266; @@ -5105,6 +5109,9 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) #else tft_settings.serial = true; tft_settings.tft_spi_freq = SPI_FREQUENCY/100000; + #ifdef SPI_READ_FREQUENCY + tft_settings.tft_rd_freq = SPI_READ_FREQUENCY/100000; + #endif #endif #if defined(TFT_SPI_OVERLAP) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 5e471e9..01a1351 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -15,6 +15,8 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ +#define TFT_ESPI_VERSION "1.4.0" + //#define ESP32 //Just used to test ESP32 options // Include header file that defines the fonts loaded, the TFT drivers @@ -142,8 +144,8 @@ #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #else - #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32));GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32));GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #endif #else #if TFT_DC >= 0 @@ -153,8 +155,8 @@ #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) #else - #define DC_C GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC);GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC);GPIO.out_w1ts = (1 << TFT_DC) #endif #else #define DC_C @@ -191,8 +193,8 @@ #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #else - #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32));GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32));GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #endif #else #if TFT_CS >= 0 @@ -200,8 +202,8 @@ #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) #else - #define CS_L GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS) + #define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1ts = (1 << TFT_CS) #endif #else #define CS_L @@ -223,7 +225,7 @@ #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); \ GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) #else - #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) #endif #else #define CS_L_DC_C CS_L; DC_C @@ -525,11 +527,20 @@ swap_coord(T& a, T& b) { T t = a; a = b; b = t; } // by calling getSetup(), zero impact on code size unless used, mainly for diagnostics typedef struct { +String version = TFT_ESPI_VERSION; int16_t esp; uint8_t trans; uint8_t serial; uint8_t overlap; +#if defined (ESP32) + #if defined (USE_HSPI_PORT) + uint8_t port = HSPI; + #else + uint8_t port = VSPI; + #endif +#endif + uint16_t tft_driver; // Hexadecimal code uint16_t tft_width; // Rotation 0 width and height uint16_t tft_height; @@ -565,6 +576,7 @@ int8_t pin_tft_d7; int8_t pin_tch_cs; int16_t tft_spi_freq; +int16_t tft_rd_freq; int16_t tch_spi_freq; } setup_t; From e8a0024054b2e0a0c00264790da5dfaf0c260599 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 25 Jan 2019 13:03:28 +0000 Subject: [PATCH 72/94] Fix issue #295 --- TFT_eSPI.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index e4cf7ad..d72d835 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -2927,10 +2927,10 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) addr_row = 0xFFFF; #ifdef CGRAM_OFFSET - xs+=colstart; - xe+=colstart; - ys+=rowstart; - ye+=rowstart; + xs += colstart; + xe += colstart; + ys += rowstart; + ye += rowstart; #endif // Column addr set @@ -2996,10 +2996,10 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) addr_row = 0xFFFF; #ifdef CGRAM_OFFSET - x0+=colstart; - x1+=colstart; - y0+=rowstart; - y1+=rowstart; +xs += colstart; +xe += colstart; +ys += rowstart; +ye += rowstart; #endif // Column addr set From caef4519f343441f15bd0b03c64054663bdf97dd Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 25 Jan 2019 14:25:40 +0000 Subject: [PATCH 73/94] Improve bounds checking update CS management Add bounds checking to graphics functions Rationalise variable types and style used to minimse type casting needs (this change ended up being a more extensive refactoring than anticipated - but once started...) Add version reporting to diagnostic sketch Boost PDQ graphicstest performance --- Extensions/Sprite.cpp | 47 ++- Extensions/Sprite.h | 14 +- TFT_eSPI.cpp | 287 ++++++++---------- TFT_eSPI.h | 78 ++--- .../TFT_graphicstest_PDQ3.ino | 7 +- .../TFT_graphicstest_PDQ.ino | 4 +- .../Read_User_Setup/Read_User_Setup.ino | 2 + library.json | 2 +- library.properties | 2 +- 9 files changed, 206 insertions(+), 237 deletions(-) diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 1ab5bb3..6bc58b2 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -543,10 +543,10 @@ uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) ** Function name: pushImage ** Description: push 565 colour image into a defined area of a sprite *************************************************************************************x*/ -void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; - if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; + if ((x + w < 0) || (y + h < 0)) return; int32_t xo = 0; int32_t yo = 0; @@ -635,14 +635,14 @@ void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint1 ** Function name: pushImage ** Description: push 565 colour FLASH (PROGMEM) image into a defined area *************************************************************************************x*/ -void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { #ifdef ESP32 pushImage(x, y, w, h, (uint16_t*) data); #else // Partitioned memory FLASH processor if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; - if ((x + (int32_t)w < 0) || (y + (int32_t)h < 0)) return; + if ((x + w < 0) || (y + h < 0)) return; int32_t xo = 0; int32_t yo = 0; @@ -877,7 +877,7 @@ void TFT_eSprite::writeColor(uint16_t color) ** Function name: setScrollRect ** Description: Set scroll area within the sprite and the gap fill colour *************************************************************************************x*/ -void TFT_eSprite::setScrollRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t color) +void TFT_eSprite::setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) { if ((x >= _iwidth) || (y >= _iheight) || !_created ) return; @@ -1082,11 +1082,10 @@ uint8_t TFT_eSprite::getRotation(void) ** Function name: drawPixel ** Description: push a single pixel at an arbitrary position *************************************************************************************x*/ -void TFT_eSprite::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) { - // x and y are unsigned so that -ve coordinates turn into large positive ones - // this make bounds checking a bit faster - if ((x >= _iwidth) || (y >= _iheight) || !_created) return; + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height) || !_created) return; if (_bpp == 16) { @@ -1598,12 +1597,12 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color ** Function name: drawChar ** Description: draw a unicode onto the screen *************************************************************************************x*/ -int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y) +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) { return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { if (!_created ) return 0; @@ -1647,8 +1646,8 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; - int width = 0; - int height = 0; + int32_t width = 0; + int32_t height = 0; uint32_t flash_address = 0; uniCode -= 32; @@ -1677,9 +1676,9 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) } #endif - int w = width; - int pX = 0; - int pY = y; + int32_t w = width; + int32_t pX = 0; + int32_t pY = y; uint8_t line = 0; #ifdef LOAD_FONT2 // chop out code if we do not need it @@ -1688,11 +1687,11 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) w = w / 8; if (x + width * textsize >= _iwidth) return width * textsize ; - for (int i = 0; i < height; i++) + for (int32_t i = 0; i < height; i++) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); - for (int k = 0; k < w; k++) + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); if (line) { @@ -1738,8 +1737,8 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) int16_t color = textcolor; if (_bpp == 16) color = (textcolor >> 8) | (textcolor << 8); else if (_bpp == 8) color = ((textcolor & 0xE000)>>8 | (textcolor & 0x0700)>>6 | (textcolor & 0x0018)>>3); - int px = 0, py = pY; // To hold character block start and end column and row values - int pc = 0; // Pixel count + int32_t px = 0, py = pY; // To hold character block start and end column and row values + int32_t pc = 0; // Pixel count uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel uint8_t tnp = 0; // Temporary copy of np for while loop uint8_t ts = textsize - 1; // Temporary copy of textsize @@ -1845,10 +1844,10 @@ void TFT_eSprite::drawGlyph(uint16_t code) int16_t xs = 0; uint16_t dl = 0; - for (int y = 0; y < this->gHeight[gNum]; y++) + for (int32_t y = 0; y < this->gHeight[gNum]; y++) { this->fontFile.read(pbuffer, this->gWidth[gNum]); - for (int x = 0; x < this->gWidth[gNum]; x++) + for (int32_t x = 0; x < this->gWidth[gNum]; x++) { uint8_t pixel = pbuffer[x]; if (pixel) @@ -1897,7 +1896,7 @@ void TFT_eSprite::drawGlyph(uint16_t code) void TFT_eSprite::printToSprite(String string) { if(!this->fontLoaded) return; - int16_t len = string.length(); + uint16_t len = string.length(); char cbuffer[len + 1]; // Add 1 for the null string.toCharArray(cbuffer, len + 1); // Add 1 for the null, otherwise characters get dropped printToSprite(cbuffer, len); @@ -1909,7 +1908,7 @@ void TFT_eSprite::printToSprite(String string) ** Function name: printToSprite ** Description: Write a string to the sprite cursor position *************************************************************************************x*/ -void TFT_eSprite::printToSprite(char *cbuffer, int len) //String string) +void TFT_eSprite::printToSprite(char *cbuffer, uint16_t len) //String string) { if(!this->fontLoaded) return; diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h index 57db847..2bf800c 100644 --- a/Extensions/Sprite.h +++ b/Extensions/Sprite.h @@ -29,7 +29,7 @@ class TFT_eSprite : public TFT_eSPI { void setBitmapColor(uint16_t c, uint16_t b); - void drawPixel(uint32_t x, uint32_t y, uint32_t color); + void drawPixel(int32_t x, int32_t y, uint32_t color); void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), @@ -45,7 +45,7 @@ class TFT_eSprite : public TFT_eSPI { // Set the scroll zone, top left corner at x,y with defined width and height // The colour (optional, black is default) is used to fill the gap after the scroll - setScrollRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t color = TFT_BLACK), + setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK), // Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down // dy is optional (default is then no up/down scroll). // The sprite coordinate frame does not move because pixels are moved @@ -81,8 +81,8 @@ class TFT_eSprite : public TFT_eSPI { uint16_t readPixel(int32_t x0, int32_t y0); // Write an image (colour bitmap) to the sprite - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data); - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); // Swap the byte order for pushImage() - corrects different image endianness void setSwapBytes(bool swap); @@ -93,8 +93,8 @@ class TFT_eSprite : public TFT_eSPI { void pushSprite(int32_t x, int32_t y); void pushSprite(int32_t x, int32_t y, uint16_t transparent); - int16_t drawChar(unsigned int uniCode, int x, int y, int font), - drawChar(unsigned int uniCode, int x, int y); + int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y); // Return the width and height of the sprite int16_t width(void), @@ -106,7 +106,7 @@ class TFT_eSprite : public TFT_eSPI { // Functions associated with anti-aliased fonts void drawGlyph(uint16_t code); void printToSprite(String string); - void printToSprite(char *cbuffer, int len); + void printToSprite(char *cbuffer, uint16_t len); int16_t printToSprite(int16_t x, int16_t y, uint16_t index); private: diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index d72d835..20ae7df 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -54,33 +54,39 @@ void busDir(uint32_t mask, uint8_t mode); inline void TFT_eSPI::spi_begin(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} +#else + CS_L; #endif } inline void TFT_eSPI::spi_end(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} + if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} +#else + CS_H; #endif } inline void TFT_eSPI::spi_begin_read(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE));} + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} #else #if !defined(ESP32_PARALLEL) spi.setFrequency(SPI_READ_FREQUENCY); #endif + CS_L; #endif } inline void TFT_eSPI::spi_end_read(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) - if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} + if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} #else #if !defined(ESP32_PARALLEL) spi.setFrequency(SPI_FREQUENCY); #endif + CS_H; #endif } @@ -145,7 +151,7 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) #ifdef ESP32_PARALLEL // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically - for (int c = 0; c<256; c++) + for (int32_t c = 0; c<256; c++) { xset_mask[c] = 0; if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); @@ -507,15 +513,16 @@ void TFT_eSPI::spiwrite(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writecommand(uint8_t c) { - //DC_C; - //CS_L; - digitalWrite(TFT_DC, LOW); - digitalWrite(TFT_CS, LOW); + spi_begin(); // CS_L; + + DC_C; + tft_Write_8(c); - digitalWrite(TFT_CS, HIGH); - digitalWrite(TFT_DC, HIGH); - //CS_H; - //DC_D; + + DC_D; + + spi_end(); // CS_H; + } @@ -525,11 +532,15 @@ void TFT_eSPI::writecommand(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writedata(uint8_t d) { - //CS_L; - digitalWrite(TFT_CS, LOW); + spi_begin(); // CS_L; + + DC_D; // Play safe, but should already be in data mode + tft_Write_8(d); - digitalWrite(TFT_CS, HIGH); - //CS_H; + + CS_L; // Allow more hold time for low VDI rail + + spi_end(); // CS_H; } @@ -561,18 +572,17 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) index = 0x10 + (index & 0x0F); DC_C; - CS_L; tft_Write_8(0xD9); DC_D; tft_Write_8(index); - CS_H; + + CS_H; // Some displays seem to need CS to be pulsed here, or is just a delay needed? + CS_L; DC_C; - CS_L; tft_Write_8(cmd_function); DC_D; reg = tft_Read_8(); - CS_H; spi_end_read(); #endif @@ -760,7 +770,7 @@ void busDir(uint32_t mask, uint8_t mode) ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read 565 pixel colours from a defined area ***************************************************************************************/ -void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return; @@ -922,7 +932,7 @@ void TFT_eSPI::end_SDA_Read(void) ** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: push 565 pixel colours into a defined area ***************************************************************************************/ -void TFT_eSPI::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { // Function deprecated, remains for backwards compatibility // pushImage() is better as it will crop partly off-screen image blocks @@ -934,10 +944,10 @@ void TFT_eSPI::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t ** Function name: pushImage ** Description: plot 16 bit colour sprite or image onto TFT ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= _height)) return; int32_t dx = 0; int32_t dy = 0; @@ -955,7 +965,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t spi_begin(); inTransaction = true; - setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR + setWindow(x, y, x + dw - 1, y + dh - 1); data += dx + dy * w; @@ -965,8 +975,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t data += w; } - CS_H; - inTransaction = false; spi_end(); } @@ -975,10 +983,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t ** Function name: pushImage ** Description: plot 16 bit sprite or image with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data, uint16_t transp) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp) { - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= _height)) return; int32_t dx = 0; int32_t dy = 0; @@ -1038,8 +1046,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t data += w; } - CS_H; - inTransaction = false; spi_end(); } @@ -1049,13 +1055,13 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t ** Function name: pushImage - for FLASH (PROGMEM) stored images ** Description: plot 16 bit image ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) { #ifdef ESP32 pushImage(x, y, w, h, (uint16_t*)data); #else // Partitioned memory FLASH processor - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= _height)) return; int32_t dx = 0; int32_t dy = 0; @@ -1084,8 +1090,8 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin uint16_t nb = (dw * dh) / 64; // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < 64; j++) { + for (int32_t i = 0; i < nb; i++) { + for (int32_t j = 0; j < 64; j++) { pix_buffer[j] = pgm_read_word(&data[i * 64 + j]); } pushColors(pix_buffer, 64, _swapBytes); @@ -1096,15 +1102,13 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin // Send any partial buffer left over if (np) { - for (int i = 0; i < np; i++) + for (int32_t i = 0; i < np; i++) { pix_buffer[i] = pgm_read_word(&data[nb * 64 + i]); } pushColors(pix_buffer, np, _swapBytes); } - CS_H; - inTransaction = false; spi_end(); #endif // if ESP32 else ESP8266 check @@ -1115,13 +1119,13 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin ** Function name: pushImage - for FLASH (PROGMEM) stored images ** Description: plot 16 bit image with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transp) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp) { #ifdef ESP32 pushImage(x, y, w, h, (uint16_t*) data, transp); #else // Partitioned memory FLASH processor - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= (int32_t)_height)) return; int32_t dx = 0; int32_t dy = 0; @@ -1183,8 +1187,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin data += w; } - CS_H; - inTransaction = false; spi_end(); #endif // if ESP32 else ESP8266 check @@ -1195,9 +1197,9 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uin ** Function name: pushImage ** Description: plot 8 bit image or sprite using a line buffer ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data, bool bpp8) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8) { - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= (int32_t)_height)) return; int32_t dx = 0; int32_t dy = 0; @@ -1292,8 +1294,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * } } - CS_H; - inTransaction = false; spi_end(); } @@ -1303,9 +1303,9 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * ** Function name: pushImage ** Description: plot 8 or 1 bit image or sprite with a transparent colour ***************************************************************************************/ -void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data, uint8_t transp, bool bpp8) +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8) { - if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; + if ((x >= _width) || (y >= _height)) return; int32_t dx = 0; int32_t dy = 0; @@ -1440,8 +1440,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t * } } - CS_H; - inTransaction = false; spi_end(); } @@ -2254,7 +2252,7 @@ int16_t TFT_eSPI::textWidth(const String& string) return textWidth(buffer, textfont); } -int16_t TFT_eSPI::textWidth(const String& string, int font) +int16_t TFT_eSPI::textWidth(const String& string, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -2267,9 +2265,9 @@ int16_t TFT_eSPI::textWidth(const char *string) return textWidth(string, textfont); } -int16_t TFT_eSPI::textWidth(const char *string, int font) +int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) { - int str_width = 0; + int32_t str_width = 0; #ifdef SMOOTH_FONT if(fontLoaded) @@ -2392,8 +2390,8 @@ int16_t TFT_eSPI::fontHeight(void) ***************************************************************************************/ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) { - if ((x >= (int16_t)_width) || // Clip right - (y >= (int16_t)_height) || // Clip bottom + if ((x >= _width) || // Clip right + (y >= _height) || // Clip bottom ((x + 6 * size - 1) < 0) || // Clip left ((y + 8 * size - 1) < 0)) // Clip top return; @@ -2413,8 +2411,9 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u uint8_t column[6]; uint8_t mask = 0x1; spi_begin(); - //inTransaction = true; + setWindow(x, y, x+5, y+8); + for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); column[5] = 0; @@ -2453,8 +2452,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u } #endif - CS_H; - //inTransaction = false; + spi_end(); } else @@ -2644,8 +2642,9 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h) { spi_begin(); + setWindow(x0, y0, x0 + w - 1, y0 + h - 1); - CS_H; + spi_end(); } @@ -2658,7 +2657,7 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) && !defined (RPI_ILI9486_DRIVER) void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow #ifdef CGRAM_OFFSET xs+=colstart; @@ -2669,7 +2668,6 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Column addr set DC_C; - CS_L; uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; @@ -2726,14 +2724,13 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; addr_row = 0xFFFF; // Column addr set DC_C; - CS_L; uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; @@ -2781,9 +2778,8 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow - CS_L; uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); @@ -2858,7 +2854,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; addr_row = 0xFFFF; @@ -2870,7 +2866,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) y1+=rowstart; #endif - CS_L_DC_C; + DC_C; tft_Write_8(TFT_CASET); @@ -2918,7 +2914,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - //spi_begin(); + spi_begin(); int32_t xe = xs + w - 1; int32_t ye = ys + h - 1; @@ -2935,7 +2931,6 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // Column addr set DC_C; - CS_L; uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; @@ -2987,7 +2982,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - //spi_begin(); + spi_begin(); int32_t xe = xs + w - 1; int32_t ye = ys + h - 1; @@ -3003,7 +2998,7 @@ ye += rowstart; #endif // Column addr set - CS_L_DC_C; + DC_C; tft_Write_8(TFT_CASET); @@ -3036,11 +3031,11 @@ ye += rowstart; ** Description: push a single pixel at an arbitrary position ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; - + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + #ifdef CGRAM_OFFSET x+=colstart; y+=rowstart; @@ -3048,8 +3043,6 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) spi_begin(); - CS_L; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; // No need to send x if it has not changed (speeds things up) @@ -3127,8 +3120,6 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) while(SPI1CMD & SPIBUSY) {} #endif - CS_H; - spi_end(); } @@ -3136,13 +3127,13 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + spi_begin(); - CS_L; uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = SPI1U1 & mask; SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); @@ -3214,17 +3205,16 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} - CS_H; - spi_end(); } #else // ESP32 -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + spi_begin(); #ifdef CGRAM_OFFSET @@ -3232,7 +3222,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) y+=rowstart; #endif - CS_L_DC_C; + DC_C; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { @@ -3279,8 +3269,6 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) tft_Write_16(color); - CS_H; - spi_end(); } #endif @@ -3295,12 +3283,8 @@ void TFT_eSPI::pushColor(uint16_t color) { spi_begin(); - CS_L; - tft_Write_16(color); - CS_H; - spi_end(); } @@ -3313,8 +3297,6 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) { spi_begin(); - CS_L; - #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; if(len) spi.writePattern(&colorBin[0], 2, 1); len--; @@ -3327,8 +3309,6 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) #endif #endif - CS_H; - spi_end(); } @@ -3340,7 +3320,6 @@ void TFT_eSPI::startWrite(void) { spi_begin(); inTransaction = true; - CS_L; } /*************************************************************************************** @@ -3349,7 +3328,6 @@ void TFT_eSPI::startWrite(void) ***************************************************************************************/ void TFT_eSPI::endWrite(void) { - CS_H; inTransaction = false; spi_end(); } @@ -3383,8 +3361,6 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) { spi_begin(); - CS_L; - #if defined (RPI_WRITE_STROBE) while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } if (len) spi.writePattern(data, len, 1); @@ -3404,8 +3380,6 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) #endif #endif - CS_H; - spi_end(); } @@ -3418,8 +3392,6 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) { spi_begin(); - CS_L; - #if defined (ESP32) || defined (ILI9488_DRIVER) #if defined (ESP32_PARALLEL) || defined (ILI9488_DRIVER) if (swap) while ( len-- ) {tft_Write_16(*data); data++;} @@ -3505,8 +3477,6 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) #endif - CS_H; - spi_end(); } @@ -3609,7 +3579,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (steep) // y increments every iteration (y0 is x-axis, and x0 is y-axis) { - if (x1 >= _height) x1 = _height - 1; + if (x1 >= (int32_t)_height) x1 = _height - 1; for (; x0 <= x1; x0++) { if ((x0 >= 0) && (y0 >= 0) && (y0 < _width)) break; @@ -3646,7 +3616,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x1 >= _width) x1 = _width - 1; for (; x0 <= x1; x0++) { - if ((x0 >= 0) && (y0 >= 0) && (y0 < _height)) break; + if ((x0 >= 0) && (y0 >= 0) && (y0 < (int32_t)_height)) break; err -= dy; if (err < 0) { err += dx; @@ -3666,7 +3636,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t err -= dy; if (err < 0) { y0 += ystep; - if ((y0 < 0) || (y0 >= _height)) break; + if ((y0 < 0) || (y0 >= (int32_t)_height)) break; err += dx; while(SPI1CMD & SPIBUSY) {} setWindow(x0+1, y0, _width, y0); @@ -3678,7 +3648,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t while(SPI1CMD & SPIBUSY) {} SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; - CS_H; + spi_end(); } @@ -3707,8 +3677,6 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) writeBlock(color, h); - CS_H; - spi_end(); } @@ -3748,8 +3716,6 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #endif #endif - CS_H; - spi_end(); } #endif @@ -3776,8 +3742,6 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) writeBlock(color, w); - CS_H; - spi_end(); } @@ -3785,11 +3749,17 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (w < 1)) return; - if ((x + w - 1) >= _width) w = _width - x; + // Clipping + if ((y < 0) || (x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + + if ((x + w) > _width) w = _width - x; + + if (w < 1) return; spi_begin(); + setWindow(x, y, x + w - 1, y); #ifdef RPI_WRITE_STROBE @@ -3811,8 +3781,6 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #endif #endif - CS_H; - spi_end(); } #endif @@ -3836,12 +3804,11 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col if ((w < 1) || (h < 1)) return; spi_begin(); + setWindow(x, y, x + w - 1, y + h - 1); writeBlock(color, w * h); - CS_H; - spi_end(); } @@ -3849,6 +3816,7 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { + // Clipping if ((x >= _width) || (y >= _height)) return; @@ -3861,6 +3829,7 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col if ((w < 1) || (h < 1)) return; spi_begin(); + setWindow(x, y, x + w - 1, y + h - 1); uint32_t n = (uint32_t)w * (uint32_t)h; @@ -3885,8 +3854,6 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col #endif #endif - CS_H; - spi_end(); } #endif @@ -4047,7 +4014,7 @@ size_t TFT_eSPI::write(uint8_t utf8) cursor_y += height; cursor_x = 0; } - if (textwrapY && (cursor_y >= _height)) cursor_y = 0; + if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0; cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont); } @@ -4077,7 +4044,7 @@ size_t TFT_eSPI::write(uint8_t utf8) cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } - if (textwrapY && (cursor_y >= _height)) cursor_y = 0; + if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0; drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize); } cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; @@ -4094,12 +4061,12 @@ size_t TFT_eSPI::write(uint8_t utf8) ** Function name: drawChar ** Description: draw a Unicode onto the screen ***************************************************************************************/ -int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y) +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) { return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { if (font==1) @@ -4142,8 +4109,8 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; - int width = 0; - int height = 0; + int32_t width = 0; + int32_t height = 0; uint32_t flash_address = 0; uniCode -= 32; @@ -4172,9 +4139,9 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } #endif - int w = width; - int pX = 0; - int pY = y; + int32_t w = width; + int32_t pX = 0; + int32_t pY = y; uint8_t line = 0; #ifdef LOAD_FONT2 // chop out code if we do not need it @@ -4187,11 +4154,11 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) spi_begin(); inTransaction = true; - for (int i = 0; i < height; i++) + for (int32_t i = 0; i < height; i++) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); - for (int k = 0; k < w; k++) + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); if (line) { @@ -4229,12 +4196,13 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) // Faster drawing of characters and background using block write { spi_begin(); + setWindow(x, y, (x + w * 8) - 1, y + height - 1); uint8_t mask; - for (int i = 0; i < height; i++) + for (int32_t i = 0; i < height; i++) { - for (int k = 0; k < w; k++) + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); pX = x + k * 8; @@ -4248,7 +4216,6 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) pY += textsize; } - CS_H; spi_end(); } } @@ -4266,8 +4233,8 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) w *= height; // Now w is total number of pixels in the character if ((textsize != 1) || (textcolor == textbgcolor)) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor); - int px = 0, py = pY; // To hold character block start and end column and row values - int pc = 0; // Pixel count + int32_t px = 0, py = pY; // To hold character block start and end column and row values + int32_t pc = 0; // Pixel count uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel uint8_t tnp = 0; // Temporary copy of np for while loop @@ -4313,7 +4280,6 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } } - CS_H; spi_end(); } else // Text colour != background && textsize = 1 @@ -4359,7 +4325,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) #endif } } - CS_H; + spi_end(); } } @@ -4374,7 +4340,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) ** Description : draw string with padding if it is defined ***************************************************************************************/ // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const String& string, int poX, int poY) +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY) { int16_t len = string.length() + 2; char buffer[len]; @@ -4382,7 +4348,7 @@ int16_t TFT_eSPI::drawString(const String& string, int poX, int poY) return drawString(buffer, poX, poY, textfont); } // With font number -int16_t TFT_eSPI::drawString(const String& string, int poX, int poY, int font) +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -4391,13 +4357,13 @@ int16_t TFT_eSPI::drawString(const String& string, int poX, int poY, int font) } // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const char *string, int poX, int poY) +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) { return drawString(string, poX, poY, textfont); } // With font number -int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) { int16_t sumX = 0; uint8_t padding = 1, baseline = 0; @@ -4536,6 +4502,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) uint16_t len = strlen(string); uint16_t n = 0; setCursor(poX, poY); + while (n < len) { uint16_t unicode = decodeUTF8((uint8_t*)string, &n, len - n); @@ -4623,7 +4590,7 @@ return sumX; ** Function name: drawCentreString (deprecated, use setTextDatum()) ** Descriptions: draw string centred on dX ***************************************************************************************/ -int16_t TFT_eSPI::drawCentreString(const String& string, int dX, int poY, int font) +int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -4631,10 +4598,10 @@ int16_t TFT_eSPI::drawCentreString(const String& string, int dX, int poY, int fo return drawCentreString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawCentreString(const char *string, int dX, int poY, int font) +int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font) { uint8_t tempdatum = textdatum; - int sumX = 0; + int32_t sumX = 0; textdatum = TC_DATUM; sumX = drawString(string, dX, poY, font); textdatum = tempdatum; @@ -4646,7 +4613,7 @@ int16_t TFT_eSPI::drawCentreString(const char *string, int dX, int poY, int font ** Function name: drawRightString (deprecated, use setTextDatum()) ** Descriptions: draw string right justified to dX ***************************************************************************************/ -int16_t TFT_eSPI::drawRightString(const String& string, int dX, int poY, int font) +int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -4654,7 +4621,7 @@ int16_t TFT_eSPI::drawRightString(const String& string, int dX, int poY, int fon return drawRightString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) +int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font) { uint8_t tempdatum = textdatum; int16_t sumX = 0; @@ -4669,7 +4636,7 @@ int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) ** Function name: drawNumber ** Description: draw a long integer ***************************************************************************************/ -int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY) +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY) { isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; @@ -4677,7 +4644,7 @@ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY) return drawString(str, poX, poY, textfont); } -int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font) +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font) { isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; @@ -4692,12 +4659,12 @@ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font) ***************************************************************************************/ // Assemble and print a string, this permits alignment relative to a datum // looks complicated but much more compact and actually faster than using print class -int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY) +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY) { return drawFloat(floatNumber, dp, poX, poY, textfont); } -int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int font) +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font) { isDigits = true; char str[14]; // Array to contain decimal string diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 01a1351..66546c7 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -15,7 +15,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "1.4.0" +#define TFT_ESPI_VERSION "1.4.1" //#define ESP32 //Just used to test ESP32 options @@ -144,8 +144,8 @@ #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #else - #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32));GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) - #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32));GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #endif #else #if TFT_DC >= 0 @@ -155,8 +155,8 @@ #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) #else - #define DC_C GPIO.out_w1tc = (1 << TFT_DC);GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1ts = (1 << TFT_DC);GPIO.out_w1ts = (1 << TFT_DC) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC) #endif #else #define DC_C @@ -193,8 +193,8 @@ #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #else - #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32));GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) - #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32));GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #endif #else #if TFT_CS >= 0 @@ -203,7 +203,7 @@ #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) #else #define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1ts = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS) #endif #else #define CS_L @@ -653,15 +653,15 @@ class TFT_eSPI : public Print { void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); // Same - begin included for backwards compatibility // These are virtual so the TFT_eSprite class can override them with sprite specific functions - virtual void drawPixel(uint32_t x, uint32_t y, uint32_t color), + virtual void drawPixel(int32_t x, int32_t y, uint32_t color), drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); - virtual int16_t drawChar(unsigned int uniCode, int x, int y, int font), - drawChar(unsigned int uniCode, int x, int y), + virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y), height(void), width(void); @@ -720,30 +720,30 @@ class TFT_eSPI : public Print { commandList(const uint8_t *addr); - uint8_t readcommand8(uint8_t cmd_function, uint8_t index); - uint16_t readcommand16(uint8_t cmd_function, uint8_t index); - uint32_t readcommand32(uint8_t cmd_function, uint8_t index); + uint8_t readcommand8(uint8_t cmd_function, uint8_t index = 0); + uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); + uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // Read the colour of a pixel at x,y and return value in 565 format uint16_t readPixel(int32_t x0, int32_t y0); // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location // Read a block of pixels to a data buffer, buffer is 16 bit and the array size must be at least w * h - void readRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void readRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); // Write a block of pixels to the screen - void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void pushRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); // These are used to render images or sprites stored in RAM arrays - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data); - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data, uint16_t transparent); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); // These are used to render images stored in FLASH (PROGMEM) - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transparent); - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); // These are used by pushSprite for 1 and 8 bit colours - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, bool bpp8 = true); - void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true); // Swap the byte order for pushImage() - corrects endianness void setSwapBytes(bool swap); @@ -768,26 +768,26 @@ class TFT_eSPI : public Print { color565(uint8_t red, uint8_t green, uint8_t blue), // Convert 8 bit red, green and blue to 16 bits color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits - int16_t drawNumber(long long_num,int poX, int poY, int font), - drawNumber(long long_num,int poX, int poY), - drawFloat(float floatNumber,int decimal,int poX, int poY, int font), - drawFloat(float floatNumber,int decimal,int poX, int poY), + int16_t drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font), + drawNumber(long long_num, int32_t poX, int32_t poY), + drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY, uint8_t font), + drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY), // Handle char arrays - drawString(const char *string, int poX, int poY, int font), - drawString(const char *string, int poX, int poY), - drawCentreString(const char *string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const char *string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() + drawString(const char *string, int32_t poX, int32_t poY, uint8_t font), + drawString(const char *string, int32_t poX, int32_t poY), + drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() // Handle String type - drawString(const String& string, int poX, int poY, int font), - drawString(const String& string, int poX, int poY), - drawCentreString(const String& string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const String& string, int dX, int poY, int font); // Deprecated, use setTextDatum() and drawString() + drawString(const String& string, int32_t poX, int32_t poY, uint8_t font), + drawString(const String& string, int32_t poX, int32_t poY), + drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font); // Deprecated, use setTextDatum() and drawString() - int16_t textWidth(const char *string, int font), + int16_t textWidth(const char *string, uint8_t font), textWidth(const char *string), - textWidth(const String& string, int font), + textWidth(const String& string, uint8_t font), textWidth(const String& string), fontHeight(int16_t font), fontHeight(void); @@ -852,9 +852,9 @@ class TFT_eSPI : public Print { int32_t win_xe, win_ye; - uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation() - uint32_t _width, _height; // Display w/h as modified by current rotation - uint32_t addr_row, addr_col; + int32_t _init_width, _init_height; // Display w/h as input, used by setRotation() + int32_t _width, _height; // Display w/h as modified by current rotation + int32_t addr_row, addr_col; uint32_t fontsloaded; diff --git a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino index 148499e..1cb0515 100644 --- a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino +++ b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino @@ -324,7 +324,7 @@ uint32_t testHaD() uint16_t curcolor = 0; const uint8_t *cmp = &HaD_128x160[0]; - + tft.startWrite(); while (cmp < &HaD_128x160[sizeof(HaD_128x160)]) { cnt = pgm_read_byte(cmp++); @@ -335,6 +335,7 @@ uint32_t testHaD() curcolor ^= color; } + tft.endWrite(); } tft.endWrite(); @@ -409,7 +410,7 @@ uint32_t testPixels() int32_t h = tft.height(); uint32_t start = micros_start(); - + tft.startWrite(); for (uint16_t y = 0; y < h; y++) { for (uint16_t x = 0; x < w; x++) @@ -417,7 +418,7 @@ uint32_t testPixels() tft.drawPixel(x, y, tft.color565(x<<3, y<<3, x*y)); } } - + tft.endWrite(); return micros() - start; } diff --git a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino index 8e03ef5..ee76936 100644 --- a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino +++ b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino @@ -434,7 +434,7 @@ uint32_t testPixels() int32_t h = tft.height(); uint32_t start = micros_start(); - + tft.startWrite(); for (uint16_t y = 0; y < h; y++) { for (uint16_t x = 0; x < w; x++) @@ -442,7 +442,7 @@ uint32_t testPixels() tft.drawPixel(x, y, tft.color565(x<<3, y<<3, x*y)); } } - + tft.endWrite(); return micros() - start; } diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index 45d48bf..d0a2f1f 100644 --- a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -41,6 +41,8 @@ void loop(void) { tft.getSetup(user); // Serial.printf("\n[code]\n"); + +Serial.printf("TFT_eSPI ver = " + user.version) +"\n"); Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); #ifdef ESP8266 diff --git a/library.json b/library.json index d32cf0c..4ac48a5 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.0", + "version": "1.4.1", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 834703f..a73d64e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.0 +version=1.4.1 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 33d93131134e7b642ddba9711fa6eedc2af3306f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 31 Jan 2019 01:17:19 +0000 Subject: [PATCH 74/94] Update for ESP8266 ESP32 printf() can handle String type but ESP8266 cannot. --- .../Test and diagnostics/Read_User_Setup/Read_User_Setup.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index d0a2f1f..1cf8f3f 100644 --- a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -41,8 +41,8 @@ void loop(void) { tft.getSetup(user); // Serial.printf("\n[code]\n"); - -Serial.printf("TFT_eSPI ver = " + user.version) +"\n"); +String ver = user.version; +Serial.println("TFT_eSPI ver = " + ver +"\n"); Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); #ifdef ESP8266 From 091d8cd2317bce14baa0a8ed784f7d542a5396a5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 3 Feb 2019 21:53:52 +0000 Subject: [PATCH 75/94] Fix issue #297 There is a bug in the ESP8266 Arduino core that averwrites the overlap mode setup and hold bits for the hardware driven SPI SS line. The TFT_eSPI library has been patched as a work-around. In overlap mode to maintain the required setup and hold times at 80MHz ESP8266 CPU clock the SPI rate must be 27MHz or less. At 160MHz CPU clock the SPI rate can be 40MHz. --- TFT_eSPI.cpp | 122 +++++++++++++++++++-------------------------- TFT_eSPI.h | 9 +++- library.json | 2 +- library.properties | 2 +- 4 files changed, 61 insertions(+), 74 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 20ae7df..0681144 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -48,10 +48,6 @@ uint8_t readByte(void); // GPIO parallel input/output control void busDir(uint32_t mask, uint8_t mode); -// If the SPI library has transaction support, these functions -// establish settings and protect from interference from other -// libraries. Otherwise, they simply do nothing. - inline void TFT_eSPI::spi_begin(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} @@ -77,6 +73,9 @@ inline void TFT_eSPI::spi_begin_read(void){ #endif CS_L; #endif +#ifdef ESP8266 + SPI1U = SPI1U_READ; +#endif } inline void TFT_eSPI::spi_end_read(void){ @@ -88,6 +87,9 @@ inline void TFT_eSPI::spi_end_read(void){ #endif CS_H; #endif +#ifdef ESP8266 + SPI1U = SPI1U_WRITE; +#endif } #if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(ESP32_PARALLEL) @@ -279,7 +281,8 @@ void TFT_eSPI::init(uint8_t tc) spi.pins(6, 7, 8, 0); #endif - spi.begin(); // This will set HMISO to input + spi.begin(); // This will set HMISO to input + #else #if !defined(ESP32_PARALLEL) #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) @@ -313,7 +316,7 @@ void TFT_eSPI::init(uint8_t tc) spi.setHwCs(1); // Use hardware SS toggling #endif #endif - + // Set to output once again in case D6 (MISO) is used for DC #ifdef TFT_DC digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode @@ -1822,8 +1825,9 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col drawFastHLine(x, y, w, color); drawFastHLine(x, y + h - 1, w, color); - drawFastVLine(x, y, h, color); - drawFastVLine(x + w - 1, y, h, color); + // Avoid drawing corner pixels twice + drawFastVLine(x, y+1, h-2, color); + drawFastVLine(x + w - 1, y+1, h-2, color); inTransaction = false; spi_end(); @@ -2420,8 +2424,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #if defined (ESP8266) && !defined (ILI9488_DRIVER) color = (color >> 8) | (color << 8); bg = (bg >> 8) | (bg << 8); - uint32_t spimask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - SPI1U1 = (SPI1U1 & spimask) | (15 << SPILMOSI) | (15 << SPILMISO); + for (int8_t j = 0; j < 8; j++) { for (int8_t k = 0; k < 5; k++ ) { if (column[k] & mask) { @@ -2669,10 +2672,8 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Column addr set DC_C; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U = SPI1U_WRITE; + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET; SPI1CMD |= SPIBUSY; @@ -2684,7 +2685,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); SPI1CMD |= SPIBUSY; @@ -2693,7 +2694,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET; SPI1CMD |= SPIBUSY; @@ -2701,7 +2702,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); SPI1CMD |= SPIBUSY; @@ -2710,13 +2711,14 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // write to RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); //spi_end(); } @@ -2732,10 +2734,8 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Column addr set DC_C; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U = SPI1U_WRITE; + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET<<8; SPI1CMD |= SPIBUSY; @@ -2749,7 +2749,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET<<8; SPI1CMD |= SPIBUSY; @@ -2763,7 +2763,7 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // write to RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR<<8; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -2780,9 +2780,8 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); // Must be called before setWimdow - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U = SPI1U_WRITE; + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // Column addr set DC_C; @@ -2932,10 +2931,8 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // Column addr set DC_C; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U = SPI1U_WRITE; + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET; SPI1CMD |= SPIBUSY; @@ -2943,7 +2940,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); SPI1CMD |= SPIBUSY; @@ -2952,7 +2949,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET; SPI1CMD |= SPIBUSY; @@ -2960,7 +2957,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); SPI1CMD |= SPIBUSY; @@ -2969,7 +2966,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // read from RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMRD; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -3043,14 +3040,13 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) spi_begin(); - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; + SPI1U = SPI1U_WRITE; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -3061,7 +3057,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)}; spi.writePattern(&cBin[0], 4, 2); #else - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go uint32_t xswap = (x >> 8) | (uint16_t)(x << 8); SPI1W0 = xswap | (xswap << 16); @@ -3077,7 +3073,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; @@ -3089,7 +3085,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)}; spi.writePattern(&cBin[0], 4, 2); #else - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go uint32_t yswap = (y >> 8) | (uint16_t)(y << 8); SPI1W0 = yswap | (yswap << 16); @@ -3102,7 +3098,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; @@ -3113,7 +3109,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #if defined (ILI9488_DRIVER) tft_Write_16(color); #else - SPI1U1 = mask | (15 << SPILMOSI) | (15 << SPILMISO); + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; @@ -3134,9 +3130,8 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) spi_begin(); - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U = SPI1U_WRITE; + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // No need to send x if it has not changed (speeds things up) if (addr_col != x) { DC_C; @@ -3404,9 +3399,9 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) uint32_t color[8]; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); + SPI1U = SPI1U_WRITE; + SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO); - SPI1U1 = (SPI1U1 & mask) | (255 << SPILMOSI) | (255 << SPILMISO); while(len>15) { @@ -3461,7 +3456,7 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) memcpy(color,data,len<<1); } while(SPI1CMD & SPIBUSY) {} - SPI1U1 = (SPI1U1 & mask) | (bits << SPILMOSI) | (bits << SPILMISO); + SPI1U1 = (bits << SPILMOSI) | (bits << SPILMISO); SPI1W0 = color[0]; SPI1W1 = color[1]; SPI1W2 = color[2]; @@ -3572,9 +3567,6 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t spi_begin(); - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = (SPI1U1 & mask) | (15 << SPILMOSI) | (15 << SPILMISO); - SPI1U = SPIUMOSI | SPIUSSE; int16_t swapped_color = (color >> 8) | (color << 8); if (steep) // y increments every iteration (y0 is x-axis, and x0 is y-axis) @@ -3593,7 +3585,6 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x0 > x1) {spi_end(); return;} setWindow(y0, x0, y0, _height); - SPI1U1 = mask; SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { while(SPI1CMD & SPIBUSY) {} @@ -3606,7 +3597,6 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t err += dx; while(SPI1CMD & SPIBUSY) {} setWindow(y0, x0+1, y0, _height); - SPI1U1 = mask; SPI1W0 = swapped_color; } } @@ -3627,7 +3617,6 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x0 > x1) {spi_end(); return;} setWindow(x0, y0, _width, y0); - SPI1U1 = mask; SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { while(SPI1CMD & SPIBUSY) {} @@ -3640,14 +3629,12 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t err += dx; while(SPI1CMD & SPIBUSY) {} setWindow(x0+1, y0, _width, y0); - SPI1U1 = mask; SPI1W0 = swapped_color; } } } while(SPI1CMD & SPIBUSY) {} - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; spi_end(); } @@ -3699,7 +3686,6 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #ifdef RPI_WRITE_STROBE #if defined (ESP8266) - // SPI1U1 will already be set to transfer 16 bits by setWindow() SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -3764,7 +3750,6 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #ifdef RPI_WRITE_STROBE #if defined (ESP8266) - // SPI1U1 will already be set to transfer 16 bits by setWindow() SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -4809,9 +4794,8 @@ void writeBlock(uint16_t color, uint32_t repeat) { uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; - uint32_t mask = ~(SPIMMOSI << SPILMOSI); - mask = SPI1U1 & mask; - SPI1U = SPIUMOSI | SPIUSSE; + + SPI1U = SPI1U_WRITE; SPI1W0 = color32; SPI1W1 = color32; @@ -4840,7 +4824,7 @@ void writeBlock(uint16_t color, uint32_t repeat) } if (repeat > 31) { - SPI1U1 = mask | (511 << SPILMOSI); + SPI1U1 = (511 << SPILMOSI); while(repeat>31) { #if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000) @@ -4856,12 +4840,11 @@ void writeBlock(uint16_t color, uint32_t repeat) if (repeat) { repeat = (repeat << 4) - 1; - SPI1U1 = mask | (repeat << SPILMOSI); + SPI1U1 = (repeat << SPILMOSI); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; } #elif defined (ILI9488_DRIVER) @@ -4870,9 +4853,7 @@ void writeBlock(uint16_t color, uint32_t repeat) void writeBlock(uint16_t color, uint32_t repeat) { - uint32_t mask = ~(SPIMMOSI << SPILMOSI); - mask = SPI1U1 & mask; - SPI1U = SPIUMOSI | SPIUSSE; + SPI1U = SPI1U_WRITE; // Split out the colours uint8_t r = (color & 0xF800)>>8; @@ -4912,7 +4893,7 @@ void writeBlock(uint16_t color, uint32_t repeat) if (repeat > 20) { - SPI1U1 = mask | (503 << SPILMOSI); + SPI1U1 = (503 << SPILMOSI); while(repeat>20) { while(SPI1CMD & SPIBUSY) {} @@ -4925,12 +4906,11 @@ void writeBlock(uint16_t color, uint32_t repeat) if (repeat) { repeat = (repeat * 24) - 1; - SPI1U1 = mask | (repeat << SPILMOSI); + SPI1U1 = (repeat << SPILMOSI); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; } #else // Now the code for ESP32 and ILI9488 diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 66546c7..512bedc 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -15,7 +15,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "1.4.1" +#define TFT_ESPI_VERSION "1.4.2" //#define ESP32 //Just used to test ESP32 options @@ -172,6 +172,13 @@ #if defined (TFT_SPI_OVERLAP) #undef TFT_CS + #define SPI1U_WRITE (SPIUMOSI | SPIUSSE | SPIUCSSETUP | SPIUCSHOLD) + #define SPI1U_READ (SPIUMOSI | SPIUSSE | SPIUCSSETUP | SPIUCSHOLD | SPIUDUPLEX) +#else + #ifdef ESP8266 + #define SPI1U_WRITE (SPIUMOSI | SPIUSSE) + #define SPI1U_READ (SPIUMOSI | SPIUSSE | SPIUDUPLEX) + #endif #endif #ifndef TFT_CS diff --git a/library.json b/library.json index 4ac48a5..ac3228d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.1", + "version": "1.4.2", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index a73d64e..9de9fc2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.1 +version=1.4.2 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 7479f7e680547ca449c26a9839ef191b40c19f9b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 4 Feb 2019 01:48:53 +0000 Subject: [PATCH 76/94] Fix transparent Sprite rendering --- TFT_eSPI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 0681144..0902360 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -60,7 +60,7 @@ inline void TFT_eSPI::spi_end(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} #else - CS_H; + if(!inTransaction) CS_H; #endif } From 61dfb2b4acb2ffbf3a397d809317d6f7d5710807 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 8 Feb 2019 18:25:55 +0000 Subject: [PATCH 77/94] Extended character set suport for Adafruit_GFX format fonts Supports Adafruit_GFX compatible font format with characters in the range 32-255. Note that the font rendering functions expect UTF-8 encoded characters/strings. --- Extensions/Smooth_font.cpp | 4 + TFT_eSPI.cpp | 142 +- .../Local_Custom_Fonts/Local_Custom_Fonts.ino | 123 + examples/Generic/Local_Custom_Fonts/MyFont.h | 3366 +++++++++++++++++ library.json | 2 +- library.properties | 2 +- 6 files changed, 3618 insertions(+), 21 deletions(-) create mode 100644 examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino create mode 100644 examples/Generic/Local_Custom_Fonts/MyFont.h diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 1952add..855aa62 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -246,6 +246,7 @@ void TFT_eSPI::unloadFont( void ) ** Function name: decodeUTF8 ** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII *************************************************************************************x*/ +/* Function moved to TFT_eSPI.cpp #define DECODE_UTF8 uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) { @@ -273,11 +274,13 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) return c; // fall-back to extended ASCII } +*/ /*************************************************************************************** ** Function name: decodeUTF8 ** Description: Serial UTF-8 decoder with fall-back to extended ASCII *************************************************************************************x*/ +/* Function moved to TFT_eSPI.cpp uint16_t TFT_eSPI::decodeUTF8(uint8_t c) { @@ -329,6 +332,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c) decoderState = 0; return (uint16_t)c; // fall-back to extended ASCII } +*/ diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 0902360..5e24cd8 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -13,6 +13,7 @@ Bodmer: Added RPi 16 bit display support ****************************************************/ + #include "TFT_eSPI.h" #if defined (ESP32) @@ -85,7 +86,7 @@ inline void TFT_eSPI::spi_end_read(void){ #if !defined(ESP32_PARALLEL) spi.setFrequency(SPI_FREQUENCY); #endif - CS_H; + if(!inTransaction) CS_H; #endif #ifdef ESP8266 SPI1U = SPI1U_WRITE; @@ -342,17 +343,6 @@ void TFT_eSPI::init(uint8_t tc) writecommand(TFT_SWRST); // Software reset #endif -#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON) - digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); - pinMode(TFT_BL, OUTPUT); -#else - #if defined (TFT_BL) && defined (M5STACK) - // Turn on the back-light LED - digitalWrite(TFT_BL, HIGH); - pinMode(TFT_BL, OUTPUT); - #endif -#endif - spi_end(); delay(150); // Wait for reset to complete @@ -407,6 +397,17 @@ void TFT_eSPI::init(uint8_t tc) spi_end(); setRotation(rotation); + +#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON) + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); + pinMode(TFT_BL, OUTPUT); +#else + #if defined (TFT_BL) && defined (M5STACK) + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); + #endif +#endif } @@ -2324,7 +2325,7 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) { while (*string) { - uniCode = *(string++); + uniCode = decodeUTF8(*string++); if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) { uniCode -= pgm_read_byte(&gfxFont->first); @@ -3895,6 +3896,95 @@ void TFT_eSPI::invertDisplay(boolean i) } +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Serial UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +#define DECODE_UTF8 // Test only, comment out to stop decoding +uint16_t TFT_eSPI::decodeUTF8(uint8_t c) +{ +#ifdef DECODE_UTF8 + // 7 bit Unicode Code Point + if ((c & 0x80) == 0x00) { + decoderState = 0; + return (uint16_t)c; + } + + if (decoderState == 0) + { + // 11 bit Unicode Code Point + if ((c & 0xE0) == 0xC0) + { + decoderBuffer = ((c & 0x1F)<<6); + decoderState = 1; + return 0; + } + + // 16 bit Unicode Code Point + if ((c & 0xF0) == 0xE0) + { + decoderBuffer = ((c & 0x0F)<<12); + decoderState = 2; + return 0; + } + // 21 bit Unicode Code Point not supported so fall-back to extended ASCII + if ((c & 0xF8) == 0xF0) return (uint16_t)c; + } + else + { + if (decoderState == 2) + { + decoderBuffer |= ((c & 0x3F)<<6); + decoderState--; + return 0; + } + else + { + decoderBuffer |= (c & 0x3F); + decoderState = 0; + return decoderBuffer; + } + } + + decoderState = 0; +#endif + + return (uint16_t)c; // fall-back to extended ASCII +} + + +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) +{ + byte c = buf[(*index)++]; + //Serial.print("Byte from string = 0x"); Serial.println(c, HEX); + +#ifdef DECODE_UTF8 + // 7 bit Unicode + if ((c & 0x80) == 0x00) return c; + + // 11 bit Unicode + if (((c & 0xE0) == 0xC0) && (remaining > 1)) + return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F); + + // 16 bit Unicode + if (((c & 0xF0) == 0xE0) && (remaining > 2)) + { + c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6); + return c | ((buf[(*index)++]&0x3F)); + } + + // 21 bit Unicode not supported so fall-back to extended ASCII + // if ((c & 0xF8) == 0xF0) return c; +#endif + + return c; // fall-back to extended ASCII +} + + /*************************************************************************************** ** Function name: write ** Description: draw characters piped through serial stream @@ -4008,6 +4098,8 @@ size_t TFT_eSPI::write(uint8_t utf8) } // Custom GFX font else { + uniCode = (uint8_t)decodeUTF8(utf8); + if (!uniCode) return 1; if(utf8 == '\n') { cursor_x = 0; @@ -4046,14 +4138,17 @@ size_t TFT_eSPI::write(uint8_t utf8) ** Function name: drawChar ** Description: draw a Unicode onto the screen ***************************************************************************************/ -int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) +int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y) { - return drawChar(uniCode, x, y, textfont); + return drawChar(utf8, x, y, textfont); } -int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) +int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) { + uint16_t uniCode = decodeUTF8(utf8); + if (!uniCode) return 0; + if (font==1) { #ifdef LOAD_GLCD @@ -4458,7 +4553,12 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 { cheight = (glyph_ab + glyph_bb) * textsize; // Get the offset for the first character only to allow for negative offsets - uint8_t c2 = *string; + uint8_t c2 = 0; + uint16_t len = strlen(string); + uint16_t n = 0; + + while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n); + if((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) { c2 -= pgm_read_byte(&gfxFont->first); @@ -4498,8 +4598,12 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 } else #endif - while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); - +Serial.print("sumX="); + while (*string) { + sumX += drawChar(*(string++), poX+sumX, poY, font); + Serial.print(sumX); + } +Serial.println(); //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Switch on debugging for the padding areas //#define PADDING_DEBUG diff --git a/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino new file mode 100644 index 0000000..b26f11e --- /dev/null +++ b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino @@ -0,0 +1,123 @@ +/* + Example for TFT_eSPI library + + This example shows the use of a Adafruit_GFX custom font with a + character code range of 32 - 255, this means accented characters + (amongst others) are available. + + The custom font file is attached to this sketch as a header file. The + font data has been created following the instructions here: + https://www.youtube.com/watch?v=L8MmTISmwZ8 + + Note that online converters for Adafruit_GFX compatible fonts are + available but these typically only use characters in the range 32-127, + and thus do not include the accented characters. These online converters + can however still be used with this sketch but the example characters + used must be changed. + + The Arduino IDE uses UTF8 encoding for these characters. The TFT_eSPI + library also expects characters in the range 128 to 255 to be UTF-8 + encoded. See link here for details: + + https://playground.arduino.cc/Code/UTF-8 + + To sumarise, UTF-8 characters are encoded as mor than 1 byte so care must + be taken: + + char c = 'µ'; // Wrong + char bad[4] = "5µA"; // Wrong + char good[] = "5µA"; // Good + String okay = "5µA"; // Good + + Created by Bodmer 08/02/19 + + Make sure LOAD_GFXFF is defined in the used User_Setup file + within the library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ###### TO SELECT YOUR DISPLAY TYPE, PINS USED AND ENABLE FONTS ###### + ######################################################################### +*/ + +#define TEST_TEXT "ßäöü ñâàå" // Text that will be printed on screen in the font +//#define TEST_TEXT "Hello" // Text that will be printed on screen in the font + +#include "SPI.h" +#include "TFT_eSPI.h" +#include "TFT_eFEX.h" + +// The custom font file attached to this sketch must be included +#include "MyFont.h" + +// Stock font and GFXFF reference handle +#define GFXFF 1 + +// Easily remembered name for the font +#define MYFONT32 &myFont32pt8b + +// Use hardware SPI +TFT_eSPI tft = TFT_eSPI(); +TFT_eFEX fex = TFT_eFEX(&tft); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + +} + +void loop() { + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Show custom fonts + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + // Where font sizes increase the screen is not cleared as the larger fonts overwrite + // the smaller one with the background colour. + + // We can set the text datum to be Top, Middle, Bottom vertically and Left, Centre + // and Right horizontally. These are the text datums that can be used: + // TL_DATUM = Top left (default) + // TC_DATUM = Top centre + // TR_DATUM = Top right + // ML_DATUM = Middle left + // MC_DATUM = Middle centre <<< This is used below + // MR_DATUM = Middle right + // BL_DATUM = Bottom left + // BC_DATUM = Bottom centre + // BR_DATUM = Bottom right + // L_BASELINE = Left character baseline (Line the 'A' character would sit on) + // C_BASELINE = Centre character baseline + // R_BASELINE = Right character baseline + + //Serial.println(); + + // Set text datum to middle centre (MC_DATUM) + tft.setTextDatum(MC_DATUM); + + // Set text colour to white with black background + // Unlike the stock Adafruit_GFX library, the TFT_eSPI library DOES optionally draw + // the background colour for the custom and Free Fonts when using drawString() + tft.setTextColor(TFT_WHITE, TFT_BLACK); // White characters on black background + //tft.setTextColor(TFT_WHITE); // or white characters, no background + + tft.fillScreen(TFT_BLUE); // Clear screen + tft.setFreeFont(MYFONT32); // Select the font + tft.drawString("MyFont 32", 160, 60, GFXFF); // Print the name of the font + tft.setFreeFont(MYFONT32); // Select the font + tft.drawString(TEST_TEXT, 160, 140, GFXFF); // Print the test text in the custom font + delay(2000); +fex.screenServer(); + // Setting textDatum does nothing when using tft.print + tft.fillScreen(TFT_BLUE); // Clear screen + tft.setCursor(0,60); // To be compatible with Adafruit_GFX the cursor datum is always bottom left + tft.print("âäàå"); // Using tft.print means text background is NEVER rendered + delay(2000); + + // Reset text padding to zero (default) + tft.setTextPadding(0); +} diff --git a/examples/Generic/Local_Custom_Fonts/MyFont.h b/examples/Generic/Local_Custom_Fonts/MyFont.h new file mode 100644 index 0000000..da5ee55 --- /dev/null +++ b/examples/Generic/Local_Custom_Fonts/MyFont.h @@ -0,0 +1,3366 @@ +// If you follow the tutorial here: +// https://www.youtube.com/watch?v=L8MmTISmwZ8 +// do not forget the names must be edited to remove the Windows file path. + +// I had to edit lines 8, 3135, 3361-3363 in this file + + +const uint8_t myFont32pt8bBitmaps[] PROGMEM = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xCF, 0xE7, 0xF3, + 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0x8F, 0xC7, 0xE1, 0xF0, 0xF8, 0x7C, + 0x3E, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF8, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, + 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, + 0xFF, 0xC3, 0xFF, 0x7F, 0xC3, 0xFF, 0x7F, 0xC1, 0xFE, 0x7F, 0x81, 0xFE, + 0x7F, 0x81, 0xFE, 0x7F, 0x81, 0xFE, 0x3F, 0x81, 0xFE, 0x3F, 0x80, 0xFE, + 0x3F, 0x80, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, + 0x0F, 0xE0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x1F, 0xE0, + 0x01, 0xFC, 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x00, 0xFE, 0x03, 0xF8, + 0x00, 0x7F, 0x01, 0xFC, 0x00, 0x3F, 0x81, 0xFE, 0x00, 0x1F, 0x80, 0xFE, + 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7F, 0x01, 0xFC, 0x00, 0x3F, 0x81, + 0xFC, 0x00, 0x3F, 0x80, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0xE0, + 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x1F, 0xC0, 0x03, 0xF8, + 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, + 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x00, + 0xFE, 0x03, 0xF8, 0x00, 0x7F, 0x03, 0xF8, 0x00, 0x7F, 0x01, 0xFC, 0x00, + 0x3F, 0x80, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0xE0, 0x3F, 0x80, + 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x07, 0xC0, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF8, 0x03, + 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, + 0x7F, 0xFF, 0x0F, 0xF9, 0xF3, 0xFC, 0x3F, 0xC7, 0xCF, 0xF9, 0xFE, 0x1F, + 0x1F, 0xE7, 0xF8, 0x7C, 0x78, 0x1F, 0xE1, 0xF0, 0x00, 0x7F, 0x87, 0xC0, + 0x00, 0xFF, 0x1F, 0x00, 0x03, 0xFC, 0x7C, 0x00, 0x0F, 0xFD, 0xF0, 0x00, + 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xE0, 0x00, 0x7D, 0xFF, 0xC0, 0x01, 0xF1, 0xFF, 0x00, 0x07, 0xC3, + 0xFC, 0x00, 0x1F, 0x0F, 0xF0, 0xF0, 0x7C, 0x1F, 0xFF, 0xE1, 0xF0, 0x7F, + 0xFF, 0x87, 0xC1, 0xFD, 0xFE, 0x1F, 0x0F, 0xF7, 0xFC, 0x7C, 0x3F, 0xDF, + 0xF9, 0xF1, 0xFF, 0x3F, 0xF7, 0xCF, 0xF8, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, + 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, + 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x80, + 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xF0, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFC, 0x00, 0x1F, 0xC7, 0xF8, 0x00, 0x7E, + 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x1F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x0F, + 0xC0, 0x00, 0xFE, 0x07, 0xE0, 0x03, 0xF0, 0x00, 0x3F, 0x81, 0xFC, 0x01, + 0xF8, 0x00, 0x0F, 0xE0, 0x7F, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x1F, 0xC0, + 0x3F, 0x00, 0x00, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x00, 0x3F, 0x01, 0xFC, + 0x07, 0xE0, 0x00, 0x0F, 0xE0, 0x7F, 0x01, 0xF8, 0x00, 0x03, 0xF8, 0x1F, + 0x80, 0xFC, 0x00, 0x00, 0xFE, 0x0F, 0xE0, 0x3F, 0x00, 0x00, 0x3F, 0x83, + 0xF8, 0x1F, 0x80, 0x00, 0x07, 0xF1, 0xFE, 0x07, 0xE0, 0x00, 0x01, 0xFF, + 0xFF, 0x03, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xE0, 0x7E, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x1F, 0x80, 0x00, 0x00, + 0x0F, 0xE0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x07, 0xF0, + 0x00, 0x00, 0x01, 0xF8, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x7E, 0x07, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0x03, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xC0, 0xFF, + 0xFF, 0x00, 0x00, 0x07, 0xE0, 0x7F, 0x8F, 0xE0, 0x00, 0x01, 0xF8, 0x1F, + 0xC3, 0xF8, 0x00, 0x00, 0xFC, 0x07, 0xE0, 0x7F, 0x00, 0x00, 0x3F, 0x03, + 0xF8, 0x1F, 0xC0, 0x00, 0x1F, 0x80, 0xFE, 0x07, 0xF0, 0x00, 0x07, 0xE0, + 0x3F, 0x81, 0xFC, 0x00, 0x03, 0xF0, 0x0F, 0xE0, 0x7F, 0x00, 0x00, 0xFC, + 0x03, 0xF8, 0x1F, 0xC0, 0x00, 0x7E, 0x00, 0xFE, 0x07, 0xF0, 0x00, 0x1F, + 0x80, 0x3F, 0x81, 0xFC, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x7F, 0x00, 0x03, + 0xF0, 0x01, 0xF8, 0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x7F, 0x0F, 0xE0, 0x00, + 0x7E, 0x00, 0x1F, 0xC3, 0xF8, 0x00, 0x3F, 0x00, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x07, 0xE0, 0x00, 0x1F, 0xFF, 0x80, + 0x01, 0xF8, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0xFC, 0x00, 0x00, 0x1F, 0xC0, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, + 0x07, 0xFE, 0x0F, 0xF8, 0x00, 0x07, 0xFE, 0x03, 0xFC, 0x00, 0x03, 0xFE, + 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x3F, + 0x80, 0x00, 0x3F, 0xE0, 0x3F, 0xC0, 0x00, 0x1F, 0xF0, 0x1F, 0xE0, 0x00, + 0x0F, 0xFC, 0x3F, 0xE0, 0x00, 0x03, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, + 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, + 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x82, 0x00, 0x0F, 0xFE, 0xFF, 0xE1, + 0xF8, 0x0F, 0xFE, 0x3F, 0xF0, 0xFF, 0x0F, 0xFC, 0x1F, 0xFC, 0xFF, 0x87, + 0xFC, 0x07, 0xFF, 0x7F, 0x87, 0xFE, 0x01, 0xFF, 0xFF, 0xC3, 0xFE, 0x00, + 0x7F, 0xFF, 0xE1, 0xFF, 0x00, 0x1F, 0xFF, 0xE0, 0xFF, 0x80, 0x07, 0xFF, + 0xF0, 0x7F, 0xC0, 0x03, 0xFF, 0xF0, 0x3F, 0xE0, 0x00, 0xFF, 0xF8, 0x1F, + 0xF0, 0x00, 0x3F, 0xFC, 0x0F, 0xFC, 0x00, 0x3F, 0xFF, 0x07, 0xFF, 0x00, + 0x3F, 0xFF, 0xE1, 0xFF, 0xC0, 0x7F, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFF, 0xFC, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x3F, 0xC0, 0x3F, 0xFF, + 0xF8, 0x0F, 0xC0, 0x0F, 0xFF, 0xF0, 0x01, 0xC0, 0x00, 0x7F, 0xC0, 0x00, + 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xEF, 0xF7, 0xF3, 0xF9, 0xFC, 0xFE, 0x00, 0x3F, 0x00, 0x7E, 0x00, + 0xFE, 0x00, 0xFC, 0x01, 0xFC, 0x01, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x07, + 0xF0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xE0, 0x1F, 0xE0, 0x1F, 0xE0, 0x1F, + 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x7F, 0xC0, 0x7F, 0x80, 0x7F, + 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, + 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x1F, 0xC0, 0x1F, + 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x07, 0xF0, 0x03, + 0xF8, 0x03, 0xF8, 0x01, 0xF8, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0xFE, 0x00, + 0x7E, 0x00, 0x3F, 0xFC, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x3F, 0x00, 0x3F, + 0x80, 0x3F, 0x80, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, + 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x07, 0xF8, 0x03, 0xF8, 0x03, 0xFC, 0x03, + 0xFC, 0x03, 0xFC, 0x03, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0xFE, 0x01, 0xFE, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFE, 0x01, + 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x03, 0xFC, 0x03, + 0xFC, 0x03, 0xFC, 0x03, 0xFC, 0x03, 0xF8, 0x07, 0xF8, 0x07, 0xF8, 0x07, + 0xF0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x1F, 0xC0, 0x1F, + 0x80, 0x3F, 0x80, 0x3F, 0x00, 0x7F, 0x00, 0x7E, 0x00, 0xFC, 0x00, 0x00, + 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, + 0x01, 0x81, 0xE0, 0x67, 0xC7, 0x87, 0x9F, 0xDE, 0x7E, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x00, 0x3F, 0x00, 0x01, 0xFE, 0x00, 0x0F, + 0xFC, 0x00, 0x7F, 0xF8, 0x03, 0xF3, 0xF0, 0x1F, 0x8F, 0xE0, 0xFE, 0x1F, + 0xC1, 0xF0, 0x3C, 0x01, 0xC0, 0xE0, 0x02, 0x01, 0x00, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, + 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, + 0xC3, 0xE1, 0xF0, 0xF0, 0xF9, 0xF9, 0xFC, 0xFC, 0x38, 0x18, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, + 0x00, 0x0F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7E, 0x00, 0x1F, 0x80, + 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0x07, + 0xF0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03, 0xF0, + 0x00, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xE0, 0x01, 0xF8, 0x00, + 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xFC, 0x00, 0x7F, + 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x00, + 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xFC, 0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, + 0xE0, 0x03, 0xF8, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, + 0xF0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8, + 0x3F, 0xF0, 0xFF, 0xE3, 0xFF, 0x01, 0xFF, 0x1F, 0xF0, 0x0F, 0xF8, 0xFF, + 0x80, 0x3F, 0xE7, 0xFC, 0x01, 0xFF, 0x7F, 0xC0, 0x0F, 0xFB, 0xFE, 0x00, + 0x7F, 0xDF, 0xF0, 0x01, 0xFE, 0xFF, 0x80, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, + 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, + 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xDF, + 0xF0, 0x03, 0xFE, 0xFF, 0x80, 0x1F, 0xF3, 0xFE, 0x00, 0xFF, 0x9F, 0xF0, + 0x07, 0xFC, 0xFF, 0x80, 0x7F, 0xC7, 0xFE, 0x03, 0xFE, 0x1F, 0xF8, 0x7F, + 0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x80, + 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xF8, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0xFF, 0x00, + 0x0F, 0xF0, 0x01, 0xFF, 0x00, 0x3F, 0xF0, 0x07, 0xFF, 0x00, 0xFF, 0xF0, + 0x1F, 0xFF, 0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xFE, 0x1F, + 0xFF, 0x81, 0xFF, 0xE0, 0x1F, 0xF8, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, + 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, + 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, + 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, + 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, + 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x00, + 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, + 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, + 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x3F, 0xF8, 0x3F, 0xF9, 0xFF, 0x80, 0x3F, + 0xF7, 0xFC, 0x00, 0xFF, 0xDF, 0xF0, 0x01, 0xFF, 0x7F, 0xC0, 0x07, 0xFD, + 0xFE, 0x00, 0x1F, 0xF0, 0xF8, 0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x0F, + 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x1F, 0xF8, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x01, 0xFF, 0x80, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, + 0xFF, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x07, 0xFE, + 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, + 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x1F, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, + 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x01, 0xFF, + 0xFF, 0xFE, 0x07, 0xFF, 0xFF, 0xF8, 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0x80, + 0xFF, 0xC7, 0xFC, 0x01, 0xFF, 0x1F, 0xF0, 0x03, 0xFC, 0x7F, 0x80, 0x0F, + 0xF0, 0x0E, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x40, + 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xC1, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFD, 0xFE, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x7F, 0xDF, + 0xF0, 0x03, 0xFF, 0x7F, 0xE0, 0x1F, 0xFC, 0xFF, 0xE0, 0xFF, 0xE3, 0xFF, + 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, + 0xFF, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xFC, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, + 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x01, + 0xFE, 0xFF, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x00, 0xFF, 0x3F, 0xC0, 0x00, + 0xFF, 0x1F, 0xE0, 0x00, 0xFF, 0x0F, 0xF0, 0x00, 0xFF, 0x07, 0xF8, 0x00, + 0x7F, 0x83, 0xFC, 0x00, 0x7F, 0x81, 0xFE, 0x00, 0x7F, 0x80, 0xFF, 0x00, + 0x7F, 0xC0, 0x7F, 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x1F, 0xE0, + 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x1F, + 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, + 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, + 0xFC, 0x0F, 0xFF, 0xFF, 0xF0, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x07, 0xF9, 0xFC, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0xFF, + 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, + 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x9F, 0xFC, 0x1F, + 0xFE, 0x7F, 0xC0, 0x1F, 0xF8, 0x3C, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF0, + 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, + 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0xFF, 0x9F, 0xF8, 0x07, 0xFE, 0x7F, 0xF0, + 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFE, 0x07, 0xFF, 0xFF, + 0xF8, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x01, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xE0, 0x07, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFE, 0x07, 0xFF, + 0xFF, 0xFC, 0x3F, 0xF8, 0x3F, 0xF0, 0xFF, 0xC0, 0x7F, 0xC7, 0xFE, 0x00, + 0xFF, 0x9F, 0xF0, 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0x81, 0xFF, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x1F, 0xC0, 0x0F, 0xF9, 0xFF, 0xE0, 0x3F, 0xEF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xE0, 0xFF, 0xEF, 0xFE, 0x01, + 0xFF, 0xBF, 0xF0, 0x03, 0xFE, 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0x7F, 0x80, 0x07, 0xFD, + 0xFF, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x7F, 0xDF, 0xF8, 0x01, 0xFE, 0x3F, + 0xF0, 0x0F, 0xF8, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, + 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xF8, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, + 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFE, 0x00, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xFF, 0xC0, + 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x8F, 0xFE, 0x0F, 0xFC, 0x7F, 0xC0, + 0x3F, 0xE3, 0xFE, 0x00, 0xFF, 0x9F, 0xE0, 0x07, 0xFC, 0xFF, 0x00, 0x1F, + 0xE7, 0xF8, 0x00, 0xFF, 0x3F, 0xC0, 0x07, 0xF9, 0xFE, 0x00, 0x7F, 0x8F, + 0xF8, 0x03, 0xFC, 0x3F, 0xC0, 0x3F, 0xE1, 0xFF, 0x83, 0xFE, 0x07, 0xFF, + 0xFF, 0xE0, 0x1F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, + 0x00, 0x1F, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC1, + 0xFF, 0x83, 0xFF, 0x1F, 0xF0, 0x0F, 0xFC, 0xFF, 0x00, 0x3F, 0xEF, 0xF8, + 0x00, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xE0, 0x00, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xE0, 0x0F, 0xF9, 0xFF, + 0xC1, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, + 0xFE, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xC0, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x7F, + 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xF8, 0x7F, 0xF0, + 0x7F, 0xF1, 0xFF, 0x00, 0xFF, 0xCF, 0xF8, 0x01, 0xFF, 0x3F, 0xE0, 0x03, + 0xFE, 0xFF, 0x80, 0x0F, 0xFB, 0xFE, 0x00, 0x3F, 0xEF, 0xF0, 0x00, 0xFF, + 0xBF, 0xE0, 0x03, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xF8, 0x01, 0xFF, 0xDF, 0xF0, 0x07, 0xFF, 0x7F, 0xF0, 0x7F, 0xFD, 0xFF, + 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, + 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0x7F, 0xC0, 0x7F, 0xF9, + 0xFF, 0x00, 0x7F, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x1E, 0x00, 0x3F, 0xE7, + 0xFC, 0x01, 0xFF, 0x9F, 0xF0, 0x07, 0xFC, 0x7F, 0xE0, 0x3F, 0xF0, 0xFF, + 0xC3, 0xFF, 0x83, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, + 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, + 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xDF, + 0xF7, 0xFD, 0xFF, 0x7F, 0xC1, 0xE0, 0x78, 0x1E, 0x0F, 0x87, 0xC3, 0xF3, + 0xF8, 0x7C, 0x1E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFE, 0x00, + 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, + 0xFF, 0x80, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, + 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x80, 0x00, 0x00, 0x01, 0xC0, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, + 0xC0, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, + 0xFE, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, + 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xE0, 0x03, + 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, + 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xF8, + 0x7F, 0xF8, 0x1F, 0xFC, 0x7F, 0xF0, 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, + 0x9F, 0xF0, 0x00, 0x3F, 0xDF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, + 0xF8, 0x78, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFC, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, + 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x3F, 0xC0, + 0x0F, 0xE0, 0x00, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xFF, 0x0F, 0xF1, 0xFC, + 0x03, 0xFC, 0x03, 0xFF, 0xF1, 0xFE, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0xFF, + 0x3F, 0xC1, 0xF8, 0x1F, 0xC0, 0x3F, 0xFF, 0xEF, 0xF0, 0x3F, 0x03, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x03, 0xF0, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x1F, 0xC0, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xC3, 0xF0, 0x1F, 0xFC, + 0x1F, 0xFF, 0x00, 0xF8, 0xFE, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0x1F, + 0x80, 0xFF, 0x80, 0x0F, 0xF8, 0x03, 0xF3, 0xF0, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x7E, 0x7E, 0x07, 0xF8, 0x00, 0x3F, 0xE0, 0x0F, 0xDF, 0x80, 0xFF, + 0x00, 0x07, 0xF8, 0x01, 0xFB, 0xF0, 0x3F, 0xE0, 0x00, 0xFF, 0x00, 0x3E, + 0x7E, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x07, 0xCF, 0xC0, 0xFF, 0x00, 0x03, + 0xFC, 0x01, 0xF9, 0xF8, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x3F, 0x3F, 0x03, + 0xF8, 0x00, 0x0F, 0xE0, 0x07, 0xE7, 0xC0, 0xFF, 0x00, 0x03, 0xFC, 0x01, + 0xF8, 0xF8, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x7F, 0x1F, 0x03, 0xFE, 0x00, + 0x1F, 0xF0, 0x0F, 0xC3, 0xF0, 0x7F, 0xC0, 0x03, 0xFE, 0x03, 0xF8, 0x7E, + 0x07, 0xF8, 0x00, 0xFF, 0x80, 0xFE, 0x0F, 0xC0, 0xFF, 0x80, 0x3F, 0xF0, + 0x3F, 0xC1, 0xF8, 0x1F, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x3F, 0x03, 0xFF, + 0xFF, 0xFF, 0xC7, 0xFC, 0x03, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x7E, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, 0xC0, 0x7F, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFC, 0x07, 0xFF, 0xFB, 0xFF, 0xFC, 0x00, 0x1F, 0x80, + 0x7F, 0xFE, 0x7F, 0xFF, 0x00, 0x03, 0xF8, 0x07, 0xFF, 0x07, 0xFF, 0x80, + 0x00, 0x3F, 0x80, 0x1F, 0x80, 0x7F, 0x80, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF8, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0F, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0xFF, 0x80, 0x00, 0x00, 0x00, + 0x0F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0xE0, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x1F, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xE0, + 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0xFE, + 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0xDF, 0xF0, 0x00, + 0x00, 0x07, 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE3, 0xFE, 0x00, 0x00, + 0x03, 0xFF, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xC0, 0x00, 0x00, + 0xFF, 0x83, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x1F, 0xF8, 0x00, 0x00, 0x7F, + 0xC0, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0x00, 0x3F, 0xE0, + 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0x00, 0x7F, 0xC0, 0x00, 0x1F, 0xF8, 0x03, + 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0x07, 0xFC, 0x00, 0x7F, + 0xC0, 0x00, 0x7F, 0xC0, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x80, + 0x00, 0x0F, 0xFC, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, + 0x01, 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x3F, 0xE0, 0x00, 0x00, + 0x3F, 0xE3, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x9F, 0xF8, 0x00, 0x00, 0x0F, + 0xFC, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0x80, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, + 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x7F, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0x80, 0x01, 0xFF, 0xE7, 0xFC, 0x00, 0x03, 0xFF, 0x3F, + 0xE0, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x03, + 0xFE, 0x7F, 0xC0, 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x00, 0xFF, 0x9F, 0xF0, + 0x00, 0x07, 0xF8, 0xFF, 0x80, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0x0F, 0xFC, + 0x3F, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, + 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3F, 0xE0, 0x00, 0x3F, 0xFD, 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xF8, + 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, + 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, + 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x01, + 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, + 0xFF, 0xF8, 0x3F, 0xFC, 0x00, 0x7F, 0xF0, 0x7F, 0xF0, 0x00, 0x7F, 0xF1, + 0xFF, 0x80, 0x00, 0x7F, 0xE3, 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xFC, 0x00, + 0x00, 0xFF, 0xDF, 0xF8, 0x00, 0x00, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0x80, + 0x7F, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x00, + 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x30, 0x0F, 0xF8, 0x00, 0x00, 0x7C, 0x1F, 0xF0, 0x00, 0x00, + 0xFF, 0x3F, 0xF0, 0x00, 0x03, 0xFF, 0x7F, 0xE0, 0x00, 0x07, 0xFE, 0x7F, + 0xE0, 0x00, 0x1F, 0xF8, 0xFF, 0xC0, 0x00, 0x3F, 0xF0, 0xFF, 0xC0, 0x00, + 0xFF, 0xE1, 0xFF, 0xE0, 0x03, 0xFF, 0x81, 0xFF, 0xF0, 0x3F, 0xFF, 0x03, + 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, + 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, + 0x3F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, + 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x80, 0x07, 0xFF, 0xC7, 0xFC, 0x00, 0x0F, + 0xFF, 0x3F, 0xE0, 0x00, 0x3F, 0xF9, 0xFF, 0x00, 0x00, 0xFF, 0xEF, 0xF8, + 0x00, 0x03, 0xFF, 0x7F, 0xC0, 0x00, 0x0F, 0xFB, 0xFE, 0x00, 0x00, 0x7F, + 0xDF, 0xF0, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xFC, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x3F, 0xF7, + 0xFC, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x01, + 0xFF, 0xCF, 0xF8, 0x00, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, + 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFE, + 0x07, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, + 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, + 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC1, 0xFF, 0xC0, 0x00, 0x7F, + 0xF8, 0x7F, 0xE0, 0x00, 0x0F, 0xFE, 0x3F, 0xF0, 0x00, 0x01, 0xFF, 0x8F, + 0xFC, 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xE1, 0xFF, 0x80, + 0x00, 0x03, 0x80, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x1F, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xDF, + 0xF0, 0x00, 0x7F, 0xFF, 0xF7, 0xFC, 0x00, 0x00, 0x07, 0xFD, 0xFF, 0x80, + 0x00, 0x01, 0xFF, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, + 0x1F, 0xF3, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x7F, 0xE0, 0x00, 0x01, 0xFF, + 0x1F, 0xFE, 0x00, 0x01, 0xFF, 0xC3, 0xFF, 0xC0, 0x01, 0xFF, 0xF0, 0xFF, + 0xFE, 0x03, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, + 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, + 0xFC, 0x3E, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x80, 0x3F, 0xE7, 0xFC, + 0x03, 0xFF, 0x3F, 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, + 0xFC, 0x3F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x1F, 0xF0, 0x00, 0xFF, + 0x80, 0x00, 0x1F, 0xFE, 0xFF, 0x80, 0x00, 0x3F, 0xFC, 0xFF, 0x80, 0x00, + 0x7F, 0xF8, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x01, 0xFF, 0xE0, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0xFF, 0x80, + 0x0F, 0xFF, 0x00, 0xFF, 0x80, 0x1F, 0xFE, 0x00, 0xFF, 0x80, 0x3F, 0xFC, + 0x00, 0xFF, 0x80, 0x7F, 0xF8, 0x00, 0xFF, 0x80, 0xFF, 0xF0, 0x00, 0xFF, + 0x81, 0xFF, 0xE0, 0x00, 0xFF, 0x83, 0xFF, 0xC0, 0x00, 0xFF, 0x87, 0xFF, + 0x80, 0x00, 0xFF, 0x8F, 0xFF, 0x00, 0x00, 0xFF, 0x9F, 0xFE, 0x00, 0x00, + 0xFF, 0xBF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, + 0xFF, 0x7F, 0xE0, 0x00, 0xFF, 0xFE, 0x7F, 0xF0, 0x00, 0xFF, 0xFC, 0x3F, + 0xF0, 0x00, 0xFF, 0xF8, 0x3F, 0xF8, 0x00, 0xFF, 0xF0, 0x1F, 0xFC, 0x00, + 0xFF, 0xE0, 0x1F, 0xFC, 0x00, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0xFF, 0x80, + 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x03, 0xFF, + 0x80, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x01, 0xFF, 0xC0, 0xFF, + 0x80, 0x00, 0xFF, 0xE0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, + 0x7F, 0xF0, 0xFF, 0x80, 0x00, 0x7F, 0xF8, 0xFF, 0x80, 0x00, 0x3F, 0xF8, + 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0xFF, 0x80, 0x00, 0x1F, 0xFE, 0xFF, 0x80, + 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x03, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFF, + 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xFF, 0xF8, 0x01, + 0xFE, 0xFF, 0xFF, 0xBF, 0x80, 0x1F, 0xEF, 0xFF, 0xFB, 0xFC, 0x01, 0xFE, + 0xFF, 0xFF, 0xBF, 0xC0, 0x1F, 0xCF, 0xFF, 0xFB, 0xFC, 0x03, 0xFC, 0xFF, + 0xFF, 0x9F, 0xC0, 0x3F, 0xCF, 0xFF, 0xF9, 0xFE, 0x03, 0xFC, 0xFF, 0xFF, + 0x9F, 0xE0, 0x7F, 0x8F, 0xFF, 0xF9, 0xFE, 0x07, 0xF8, 0xFF, 0xFF, 0x8F, + 0xF0, 0x7F, 0x8F, 0xFF, 0xF8, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x8F, 0xF0, + 0xFF, 0x0F, 0xFF, 0xF8, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x87, 0xF8, 0xFF, + 0x0F, 0xFF, 0xF8, 0x7F, 0x8F, 0xF0, 0xFF, 0xFF, 0x87, 0xF9, 0xFE, 0x0F, + 0xFF, 0xF8, 0x7F, 0x9F, 0xE0, 0xFF, 0xFF, 0x83, 0xFD, 0xFE, 0x0F, 0xFF, + 0xF8, 0x3F, 0xDF, 0xE0, 0xFF, 0xFF, 0x83, 0xFF, 0xFC, 0x0F, 0xFF, 0xF8, + 0x3F, 0xFF, 0xC0, 0xFF, 0xFF, 0x81, 0xFF, 0xFC, 0x0F, 0xFF, 0xF8, 0x1F, + 0xFF, 0xC0, 0xFF, 0xFF, 0x81, 0xFF, 0xF8, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, + 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xF8, 0x0F, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, + 0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x0F, 0xFF, 0xF8, 0x0F, 0xFF, 0x00, 0xFF, + 0xFF, 0x80, 0x7F, 0xF0, 0x0F, 0xFF, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xFF, + 0x80, 0x7F, 0xE0, 0x0F, 0xFF, 0xF8, 0x07, 0xFE, 0x00, 0xFF, 0xFF, 0x80, + 0x3F, 0xE0, 0x0F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xF0, 0x01, + 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFE, + 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xEF, 0xFE, 0x03, 0xFF, 0xFC, + 0xFF, 0xC0, 0x7F, 0xFF, 0x9F, 0xFC, 0x0F, 0xFF, 0xF1, 0xFF, 0x81, 0xFF, + 0xFE, 0x1F, 0xF8, 0x3F, 0xFF, 0xC3, 0xFF, 0x87, 0xFF, 0xF8, 0x3F, 0xF0, + 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0xE0, 0x7F, 0xF3, 0xFF, 0xFC, 0x07, + 0xFE, 0x7F, 0xFF, 0x80, 0xFF, 0xEF, 0xFF, 0xF0, 0x0F, 0xFD, 0xFF, 0xFE, + 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, + 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x3F, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFE, 0x00, + 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFE, + 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, + 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xC0, 0x7F, 0xFE, 0x03, 0xFF, 0xE0, + 0x01, 0xFF, 0xE0, 0x7F, 0xF0, 0x00, 0x1F, 0xFE, 0x1F, 0xFC, 0x00, 0x01, + 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x1F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, + 0x9F, 0xF8, 0x00, 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, + 0x00, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFB, 0xFE, 0x00, 0x00, 0x03, + 0xFF, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF8, + 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xC1, 0xFF, + 0xC0, 0x00, 0x7F, 0xF8, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x03, 0xFF, 0xF0, + 0x1F, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xCF, + 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x07, 0xFF, + 0xBF, 0xE0, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xE0, + 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xF3, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, + 0x0F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x7F, 0xFE, + 0x00, 0xFF, 0xF8, 0x00, 0x7F, 0xF8, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xE0, + 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0x03, 0xFF, 0x00, 0x00, 0x1F, 0xFC, 0x3F, + 0xF0, 0x00, 0x00, 0x7F, 0xE1, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x0F, 0xF8, + 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, + 0x00, 0x03, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xC0, 0x00, 0x00, + 0x1F, 0xF3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF0, 0x00, 0x00, 0x07, + 0xFC, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xCF, + 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xF3, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x40, 0x0F, 0xF8, 0x7F, 0xE0, + 0x07, 0xC0, 0xFF, 0xC3, 0xFF, 0x00, 0x3F, 0x87, 0xFE, 0x0F, 0xFC, 0x03, + 0xFE, 0x7F, 0xE0, 0x7F, 0xF0, 0x1F, 0xFF, 0xFF, 0x03, 0xFF, 0xC0, 0x7F, + 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0x01, 0xFF, + 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x7F, 0xF8, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0xC0, 0x00, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, + 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0x80, 0x00, + 0x1F, 0xF8, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xF0, + 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, + 0x00, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0x81, 0xFF, 0xE0, 0x00, + 0xFF, 0x80, 0x7F, 0xF0, 0x00, 0xFF, 0x80, 0x3F, 0xF8, 0x00, 0xFF, 0x80, + 0x1F, 0xFC, 0x00, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0xFF, 0x80, 0x0F, 0xFF, + 0x00, 0xFF, 0x80, 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0x80, 0xFF, + 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x01, 0xFF, 0xC0, 0xFF, 0x80, 0x00, + 0xFF, 0xE0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, 0x7F, 0xF0, + 0xFF, 0x80, 0x00, 0x3F, 0xF8, 0xFF, 0x80, 0x00, 0x3F, 0xF8, 0xFF, 0x80, + 0x00, 0x1F, 0xFC, 0xFF, 0x80, 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x00, 0x0F, + 0xFE, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x01, + 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, 0xFE, 0x03, 0xFF, 0xC1, + 0xFF, 0x80, 0x07, 0xFF, 0x0F, 0xF8, 0x00, 0x1F, 0xF8, 0x7F, 0xC0, 0x00, + 0xFF, 0xC3, 0xFE, 0x00, 0x03, 0xFE, 0x1F, 0xF0, 0x00, 0x1F, 0xF8, 0xFF, + 0x80, 0x00, 0xFF, 0xC7, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x00, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x3F, + 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0xF0, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xDF, 0xF0, 0x00, 0x03, 0xFE, + 0xFF, 0xC0, 0x00, 0x3F, 0xF7, 0xFF, 0x00, 0x03, 0xFF, 0x9F, 0xFC, 0x00, + 0x3F, 0xF8, 0xFF, 0xF8, 0x07, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, + 0xE0, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xF7, 0xFF, 0x00, 0x1F, + 0xFC, 0xFF, 0xF8, 0x0F, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, + 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, + 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xDF, 0xF0, + 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x07, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x0F, 0xFC, 0x00, 0x00, 0xFF, + 0xC3, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x7F, 0xC0, 0x00, 0x0F, 0xF8, 0x1F, + 0xF8, 0x00, 0x07, 0xFE, 0x07, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0xFF, 0x80, + 0x00, 0x7F, 0xC0, 0x3F, 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFC, 0x00, 0x0F, + 0xF8, 0x01, 0xFF, 0x80, 0x03, 0xFE, 0x00, 0x7F, 0xE0, 0x01, 0xFF, 0x80, + 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFF, 0x00, 0x1F, 0xF0, 0x00, 0xFF, + 0xC0, 0x0F, 0xFC, 0x00, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x07, 0xFE, 0x00, + 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x00, 0x3F, 0xE0, 0x1F, 0xF0, + 0x00, 0x0F, 0xFC, 0x07, 0xFC, 0x00, 0x03, 0xFF, 0x03, 0xFF, 0x00, 0x00, + 0x7F, 0xC0, 0xFF, 0x80, 0x00, 0x1F, 0xF8, 0x3F, 0xE0, 0x00, 0x07, 0xFE, + 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x87, 0xFC, 0x00, 0x00, 0x3F, 0xF1, 0xFF, + 0x00, 0x00, 0x07, 0xFC, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x3F, 0xE0, 0x00, + 0x00, 0x7F, 0xEF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, + 0xE0, 0x00, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x1F, + 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xF0, 0x00, 0x3F, 0xEF, 0xF8, 0x00, + 0x1F, 0xFE, 0x00, 0x07, 0xFD, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0xFF, + 0xBF, 0xE0, 0x00, 0x7F, 0xF8, 0x00, 0x3F, 0xF7, 0xFE, 0x00, 0x1F, 0xFF, + 0x80, 0x07, 0xFC, 0x7F, 0xC0, 0x03, 0xFF, 0xF0, 0x00, 0xFF, 0x8F, 0xF8, + 0x00, 0x7F, 0xFE, 0x00, 0x1F, 0xF1, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x03, + 0xFE, 0x3F, 0xE0, 0x03, 0xFF, 0xFC, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0x7F, + 0xFF, 0x80, 0x1F, 0xF0, 0x7F, 0xC0, 0x0F, 0xFF, 0xF0, 0x03, 0xFE, 0x0F, + 0xF8, 0x03, 0xFF, 0xFE, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, + 0x1F, 0xF0, 0x3F, 0xE0, 0x0F, 0xF7, 0xFC, 0x03, 0xFE, 0x03, 0xFE, 0x01, + 0xFE, 0x7F, 0x80, 0x7F, 0xC0, 0x7F, 0xC0, 0x7F, 0xCF, 0xF0, 0x0F, 0xF8, + 0x0F, 0xF8, 0x0F, 0xF1, 0xFF, 0x01, 0xFE, 0x01, 0xFF, 0x01, 0xFE, 0x3F, + 0xE0, 0x7F, 0xC0, 0x1F, 0xF0, 0x3F, 0xC3, 0xFC, 0x0F, 0xF8, 0x03, 0xFE, + 0x0F, 0xF8, 0x7F, 0x81, 0xFF, 0x00, 0x7F, 0xC1, 0xFE, 0x0F, 0xF8, 0x3F, + 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, 0xFF, 0x0F, 0xF8, 0x00, 0xFF, 0x07, 0xF8, + 0x1F, 0xE1, 0xFF, 0x00, 0x1F, 0xF1, 0xFF, 0x03, 0xFC, 0x3F, 0xE0, 0x03, + 0xFE, 0x3F, 0xC0, 0x7F, 0xC7, 0xF8, 0x00, 0x7F, 0xC7, 0xF8, 0x07, 0xF8, + 0xFF, 0x00, 0x07, 0xF9, 0xFF, 0x00, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, 0xBF, + 0xE0, 0x1F, 0xE7, 0xFC, 0x00, 0x1F, 0xF7, 0xF8, 0x03, 0xFE, 0xFF, 0x00, + 0x03, 0xFE, 0xFF, 0x00, 0x3F, 0xDF, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x07, + 0xFB, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, 0xFF, 0xFC, + 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x00, + 0x07, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x00, + 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x01, 0xFF, + 0xF0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, + 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x7F, 0xF0, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x01, + 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF8, 0x00, 0x3F, 0xF0, + 0x00, 0x03, 0xFF, 0x0F, 0xFE, 0x00, 0x01, 0xFF, 0xC1, 0xFF, 0xC0, 0x00, + 0xFF, 0xE0, 0x3F, 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFE, 0x00, 0x1F, 0xFC, + 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x3F, 0xF0, 0x03, 0xFF, 0x00, 0x0F, + 0xFE, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x3F, 0xF0, + 0x3F, 0xF0, 0x00, 0x0F, 0xFE, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xCF, 0xFE, + 0x00, 0x00, 0x3F, 0xF3, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF, + 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x01, 0xFF, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, + 0x03, 0xFF, 0x7F, 0xF0, 0x00, 0x01, 0xFF, 0xCF, 0xFE, 0x00, 0x00, 0xFF, + 0xE1, 0xFF, 0xC0, 0x00, 0x3F, 0xF0, 0x7F, 0xF0, 0x00, 0x1F, 0xFC, 0x0F, + 0xFE, 0x00, 0x0F, 0xFE, 0x01, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x7F, 0xF0, + 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0xFF, 0xE0, 0x01, 0xFF, 0xC0, 0x3F, + 0xF8, 0x00, 0x7F, 0xF0, 0x1F, 0xFC, 0x00, 0x0F, 0xFE, 0x0F, 0xFE, 0x00, + 0x01, 0xFF, 0xC3, 0xFF, 0x80, 0x00, 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x0F, + 0xFE, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x01, 0xFF, + 0xDF, 0xF8, 0x00, 0x00, 0x7F, 0xE7, 0xFF, 0x00, 0x00, 0x3F, 0xF8, 0xFF, + 0xE0, 0x00, 0x0F, 0xFC, 0x1F, 0xF8, 0x00, 0x07, 0xFE, 0x07, 0xFF, 0x00, + 0x03, 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x7F, + 0xE0, 0x07, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, + 0x1F, 0xF8, 0x07, 0xFE, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0x80, 0x00, 0xFF, + 0xC0, 0xFF, 0xC0, 0x00, 0x3F, 0xF8, 0x3F, 0xF0, 0x00, 0x07, 0xFE, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xC7, 0xFC, 0x00, 0x00, 0x3F, 0xF3, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, + 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x80, + 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, + 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, + 0xFC, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, + 0x0F, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, + 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xE0, + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x3F, 0x80, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0xC0, + 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xF8, 0x00, + 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, + 0xC0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x01, 0xFC, + 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFE, 0x00, 0x3F, 0x80, + 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x03, 0xF0, 0x00, + 0xFC, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, + 0xC0, 0x07, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x03, 0xF8, + 0x00, 0x7E, 0x00, 0x1F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0x03, 0xFC, + 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, + 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, + 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, + 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, + 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, + 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, + 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x00, 0x01, + 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0xFF, 0x7F, 0x80, 0x07, 0xFB, + 0xFC, 0x00, 0x7F, 0x8F, 0xF0, 0x03, 0xFC, 0x7F, 0x80, 0x3F, 0xC1, 0xFE, + 0x01, 0xFE, 0x0F, 0xF0, 0x1F, 0xE0, 0x7F, 0xC0, 0xFF, 0x01, 0xFE, 0x0F, + 0xF8, 0x0F, 0xF8, 0x7F, 0x80, 0x3F, 0xC7, 0xFC, 0x01, 0xFF, 0x3F, 0xC0, + 0x0F, 0xFB, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, + 0x07, 0xF0, 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x3F, 0xF8, + 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFC, + 0x1F, 0xF8, 0x1F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0xFF, 0x80, 0x1F, 0xF0, + 0x1E, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFC, 0x07, + 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, + 0xFF, 0x3F, 0xC7, 0xFF, 0xC0, 0x7F, 0x8F, 0xFC, 0x00, 0xFF, 0x3F, 0xE0, + 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0xFC, 0xFF, 0x80, 0x0F, 0xF9, 0xFF, 0x00, + 0x3F, 0xF3, 0xFF, 0x00, 0xFF, 0xE3, 0xFF, 0x07, 0xFF, 0xC7, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xF9, + 0xFE, 0x1F, 0xFF, 0xE3, 0xFC, 0x0F, 0xFF, 0x07, 0xFC, 0x07, 0xF8, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x81, 0xFC, + 0x00, 0xFF, 0x8F, 0xFF, 0x00, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0xBF, 0xFF, + 0xE0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFC, 0xFF, 0xF8, 0x3F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xE0, 0x07, + 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, + 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFC, 0xFF, 0xFC, 0x1F, + 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x7F, 0xFF, + 0xF0, 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x1F, 0xFF, 0xC0, 0xFF, 0x07, 0xFF, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, 0x7F, + 0xE0, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x7F, 0xFF, 0xE0, + 0x01, 0xF0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x3C, 0x3F, 0xE0, 0x00, 0xFF, 0x7F, + 0xC0, 0x07, 0xFD, 0xFF, 0x00, 0x1F, 0xF7, 0xFE, 0x00, 0xFF, 0x8F, 0xFE, + 0x0F, 0xFE, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, + 0xFE, 0x01, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xF8, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, + 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, + 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, + 0x01, 0xFC, 0x0F, 0xF0, 0x1F, 0xFE, 0x1F, 0xE0, 0x7F, 0xFF, 0x3F, 0xC3, + 0xFF, 0xFF, 0x7F, 0x8F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x7F, + 0xFF, 0xFF, 0xFD, 0xFF, 0xE0, 0xFF, 0xFB, 0xFF, 0x00, 0x7F, 0xF7, 0xFC, + 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xC0, + 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, + 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x3F, + 0xF7, 0xFC, 0x00, 0x7F, 0xEF, 0xFC, 0x01, 0xFF, 0xCF, 0xFE, 0x0F, 0xFF, + 0x9F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFB, 0xFC, + 0x1F, 0xFF, 0xE7, 0xF8, 0x1F, 0xFF, 0x8F, 0xF0, 0x1F, 0xFE, 0x1F, 0xE0, + 0x07, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x01, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x01, + 0xFF, 0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0xFC, 0x1F, 0xFC, 0x1F, 0xF8, 0x3F, + 0xE0, 0x1F, 0xF8, 0xFF, 0xC0, 0x1F, 0xF1, 0xFF, 0x00, 0x1F, 0xE3, 0xFE, + 0x00, 0x3F, 0xEF, 0xF8, 0x00, 0x3F, 0xDF, 0xF0, 0x00, 0x7F, 0xBF, 0xE0, + 0x00, 0xFF, 0x7F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x03, + 0xE0, 0x7F, 0xC0, 0x07, 0xFC, 0xFF, 0xC0, 0x1F, 0xF8, 0xFF, 0xC0, 0x3F, + 0xE1, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFC, + 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x03, + 0xFF, 0xF0, 0x1F, 0xFF, 0xC0, 0xFF, 0xFE, 0x07, 0xFF, 0xF8, 0x1F, 0xFF, + 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0x00, 0x07, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, 0x03, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0x3F, 0xFF, 0xFC, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, + 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, + 0x00, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, + 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, + 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, + 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x03, 0xFF, 0xC3, 0xFC, 0x0F, + 0xFF, 0xC7, 0xF8, 0x7F, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0xDF, 0xE3, 0xFF, + 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0x1F, 0xFF, 0x7F, 0xE0, + 0x0F, 0xFE, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, + 0x7F, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, + 0x7F, 0xC0, 0x07, 0xFE, 0xFF, 0xC0, 0x1F, 0xFD, 0xFF, 0xE0, 0xFF, 0xF9, + 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xBF, 0xC3, + 0xFF, 0xFE, 0x7F, 0x83, 0xFF, 0xF8, 0xFF, 0x01, 0xFF, 0xE1, 0xFE, 0x00, + 0xFE, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xC0, + 0x00, 0x1F, 0xEF, 0xFC, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0xFF, 0xBF, 0xF0, + 0x03, 0xFF, 0x7F, 0xF8, 0x1F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFE, 0x00, 0xFF, 0x80, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0x80, 0xFF, 0x87, 0xFF, 0x83, 0xFE, 0x3F, + 0xFF, 0x8F, 0xF9, 0xFF, 0xFF, 0x3F, 0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFB, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, + 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x03, + 0xFF, 0x7F, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0xFF, + 0xF8, 0xFF, 0xF0, 0x3F, 0xC0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0xFF, 0x80, 0x1F, 0xFB, 0xFE, 0x00, 0xFF, 0xCF, 0xF8, 0x07, + 0xFE, 0x3F, 0xE0, 0x3F, 0xF0, 0xFF, 0x81, 0xFF, 0x83, 0xFE, 0x0F, 0xFE, + 0x0F, 0xF8, 0x7F, 0xF0, 0x3F, 0xE3, 0xFF, 0x80, 0xFF, 0x8F, 0xFC, 0x03, + 0xFE, 0x7F, 0xE0, 0x0F, 0xFB, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0xFF, + 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, + 0xFC, 0x00, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x3F, 0xFC, 0xFF, 0x80, 0xFF, 0xE3, 0xFE, 0x03, 0xFF, 0x07, 0xFC, + 0x0F, 0xF8, 0x1F, 0xF0, 0x3F, 0xE0, 0x3F, 0xE0, 0xFF, 0x80, 0xFF, 0xC3, + 0xFE, 0x01, 0xFF, 0x0F, 0xF8, 0x03, 0xFE, 0x3F, 0xE0, 0x0F, 0xF8, 0xFF, + 0x80, 0x1F, 0xF3, 0xFE, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0xBF, 0xE0, + 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0xFF, 0x0F, 0xFF, + 0x00, 0xFF, 0xE0, 0xFF, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0x3F, 0xFF, + 0xC7, 0xFF, 0xFC, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF8, 0x7F, + 0xFF, 0x07, 0xFE, 0xFF, 0xE0, 0x1F, 0xFE, 0x03, 0xFF, 0xFF, 0xC0, 0x1F, + 0xFC, 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x1F, + 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x03, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, + 0xFF, 0xFE, 0x3F, 0xC7, 0xFF, 0xFC, 0xFF, 0x3F, 0xFF, 0xFB, 0xFD, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x07, 0xFF, 0xFF, 0xF0, 0x0F, + 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF0, 0x01, 0xFF, + 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xF0, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xC0, + 0x7F, 0xFF, 0xFF, 0xF0, 0x7F, 0xF8, 0x3F, 0xFC, 0x3F, 0xF0, 0x07, 0xFE, + 0x3F, 0xF0, 0x01, 0xFF, 0x9F, 0xF0, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0x3F, + 0xEF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, + 0x7F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x03, 0xFE, 0x7F, 0xC0, 0x01, 0xFF, 0x3F, 0xF0, 0x01, 0xFF, 0x9F, 0xFC, + 0x01, 0xFF, 0x87, 0xFF, 0x83, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0xFF, 0x07, 0xFF, 0x00, 0xFF, 0x1F, 0xFF, 0xC0, + 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x7F, 0xFF, 0xF0, 0xFF, 0x7F, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, + 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, + 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFE, + 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xBF, 0xFF, 0xE0, 0xFF, 0x9F, 0xFF, 0xC0, + 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x81, 0xFC, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0xFF, 0xE0, 0xFF, 0x03, 0xFF, 0xF8, 0xFF, 0x07, 0xFF, 0xFC, 0xFF, + 0x0F, 0xFF, 0xFE, 0xFF, 0x1F, 0xFF, 0xFE, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, + 0x3F, 0xFC, 0x3F, 0xFF, 0x7F, 0xF0, 0x0F, 0xFF, 0x7F, 0xE0, 0x07, 0xFF, + 0x7F, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0x7F, 0xC0, 0x07, 0xFF, + 0x7F, 0xE0, 0x07, 0xFF, 0x7F, 0xF0, 0x0F, 0xFF, 0x3F, 0xF8, 0x3F, 0xFF, + 0x3F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0xFD, 0xFF, 0x03, 0xFF, 0xF9, 0xFF, 0x01, 0xFF, 0xE1, 0xFF, + 0x00, 0x3F, 0x81, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x07, 0xE7, 0xF8, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFE, 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xE7, 0xFF, 0x83, 0x3F, 0xF8, 0x01, 0xFF, 0x80, 0x0F, + 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, + 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, + 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x3F, + 0xF0, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, + 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, + 0xFE, 0x1F, 0xF8, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x7F, 0x80, 0x0F, + 0xF8, 0xFF, 0x00, 0x0F, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, + 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xC0, + 0x00, 0x01, 0xFF, 0x83, 0xC0, 0x01, 0xFF, 0x7F, 0xC0, 0x03, 0xFE, 0xFF, + 0x80, 0x07, 0xFD, 0xFF, 0x80, 0x0F, 0xF9, 0xFF, 0xC0, 0x7F, 0xE3, 0xFF, + 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, + 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, + 0xE0, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x03, 0xE0, 0x00, 0xFC, 0x00, + 0x7F, 0x80, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, 0xF8, 0x01, + 0xFF, 0x00, 0x3F, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xE0, 0x07, + 0xFC, 0x00, 0xFF, 0x80, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, + 0xF8, 0x01, 0xFF, 0x00, 0x3F, 0xE0, 0x07, 0xFC, 0x00, 0xFF, 0x80, 0x1F, + 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, 0xF8, 0x01, 0xFF, 0x00, 0x3F, + 0xE0, 0x07, 0xFC, 0x00, 0xFF, 0x80, 0x1F, 0xF0, 0x83, 0xFF, 0xF8, 0x7F, + 0xFF, 0x07, 0xFF, 0xE0, 0xFF, 0xFC, 0x0F, 0xFF, 0x80, 0xFF, 0xF0, 0x07, + 0xF8, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0x7F, 0xC0, 0x0F, 0xFD, 0xFF, + 0x80, 0x7F, 0xF7, 0xFF, 0x07, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0x3F, 0xC3, 0xFF, 0xF8, + 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x03, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x0F, 0xF8, 0xFF, 0x80, + 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x87, 0xF8, 0x00, 0x7F, 0xC1, 0xFF, + 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, 0x0F, 0xF8, 0x03, 0xFE, 0x03, + 0xFE, 0x00, 0xFF, 0x80, 0x7F, 0x80, 0x7F, 0xC0, 0x1F, 0xF0, 0x1F, 0xF0, + 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0xFF, + 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, 0x1F, 0xF0, 0x00, 0x7F, 0xC7, + 0xF8, 0x00, 0x0F, 0xF1, 0xFE, 0x00, 0x03, 0xFC, 0xFF, 0x80, 0x00, 0x7F, + 0xBF, 0xC0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, + 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0xFF, + 0xBF, 0xC0, 0x07, 0xFC, 0x00, 0x7F, 0xDF, 0xE0, 0x03, 0xFE, 0x00, 0x3F, + 0xCF, 0xF8, 0x03, 0xFF, 0x80, 0x3F, 0xE3, 0xFC, 0x01, 0xFF, 0xC0, 0x1F, + 0xF1, 0xFE, 0x00, 0xFF, 0xE0, 0x0F, 0xF0, 0xFF, 0x80, 0x7F, 0xF0, 0x07, + 0xF8, 0x3F, 0xC0, 0x7F, 0xFC, 0x07, 0xFC, 0x1F, 0xE0, 0x3F, 0xFE, 0x03, + 0xFC, 0x0F, 0xF0, 0x1F, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x0F, 0xFF, 0x81, + 0xFF, 0x01, 0xFE, 0x0F, 0xFF, 0xE0, 0xFF, 0x00, 0xFF, 0x07, 0xF7, 0xF0, + 0x7F, 0x80, 0x3F, 0x83, 0xFB, 0xF8, 0x3F, 0xC0, 0x1F, 0xE1, 0xFD, 0xFC, + 0x3F, 0xC0, 0x0F, 0xF1, 0xFE, 0x7F, 0x1F, 0xE0, 0x07, 0xF8, 0xFE, 0x3F, + 0x8F, 0xF0, 0x01, 0xFE, 0x7F, 0x1F, 0xCF, 0xF0, 0x00, 0xFF, 0x3F, 0x8F, + 0xE7, 0xF8, 0x00, 0x7F, 0xBF, 0xC3, 0xFB, 0xFC, 0x00, 0x1F, 0xDF, 0xC1, + 0xFD, 0xFC, 0x00, 0x0F, 0xFF, 0xE0, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xF0, + 0x7F, 0xFF, 0x00, 0x01, 0xFF, 0xF8, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xF8, + 0x0F, 0xFF, 0x80, 0x00, 0x7F, 0xFC, 0x07, 0xFF, 0xC0, 0x00, 0x1F, 0xFE, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, + 0x00, 0x7F, 0xF0, 0x00, 0x01, 0xFF, 0x80, 0x3F, 0xF8, 0x00, 0x00, 0xFF, + 0xC0, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x00, 0x3F, + 0xE0, 0x03, 0xFE, 0x00, 0x00, 0x7F, 0xF0, 0x01, 0xFF, 0x8F, 0xFC, 0x00, + 0xFF, 0xC1, 0xFF, 0x80, 0x3F, 0xF0, 0x7F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, + 0x0F, 0xFC, 0x01, 0xFF, 0x83, 0xFF, 0x00, 0x7F, 0xF1, 0xFF, 0x80, 0x0F, + 0xFC, 0xFF, 0xC0, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x3F, 0xFF, 0xF8, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xF0, + 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x03, 0xFF, + 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x07, 0xFE, 0xFF, 0xC0, 0x03, + 0xFF, 0x3F, 0xF8, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0x7F, 0xE0, 0xFF, 0xC0, + 0x3F, 0xF0, 0x3F, 0xF8, 0x1F, 0xF8, 0x07, 0xFE, 0x07, 0xFE, 0x00, 0xFF, + 0xC3, 0xFF, 0x00, 0x3F, 0xF9, 0xFF, 0x80, 0x07, 0xFE, 0x7F, 0xE0, 0x00, + 0xFF, 0xC0, 0x7F, 0xC0, 0x00, 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xE7, 0xFC, + 0x00, 0x0F, 0xF8, 0xFF, 0x80, 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, + 0x0F, 0xF0, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, + 0xC0, 0x1F, 0xE0, 0x1F, 0xF0, 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x01, + 0xFE, 0x00, 0x3F, 0xC0, 0xFF, 0x80, 0x0F, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, + 0x0F, 0xF0, 0x00, 0x7F, 0x87, 0xFC, 0x00, 0x1F, 0xF1, 0xFE, 0x00, 0x03, + 0xFC, 0x7F, 0x80, 0x00, 0xFF, 0x3F, 0xE0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, + 0x07, 0xFB, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, + 0x01, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xE7, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x7F, 0xF0, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x7F, + 0xF0, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x03, 0xFF, 0x80, + 0x00, 0x3F, 0xF8, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x03, + 0xF8, 0x00, 0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0xFF, 0xF0, 0x0F, 0xFF, 0x80, + 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0x00, 0x0F, 0xF0, + 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0xFF, 0x00, + 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0xFF, + 0x80, 0x0F, 0xF8, 0x00, 0xFF, 0xC0, 0x3F, 0xFE, 0x01, 0xFF, 0xE0, 0x0F, + 0xFE, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0xFF, 0xF0, + 0x07, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0x7F, 0xC0, 0x01, + 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, + 0x00, 0xFF, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xC0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, + 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x1F, + 0xFF, 0x00, 0x7F, 0xF8, 0x01, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x07, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x07, 0xFE, 0x00, 0x3F, 0xFC, 0x01, + 0xFF, 0xF0, 0x0F, 0xFF, 0x80, 0x7F, 0xFE, 0x03, 0xFF, 0xF0, 0x1F, 0xFF, + 0x80, 0x07, 0xFC, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0xFF, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x00, 0xFF, 0x80, 0x07, 0xFF, + 0x00, 0x1F, 0xFE, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x07, 0xFF, 0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xC0, 0x3F, 0xF8, + 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xF8, 0x00, 0x3F, + 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x0F, 0xFF, 0xC0, 0x7F, + 0xFE, 0x03, 0xFF, 0xF0, 0x1F, 0xFF, 0x00, 0xFF, 0xF8, 0x07, 0xFF, 0x80, + 0x3F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x8F, 0xFF, + 0x80, 0x00, 0xCF, 0xFF, 0xF8, 0x01, 0xEF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0x70, 0x00, 0xFF, 0xFF, 0x30, + 0x00, 0x1F, 0xFE, 0x10, 0x00, 0x01, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xE1, 0xF0, + 0xF8, 0x7C, 0x3F, 0x1F, 0x8F, 0xC7, 0xE7, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, + 0x3F, 0x9F, 0xCF, 0xF7, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xFF, 0xFC, + 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8, + 0x1F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x8F, 0xFF, 0x9F, + 0xF8, 0x3F, 0xFE, 0x7F, 0xC0, 0xFF, 0xFB, 0xFF, 0x07, 0x9F, 0xFF, 0xF8, + 0x1E, 0x7C, 0x3F, 0xE0, 0x78, 0x00, 0xFF, 0x83, 0xE0, 0x03, 0xFE, 0x0F, + 0x00, 0x0F, 0xF0, 0x3C, 0x00, 0x3F, 0xC1, 0xF0, 0x00, 0xFF, 0x07, 0x80, + 0x03, 0xFC, 0x1E, 0x00, 0x0F, 0xF8, 0x78, 0x00, 0x3F, 0xE3, 0xC0, 0x00, + 0xFF, 0x8F, 0x00, 0x03, 0xFE, 0x3C, 0x0F, 0x0F, 0xF9, 0xF0, 0x3F, 0xDF, + 0xF7, 0x81, 0xFF, 0x7F, 0xFE, 0x07, 0xFD, 0xFF, 0xF8, 0x3F, 0xE3, 0xFF, + 0xC3, 0xFF, 0x8F, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0x80, 0x7F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, + 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x01, 0xE0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xF8, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFC, 0x3F, 0xF8, + 0x07, 0xFC, 0x03, 0xFF, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0xFF, 0x80, 0x1F, + 0xF0, 0x3F, 0xC0, 0x03, 0xFC, 0x0F, 0xF0, 0x00, 0xE0, 0x03, 0xFC, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x0F, + 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFE, 0x00, + 0x3F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x07, 0xFB, 0xF0, 0x00, 0x83, 0xFF, 0xFF, 0x00, 0x63, + 0xFF, 0xFF, 0xF0, 0x7C, 0x7F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0xFF, + 0xFF, 0xC7, 0x00, 0x0F, 0xFF, 0xE1, 0x00, 0x00, 0x3F, 0xC0, 0x04, 0x00, + 0x00, 0x10, 0x0E, 0x00, 0x00, 0x38, 0x1F, 0x00, 0x00, 0x78, 0x3F, 0x07, + 0xF0, 0xFC, 0x3F, 0x9F, 0xFC, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, + 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x1F, 0xF0, + 0x07, 0xF8, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xC0, + 0x01, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xE0, + 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xF0, 0x07, 0xF8, 0x0F, 0xFC, + 0x1F, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, + 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0x3F, 0x9F, 0xFC, 0xFE, 0x1F, 0x87, 0xF0, 0xFC, 0x0F, 0x00, + 0x00, 0x78, 0x0E, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, 0x10, 0xFF, 0xC0, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x0F, 0xF9, 0xFF, 0x80, 0x03, 0xFF, 0x1F, + 0xF0, 0x00, 0x7F, 0xC3, 0xFF, 0x00, 0x1F, 0xF8, 0x3F, 0xE0, 0x03, 0xFE, + 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x7F, 0xC0, 0x1F, 0xF0, 0x0F, 0xF8, 0x07, + 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x1F, 0xF0, 0x3F, 0xF0, 0x01, 0xFF, + 0x07, 0xFC, 0x00, 0x3F, 0xE1, 0xFF, 0x80, 0x07, 0xFE, 0x3F, 0xE0, 0x00, + 0x7F, 0xCF, 0xFC, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0xFF, 0xBF, 0xE0, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, + 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, + 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xC3, + 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0x7F, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xE0, 0x00, 0x01, + 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0xFF, + 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x0F, 0xFC, + 0x3F, 0xF0, 0x3F, 0xE0, 0x1F, 0xF0, 0x7F, 0xC0, 0x3F, 0xE0, 0xFF, 0x80, + 0x3F, 0xC0, 0xFF, 0x80, 0x78, 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xE0, + 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0, + 0x07, 0xFF, 0xFF, 0xF0, 0x0F, 0xF3, 0xFF, 0xF8, 0x1F, 0xC1, 0xFF, 0xF8, + 0x7F, 0x81, 0xFF, 0xF8, 0xFF, 0x00, 0xFF, 0xF9, 0xFE, 0x00, 0xFF, 0xF3, + 0xFC, 0x00, 0xFF, 0xF7, 0xF8, 0x00, 0x7F, 0xEF, 0xF8, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0x7F, 0xBF, 0xFC, 0x00, 0xFF, 0x7F, + 0xFC, 0x01, 0xFE, 0x7F, 0xFE, 0x03, 0xFC, 0x7F, 0xFE, 0x07, 0xF0, 0x7F, + 0xFF, 0x1F, 0xE0, 0x7F, 0xFF, 0x7F, 0x80, 0x3F, 0xFF, 0xFF, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, + 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, + 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x01, 0xE0, 0x07, + 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x7F, 0xC0, 0x1F, 0xF0, 0xFF, 0xC0, 0x3F, + 0xE1, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFE, + 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0xFF, 0x07, 0xFF, 0xF8, + 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0x83, 0xFF, + 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, + 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x01, 0xFE, + 0x00, 0x00, 0x3F, 0xC0, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x1F, 0xC0, + 0x00, 0x00, 0x1F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x1F, 0x80, 0xFC, 0x00, + 0x7F, 0x00, 0x1F, 0x83, 0xF0, 0x07, 0xFF, 0xC0, 0x3F, 0x07, 0xC0, 0x1F, + 0xFF, 0xC0, 0x3F, 0x0F, 0x80, 0x7F, 0xFF, 0xC0, 0x3E, 0x3E, 0x01, 0xFC, + 0x1F, 0xC0, 0x7C, 0x7C, 0x07, 0xE0, 0x1F, 0x80, 0x7D, 0xF0, 0x0F, 0xC0, + 0x1F, 0x80, 0xFB, 0xE0, 0x3F, 0x00, 0x18, 0x01, 0xF7, 0xC0, 0x7E, 0x00, + 0x00, 0x01, 0xEF, 0x80, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x01, 0xF0, 0x00, + 0x00, 0x07, 0xFC, 0x03, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x07, 0xC0, 0x00, + 0x00, 0x1F, 0xF0, 0x0F, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x1F, 0x00, 0x00, + 0x00, 0x7F, 0xE0, 0x3E, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x7E, 0x00, 0x00, + 0x01, 0xFF, 0x80, 0xFC, 0x00, 0x70, 0x07, 0xDF, 0x00, 0xFC, 0x01, 0xF8, + 0x0F, 0x9F, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x3E, 0x01, 0xFC, 0x1F, 0xC0, + 0x7C, 0x3E, 0x01, 0xFF, 0xFF, 0x00, 0xF8, 0x7C, 0x01, 0xFF, 0xFC, 0x03, + 0xF0, 0xFC, 0x01, 0xFF, 0xF0, 0x07, 0xC0, 0xFC, 0x00, 0x7F, 0x00, 0x1F, + 0x80, 0xFC, 0x00, 0x00, 0x00, 0x7E, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, + 0x01, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, + 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, + 0x01, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, + 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x7F, 0xFE, 0x07, + 0xFF, 0xF8, 0x7F, 0xFF, 0xC3, 0xFF, 0xFF, 0x3F, 0x83, 0xF9, 0xF8, 0x1F, + 0xC1, 0xC0, 0x7E, 0x00, 0x0F, 0xF0, 0x07, 0xFF, 0x83, 0xFF, 0xFC, 0x7F, + 0xFF, 0xE7, 0xFF, 0xBF, 0x3F, 0xC1, 0xFB, 0xF8, 0x1F, 0xDF, 0xC0, 0xFE, + 0xFE, 0x07, 0xF7, 0xF8, 0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xFF, 0xE7, 0xFF, + 0xFF, 0x0F, 0xFD, 0xF8, 0x3F, 0x87, 0xE0, 0x00, 0x7F, 0x07, 0xF0, 0x03, + 0xF8, 0x3F, 0x80, 0x3F, 0x83, 0xF8, 0x03, 0xFC, 0x3F, 0xC0, 0x1F, 0xC1, + 0xFC, 0x01, 0xFC, 0x1F, 0xC0, 0x1F, 0xE1, 0xFE, 0x00, 0xFE, 0x0F, 0xE0, + 0x0F, 0xF0, 0xFF, 0x00, 0xFF, 0x0F, 0xF0, 0x07, 0xF8, 0x7F, 0x80, 0x7F, + 0x87, 0xF8, 0x07, 0xFC, 0x7F, 0xC0, 0x3F, 0xC3, 0xFC, 0x03, 0xFE, 0x3F, + 0xE0, 0x0F, 0xF0, 0xFF, 0x00, 0x7F, 0xC7, 0xFC, 0x01, 0xFE, 0x1F, 0xE0, + 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0xC3, 0xFC, 0x00, 0xFF, 0x0F, 0xF0, 0x03, + 0xF8, 0x3F, 0x80, 0x1F, 0xE1, 0xFE, 0x00, 0x7F, 0x07, 0xF8, 0x01, 0xFC, + 0x1F, 0xC0, 0x0F, 0xF0, 0xFF, 0x00, 0x3F, 0x83, 0xF8, 0x00, 0xFE, 0x0F, + 0xE0, 0x07, 0xF0, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, + 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x00, + 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, + 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0x01, 0xFF, 0xC0, 0x00, + 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x07, + 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x3F, + 0x00, 0x00, 0x00, 0x1F, 0x80, 0xFC, 0x3F, 0xFF, 0x80, 0x1F, 0x83, 0xF0, + 0x7F, 0xFF, 0xC0, 0x1F, 0x07, 0xC0, 0xFF, 0xFF, 0xC0, 0x3F, 0x0F, 0x81, + 0xFF, 0xFF, 0xC0, 0x3E, 0x3E, 0x03, 0xE0, 0x3F, 0x80, 0x7C, 0x7C, 0x07, + 0xC0, 0x1F, 0x80, 0x7D, 0xF0, 0x0F, 0x80, 0x3F, 0x00, 0xFB, 0xE0, 0x1F, + 0x00, 0x3E, 0x00, 0xF7, 0xC0, 0x3E, 0x00, 0xFC, 0x01, 0xEF, 0x80, 0x7C, + 0x01, 0xF8, 0x03, 0xFF, 0x00, 0xF8, 0x07, 0xE0, 0x07, 0xFC, 0x01, 0xFF, + 0xFF, 0x80, 0x0F, 0xF8, 0x03, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x07, 0xFF, + 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x1F, 0x0F, + 0xC0, 0x00, 0xFF, 0xC0, 0x3E, 0x0F, 0xC0, 0x01, 0xFF, 0x80, 0x7C, 0x0F, + 0xC0, 0x03, 0xDF, 0x00, 0xF8, 0x0F, 0xC0, 0x0F, 0x9F, 0x01, 0xF0, 0x1F, + 0x80, 0x1F, 0x3E, 0x03, 0xE0, 0x1F, 0x80, 0x7C, 0x3E, 0x07, 0xC0, 0x3F, + 0x00, 0xF8, 0x7C, 0x0F, 0x80, 0x3F, 0x03, 0xF0, 0xFC, 0x1F, 0x00, 0x7F, + 0x07, 0xC0, 0xFC, 0x3E, 0x00, 0x7E, 0x1F, 0x80, 0xFC, 0x00, 0x00, 0x00, + 0x7E, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x01, 0xFC, 0x00, 0x00, 0x0F, + 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x01, 0xFF, 0x00, 0x01, 0xFF, + 0x00, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0xFF, 0xFC, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xF8, 0x01, + 0xFF, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0xC7, 0xFF, 0xFC, 0xFC, 0x1F, 0xBF, + 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, + 0x01, 0xFF, 0xC0, 0x7E, 0xFC, 0x1F, 0x9F, 0xFF, 0xF1, 0xFF, 0xFC, 0x1F, + 0xFF, 0x01, 0xFF, 0xC0, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x00, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xF8, 0x03, 0xFF, 0xC3, 0xFF, + 0xF8, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF, 0x83, 0xF7, 0xE0, 0xFF, 0xF0, 0x1F, + 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0xFF, 0x00, + 0x7F, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xE0, 0x07, 0xFF, + 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xF8, + 0x01, 0xFF, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFC, 0x3F, + 0x1F, 0x03, 0xF0, 0xE0, 0xFC, 0x00, 0x3F, 0x80, 0x3F, 0xE0, 0x07, 0xF8, + 0x00, 0xFF, 0x80, 0x1F, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF3, 0xE0, 0x3F, + 0xFC, 0x0F, 0xEF, 0xC3, 0xFD, 0xFF, 0xFF, 0x1F, 0xFF, 0xC1, 0xFF, 0xF8, + 0x1F, 0xFC, 0x00, 0xFE, 0x00, 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, + 0x3F, 0x81, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0xFC, 0x00, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xF0, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, + 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFB, 0xFF, 0xBF, 0xFF, 0xEF, 0xFE, 0xFF, 0xFF, 0x9F, 0xF3, + 0xFF, 0xFE, 0x1F, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFE, + 0x7F, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x87, + 0xF0, 0xFF, 0xFF, 0xF0, 0xFE, 0x1F, 0xFF, 0xFE, 0x1F, 0xC3, 0xFF, 0xFF, + 0xC3, 0xF8, 0x7F, 0xFF, 0xF8, 0x7F, 0x0F, 0xFF, 0xFF, 0x0F, 0xE1, 0xFF, + 0xFF, 0xE1, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0x87, 0xFF, 0xFF, 0x87, 0xF0, + 0xFF, 0xFF, 0xF0, 0xFE, 0x0F, 0xFF, 0xFE, 0x1F, 0xC1, 0xFF, 0xFF, 0xC3, + 0xF8, 0x1F, 0xFF, 0xF8, 0x7F, 0x03, 0xFF, 0xFF, 0x0F, 0xE0, 0x3F, 0xFF, + 0xE1, 0xFC, 0x03, 0xFF, 0xFC, 0x3F, 0x80, 0x1F, 0xFF, 0x87, 0xF0, 0x00, + 0x7F, 0xF0, 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, + 0x00, 0x07, 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, + 0xFC, 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, + 0xF0, 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, + 0x07, 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, + 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, + 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, 0x07, + 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, 0x00, + 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, 0xFE, + 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, 0x07, 0xF8, + 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, 0x00, 0x03, + 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, 0xFE, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, + 0xF8, 0x07, 0xFF, 0x07, 0xFF, 0xC2, 0x07, 0xF0, 0x01, 0xF8, 0x00, 0xFC, + 0x00, 0x7E, 0x00, 0xFE, 0xFF, 0xFE, 0x7F, 0xFE, 0x0F, 0xF8, 0x00, 0x01, + 0xF0, 0x3F, 0x07, 0xF0, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF3, + 0xF8, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, + 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x01, 0xFC, + 0x00, 0x3F, 0xF8, 0x07, 0xFF, 0xF0, 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x3F, + 0xC7, 0xF9, 0xF8, 0x1F, 0xDF, 0xC0, 0x7F, 0xFE, 0x03, 0xFF, 0xE0, 0x1F, + 0xFF, 0x00, 0xFF, 0xF8, 0x07, 0xFF, 0xC0, 0x3F, 0xFE, 0x01, 0xFF, 0xF8, + 0x0F, 0xFF, 0xC0, 0x7F, 0x7E, 0x07, 0xF3, 0xFC, 0x7F, 0x8F, 0xFF, 0xF8, + 0x7F, 0xFF, 0xC1, 0xFF, 0xFC, 0x03, 0xFF, 0x80, 0x07, 0xF0, 0x00, 0x7E, + 0x07, 0xE0, 0x03, 0xF8, 0x3F, 0x80, 0x0F, 0xE0, 0xFE, 0x00, 0x7F, 0x07, + 0xF0, 0x01, 0xFC, 0x1F, 0xC0, 0x0F, 0xF0, 0xFF, 0x00, 0x3F, 0x83, 0xF8, + 0x01, 0xFE, 0x1F, 0xE0, 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0xC1, 0xFC, 0x00, + 0xFF, 0x0F, 0xF0, 0x03, 0xFC, 0x3F, 0xC0, 0x1F, 0xE1, 0xFE, 0x00, 0x7F, + 0x87, 0xF8, 0x03, 0xFE, 0x3F, 0xE0, 0x1F, 0xE1, 0xFE, 0x01, 0xFF, 0x1F, + 0xF0, 0x0F, 0xF0, 0xFF, 0x00, 0xFF, 0x0F, 0xF0, 0x07, 0xF8, 0x7F, 0x80, + 0x7F, 0x87, 0xF8, 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0x83, 0xFC, 0x03, 0xFC, + 0x3F, 0xC0, 0x1F, 0xC1, 0xFC, 0x01, 0xFC, 0x1F, 0xE0, 0x0F, 0xE0, 0xFE, + 0x00, 0xFE, 0x0F, 0xE0, 0x07, 0xE0, 0x7E, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x3E, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x1F, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x0F, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x0F, 0x80, 0x03, 0xFF, 0xC0, + 0x00, 0x0F, 0x80, 0x01, 0xF7, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0xF3, 0xF0, + 0x00, 0x07, 0xC0, 0x00, 0x41, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFC, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7E, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x3F, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x0F, + 0xC0, 0x00, 0xF8, 0x00, 0x00, 0x07, 0xE0, 0x00, 0xF8, 0x00, 0x00, 0x03, + 0xF0, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x1F, 0x00, 0x00, 0x00, + 0x0F, 0xC0, 0x1F, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x0F, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFC, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFE, + 0x00, 0x00, 0x07, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xC0, 0x01, 0xFF, + 0x80, 0x00, 0x03, 0xE0, 0x01, 0xFF, 0xC0, 0x00, 0x03, 0xE0, 0x01, 0xF7, + 0xE0, 0x00, 0x03, 0xE0, 0x01, 0xFB, 0xF0, 0x00, 0x01, 0xF0, 0x01, 0xF9, + 0xF8, 0x00, 0x01, 0xF0, 0x01, 0xF8, 0xFC, 0x00, 0x00, 0xF8, 0x00, 0xF8, + 0x7E, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0x78, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x7C, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x3E, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x3E, 0x00, 0x0F, + 0xFF, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x07, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x7C, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0xF8, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0xFF, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0xFB, 0xF0, 0x00, + 0x03, 0xE0, 0x00, 0xF3, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x83, 0xF0, 0x00, + 0x07, 0xC0, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xF0, 0x00, + 0x0F, 0x80, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x7C, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x01, + 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x03, + 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xC0, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x7F, 0xF8, 0x00, 0x00, 0x0F, + 0x80, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x1E, + 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3E, 0x03, 0xF8, 0x7F, 0x00, 0x00, 0x7C, + 0x03, 0xF0, 0x3F, 0x00, 0x00, 0x7C, 0x03, 0xF0, 0x3F, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xF0, + 0x00, 0x00, 0xFE, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xE0, + 0x00, 0x03, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xC0, + 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x7F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x1E, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x3E, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x7C, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0xF8, 0x00, + 0x07, 0xFF, 0xFF, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x7F, 0xFC, + 0x00, 0x00, 0x3E, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 0x07, 0xFF, + 0xF8, 0x00, 0x01, 0xF0, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x7C, 0x00, 0x1F, + 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0xE0, 0xFC, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x78, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x1F, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xF8, + 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x07, + 0xC0, 0x00, 0x00, 0x01, 0xF0, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x3F, 0x00, + 0x7C, 0x00, 0x00, 0xFC, 0x0F, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0xC3, 0xFC, + 0x03, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0xFF, + 0xC0, 0x1F, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x03, 0xC0, 0x00, 0x00, 0x1F, + 0xFC, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xC0, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x03, + 0xFC, 0x00, 0x00, 0x01, 0xE0, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7C, 0x00, + 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x03, 0xE0, + 0x03, 0xEF, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0xFD, 0xF8, 0x00, 0x00, 0x1F, + 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x07, 0xC0, 0x0F, 0xC7, 0xE0, 0x00, 0x01, + 0xF0, 0x01, 0xF0, 0xFC, 0x00, 0x00, 0x3E, 0x00, 0x7C, 0x1F, 0x80, 0x00, + 0x0F, 0x80, 0x1F, 0xFF, 0xFE, 0x00, 0x01, 0xF0, 0x03, 0xFF, 0xFF, 0xC0, + 0x00, 0x7C, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x03, 0xE0, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0xF8, 0x00, 0x00, 0x07, + 0xE0, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x07, 0xC0, 0x00, 0x00, + 0x1F, 0x80, 0x00, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, + 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x3E, 0x1F, 0xF0, 0x00, + 0x1F, 0xEF, 0xF8, 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x0F, 0xF9, 0xFF, 0x80, + 0x0F, 0xFC, 0x7F, 0xF0, 0x3F, 0xFC, 0x3F, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, + 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, + 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x03, + 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xEF, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x00, + 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x7F, 0xE0, 0x00, + 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x0F, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x00, 0x00, 0x1F, + 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, 0x80, 0x3F, 0xE0, 0x00, 0x0F, 0xFC, + 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x03, 0xFE, 0x00, + 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, + 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF8, 0x00, 0x00, 0xFF, 0x80, 0xFF, + 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xF0, 0x3F, 0xE0, + 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x07, 0xFE, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, + 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, + 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x3F, 0xEF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x1F, + 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, + 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x0F, + 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x01, 0xFF, + 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, 0x80, 0x3F, 0xE0, + 0x00, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, + 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, + 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF8, 0x00, 0x00, + 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x3F, + 0xF0, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x07, 0xFE, + 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, + 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x01, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xDF, 0xC0, 0x00, 0x00, 0x00, 0xFC, + 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xE3, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x0F, + 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, + 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x3F, 0xEF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, + 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, + 0x00, 0x0F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, + 0x07, 0xFC, 0x0F, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, + 0xFF, 0x01, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, + 0x80, 0x3F, 0xE0, 0x00, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, + 0x07, 0xFC, 0x00, 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, + 0xF8, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, + 0x00, 0x00, 0x3F, 0xF0, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, + 0x00, 0x07, 0xFE, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, + 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x01, 0xF0, 0x07, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x3C, 0x00, 0x00, 0x01, 0xFF, 0xC3, 0xE0, + 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x07, 0x87, 0xFF, 0x80, 0x00, 0x00, 0x3C, 0x0F, 0xF8, 0x00, 0x00, + 0x01, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0xF8, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x07, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, 0x03, + 0xFE, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x81, + 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, + 0xE0, 0x00, 0x03, 0xFE, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x07, 0xFC, + 0x00, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0x80, + 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xF0, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0x00, 0x00, + 0x1F, 0xF0, 0x1F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0xFF, 0x80, 0x00, 0x07, + 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0xFF, + 0xC3, 0xFE, 0x00, 0x00, 0x03, 0xFE, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF9, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x00, + 0x7F, 0x83, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x1F, + 0xE0, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF8, + 0x3F, 0xC0, 0x00, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x0F, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x07, 0xFD, 0xFF, + 0x00, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x3F, 0xE0, + 0x00, 0x00, 0x3F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x0F, 0xFC, 0x00, + 0x00, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x81, 0xFF, 0x80, 0x00, + 0x07, 0xFC, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x03, + 0xFE, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x07, 0xFC, 0x00, 0x01, 0xFF, + 0x80, 0x3F, 0xF0, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0xC0, + 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0xFF, 0x80, 0x00, 0x07, 0xFE, 0x07, 0xFC, + 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFE, 0x00, + 0x00, 0x03, 0xFE, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0x00, + 0x1F, 0xF8, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x00, + 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, + 0x00, 0x03, 0xC1, 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x78, 0xF0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, + 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, + 0x01, 0xFF, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF8, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0xFF, 0xC0, 0x00, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, + 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x00, 0xFF, 0xC0, 0x00, 0x0F, 0xF8, 0x03, + 0xFE, 0x00, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x07, 0xFC, 0x00, 0x7F, + 0xC0, 0x00, 0x3F, 0xE0, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xF8, + 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x80, + 0x00, 0x0F, 0xF8, 0x0F, 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, + 0x03, 0xFF, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x3F, 0xF0, 0x00, 0x00, + 0x7F, 0xE1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x1F, 0xF8, 0x00, 0x00, 0x0F, + 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xE7, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x03, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x7F, + 0xE1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x83, 0xFE, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xFF, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, + 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x1F, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0x00, 0x03, 0xFE, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x03, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x7F, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x1F, + 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, + 0x07, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xF8, 0x00, 0xFF, + 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0xFF, 0xC0, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xF8, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0x00, + 0x01, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFF, + 0xFC, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF7, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, + 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, + 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, 0xFF, 0xF8, 0x3F, 0xFC, 0x00, + 0x7F, 0xF0, 0x7F, 0xF0, 0x00, 0x7F, 0xF1, 0xFF, 0x80, 0x00, 0x7F, 0xE3, + 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xFC, 0x00, 0x00, 0xFF, 0xDF, 0xF8, 0x00, + 0x00, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0x80, 0x7F, 0xC0, 0x00, 0x00, 0x01, + 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x30, 0x0F, 0xF8, + 0x00, 0x00, 0x7C, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x3F, 0xF0, 0x00, 0x03, + 0xFF, 0x7F, 0xE0, 0x00, 0x07, 0xFE, 0x7F, 0xE0, 0x00, 0x1F, 0xF8, 0xFF, + 0xC0, 0x00, 0x3F, 0xF0, 0xFF, 0xC0, 0x00, 0xFF, 0xE1, 0xFF, 0xE0, 0x03, + 0xFF, 0x81, 0xFF, 0xF0, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, + 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x00, + 0x00, 0x04, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, + 0x1F, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x0F, 0xE0, + 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x00, 0xFE, + 0xFE, 0x00, 0x00, 0x3F, 0x3F, 0x80, 0x00, 0x1F, 0xC7, 0xF0, 0x00, 0x0F, + 0xE0, 0xFE, 0x00, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, + 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x3F, 0xC1, 0xFE, + 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, + 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, 0x07, 0xF0, + 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, + 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, + 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, + 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, + 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, + 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, + 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x0F, 0xF8, 0x7F, + 0xC1, 0xFE, 0x0F, 0xF0, 0x3F, 0x81, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x0F, 0xF8, 0x3F, + 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, + 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, + 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, + 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, + 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, + 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, + 0x83, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x3F, 0xF8, 0x01, 0xFF, 0xC0, 0x1F, + 0xFF, 0x01, 0xFD, 0xFC, 0x0F, 0xCF, 0xE0, 0xFE, 0x3F, 0x8F, 0xE0, 0xFE, + 0xFE, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, + 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, + 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, + 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, + 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, + 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x00, + 0xFF, 0x07, 0xFF, 0xF8, 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, + 0x7F, 0xFF, 0x83, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, + 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, + 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, + 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, + 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, + 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, + 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, + 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, + 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x01, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, + 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x07, 0xFC, 0x00, 0x3F, 0xFE, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x7F, + 0xC0, 0x00, 0x7F, 0xF0, 0x1F, 0xF0, 0x00, 0x0F, 0xFE, 0x07, 0xFC, 0x00, + 0x01, 0xFF, 0x81, 0xFF, 0x00, 0x00, 0x3F, 0xE0, 0x7F, 0xC0, 0x00, 0x0F, + 0xFC, 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0x07, 0xFC, 0x00, 0x00, 0xFF, 0xC1, + 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x7F, + 0xC0, 0x00, 0x07, 0xFC, 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x07, 0xFC, 0x00, + 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x7F, 0xC0, 0x00, 0x0F, + 0xFC, 0x1F, 0xF0, 0x00, 0x03, 0xFE, 0x07, 0xFC, 0x00, 0x01, 0xFF, 0x81, + 0xFF, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, 0x3F, 0xF0, 0x1F, 0xF0, + 0x00, 0x1F, 0xFC, 0x07, 0xFC, 0x00, 0x3F, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, + 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF0, 0x00, 0x1F, 0xF0, 0x1E, 0x00, + 0x03, 0xFF, 0x87, 0xC0, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFE, + 0x00, 0x03, 0xC3, 0xFF, 0xC0, 0x00, 0x78, 0x1F, 0xF0, 0x00, 0x0F, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x01, 0xFF, + 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xE0, + 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, + 0xFC, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, + 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0x00, + 0x7F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFE, 0xFF, + 0xE0, 0x3F, 0xFF, 0xCF, 0xFC, 0x07, 0xFF, 0xF9, 0xFF, 0xC0, 0xFF, 0xFF, + 0x1F, 0xF8, 0x1F, 0xFF, 0xE1, 0xFF, 0x83, 0xFF, 0xFC, 0x3F, 0xF8, 0x7F, + 0xFF, 0x83, 0xFF, 0x0F, 0xFF, 0xF0, 0x7F, 0xF1, 0xFF, 0xFE, 0x07, 0xFF, + 0x3F, 0xFF, 0xC0, 0x7F, 0xE7, 0xFF, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF, 0x00, + 0xFF, 0xDF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, + 0x80, 0x1F, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x07, + 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, + 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, + 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, + 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, + 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, + 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, + 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, + 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, + 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, + 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, + 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, + 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, + 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, + 0x3F, 0xBF, 0x80, 0x00, 0x00, 0x07, 0xE7, 0xF0, 0x00, 0x00, 0x01, 0xFC, + 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0xC0, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, + 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, + 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, + 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, + 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, + 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, + 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0x00, + 0x00, 0x01, 0xFF, 0x01, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x7C, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3C, + 0x3F, 0xFC, 0x00, 0x00, 0x07, 0x81, 0xFF, 0x00, 0x00, 0x00, 0xF0, 0x07, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, + 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE1, 0xFF, + 0x80, 0x00, 0x0F, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xF0, + 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x7F, 0xE0, 0x00, + 0x03, 0xFF, 0x8F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0xFF, 0xE0, 0x00, 0x3F, + 0xFC, 0x1F, 0xFF, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0xFF, 0x00, + 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x00, + 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x00, 0x3F, + 0xC1, 0xFE, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, + 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE1, 0xFF, + 0x80, 0x00, 0x0F, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xF0, + 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x7F, 0xE0, 0x00, + 0x03, 0xFF, 0x8F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0xFF, 0xE0, 0x00, 0x3F, + 0xFC, 0x1F, 0xFF, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, + 0x00, 0x07, 0x00, 0xF0, 0x00, 0x3E, 0x0F, 0xE0, 0x01, 0xFC, 0x7F, 0xC0, + 0x0F, 0xFB, 0xFF, 0x80, 0x7F, 0xF7, 0xFF, 0x03, 0xFF, 0x8F, 0xFE, 0x1F, + 0xFC, 0x1F, 0xFC, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xF8, + 0x00, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0x80, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x07, + 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, + 0xFF, 0xC0, 0x7F, 0xF3, 0xFF, 0x83, 0xFF, 0x87, 0xFF, 0x0F, 0xFC, 0x0F, + 0xFE, 0x7F, 0xE0, 0x1F, 0xFD, 0xFF, 0x00, 0x3F, 0xF3, 0xF8, 0x00, 0x7F, + 0x07, 0xC0, 0x00, 0xF8, 0x0E, 0x00, 0x01, 0xC0, 0x10, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x1F, 0xFC, 0x00, 0x78, 0x00, 0x07, 0xFF, 0xFC, 0x07, 0xE0, 0x01, + 0xFF, 0xFF, 0xFC, 0x7F, 0x80, 0x1F, 0xFF, 0xFF, 0xF3, 0xF8, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x0F, + 0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x00, 0x3F, + 0xF8, 0x0F, 0xFE, 0x00, 0x01, 0xFF, 0xE0, 0x7F, 0xE0, 0x00, 0x1F, 0xFF, + 0x07, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x3F, 0xF0, 0x00, 0x1F, 0xFF, 0xE1, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x1F, 0xF8, 0x00, 0x1F, 0xEF, 0xFC, 0xFF, + 0xC0, 0x01, 0xFE, 0x7F, 0xE7, 0xFC, 0x00, 0x1F, 0xE1, 0xFF, 0x3F, 0xE0, + 0x01, 0xFE, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE0, 0x7F, 0xCF, 0xF8, 0x00, + 0xFE, 0x03, 0xFE, 0x7F, 0xC0, 0x0F, 0xE0, 0x1F, 0xF3, 0xFE, 0x00, 0xFF, + 0x00, 0xFF, 0x9F, 0xF0, 0x0F, 0xF0, 0x07, 0xFC, 0xFF, 0x80, 0xFF, 0x00, + 0x3F, 0xE7, 0xFC, 0x0F, 0xF0, 0x01, 0xFF, 0x3F, 0xE0, 0xFF, 0x00, 0x0F, + 0xF9, 0xFF, 0x8F, 0xF0, 0x00, 0x7F, 0xCF, 0xFC, 0xFF, 0x00, 0x07, 0xFE, + 0x7F, 0xEF, 0xF0, 0x00, 0x3F, 0xF1, 0xFF, 0x7F, 0x00, 0x01, 0xFF, 0x8F, + 0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x7F, 0xFF, 0x80, 0x00, 0xFF, 0xC1, 0xFF, + 0xF8, 0x00, 0x0F, 0xFE, 0x0F, 0xFF, 0x80, 0x00, 0xFF, 0xE0, 0x3F, 0xF8, + 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0xE0, + 0x3F, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, + 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x3F, 0xDF, 0xFF, 0xFF, 0xF0, 0x03, 0xFC, 0x3F, 0xFF, 0xFF, 0x00, + 0x0F, 0xC0, 0x7F, 0xFF, 0xE0, 0x00, 0x3C, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, + 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, + 0xFF, 0xE0, 0x00, 0x7F, 0xEF, 0xFE, 0x00, 0x3F, 0xF9, 0xFF, 0xF0, 0x1F, + 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, + 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x07, + 0xF8, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, + 0x0F, 0xF0, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, + 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, + 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xEF, + 0xFE, 0x00, 0x3F, 0xF9, 0xFF, 0xF0, 0x1F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, + 0x80, 0x00, 0x03, 0xFB, 0xF8, 0x00, 0x00, 0x7E, 0x7F, 0x00, 0x00, 0x1F, + 0xC7, 0xF0, 0x00, 0x07, 0xF0, 0x7F, 0x00, 0x01, 0xFC, 0x07, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xEF, 0xFE, 0x00, 0x3F, 0xF9, 0xFF, + 0xF0, 0x1F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, + 0x3F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, + 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x3F, + 0xFC, 0x00, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x3F, 0xC1, 0xFE, 0x00, + 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0xFF, + 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x0F, 0xF0, + 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x03, 0xFF, + 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, + 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, + 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x7F, 0xF0, 0x01, + 0xFF, 0xCF, 0xFF, 0x80, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, + 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFE, 0x01, + 0xFF, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xE0, + 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, + 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xF7, 0xFE, 0x00, 0x00, 0x1F, 0xF9, + 0xFF, 0xC0, 0x00, 0x0F, 0xFE, 0x3F, 0xF8, 0x00, 0x03, 0xFF, 0x07, 0xFE, + 0x00, 0x01, 0xFF, 0x81, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x3F, 0xF0, 0x00, + 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0x1F, 0xF8, 0x01, 0xFF, 0xC0, 0x07, 0xFE, + 0x00, 0x3F, 0xF0, 0x03, 0xFF, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0x80, 0x01, + 0xFF, 0x80, 0x7F, 0xE0, 0x00, 0x3F, 0xF0, 0x3F, 0xF0, 0x00, 0x0F, 0xFE, + 0x0F, 0xFC, 0x00, 0x01, 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x3F, 0xF1, 0xFF, + 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, + 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, + 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, + 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, + 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, + 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x07, 0xFF, 0xBF, 0xE0, + 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, + 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x07, + 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, + 0xFF, 0xC0, 0x7F, 0xF0, 0xFF, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, + 0x7F, 0xC0, 0x7F, 0x80, 0x7F, 0xC0, 0x7F, 0x80, 0x7F, 0xC0, 0xFF, 0x80, + 0x7F, 0xC0, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, + 0xFF, 0x00, 0xFF, 0x81, 0xFF, 0x00, 0xFF, 0x81, 0xFE, 0x00, 0xFF, 0x83, + 0xFE, 0x00, 0xFF, 0x83, 0xFC, 0x00, 0xFF, 0x87, 0xFC, 0x00, 0xFF, 0x87, + 0xFE, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x83, + 0xFF, 0x80, 0xFF, 0x81, 0xFF, 0xC0, 0xFF, 0x81, 0xFF, 0xE0, 0xFF, 0x80, + 0xFF, 0xF0, 0xFF, 0x80, 0x7F, 0xF8, 0xFF, 0x80, 0x3F, 0xFC, 0xFF, 0x80, + 0x1F, 0xFC, 0xFF, 0x80, 0x0F, 0xFE, 0xFF, 0x80, 0x07, 0xFE, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0xC1, 0xFF, 0xFF, 0x83, + 0xE3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0xFF, 0x8F, + 0xFF, 0xFC, 0xFF, 0x87, 0xFF, 0xFC, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0x80, + 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, + 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xE0, + 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, + 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0x81, 0xFF, 0xC3, + 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, 0xFF, 0x01, 0xE0, 0x03, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0xF0, 0x00, + 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x83, 0xFF, + 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xF3, 0xFC, 0x7F, 0xFC, + 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, + 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, 0xF0, 0x03, 0xFF, 0x3F, 0xF0, 0x0F, + 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x9F, 0xE1, 0xFF, 0xFE, 0x3F, + 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, + 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, + 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, + 0x81, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, 0xFF, 0x01, 0xE0, + 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x01, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, + 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xF3, + 0xFC, 0x7F, 0xFC, 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, 0xFE, 0x00, 0x3F, + 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, 0xF0, 0x03, 0xFF, + 0x3F, 0xF0, 0x0F, 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x9F, 0xE1, + 0xFF, 0xFE, 0x3F, 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xFF, 0xE0, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x1F, 0x9F, 0xC0, 0x00, + 0x7F, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, + 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, + 0xFF, 0xC1, 0xFF, 0x81, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, + 0xFF, 0x01, 0xE0, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, + 0xF8, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x7F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, + 0x1F, 0xFF, 0xF3, 0xFC, 0x7F, 0xFC, 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, + 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, + 0xF0, 0x03, 0xFF, 0x3F, 0xF0, 0x0F, 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, + 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, + 0xFF, 0x9F, 0xE1, 0xFF, 0xFE, 0x3F, 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, + 0x80, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xC0, 0x07, 0xFC, 0x07, 0x80, 0x0F, + 0xFE, 0x1F, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0xF0, + 0xFF, 0xF0, 0x01, 0xE0, 0x7F, 0xC0, 0x03, 0xC0, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, + 0xE0, 0xFF, 0xC0, 0xFF, 0xE1, 0xFE, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0xFF, + 0x80, 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xE0, + 0x3F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x0F, + 0xFF, 0xF9, 0xFE, 0x3F, 0xFE, 0x03, 0xFC, 0x7F, 0xE0, 0x07, 0xF9, 0xFF, + 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, + 0x01, 0xFF, 0x9F, 0xF8, 0x07, 0xFF, 0x1F, 0xF8, 0x3F, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, + 0xCF, 0xF0, 0xFF, 0xFF, 0x1F, 0xE0, 0x7F, 0xF8, 0x3F, 0xE0, 0x3F, 0xC0, + 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x7F, 0x80, 0x1F, 0xE0, + 0xFF, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0xFF, 0x07, + 0xF8, 0x01, 0xFE, 0x0F, 0xF0, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, + 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, + 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xE0, + 0xFF, 0xC0, 0xFF, 0xE1, 0xFE, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0xFF, 0x80, + 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xE0, 0x3F, + 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xF9, 0xFE, 0x3F, 0xFE, 0x03, 0xFC, 0x7F, 0xE0, 0x07, 0xF9, 0xFF, 0x00, + 0x1F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x01, + 0xFF, 0x9F, 0xF8, 0x07, 0xFF, 0x1F, 0xF8, 0x3F, 0xFE, 0x3F, 0xFF, 0xFF, + 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xCF, + 0xF0, 0xFF, 0xFF, 0x1F, 0xE0, 0x7F, 0xF8, 0x3F, 0xE0, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x01, 0xE3, 0xC0, 0x00, 0x03, 0x83, 0x80, 0x00, 0x0F, 0x07, 0x00, + 0x00, 0x1E, 0x0F, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x1F, + 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, + 0xFF, 0xFE, 0x0F, 0xFC, 0x0F, 0xFE, 0x1F, 0xE0, 0x07, 0xFC, 0x7F, 0xC0, + 0x0F, 0xF8, 0x0F, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, + 0xFE, 0x03, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0x9F, 0xE3, 0xFF, 0xE0, 0x3F, 0xC7, 0xFE, 0x00, 0x7F, + 0x9F, 0xF0, 0x01, 0xFF, 0x3F, 0xE0, 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0xFC, + 0xFF, 0x80, 0x1F, 0xF9, 0xFF, 0x80, 0x7F, 0xF1, 0xFF, 0x83, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xF1, 0xFE, 0x07, 0xFF, 0x83, 0xFE, 0x03, + 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0xFF, + 0x83, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, + 0xC1, 0xFF, 0xFC, 0x1F, 0xFC, 0x7F, 0xC0, 0x1F, 0xFE, 0x01, 0xFF, 0x1F, + 0xE0, 0x03, 0xFF, 0x00, 0x3F, 0xE0, 0x78, 0x00, 0xFF, 0x80, 0x07, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x7F, + 0x80, 0x00, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x03, 0xFF, 0xFF, 0x00, 0x07, + 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0xF0, + 0x00, 0x00, 0x3F, 0xF0, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xE0, 0xFF, 0x00, 0x1F, + 0xFC, 0x00, 0x7F, 0xBF, 0xE0, 0x07, 0xFF, 0x00, 0x3F, 0xEF, 0xF8, 0x03, + 0xFF, 0xE0, 0x1F, 0xFB, 0xFF, 0x83, 0xFF, 0xFE, 0x0F, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xE0, 0x1F, + 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x00, + 0x1F, 0xE0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xFF, + 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, + 0xE0, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, + 0x7F, 0xE0, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xF0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x3C, 0x3F, 0xE0, 0x00, 0xFF, + 0x7F, 0xC0, 0x07, 0xFD, 0xFF, 0x00, 0x1F, 0xF7, 0xFE, 0x00, 0xFF, 0x8F, + 0xFE, 0x0F, 0xFE, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x3F, 0xFE, + 0x00, 0x00, 0x81, 0xFC, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, + 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, + 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, 0xFF, + 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, + 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, 0x01, 0xFF, 0x1F, 0xF0, 0x01, 0xFE, + 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, + 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, + 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, 0xCF, 0xFC, 0x01, 0xFF, 0x8F, 0xFC, + 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xC1, + 0xFF, 0xC1, 0xFF, 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, 0x01, 0xFF, 0x1F, + 0xF0, 0x01, 0xFE, 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, + 0x00, 0x07, 0xFB, 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, 0xCF, 0xFC, 0x01, + 0xFF, 0x8F, 0xFC, 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x1F, 0xFF, 0xFF, + 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFE, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xFF, 0xE0, + 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x1F, 0x9F, 0xC0, + 0x00, 0x7F, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, + 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, + 0xFF, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, + 0x01, 0xFF, 0x1F, 0xF0, 0x01, 0xFE, 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, + 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, + 0xCF, 0xFC, 0x01, 0xFF, 0x8F, 0xFC, 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, + 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, + 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x7F, 0x80, + 0x1F, 0xE0, 0xFF, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x7F, 0x83, 0xFC, 0x00, + 0xFF, 0x07, 0xF8, 0x01, 0xFE, 0x0F, 0xF0, 0x03, 0xFC, 0x1F, 0xE0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, + 0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC1, 0xFF, 0x00, 0xFF, 0xC7, 0xFE, 0x00, + 0xFF, 0x8F, 0xF8, 0x00, 0xFF, 0x1F, 0xF0, 0x01, 0xFF, 0x7F, 0xC0, 0x01, + 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, 0xFF, 0xFF, 0xFF, + 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x1F, 0x03, 0xFE, 0x00, 0x3F, 0xE7, + 0xFE, 0x00, 0xFF, 0xC7, 0xFE, 0x01, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, + 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, + 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, 0x07, 0xF0, + 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, + 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, + 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, + 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, + 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, + 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x3F, 0x81, 0xFE, 0x07, 0xF0, + 0x3F, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, + 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, + 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, + 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, + 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, + 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x00, 0x03, 0xFE, 0x00, + 0x3F, 0xF8, 0x01, 0xFF, 0xC0, 0x1F, 0xFF, 0x01, 0xFD, 0xFC, 0x0F, 0xCF, + 0xE0, 0xFE, 0x3F, 0x8F, 0xE0, 0xFE, 0xFE, 0x03, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x07, 0xF8, + 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, + 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, + 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, + 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, + 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, + 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, + 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0xFF, 0x07, + 0xFF, 0xF8, 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, + 0x83, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, + 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, + 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, + 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x80, + 0x80, 0x00, 0x3F, 0xE1, 0xE0, 0x00, 0x07, 0xFB, 0xF0, 0x00, 0x01, 0xFF, + 0xF0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, + 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFC, 0x7F, 0x80, 0x00, 0x78, + 0x1F, 0xE0, 0x00, 0x30, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, + 0xF8, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, + 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, + 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0x83, 0xFF, 0xE7, 0xFF, 0x00, 0xFF, 0xF3, + 0xFF, 0x00, 0x1F, 0xFB, 0xFF, 0x00, 0x0F, 0xFD, 0xFF, 0x80, 0x03, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, + 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xCF, 0xF8, 0x00, + 0x7F, 0xE7, 0xFE, 0x00, 0x3F, 0xF1, 0xFF, 0x80, 0x3F, 0xF0, 0xFF, 0xF0, + 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x07, + 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xF8, 0x03, 0xC0, 0x0F, + 0xF8, 0x0F, 0x00, 0x3F, 0xF8, 0x7C, 0x01, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, + 0xFF, 0x80, 0x1E, 0x1F, 0xFE, 0x00, 0x78, 0x1F, 0xF0, 0x01, 0xE0, 0x0F, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x80, 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x3F, 0xFF, 0x8F, + 0xF1, 0xFF, 0xFF, 0x3F, 0xCF, 0xFF, 0xFE, 0xFF, 0x7F, 0xFF, 0xFB, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF0, 0x01, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, + 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, + 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0x01, 0xFF, 0x00, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x07, 0xFF, + 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFC, 0x07, 0xFF, + 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, 0x00, 0x7F, 0xE3, 0xFF, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, 0x80, 0x03, 0xFE, 0xFF, + 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, + 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0xC0, 0x1F, + 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, + 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x7F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFC, + 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, 0x00, 0x7F, + 0xE3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, 0x80, 0x03, + 0xFE, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, + 0xC0, 0x1F, 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, + 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xF7, 0xF0, 0x00, 0x03, 0xF3, 0xF8, + 0x00, 0x03, 0xF8, 0xFE, 0x00, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x0F, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, + 0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, + 0x00, 0x7F, 0xE3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, + 0x80, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, + 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, + 0xF9, 0xFF, 0xC0, 0x1F, 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, + 0xFC, 0x0F, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, + 0xFC, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x7C, 0x01, 0xE0, 0x00, 0xFF, 0x80, 0xF0, 0x00, 0x7F, + 0xF0, 0xF8, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x1E, + 0x1F, 0xFE, 0x00, 0x0F, 0x03, 0xFE, 0x00, 0x07, 0x80, 0x3E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0x07, 0xFF, 0x87, 0xFE, 0x00, 0xFF, + 0xC7, 0xFE, 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x0F, 0xFB, 0xFF, 0x00, 0x07, + 0xFD, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x7F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x3F, 0xF3, 0xFF, + 0x80, 0x3F, 0xF0, 0xFF, 0xF0, 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x03, 0xFC, 0x1F, 0xE0, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0xFF, 0x07, 0xF8, + 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x1F, 0xE0, 0xFF, + 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, + 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, + 0xFF, 0xFE, 0x0F, 0xFF, 0x07, 0xFF, 0x87, 0xFE, 0x00, 0xFF, 0xC7, 0xFE, + 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x0F, 0xFB, 0xFF, 0x00, 0x07, 0xFD, 0xFF, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, + 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, + 0xCF, 0xF8, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x3F, 0xF3, 0xFF, 0x80, 0x3F, + 0xF0, 0xFF, 0xF0, 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0xFE, 0x03, 0xC0, 0x0F, 0xFF, 0xE3, 0xF0, 0x1F, 0xFF, 0xFB, 0xF0, 0x1F, + 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xFC, 0x1F, 0xFE, 0x0F, 0xFF, 0x0F, 0xFC, 0x01, 0xFF, 0x8F, + 0xFC, 0x01, 0xFF, 0xE7, 0xFC, 0x01, 0xFF, 0xF7, 0xFC, 0x00, 0xFF, 0xFB, + 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFD, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, + 0xFF, 0x80, 0xFC, 0x3F, 0xFF, 0xC0, 0xFC, 0x1F, 0xFF, 0xE0, 0x7C, 0x0F, + 0xFF, 0xF0, 0x7E, 0x07, 0xFF, 0xF8, 0x7E, 0x03, 0xFF, 0xFE, 0x7E, 0x01, + 0xFF, 0xFF, 0x7E, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xBF, 0xFE, 0x00, + 0x7F, 0xDF, 0xFF, 0x00, 0x7F, 0xCF, 0xFF, 0x00, 0x7F, 0xE3, 0xFF, 0x00, + 0x7F, 0xE1, 0xFF, 0xE0, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, + 0xFF, 0xF0, 0x1F, 0x8F, 0xFF, 0xE0, 0x07, 0x80, 0xFF, 0x80, 0x01, 0x80, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, + 0x3F, 0xF7, 0xFE, 0x01, 0xFF, 0xDF, 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, + 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, + 0x0F, 0xFF, 0xE3, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, 0x3F, 0xF7, 0xFE, + 0x01, 0xFF, 0xDF, 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xE3, + 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0xFE, 0xFE, 0x00, 0x03, 0xF3, 0xF8, 0x00, 0x1F, 0xC7, 0xF0, 0x00, + 0xFE, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, 0x3F, 0xF7, 0xFE, 0x01, 0xFF, 0xDF, + 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, + 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xE3, 0xFC, 0x1F, 0xFE, + 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x1F, 0xE0, + 0xFF, 0x00, 0x7F, 0x83, 0xFC, 0x01, 0xFE, 0x0F, 0xF0, 0x07, 0xF8, 0x3F, + 0xC0, 0x1F, 0xE0, 0xFF, 0x00, 0x7F, 0x83, 0xFC, 0x01, 0xFE, 0x0F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0x7F, 0xC0, 0x0F, + 0xFD, 0xFF, 0x80, 0x7F, 0xF7, 0xFF, 0x07, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0x3F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0x3F, 0xC3, + 0xFF, 0xF8, 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x03, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF7, 0xFC, + 0x00, 0x07, 0xF9, 0xFF, 0x00, 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x8F, + 0xF8, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xFC, + 0x1F, 0xF0, 0x01, 0xFE, 0x03, 0xFC, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, + 0xE0, 0x3F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x07, 0xFC, 0x01, 0xFF, 0x01, + 0xFE, 0x00, 0x3F, 0xC0, 0x7F, 0x80, 0x0F, 0xF0, 0x3F, 0xE0, 0x03, 0xFE, + 0x0F, 0xF0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x1F, 0xE1, 0xFF, 0x00, 0x07, + 0xFC, 0x7F, 0x80, 0x00, 0xFF, 0x1F, 0xE0, 0x00, 0x3F, 0xCF, 0xF8, 0x00, + 0x07, 0xFB, 0xFC, 0x00, 0x01, 0xFE, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xC0, + 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, + 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x80, + 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x81, + 0xFC, 0x00, 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0xBF, + 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xE0, + 0x07, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, + 0x03, 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xFC, + 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xF0, 0xFF, 0xBF, 0xFF, 0xE0, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0x87, + 0xFF, 0x00, 0xFF, 0x81, 0xFC, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x7F, + 0x83, 0xFC, 0x00, 0x1F, 0xE0, 0xFF, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x01, + 0xFE, 0x0F, 0xF0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x1F, 0xE0, 0xFF, 0x00, + 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x0F, 0xF8, 0xFF, 0x80, + 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x7F, 0xC1, 0xFF, + 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, 0x0F, 0xF0, 0x03, 0xFE, 0x03, + 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x1F, 0xF0, + 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0xFF, + 0x80, 0x0F, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x7F, 0x87, + 0xFC, 0x00, 0x1F, 0xF1, 0xFE, 0x00, 0x03, 0xFC, 0x7F, 0x80, 0x00, 0xFF, + 0x3F, 0xE0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x07, 0xFB, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xE0, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xF8, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, + 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, + 0xFE, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x1F, + 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x00 }; + +const GFXglyph myFont32pt8bGlyphs[] PROGMEM = { + { 0, 0, 0, 18, 0, 1 }, // 0x20 ' ' + { 0, 9, 45, 21, 6, -44 }, // 0x21 '!' + { 51, 24, 16, 30, 3, -44 }, // 0x22 '"' + { 99, 33, 45, 35, 1, -44 }, // 0x23 '#' + { 285, 30, 55, 35, 2, -47 }, // 0x24 '$' + { 492, 50, 48, 56, 3, -45 }, // 0x25 '%' + { 792, 41, 47, 46, 3, -45 }, // 0x26 '&' + { 1033, 9, 16, 15, 3, -44 }, // 0x27 ''' + { 1051, 16, 58, 21, 3, -44 }, // 0x28 '(' + { 1167, 16, 58, 21, 2, -44 }, // 0x29 ')' + { 1283, 22, 21, 25, 1, -44 }, // 0x2A '*' + { 1341, 31, 32, 37, 3, -37 }, // 0x2B '+' + { 1465, 9, 19, 18, 4, -8 }, // 0x2C ',' + { 1487, 17, 8, 21, 4, -19 }, // 0x2D '-' + { 1504, 8, 9, 18, 5, -8 }, // 0x2E '.' + { 1513, 18, 45, 18, 0, -44 }, // 0x2F '/' + { 1615, 29, 46, 35, 3, -44 }, // 0x30 '0' + { 1782, 20, 45, 35, 5, -44 }, // 0x31 '1' + { 1895, 30, 45, 35, 2, -44 }, // 0x32 '2' + { 2064, 30, 46, 35, 2, -44 }, // 0x33 '3' + { 2237, 33, 44, 35, 1, -43 }, // 0x34 '4' + { 2419, 30, 45, 35, 3, -43 }, // 0x35 '5' + { 2588, 30, 46, 35, 3, -44 }, // 0x36 '6' + { 2761, 29, 44, 35, 3, -43 }, // 0x37 '7' + { 2921, 29, 46, 35, 3, -44 }, // 0x38 '8' + { 3088, 30, 46, 35, 2, -44 }, // 0x39 '9' + { 3261, 9, 33, 21, 6, -32 }, // 0x3A ':' + { 3299, 10, 43, 21, 5, -32 }, // 0x3B ';' + { 3353, 31, 34, 37, 3, -38 }, // 0x3C '<' + { 3485, 31, 22, 37, 3, -32 }, // 0x3D '=' + { 3571, 31, 34, 37, 3, -38 }, // 0x3E '>' + { 3703, 33, 46, 38, 3, -45 }, // 0x3F '?' + { 3893, 59, 61, 61, 2, -45 }, // 0x40 '@' + { 4343, 45, 45, 46, 0, -44 }, // 0x41 'A' + { 4597, 37, 45, 46, 5, -44 }, // 0x42 'B' + { 4806, 39, 46, 46, 3, -45 }, // 0x43 'C' + { 5031, 37, 45, 46, 5, -44 }, // 0x44 'D' + { 5240, 34, 45, 42, 5, -44 }, // 0x45 'E' + { 5432, 31, 45, 38, 5, -44 }, // 0x46 'F' + { 5607, 42, 47, 49, 3, -45 }, // 0x47 'G' + { 5854, 36, 45, 46, 5, -44 }, // 0x48 'H' + { 6057, 9, 45, 18, 4, -44 }, // 0x49 'I' + { 6108, 29, 46, 35, 1, -44 }, // 0x4A 'J' + { 6275, 40, 45, 46, 5, -44 }, // 0x4B 'K' + { 6500, 32, 45, 38, 5, -44 }, // 0x4C 'L' + { 6680, 44, 45, 52, 4, -44 }, // 0x4D 'M' + { 6928, 35, 45, 46, 5, -44 }, // 0x4E 'N' + { 7125, 43, 47, 49, 3, -45 }, // 0x4F 'O' + { 7378, 34, 45, 42, 5, -44 }, // 0x50 'P' + { 7570, 45, 51, 49, 3, -45 }, // 0x51 'Q' + { 7857, 40, 45, 46, 5, -44 }, // 0x52 'R' + { 8082, 37, 47, 42, 2, -45 }, // 0x53 'S' + { 8300, 36, 45, 38, 1, -44 }, // 0x54 'T' + { 8503, 35, 46, 46, 5, -44 }, // 0x55 'U' + { 8705, 42, 45, 42, 0, -44 }, // 0x56 'V' + { 8942, 59, 45, 59, 0, -44 }, // 0x57 'W' + { 9274, 42, 45, 42, 0, -44 }, // 0x58 'X' + { 9511, 42, 45, 42, 0, -44 }, // 0x59 'Y' + { 9748, 36, 45, 38, 1, -44 }, // 0x5A 'Z' + { 9951, 16, 58, 21, 4, -44 }, // 0x5B '[' + { 10067, 18, 45, 18, 0, -44 }, // 0x5C '\' + { 10169, 15, 58, 21, 1, -44 }, // 0x5D ']' + { 10278, 29, 24, 37, 4, -45 }, // 0x5E '^' + { 10365, 36, 7, 35, -1, 6 }, // 0x5F '_' + { 10397, 14, 9, 21, 1, -44 }, // 0x60 '`' + { 10413, 31, 35, 35, 2, -33 }, // 0x61 'a' + { 10549, 32, 46, 38, 4, -44 }, // 0x62 'b' + { 10733, 30, 35, 35, 3, -33 }, // 0x63 'c' + { 10865, 31, 46, 38, 3, -44 }, // 0x64 'd' + { 11044, 31, 35, 35, 2, -33 }, // 0x65 'e' + { 11180, 22, 46, 21, 1, -45 }, // 0x66 'f' + { 11307, 31, 48, 38, 3, -33 }, // 0x67 'g' + { 11493, 30, 45, 38, 4, -44 }, // 0x68 'h' + { 11662, 8, 45, 18, 5, -44 }, // 0x69 'i' + { 11707, 16, 59, 18, -3, -44 }, // 0x6A 'j' + { 11825, 30, 45, 35, 4, -44 }, // 0x6B 'k' + { 11994, 8, 45, 18, 5, -44 }, // 0x6C 'l' + { 12039, 48, 34, 56, 4, -33 }, // 0x6D 'm' + { 12243, 30, 34, 38, 4, -33 }, // 0x6E 'n' + { 12371, 33, 35, 38, 3, -33 }, // 0x6F 'o' + { 12516, 32, 47, 38, 4, -33 }, // 0x70 'p' + { 12704, 32, 47, 38, 3, -33 }, // 0x71 'q' + { 12892, 21, 34, 25, 4, -33 }, // 0x72 'r' + { 12982, 31, 35, 35, 1, -33 }, // 0x73 's' + { 13118, 19, 45, 21, 1, -43 }, // 0x74 't' + { 13225, 30, 34, 38, 4, -32 }, // 0x75 'u' + { 13353, 34, 33, 35, 0, -32 }, // 0x76 'v' + { 13494, 49, 33, 49, 0, -32 }, // 0x77 'w' + { 13697, 34, 33, 35, 0, -32 }, // 0x78 'x' + { 13838, 34, 47, 35, 0, -32 }, // 0x79 'y' + { 14038, 29, 33, 32, 1, -32 }, // 0x7A 'z' + { 14158, 21, 60, 25, 2, -45 }, // 0x7B '{' + { 14316, 7, 59, 18, 5, -44 }, // 0x7C '|' + { 14368, 21, 60, 25, 1, -45 }, // 0x7D '}' + { 14526, 33, 12, 37, 2, -27 }, // 0x7E '~' + { 14576, 31, 39, 47, 8, -38 }, // 0x7F + { 14728, 31, 39, 47, 8, -38 }, // 0x80 + { 14880, 31, 39, 47, 8, -38 }, // 0x81 + { 15032, 31, 39, 47, 8, -38 }, // 0x82 + { 15184, 31, 39, 47, 8, -38 }, // 0x83 + { 15336, 31, 39, 47, 8, -38 }, // 0x84 + { 15488, 31, 39, 47, 8, -38 }, // 0x85 + { 15640, 31, 39, 47, 8, -38 }, // 0x86 + { 15792, 31, 39, 47, 8, -38 }, // 0x87 + { 15944, 31, 39, 47, 8, -38 }, // 0x88 + { 16096, 31, 39, 47, 8, -38 }, // 0x89 + { 16248, 31, 39, 47, 8, -38 }, // 0x8A + { 16400, 31, 39, 47, 8, -38 }, // 0x8B + { 16552, 31, 39, 47, 8, -38 }, // 0x8C + { 16704, 31, 39, 47, 8, -38 }, // 0x8D + { 16856, 31, 39, 47, 8, -38 }, // 0x8E + { 17008, 31, 39, 47, 8, -38 }, // 0x8F + { 17160, 31, 39, 47, 8, -38 }, // 0x90 + { 17312, 31, 39, 47, 8, -38 }, // 0x91 + { 17464, 31, 39, 47, 8, -38 }, // 0x92 + { 17616, 31, 39, 47, 8, -38 }, // 0x93 + { 17768, 31, 39, 47, 8, -38 }, // 0x94 + { 17920, 31, 39, 47, 8, -38 }, // 0x95 + { 18072, 31, 39, 47, 8, -38 }, // 0x96 + { 18224, 31, 39, 47, 8, -38 }, // 0x97 + { 18376, 31, 39, 47, 8, -38 }, // 0x98 + { 18528, 31, 39, 47, 8, -38 }, // 0x99 + { 18680, 31, 39, 47, 8, -38 }, // 0x9A + { 18832, 31, 39, 47, 8, -38 }, // 0x9B + { 18984, 31, 39, 47, 8, -38 }, // 0x9C + { 19136, 31, 39, 47, 8, -38 }, // 0x9D + { 19288, 31, 39, 47, 8, -38 }, // 0x9E + { 19440, 31, 39, 47, 8, -38 }, // 0x9F + { 19592, 0, 0, 18, 0, 1 }, // 0xA0 + { 19592, 9, 46, 21, 6, -32 }, // 0xA1 + { 19644, 30, 58, 35, 3, -44 }, // 0xA2 + { 19862, 34, 47, 35, 0, -45 }, // 0xA3 + { 20062, 32, 33, 35, 1, -38 }, // 0xA4 + { 20194, 35, 45, 35, 0, -44 }, // 0xA5 + { 20391, 7, 59, 18, 5, -44 }, // 0xA6 + { 20443, 31, 59, 35, 2, -45 }, // 0xA7 + { 20672, 21, 8, 21, 0, -44 }, // 0xA8 + { 20693, 47, 47, 46, 0, -45 }, // 0xA9 + { 20970, 21, 23, 23, 1, -45 }, // 0xAA + { 21031, 29, 29, 35, 3, -30 }, // 0xAB + { 21137, 31, 22, 37, 3, -32 }, // 0xAC + { 21223, 17, 8, 21, 4, -19 }, // 0xAD + { 21240, 47, 47, 46, 0, -45 }, // 0xAE + { 21517, 36, 7, 35, -1, -54 }, // 0xAF + { 21549, 19, 19, 25, 3, -45 }, // 0xB0 + { 21595, 31, 43, 35, 2, -42 }, // 0xB1 + { 21762, 18, 23, 21, 1, -45 }, // 0xB2 + { 21814, 19, 23, 21, 1, -45 }, // 0xB3 + { 21869, 14, 9, 21, 6, -44 }, // 0xB4 + { 21885, 30, 46, 36, 3, -32 }, // 0xB5 + { 22058, 35, 57, 35, 0, -44 }, // 0xB6 + { 22308, 9, 9, 21, 6, -26 }, // 0xB7 + { 22319, 17, 11, 21, 1, 1 }, // 0xB8 + { 22343, 12, 23, 21, 3, -45 }, // 0xB9 + { 22378, 21, 23, 23, 1, -45 }, // 0xBA + { 22439, 29, 29, 35, 3, -30 }, // 0xBB + { 22545, 49, 46, 53, 3, -44 }, // 0xBC + { 22827, 48, 47, 53, 3, -45 }, // 0xBD + { 23109, 51, 47, 53, 1, -45 }, // 0xBE + { 23409, 33, 47, 38, 3, -32 }, // 0xBF + { 23603, 45, 58, 46, 0, -57 }, // 0xC0 + { 23930, 45, 58, 46, 0, -57 }, // 0xC1 + { 24257, 45, 58, 46, 0, -57 }, // 0xC2 + { 24584, 45, 57, 46, 0, -56 }, // 0xC3 + { 24905, 45, 57, 46, 0, -56 }, // 0xC4 + { 25226, 45, 54, 46, 0, -53 }, // 0xC5 + { 25530, 63, 45, 63, -3, -44 }, // 0xC6 + { 25885, 39, 57, 46, 3, -45 }, // 0xC7 + { 26163, 34, 58, 42, 5, -57 }, // 0xC8 + { 26410, 34, 58, 42, 5, -57 }, // 0xC9 + { 26657, 34, 58, 42, 5, -57 }, // 0xCA + { 26904, 34, 57, 42, 5, -56 }, // 0xCB + { 27147, 14, 58, 18, -1, -57 }, // 0xCC + { 27249, 14, 58, 18, 4, -57 }, // 0xCD + { 27351, 21, 58, 18, -1, -57 }, // 0xCE + { 27504, 21, 57, 18, -2, -56 }, // 0xCF + { 27654, 42, 45, 46, 0, -44 }, // 0xD0 + { 27891, 35, 57, 46, 5, -56 }, // 0xD1 + { 28141, 43, 59, 49, 3, -57 }, // 0xD2 + { 28459, 43, 59, 49, 3, -57 }, // 0xD3 + { 28777, 43, 59, 49, 3, -57 }, // 0xD4 + { 29095, 43, 58, 49, 3, -56 }, // 0xD5 + { 29407, 43, 58, 49, 3, -56 }, // 0xD6 + { 29719, 30, 30, 37, 3, -36 }, // 0xD7 + { 29832, 45, 50, 49, 2, -47 }, // 0xD8 + { 30114, 35, 59, 46, 5, -57 }, // 0xD9 + { 30373, 35, 59, 46, 5, -57 }, // 0xDA + { 30632, 35, 59, 46, 5, -57 }, // 0xDB + { 30891, 35, 58, 46, 5, -56 }, // 0xDC + { 31145, 42, 58, 42, 0, -57 }, // 0xDD + { 31450, 34, 45, 42, 5, -44 }, // 0xDE + { 31642, 32, 47, 38, 4, -45 }, // 0xDF + { 31830, 31, 47, 35, 2, -45 }, // 0xE0 + { 32013, 31, 47, 35, 2, -45 }, // 0xE1 + { 32196, 31, 47, 35, 2, -45 }, // 0xE2 + { 32379, 31, 46, 35, 2, -44 }, // 0xE3 + { 32558, 31, 46, 35, 2, -44 }, // 0xE4 + { 32737, 31, 50, 35, 2, -48 }, // 0xE5 + { 32931, 50, 35, 56, 3, -33 }, // 0xE6 + { 33150, 30, 45, 35, 3, -33 }, // 0xE7 + { 33319, 31, 47, 35, 2, -45 }, // 0xE8 + { 33502, 31, 47, 35, 2, -45 }, // 0xE9 + { 33685, 31, 47, 35, 2, -45 }, // 0xEA + { 33868, 31, 46, 35, 2, -44 }, // 0xEB + { 34047, 14, 46, 18, -1, -45 }, // 0xEC + { 34128, 14, 46, 18, 4, -45 }, // 0xED + { 34209, 21, 46, 18, -2, -45 }, // 0xEE + { 34330, 21, 45, 18, -2, -44 }, // 0xEF + { 34449, 33, 46, 38, 3, -44 }, // 0xF0 + { 34639, 30, 45, 38, 4, -44 }, // 0xF1 + { 34808, 33, 47, 38, 3, -45 }, // 0xF2 + { 35002, 33, 47, 38, 3, -45 }, // 0xF3 + { 35196, 33, 47, 38, 3, -45 }, // 0xF4 + { 35390, 33, 46, 38, 3, -44 }, // 0xF5 + { 35580, 33, 46, 38, 3, -44 }, // 0xF6 + { 35770, 31, 32, 35, 2, -37 }, // 0xF7 + { 35894, 33, 38, 38, 3, -35 }, // 0xF8 + { 36051, 30, 47, 38, 4, -45 }, // 0xF9 + { 36228, 30, 47, 38, 4, -45 }, // 0xFA + { 36405, 30, 47, 38, 4, -45 }, // 0xFB + { 36582, 30, 46, 38, 4, -44 }, // 0xFC + { 36755, 34, 60, 35, 0, -45 }, // 0xFD + { 37010, 32, 58, 38, 4, -44 }, // 0xFE + { 37242, 34, 59, 35, 0, -44 } }; // 0xFF + +const GFXfont myFont32pt8b PROGMEM = { + (uint8_t *)myFont32pt8bBitmaps, + (GFXglyph *)myFont32pt8bGlyphs, + 0x20, 0xFF, 72 }; + +// Approx. 39068 bytes diff --git a/library.json b/library.json index ac3228d..7b1724d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.2", + "version": "1.4.3", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 9de9fc2..707afde 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.2 +version=1.4.3 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 0b8e9572034d4527dd23b442a6fa814430bdc2be Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 8 Feb 2019 18:50:03 +0000 Subject: [PATCH 78/94] Remove screen server code --- examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino index b26f11e..67deb9a 100644 --- a/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino +++ b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino @@ -45,7 +45,6 @@ #include "SPI.h" #include "TFT_eSPI.h" -#include "TFT_eFEX.h" // The custom font file attached to this sketch must be included #include "MyFont.h" @@ -58,7 +57,6 @@ // Use hardware SPI TFT_eSPI tft = TFT_eSPI(); -TFT_eFEX fex = TFT_eFEX(&tft); void setup(void) { @@ -111,7 +109,7 @@ void loop() { tft.setFreeFont(MYFONT32); // Select the font tft.drawString(TEST_TEXT, 160, 140, GFXFF); // Print the test text in the custom font delay(2000); -fex.screenServer(); + // Setting textDatum does nothing when using tft.print tft.fillScreen(TFT_BLUE); // Clear screen tft.setCursor(0,60); // To be compatible with Adafruit_GFX the cursor datum is always bottom left From b5a74a016ae7c04f759e6a8ed44ef9bbe5adf26f Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 10 Feb 2019 01:25:34 +0000 Subject: [PATCH 79/94] Fix #301 --- TFT_eSPI.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 512bedc..b1b0cb0 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -389,6 +389,7 @@ #if !defined (ESP32_PARALLEL) + // Read from display using SPI or software SPI #if defined (ESP8266) && defined (TFT_SDA_READ) // Use a bit banged function call for ESP8266 and bi-directional SDA pin @@ -398,6 +399,12 @@ // Use a SPI read transfer #define tft_Read_8() spi.transfer(0) #endif + + // Make sure TFT_MISO is defined if not used to avoid an error message + #ifndef TFT_MISO + #define TFT_MISO -1 + #endif + #endif From 6a42e4b16d3f44e2665c85e5f010b3fca74956e7 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 10 Feb 2019 11:06:40 +0000 Subject: [PATCH 80/94] Remove debug lines to fix rendering part of #303 --- TFT_eSPI.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 5e24cd8..4dc8679 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4598,12 +4598,10 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 } else #endif -Serial.print("sumX="); - while (*string) { - sumX += drawChar(*(string++), poX+sumX, poY, font); - Serial.print(sumX); - } -Serial.println(); + { + while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); + } + //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Switch on debugging for the padding areas //#define PADDING_DEBUG From 1e1e888fa0767e3e72c93950921bb5ed281fba2c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 10 Feb 2019 21:36:40 +0000 Subject: [PATCH 81/94] Support extended font formats Adafruit_GFX font support extended to Unidode Basic Multilingual Plane Print stream deocdes UTF-8 Smooth font ascent and descent (affects line spacing) changed to rely on metrics provided by Processing IDE (issue #303) Bug fix for font rendering with no background on RLE native fonts --- Extensions/Smooth_font.cpp | 17 ++- Extensions/Smooth_font.h | 6 - Extensions/Sprite.cpp | 43 +++--- Extensions/Sprite.h | 2 +- Fonts/GFXFF/gfxfont.h | 4 +- TFT_eSPI.cpp | 113 ++++++++------- TFT_eSPI.h | 7 +- .../Create_font/Create_font.pde | 130 +++++++++++------- .../Read_User_Setup/Read_User_Setup.ino | 4 +- library.json | 2 +- library.properties | 2 +- 11 files changed, 188 insertions(+), 142 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 855aa62..8d7628f 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -97,7 +97,7 @@ void TFT_eSPI::loadFont(String fontName) gFont.ascent = (uint16_t)readInt32(); // top of "d" gFont.descent = (uint16_t)readInt32(); // bottom of "p" - // These next gFont values will be updated when the Metrics are fetched + // These next gFont values might be updated when the Metrics are fetched gFont.maxAscent = gFont.ascent; // Determined from metrics gFont.maxDescent = gFont.descent; // Determined from metrics gFont.yAdvance = gFont.ascent + gFont.descent; @@ -147,11 +147,19 @@ void TFT_eSPI::loadMetrics(uint16_t gCount) gdX[gNum] = (int8_t)readInt32(); // x delta from cursor readInt32(); // ignored - // Different glyph sets have different ascent values not always based on "d", so get maximum glyph ascent + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gHeight = "); Serial.println(gHeight[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gWidth = "); Serial.println(gWidth[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gxAdvance = "); Serial.println(gxAdvance[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdY = "); Serial.println(gdY[gNum]); + + // Different glyph sets have different ascent values not always based on "d", so we could get + // the maximum glyph ascent by checking all characters. BUT this method can generate bad values + // for non-existant glyphs, so we will reply on processing for the value and disable this code for now... + /* if (gdY[gNum] > gFont.maxAscent) { - // Avoid UTF coding values and characters that tend to give duff values - if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF)) + // Try to avoid UTF coding values and characters that tend to give duff values + if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0x7F)) || (gUnicode[gNum] > 0xA0)) { gFont.maxAscent = gdY[gNum]; #ifdef SHOW_ASCENT_DESCENT @@ -159,6 +167,7 @@ void TFT_eSPI::loadMetrics(uint16_t gCount) #endif } } + */ // Different glyph sets have different descent values not always based on "p", so get maximum glyph descent if (((int16_t)gHeight[gNum] - (int16_t)gdY[gNum]) > gFont.maxDescent) diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h index 2c7faa2..1bc9fd2 100644 --- a/Extensions/Smooth_font.h +++ b/Extensions/Smooth_font.h @@ -8,9 +8,6 @@ void unloadFont( void ); bool getUnicodeIndex(uint16_t unicode, uint16_t *index); - uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining); - uint16_t decodeUTF8(uint8_t c); - uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); virtual void drawGlyph(uint16_t code); @@ -44,9 +41,6 @@ fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 }; String _gFontFilename; - uint8_t decoderState = 0; // UTF8 decoder state - uint16_t decoderBuffer; // Unicode code-point buffer - bool fontLoaded = false; // Flags when a anti-aliased font is loaded private: diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 6bc58b2..3782775 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -1312,13 +1312,16 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t *************************************************************************************x*/ size_t TFT_eSprite::write(uint8_t utf8) { + uint16_t uniCode = decodeUTF8(utf8); + + if (!uniCode) return 1; + if (utf8 == '\r') return 1; #ifdef SMOOTH_FONT if(this->fontLoaded) { - uint16_t unicode = decodeUTF8(utf8); - if (unicode < 32 && utf8 != '\n') return 1; + if (uniCode < 32 && utf8 != '\n') return 1; //fontFile = SPIFFS.open( _gFontFilename, "r" ); //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); @@ -1330,7 +1333,8 @@ size_t TFT_eSprite::write(uint8_t utf8) //} //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); - drawGlyph(unicode); + drawGlyph(uniCode); + //fontFile.close(); return 1; } @@ -1338,10 +1342,8 @@ size_t TFT_eSprite::write(uint8_t utf8) if (!_created ) return 1; - - uint8_t uniCode = utf8; // Work with a copy - if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (utf8 < 32) return 1; + if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (uniCode < 32) return 1; uint16_t width = 0; uint16_t height = 0; @@ -1362,7 +1364,7 @@ size_t TFT_eSprite::write(uint8_t utf8) if (textfont == 2) { if (utf8 > 127) return 1; - // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) + width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; // Font 2 is rendered in whole byte widths so we must allow for this @@ -1380,7 +1382,6 @@ size_t TFT_eSprite::write(uint8_t utf8) { if (utf8 > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements - // A tad slower than above but this is not significant and is more convenient for the RLE fonts width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); height= pgm_read_byte( &fontdata[textfont].height ); } @@ -1420,15 +1421,14 @@ size_t TFT_eSprite::write(uint8_t utf8) } // Custom GFX font else { - if(utf8 == '\n') { this->cursor_x = 0; this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } else { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; - if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; + if (uniCode > pgm_read_word(&gfxFont->last )) return 1; + if (uniCode < pgm_read_word(&gfxFont->first)) return 1; - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + uint8_t c2 = uniCode - pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); @@ -1456,7 +1456,7 @@ size_t TFT_eSprite::write(uint8_t utf8) ** Function name: drawChar ** Description: draw a single character in the Adafruit GLCD or freefont *************************************************************************************x*/ -void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) +void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size) { if (!_created ) return; @@ -1466,6 +1466,7 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color ((y + 8 * size - 1) < 0)) // Clip top return; + if (c < 32) return; #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> #ifdef LOAD_GFXFF @@ -1534,15 +1535,15 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color #ifdef LOAD_GFXFF // Filter out bad characters not present in font - if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) { //>>>>>>>>>>>>>>>>>>>>>>>>>>> - c -= pgm_read_byte(&gfxFont->first); + c -= pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); - uint16_t bo = pgm_read_word(&glyph->bitmapOffset); + uint32_t bo = pgm_read_word(&glyph->bitmapOffset); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); //xa = pgm_read_byte(&glyph->xAdvance); @@ -1597,15 +1598,19 @@ void TFT_eSprite::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color ** Function name: drawChar ** Description: draw a unicode onto the screen *************************************************************************************x*/ + // Any UTF-8 decoding must be done before calling drawChar() int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) { return drawChar(uniCode, x, y, textfont); } + // Any UTF-8 decoding must be done before calling drawChar() int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { if (!_created ) return 0; + if (!uniCode) return 0; + if (font==1) { #ifdef LOAD_GLCD @@ -1630,9 +1635,9 @@ int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t fo } else { - if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) + if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) { - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); return pgm_read_byte(&glyph->xAdvance) * textsize; } diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h index 2bf800c..5dea24e 100644 --- a/Extensions/Sprite.h +++ b/Extensions/Sprite.h @@ -31,7 +31,7 @@ class TFT_eSprite : public TFT_eSPI { void drawPixel(int32_t x, int32_t y, uint32_t color); - void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), + void drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), fillSprite(uint32_t color), diff --git a/Fonts/GFXFF/gfxfont.h b/Fonts/GFXFF/gfxfont.h index eae3997..cd2bccc 100644 --- a/Fonts/GFXFF/gfxfont.h +++ b/Fonts/GFXFF/gfxfont.h @@ -12,7 +12,7 @@ #ifdef LOAD_GFXFF typedef struct { // Data stored PER GLYPH - uint16_t bitmapOffset; // Pointer into GFXfont->bitmap + uint32_t bitmapOffset; // Pointer into GFXfont->bitmap uint8_t width, height; // Bitmap dimensions in pixels uint8_t xAdvance; // Distance to advance cursor (x axis) int8_t xOffset, yOffset; // Dist from cursor pos to UL corner @@ -21,7 +21,7 @@ typedef struct { // Data stored PER GLYPH typedef struct { // Data stored for FONT AS A WHOLE: uint8_t *bitmap; // Glyph bitmaps, concatenated GFXglyph *glyph; // Glyph array - uint8_t first, last; // ASCII extents + uint16_t first, last; // ASCII extents uint8_t yAdvance; // Newline distance (y axis) } GFXfont; diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 4dc8679..9c4fc66 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -2272,21 +2272,22 @@ int16_t TFT_eSPI::textWidth(const char *string) int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) { - int32_t str_width = 0; + int32_t str_width = 0; + uint16_t uniCode = 0; #ifdef SMOOTH_FONT if(fontLoaded) { while (*string) { - uint16_t unicode = decodeUTF8(*string++); - if (unicode) + uniCode = decodeUTF8(*string++); + if (uniCode) { - if (unicode == 0x20) str_width += gFont.spaceWidth; + if (uniCode == 0x20) str_width += gFont.spaceWidth; else { uint16_t gNum = 0; - bool found = getUnicodeIndex(unicode, &gNum); + bool found = getUnicodeIndex(uniCode, &gNum); if (found) { if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; @@ -2302,18 +2303,15 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) } #endif - unsigned char uniCode; - char *widthtable; - if (font>1 && font<9) { - widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop + char *widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop while (*string) { uniCode = *(string++); if (uniCode > 31 && uniCode < 128) - str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subract 32 from uniCode + str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subtract 32 from uniCode else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width } } @@ -2326,9 +2324,9 @@ int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) while (*string) { uniCode = decodeUTF8(*string++); - if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + if ((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last ))) { - uniCode -= pgm_read_byte(&gfxFont->first); + uniCode -= pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); // If this is not the last character or is a digit then use xAdvance if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance); @@ -2393,7 +2391,7 @@ int16_t TFT_eSPI::fontHeight(void) ** Function name: drawChar ** Description: draw a single character in the Adafruit GLCD font ***************************************************************************************/ -void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) +void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size) { if ((x >= _width) || // Clip right (y >= _height) || // Clip bottom @@ -2498,17 +2496,17 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #ifdef LOAD_GFXFF // Filter out bad characters not present in font - if ((c >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) { spi_begin(); inTransaction = true; //>>>>>>>>>>>>>>>>>>>>>>>>>>> - c -= pgm_read_byte(&gfxFont->first); + c -= pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); - uint16_t bo = pgm_read_word(&glyph->bitmapOffset); + uint32_t bo = pgm_read_word(&glyph->bitmapOffset); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); //xa = pgm_read_byte(&glyph->xAdvance); @@ -3991,18 +3989,18 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) ***************************************************************************************/ size_t TFT_eSPI::write(uint8_t utf8) { + uint16_t uniCode = decodeUTF8(utf8); + + if (!uniCode) return 1; + if (utf8 == '\r') return 1; #ifdef SMOOTH_FONT if(fontLoaded) { - uint16_t unicode = decodeUTF8(utf8); - - //Serial.print("UniCode="); Serial.println(unicode); + //Serial.print("UniCode="); Serial.println(uniCode); //Serial.print("UTF8 ="); Serial.println(utf8); - if (!unicode) return 1; - //fontFile = SPIFFS.open( _gFontFilename, "r" ); //if(!fontFile) @@ -4011,16 +4009,15 @@ size_t TFT_eSPI::write(uint8_t utf8) // return 1; //} - drawGlyph(unicode); + drawGlyph(uniCode); //fontFile.close(); return 1; } #endif - uint8_t uniCode = utf8; // Work with a copy - if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors - else if (utf8 < 32) return 1; + if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (uniCode < 32) return 1; uint16_t width = 0; uint16_t height = 0; @@ -4040,8 +4037,8 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { - if (utf8 > 127) return 1; - // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) + if (uniCode > 127) return 1; + width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; // Font 2 is rendered in whole byte widths so we must allow for this @@ -4057,9 +4054,8 @@ size_t TFT_eSPI::write(uint8_t utf8) { if ((textfont>2) && (textfont<9)) { - if (utf8 > 127) return 1; + if (uniCode > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements - // A tad slower than above but this is not significant and is more convenient for the RLE fonts width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); height= pgm_read_byte( &fontdata[textfont].height ); } @@ -4098,18 +4094,15 @@ size_t TFT_eSPI::write(uint8_t utf8) } // Custom GFX font else { - uniCode = (uint8_t)decodeUTF8(utf8); - if (!uniCode) return 1; - if(utf8 == '\n') { cursor_x = 0; cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } else { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last )) return 1; - if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 1; + if (uniCode > pgm_read_word(&gfxFont->last )) return 1; + if (uniCode < pgm_read_word(&gfxFont->first)) return 1; - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); uint8_t w = pgm_read_byte(&glyph->width), h = pgm_read_byte(&glyph->height); @@ -4136,17 +4129,17 @@ size_t TFT_eSPI::write(uint8_t utf8) /*************************************************************************************** ** Function name: drawChar -** Description: draw a Unicode onto the screen +** Description: draw a Unicode glyph onto the screen ***************************************************************************************/ -int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y) + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) { - return drawChar(utf8, x, y, textfont); + return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { - - uint16_t uniCode = decodeUTF8(utf8); if (!uniCode) return 0; if (font==1) @@ -4173,9 +4166,9 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) } else { - if((uniCode >= pgm_read_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) + if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) { - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); return pgm_read_byte(&glyph->xAdvance) * textsize; } @@ -4197,7 +4190,6 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) #ifdef LOAD_FONT2 if (font == 2) { - // This is faster than using the fontdata structure flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); width = pgm_read_byte(widtbl_f16 + uniCode); height = chr_hgt_f16; @@ -4211,7 +4203,6 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) { if ((font>2) && (font<9)) { - // This is slower than above but is more convenient for the RLE fonts flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); height= pgm_read_byte( &fontdata[font].height ); @@ -4309,6 +4300,7 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) // Font is not 2 and hence is RLE encoded { spi_begin(); + inTransaction = true; w *= height; // Now w is total number of pixels in the character if ((textsize != 1) || (textcolor == textbgcolor)) { @@ -4360,6 +4352,7 @@ int16_t TFT_eSPI::drawChar(uint16_t utf8, int32_t x, int32_t y, uint8_t font) } } + inTransaction = false; spi_end(); } else // Text colour != background && textsize = 1 @@ -4442,7 +4435,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) return drawString(string, poX, poY, textfont); } -// With font number +// With font number. Note: font number is over-ridden if a smooth font is loaded int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) { int16_t sumX = 0; @@ -4553,15 +4546,15 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 { cheight = (glyph_ab + glyph_bb) * textsize; // Get the offset for the first character only to allow for negative offsets - uint8_t c2 = 0; + uint16_t c2 = 0; uint16_t len = strlen(string); uint16_t n = 0; while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n); - if((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) + if((c2 >= pgm_read_word(&gfxFont->first)) && (c2 <= pgm_read_word(&gfxFont->last) )) { - c2 -= pgm_read_byte(&gfxFont->first); + c2 -= pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); xo = pgm_read_byte(&glyph->xOffset) * textsize; // Adjust for negative xOffset @@ -4576,6 +4569,9 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 } #endif + uint16_t len = strlen(string); + uint16_t n = 0; + #ifdef SMOOTH_FONT if(fontLoaded) { @@ -4584,14 +4580,13 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 //drawLine(poX, poY - 5, poX, poY + 5, TFT_GREEN); //fontFile = SPIFFS.open( _gFontFilename, "r"); if(!fontFile) return 0; - uint16_t len = strlen(string); - uint16_t n = 0; + setCursor(poX, poY); while (n < len) { - uint16_t unicode = decodeUTF8((uint8_t*)string, &n, len - n); - drawGlyph(unicode); + uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n); + drawGlyph(uniCode); } sumX += cwidth; //fontFile.close(); @@ -4599,7 +4594,11 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 else #endif { - while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); + while (n < len) + { + uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n); + sumX += drawChar(uniCode, poX+sumX, poY, font); + } } //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv @@ -4669,7 +4668,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 #endif //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -return sumX; +return sumX + poX; } @@ -4782,7 +4781,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t // No chance of overflow from here on // Get integer part - unsigned long temp = (unsigned long)floatNumber; + uint32_t temp = (uint32_t)floatNumber; // Put integer part into array ltoa(temp, str + ptr, 10); @@ -4830,7 +4829,7 @@ void TFT_eSPI::setFreeFont(const GFXfont *f) glyph_ab = 0; glyph_bb = 0; - uint8_t numChars = pgm_read_byte(&gfxFont->last) - pgm_read_byte(&gfxFont->first); + uint16_t numChars = pgm_read_word(&gfxFont->last) - pgm_read_word(&gfxFont->first); // Find the biggest above and below baseline offsets for (uint8_t c = 0; c < numChars; c++) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index b1b0cb0..55110f0 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -668,7 +668,7 @@ class TFT_eSPI : public Print { // These are virtual so the TFT_eSprite class can override them with sprite specific functions virtual void drawPixel(int32_t x, int32_t y, uint32_t color), - drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), + drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), @@ -813,6 +813,8 @@ class TFT_eSPI : public Print { void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead void endWrite(void); // End SPI transaction + uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining); + uint16_t decodeUTF8(uint8_t c); size_t write(uint8_t); #ifdef TFT_SDA_READ @@ -838,6 +840,9 @@ class TFT_eSPI : public Print { int16_t _xpivot; // x pivot point coordinate int16_t _ypivot; // x pivot point coordinate + uint8_t decoderState = 0; // UTF8 decoder state + uint16_t decoderBuffer; // Unicode code-point buffer + private: inline void spi_begin() __attribute__((always_inline)); diff --git a/Tools/Create_Smooth_Font/Create_font/Create_font.pde b/Tools/Create_Smooth_Font/Create_font/Create_font.pde index 1363b6b..6832248 100644 --- a/Tools/Create_Smooth_Font/Create_font/Create_font.pde +++ b/Tools/Create_Smooth_Font/Create_font/Create_font.pde @@ -1,6 +1,8 @@ // This is a Processing sketch, see https://processing.org/ to download the IDE -// Select the character range in the user configure section starting at line 100 +// Select the font, size and character ranges in the user configuration section +// of this sketch, which starts at line 120. Instructions start at line 50. + /* Software License Agreement (FreeBSD License) @@ -36,47 +38,61 @@ Software License Agreement (FreeBSD License) //////////////////////////////////////////////////////////////////////////////////////////////// - // This is a processing sketch to create font files for the TFT_eSPI library: // https://github.com/Bodmer/TFT_eSPI -// Coded by Bodmer January 2018 +// Coded by Bodmer January 2018, updated 10/2/19 +// Version 0.8 -// See comments below in code for specifying the font parameters -// (point size, unicode blocks to include etc). Ranges of characers or -// specific individual unicodes can be included in the created font file/ +// >>>>>>>>>>>>>>>>>>>> INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< + +// See comments below in code for specifying the font parameters (point size, +// unicode blocks to include etc). Ranges of characters (glyphs) and specific +// individual glyphs can be included in the created "*.vlw" font file. // Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to -// see that folder. +// see that folder location. -// 16 bit unicodes in the range 0x0000 - 0xFFFF are supported. +// 16 bit Unicode point codes in the range 0x0000 - 0xFFFF are supported. +// Codes 0-31 are control codes such as "tab" and "carraige return" etc. +// and 32 is a "space", these should NOT be included. // The sketch will convert True Type (a .ttf or .otf file) file stored in the -// sketches "Data" folder as well as your computers system fonts. +// sketches "Data" folder as well as your computers' system fonts. -// To maximise rendering performance only include the characters you will use. -// Characters at the start of the file will render faster than those at the end. +// To maximise rendering performance and the memory consumed only include the characters +// you will use. Characters at the start of the file will render faster than those at +// the end due to the buffering and file seeking overhead. + +// The inclusion of "non-existant" characters in a font may give unpredicatable results +// when rendering with the TFT_eSPI library. The Processing sketch window that pops up +// to show the font characters will print "boxes" (also known as Tofu!) for non existant +// characters. // Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory // using the Arduino IDE plugin detailed here: // https://github.com/esp8266/arduino-esp8266fs-plugin // https://github.com/me-no-dev/arduino-esp32fs-plugin -// The sketch list all the available PC fonts to the console, you may need to increase -// console line count (in preferences.txt) to stop some fonts scrolling out of view. +// When the sketch is run it will generate a file called "System_Font_List.txt" in the +// sketch "FontFiles" folder, press Ctrl+K to see it. Open the file in a text editor to +// view it. This list provides the font reference number needed below to locate that +// font on your system. + +// The sketch also lists all the available system fonts to the console, you can increase +// the console line count (in preferences.txt) to stop some fonts scrolling out of view. // See link in File>Preferences to locate "preferences.txt" file. You must close // Processing then edit the file lines. If Processing is not closed first then the // edits will be overwritten by defaults! Edit "preferences.txt" as follows for -// 1000 lines, then save, then run Processing again: +// 3000 lines, then save, then run Processing again: + +// console.length=3000; // Line 4 in file +// console.scrollback.lines=3000; // Line 7 in file - /* - console.length=1000 // Line 4 in file - console.scrollback.lines=1000 // Line 7 in file - */ // Useful links: - /* +/* https://en.wikipedia.org/wiki/Unicode_font @@ -86,33 +102,39 @@ Software License Agreement (FreeBSD License) http://savannah.gnu.org/projects/freefont/ http://www.google.com/get/noto/ - + https://github.com/Bodmer/TFT_eSPI https://github.com/esp8266/arduino-esp8266fs-plugin https://github.com/me-no-dev/arduino-esp32fs-plugin - */ -//////////////////////////////////////////////////////////////////////////////////////////////// + >>>>>>>>>>>>>>>>>>>> END OF INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< */ -import java.awt.Desktop; + +import java.awt.Desktop; // Required to allow sketch to open file windows + + +//////////////////////////////////////////////////////////////////////////////////////////////// // >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<< +// Use font number or name, -1 for fontNumber means use fontName below, a value >=0 means use system font number from list. +// When the sketch is run it will generate a file called "systemFontList.txt" in the sketch folder, press Ctrl+K to see it. +// Open the "systemFontList.txt" in a text editor to view the font files and reference numbers for your system. -// Use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts +int fontNumber = -1; // << Use [Number] in brackets from the fonts listed. + +// OR use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts // the font numbers are listed when the sketch is run. -// | 1 2 | Maximum filename size for SPIFFS is 32 including leading / +// | 1 2 | Maximum filename size for SPIFFS is 31 including leading / // 1234567890123456789012345 and added point size and .vlw extension, so max is 25 -String fontName = "Final-Frontier"; //Manually crop the filename length later after creation if needed - -String fontType = ".ttf"; //SPIFFS does not accept underscore in filename! +String fontName = "Final-Frontier"; // Manually crop the filename length later after creation if needed + // Note: SPIFFS does NOT accept underscore in a filename! +String fontType = ".ttf"; //String fontType = ".otf"; -// Use font number instead of name, -1 means use name above, or a value >=0 means use system font number from list. -int fontNumber = -1; // << Use [Number] in brackets from the fonts listed in console window -// Define the font size in points for the created font file -int fontSize = 28; +// Define the font size in points for the TFT_eSPI font file +int fontSize = 20; // Font size to use in the Processing sketch display window that pops up (can be different to above) int displayFontSize = 28; @@ -125,7 +147,7 @@ int displayFontSize = 28; static final int[] unicodeBlocks = { // The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block // Remove // at start of lines below to include that unicode block, different code ranges can also be specified by - // editting the start and end of range values. Multiple lines from the list below can be included, limited only by + // editting the start and end-of-range values. Multiple lines from the list below can be included, limited only by // the final font file size! // Block range, //Block name, Code points, Assigned characters, Scripts @@ -298,20 +320,20 @@ static final int[] unicodeBlocks = { //0x0061, 0x007A, //Example custom range (Lower case a-z) }; -// Here we specify specific individual Unicodes to be included (appended at end of selected range) +// Here we specify particular individual Unicodes to be included (appended at end of selected range) static final int[] specificUnicodes = { // Commonly used codes, add or remove // in next line // 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω € // Numbers and characters for showing time, change next line to //* to use - /* +/* 0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m 0x0070, // p - //*/ + //*/ - // More characters, change next line to //* to use + // More characters for TFT_eSPI test sketches, change next line to //* to use /* 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D, 0x010E, 0x010F, 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B, @@ -337,8 +359,8 @@ static final int[] specificUnicodes = { //*/ }; - // >>>>>>>>>> USER CONFIGURED PARAMETERS END HERE <<<<<<<<<< + //////////////////////////////////////////////////////////////////////////////////////////////// // Variable to hold the inclusive Unicode range (16 bit values only for this sketch) @@ -347,7 +369,10 @@ int lastUnicode = 0; PFont myFont; +PrintWriter logOutput; + void setup() { + logOutput = createWriter("FontFiles/System_Font_List.txt"); size(1000, 800); @@ -355,6 +380,15 @@ void setup() { String[] fontList = PFont.list(); printArray(fontList); + // Save font list to file + for (int x = 0; x < fontList.length; x++) + { + logOutput.print("[" + x + "] "); + logOutput.println(fontList[x]); + } + logOutput.flush(); // Writes the remaining data to the file + logOutput.close(); // Finishes the file + // Set the fontName from the array number or the defined fontName if (fontNumber >= 0) { @@ -410,19 +444,19 @@ void setup() { } } - // loading the range specified + // loading the specific point codes for (int i = 0; i < specificUnicodes.length; i++) { charset[index] = Character.toChars(specificUnicodes[i])[0]; index++; } - - // Make font smooth + + // Make font smooth (anti-aliased) boolean smooth = true; // Create the font in memory myFont = createFont(fontName+fontType, displayFontSize, smooth, charset); - // Print a few characters to the sketch window + // Print characters to the sketch window fill(0, 0, 0); textFont(myFont); @@ -444,10 +478,10 @@ void setup() { int unicode = charset[index]; float cwidth = textWidth((char)unicode) + 2; if ( (x + cwidth) > (width - gapx) ) break; - - // Draw the letter to the screen + + // Draw the glyph to the screen text(new String(Character.toChars(unicode)), x, y); - + // Move cursor x += cwidth; // Increment the counter @@ -458,12 +492,12 @@ void setup() { } - // creating font + // creating font to save as a file PFont font; font = createFont(fontName+fontType, fontSize, smooth, charset); - println("Created font " + fontName + str(fontSize) + ".vlw"); + println("Created font " + fontName + str(fontSize) + ".vlw"); // creating file try { @@ -486,4 +520,4 @@ void setup() { catch(IOException e) { println("Doh! Failed to create the file"); } -} \ No newline at end of file +} diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index 1cf8f3f..d0a2f1f 100644 --- a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -41,8 +41,8 @@ void loop(void) { tft.getSetup(user); // Serial.printf("\n[code]\n"); -String ver = user.version; -Serial.println("TFT_eSPI ver = " + ver +"\n"); + +Serial.printf("TFT_eSPI ver = " + user.version) +"\n"); Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); #ifdef ESP8266 diff --git a/library.json b/library.json index 7b1724d..f3f1f04 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.3", + "version": "1.4.4", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 707afde..d65fa12 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.3 +version=1.4.4 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 35a402f6a8ad2b4830cb9825aadd4aee30af6bcc Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 10 Feb 2019 21:38:34 +0000 Subject: [PATCH 82/94] Raise issue in header --- TFT_eSPI.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 55110f0..93de46b 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -15,7 +15,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "1.4.2" +#define TFT_ESPI_VERSION "1.4.4" //#define ESP32 //Just used to test ESP32 options From e25da37fc5e0be90adba8f24757c14af55d03dd0 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 11 Feb 2019 21:09:38 +0000 Subject: [PATCH 83/94] Correct diagnostic example --- .../Test and diagnostics/Read_User_Setup/Read_User_Setup.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index d0a2f1f..fb49cf3 100644 --- a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -42,7 +42,7 @@ tft.getSetup(user); // Serial.printf("\n[code]\n"); -Serial.printf("TFT_eSPI ver = " + user.version) +"\n"); +Serial.print ("TFT_eSPI ver = " + user.version +"\n"); Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); #ifdef ESP8266 From dd4e184b53dd6bdfef1bdf0fde361caba987a2b0 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 13 Feb 2019 09:30:44 +0000 Subject: [PATCH 84/94] Remove obsolete comment --- User_Setup.h | 1 - 1 file changed, 1 deletion(-) diff --git a/User_Setup.h b/User_Setup.h index b581333..a963e3b 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -114,7 +114,6 @@ // // The NodeMCU D0 pin can be used for RST // -// See Section 2. below if DC or CS is connected to D0 // // Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin // If 5V is not available at a pin you can use 3.3V but backlight brightness From d6e07078f7c8a5486a783462c4a8d2955e6f9150 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 13 Feb 2019 09:32:13 +0000 Subject: [PATCH 85/94] Remove obsolete comment --- User_Setups/SetupX_Template.h | 1 - 1 file changed, 1 deletion(-) diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index 36a2372..aa5037a 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -114,7 +114,6 @@ // // The NodeMCU D0 pin can be used for RST // -// See Section 2. below if DC or CS is connected to D0 // // Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin // If 5V is not available at a pin you can use 3.3V but backlight brightness From 26d7e4038aaac3f1bf343d7ee3767fecb095a249 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Thu, 14 Feb 2019 00:32:10 +0000 Subject: [PATCH 86/94] Fix touch screen handler The touch screen handler was broken for the ESP8266 only. The library uses SPI write only configuration for ESP8266 so the SPI buffer can be recycled and it was left in write only mode. The library now switches back to read & write mode at the end of a transaction. --- Extensions/Touch.cpp | 14 +---- TFT_eSPI.cpp | 52 ++++++++++--------- TFT_eSPI.h | 2 +- .../Read_User_Setup/Read_User_Setup.ino | 2 +- library.json | 2 +- library.properties | 2 +- 6 files changed, 33 insertions(+), 41 deletions(-) diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 943d2e0..3f45102 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -16,11 +16,8 @@ ***************************************************************************************/ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ uint16_t tmp; - CS_H; spi_begin_touch(); - - T_CS_L; // Start YP sample request for x position, read 4 times and keep last sample spi.transfer(0xd0); // Start new YP conversion @@ -51,8 +48,6 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ *y = tmp; - T_CS_H; - spi_end_touch(); return true; @@ -63,20 +58,15 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ ** Description: read raw pressure on touchpad and return Z value. ***************************************************************************************/ uint16_t TFT_eSPI::getTouchRawZ(void){ - CS_H; spi_begin_touch(); - T_CS_L; - - // Calculate Z + // Z sample request int16_t tz = 0xFFF; spi.transfer(0xb0); // Start new Z1 conversion tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion tz -= spi.transfer16(0x00) >> 3; // Read Z2 - T_CS_H; - spi_end_touch(); return (uint16_t)tz; @@ -86,7 +76,7 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ ** Function name: validTouch ** Description: read validated position. Return false if not pressed. ***************************************************************************************/ -#define _RAWERR 10 // Deadband error allowed in successive position samples +#define _RAWERR 20 // Deadband error allowed in successive position samples uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ uint16_t x_tmp, y_tmp, x_tmp2, y_tmp2; diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 9c4fc66..36760b3 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -55,11 +55,17 @@ inline void TFT_eSPI::spi_begin(void){ #else CS_L; #endif +#ifdef ESP8266 + SPI1U = SPI1U_WRITE; +#endif } inline void TFT_eSPI::spi_end(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} + #ifdef ESP8266 + SPI1U = SPI1U_READ; + #endif #else if(!inTransaction) CS_H; #endif @@ -96,19 +102,33 @@ inline void TFT_eSPI::spi_end_read(void){ #if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(ESP32_PARALLEL) inline void TFT_eSPI::spi_begin_touch(void){ + CS_H; // Just in case it has been left low + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} #else spi.setFrequency(SPI_TOUCH_FREQUENCY); #endif + + #ifdef ESP8266 + SPI1U = SPI1U_READ; + #endif + + T_CS_L; } inline void TFT_eSPI::spi_end_touch(void){ + T_CS_H; + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} #else spi.setFrequency(SPI_FREQUENCY); #endif + + #ifdef ESP8266 + SPI1U = SPI1U_WRITE; + #endif } #endif @@ -325,6 +345,7 @@ void TFT_eSPI::init(uint8_t tc) #endif _booted = false; + spi_end(); } // end of: if just _booted // Toggle RST low to reset @@ -475,8 +496,6 @@ void TFT_eSPI::commandList (const uint8_t *addr) uint8_t numArgs; uint8_t ms; - spi_begin(); - numCommands = pgm_read_byte(addr++); // Number of commands to follow while (numCommands--) // For each command... @@ -497,7 +516,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) delay( (ms==255 ? 500 : ms) ); } } - spi_end(); + } @@ -2671,7 +2690,6 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Column addr set DC_C; - SPI1U = SPI1U_WRITE; SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET; @@ -2733,7 +2751,6 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Column addr set DC_C; - SPI1U = SPI1U_WRITE; SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET<<8; @@ -2779,7 +2796,6 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { //spi_begin(); // Must be called before setWimdow - SPI1U = SPI1U_WRITE; SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // Column addr set @@ -2912,7 +2928,6 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - spi_begin(); int32_t xe = xs + w - 1; int32_t ye = ys + h - 1; @@ -2930,7 +2945,6 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) // Column addr set DC_C; - SPI1U = SPI1U_WRITE; SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET; @@ -2971,14 +2985,13 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) while(SPI1CMD & SPIBUSY) {} DC_D; - //spi_end(); + } #else //ESP32 void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - spi_begin(); int32_t xe = xs + w - 1; int32_t ye = ys + h - 1; @@ -3017,7 +3030,6 @@ ye += rowstart; DC_D; - //spi_end(); } #endif @@ -3039,7 +3051,6 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) spi_begin(); - SPI1U = SPI1U_WRITE; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { @@ -3129,7 +3140,6 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) spi_begin(); - SPI1U = SPI1U_WRITE; SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // No need to send x if it has not changed (speeds things up) if (addr_col != x) { @@ -3398,7 +3408,6 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) uint32_t color[8]; - SPI1U = SPI1U_WRITE; SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO); @@ -4351,14 +4360,10 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) pc += line; } } - - inTransaction = false; - spi_end(); } else // Text colour != background && textsize = 1 // so use faster drawing of characters and background using block write { - //spi_begin(); setWindow(x, y, x + width - 1, y + height - 1); #ifdef RPI_WRITE_STROBE @@ -4398,9 +4403,9 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #endif } } - - spi_end(); } + inTransaction = false; + spi_end(); } // End of RLE font rendering #endif @@ -4616,6 +4621,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 { poX +=xo; // Adjust for negative offset start character poY -= glyph_ab * textsize; + sumX += poX; } #endif switch(padding) { @@ -4668,7 +4674,7 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8 #endif //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -return sumX + poX; +return sumX; } @@ -4896,8 +4902,6 @@ void writeBlock(uint16_t color, uint32_t repeat) uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; - SPI1U = SPI1U_WRITE; - SPI1W0 = color32; SPI1W1 = color32; SPI1W2 = color32; @@ -4954,8 +4958,6 @@ void writeBlock(uint16_t color, uint32_t repeat) void writeBlock(uint16_t color, uint32_t repeat) { - SPI1U = SPI1U_WRITE; - // Split out the colours uint8_t r = (color & 0xF800)>>8; uint8_t g = (color & 0x07E0)>>3; diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 93de46b..2d52ac9 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -15,7 +15,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "1.4.4" +#define TFT_ESPI_VERSION "1.4.5" //#define ESP32 //Just used to test ESP32 options diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino index fb49cf3..f13cb16 100644 --- a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -42,7 +42,7 @@ tft.getSetup(user); // Serial.printf("\n[code]\n"); -Serial.print ("TFT_eSPI ver = " + user.version +"\n"); +Serial.print ("TFT_eSPI ver = " + user.version + "\n"); Serial.printf("Processor = ESP%i\n", user.esp, HEX); Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); #ifdef ESP8266 diff --git a/library.json b/library.json index f3f1f04..3e84942 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.4", + "version": "1.4.5", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index d65fa12..43ac980 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.4 +version=1.4.5 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From e17ba463c967ccf780a38843e0e56467cb619805 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 17 Feb 2019 22:35:49 +0000 Subject: [PATCH 87/94] Add UTF-8 on/off control via new setAttribute function No change to legacy sketches meeded, UTF-8 decoding is on by default. Add colour test example. --- TFT_eSPI.cpp | 60 ++++++-- TFT_eSPI.h | 20 ++- .../Colour_Test/Colour_Test.ino | 132 ++++++++++++++++++ library.json | 2 +- library.properties | 2 +- 5 files changed, 199 insertions(+), 17 deletions(-) create mode 100644 examples/Test and diagnostics/Colour_Test/Colour_Test.ino diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 36760b3..53d498c 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -218,7 +218,9 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) locked = true; // ESP32 transaction mutex lock flags inTransaction = false; - _booted = true; + _booted = true; + _cp437 = true; + _utf8 = true; addr_row = 0xFFFF; addr_col = 0xFFFF; @@ -703,14 +705,14 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // Dummy read to throw away don't care value tft_Read_8(); - #if !defined (ILI9488_DRIVER) + //#if !defined (ILI9488_DRIVER) // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits uint8_t r = tft_Read_8(); uint8_t g = tft_Read_8(); uint8_t b = tft_Read_8(); - +/* #else // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse @@ -720,7 +722,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) uint8_t b = (tft_Read_8()&0x7E)<<1; #endif - +*/ CS_H; #ifdef TFT_SDA_READ @@ -3903,6 +3905,46 @@ void TFT_eSPI::invertDisplay(boolean i) } +/************************************************************************** +** Function name: setAttribute +** Description: Sets a control parameter of an attribute +**************************************************************************/ +void TFT_eSPI::setAttribute(uint8_t attr_id, uint8_t param) { + switch (attr_id) { + break; + case 1: + _cp437 = param; + break; + case 2: + _utf8 = param; + break; + //case 3: // TBD future feature control + // _tbd = param; + // break; + } +} + + +/************************************************************************** +** Function name: getAttribute +** Description: Get value of an attribute (control parameter) +**************************************************************************/ +uint8_t TFT_eSPI::getAttribute(uint8_t attr_id) { + switch (attr_id) { + case 1: // ON/OFF control of full CP437 character set + return _cp437; + break; + case 2: // ON/OFF control of UTF-8 decoding + return _utf8; + break; + //case 3: // TBD future feature control + // return _tbd; + // break; + } + + return false; +} + /*************************************************************************************** ** Function name: decodeUTF8 ** Description: Serial UTF-8 decoder with fall-back to extended ASCII @@ -3998,12 +4040,14 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) ***************************************************************************************/ size_t TFT_eSPI::write(uint8_t utf8) { - uint16_t uniCode = decodeUTF8(utf8); - - if (!uniCode) return 1; - if (utf8 == '\r') return 1; + uint16_t uniCode = utf8; + + if (_utf8) uniCode = decodeUTF8(utf8); + + if (uniCode == 0) return 1; + #ifdef SMOOTH_FONT if(fontLoaded) { diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 2d52ac9..cc937d7 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -808,8 +808,8 @@ class TFT_eSPI : public Print { void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); - // Compatibility additions (non-essential) - void startWrite(void); // Begin SPI transaction (not normally needed) + // Compatibility additions + void startWrite(void); // Begin SPI transaction void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead void endWrite(void); // End SPI transaction @@ -825,6 +825,10 @@ class TFT_eSPI : public Print { void end_SDA_Read(void); #endif + // Set or get an arbitrary library attribute or configuration option + void setAttribute(uint8_t id = 0, uint8_t a = 0); + uint8_t getAttribute(uint8_t id = 0); + void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate int32_t cursor_x, cursor_y, padX; @@ -877,17 +881,19 @@ class TFT_eSPI : public Print { uint32_t fontsloaded; - uint8_t glyph_ab, // glyph height above baseline - glyph_bb; // glyph height below baseline + uint8_t glyph_ab, // glyph delta Y (height) above baseline + glyph_bb; // glyph delta Y (height) below baseline - bool isDigits; // adjust bounding box for numbers to reduce visual jiggling + bool isDigits; // adjust bounding box for numbers to reduce visual jiggling bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display bool _swapBytes; // Swap the byte order for TFT pushImage() bool locked, inTransaction; // Transaction and mutex lock flags for ESP32 - bool _booted; + bool _booted; // init() or begin() has already run once + bool _cp437; // If set, use correct CP437 charset (default is ON) + bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON) - uint32_t _lastColor; + uint32_t _lastColor; // Buffered value of last colour used #ifdef LOAD_GFXFF GFXfont *gfxFont; diff --git a/examples/Test and diagnostics/Colour_Test/Colour_Test.ino b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino new file mode 100644 index 0000000..fb65bb4 --- /dev/null +++ b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino @@ -0,0 +1,132 @@ + +// Diagnostic test for the displayed colour order +// +// Writen by Bodmer 17/2/19 for the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +/* + Different hardware manufacturers use different colour order + configurations at the hardware level. This may result in + incorrect colours being displayed. + + Incorrectly displayed colours could also be the result of + using the wrong display driver in the library setup file. + + Typically displays have a control register (MADCTL) that can + be used to set the Red Green Blue (RGB) colour order to RGB + or BRG so that red and blue are swapped on the display. + + This control register is also used to manage the display + rotation and coordinate mirroring. The control register + typically has 8 bits, for the ILI9341 these are: + + Bit Function + 7 Mirror Y coordinate (row address order) + 6 Mirror X coordinate (column address order) + 5 Row/column exchange (for rotation) + 4 Refresh direction (top to bottom or bottom to top in portrait orientation) + 3 RGB order (swaps red and blue) + 2 Refresh direction (top to bottom or bottom to top in landscape orientation) + 1 Not used + 0 Not used + + The control register bits can be written with this example command sequence: + + tft.writecommand(TFT_MADCTL); + tft.writedata(0x48); // Bits 6 and 3 set + + 0x48 is the default value for ILI9341 (0xA8 for ESP32 M5STACK) + in rotation 0 orientation. + + Another control register can be used to "invert" colours, + this swaps black and white as well as other colours (e.g. + green to magenta, red to cyan, blue to yellow). + + To invert colours insert this line after tft.init() or tft.begin(): + + tft.invertDisplay( invert ); // Where invert is true or false + +*/ + +#include + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +void setup(void) { + tft.init(); + + tft.fillScreen(TFT_BLACK); + + // Set "cursor" at top left corner of display (0,0) and select font 4 + tft.setCursor(0, 0, 4); + + // Set the font colour to be white with a black background + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Intialised default\n"); + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(10000); + +} + +void loop() { + + tft.invertDisplay( false ); // Where i is true or false + + tft.fillScreen(TFT_BLACK); + + tft.setCursor(0, 0, 4); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Invert OFF\n"); + + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(10000); + + + // Binary inversion of colours + tft.invertDisplay( true ); // Where i is true or false + + tft.fillScreen(TFT_BLACK); + + tft.setCursor(0, 0, 4); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Invert ON\n"); + + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(10000); +} diff --git a/library.json b/library.json index 3e84942..09ec816 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.5", + "version": "1.4.6", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 43ac980..09b3308 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.5 +version=1.4.6 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 13f0589aa6d68289b0479d8419904f44fc55d0e5 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 18 Feb 2019 01:21:26 +0000 Subject: [PATCH 88/94] Adapt for new setAddrWindow parameters --- examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino index 0e3654e..4d5d4e7 100644 --- a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino +++ b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino @@ -141,7 +141,7 @@ void drawEye( // Renders one eye. Inputs must be pre-clipped & valid. // reset on each frame here in case of an SPI glitch. //eye[e].tft.setAddrWindow(319-127, 0, 319, 127); - eye[e].tft.setAddrWindow(0, 0, 127, 127); + eye[e].tft.setAddrWindow(0, 0, 128, 128); //digitalWrite(eye[e].cs, LOW); // Chip select From 66a21cb761e00c936253092b825e6b9ba7c2583c Mon Sep 17 00:00:00 2001 From: Bodmer Date: Tue, 19 Feb 2019 00:16:29 +0000 Subject: [PATCH 89/94] Fix ESP8266 core library issue reported in #310 --- TFT_eSPI.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 53d498c..86c8971 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -2788,6 +2788,9 @@ void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; + // Re-instate SPI flags settings corrupted by SPI library writePattern() call + SPI1U = SPI1U_WRITE; + //spi_end(); } From 1edfe6c680b7602e12d0fa3f1d3e633c97d84d4b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 20 Feb 2019 00:45:02 +0000 Subject: [PATCH 90/94] Fic #311 Pixel function used wrong width and height for bounds check. Remove String variable in smooth font code (not used) Correct ESP8266UncannyEyes example for new setAddrWindow parameters --- Extensions/Smooth_font.cpp | 6 ++---- Extensions/Smooth_font.h | 2 -- Extensions/Sprite.cpp | 7 ++++++- .../Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino | 2 +- library.json | 2 +- library.properties | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 8d7628f..f63b45c 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -76,15 +76,13 @@ void TFT_eSPI::loadFont(String fontName) unloadFont(); - _gFontFilename = "/" + fontName + ".vlw"; - // Avoid a crash on the ESP32 if the file does not exist - if (SPIFFS.exists(_gFontFilename) == false) { + if (SPIFFS.exists("/" + fontName + ".vlw") == false) { Serial.println("Font file " + fontName + " not found!"); return; } - fontFile = SPIFFS.open( _gFontFilename, "r"); + fontFile = SPIFFS.open( "/" + fontName + ".vlw", "r"); if(!fontFile) return; diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h index 1bc9fd2..aa51855 100644 --- a/Extensions/Smooth_font.h +++ b/Extensions/Smooth_font.h @@ -39,8 +39,6 @@ fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 }; int8_t* gdX = NULL; //leftExtent uint32_t* gBitmap = NULL; //file pointer to greyscale bitmap - String _gFontFilename; - bool fontLoaded = false; // Flags when a anti-aliased font is loaded private: diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index 3782775..f389141 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -1059,6 +1059,8 @@ int16_t TFT_eSprite::height(void) // Does nothing for 8 and 16 bpp sprites. TODO allow rotation of these sprites void TFT_eSprite::setRotation(uint8_t rotation) { + if (_bpp != 1) return; + _rotation = rotation; if (rotation == 0 && _iwidth > _iheight) swap_coord(_iwidth, _iheight); if (rotation == 1 && _iwidth < _iheight) swap_coord(_iwidth, _iheight); @@ -1085,19 +1087,22 @@ uint8_t TFT_eSprite::getRotation(void) void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) { // Range checking - if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height) || !_created) return; + if ((x < 0) || (y < 0) || !_created) return; if (_bpp == 16) { + if ((x >= _iwidth) || (y >= _iheight)) return; color = (color >> 8) | (color << 8); _img[x+y*_iwidth] = (uint16_t) color; } else if (_bpp == 8) { + if ((x >= _iwidth) || (y >= _iheight)) return; _img8[x+y*_iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); } else // 1 bpp { + if ((x >= _dwidth) || (y >= _dheight)) return; if (_rotation == 1) { uint16_t tx = x; diff --git a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino index 4d5d4e7..0e3654e 100644 --- a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino +++ b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino @@ -141,7 +141,7 @@ void drawEye( // Renders one eye. Inputs must be pre-clipped & valid. // reset on each frame here in case of an SPI glitch. //eye[e].tft.setAddrWindow(319-127, 0, 319, 127); - eye[e].tft.setAddrWindow(0, 0, 128, 128); + eye[e].tft.setAddrWindow(0, 0, 127, 127); //digitalWrite(eye[e].cs, LOW); // Chip select diff --git a/library.json b/library.json index 09ec816..6381bb3 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.6", + "version": "1.4.7", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index 09b3308..f4e7a65 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.6 +version=1.4.7 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 43862876a2c63d43aa096c012ca46d6af7e5105b Mon Sep 17 00:00:00 2001 From: Bodmer Date: Wed, 20 Feb 2019 23:33:21 +0000 Subject: [PATCH 91/94] Permit larger anti-aliased fonts Size limit for anti-aliased fonts raised to ~200 pixels --- Extensions/Smooth_font.cpp | 4 ++-- Extensions/Smooth_font.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index f63b45c..6e5f89d 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -124,7 +124,7 @@ void TFT_eSPI::loadMetrics(uint16_t gCount) gHeight = (uint8_t*)malloc( gCount ); // Height of glyph gWidth = (uint8_t*)malloc( gCount ); // Width of glyph gxAdvance = (uint8_t*)malloc( gCount ); // xAdvance - to move x cursor - gdY = (int8_t*)malloc( gCount ); // offset from bitmap top edge from lowest point in any character + gdY = (int16_t*)malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in SPIFFS file @@ -141,7 +141,7 @@ void TFT_eSPI::loadMetrics(uint16_t gCount) gHeight[gNum] = (uint8_t)readInt32(); // Height of glyph gWidth[gNum] = (uint8_t)readInt32(); // Width of glyph gxAdvance[gNum] = (uint8_t)readInt32(); // xAdvance - to move x cursor - gdY[gNum] = (int8_t)readInt32(); // y delta from baseline + gdY[gNum] = (int16_t)readInt32(); // y delta from baseline gdX[gNum] = (int8_t)readInt32(); // x delta from cursor readInt32(); // ignored diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h index aa51855..c1cc483 100644 --- a/Extensions/Smooth_font.h +++ b/Extensions/Smooth_font.h @@ -35,7 +35,7 @@ fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 }; uint8_t* gHeight = NULL; //cheight uint8_t* gWidth = NULL; //cwidth uint8_t* gxAdvance = NULL; //setWidth - int8_t* gdY = NULL; //topExtent + int16_t* gdY = NULL; //topExtent int8_t* gdX = NULL; //leftExtent uint32_t* gBitmap = NULL; //file pointer to greyscale bitmap From 46425b83bc1e3d43d8a52425f5f243b2d5f5a0b8 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Fri, 22 Feb 2019 00:13:40 +0000 Subject: [PATCH 92/94] Fix bug in UTF-8 line buffer decoder --- TFT_eSPI.cpp | 2 +- library.json | 2 +- library.properties | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 86c8971..19af227 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -4011,7 +4011,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t c) *************************************************************************************x*/ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) { - byte c = buf[(*index)++]; + uint16_t c = buf[(*index)++]; //Serial.print("Byte from string = 0x"); Serial.println(c, HEX); #ifdef DECODE_UTF8 diff --git a/library.json b/library.json index 6381bb3..da5bb7c 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.7", + "version": "1.4.8", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index f4e7a65..a1b8621 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.7 +version=1.4.8 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE From 652383b694398d5379d4e3870e2f9d927f6a8bdc Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 4 Mar 2019 13:34:29 +0000 Subject: [PATCH 93/94] Fix part of Issue #322 --- TFT_Drivers/ST7789_Init.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index c72b51d..cad01a3 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -13,7 +13,7 @@ //------------------------------display and color format setting--------------------------------// writecommand(ST7789_MADCTL); - writedata(0x00); + //writedata(0x00); writedata(TFT_MAD_COLOR_ORDER); // JLX240 display datasheet From 9f179201157febae786aa9aaa9a0eed399971913 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 15 Apr 2019 12:23:16 +0100 Subject: [PATCH 94/94] Add ESP32 SD support for smooth font plus performance updates Added SD card storage for smooth fonts with ESP32 ESP32 will use PSRAM (if available and enabled) to hold smooth font metrics Improve performance of ESP32 Sprite shared functions Add basic ST7789 driver option Latent bug fixes for pin mask --- Extensions/Smooth_font.cpp | 71 +++++-- Extensions/Smooth_font.h | 13 +- TFT_Drivers/ST7789_2_Defines.h | 143 ++++++++++++++ TFT_Drivers/ST7789_2_Init.h | 22 +++ TFT_Drivers/ST7789_2_Rotation.h | 48 +++++ TFT_Drivers/ST7789_Init.h | 4 +- TFT_eSPI.cpp | 95 ++++++---- TFT_eSPI.h | 4 +- User_Setup.h | 5 +- User_Setup_Select.h | 6 +- User_Setups/Setup10_RPi_touch_ILI9486.h | 2 +- User_Setups/Setup18_ST7789.h | 11 +- User_Setups/Setup21_ILI9488.h | 4 + User_Setups/Setup24_ST7789.h | 53 ++++++ User_Setups/SetupX_Template.h | 7 +- .../ESP32_Smooth_Font_SD.ino | 174 ++++++++++++++++++ .../data/Final-Frontier-28.vlw | Bin 0 -> 25287 bytes .../Colour_Test/Colour_Test.ino | 6 +- library.json | 2 +- library.properties | 2 +- 20 files changed, 600 insertions(+), 72 deletions(-) create mode 100644 TFT_Drivers/ST7789_2_Defines.h create mode 100644 TFT_Drivers/ST7789_2_Init.h create mode 100644 TFT_Drivers/ST7789_2_Rotation.h create mode 100644 User_Setups/Setup24_ST7789.h create mode 100644 examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino create mode 100644 examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp index 6e5f89d..ca1cb63 100644 --- a/Extensions/Smooth_font.cpp +++ b/Extensions/Smooth_font.cpp @@ -8,9 +8,18 @@ /*************************************************************************************** ** Function name: loadFont -** Description: loads parameters from a new font vlw file stored in SPIFFS +** Description: loads parameters from a new font vlw file *************************************************************************************x*/ -void TFT_eSPI::loadFont(String fontName) +void TFT_eSPI::loadFont(String fontName, fs::FS &ffs) +{ + fontFS = ffs; + loadFont(fontName, false); +} +/*************************************************************************************** +** Function name: loadFont +** Description: loads parameters from a new font vlw file +*************************************************************************************x*/ +void TFT_eSPI::loadFont(String fontName, bool flash) { /* The vlw font format does not appear to be documented anywhere, so some reverse @@ -74,15 +83,19 @@ void TFT_eSPI::loadFont(String fontName) */ - unloadFont(); - + spiffs = flash; + + if(spiffs) fontFS = SPIFFS; + + unloadFont(); + // Avoid a crash on the ESP32 if the file does not exist - if (SPIFFS.exists("/" + fontName + ".vlw") == false) { + if (fontFS.exists("/" + fontName + ".vlw") == false) { Serial.println("Font file " + fontName + " not found!"); return; } - fontFile = SPIFFS.open( "/" + fontName + ".vlw", "r"); + fontFile = fontFS.open( "/" + fontName + ".vlw", "r"); if(!fontFile) return; @@ -120,13 +133,28 @@ void TFT_eSPI::loadMetrics(uint16_t gCount) uint32_t headerPtr = 24; uint32_t bitmapPtr = 24 + gCount * 28; - gUnicode = (uint16_t*)malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) - gHeight = (uint8_t*)malloc( gCount ); // Height of glyph - gWidth = (uint8_t*)malloc( gCount ); // Width of glyph - gxAdvance = (uint8_t*)malloc( gCount ); // xAdvance - to move x cursor - gdY = (int16_t*)malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character - gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X - gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in SPIFFS file +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) + { + gUnicode = (uint16_t*)ps_malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gHeight = (uint8_t*)ps_malloc( gCount ); // Height of glyph + gWidth = (uint8_t*)ps_malloc( gCount ); // Width of glyph + gxAdvance = (uint8_t*)ps_malloc( gCount ); // xAdvance - to move x cursor + gdY = (int16_t*)ps_malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character + gdX = (int8_t*)ps_malloc( gCount ); // offset for bitmap left edge relative to cursor X + gBitmap = (uint32_t*)ps_malloc( gCount * 4); // seek pointer to glyph bitmap in the file + } + else +#endif + { + gUnicode = (uint16_t*)malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gHeight = (uint8_t*)malloc( gCount ); // Height of glyph + gWidth = (uint8_t*)malloc( gCount ); // Width of glyph + gxAdvance = (uint8_t*)malloc( gCount ); // xAdvance - to move x cursor + gdY = (int16_t*)malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character + gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X + gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in the file + } #ifdef SHOW_ASCENT_DESCENT Serial.print("ascent = "); Serial.println(gFont.ascent); @@ -456,7 +484,19 @@ void TFT_eSPI::drawGlyph(uint16_t code) for (int y = 0; y < gHeight[gNum]; y++) { - fontFile.read(pbuffer, gWidth[gNum]); //= 0) cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS); #endif - #ifdef TFT_DC + #if defined (TFT_DC) && (TFT_DC >= 0) dcpinmask = (uint32_t) digitalPinToBitMask(TFT_DC); #endif - #ifdef TFT_WR + #if defined (TFT_WR) && (TFT_WR >= 0) wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR); #endif - #ifdef TFT_SCLK + #if defined (TFT_SCLK) && (TFT_SCLK >= 0) sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK); #endif @@ -407,6 +412,9 @@ void TFT_eSPI::init(uint8_t tc) #elif defined (R61581_DRIVER) #include "TFT_Drivers/R61581_Init.h" +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Init.h" + #endif #ifdef TFT_INVERSION_ON @@ -477,6 +485,9 @@ void TFT_eSPI::setRotation(uint8_t m) #elif defined (R61581_DRIVER) #include "TFT_Drivers/R61581_Rotation.h" +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Rotation.h" + #endif delayMicroseconds(10); @@ -1561,7 +1572,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t dy = r+r; int32_t p = -(r>>1); - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // These are ordered to minimise coordinate changes in x or y @@ -1598,7 +1609,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1654,7 +1665,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t dy = r+r; int32_t p = -(r>>1); - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; drawFastHLine(x0 - r, y0, dy+1, color); @@ -1680,7 +1691,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1736,7 +1747,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) @@ -1772,7 +1783,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1791,7 +1802,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) @@ -1821,7 +1832,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1842,7 +1853,7 @@ void TFT_eSPI::fillScreen(uint32_t color) // Draw a rectangle void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; drawFastHLine(x, y, w, color); @@ -1852,7 +1863,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col drawFastVLine(x + w - 1, y+1, h-2, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1863,7 +1874,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col // Draw a rounded rectangle void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // smarter version @@ -1878,7 +1889,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t drawCircleHelper(x + r , y + h - r - 1, r, 8, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1889,7 +1900,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t // Fill a rounded rectangle, changed to horizontal lines (faster in sprites) void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // smarter version @@ -1900,7 +1911,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1911,7 +1922,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t // Draw a triangle void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; drawLine(x0, y0, x1, y1, color); @@ -1919,7 +1930,7 @@ void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3 drawLine(x2, y2, x0, y0, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1953,7 +1964,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in return; } - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; int32_t @@ -2000,7 +2011,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -2010,7 +2021,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in ***************************************************************************************/ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2024,7 +2035,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -2034,7 +2045,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w ***************************************************************************************/ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2048,7 +2059,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -2058,7 +2069,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t ***************************************************************************************/ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2072,7 +2083,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -2480,7 +2491,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 } else { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (int8_t i = 0; i < 6; i++ ) { uint8_t line; @@ -2505,7 +2516,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 } } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2519,7 +2530,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 // Filter out bad characters not present in font if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2643,7 +2654,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 } #endif inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } #endif @@ -3500,7 +3511,7 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; boolean steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { @@ -4278,7 +4289,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) if (x + width * textsize >= (int16_t)_width) return width * textsize ; if (textcolor == textbgcolor || textsize != 1) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (int32_t i = 0; i < height; i++) @@ -5178,6 +5189,18 @@ void writeBlock(uint16_t color, uint32_t repeat) #endif +/*************************************************************************************** +** Function name: getSPIinstance +** Description: Get the instance of the SPI class (for ESP32 only) +***************************************************************************************/ +#ifndef ESP32_PARALLEL +SPIClass& TFT_eSPI::getSPIinstance(void) +{ + return spi; +} +#endif + + /*************************************************************************************** ** Function name: getSetup ** Description: Get the setup details for diagnostic and sketch access diff --git a/TFT_eSPI.h b/TFT_eSPI.h index cc937d7..0756d39 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -37,7 +37,7 @@ #define SPI_READ_FREQUENCY SPI_FREQUENCY #endif -#ifdef ST7789_DRIVER +#if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) #define TFT_SPI_MODE SPI_MODE3 #else #define TFT_SPI_MODE SPI_MODE0 @@ -831,6 +831,8 @@ class TFT_eSPI : public Print { void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate + static SPIClass& getSPIinstance(void); + int32_t cursor_x, cursor_y, padX; uint32_t textcolor, textbgcolor; diff --git a/User_Setup.h b/User_Setup.h index a963e3b..3f44644 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -25,14 +25,15 @@ //#define ILI9481_DRIVER //#define ILI9486_DRIVER //#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) -//#define ST7789_DRIVER // Define additional parameters below for this display +//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display +//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display //#define R61581_DRIVER // Some displays support SPI reads via the MISO pin, other displays have a single // bi-directional SDA pin and the library will try to read this via the MOSI line. // To use the SDA line for reading data from the TFT uncomment the following line: -// #define TFT_SDA_READ // This option if for ESP32 ONLY, tested with ST7789 display only +// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only // For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display // Try ONE option at a time to find the correct colour order for your display diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 69d27a0..06568f1 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -39,13 +39,14 @@ //#include // Setup file configured for HX8357D (untested) //#include // Setup file for the ESP32 with parallel bus TFT //#include // Setup file for any Waveshare ePaper display -//#include // Setup file configured for HX8357D (untested) +//#include // Setup file configured for ST7789 //#include // Setup file for ESP8266 and ILI9488 SPI bus TFT //#include // Setup file for ESP32 and ILI9488 SPI bus TFT //#include // Setup file for ESP32 and TTGO T4 (BTC) ILI9341 SPI bus TFT //#include // Setup file for ESP32 and TTGO TM ST7789 SPI bus TFT +//#include // Setup file configured for ST7789 240 x 240 //#include // Setup file configured for my ST7735S 80x160 @@ -106,6 +107,9 @@ #elif defined (R61581_DRIVER) #include "TFT_Drivers/R61581_Defines.h" #define TFT_DRIVER 0x6158 +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Defines.h" + #define TFT_DRIVER 0x778B #elif defined (XYZZY_DRIVER) // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE #include "TFT_Drivers/XYZZY_Defines.h" #define TFT_DRIVER 0x0000 diff --git a/User_Setups/Setup10_RPi_touch_ILI9486.h b/User_Setups/Setup10_RPi_touch_ILI9486.h index 8e59a6b..ffe2f71 100644 --- a/User_Setups/Setup10_RPi_touch_ILI9486.h +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -23,7 +23,7 @@ #define SMOOTH_FONT -#define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 16000000 #define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setups/Setup18_ST7789.h b/User_Setups/Setup18_ST7789.h index 25d57a3..1f9be03 100644 --- a/User_Setups/Setup18_ST7789.h +++ b/User_Setups/Setup18_ST7789.h @@ -2,8 +2,17 @@ #define ST7789_DRIVER +// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only -#define TFT_SDA_READ +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red // My ST7789 display has TCT_CS wired permananently low so the pin is not defined here diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h index 1a39a02..358eef4 100644 --- a/User_Setups/Setup21_ILI9488.h +++ b/User_Setups/Setup21_ILI9488.h @@ -2,6 +2,7 @@ #define ILI9488_DRIVER +//#define TFT_INVERSION_OFF #define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) #define TFT_MOSI 23 @@ -27,4 +28,7 @@ // #define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 16000000 + #define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setups/Setup24_ST7789.h b/User_Setups/Setup24_ST7789.h new file mode 100644 index 0000000..d75b743 --- /dev/null +++ b/User_Setups/Setup24_ST7789.h @@ -0,0 +1,53 @@ +// ST7789 240 x 240 display with no chip select line + +#define ST7789_DRIVER // Configure all registers + +#define TFT_WIDTH 240 +#define TFT_HEIGHT 240 + +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + +// DSTIKE stepup +//#define TFT_DC 23 +//#define TFT_RST 32 +//#define TFT_MOSI 26 +//#define TFT_SCLK 27 + +// Generic ESP32 setup +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS -1 // Not connected +//#define TFT_DC 2 +//#define TFT_RST 4 // Connect reset to ensure display initialises + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS -1 // Define as not used +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 27000000 +#define SPI_FREQUENCY 40000000 + +#define SPI_READ_FREQUENCY 20000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + +// #define SUPPORT_TRANSACTIONS \ No newline at end of file diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index aa5037a..534a634 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -25,7 +25,8 @@ //#define ILI9481_DRIVER //#define ILI9486_DRIVER //#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) -//#define ST7789_DRIVER // Define additional parameters below for this display +//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display +//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display //#define R61581_DRIVER // Some displays support SPI reads via the MISO pin, other displays have a single @@ -37,8 +38,8 @@ // For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display // Try ONE option at a time to find the correct colour order for your display -// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue -// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red // For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below diff --git a/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino new file mode 100644 index 0000000..c6dbb19 --- /dev/null +++ b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino @@ -0,0 +1,174 @@ +/* + Sketch to demonstrate using the print class with smooth fonts + that are saved onto an SD Card accessed by the SD library. + + For ESP32 only, GPIO 5 must be used for SD chip select. + This method of storing the fonts is NOT compatible with the ESP8266. + + Sketch is written for a 240 x 320 display + + Load the font file onto the root directory of the SD Card. The font files + used by this sketch can be found in the Data folder, press Ctrl+K to see it. + + The library supports 16 bit unicode characters: + https://en.wikipedia.org/wiki/Unicode_font + + The characters supported are in the in the Basic Multilingal Plane: + https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + + Make sure all the display driver and pin connenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Font file is stored on SD card +#include + +// Graphics and font library +#include +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + Serial.begin(115200); // Used for messages + + // Initialise the SD library before the TFT so the chip select is defined + if (!SD.begin()) { + Serial.println("Card Mount Failed"); + return; + } + uint8_t cardType = SD.cardType(); + + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.print("SD Card Type: "); + if (cardType == CARD_MMC) { + Serial.println("MMC"); + } else if (cardType == CARD_SD) { + Serial.println("SDSC"); + } else if (cardType == CARD_SDHC) { + Serial.println("SDHC"); + } else { + Serial.println("UNKNOWN"); + } + + uint64_t cardSize = SD.cardSize() / (1024 * 1024); + Serial.printf("SD Card Size: %lluMB\n", cardSize); + + // Initialise the TFT after the SD card! + tft.init(); + tft.setRotation(1); + tft.fillScreen(TFT_BLACK); + + listDir(SD, "/", 0); + + Serial.println("SD and TFT initialisation done."); +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + // Wrap test at right and bottom of screen + tft.setTextWrap(true, true); + + // Name of font file (library adds leading / and .vlw) + String fileName = "Final-Frontier-28"; + + // Font and background colour, background colour is used for anti-alias blending + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // Load the font + tft.loadFont(fileName, SD); // Use font stored on SD + + // Display all characters of the font + tft.showFont(2000); + + uint32_t dt = millis(); + + int count = 100; + + while (count--) + { + // Set "cursor" at top left corner of display (0,0) + // (cursor will move to next line automatically during printing with 'tft.println' + // or stay on the line is there is room for the text with tft.print) + tft.setCursor(0, 0); + + // Set the font colour to be white with a black background, set text size multiplier to 1 + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Hello World!"); + + // Set the font colour to be yellow + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.println(1234.56); + + // Set the font colour to be red + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println((uint32_t)3735928559, HEX); // Should print DEADBEEF + + // Set the font colour to be green with black background + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Anti-aliased font!"); + tft.println(""); + + // Test some print formatting functions + float fnumber = 123.45; + + // Set the font colour to be blue + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.print("Float = "); tft.println(fnumber); // Print floating point number + tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary + tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal + } + + Serial.println(millis()-dt); + + // Unload the font to recover used RAM + tft.unloadFont(); + + delay(10000); +} + +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + Serial.printf("Listing directory: %s\n", dirname); + + File root = fs.open(dirname); + if(!root){ + Serial.println("Failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println("Not a directory"); + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + Serial.print(" DIR : "); + Serial.println(file.name()); + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print(" SIZE: "); + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} diff --git a/examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw new file mode 100644 index 0000000000000000000000000000000000000000..2872fd554bbf34f5e1268770dd8ea3cf55cecdfd GIT binary patch literal 25287 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 literal 0 HcmV?d00001 diff --git a/examples/Test and diagnostics/Colour_Test/Colour_Test.ino b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino index fb65bb4..ed7a061 100644 --- a/examples/Test and diagnostics/Colour_Test/Colour_Test.ino +++ b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino @@ -78,7 +78,7 @@ void setup(void) { tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); - delay(10000); + delay(5000); } @@ -104,7 +104,7 @@ void loop() { tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); - delay(10000); + delay(5000); // Binary inversion of colours @@ -128,5 +128,5 @@ void loop() { tft.setTextColor(TFT_BLUE, TFT_BLACK); tft.println("Blue text"); - delay(10000); + delay(5000); } diff --git a/library.json b/library.json index da5bb7c..1474e04 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.4.8", + "version": "1.4.9", "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": diff --git a/library.properties b/library.properties index a1b8621..a8b48c7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.4.8 +version=1.4.9 author=Bodmer maintainer=Bodmer sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE