├── JPEGS ├── F103RBT6.jpg ├── JpegView.jpg ├── SMT32_PillBoard.jpg ├── healsky3.jpg ├── sunrise.jpg └── tree.jpg ├── README.md ├── STM32_TFT_8bit.cpp ├── STM32_TFT_8bit.h ├── examples ├── ClockAnalog_STM32 │ └── ClockAnalog_STM32.ino ├── CubeDemo_STM32 │ └── CubeDemo_STM32.ino ├── GraphicsTest_240x320_SMT32 │ └── GraphicsTest_240x320_SMT32.ino ├── GraphicsTest_240x400_SMT32 │ └── GraphicsTest_240x400_SMT32.ino ├── GraphicsTest_320x480_SMT32 │ └── GraphicsTest_320x480_SMT32.ino ├── JpegView_240x320_SMT32 │ ├── JPEG_Functions.ino │ └── JpegView_240x320_SMT32.ino ├── JpegView_320x480_SMT32 │ ├── JPEG_Functions.ino │ └── JpegView_320x480_SMT32.ino ├── LCD_ID_Reader │ ├── LCD_ID_Reader.ino │ └── README.md ├── ScrollTest_STM32 │ ├── ScrollTest_STM32.ino │ └── icons.c ├── TFT_ArcFill_STM32 │ └── TFT_ArcFill_STM32.ino ├── TFT_Meter_linear_STM32 │ └── TFT_Meter_linear_STM32.ino ├── TFT_Meters_STM32 │ └── TFT_Meters_STM32.ino ├── TFT_Pong_STM32 │ └── TFT_Pong_STM32.ino └── UTFT_demo_STM32 │ └── UTFT_demo_STM32.ino └── library.properties /JPEGS/F103RBT6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/F103RBT6.jpg -------------------------------------------------------------------------------- /JPEGS/JpegView.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/JpegView.jpg -------------------------------------------------------------------------------- /JPEGS/SMT32_PillBoard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/SMT32_PillBoard.jpg -------------------------------------------------------------------------------- /JPEGS/healsky3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/healsky3.jpg -------------------------------------------------------------------------------- /JPEGS/sunrise.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/sunrise.jpg -------------------------------------------------------------------------------- /JPEGS/tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nopnop2002/STM32_TFT_8bit/a41ea46b5513001c74907149dc6d57235211c91d/JPEGS/tree.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STM32_TFT_8bit 2 | 8bit TFT Library for Arduino_STM32(MAPLE Core) 3 | 4 | I ported from here. 5 | https://github.com/prenticedavid/MCUFRIEND_kbv 6 | 7 | ---- 8 | 9 | # Software requirement 10 | 11 | - Core library 12 | https://github.com/rogerclarkmelbourne/Arduino_STM32 13 | 14 | - Adafruit GFX Library 15 | https://github.com/adafruit/Adafruit-GFX-Library 16 | 17 | ---- 18 | 19 | # Wirering for 8bit Parallel TFT 20 | 21 | Using GPIOA as Data Port 22 | `#define TFT_DATA GPIOA` 23 | 24 | |TFT||STM32F103| 25 | |:-:|:-:|:-:| 26 | |LCD_RST|--|PB7| 27 | |LCD_CS|--|PB6| 28 | |LCD_RS|--|PB5| 29 | |LCD_WR|--|PB4(*2)| 30 | |LCD_RD|--|PB3(*2)| 31 | |LCD_D0|--|PA0| 32 | |LCD_D1|--|PA1| 33 | |LCD_D2|--|PA2| 34 | |LCD_D3|--|PA3| 35 | |LCD_D4|--|PA4| 36 | |LCD_D5|--|PA5| 37 | |LCD_D6|--|PA6| 38 | |LCD_D7|--|PA7| 39 | |5V|--|5V(*1)| 40 | |3.3V|--|3.3V(*1)| 41 | |GND|--|GND| 42 | 43 | 44 | Using GPIOC as Data Port 45 | `#define TFT_DATA GPIOC` 46 | 47 | |TFT||STM32F103| 48 | |:-:|:-:|:-:| 49 | |LCD_RST|--|PB7| 50 | |LCD_CS|--|PB6| 51 | |LCD_RS|--|PB5| 52 | |LCD_WR|--|PB4(*2)| 53 | |LCD_RD|--|PB3(*2)| 54 | |LCD_D0|--|PC0| 55 | |LCD_D1|--|PC1| 56 | |LCD_D2|--|PC2| 57 | |LCD_D3|--|PC3| 58 | |LCD_D4|--|PC4| 59 | |LCD_D5|--|PC5| 60 | |LCD_D6|--|PC6| 61 | |LCD_D7|--|PC7| 62 | |5V|--|5V(*1)| 63 | |3.3V|--|3.3V(*1)| 64 | |GND|--|GND| 65 | 66 | (*1)When a regulator(It's often AMS1117) is mounted on the back, it's operated 5V. 67 | When a regulator is NOT mounted on the back, it's operated 3.3V. 68 | 69 | (*2)By several boards, This port is used as JTAG. 70 | You need remap. 71 | afio_cfg_debug_ports(AFIO_DEBUG_NONE) 72 | 73 | Pin define is "STM32_TFT_8bit.h" 74 | 75 | ---- 76 | 77 | # Tested TFT 78 | - ILI9325 2.4inch 240x320 TFT-Shield 79 | - ILI9341 2.4inch 240x320 TFT-Shield 80 | - ILI9342 2.4inch 240x320 TFT-Shield 81 | - SPFD5408 2.4inch 240x320 TFT-Shield 82 | - R61505 2.4inch 240x320 TFT-Shield 83 | - ST7783 2.4inch 240x320 TFT-Shield 84 | - LGDP4532 2.4inch 240x320 TFT-Shield 85 | - R61509V 3.6inch 240x400 TFT-Shield 86 | - ST7793 3.6inch 240x400 TFT-Shield 87 | - ILI9481 3.5inch 320x480 TFT-Shield 88 | - ILI9486 3.5inch 320x480 TFT-Shield 89 | - RM68140 3.95inch 320x480 TFT-Shield 90 | - ST7796 3.95inch 320x480 TFT-Shield 91 | - OPEN-SMART ILI9225 TFT-Shield 92 | - OPEN-SMART ILI9327 TFT-Shield 93 | - OPEN-SMART ILI9340 TFT-Shield 94 | 95 | I found that these display cannot follow high-speed GPIO-ON and GPIO-OFF. 96 | - OPEN-SMART S6D1121 16Pin-Parallel 97 | - OPEN-SMART ST7775 16Pin-Parallel 98 | - OPEN-SMART ST7783 16Pin-Parallel 99 | - OPEN-SMART R61509V 16Pin-Parallel 100 | - OPEN-SMART ILI9488 16Pin-Parallel 101 | 102 | ---- 103 | 104 | # Setting your TFT's resolution 105 | 106 | If your TFT's resolution is 320x480, 107 | you have to set your TFT's resolution using tft.setResoution. 108 | 109 | Example: 110 | ``` 111 | ID = tft.readID(); 112 | tft.setResolution(320, 480); // Set your resolution 113 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 114 | tft.begin(ID); 115 | uint32_t width = tft.width(); 116 | Serial.print("Width: "); Serial.println(width); // You will see 320 117 | uint32_t height = tft.height(); 118 | Serial.print("Height: "); Serial.println(height); // You will see 480 119 | ``` 120 | 121 | If your TFT's resolution is 240x400, 122 | you have to set your TFT's resolution and TFT's offset. 123 | 124 | Example: 125 | ``` 126 | ID = tft.readID(); 127 | tft.setResolution(240, 400); // Set your resolution 128 | tft.setOffset(32); // Set your offset 129 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 130 | tft.begin(ID); 131 | uint32_t width = tft.width(); 132 | Serial.print("Width: "); Serial.println(width); // You will see 240 133 | uint32_t height = tft.height(); 134 | Serial.print("Height: "); Serial.println(height); // You will see 400 135 | ``` 136 | 137 | --- 138 | 139 | - SPFD5408 + ILI9486 140 | ![8BIT_TFT-1](https://user-images.githubusercontent.com/6020549/84582637-a4ccd180-ae29-11ea-85f7-eb6881d6548d.JPG) 141 | 142 | - ILI9325 + ILI9481 143 | ![8BIT_TFT-2](https://user-images.githubusercontent.com/6020549/84582638-a7c7c200-ae29-11ea-876e-98f5462fcaf8.JPG) 144 | 145 | - ILI9341 + ST7793 146 | ![8BIT_TFT-3](https://user-images.githubusercontent.com/6020549/84582639-a9918580-ae29-11ea-9d53-57721d7cef9e.JPG) 147 | 148 | - ILI9342 + R61509V 149 | ![8BIT_TFT-4](https://user-images.githubusercontent.com/6020549/84582789-8536a880-ae2b-11ea-9ed2-a99bf8d0e495.JPG) 150 | 151 | - ST7783 + ST7796 152 | ![8BIT_TFT-5](https://user-images.githubusercontent.com/6020549/87236076-4b06f980-c41f-11ea-976e-97eaba22e8fa.JPG) 153 | 154 | ---- 155 | 156 | # F4 board support 157 | If you want more faster, plase use [this](https://github.com/nopnop2002/Arduino-STM32-8bitTFT). 158 | F4 board is very fast. 159 | 160 | ---- 161 | 162 | # JPEG Viewer 163 | 164 | Viewer of a JPEG file in the SD card. 165 | 166 | # Software requirement 167 | 168 | - Arduino FAT16/FAT32 Library 169 | https://github.com/greiman/SdFat 170 | 171 | - JPEG decoder library 172 | https://github.com/Bodmer/JPEGDecoder 173 | 174 | # Wirering for TFT built-in SD-CARD Reader 175 | 176 | |TFT||STM32F103| 177 | |:-:|:-:|:-:| 178 | |SD_SS|--|PB12| 179 | |SD_SCK|--|PB13| 180 | |SD_DI|--|PB15| 181 | |SD_DO|--|PB14| 182 | |5V|--|5V(*)| 183 | |3.3V|--|3.3V(*)| 184 | |GND|--|GND| 185 | 186 | \*When a regulator(It's often AMS1117) is mounted on the back, it's operated 5V. 187 | \*When a regulator is NOT mounted on the back, it's operated 3.3V. 188 | 189 | # How to use 190 | 191 | Copy JPEGS file to your SD-CARD. 192 | \*The biggest length of the JPEG file name is 32 character. 193 | Wire TFT built-in SD-CARD Reader to STM32. 194 | Execute JpegView_240x320_SMT32. 195 | 196 | ![jpegview-2](https://user-images.githubusercontent.com/6020549/39962758-a9b65e36-5693-11e8-9f67-d36a92a71fb1.JPG) 197 | 198 | -------------------------------------------------------------------------------- /STM32_TFT_8bit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #ifndef _STM32_TFTH_ 22 | #define _STM32_TFTH_ 23 | 24 | #include "Arduino.h" 25 | #include "Print.h" 26 | #include 27 | #include 28 | 29 | 30 | /* 31 | If you use TFT of different resolution, change this. 32 | */ 33 | #define TFTWIDTH 240 34 | #define TFTHEIGHT 320 35 | 36 | // Color definitions 37 | #define BLACK 0x0000 /* 0, 0, 0 */ 38 | #define NAVY 0x000F /* 0, 0, 128 */ 39 | #define DARKGREEN 0x03E0 /* 0, 128, 0 */ 40 | #define DARKCYAN 0x03EF /* 0, 128, 128 */ 41 | #define MAROON 0x7800 /* 128, 0, 0 */ 42 | #define PURPLE 0x780F /* 128, 0, 128 */ 43 | #define OLIVE 0x7BE0 /* 128, 128, 0 */ 44 | #define LIGHTGRAY 0xC618 /* 192, 192, 192 */ 45 | #define DARKGRAY 0x7BEF /* 128, 128, 128 */ 46 | #define BLUE 0x001F /* 0, 0, 255 */ 47 | #define GREEN 0x07E0 /* 0, 255, 0 */ 48 | #define CYAN 0x07FF /* 0, 255, 255 */ 49 | #define RED 0xF800 /* 255, 0, 0 */ 50 | #define MAGENTA 0xF81F /* 255, 0, 255 */ 51 | #define YELLOW 0xFFE0 /* 255, 255, 0 */ 52 | #define WHITE 0xFFFF /* 255, 255, 255 */ 53 | #define ORANGE 0xFD20 /* 255, 165, 0 */ 54 | #define GREENYELLOW 0xAFE5 /* 173, 255, 47 */ 55 | #define PINK 0xF81F 56 | #define GRAY 0x5AEB 57 | 58 | /* 59 | Define pins and Output Data Registers 60 | */ 61 | 62 | #define TFT_DATA GPIOA 63 | //Port data |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | 64 | //Pin stm32 |PA7|PA6|PA5|PA4|PA3|PA2|PA1|PA0| 65 | 66 | //#define TFT_DATA GPIOC 67 | //Port data |D7 |D6 |D5 |D4 |D3 |D2 |D1 |D0 | 68 | //Pin stm32 |PC7|PC6|PC5|PC4|PC3|PC2|PC1|PC0| 69 | 70 | #define TFT_CNTRL GPIOB 71 | //Control pins |RD |WR |RS |CS |RST| 72 | //Pin stm32 |PB3|PB4|PB5|PB6|PB7| 73 | #define TFT_RD PB3 74 | #define TFT_WR PB4 75 | #define TFT_RS PB5 76 | #define TFT_CS PB6 77 | #define TFT_RST PB7 78 | #define TFT_RD_MASK digitalPinToBitMask(TFT_RD) 79 | #define TFT_WR_MASK digitalPinToBitMask(TFT_WR) 80 | #define TFT_RS_MASK digitalPinToBitMask(TFT_RS) 81 | #define TFT_CS_MASK digitalPinToBitMask(TFT_CS) 82 | #define TFT_RST_MASK digitalPinToBitMask(TFT_RST) 83 | 84 | #define RD_ACTIVE TFT_CNTRL->regs->BRR = TFT_RD_MASK 85 | #define RD_IDLE TFT_CNTRL->regs->BSRR = TFT_RD_MASK 86 | #define WR_ACTIVE TFT_CNTRL->regs->BRR = TFT_WR_MASK 87 | #define WR_IDLE TFT_CNTRL->regs->BSRR = TFT_WR_MASK 88 | #define CD_COMMAND TFT_CNTRL->regs->BRR = TFT_RS_MASK 89 | #define CD_DATA TFT_CNTRL->regs->BSRR = TFT_RS_MASK 90 | #define CS_ACTIVE TFT_CNTRL->regs->BRR = TFT_CS_MASK 91 | #define CS_IDLE TFT_CNTRL->regs->BSRR = TFT_CS_MASK 92 | #define RST_ACTIVE TFT_CNTRL->regs->BRR = TFT_RST_MASK 93 | #define RST_IDLE TFT_CNTRL->regs->BSRR = TFT_RST_MASK 94 | 95 | #define RD_STROBE {RD_ACTIVE; RD_IDLE;} // Not used 96 | #define WR_STROBE {WR_ACTIVE; WR_IDLE;} 97 | #define swap(a, b) {int16_t t = a; a = b; b = t;} // Not used 98 | 99 | 100 | class STM32_TFT_8bit : public Adafruit_GFX { 101 | 102 | public: 103 | 104 | STM32_TFT_8bit(void); 105 | 106 | void setResolution(int16_t width, int16_t height); 107 | void setOffset(int16_t offset); 108 | void begin(uint16_t ID); 109 | void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); 110 | void fillScreen(uint16_t color); 111 | void drawLine(int16_t x0, int16_t y0,int16_t x1, int16_t y1, uint16_t color); 112 | void drawPixel(int16_t x, int16_t y, uint16_t color); 113 | void pushColors8(uint8_t * block, int16_t n, bool first); 114 | void pushColors(uint16_t * block, int16_t n, bool first); 115 | void drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color); 116 | void drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color); 117 | void fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color); 118 | uint16_t color565(uint8_t r, uint8_t g, uint8_t b); 119 | int16_t readGRAM(int16_t x, int16_t y, uint16_t * block, int16_t w, int16_t h); 120 | uint16_t readPixel(int16_t x, int16_t y) { uint16_t color; readGRAM(x, y, &color, 1, 1); return color; } 121 | void setRotation(uint8_t r); 122 | void vertScroll(int16_t top, int16_t scrollines, int16_t offset); 123 | void invertDisplay(boolean i); 124 | 125 | /* These are not for current use, 8-bit protocol only! */ 126 | //uint8_t readdata(void), 127 | uint8_t readcommand8(uint8_t reg); 128 | uint16_t read16bits(void); 129 | uint16_t readReg16(uint16_t reg); 130 | uint16_t readReg16Index(uint16_t reg, int8_t index); 131 | uint32_t readReg32(uint16_t reg); 132 | uint32_t readReg40(uint16_t reg); 133 | uint16_t readID(void); 134 | 135 | 136 | private: 137 | //uint8_t tabcolor; 138 | uint8_t read8(void); 139 | void setReadDataBus(void); 140 | void setWriteDataBus(void); 141 | void write8(uint8_t); 142 | void writeCmdByte(uint8_t c); 143 | void writeCmdWord(uint16_t c); 144 | void WriteCmd(uint16_t c); 145 | void writeDataByte(uint8_t d); 146 | void writeDataWord(uint16_t d); 147 | void WriteCmdData(uint16_t cmd, uint16_t dat); 148 | void WriteCmdParamN(uint8_t cmd, int8_t N, uint8_t * block); 149 | void WriteCmdParam4(uint8_t cmd, uint8_t d1, uint8_t d2, uint8_t d3, uint8_t d4); 150 | void init_table(const void *table, int16_t size); 151 | void init_table16(const void *table, int16_t size); 152 | uint16_t _lcd_xor, _lcd_capable; 153 | uint16_t _lcd_ID, _lcd_rev, _lcd_madctl, _lcd_drivOut, _MC, _MP, _MW, _SC, _EC, _SP, _EP; 154 | int16_t _lcd_width = 0, _lcd_height = 0, _lcd_offset=0; 155 | }; 156 | 157 | #endif //endif of the header file 158 | -------------------------------------------------------------------------------- /examples/ClockAnalog_STM32/ClockAnalog_STM32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | An example analogue clock using a TFT LCD screen to show the time 3 | use of some of the drawing commands with the Adafruit_GFX library. 4 | For a more accurate clock, it would be better to use the RTC library. 5 | But this is just a demo. 6 | 7 | Gilchrist 6/2/2014 1.0 8 | Updated by Alan Senior 18/1/2015 9 | Updated by nopnop2002 5/1/2018 10 | */ 11 | 12 | 13 | #include 14 | #include "STM32_TFT_8bit.h" 15 | 16 | STM32_TFT_8bit tft; 17 | 18 | float sx = 0, sy = 1, mx = 1, my = 0, hx = -1, hy = 0; // Saved H, M, S x & y multipliers 19 | float sdeg=0, mdeg=0, hdeg=0; 20 | uint16_t osx=120, osy=120, omx=120, omy=120, ohx=120, ohy=120; // Saved H, M, S x & y coords 21 | uint16_t x00=0, x11=0, y00=0, y11=0; 22 | uint32_t targetTime = 0; // for next 1 second timeout 23 | uint8_t hh,mm,ss; 24 | boolean initial = 1; 25 | 26 | void setup(void) { 27 | delay(1000); 28 | Serial.begin(9600); 29 | hh=conv2d(__TIME__); 30 | mm=conv2d(__TIME__+3); 31 | ss=conv2d(__TIME__+6); // Get H, M, S from compile time 32 | uint16_t ID = tft.readID(); 33 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 34 | tft.begin(ID); 35 | uint16_t wid = tft.width(); 36 | uint16_t ht = tft.height(); 37 | Serial.println("width=" + String(wid) + " height=" + String(ht)); 38 | 39 | if (wid < ht) { 40 | tft.setRotation(0); 41 | } else { 42 | tft.setRotation(1); 43 | } 44 | tft.fillScreen(GRAY); 45 | tft.setTextColor(WHITE, GRAY); // Adding a background colour erases previous text automatically 46 | 47 | // Draw clock face 48 | tft.fillCircle(120, 120, 118, GREEN); 49 | tft.fillCircle(120, 120, 110, BLACK); 50 | 51 | // Draw 12 lines 52 | for(int i = 0; i<360; i+= 30) { 53 | sx = cos((i-90)*0.0174532925); 54 | sy = sin((i-90)*0.0174532925); 55 | x00 = sx*114+120; 56 | y00 = sy*114+120; 57 | x11 = sx*100+120; 58 | y11 = sy*100+120; 59 | 60 | tft.drawLine(x00, y00, x11, y11, GREEN); 61 | } 62 | 63 | // Draw 60 dots 64 | for(int i = 0; i<360; i+= 6) { 65 | sx = cos((i-90)*0.0174532925); 66 | sy = sin((i-90)*0.0174532925); 67 | x00 = sx*102+120; 68 | y00 = sy*102+120; 69 | // Draw minute markers 70 | tft.drawPixel(x00, y00, WHITE); 71 | 72 | // Draw main quadrant dots 73 | if(i==0 || i==180) tft.fillCircle(x00, y00, 2, WHITE); 74 | if(i==90 || i==270) tft.fillCircle(x00, y00, 2, WHITE); 75 | } 76 | 77 | tft.fillCircle(120, 121, 3, WHITE); 78 | tft.setCursor(20, 260); 79 | tft.setTextSize(3); 80 | tft.println(__DATE__); 81 | targetTime = millis() + 1000; 82 | } 83 | 84 | void loop() { 85 | 86 | if (targetTime < millis()) { 87 | targetTime = millis()+1000; 88 | ss++; // Advance second 89 | if (ss==60) { 90 | ss=0; 91 | mm++; // Advance minute 92 | if(mm>59) { 93 | mm=0; 94 | hh++; // Advance hour 95 | if (hh>23) { 96 | hh=0; 97 | } 98 | } 99 | } 100 | #ifdef _DEBUG_ 101 | Serial.print("hh="); 102 | Serial.print(hh); 103 | Serial.print(" mm="); 104 | Serial.print(mm); 105 | Serial.print(" ss="); 106 | Serial.println(ss); 107 | #endif 108 | 109 | // Pre-compute hand degrees, x & y coords for a fast screen update 110 | sdeg = ss*6; // 0-59 -> 0-354 111 | mdeg = mm*6+sdeg*0.01666667; // 0-59 -> 0-360 - includes seconds 112 | hdeg = hh*30+mdeg*0.0833333; // 0-11 -> 0-360 - includes minutes and seconds 113 | hx = cos((hdeg-90)*0.0174532925); 114 | hy = sin((hdeg-90)*0.0174532925); 115 | mx = cos((mdeg-90)*0.0174532925); 116 | my = sin((mdeg-90)*0.0174532925); 117 | sx = cos((sdeg-90)*0.0174532925); 118 | sy = sin((sdeg-90)*0.0174532925); 119 | 120 | if (ss==0 || initial) { 121 | initial = 0; 122 | // Erase hour and minute hand positions every minute 123 | tft.drawLine(ohx, ohy, 120, 121, BLACK); 124 | ohx = hx*62+121; 125 | ohy = hy*62+121; 126 | tft.drawLine(omx, omy, 120, 121, BLACK); 127 | omx = mx*84+120; 128 | omy = my*84+121; 129 | } 130 | 131 | // Redraw new hand positions, hour and minute hands not erased here to avoid flicker 132 | tft.drawLine(osx, osy, 120, 121, BLACK); 133 | osx = sx*90+121; 134 | osy = sy*90+121; 135 | tft.drawLine(osx, osy, 120, 121, RED); 136 | tft.drawLine(ohx, ohy, 120, 121, WHITE); 137 | tft.drawLine(omx, omy, 120, 121, WHITE); 138 | tft.drawLine(osx, osy, 120, 121, RED); 139 | 140 | tft.fillCircle(120, 121, 3, RED); 141 | } 142 | } 143 | 144 | static uint8_t conv2d(const char* p) { 145 | uint8_t v = 0; 146 | if ('0' <= *p && *p <= '9') 147 | v = *p - '0'; 148 | return 10 * v + *++p - '0'; 149 | } 150 | 151 | -------------------------------------------------------------------------------- /examples/CubeDemo_STM32/CubeDemo_STM32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Cube demo for STM32 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include "STM32_TFT_8bit.h" 20 | 21 | STM32_TFT_8bit tft; 22 | 23 | #define BACK_COLOR WHITE // You can change 24 | 25 | const float sin_d[] = { 26 | 0, 0.17, 0.34, 0.5, 0.64, 0.77, 0.87, 0.94, 0.98, 1, 0.98, 0.94, 27 | 0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34, -0.5, -0.64, 28 | -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87, -0.77, 29 | -0.64, -0.5, -0.34, -0.17 30 | }; 31 | const float cos_d[] = { 32 | 1, 0.98, 0.94, 0.87, 0.77, 0.64, 0.5, 0.34, 0.17, 0, -0.17, -0.34, 33 | -0.5, -0.64, -0.77, -0.87, -0.94, -0.98, -1, -0.98, -0.94, -0.87, 34 | -0.77, -0.64, -0.5, -0.34, -0.17, 0, 0.17, 0.34, 0.5, 0.64, 0.77, 35 | 0.87, 0.94, 0.98 36 | }; 37 | const float d = 5; 38 | float cube1_px[] = { 39 | -d, d, d, -d, -d, d, d, -d 40 | }; 41 | float cube1_py[] = { 42 | -d, -d, d, d, -d, -d, d, d 43 | }; 44 | float cube1_pz[] = { 45 | -d, -d, -d, -d, d, d, d, d 46 | }; 47 | 48 | float cube1_p2x[] = { 49 | 0, 0, 0, 0, 0, 0, 0, 0 50 | }; 51 | float cube1_p2y[] = { 52 | 0, 0, 0, 0, 0, 0, 0, 0 53 | }; 54 | 55 | int cube1_r[] = { 56 | 0, 0, 0 57 | }; 58 | const float d2 = 10; 59 | float cube2_px[] = { 60 | -d2, d2, d2, -d2, -d2, d2, d2, -d2 61 | }; 62 | float cube2_py[] = { 63 | -d2, -d2, d2, d2, -d2, -d2, d2, d2 64 | }; 65 | float cube2_pz[] = { 66 | -d2, -d2, -d2, -d2, d2, d2, d2, d2 67 | }; 68 | 69 | float cube2_p2x[] = { 70 | 0, 0, 0, 0, 0, 0, 0, 0 71 | }; 72 | float cube2_p2y[] = { 73 | 0, 0, 0, 0, 0, 0, 0, 0 74 | }; 75 | 76 | int cube2_r[] = { 77 | 0, 0, 0 78 | }; 79 | 80 | uint16_t cube1_x, cube1_y, cube2_x, cube2_y, cube1_color, cube2_color; 81 | 82 | 83 | void cube(float *px, float *py, float *pz, float *p2x, float *p2y, int *r, uint16_t *x, uint16_t *y, uint16_t *color) { 84 | 85 | for (int i = 0; i < 3; i++) { 86 | tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], BACK_COLOR); 87 | tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], BACK_COLOR); 88 | tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], BACK_COLOR); 89 | } 90 | tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], BACK_COLOR); 91 | tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], BACK_COLOR); 92 | tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], BACK_COLOR); 93 | 94 | r[0] = r[0] + 1; 95 | r[1] = r[1] + 1; 96 | if (r[0] == 36) r[0] = 0; 97 | if (r[1] == 36) r[1] = 0; 98 | if (r[2] == 36) r[2] = 0; 99 | for (int i = 0; i < 8; i++) 100 | { 101 | float px2 = px[i]; 102 | float py2 = cos_d[r[0]] * py[i] - sin_d[r[0]] * pz[i]; 103 | float pz2 = sin_d[r[0]] * py[i] + cos_d[r[0]] * pz[i]; 104 | 105 | float px3 = cos_d[r[1]] * px2 + sin_d[r[1]] * pz2; 106 | float py3 = py2; 107 | float pz3 = -sin_d[r[1]] * px2 + cos_d[r[1]] * pz2; 108 | 109 | float ax = cos_d[r[2]] * px3 - sin_d[r[2]] * py3; 110 | float ay = sin_d[r[2]] * px3 + cos_d[r[2]] * py3; 111 | float az = pz3 - 190; 112 | 113 | p2x[i] = *x + ax * 500 / az; 114 | p2y[i] = *y + ay * 500 / az; 115 | } 116 | 117 | for (int i = 0; i < 3; i++) { 118 | tft.drawLine(p2x[i], p2y[i], p2x[i + 1], p2y[i + 1], *color); 119 | tft.drawLine(p2x[i + 4], p2y[i + 4], p2x[i + 5], p2y[i + 5], *color); 120 | tft.drawLine(p2x[i], p2y[i], p2x[i + 4], p2y[i + 4], *color); 121 | } 122 | tft.drawLine(p2x[3], p2y[3], p2x[0], p2y[0], *color); 123 | tft.drawLine(p2x[7], p2y[7], p2x[4], p2y[4], *color); 124 | tft.drawLine(p2x[3], p2y[3], p2x[7], p2y[7], *color); 125 | } 126 | 127 | 128 | void setup() { 129 | delay(1000); 130 | Serial.begin(9600); 131 | Serial.println("STM32_TFT_8bit Test!"); 132 | 133 | uint32_t ID = tft.readID(); 134 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 135 | tft.begin(ID); 136 | 137 | uint32_t width = tft.width(); 138 | Serial.print("Width: "); Serial.println(width); 139 | uint32_t height = tft.height(); 140 | Serial.print("Height: "); Serial.println(height); 141 | 142 | tft.fillScreen(BACK_COLOR); 143 | cube1_x = ((tft.width()) / 4); 144 | cube1_y = ((tft.height()) / 4); 145 | cube2_x = ((tft.width()) / 2); 146 | cube2_y = ((tft.height()) / 2); 147 | cube1_color = BLACK; 148 | cube2_color = RED; 149 | 150 | uint16_t x = 0; 151 | for (uint32_t n = 247583650 ; n > 247400000 ; n--) { 152 | x = sqrt (n); 153 | cube(cube1_px, cube1_py, cube1_pz, cube1_p2x, cube1_p2y, cube1_r, &cube1_x, &cube1_y, &cube1_color); 154 | cube(cube2_px, cube2_py, cube2_pz, cube2_p2x, cube2_p2y, cube2_r, &cube2_x, &cube2_y, &cube2_color); 155 | } 156 | 157 | } 158 | 159 | void loop() { 160 | } 161 | -------------------------------------------------------------------------------- /examples/GraphicsTest_240x320_SMT32/GraphicsTest_240x320_SMT32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include "STM32_TFT_8bit.h" 23 | 24 | STM32_TFT_8bit tft; 25 | 26 | uint32_t ID; 27 | 28 | void setup() { 29 | delay(1000); 30 | Serial.begin(9600); 31 | Serial.println("STM32_TFT_8bit Test!"); 32 | 33 | ID = tft.readID(); 34 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 35 | tft.begin(ID); 36 | 37 | uint32_t width = tft.width(); 38 | Serial.print("Width: "); Serial.println(width); 39 | uint32_t height = tft.height(); 40 | Serial.print("Height: "); Serial.println(height); 41 | 42 | Serial.println(F("Benchmark Time (microseconds)")); 43 | 44 | Serial.print(F("Screen fill ")); 45 | Serial.println(testFillScreen()); 46 | delay(500); 47 | 48 | Serial.print(F("Text ")); 49 | Serial.println(testText(ID)); 50 | delay(3000); 51 | 52 | Serial.print(F("Lines ")); 53 | Serial.println(testLines(CYAN)); 54 | delay(500); 55 | 56 | Serial.print(F("Horiz/Vert Lines ")); 57 | Serial.println(testFastLines(RED, BLUE)); 58 | delay(500); 59 | 60 | Serial.print(F("Rectangles (outline) ")); 61 | Serial.println(testRects(GREEN)); 62 | delay(500); 63 | 64 | Serial.print(F("Rectangles (filled) ")); 65 | Serial.println(testFilledRects(YELLOW, MAGENTA)); 66 | delay(500); 67 | 68 | Serial.print(F("Circles (filled) ")); 69 | Serial.println(testFilledCircles(10, MAGENTA)); 70 | 71 | Serial.print(F("Circles (outline) ")); 72 | Serial.println(testCircles(10, WHITE)); 73 | delay(500); 74 | 75 | Serial.print(F("Triangles (outline) ")); 76 | Serial.println(testTriangles()); 77 | delay(500); 78 | 79 | Serial.print(F("Triangles (filled) ")); 80 | Serial.println(testFilledTriangles()); 81 | delay(500); 82 | 83 | Serial.print(F("Rounded rects (outline) ")); 84 | Serial.println(testRoundRects()); 85 | delay(500); 86 | 87 | Serial.print(F("Rounded rects (filled) ")); 88 | Serial.println(testFilledRoundRects()); 89 | delay(500); 90 | 91 | Serial.println(F("Done!")); 92 | 93 | } 94 | 95 | 96 | void loop(void) { 97 | for(uint8_t rotation=0; rotation<4; rotation++) { 98 | tft.setRotation(rotation); 99 | testText(ID); 100 | delay(1000); 101 | } 102 | } 103 | 104 | unsigned long testFillScreen() { 105 | unsigned long start = micros(); 106 | tft.fillScreen(BLACK); 107 | tft.fillScreen(RED); 108 | tft.fillScreen(GREEN); 109 | tft.fillScreen(BLUE); 110 | tft.fillScreen(BLACK); 111 | return micros() - start; 112 | } 113 | 114 | unsigned long testText(uint32_t ID) { 115 | tft.fillScreen(BLACK); 116 | unsigned long start = micros(); 117 | tft.setCursor(0, 0); 118 | tft.setTextColor(WHITE); tft.setTextSize(1); 119 | tft.println("Hello World!"); 120 | tft.setTextColor(YELLOW); tft.setTextSize(2); 121 | tft.println(1234.56); 122 | tft.setTextColor(RED); tft.setTextSize(3); 123 | tft.print("TFT is "); 124 | tft.println(ID, HEX); 125 | tft.println(); 126 | tft.setTextColor(GREEN); 127 | tft.setTextSize(5); 128 | tft.println("Groop"); 129 | tft.setTextSize(2); 130 | tft.println("I implore thee,"); 131 | tft.setTextSize(1); 132 | tft.println("my foonting turlingdromes."); 133 | tft.println("And hooptiously drangle me"); 134 | tft.println("with crinkly bindlewurdles,"); 135 | tft.println("Or I will rend thee"); 136 | tft.println("in the gobberwarts"); 137 | tft.println("with my blurglecruncheon,"); 138 | tft.println("see if I don't!"); 139 | return micros() - start; 140 | } 141 | 142 | unsigned long testLines(uint16_t color) { 143 | unsigned long start, t; 144 | int x1, y1, x2, y2, 145 | w = tft.width(), 146 | h = tft.height(); 147 | 148 | tft.fillScreen(BLACK); 149 | 150 | x1 = y1 = 0; 151 | y2 = h - 1; 152 | start = micros(); 153 | for(x2=0; x20; i-=6) { 231 | i2 = i / 2; 232 | start = micros(); 233 | tft.fillRect(cx-i2, cy-i2, i, i, color1); 234 | t += micros() - start; 235 | // Outlines are not included in timing results 236 | tft.drawRect(cx-i2, cy-i2, i, i, color2); 237 | } 238 | 239 | return t; 240 | } 241 | 242 | unsigned long testFilledCircles(uint8_t radius, uint16_t color) { 243 | unsigned long start; 244 | int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; 245 | 246 | tft.fillScreen(BLACK); 247 | start = micros(); 248 | for(x=radius; x10; i-=5) { 302 | start = micros(); 303 | tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 304 | BLACK); 305 | t += micros() - start; 306 | tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 307 | MAROON); 308 | } 309 | 310 | return t; 311 | } 312 | 313 | unsigned long testRoundRects() { 314 | unsigned long start; 315 | int w, i, i2, 316 | cx = tft.width() / 2 - 1, 317 | cy = tft.height() / 2 - 1; 318 | 319 | tft.fillScreen(BLACK); 320 | w = min(tft.width(), tft.height()); 321 | start = micros(); 322 | for(i=0; i20; i-=6) { 339 | i2 = i / 2; 340 | tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, DARKCYAN); 341 | } 342 | 343 | return micros() - start; 344 | } 345 | -------------------------------------------------------------------------------- /examples/GraphicsTest_240x400_SMT32/GraphicsTest_240x400_SMT32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include "STM32_TFT_8bit.h" 23 | 24 | STM32_TFT_8bit tft; 25 | 26 | uint32_t ID; 27 | 28 | void setup() { 29 | delay(1000); 30 | Serial.begin(9600); 31 | Serial.println("STM32_TFT_8bit Test!"); 32 | 33 | ID = tft.readID(); 34 | // Set your TFT's resolution 35 | tft.setResolution(240, 400); // Set your resolution 36 | // Set your TFT's offset 37 | tft.setOffset(32); // Set your offset 38 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 39 | tft.begin(ID); 40 | 41 | uint32_t width = tft.width(); 42 | Serial.print("Width: "); Serial.println(width); 43 | uint32_t height = tft.height(); 44 | Serial.print("Height: "); Serial.println(height); 45 | 46 | Serial.println(F("Benchmark Time (microseconds)")); 47 | 48 | Serial.print(F("Screen fill ")); 49 | Serial.println(testFillScreen()); 50 | delay(500); 51 | 52 | Serial.print(F("Text ")); 53 | Serial.println(testText(ID)); 54 | delay(3000); 55 | 56 | Serial.print(F("Lines ")); 57 | Serial.println(testLines(CYAN)); 58 | delay(500); 59 | 60 | Serial.print(F("Horiz/Vert Lines ")); 61 | Serial.println(testFastLines(RED, BLUE)); 62 | delay(500); 63 | 64 | Serial.print(F("Rectangles (outline) ")); 65 | Serial.println(testRects(GREEN)); 66 | delay(500); 67 | 68 | Serial.print(F("Rectangles (filled) ")); 69 | Serial.println(testFilledRects(YELLOW, MAGENTA)); 70 | delay(500); 71 | 72 | Serial.print(F("Circles (filled) ")); 73 | Serial.println(testFilledCircles(10, MAGENTA)); 74 | 75 | Serial.print(F("Circles (outline) ")); 76 | Serial.println(testCircles(10, WHITE)); 77 | delay(500); 78 | 79 | Serial.print(F("Triangles (outline) ")); 80 | Serial.println(testTriangles()); 81 | delay(500); 82 | 83 | Serial.print(F("Triangles (filled) ")); 84 | Serial.println(testFilledTriangles()); 85 | delay(500); 86 | 87 | Serial.print(F("Rounded rects (outline) ")); 88 | Serial.println(testRoundRects()); 89 | delay(500); 90 | 91 | Serial.print(F("Rounded rects (filled) ")); 92 | Serial.println(testFilledRoundRects()); 93 | delay(500); 94 | 95 | Serial.println(F("Done!")); 96 | 97 | } 98 | 99 | 100 | void loop(void) { 101 | for(uint8_t rotation=0; rotation<4; rotation++) { 102 | tft.setRotation(rotation); 103 | testText(ID); 104 | delay(1000); 105 | } 106 | } 107 | 108 | unsigned long testFillScreen() { 109 | unsigned long start = micros(); 110 | tft.fillScreen(BLACK); 111 | tft.fillScreen(RED); 112 | tft.fillScreen(GREEN); 113 | tft.fillScreen(BLUE); 114 | tft.fillScreen(BLACK); 115 | return micros() - start; 116 | } 117 | 118 | unsigned long testText(uint32_t ID) { 119 | tft.fillScreen(BLACK); 120 | unsigned long start = micros(); 121 | tft.setCursor(0, 0); 122 | tft.setTextColor(WHITE); tft.setTextSize(1); 123 | tft.println("Hello World!"); 124 | tft.setTextColor(YELLOW); tft.setTextSize(2); 125 | tft.println(1234.56); 126 | tft.setTextColor(RED); tft.setTextSize(3); 127 | tft.print("TFT is "); 128 | tft.println(ID, HEX); 129 | tft.println(); 130 | tft.setTextColor(GREEN); 131 | tft.setTextSize(5); 132 | tft.println("Groop"); 133 | tft.setTextSize(2); 134 | tft.println("I implore thee,"); 135 | tft.setTextSize(1); 136 | tft.println("my foonting turlingdromes."); 137 | tft.println("And hooptiously drangle me"); 138 | tft.println("with crinkly bindlewurdles,"); 139 | tft.println("Or I will rend thee"); 140 | tft.println("in the gobberwarts"); 141 | tft.println("with my blurglecruncheon,"); 142 | tft.println("see if I don't!"); 143 | return micros() - start; 144 | } 145 | 146 | unsigned long testLines(uint16_t color) { 147 | unsigned long start, t; 148 | int x1, y1, x2, y2, 149 | w = tft.width(), 150 | h = tft.height(); 151 | 152 | tft.fillScreen(BLACK); 153 | 154 | x1 = y1 = 0; 155 | y2 = h - 1; 156 | start = micros(); 157 | for(x2=0; x20; i-=6) { 235 | i2 = i / 2; 236 | start = micros(); 237 | tft.fillRect(cx-i2, cy-i2, i, i, color1); 238 | t += micros() - start; 239 | // Outlines are not included in timing results 240 | tft.drawRect(cx-i2, cy-i2, i, i, color2); 241 | } 242 | 243 | return t; 244 | } 245 | 246 | unsigned long testFilledCircles(uint8_t radius, uint16_t color) { 247 | unsigned long start; 248 | int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; 249 | 250 | tft.fillScreen(BLACK); 251 | start = micros(); 252 | for(x=radius; x10; i-=5) { 306 | start = micros(); 307 | tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 308 | BLACK); 309 | t += micros() - start; 310 | tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 311 | MAROON); 312 | } 313 | 314 | return t; 315 | } 316 | 317 | unsigned long testRoundRects() { 318 | unsigned long start; 319 | int w, i, i2, 320 | cx = tft.width() / 2 - 1, 321 | cy = tft.height() / 2 - 1; 322 | 323 | tft.fillScreen(BLACK); 324 | w = min(tft.width(), tft.height()); 325 | start = micros(); 326 | for(i=0; i20; i-=6) { 343 | i2 = i / 2; 344 | tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, DARKCYAN); 345 | } 346 | 347 | return micros() - start; 348 | } 349 | -------------------------------------------------------------------------------- /examples/GraphicsTest_320x480_SMT32/GraphicsTest_320x480_SMT32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include "STM32_TFT_8bit.h" 23 | 24 | STM32_TFT_8bit tft; 25 | 26 | uint32_t ID; 27 | 28 | void setup() { 29 | delay(1000); 30 | Serial.begin(9600); 31 | Serial.println("STM32_TFT_8bit Test!"); 32 | 33 | ID = tft.readID(); 34 | tft.setResolution(320, 480); // Set your resolution 35 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 36 | tft.begin(ID); 37 | 38 | uint32_t width = tft.width(); 39 | Serial.print("Width: "); Serial.println(width); 40 | uint32_t height = tft.height(); 41 | Serial.print("Height: "); Serial.println(height); 42 | 43 | Serial.println(F("Benchmark Time (microseconds)")); 44 | 45 | Serial.print(F("Screen fill ")); 46 | Serial.println(testFillScreen()); 47 | delay(500); 48 | 49 | Serial.print(F("Text ")); 50 | Serial.println(testText(ID)); 51 | delay(3000); 52 | 53 | Serial.print(F("Lines ")); 54 | Serial.println(testLines(CYAN)); 55 | delay(500); 56 | 57 | Serial.print(F("Horiz/Vert Lines ")); 58 | Serial.println(testFastLines(RED, BLUE)); 59 | delay(500); 60 | 61 | Serial.print(F("Rectangles (outline) ")); 62 | Serial.println(testRects(GREEN)); 63 | delay(500); 64 | 65 | Serial.print(F("Rectangles (filled) ")); 66 | Serial.println(testFilledRects(YELLOW, MAGENTA)); 67 | delay(500); 68 | 69 | Serial.print(F("Circles (filled) ")); 70 | Serial.println(testFilledCircles(10, MAGENTA)); 71 | 72 | Serial.print(F("Circles (outline) ")); 73 | Serial.println(testCircles(10, WHITE)); 74 | delay(500); 75 | 76 | Serial.print(F("Triangles (outline) ")); 77 | Serial.println(testTriangles()); 78 | delay(500); 79 | 80 | Serial.print(F("Triangles (filled) ")); 81 | Serial.println(testFilledTriangles()); 82 | delay(500); 83 | 84 | Serial.print(F("Rounded rects (outline) ")); 85 | Serial.println(testRoundRects()); 86 | delay(500); 87 | 88 | Serial.print(F("Rounded rects (filled) ")); 89 | Serial.println(testFilledRoundRects()); 90 | delay(500); 91 | 92 | Serial.println(F("Done!")); 93 | 94 | } 95 | 96 | 97 | void loop(void) { 98 | for(uint8_t rotation=0; rotation<4; rotation++) { 99 | tft.setRotation(rotation); 100 | testText(ID); 101 | delay(1000); 102 | } 103 | } 104 | 105 | unsigned long testFillScreen() { 106 | unsigned long start = micros(); 107 | tft.fillScreen(BLACK); 108 | tft.fillScreen(RED); 109 | tft.fillScreen(GREEN); 110 | tft.fillScreen(BLUE); 111 | tft.fillScreen(BLACK); 112 | return micros() - start; 113 | } 114 | 115 | unsigned long testText(uint32_t ID) { 116 | tft.fillScreen(BLACK); 117 | unsigned long start = micros(); 118 | tft.setCursor(0, 0); 119 | tft.setTextColor(WHITE); tft.setTextSize(1); 120 | tft.println("Hello World!"); 121 | tft.setTextColor(YELLOW); tft.setTextSize(2); 122 | tft.println(1234.56); 123 | tft.setTextColor(RED); tft.setTextSize(3); 124 | tft.print("TFT is "); 125 | tft.println(ID, HEX); 126 | tft.println(); 127 | tft.setTextColor(GREEN); 128 | tft.setTextSize(5); 129 | tft.println("Groop"); 130 | tft.setTextSize(2); 131 | tft.println("I implore thee,"); 132 | tft.setTextSize(1); 133 | tft.println("my foonting turlingdromes."); 134 | tft.println("And hooptiously drangle me"); 135 | tft.println("with crinkly bindlewurdles,"); 136 | tft.println("Or I will rend thee"); 137 | tft.println("in the gobberwarts"); 138 | tft.println("with my blurglecruncheon,"); 139 | tft.println("see if I don't!"); 140 | return micros() - start; 141 | } 142 | 143 | unsigned long testLines(uint16_t color) { 144 | unsigned long start, t; 145 | int x1, y1, x2, y2, 146 | w = tft.width(), 147 | h = tft.height(); 148 | 149 | tft.fillScreen(BLACK); 150 | 151 | x1 = y1 = 0; 152 | y2 = h - 1; 153 | start = micros(); 154 | for(x2=0; x20; i-=6) { 232 | i2 = i / 2; 233 | start = micros(); 234 | tft.fillRect(cx-i2, cy-i2, i, i, color1); 235 | t += micros() - start; 236 | // Outlines are not included in timing results 237 | tft.drawRect(cx-i2, cy-i2, i, i, color2); 238 | } 239 | 240 | return t; 241 | } 242 | 243 | unsigned long testFilledCircles(uint8_t radius, uint16_t color) { 244 | unsigned long start; 245 | int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2; 246 | 247 | tft.fillScreen(BLACK); 248 | start = micros(); 249 | for(x=radius; x10; i-=5) { 303 | start = micros(); 304 | tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 305 | BLACK); 306 | t += micros() - start; 307 | tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i, 308 | MAROON); 309 | } 310 | 311 | return t; 312 | } 313 | 314 | unsigned long testRoundRects() { 315 | unsigned long start; 316 | int w, i, i2, 317 | cx = tft.width() / 2 - 1, 318 | cy = tft.height() / 2 - 1; 319 | 320 | tft.fillScreen(BLACK); 321 | w = min(tft.width(), tft.height()); 322 | start = micros(); 323 | for(i=0; i20; i-=6) { 340 | i2 = i / 2; 341 | tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, DARKCYAN); 342 | } 343 | 344 | return micros() - start; 345 | } 346 | -------------------------------------------------------------------------------- /examples/JpegView_240x320_SMT32/JPEG_Functions.ino: -------------------------------------------------------------------------------- 1 | /*==================================================================================== 2 | This sketch contains support functions to render the Jpeg images. 3 | 4 | Created by Bodmer 5th Feb 2017 5 | Updated by nopnop2002 19/4/2018 6 | ==================================================================================*/ 7 | 8 | // Return the minimum of two values a and b 9 | #define minimum(a,b) (((a) < (b)) ? (a) : (b)) 10 | #define maximum(a,b) (((a) > (b)) ? (a) : (b)) 11 | 12 | //==================================================================================== 13 | // This function opens the array and primes the decoder 14 | //==================================================================================== 15 | void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int ypos) { 16 | 17 | boolean decoded = JpegDec.decodeArray(arrayname, array_size); 18 | 19 | if (decoded) { 20 | // print information about the image to the serial port 21 | jpegInfo(); 22 | 23 | // render the image onto the screen at given coordinates 24 | jpegRender(xpos, ypos, 0); 25 | } 26 | else { 27 | Serial.println("Jpeg file format not supported!"); 28 | } 29 | } 30 | 31 | //==================================================================================== 32 | // This function opens the Filing System Jpeg image file and primes the decoder 33 | // 34 | // options : OPT_REDUCTION 35 | // If it's large than screen, it would reduce so that it may fit into a screen. 36 | // OPT_CENTER 37 | // If it's smaller than screen, it would show to the center of the screen. 38 | //==================================================================================== 39 | void drawFSJpeg(const char *filename, int xpos, int ypos, int options) { 40 | 41 | Serial.println("====================================="); 42 | Serial.print("Drawing file: "); Serial.println(filename); 43 | Serial.println("====================================="); 44 | 45 | // Open the file (the Jpeg decoder library will close it) 46 | File jpgFile = SD.open( filename, FILE_READ); // file handle reference for SD library 47 | 48 | if ( !jpgFile ) { 49 | Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); 50 | return; 51 | } 52 | 53 | // To initialise the decoder and provide the file, we can use one of the following methods: 54 | boolean decoded = JpegDec.decodeSdFile(jpgFile); // we can pass the SD file handle to the decoder, 55 | //boolean decoded = JpegDec.decodeFsFile(filename); // or we can pass the filename 56 | // The filename can be a String or character array 57 | if (decoded) { 58 | // print information about the image to the serial port 59 | jpegInfo(); 60 | 61 | // render the image onto the screen at given coordinates 62 | jpegRender(xpos, ypos, options); 63 | } 64 | else { 65 | Serial.println("Jpeg file format not supported!"); 66 | } 67 | } 68 | 69 | //==================================================================================== 70 | // Decode and paint onto the TFT screen 71 | //==================================================================================== 72 | void jpegRender(int xpos, int ypos, int options) { 73 | 74 | //if (options & OPT_REDUCTION) Serial.println("OPT_REDUCTION"); 75 | //if (options & OPT_CENTER) Serial.println("OPT_CENTER"); 76 | // retrieve infomration about the image 77 | uint16_t *pImg; 78 | uint16_t mcu_w = JpegDec.MCUWidth; 79 | uint16_t mcu_h = JpegDec.MCUHeight; 80 | uint32_t max_x = JpegDec.width; 81 | uint32_t max_y = JpegDec.height; 82 | //Serial.println("mcu_w=" + String(mcu_w)); 83 | //Serial.println("mcu_h=" + String(mcu_h)); 84 | //Serial.println("max_x=" + String(max_x)); 85 | //Serial.println("max_y=" + String(max_y)); 86 | 87 | uint16_t szImg2 = mcu_w * mcu_h; 88 | uint16_t *pImg2; 89 | pImg2 = (uint16_t *) malloc(szImg2*2); 90 | 91 | uint32_t tft_width = tft.width(); 92 | //Serial.print("tft_width: "); Serial.println(tft_width); 93 | uint32_t tft_height = tft.height(); 94 | //Serial.print("tft_height: "); Serial.println(tft_height); 95 | 96 | int reduction_x = 1; 97 | int reduction_y = 1; 98 | if (max_x > tft_width) { 99 | reduction_x = (max_x / tft_width); 100 | if (max_x % tft_width) reduction_x++; 101 | } 102 | if (max_y > tft_height) { 103 | reduction_y = (max_y / tft_height); 104 | if (max_y % tft_height) reduction_y++; 105 | } 106 | //Serial.println("reduction_x=" + String(reduction_x)); 107 | //Serial.println("reduction_y=" + String(reduction_y)); 108 | int reduction = maximum(reduction_x, reduction_y); 109 | //Serial.println("reduction=" + String(reduction)); 110 | 111 | // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) 112 | // Typically these MCUs are 16x16 pixel blocks 113 | // Determine the width and height of the right and bottom edge image blocks 114 | uint32_t min_w = minimum(mcu_w, max_x % mcu_w); 115 | uint32_t min_h = minimum(mcu_h, max_y % mcu_h); 116 | //Serial.println("min_w=" + String(min_w)); 117 | //Serial.println("min_h=" + String(min_h)); 118 | 119 | 120 | // save the current image block size 121 | uint32_t win_w = mcu_w; 122 | uint32_t win_h = mcu_h; 123 | 124 | // record the current time so we can measure how long it takes to draw an image 125 | uint32_t drawTime = millis(); 126 | 127 | uint16_t max_xx = max_x; 128 | uint16_t max_yy = max_y; 129 | if (reduction > 1 && (options & OPT_REDUCTION) ) { 130 | max_xx = max_x / reduction; // new image size of X 131 | max_yy = max_y / reduction; // new image size of Y 132 | } 133 | //Serial.println("max_xx=" + String(max_xx)); 134 | //Serial.println("max_yy=" + String(max_yy)); 135 | 136 | // calculation center position 137 | int delta_x = 0; 138 | int delta_y = 0; 139 | if ( (max_xx < tft_width) && (options & OPT_CENTER) ) { 140 | delta_x = (tft_width - max_xx) / 2; 141 | } 142 | if ( (max_yy < tft_height) && (options & OPT_CENTER) ) { 143 | delta_y = (tft_height - max_yy) / 2; 144 | } 145 | //Serial.println("delta_x=" + String(delta_x)); 146 | //Serial.println("delta_y=" + String(delta_y)); 147 | 148 | // save the coordinate of the right and bottom edges to assist image cropping 149 | // to the screen size 150 | max_x += xpos; 151 | max_y += ypos; 152 | 153 | // read each MCU block until there are no more 154 | while ( JpegDec.read()) { 155 | 156 | // save a pointer to the image block 157 | pImg = JpegDec.pImage; 158 | 159 | // calculate where the image block should be drawn on the screen 160 | int mcu_x = JpegDec.MCUx * mcu_w + xpos; 161 | int mcu_y = JpegDec.MCUy * mcu_h + ypos; 162 | 163 | // check if the image block size needs to be changed for the right and bottom edges 164 | if (mcu_x + mcu_w <= max_x) win_w = mcu_w; 165 | else win_w = min_w; 166 | if (mcu_y + mcu_h <= max_y) win_h = mcu_h; 167 | else win_h = min_h; 168 | 169 | memcpy(pImg2, JpegDec.pImage, szImg2*2); 170 | int mcu_xx = mcu_x + delta_x; 171 | int mcu_yy = mcu_y + delta_y; 172 | uint32_t win_ww = win_w; 173 | uint32_t win_hh = win_h; 174 | 175 | if (reduction > 1 && (options & OPT_REDUCTION) ){ 176 | int pos1 = 0; 177 | int pos2 = 0; 178 | for(int x=0; x 1 && (options & OPT_REDUCTION) ) { 243 | int reductionRate = (float)(1.0 / reduction) * 100; 244 | Serial.print ("Rate of reduction was : "); Serial.print(reductionRate); Serial.println(" %"); 245 | } 246 | Serial.println("====================================="); 247 | 248 | } 249 | //==================================================================================== 250 | // Send time taken to Serial port 251 | //==================================================================================== 252 | void jpegInfo() { 253 | Serial.println(F("===============")); 254 | Serial.println(F("JPEG image info")); 255 | Serial.println(F("===============")); 256 | Serial.print(F( "Width :")); Serial.println(JpegDec.width); 257 | Serial.print(F( "Height :")); Serial.println(JpegDec.height); 258 | Serial.print(F( "Components :")); Serial.println(JpegDec.comps); 259 | Serial.print(F( "MCU / row :")); Serial.println(JpegDec.MCUSPerRow); 260 | Serial.print(F( "MCU / col :")); Serial.println(JpegDec.MCUSPerCol); 261 | Serial.print(F( "Scan type :")); Serial.println(JpegDec.scanType); 262 | Serial.print(F( "MCU width :")); Serial.println(JpegDec.MCUWidth); 263 | Serial.print(F( "MCU height :")); Serial.println(JpegDec.MCUHeight); 264 | Serial.println(F("===============")); 265 | } 266 | 267 | //==================================================================================== 268 | // Open a Jpeg file on an SD card and dump it to the Serial port as a C array 269 | //==================================================================================== 270 | void createArray(const char *filename) { 271 | 272 | File jpgFile; // File handle reference For SD library 273 | 274 | if ( !( jpgFile = SD.open( filename, FILE_READ))) { 275 | Serial.println(F("JPEG file not found")); 276 | return; 277 | } 278 | 279 | uint8_t data; 280 | byte line_len = 0; 281 | Serial.println("// Generated by a JPEGDecoder library example sketch:"); 282 | Serial.println("// https://github.com/Bodmer/JPEGDecoder"); 283 | Serial.println(""); 284 | Serial.println("#if defined(__AVR__)"); 285 | Serial.println(" #include "); 286 | Serial.println("#endif"); 287 | Serial.println(""); 288 | Serial.print("const uint8_t "); 289 | while (*filename != '.') Serial.print(*filename++); 290 | Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors 291 | 292 | while ( jpgFile.available()) { 293 | 294 | data = jpgFile.read(); 295 | Serial.print("0x"); if (abs(data) < 16) Serial.print("0"); 296 | Serial.print(data, HEX); Serial.print(",");// Add value and comma 297 | line_len++; 298 | if ( line_len >= 32) { 299 | line_len = 0; 300 | Serial.println(); 301 | } 302 | 303 | } 304 | 305 | Serial.println("};\r\n"); 306 | jpgFile.close(); 307 | } 308 | 309 | // Function to print all timestamps. 310 | void printTimestamps(SdFile& f) { 311 | dir_t d; 312 | if (!f.dirEntry(&d)) { 313 | return; 314 | } 315 | 316 | //Serial.print("Creation: "); 317 | //f.printFatDate(d.creationDate); 318 | //Serial.print(" "); 319 | //f.printFatTime(d.creationTime); 320 | 321 | //Serial.print("Modify: "); 322 | f.printFatDate(d.lastWriteDate); 323 | Serial.print(" "); 324 | f.printFatTime(d.lastWriteTime); 325 | 326 | //Serial.print("Access: "); 327 | //f.printFatDate(d.lastAccessDate); 328 | Serial.print(" "); 329 | } 330 | 331 | // Max of ten files since files are selected with a single digit. 332 | #define nMax 100 333 | 334 | // Show JPEG file list on console 335 | int showJpegFileList (uint16_t * JPEGIndex, int MaxIndex) { 336 | 337 | // Position of file's directory entry. 338 | uint16_t *dirIndexP; 339 | dirIndexP = (uint16_t *) malloc(nMax); 340 | 341 | SdFile file; 342 | SdFile dirFile; 343 | 344 | // Save index in root directory. 345 | if (!dirFile.open("/", O_READ)) { 346 | SD.errorHalt("open root failed"); 347 | } 348 | uint16_t n = 0; 349 | while (n < nMax && file.openNext(&dirFile, O_READ)) { 350 | 351 | // Skip directories and hidden files. 352 | if (!file.isSubDir() && !file.isHidden()) { 353 | 354 | // Save dirIndex of file in directory. 355 | dirIndexP[n] = file.dirIndex(); 356 | 357 | #if 0 358 | // Print the file number and name. 359 | Serial.print(n); 360 | Serial.write(' '); 361 | file.printName(&Serial); 362 | Serial.println(); 363 | #endif 364 | n++; 365 | } 366 | file.close(); 367 | } 368 | //Serial.println("n=" + String(n)); 369 | 370 | // List files in root directory. 371 | int ipos = 0; 372 | Serial.println("--------------------------------------------"); 373 | for(int i=0;i=97 && fname[i]<=122) 387 | FNAME[i] = fname[i]-32; 388 | } 389 | 390 | //Serial.println("fname=" + String(fname)); 391 | //Serial.println("FNAME=" + String(FNAME)); 392 | if (strstr(FNAME, ".JPG")) { 393 | printTimestamps(file); 394 | sprintf(buf,"%10d %s",fsz,fname); 395 | //Serial.println("fname[" + String(i) + "]=" + String(fname)); 396 | Serial.println(buf); 397 | if (ipos < MaxIndex) JPEGIndex[ipos++] = dirIndexP[i]; 398 | } 399 | file.close(); 400 | Serial.flush(); 401 | } 402 | dirFile.close(); 403 | free(dirIndexP); 404 | Serial.println("--------------------------------------------"); 405 | return ipos; 406 | } 407 | 408 | 409 | char *getFileName(int index) 410 | { 411 | char fname[32]; 412 | 413 | // Get JPEG file name 414 | //Serial.println("index=" + String(index)); 415 | SdFile file; 416 | SdFile dirFile; 417 | if (!dirFile.open("/", O_READ)) { 418 | SD.errorHalt("open root failed"); 419 | } 420 | if (!file.open(&dirFile, index, O_READ)) { 421 | SD.errorHalt(F("open file failed")); 422 | } 423 | //Serial.print("open ok "); 424 | file.getName(fname,sizeof(fname)); 425 | //Serial.println("fname=" + String(fname)); 426 | file.close(); 427 | dirFile.close(); 428 | return fname; 429 | } 430 | 431 | //==================================================================================== 432 | 433 | -------------------------------------------------------------------------------- /examples/JpegView_240x320_SMT32/JpegView_240x320_SMT32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include "STM32_TFT_8bit.h" 23 | #include // https://github.com/greiman/SdFat 24 | #include // https://github.com/Bodmer/JPEGDecoder 25 | 26 | STM32_TFT_8bit tft; 27 | 28 | uint32_t ID; 29 | 30 | // Use second SPI port 31 | /* 32 | * MOSI --- PB15 33 | * MISO --- PB14 34 | * SCK ---- PB13 35 | * CS ----- PB12 36 | */ 37 | SPIClass SPI_2(2); 38 | SdFat SD(&SPI_2); 39 | // SdFatEX SD(&SPI_2); 40 | const uint8_t SD_CS = PB12; // chip select for sd2 41 | 42 | //------------------------------------------------------------------------------ 43 | // print error msg, any SD error codes, and halt. 44 | // store messages in flash 45 | #define errorExit(msg) errorHalt(F(msg)) 46 | #define initError(msg) initErrorHalt(F(msg)) 47 | //------------------------------------------------------------------------------ 48 | 49 | #define OPT_REDUCTION 1 50 | #define OPT_CENTER 2 51 | 52 | #define MaxJPEG 100 53 | int numJPEG; 54 | uint16_t JPEGIndex[MaxJPEG]; 55 | 56 | void setup() { 57 | delay(1000); 58 | Serial.begin(9600); 59 | Serial.println("STM32_TFT_8bit Test!"); 60 | 61 | ID = tft.readID(); 62 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 63 | tft.begin(ID); 64 | 65 | uint32_t width = tft.width(); 66 | Serial.print("Width: "); Serial.println(width); 67 | uint32_t height = tft.height(); 68 | Serial.print("Height: "); Serial.println(height); 69 | if (width < height) tft.setRotation(3); 70 | 71 | // initialize the second card 72 | //if (!SD.begin(SD_CS, SD_SCK_MHZ(18))) { 73 | if (!SD.begin(SD_CS)) { 74 | SD.initError("sd:"); 75 | } 76 | 77 | // Show JPEG file list on console 78 | numJPEG = showJpegFileList(JPEGIndex, MaxJPEG); 79 | Serial.println("numJPEG=" + String(numJPEG)); 80 | } 81 | 82 | 83 | void loop(void) { 84 | static int ipos = 0; 85 | char fname[32]; 86 | 87 | // Get JPEG file name 88 | strcpy(fname, getFileName(JPEGIndex[ipos])); 89 | 90 | // Draw JPEG image with recuction 91 | tft.fillScreen(random(0x10000)); 92 | drawFSJpeg(fname, 0, 0, OPT_REDUCTION + OPT_CENTER); 93 | 94 | ipos++; 95 | if (ipos == numJPEG) ipos = 0; 96 | 97 | delay(5000); 98 | } 99 | 100 | 101 | -------------------------------------------------------------------------------- /examples/JpegView_320x480_SMT32/JPEG_Functions.ino: -------------------------------------------------------------------------------- 1 | /*==================================================================================== 2 | This sketch contains support functions to render the Jpeg images. 3 | 4 | Created by Bodmer 5th Feb 2017 5 | Updated by nopnop2002 19/4/2018 6 | ==================================================================================*/ 7 | 8 | // Return the minimum of two values a and b 9 | #define minimum(a,b) (((a) < (b)) ? (a) : (b)) 10 | #define maximum(a,b) (((a) > (b)) ? (a) : (b)) 11 | 12 | //==================================================================================== 13 | // This function opens the array and primes the decoder 14 | //==================================================================================== 15 | void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int ypos) { 16 | 17 | boolean decoded = JpegDec.decodeArray(arrayname, array_size); 18 | 19 | if (decoded) { 20 | // print information about the image to the serial port 21 | jpegInfo(); 22 | 23 | // render the image onto the screen at given coordinates 24 | jpegRender(xpos, ypos, 0); 25 | } 26 | else { 27 | Serial.println("Jpeg file format not supported!"); 28 | } 29 | } 30 | 31 | //==================================================================================== 32 | // This function opens the Filing System Jpeg image file and primes the decoder 33 | // 34 | // options : OPT_REDUCTION 35 | // If it's large than screen, it would reduce so that it may fit into a screen. 36 | // OPT_CENTER 37 | // If it's smaller than screen, it would show to the center of the screen. 38 | //==================================================================================== 39 | void drawFSJpeg(const char *filename, int xpos, int ypos, int options) { 40 | 41 | Serial.println("====================================="); 42 | Serial.print("Drawing file: "); Serial.println(filename); 43 | Serial.println("====================================="); 44 | 45 | // Open the file (the Jpeg decoder library will close it) 46 | File jpgFile = SD.open( filename, FILE_READ); // file handle reference for SD library 47 | 48 | if ( !jpgFile ) { 49 | Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); 50 | return; 51 | } 52 | 53 | // To initialise the decoder and provide the file, we can use one of the following methods: 54 | boolean decoded = JpegDec.decodeSdFile(jpgFile); // we can pass the SD file handle to the decoder, 55 | //boolean decoded = JpegDec.decodeFsFile(filename); // or we can pass the filename 56 | // The filename can be a String or character array 57 | if (decoded) { 58 | // print information about the image to the serial port 59 | jpegInfo(); 60 | 61 | // render the image onto the screen at given coordinates 62 | jpegRender(xpos, ypos, options); 63 | } 64 | else { 65 | Serial.println("Jpeg file format not supported!"); 66 | } 67 | } 68 | 69 | //==================================================================================== 70 | // Decode and paint onto the TFT screen 71 | //==================================================================================== 72 | void jpegRender(int xpos, int ypos, int options) { 73 | 74 | //if (options & OPT_REDUCTION) Serial.println("OPT_REDUCTION"); 75 | //if (options & OPT_CENTER) Serial.println("OPT_CENTER"); 76 | // retrieve infomration about the image 77 | uint16_t *pImg; 78 | uint16_t mcu_w = JpegDec.MCUWidth; 79 | uint16_t mcu_h = JpegDec.MCUHeight; 80 | uint32_t max_x = JpegDec.width; 81 | uint32_t max_y = JpegDec.height; 82 | //Serial.println("mcu_w=" + String(mcu_w)); 83 | //Serial.println("mcu_h=" + String(mcu_h)); 84 | //Serial.println("max_x=" + String(max_x)); 85 | //Serial.println("max_y=" + String(max_y)); 86 | 87 | uint16_t szImg2 = mcu_w * mcu_h; 88 | uint16_t *pImg2; 89 | pImg2 = (uint16_t *) malloc(szImg2*2); 90 | 91 | uint32_t tft_width = tft.width(); 92 | //Serial.print("tft_width: "); Serial.println(tft_width); 93 | uint32_t tft_height = tft.height(); 94 | //Serial.print("tft_height: "); Serial.println(tft_height); 95 | 96 | int reduction_x = 1; 97 | int reduction_y = 1; 98 | if (max_x > tft_width) { 99 | reduction_x = (max_x / tft_width); 100 | if (max_x % tft_width) reduction_x++; 101 | } 102 | if (max_y > tft_height) { 103 | reduction_y = (max_y / tft_height); 104 | if (max_y % tft_height) reduction_y++; 105 | } 106 | //Serial.println("reduction_x=" + String(reduction_x)); 107 | //Serial.println("reduction_y=" + String(reduction_y)); 108 | int reduction = maximum(reduction_x, reduction_y); 109 | //Serial.println("reduction=" + String(reduction)); 110 | 111 | // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) 112 | // Typically these MCUs are 16x16 pixel blocks 113 | // Determine the width and height of the right and bottom edge image blocks 114 | uint32_t min_w = minimum(mcu_w, max_x % mcu_w); 115 | uint32_t min_h = minimum(mcu_h, max_y % mcu_h); 116 | //Serial.println("min_w=" + String(min_w)); 117 | //Serial.println("min_h=" + String(min_h)); 118 | 119 | 120 | // save the current image block size 121 | uint32_t win_w = mcu_w; 122 | uint32_t win_h = mcu_h; 123 | 124 | // record the current time so we can measure how long it takes to draw an image 125 | uint32_t drawTime = millis(); 126 | 127 | uint16_t max_xx = max_x; 128 | uint16_t max_yy = max_y; 129 | if (reduction > 1 && (options & OPT_REDUCTION) ) { 130 | max_xx = max_x / reduction; // new image size of X 131 | max_yy = max_y / reduction; // new image size of Y 132 | } 133 | //Serial.println("max_xx=" + String(max_xx)); 134 | //Serial.println("max_yy=" + String(max_yy)); 135 | 136 | // calculation center position 137 | int delta_x = 0; 138 | int delta_y = 0; 139 | if ( (max_xx < tft_width) && (options & OPT_CENTER) ) { 140 | delta_x = (tft_width - max_xx) / 2; 141 | } 142 | if ( (max_yy < tft_height) && (options & OPT_CENTER) ) { 143 | delta_y = (tft_height - max_yy) / 2; 144 | } 145 | //Serial.println("delta_x=" + String(delta_x)); 146 | //Serial.println("delta_y=" + String(delta_y)); 147 | 148 | // save the coordinate of the right and bottom edges to assist image cropping 149 | // to the screen size 150 | max_x += xpos; 151 | max_y += ypos; 152 | 153 | // read each MCU block until there are no more 154 | while ( JpegDec.read()) { 155 | 156 | // save a pointer to the image block 157 | pImg = JpegDec.pImage; 158 | 159 | // calculate where the image block should be drawn on the screen 160 | int mcu_x = JpegDec.MCUx * mcu_w + xpos; 161 | int mcu_y = JpegDec.MCUy * mcu_h + ypos; 162 | 163 | // check if the image block size needs to be changed for the right and bottom edges 164 | if (mcu_x + mcu_w <= max_x) win_w = mcu_w; 165 | else win_w = min_w; 166 | if (mcu_y + mcu_h <= max_y) win_h = mcu_h; 167 | else win_h = min_h; 168 | 169 | memcpy(pImg2, JpegDec.pImage, szImg2*2); 170 | int mcu_xx = mcu_x + delta_x; 171 | int mcu_yy = mcu_y + delta_y; 172 | uint32_t win_ww = win_w; 173 | uint32_t win_hh = win_h; 174 | 175 | if (reduction > 1 && (options & OPT_REDUCTION) ){ 176 | int pos1 = 0; 177 | int pos2 = 0; 178 | for(int x=0; x 1 && (options & OPT_REDUCTION) ) { 243 | int reductionRate = (float)(1.0 / reduction) * 100; 244 | Serial.print ("Rate of reduction was : "); Serial.print(reductionRate); Serial.println(" %"); 245 | } 246 | Serial.println("====================================="); 247 | 248 | } 249 | //==================================================================================== 250 | // Send time taken to Serial port 251 | //==================================================================================== 252 | void jpegInfo() { 253 | Serial.println(F("===============")); 254 | Serial.println(F("JPEG image info")); 255 | Serial.println(F("===============")); 256 | Serial.print(F( "Width :")); Serial.println(JpegDec.width); 257 | Serial.print(F( "Height :")); Serial.println(JpegDec.height); 258 | Serial.print(F( "Components :")); Serial.println(JpegDec.comps); 259 | Serial.print(F( "MCU / row :")); Serial.println(JpegDec.MCUSPerRow); 260 | Serial.print(F( "MCU / col :")); Serial.println(JpegDec.MCUSPerCol); 261 | Serial.print(F( "Scan type :")); Serial.println(JpegDec.scanType); 262 | Serial.print(F( "MCU width :")); Serial.println(JpegDec.MCUWidth); 263 | Serial.print(F( "MCU height :")); Serial.println(JpegDec.MCUHeight); 264 | Serial.println(F("===============")); 265 | } 266 | 267 | //==================================================================================== 268 | // Open a Jpeg file on an SD card and dump it to the Serial port as a C array 269 | //==================================================================================== 270 | void createArray(const char *filename) { 271 | 272 | File jpgFile; // File handle reference For SD library 273 | 274 | if ( !( jpgFile = SD.open( filename, FILE_READ))) { 275 | Serial.println(F("JPEG file not found")); 276 | return; 277 | } 278 | 279 | uint8_t data; 280 | byte line_len = 0; 281 | Serial.println("// Generated by a JPEGDecoder library example sketch:"); 282 | Serial.println("// https://github.com/Bodmer/JPEGDecoder"); 283 | Serial.println(""); 284 | Serial.println("#if defined(__AVR__)"); 285 | Serial.println(" #include "); 286 | Serial.println("#endif"); 287 | Serial.println(""); 288 | Serial.print("const uint8_t "); 289 | while (*filename != '.') Serial.print(*filename++); 290 | Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors 291 | 292 | while ( jpgFile.available()) { 293 | 294 | data = jpgFile.read(); 295 | Serial.print("0x"); if (abs(data) < 16) Serial.print("0"); 296 | Serial.print(data, HEX); Serial.print(",");// Add value and comma 297 | line_len++; 298 | if ( line_len >= 32) { 299 | line_len = 0; 300 | Serial.println(); 301 | } 302 | 303 | } 304 | 305 | Serial.println("};\r\n"); 306 | jpgFile.close(); 307 | } 308 | 309 | // Function to print all timestamps. 310 | void printTimestamps(SdFile& f) { 311 | dir_t d; 312 | if (!f.dirEntry(&d)) { 313 | return; 314 | } 315 | 316 | //Serial.print("Creation: "); 317 | //f.printFatDate(d.creationDate); 318 | //Serial.print(" "); 319 | //f.printFatTime(d.creationTime); 320 | 321 | //Serial.print("Modify: "); 322 | f.printFatDate(d.lastWriteDate); 323 | Serial.print(" "); 324 | f.printFatTime(d.lastWriteTime); 325 | 326 | //Serial.print("Access: "); 327 | //f.printFatDate(d.lastAccessDate); 328 | Serial.print(" "); 329 | } 330 | 331 | // Max of ten files since files are selected with a single digit. 332 | #define nMax 100 333 | 334 | // Show JPEG file list on console 335 | int showJpegFileList (uint16_t * JPEGIndex, int MaxIndex) { 336 | 337 | // Position of file's directory entry. 338 | uint16_t *dirIndexP; 339 | dirIndexP = (uint16_t *) malloc(nMax); 340 | 341 | SdFile file; 342 | SdFile dirFile; 343 | 344 | // Save index in root directory. 345 | if (!dirFile.open("/", O_READ)) { 346 | SD.errorHalt("open root failed"); 347 | } 348 | uint16_t n = 0; 349 | while (n < nMax && file.openNext(&dirFile, O_READ)) { 350 | 351 | // Skip directories and hidden files. 352 | if (!file.isSubDir() && !file.isHidden()) { 353 | 354 | // Save dirIndex of file in directory. 355 | dirIndexP[n] = file.dirIndex(); 356 | 357 | #if 0 358 | // Print the file number and name. 359 | Serial.print(n); 360 | Serial.write(' '); 361 | file.printName(&Serial); 362 | Serial.println(); 363 | #endif 364 | n++; 365 | } 366 | file.close(); 367 | } 368 | //Serial.println("n=" + String(n)); 369 | 370 | // List files in root directory. 371 | int ipos = 0; 372 | Serial.println("--------------------------------------------"); 373 | for(int i=0;i=97 && fname[i]<=122) 387 | FNAME[i] = fname[i]-32; 388 | } 389 | 390 | //Serial.println("fname=" + String(fname)); 391 | //Serial.println("FNAME=" + String(FNAME)); 392 | if (strstr(FNAME, ".JPG")) { 393 | printTimestamps(file); 394 | sprintf(buf,"%10d %s",fsz,fname); 395 | //Serial.println("fname[" + String(i) + "]=" + String(fname)); 396 | Serial.println(buf); 397 | if (ipos < MaxIndex) JPEGIndex[ipos++] = dirIndexP[i]; 398 | } 399 | file.close(); 400 | Serial.flush(); 401 | } 402 | dirFile.close(); 403 | free(dirIndexP); 404 | Serial.println("--------------------------------------------"); 405 | return ipos; 406 | } 407 | 408 | 409 | char *getFileName(int index) 410 | { 411 | char fname[32]; 412 | 413 | // Get JPEG file name 414 | //Serial.println("index=" + String(index)); 415 | SdFile file; 416 | SdFile dirFile; 417 | if (!dirFile.open("/", O_READ)) { 418 | SD.errorHalt("open root failed"); 419 | } 420 | if (!file.open(&dirFile, index, O_READ)) { 421 | SD.errorHalt(F("open file failed")); 422 | } 423 | //Serial.print("open ok "); 424 | file.getName(fname,sizeof(fname)); 425 | //Serial.println("fname=" + String(fname)); 426 | file.close(); 427 | dirFile.close(); 428 | return fname; 429 | } 430 | 431 | //==================================================================================== 432 | 433 | -------------------------------------------------------------------------------- /examples/JpegView_320x480_SMT32/JpegView_320x480_SMT32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | 21 | #include 22 | #include "STM32_TFT_8bit.h" 23 | #include // https://github.com/greiman/SdFat 24 | #include // https://github.com/Bodmer/JPEGDecoder 25 | 26 | STM32_TFT_8bit tft; 27 | 28 | uint32_t ID; 29 | 30 | // Use second SPI port 31 | /* 32 | * MOSI --- PB15 33 | * MISO --- PB14 34 | * SCK ---- PB13 35 | * CS ----- PB12 36 | */ 37 | SPIClass SPI_2(2); 38 | SdFat SD(&SPI_2); 39 | // SdFatEX SD(&SPI_2); 40 | const uint8_t SD_CS = PB12; // chip select for sd2 41 | 42 | //------------------------------------------------------------------------------ 43 | // print error msg, any SD error codes, and halt. 44 | // store messages in flash 45 | #define errorExit(msg) errorHalt(F(msg)) 46 | #define initError(msg) initErrorHalt(F(msg)) 47 | //------------------------------------------------------------------------------ 48 | 49 | #define OPT_REDUCTION 1 50 | #define OPT_CENTER 2 51 | 52 | #define MaxJPEG 100 53 | int numJPEG; 54 | uint16_t JPEGIndex[MaxJPEG]; 55 | 56 | void setup() { 57 | delay(1000); 58 | Serial.begin(9600); 59 | Serial.println("STM32_TFT_8bit Test!"); 60 | 61 | ID = tft.readID(); 62 | tft.setResolution(320, 480); // Set your resolution 63 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 64 | tft.begin(ID); 65 | 66 | uint32_t width = tft.width(); 67 | Serial.print("Width: "); Serial.println(width); 68 | uint32_t height = tft.height(); 69 | Serial.print("Height: "); Serial.println(height); 70 | if (width < height) tft.setRotation(3); 71 | 72 | // initialize the second card 73 | //if (!SD.begin(SD_CS, SD_SCK_MHZ(18))) { 74 | if (!SD.begin(SD_CS)) { 75 | SD.initError("sd:"); 76 | } 77 | 78 | // Show JPEG file list on console 79 | numJPEG = showJpegFileList(JPEGIndex, MaxJPEG); 80 | Serial.println("numJPEG=" + String(numJPEG)); 81 | } 82 | 83 | 84 | void loop(void) { 85 | static int ipos = 0; 86 | char fname[32]; 87 | 88 | // Get JPEG file name 89 | strcpy(fname, getFileName(JPEGIndex[ipos])); 90 | 91 | // Draw JPEG image with recuction 92 | tft.fillScreen(random(0x10000)); 93 | drawFSJpeg(fname, 0, 0, OPT_REDUCTION + OPT_CENTER); 94 | 95 | ipos++; 96 | if (ipos == numJPEG) ipos = 0; 97 | 98 | delay(5000); 99 | } 100 | 101 | 102 | -------------------------------------------------------------------------------- /examples/LCD_ID_Reader/LCD_ID_Reader.ino: -------------------------------------------------------------------------------- 1 | // adapted from LCD_ID_Reader from http://misc.ws/lcd_information 2 | // controllers either read as 16-bit or as a sequence of 8-bit values 3 | 4 | #define LCD_RST PB7 5 | #define LCD_CS PB6 6 | #define LCD_RS PB5 7 | #define LCD_WR PB4 8 | #define LCD_RD PB3 9 | 10 | #define LCD_D0 PA0 11 | #define LCD_D1 PA1 12 | #define LCD_D2 PA2 13 | #define LCD_D3 PA3 14 | #define LCD_D4 PA4 15 | #define LCD_D5 PA5 16 | #define LCD_D6 PA6 17 | #define LCD_D7 PA7 18 | 19 | void setup() 20 | { 21 | Serial.begin(9600); 22 | while (!Serial) ; 23 | Serial.println("Read Registers on MCUFRIEND UNO shield"); 24 | Serial.println("controllers either read as single 16-bit"); 25 | Serial.println("e.g. the ID is at readReg(0)"); 26 | Serial.println("or as a sequence of 8-bit values"); 27 | Serial.println("in special locations (first is dummy)"); 28 | Serial.println(""); 29 | lcdInit(); 30 | lcdReset(); //ensures that controller is in default state 31 | // for (uint16_t i = 0; i < 256; i++) readReg(i, 7, "f.k"); 32 | readReg(0x00, 2, "ID: ILI9320, ILI9325, ILI9335, ..."); 33 | readReg(0x04, 4, "Manufacturer ID"); 34 | readReg(0x09, 5, "Status Register"); 35 | readReg(0x0A, 2, "Get Powsr Mode"); 36 | readReg(0x0C, 2, "Get Pixel Format"); 37 | readReg(0x61, 2, "RDID1 HX8347-G"); 38 | readReg(0x62, 2, "RDID2 HX8347-G"); 39 | readReg(0x63, 2, "RDID3 HX8347-G"); 40 | readReg(0x64, 2, "RDID1 HX8347-A"); 41 | readReg(0x65, 2, "RDID2 HX8347-A"); 42 | readReg(0x66, 2, "RDID3 HX8347-A"); 43 | readReg(0x67, 2, "RDID Himax HX8347-A"); 44 | readReg(0x70, 2, "Panel Himax HX8347-A"); 45 | readReg(0xA1, 5, "RD_DDB SSD1963"); 46 | readReg(0xB0, 2, "RGB Interface Signal Control"); 47 | readReg(0xB4, 2, "Inversion Control"); 48 | readReg(0xB6, 5, "Display Control"); 49 | readReg(0xB7, 2, "Entry Mode Set"); 50 | readReg(0xBF, 6, "ILI9481, HX8357-B"); 51 | readReg(0xC0, 9, "Panel Control"); 52 | readReg(0xC8, 13, "GAMMA"); 53 | readReg(0xCC, 2, "Panel Control"); 54 | readReg(0xD0, 3, "Power Control"); 55 | readReg(0xD2, 5, "NVM Read"); 56 | readReg(0xD3, 4, "ILI9341, ILI9488"); 57 | readReg(0xDA, 2, "RDID1"); 58 | readReg(0xDB, 2, "RDID2"); 59 | readReg(0xDC, 2, "RDID3"); 60 | readReg(0xE0, 16, "GAMMA-P"); 61 | readReg(0xE1, 16, "GAMMA-N"); 62 | readReg(0xEF, 6, "ILI9327"); 63 | readReg(0xF2, 12, "Adjust Control 2"); 64 | readReg(0xF6, 4, "Interface Control"); 65 | } 66 | 67 | void loop() 68 | { 69 | // put your main code here, to run repeatedly: 70 | 71 | } 72 | 73 | void printhex(uint8_t val) 74 | { 75 | if (val < 0x10) Serial.print("0"); 76 | Serial.print(val, HEX); 77 | } 78 | 79 | void readReg(uint16_t reg, uint8_t n, const char *msg) 80 | { 81 | uint8_t val8; 82 | lcdReset(); 83 | lcdSetWriteDir(); 84 | lcdWriteCommand(0xB0); //Command Access Protect 85 | lcdWriteData(0x00); //looks wrong 86 | /* 87 | lcdWriteCommand(0xF6); 88 | lcdWriteData(0x01); 89 | lcdWriteData(0x01); 90 | lcdWriteData(0x03); 91 | */ 92 | lcdWriteCommand(reg); 93 | Serial.print("reg(0x"); 94 | printhex(reg >> 8); 95 | printhex(reg); 96 | Serial.print(")"); 97 | lcdSetReadDir(); 98 | while (n--) { 99 | val8 = lcdReadData8(); 100 | Serial.print(" "); 101 | printhex(val8); 102 | } 103 | lcdSetWriteDir(); 104 | Serial.print("\t"); 105 | Serial.println(msg); 106 | } 107 | 108 | void lcdInit() 109 | { 110 | pinMode(LCD_CS, OUTPUT); 111 | digitalWrite(LCD_CS, HIGH); 112 | pinMode(LCD_RS, OUTPUT); 113 | digitalWrite(LCD_RS, HIGH); 114 | pinMode(LCD_WR, OUTPUT); 115 | digitalWrite(LCD_WR, HIGH); 116 | pinMode(LCD_RD, OUTPUT); 117 | digitalWrite(LCD_RD, HIGH); 118 | pinMode(LCD_RST, OUTPUT); 119 | digitalWrite(LCD_RST, HIGH); 120 | } 121 | 122 | void lcdReset() 123 | { 124 | digitalWrite(LCD_RST, LOW); 125 | delay(2); 126 | digitalWrite(LCD_RST, HIGH); 127 | delay(10); //allow controller to re-start 128 | } 129 | 130 | void lcdWrite8(uint16_t data) 131 | { 132 | digitalWrite(LCD_D0, data & 1); 133 | digitalWrite(LCD_D1, (data & 2) >> 1); 134 | digitalWrite(LCD_D2, (data & 4) >> 2); 135 | digitalWrite(LCD_D3, (data & 8) >> 3); 136 | digitalWrite(LCD_D4, (data & 16) >> 4); 137 | digitalWrite(LCD_D5, (data & 32) >> 5); 138 | digitalWrite(LCD_D6, (data & 64) >> 6); 139 | digitalWrite(LCD_D7, (data & 128) >> 7); 140 | } 141 | 142 | uint16_t lcdRead8() 143 | { 144 | uint16_t result = digitalRead(LCD_D7); 145 | result <<= 1; 146 | result |= digitalRead(LCD_D6); 147 | result <<= 1; 148 | result |= digitalRead(LCD_D5); 149 | result <<= 1; 150 | result |= digitalRead(LCD_D4); 151 | result <<= 1; 152 | result |= digitalRead(LCD_D3); 153 | result <<= 1; 154 | result |= digitalRead(LCD_D2); 155 | result <<= 1; 156 | result |= digitalRead(LCD_D1); 157 | result <<= 1; 158 | result |= digitalRead(LCD_D0); 159 | 160 | return result; 161 | } 162 | 163 | void lcdSetWriteDir() 164 | { 165 | pinMode(LCD_D0, OUTPUT); 166 | pinMode(LCD_D1, OUTPUT); 167 | pinMode(LCD_D2, OUTPUT); 168 | pinMode(LCD_D3, OUTPUT); 169 | pinMode(LCD_D4, OUTPUT); 170 | pinMode(LCD_D5, OUTPUT); 171 | pinMode(LCD_D6, OUTPUT); 172 | pinMode(LCD_D7, OUTPUT); 173 | } 174 | 175 | 176 | void lcdSetReadDir() 177 | { 178 | pinMode(LCD_D0, INPUT); 179 | pinMode(LCD_D1, INPUT); 180 | pinMode(LCD_D2, INPUT); 181 | pinMode(LCD_D3, INPUT); 182 | pinMode(LCD_D4, INPUT); 183 | pinMode(LCD_D5, INPUT); 184 | pinMode(LCD_D6, INPUT); 185 | pinMode(LCD_D7, INPUT); 186 | } 187 | 188 | void lcdWriteData(uint16_t data) 189 | { 190 | lcdSetWriteDir(); 191 | digitalWrite(LCD_CS, LOW); 192 | digitalWrite(LCD_RS, HIGH); 193 | digitalWrite(LCD_RD, HIGH); 194 | digitalWrite(LCD_WR, HIGH); 195 | 196 | lcdWrite8(data >> 8); 197 | 198 | digitalWrite(LCD_WR, LOW); 199 | delayMicroseconds(10); 200 | digitalWrite(LCD_WR, HIGH); 201 | 202 | lcdWrite8(data); 203 | 204 | digitalWrite(LCD_WR, LOW); 205 | delayMicroseconds(10); 206 | digitalWrite(LCD_WR, HIGH); 207 | 208 | digitalWrite(LCD_CS, HIGH); 209 | } 210 | 211 | void lcdWriteCommand(uint16_t command) 212 | { 213 | lcdSetWriteDir(); 214 | digitalWrite(LCD_CS, LOW); 215 | digitalWrite(LCD_RS, LOW); 216 | digitalWrite(LCD_RD, HIGH); 217 | digitalWrite(LCD_WR, HIGH); 218 | lcdWrite8(command >> 8); 219 | digitalWrite(LCD_WR, LOW); 220 | delayMicroseconds(10); 221 | digitalWrite(LCD_WR, HIGH); 222 | lcdWrite8(command); 223 | digitalWrite(LCD_WR, LOW); 224 | delayMicroseconds(10); 225 | digitalWrite(LCD_WR, HIGH); 226 | digitalWrite(LCD_CS, HIGH); 227 | } 228 | 229 | uint8_t lcdReadData8() 230 | { 231 | uint8_t result; 232 | lcdSetReadDir(); 233 | digitalWrite(LCD_CS, LOW); 234 | digitalWrite(LCD_RS, HIGH); 235 | digitalWrite(LCD_RD, HIGH); 236 | digitalWrite(LCD_WR, HIGH); 237 | 238 | digitalWrite(LCD_RD, LOW); 239 | delayMicroseconds(10); 240 | result = lcdRead8(); 241 | digitalWrite(LCD_RD, HIGH); 242 | 243 | delayMicroseconds(10); 244 | 245 | return result; 246 | } 247 | 248 | 249 | uint16_t lcdReadData16() 250 | { 251 | uint16_t result; 252 | result = lcdReadData8() << 8; 253 | result |= lcdReadData8(); 254 | return result; 255 | } 256 | 257 | 258 | void lcdWriteRegister(uint16_t addr, uint16_t data) 259 | { 260 | lcdWriteCommand(addr); 261 | lcdWriteData(data); 262 | } 263 | -------------------------------------------------------------------------------- /examples/LCD_ID_Reader/README.md: -------------------------------------------------------------------------------- 1 | # LCD_ID_Reader 2 | Many controllers are used in the parallel TFT for UNO. 3 | This is a tool to find the TFT controller. 4 | 5 | # Wirering for 8bit Parallel TFT 6 | 7 | |TFT||STM32F103| 8 | |:-:|:-:|:-:| 9 | |LCD_RST|--|PB7| 10 | |LCD_CS|--|PB6| 11 | |LCD_RS|--|PB5| 12 | |LCD_WR|--|PB4(*2)| 13 | |LCD_RD|--|PB3(*2)| 14 | |LCD_D0|--|PA0| 15 | |LCD_D1|--|PA1| 16 | |LCD_D2|--|PA2| 17 | |LCD_D3|--|PA3| 18 | |LCD_D4|--|PA4| 19 | |LCD_D5|--|PA5| 20 | |LCD_D6|--|PA6| 21 | |LCD_D7|--|PA7| 22 | |5V|--|5V(*1)| 23 | |3.3V|--|3.3V(*1)| 24 | |GND|--|GND| 25 | 26 | (*1)When a regulator(It's often AMS1117) is mounted on the back, it's operated 5V. 27 | When a regulator is NOT mounted on the back, it's operated 3.3V. 28 | 29 | (*2)By several boards, This port is used as JTAG. 30 | You need remap. 31 | afio_cfg_debug_ports(AFIO_DEBUG_NONE) 32 | 33 | 34 | # Serial print 35 | ``` 36 | Read Registers on MCUFRIEND UNO shield 37 | controllers either read as single 16-bit 38 | e.g. the ID is at readReg(0) 39 | or as a sequence of 8-bit values 40 | in special locations (first is dummy) 41 | 42 | reg(0x0000) 00 00 ID: ILI9320, ILI9325, ILI9335, ... 43 | reg(0x0004) 00 54 80 66 Manufacturer ID 44 | reg(0x0009) 00 00 61 00 00 Status Register 45 | reg(0x000A) 00 08 Get Powsr Mode 46 | reg(0x000C) 00 66 Get Pixel Format 47 | reg(0x0061) 00 00 RDID1 HX8347-G 48 | reg(0x0062) 00 00 RDID2 HX8347-G 49 | reg(0x0063) 00 00 RDID3 HX8347-G 50 | reg(0x0064) 00 00 RDID1 HX8347-A 51 | reg(0x0065) 00 00 RDID2 HX8347-A 52 | reg(0x0066) 00 00 RDID3 HX8347-A 53 | reg(0x0067) 00 00 RDID Himax HX8347-A 54 | reg(0x0070) 00 00 Panel Himax HX8347-A 55 | reg(0x00A1) 00 93 30 93 30 RD_DDB SSD1963 56 | reg(0x00B0) 00 00 RGB Interface Signal Control 57 | reg(0x00B4) 00 00 Inversion Control 58 | reg(0x00B6) 00 02 02 3B 3B Display Control 59 | reg(0x00B7) 00 06 Entry Mode Set 60 | reg(0x00BF) 00 00 00 00 00 00 ILI9481, HX8357-B 61 | reg(0x00C0) 00 0E 0E 0E 0E 0E 0E 0E 0E Panel Control 62 | reg(0x00C8) 00 00 00 00 00 00 00 00 00 00 00 00 00 GAMMA 63 | reg(0x00CC) 00 04 Panel Control 64 | reg(0x00D0) 00 00 00 Power Control 65 | reg(0x00D2) 00 00 00 00 00 NVM Read 66 | reg(0x00D3) 00 00 94 86 ILI9341, ILI9488 67 | reg(0x00DA) 00 54 RDID1 68 | reg(0x00DB) 00 80 RDID2 69 | reg(0x00DC) 00 66 RDID3 70 | reg(0x00E0) 00 0F 21 1C 0B 0E 08 49 98 38 09 11 03 14 10 00 GAMMA-P 71 | reg(0x00E1) 00 0F 2F 2B 0C 0E 06 47 76 37 07 11 04 23 1E 00 GAMMA-N 72 | reg(0x00EF) 00 80 00 10 60 40 ILI9327 73 | reg(0x00F2) 00 18 A3 12 02 B2 12 FF 10 00 00 00 Adjust Control 2 74 | reg(0x00F6) 00 54 80 66 Interface Control 75 | ``` 76 | 77 | From the output of 0x00D3, you can see that the controller is ILI9486. 78 | 79 | -------------------------------------------------------------------------------- /examples/ScrollTest_STM32/ScrollTest_STM32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * 8bit TFT Library for STM32F103 3 | * based on MCUFRIEND_kbv.cpp by David Prentice 4 | * https://github.com/prenticedavid/MCUFRIEND_kbv 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | #include "STM32_TFT_8bit.h" 22 | 23 | STM32_TFT_8bit tft; 24 | 25 | void setup(void) { 26 | delay(1000); 27 | Serial.begin(9600); 28 | 29 | uint16_t ID = tft.readID(); 30 | Serial.println("ID = 0x" + String(ID,HEX)); 31 | tft.begin(ID); 32 | } 33 | 34 | 35 | void loop(void) { 36 | uint8_t aspect; 37 | uint16_t pixel; 38 | const char *aspectname[] = { 39 | "PORTRAIT", "LANDSCAPE", "PORTRAIT_REV", "LANDSCAPE_REV" 40 | }; 41 | const char *colorname[] = { "BLUE", "GREEN", "RED", "GRAY" }; 42 | uint16_t colormask[] = { 0x001F, 0x07E0, 0xF800, 0xFFFF }; 43 | uint16_t dx, rgb, n, wid, ht, msgline; 44 | tft.setRotation(0); 45 | if (tft.height() > 64) { 46 | for (uint8_t cnt = 0; cnt < 4; cnt++) { 47 | aspect = (cnt + 0) & 3; 48 | tft.setRotation(aspect); 49 | wid = tft.width(); 50 | ht = tft.height(); 51 | Serial.println("aspect=" + String(aspect)); 52 | Serial.println("width=" + String(wid) + " height=" + String(ht)); 53 | msgline = (ht > 160) ? 200 : 112; 54 | testText(); 55 | 56 | // Show COLOR GRADES 57 | dx = wid / 32; 58 | for (n = 0; n < 32; n++) { 59 | rgb = n * 8; 60 | rgb = tft.color565(rgb, rgb, rgb); 61 | tft.fillRect(n * dx, 48, dx, 63, rgb & colormask[aspect]); 62 | } 63 | tft.drawRect(0, 48 + 63, wid, 1, WHITE); 64 | tft.setTextSize(2); 65 | tft.setTextColor(colormask[aspect], BLACK); 66 | tft.setCursor(0, 72); 67 | tft.print(colorname[aspect]); 68 | tft.setTextColor(WHITE); 69 | tft.println(" COLOR GRADES"); 70 | tft.setTextColor(WHITE, BLACK); 71 | printmsg(184, aspectname[aspect]); 72 | delay(1000); 73 | tft.drawPixel(0, 0, YELLOW); 74 | pixel = tft.readPixel(0, 0); 75 | tft.setTextSize((ht > 160) ? 2 : 1); //for messages 76 | 77 | // Show penguin icon 78 | extern const uint8_t penguin[]; 79 | tft.setAddrWindow(wid - 40 - 40, 20 + 0, wid - 1 - 40, 20 + 39); 80 | tft.pushColors8((uint8_t *)penguin, 1600, 1); 81 | 82 | // Scroll Screen 83 | tft.setAddrWindow(0, 0, wid - 1, ht - 1); 84 | if (aspect & 1) tft.drawRect(wid - 1, 0, 1, ht, WHITE); 85 | else tft.drawRect(0, ht - 1, wid, 1, WHITE); 86 | printmsg(msgline, "VERTICAL SCROLL UP"); 87 | uint16_t maxscroll; 88 | if (tft.getRotation() & 1) maxscroll = wid; 89 | else maxscroll = ht; 90 | int step = -1; 91 | if ( wid < ht ) step = 1; 92 | 93 | // Scroll Up 94 | for (int16_t i = 1; i <= maxscroll; i++) { 95 | tft.vertScroll(0, maxscroll, i * step); 96 | delay(10); 97 | } 98 | delay(1000); 99 | 100 | // Scroll Down 101 | printmsg(msgline, "VERTICAL SCROLL DN"); 102 | for (int16_t i = 1; i <= maxscroll; i++) { 103 | tft.vertScroll(0, maxscroll, (0 - i) * step); 104 | delay(10); 105 | } 106 | tft.vertScroll(0, maxscroll, 0); 107 | printmsg(msgline, "SCROLL DISABLED"); 108 | 109 | // Scroll COLOR GRADES 110 | delay(1000); 111 | if ((aspect & 1) == 0) { //Portrait 112 | int stline; 113 | stline = 128; 114 | step = -1; 115 | if (wid < ht) { 116 | stline = 48; 117 | step = 1; 118 | } 119 | tft.setTextColor(BLUE, BLACK); 120 | printmsg(msgline, "ONLY THE COLOR BAND"); 121 | for (int16_t i = 1; i <= 64; i++) { 122 | tft.vertScroll(stline, 64, i * step); 123 | delay(20); 124 | } 125 | delay(1000); 126 | for (int16_t i = 1; i <= 64; i++) { 127 | tft.vertScroll(stline, 64, (0 - i) * step); 128 | delay(20); 129 | } 130 | delay(1000); 131 | 132 | #if 0 133 | if ( wid < ht ) { 134 | stline = 48; 135 | for (int16_t i = 1; i <= 64; i++) { 136 | tft.vertScroll(stline, 64, i); 137 | delay(20); 138 | } 139 | delay(1000); 140 | for (int16_t i = 1; i <= 64; i++) { 141 | tft.vertScroll(stline, 64, 0 - i); 142 | delay(20); 143 | } 144 | delay(1000); 145 | } else { 146 | stline = 128; 147 | for (int16_t i = 1; i <= 64; i++) { 148 | tft.vertScroll(stline, 64, 0 - i); 149 | delay(20); 150 | } 151 | delay(1000); 152 | for (int16_t i = 1; i <= 64; i++) { 153 | tft.vertScroll(stline, 64, i); 154 | delay(20); 155 | } 156 | delay(1000); 157 | } 158 | #endif 159 | } 160 | 161 | printmsg(msgline, "INVERT DISPLAY"); 162 | tft.invertDisplay(true); 163 | delay(3000); 164 | printmsg(msgline, "NORMAL DISPLAY"); 165 | tft.invertDisplay(false); 166 | delay(3000); 167 | } 168 | } 169 | } 170 | 171 | void testText() { 172 | tft.fillScreen(BLACK); 173 | tft.setCursor(0, 0); 174 | tft.setTextColor(WHITE); tft.setTextSize(1); 175 | tft.println("Hello World!"); 176 | tft.setTextColor(YELLOW); tft.setTextSize(2); 177 | tft.println(123.45); 178 | tft.setTextColor(RED); tft.setTextSize(3); 179 | tft.println(0xDEADBEEF, HEX); 180 | tft.println(); 181 | tft.setTextColor(GREEN); 182 | tft.setTextSize(5); 183 | tft.println("Groop"); 184 | tft.setTextSize(2); 185 | tft.println("I implore thee,"); 186 | tft.setTextSize(1); 187 | tft.println("my foonting turlingdromes."); 188 | tft.println("And hooptiously drangle me"); 189 | tft.println("with crinkly bindlewurdles,"); 190 | tft.println("Or I will rend thee"); 191 | tft.println("in the gobberwarts"); 192 | tft.println("with my blurglecruncheon,"); 193 | tft.println("see if I don't!"); 194 | } 195 | 196 | void printmsg(int row, const char *msg) 197 | { 198 | static char primary_msg[64]; 199 | 200 | if (strlen(primary_msg)) { 201 | tft.setTextColor(BLACK, BLACK); 202 | tft.setCursor(0, row); 203 | tft.println(primary_msg); 204 | } 205 | tft.setTextColor(YELLOW, BLACK); 206 | tft.setCursor(0, row); 207 | tft.println(msg); 208 | strcpy(primary_msg,msg); 209 | } 210 | 211 | 212 | 213 | -------------------------------------------------------------------------------- /examples/ScrollTest_STM32/icons.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const uint8_t penguin[3200] = { /* 0X00,0X10,0X28,0X00,0X28,0X00,0X01,0X1B, */ 4 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 5 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0X7D, 0XEF, 6 | 0XBA, 0XD6, 0XB6, 0XB5, 0XF3, 0X9C, 0XB2, 0X94, 0XB3, 0X9C, 0XB2, 0X94, 0X34, 0XA5, 0XF7, 0XBD, 7 | 0XFB, 0XDE, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 8 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 9 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 10 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0XFB, 0XDE, 0XF3, 0X9C, 0XCB, 0X5A, 11 | 0XC7, 0X39, 0X04, 0X21, 0X82, 0X10, 0X42, 0X10, 0X42, 0X10, 0X41, 0X08, 0X83, 0X18, 0X45, 0X29, 12 | 0XC7, 0X39, 0X0C, 0X63, 0X75, 0XAD, 0X3C, 0XE7, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 13 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 14 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 15 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3C, 0XE7, 0XB2, 0X94, 0X08, 0X42, 0XC3, 0X18, 0X82, 0X10, 16 | 0X04, 0X21, 0X45, 0X29, 0X86, 0X31, 0X86, 0X31, 0X86, 0X31, 0X86, 0X31, 0X45, 0X29, 0X04, 0X21, 17 | 0X82, 0X10, 0X41, 0X08, 0XC3, 0X18, 0X08, 0X42, 0XF3, 0X9C, 0X3C, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 18 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 19 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 20 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFB, 0XDE, 0X0C, 0X63, 0XC3, 0X18, 0XC3, 0X18, 0X45, 0X29, 0XC7, 0X39, 21 | 0X08, 0X42, 0X08, 0X42, 0X08, 0X42, 0X08, 0X42, 0X08, 0X42, 0X08, 0X42, 0XC7, 0X39, 0XC7, 0X39, 22 | 0X86, 0X31, 0X86, 0X31, 0X04, 0X21, 0X41, 0X08, 0X82, 0X10, 0XCB, 0X5A, 0XBA, 0XD6, 0XFF, 0XFF, 23 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 24 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 25 | 0XFF, 0XFF, 0XFB, 0XDE, 0XCB, 0X5A, 0X82, 0X10, 0X45, 0X29, 0XC7, 0X39, 0X08, 0X42, 0X08, 0X42, 26 | 0X09, 0X4A, 0X49, 0X4A, 0X49, 0X4A, 0X49, 0X4A, 0X49, 0X4A, 0X49, 0X4A, 0X08, 0X42, 0XC7, 0X39, 27 | 0XC7, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X83, 0X18, 0X00, 0X00, 0XC8, 0X41, 0X38, 0XC6, 28 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 29 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 30 | 0X7D, 0XEF, 0X8E, 0X73, 0X82, 0X10, 0X45, 0X29, 0XC7, 0X39, 0X08, 0X42, 0X09, 0X4A, 0X8A, 0X52, 31 | 0X30, 0X84, 0XCF, 0X7B, 0X8A, 0X52, 0X49, 0X4A, 0X4A, 0X52, 0X49, 0X4A, 0XCB, 0X5A, 0XCF, 0X7B, 32 | 0X0C, 0X63, 0X08, 0X42, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0XC3, 0X18, 0X00, 0X00, 0X49, 0X4A, 33 | 0XBA, 0XD6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 34 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 35 | 0XF3, 0X9C, 0XC3, 0X18, 0X04, 0X21, 0XC7, 0X39, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X72, 0X94, 36 | 0X7D, 0XEF, 0X7D, 0XEF, 0XB2, 0X94, 0X4A, 0X52, 0X49, 0X4A, 0X8A, 0X52, 0X75, 0XAD, 0XBE, 0XF7, 37 | 0XBA, 0XD6, 0X4D, 0X6B, 0XC7, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0XC3, 0X18, 0X41, 0X08, 38 | 0XCF, 0X7B, 0X7C, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 39 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBA, 0XD6, 40 | 0X08, 0X42, 0X82, 0X10, 0XC7, 0X39, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X8E, 0X73, 0XFB, 0XDE, 41 | 0XFF, 0XFF, 0XBE, 0XF7, 0XBA, 0XD6, 0X8E, 0X73, 0X08, 0X42, 0X30, 0X84, 0X3C, 0XE7, 0X7D, 0XEF, 42 | 0XFF, 0XFF, 0XB6, 0XB5, 0X49, 0X4A, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X04, 0X21, 0X41, 0X08, 43 | 0X45, 0X29, 0XB6, 0XB5, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 44 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0X71, 0X8C, 45 | 0X41, 0X08, 0X45, 0X29, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X4A, 0X52, 0XB2, 0X94, 0XBE, 0XF7, 46 | 0XBE, 0XF7, 0XB2, 0X94, 0XCF, 0X7B, 0XCF, 0X7B, 0X49, 0X4A, 0XB6, 0XB5, 0XF3, 0X9C, 0X0C, 0X63, 47 | 0X38, 0XC6, 0XBA, 0XD6, 0X0C, 0X63, 0X87, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0XC3, 0X18, 48 | 0X41, 0X08, 0X30, 0X84, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 49 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3C, 0XE7, 0XCB, 0X5A, 50 | 0X41, 0X08, 0XC7, 0X39, 0X08, 0X42, 0X49, 0X4A, 0X4A, 0X52, 0X8A, 0X52, 0XF3, 0X9C, 0XFF, 0XFF, 51 | 0X7D, 0XEF, 0XC7, 0X39, 0XC3, 0X18, 0X0C, 0X63, 0XCB, 0X5A, 0XB6, 0XB5, 0XB2, 0X94, 0XCB, 0X5A, 52 | 0X75, 0XAD, 0XFA, 0XD6, 0X4D, 0X6B, 0X87, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X04, 0X21, 53 | 0X41, 0X08, 0X8A, 0X52, 0X79, 0XCE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 54 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X38, 0XC6, 0X86, 0X31, 55 | 0X04, 0X21, 0XC8, 0X41, 0X49, 0X4A, 0X49, 0X4A, 0X4A, 0X52, 0X49, 0X4A, 0XB1, 0X8C, 0XBE, 0XF7, 56 | 0XBE, 0XF7, 0XB2, 0X94, 0XCF, 0X7B, 0XCF, 0X7B, 0X49, 0X4A, 0X74, 0XA5, 0X7D, 0XEF, 0X7C, 0XE7, 57 | 0XBE, 0XF7, 0X79, 0XCE, 0X0C, 0X63, 0XC7, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X04, 0X21, 58 | 0X82, 0X10, 0X45, 0X29, 0X75, 0XAD, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 59 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X34, 0XA5, 0X82, 0X10, 60 | 0X86, 0X31, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X8A, 0X52, 0X49, 0X4A, 0X4D, 0X6B, 0XBA, 0XD6, 61 | 0XFF, 0XFF, 0XFF, 0XFF, 0X79, 0XCE, 0X0D, 0X63, 0XC7, 0X39, 0XCF, 0X7B, 0X7D, 0XEF, 0XFF, 0XFF, 62 | 0XFF, 0XFF, 0X75, 0XAD, 0X08, 0X42, 0X86, 0X31, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X45, 0X29, 63 | 0XC3, 0X18, 0XC3, 0X18, 0XB2, 0X94, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 64 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0XB2, 0X8C, 0X41, 0X08, 65 | 0XC7, 0X39, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X8A, 0X52, 0X8A, 0X52, 0X4A, 0X4A, 0XD0, 0X7B, 66 | 0X7A, 0XC6, 0X7B, 0XBE, 0X90, 0X6B, 0XC9, 0X39, 0X88, 0X31, 0XC9, 0X39, 0XB3, 0X84, 0XBB, 0XC6, 67 | 0XF8, 0XB5, 0XCC, 0X5A, 0X86, 0X31, 0XC7, 0X39, 0XC7, 0X39, 0X86, 0X31, 0X45, 0X29, 0X45, 0X29, 68 | 0XC4, 0X20, 0X41, 0X08, 0X30, 0X84, 0X3C, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 69 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3C, 0XE7, 0X8A, 0X4A, 0XC3, 0X10, 70 | 0XC7, 0X39, 0X08, 0X42, 0X49, 0X4A, 0X49, 0X4A, 0X4A, 0X4A, 0X4A, 0X42, 0X09, 0X3A, 0X08, 0X4A, 71 | 0X09, 0X6B, 0X49, 0X7B, 0XC6, 0X7A, 0X05, 0X83, 0X46, 0X83, 0XC5, 0X7A, 0XC6, 0X72, 0X09, 0X7B, 72 | 0X48, 0X5A, 0X87, 0X31, 0X88, 0X21, 0X88, 0X29, 0X86, 0X31, 0X86, 0X31, 0X45, 0X29, 0X45, 0X29, 73 | 0X04, 0X21, 0X41, 0X08, 0X4A, 0X4A, 0XBA, 0XD6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 74 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XF7, 0XC5, 0X82, 0X50, 0X05, 0X41, 75 | 0XC7, 0X29, 0X08, 0X42, 0X49, 0X4A, 0X4A, 0X42, 0X49, 0X4A, 0X09, 0X7B, 0X88, 0X9B, 0XC6, 0XB3, 76 | 0X21, 0XD4, 0XA0, 0XDC, 0XE1, 0XE4, 0X61, 0XED, 0X61, 0XED, 0X21, 0XED, 0XA0, 0XE4, 0X20, 0XDC, 77 | 0X80, 0XCB, 0X43, 0XAB, 0XC4, 0X82, 0X06, 0X5A, 0X47, 0X21, 0X46, 0X29, 0X45, 0X29, 0X04, 0X29, 78 | 0X04, 0X19, 0X82, 0X10, 0X82, 0X18, 0XF3, 0X9C, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 79 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7D, 0XEF, 0X4D, 0X93, 0X00, 0XA0, 0X82, 0XB8, 80 | 0XC7, 0X31, 0X09, 0X32, 0X49, 0X4A, 0X86, 0X7A, 0X43, 0XC3, 0X6B, 0XED, 0XF4, 0XF6, 0XEB, 0XFD, 81 | 0X20, 0XFD, 0X20, 0XFD, 0X60, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X20, 0XFD, 82 | 0XE0, 0XFC, 0XA0, 0XFC, 0X60, 0XF4, 0XC1, 0XDB, 0X83, 0X9A, 0XC5, 0X49, 0X45, 0X29, 0X04, 0X19, 83 | 0XC4, 0X20, 0X82, 0X38, 0X00, 0X50, 0XCB, 0X6A, 0XBA, 0XD6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 84 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFB, 0XEE, 0X04, 0XA1, 0X00, 0XC0, 0X00, 0XF0, 85 | 0XC3, 0XA0, 0XC8, 0X41, 0X49, 0X42, 0X05, 0X9B, 0X20, 0XFC, 0XA4, 0XFC, 0X69, 0XFD, 0XE8, 0XFD, 86 | 0X63, 0XFD, 0X20, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0XE0, 0XFC, 87 | 0XE0, 0XFC, 0XA0, 0XFC, 0X60, 0XFC, 0X20, 0XFC, 0X41, 0XD3, 0XC5, 0X49, 0X45, 0X19, 0XC4, 0X38, 88 | 0X82, 0X68, 0X41, 0X88, 0X00, 0X70, 0X49, 0X5A, 0X79, 0XCE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 89 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFB, 0XF6, 0X82, 0XC0, 0X00, 0XD0, 0X86, 0XC1, 90 | 0X46, 0XF1, 0X41, 0XC8, 0X45, 0X79, 0X89, 0X52, 0X88, 0X62, 0X86, 0X6A, 0XC6, 0X7A, 0XC4, 0XBB, 91 | 0XE1, 0XFC, 0X60, 0XFD, 0X60, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0XE0, 0XFC, 92 | 0X60, 0XE4, 0X03, 0X93, 0X84, 0X72, 0X44, 0X6A, 0XC5, 0X41, 0X45, 0X29, 0XC3, 0X58, 0X41, 0XA8, 93 | 0X40, 0X98, 0X00, 0XB0, 0X00, 0X60, 0X0C, 0X6B, 0X79, 0XCE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 94 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7D, 0XEF, 0XCE, 0X83, 0X82, 0X88, 0X00, 0XF8, 0XC4, 0XD8, 95 | 0X0C, 0XF3, 0X8A, 0XFA, 0X82, 0XE8, 0X82, 0XB0, 0X45, 0X69, 0XC7, 0X51, 0X08, 0X42, 0X08, 0X3A, 96 | 0X86, 0X5A, 0X83, 0X9B, 0XA2, 0XBC, 0X22, 0XCD, 0X21, 0XCD, 0XA1, 0XC4, 0X22, 0XB4, 0XC4, 0X7A, 97 | 0X06, 0X3A, 0X86, 0X29, 0X45, 0X29, 0X05, 0X31, 0XC4, 0X50, 0X41, 0X90, 0X00, 0XC0, 0X00, 0XA8, 98 | 0X00, 0XA0, 0X00, 0XA8, 0X00, 0X30, 0X4A, 0X4A, 0XBA, 0XD6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 99 | 0XFF, 0XFF, 0XFF, 0XFF, 0X7D, 0XEF, 0X8E, 0X73, 0XC3, 0X18, 0X05, 0X39, 0X82, 0XA8, 0X00, 0XF8, 100 | 0XC3, 0XF8, 0X4D, 0XFB, 0X4D, 0XFB, 0XC7, 0XF9, 0XC3, 0XF0, 0X82, 0XD8, 0XC3, 0XB0, 0X04, 0X81, 101 | 0X45, 0X61, 0X46, 0X51, 0X86, 0X49, 0X86, 0X49, 0X46, 0X41, 0X45, 0X41, 0X45, 0X41, 0X45, 0X41, 102 | 0X05, 0X49, 0X04, 0X61, 0X82, 0X90, 0X41, 0XB0, 0X00, 0XD0, 0X00, 0XC8, 0X00, 0XA8, 0X00, 0XA8, 103 | 0X00, 0XB8, 0X41, 0X58, 0X82, 0X10, 0X82, 0X10, 0XB2, 0X94, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 104 | 0XFF, 0XFF, 0XBE, 0XF7, 0XCF, 0X7B, 0X82, 0X10, 0X04, 0X21, 0X86, 0X29, 0X86, 0X41, 0X04, 0X99, 105 | 0X40, 0XE8, 0X41, 0XF8, 0X86, 0XF9, 0XCB, 0XFA, 0X49, 0XFA, 0X82, 0XF8, 0X00, 0XF8, 0X00, 0XF0, 106 | 0X00, 0XE8, 0X41, 0XD8, 0X41, 0XD0, 0X41, 0XC0, 0X41, 0XC0, 0X41, 0XC0, 0X41, 0XC0, 0X41, 0XC8, 107 | 0X00, 0XD0, 0X00, 0XE0, 0X00, 0XE0, 0X00, 0XD8, 0X00, 0XD0, 0X00, 0XB8, 0X00, 0XA8, 0X41, 0X88, 108 | 0X82, 0X48, 0X82, 0X10, 0X82, 0X10, 0X00, 0X00, 0X45, 0X29, 0X79, 0XCE, 0XFF, 0XFF, 0XFF, 0XFF, 109 | 0XBE, 0XF7, 0XF3, 0X9C, 0X82, 0X10, 0XC3, 0X18, 0X45, 0X29, 0X86, 0X31, 0XC7, 0X31, 0X30, 0X7C, 110 | 0XF3, 0XDC, 0X86, 0XE1, 0X00, 0XF0, 0X00, 0XF8, 0X41, 0XF8, 0X41, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 111 | 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 112 | 0X00, 0XE8, 0X00, 0XE0, 0X00, 0XE0, 0X00, 0XD8, 0X00, 0XC8, 0X41, 0XA0, 0X8A, 0X9A, 0X0C, 0X63, 113 | 0X04, 0X11, 0X82, 0X10, 0X82, 0X10, 0X41, 0X08, 0X00, 0X00, 0X4D, 0X6B, 0X7D, 0XEF, 0XFF, 0XFF, 114 | 0XFB, 0XDE, 0X08, 0X42, 0X42, 0X10, 0X45, 0X29, 0X86, 0X31, 0X86, 0X31, 0X49, 0X4A, 0X38, 0XBE, 115 | 0XFF, 0XFF, 0X38, 0XD6, 0X86, 0XA9, 0X00, 0XC8, 0X00, 0XE0, 0X00, 0XF0, 0X00, 0XF8, 0X00, 0XF8, 116 | 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF8, 0X00, 0XF0, 0X00, 0XF0, 117 | 0X00, 0XE8, 0X00, 0XE0, 0X00, 0XD0, 0XC3, 0X98, 0X8A, 0X8A, 0XB2, 0XA4, 0XBA, 0XC6, 0XF7, 0XB5, 118 | 0X08, 0X42, 0X41, 0X08, 0X82, 0X10, 0X41, 0X08, 0X00, 0X00, 0X45, 0X29, 0XF7, 0XBD, 0XFF, 0XFF, 119 | 0X71, 0X8C, 0X41, 0X08, 0X04, 0X21, 0X45, 0X29, 0X86, 0X31, 0X86, 0X31, 0X0C, 0X63, 0X3C, 0XE7, 120 | 0XFF, 0XFF, 0X79, 0XD6, 0X46, 0XB9, 0X00, 0XE0, 0X42, 0XC8, 0X82, 0XA8, 0X82, 0XB0, 0X41, 0XD8, 121 | 0X82, 0XE8, 0X82, 0XF0, 0X41, 0XE8, 0X41, 0XE8, 0X41, 0XE8, 0X41, 0XF0, 0X41, 0XE8, 0X41, 0XD8, 122 | 0X04, 0XC1, 0X08, 0X92, 0X4D, 0X8B, 0X34, 0XA5, 0XFB, 0XC6, 0XFB, 0XD6, 0XBA, 0XCE, 0X3C, 0XE7, 123 | 0X30, 0X84, 0XC3, 0X18, 0X41, 0X08, 0X41, 0X08, 0X00, 0X00, 0X41, 0X08, 0XCF, 0X7B, 0X7D, 0XEF, 124 | 0X49, 0X4A, 0X00, 0X00, 0X04, 0X21, 0X45, 0X29, 0X46, 0X31, 0X86, 0X31, 0X30, 0X84, 0XFF, 0XFF, 125 | 0XFF, 0XF7, 0XF7, 0XDD, 0X09, 0XDA, 0X83, 0XF8, 0X01, 0XF0, 0X42, 0XC0, 0X82, 0X98, 0X49, 0X9A, 126 | 0XF3, 0XB4, 0XF3, 0XCC, 0X71, 0XBC, 0X8E, 0XBB, 0X8E, 0XBB, 0X30, 0XBC, 0X71, 0XBC, 0XF3, 0XBC, 127 | 0XB6, 0XBD, 0XFB, 0XCE, 0XBE, 0XE7, 0X7D, 0XE7, 0X3B, 0XDF, 0XBA, 0XD6, 0X79, 0XCE, 0XFB, 0XDE, 128 | 0X75, 0XAD, 0X86, 0X31, 0X41, 0X08, 0X41, 0X08, 0X00, 0X00, 0X00, 0X00, 0X49, 0X4A, 0XFB, 0XDE, 129 | 0X04, 0X21, 0X41, 0X08, 0X04, 0X21, 0X45, 0X29, 0X45, 0X29, 0X87, 0X39, 0XB2, 0X94, 0XFF, 0XFF, 130 | 0XBE, 0XF7, 0X34, 0XDD, 0X0C, 0XEB, 0X09, 0XFA, 0X00, 0XF0, 0X01, 0XD8, 0X00, 0XD8, 0X8B, 0XD2, 131 | 0X7D, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 132 | 0XFF, 0XFF, 0XBE, 0XFF, 0X7D, 0XEF, 0XFB, 0XDE, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0XBA, 0XD6, 133 | 0X78, 0XC6, 0XC7, 0X39, 0X00, 0X00, 0X41, 0X08, 0X00, 0X00, 0X00, 0X00, 0XC7, 0X39, 0X79, 0XCE, 134 | 0X00, 0X00, 0X82, 0X10, 0XC3, 0X18, 0X04, 0X21, 0X05, 0X29, 0X86, 0X31, 0XB3, 0X9C, 0XFF, 0XFF, 135 | 0XFF, 0XF7, 0X75, 0XDD, 0XC7, 0XE9, 0XC7, 0XF9, 0X01, 0XF8, 0X01, 0XF0, 0X00, 0XE8, 0X49, 0XE2, 136 | 0XFB, 0XEE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 137 | 0XFF, 0XFF, 0XBE, 0XF7, 0X7D, 0XEF, 0XFB, 0XDE, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0XBA, 0XD6, 138 | 0XB9, 0XCE, 0X08, 0X42, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0XC7, 0X39, 0X38, 0XC6, 139 | 0X00, 0X00, 0X82, 0X10, 0X82, 0X10, 0X04, 0X21, 0X04, 0X21, 0X45, 0X29, 0X30, 0X84, 0XFF, 0XFF, 140 | 0XFF, 0XFF, 0X38, 0XDE, 0XC4, 0XD0, 0X00, 0XF0, 0X01, 0XF8, 0X00, 0XF8, 0X00, 0XF0, 0X08, 0XD2, 141 | 0XFB, 0XE6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 142 | 0XFF, 0XFF, 0XBE, 0XF7, 0X7D, 0XEF, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0X79, 0XCE, 0XBA, 0XD6, 143 | 0X79, 0XCE, 0XC7, 0X39, 0X41, 0X08, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X86, 0X31, 0X38, 0XC6, 144 | 0X00, 0X00, 0X00, 0X00, 0XC3, 0X18, 0XCB, 0X5A, 0X86, 0X31, 0XC3, 0X18, 0XCB, 0X5A, 0X7D, 0XEF, 145 | 0XFF, 0XFF, 0X7D, 0XEF, 0XCF, 0XBB, 0XC3, 0XB0, 0X41, 0XD0, 0X41, 0XD0, 0X82, 0XB8, 0X4D, 0XB3, 146 | 0X7D, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 147 | 0XBE, 0XF7, 0XBE, 0XF7, 0X3D, 0XEF, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0X79, 0XCE, 0XFA, 0XD6, 148 | 0XF7, 0XBD, 0X04, 0X21, 0X86, 0X31, 0X04, 0X21, 0X00, 0X00, 0X00, 0X00, 0X86, 0X31, 0X38, 0XC6, 149 | 0X86, 0X31, 0XC3, 0X18, 0XCB, 0X5A, 0X75, 0XAD, 0XCF, 0X7B, 0X41, 0X08, 0X86, 0X31, 0XF7, 0XBD, 150 | 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XEF, 0X74, 0XB5, 0X30, 0X9C, 0X30, 0X9C, 0X72, 0XA4, 0XBB, 0XD6, 151 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 152 | 0XBE, 0XF7, 0X7D, 0XEF, 0X3C, 0XE7, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0X79, 0XCE, 0X3C, 0XE7, 153 | 0X71, 0X8C, 0X81, 0X08, 0X0C, 0X63, 0XCF, 0X7B, 0X82, 0X10, 0X00, 0X00, 0X8A, 0X52, 0X38, 0XC6, 154 | 0X75, 0XAD, 0X71, 0X8C, 0XB6, 0XB5, 0X3C, 0XE7, 0XFB, 0XDE, 0XC7, 0X39, 0X00, 0X00, 0XCF, 0X73, 155 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 156 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 157 | 0X7D, 0XEF, 0X7D, 0XEF, 0X3B, 0XDF, 0XFA, 0XD6, 0X79, 0XCE, 0X79, 0XCE, 0XFB, 0XDE, 0XB9, 0XCE, 158 | 0XC7, 0X39, 0XC4, 0X20, 0X71, 0X8C, 0XBA, 0XD6, 0X71, 0X8C, 0XCB, 0X5A, 0XB2, 0X94, 0XBA, 0XD6, 159 | 0XFF, 0XFF, 0X7D, 0XEF, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XB6, 0XB5, 0X46, 0X29, 0X05, 0X19, 160 | 0X75, 0XA5, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 161 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 162 | 0X7D, 0XEF, 0X3C, 0XE7, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0XBA, 0XD6, 0XFC, 0XDE, 0X4E, 0X63, 163 | 0X42, 0X08, 0X0C, 0X63, 0XF7, 0XBD, 0XBE, 0XF7, 0XFF, 0XFF, 0XFB, 0XDE, 0XFB, 0XDE, 0XBE, 0XF7, 164 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XF4, 0X9C, 0X04, 0X21, 165 | 0X05, 0X21, 0XB6, 0XA5, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 166 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0XBE, 0XF7, 0X7D, 0XEF, 167 | 0X3C, 0XE7, 0XFB, 0XDE, 0XBA, 0XD6, 0X79, 0XCE, 0XFB, 0XDE, 0XBB, 0XD6, 0XD1, 0X73, 0X83, 0X18, 168 | 0X86, 0X39, 0X34, 0X9D, 0XBD, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 169 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XFF, 0X35, 0XD6, 0XEB, 0XCC, 0X43, 0XB3, 170 | 0X40, 0X51, 0X05, 0X19, 0XF5, 0X8C, 0XBE, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 171 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0XBE, 0XF7, 0X7D, 0XEF, 0X7D, 0XEF, 0X3C, 0XE7, 172 | 0XFB, 0XDE, 0XBA, 0XDE, 0XBA, 0XD6, 0X3C, 0XDF, 0X3A, 0XBE, 0X4F, 0X63, 0X82, 0X49, 0X40, 0XA3, 173 | 0X23, 0XB4, 0XCC, 0X83, 0X3A, 0XBE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 174 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBF, 0XF7, 0XB5, 0XBD, 0X82, 0X92, 0X20, 0XF4, 0XA0, 0XFC, 175 | 0X60, 0XE4, 0X40, 0X82, 0X84, 0X41, 0X8F, 0X6B, 0X77, 0XAD, 0X3D, 0XE7, 0XFF, 0XFF, 0XFF, 0XFF, 176 | 0XFE, 0XFF, 0XBE, 0XF7, 0XBE, 0XF7, 0XBE, 0XF7, 0X7D, 0XEF, 0X7D, 0XEF, 0X3C, 0XE7, 0XFB, 0XDE, 177 | 0XFB, 0XDE, 0X3D, 0XE7, 0XBB, 0XCE, 0X36, 0X9D, 0X0B, 0X6B, 0X41, 0X6A, 0X60, 0XC4, 0X20, 0XFE, 178 | 0X60, 0XF5, 0X00, 0X8B, 0XC7, 0X6A, 0X38, 0XC6, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 179 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7D, 0XEF, 0X4B, 0X7B, 0X80, 0XB2, 0XA0, 0XFC, 0XA0, 0XFC, 180 | 0XE0, 0XFC, 0XE0, 0XFC, 0XC0, 0XCB, 0XC1, 0X8A, 0X45, 0X62, 0X4D, 0X6B, 0XB3, 0X94, 0XF7, 0XBD, 181 | 0X3D, 0XDF, 0XFF, 0XF7, 0XFF, 0XFF, 0XBE, 0XF7, 0X7D, 0XEF, 0X7D, 0XEF, 0X7D, 0XE7, 0X3D, 0XDF, 182 | 0XBA, 0XC6, 0X75, 0XA5, 0X8D, 0X7B, 0X84, 0X7A, 0X40, 0XB3, 0XE0, 0XEC, 0XE0, 0XFD, 0XE0, 0XFD, 183 | 0X60, 0XF5, 0X20, 0XE5, 0XA0, 0XD4, 0X0A, 0X6B, 0XFB, 0XDE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 184 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7D, 0XEF, 0XCC, 0X93, 0X40, 0XEB, 0X60, 0XFC, 0XA0, 0XFC, 185 | 0XE0, 0XFC, 0X20, 0XFD, 0X60, 0XFD, 0X20, 0XF5, 0XA0, 0XD4, 0XC0, 0XBB, 0X42, 0X9B, 0X45, 0X8B, 186 | 0X6B, 0X9C, 0XAE, 0X9C, 0X71, 0X8C, 0XB3, 0X94, 0X33, 0X9D, 0X34, 0XA5, 0XF2, 0XA4, 0XF0, 0XB4, 187 | 0XCA, 0X9B, 0X04, 0X9B, 0X40, 0XBB, 0X20, 0XE4, 0X20, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0XE0, 0XFD, 188 | 0XE0, 0XFD, 0XE0, 0XFD, 0X20, 0XC4, 0X88, 0X5A, 0X38, 0XBE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 189 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X78, 0XD6, 0X46, 0XAB, 0X40, 0XDB, 0X20, 0XF4, 190 | 0X60, 0XFC, 0XA0, 0XFC, 0XE0, 0XFC, 0X60, 0XFD, 0XA0, 0XFD, 0X60, 0XFD, 0X20, 0XF5, 0XA0, 0XDC, 191 | 0XC0, 0XB3, 0XC0, 0X51, 0X86, 0X29, 0X0D, 0X63, 0X8F, 0X7B, 0X0D, 0X5B, 0XC7, 0X41, 0X01, 0X82, 192 | 0X00, 0XC3, 0XC0, 0XE3, 0X60, 0XFC, 0XA0, 0XFC, 0XE0, 0XFC, 0XE0, 0XFC, 0X60, 0XF5, 0X60, 0XF5, 193 | 0X20, 0XE5, 0X80, 0X9B, 0X86, 0X62, 0X30, 0X84, 0X79, 0XCE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 194 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X38, 0XC6, 0X2D, 0X9C, 0X05, 0X93, 195 | 0X43, 0XA3, 0X82, 0XB3, 0XC2, 0XBB, 0XC2, 0XBB, 0X22, 0XB4, 0X82, 0XA3, 0X42, 0X93, 0XC3, 0X7A, 196 | 0X85, 0X62, 0X0B, 0X63, 0X71, 0X84, 0XB6, 0XB5, 0X79, 0XCE, 0X79, 0XC6, 0XB5, 0XAD, 0X70, 0X94, 197 | 0X4A, 0X8B, 0X06, 0X83, 0X04, 0X93, 0X04, 0X9B, 0X43, 0X9B, 0X43, 0X9B, 0X43, 0X93, 0X04, 0X83, 198 | 0X08, 0X73, 0X8D, 0X73, 0XB3, 0X94, 0X79, 0XCE, 0X7D, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 199 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3C, 0XDF, 0X38, 0XBE, 200 | 0X75, 0XB5, 0X33, 0XA5, 0X33, 0XA5, 0XF3, 0X9C, 0XF3, 0X9C, 0XF3, 0X9C, 0XF3, 0X94, 0XF3, 0X9C, 201 | 0X35, 0XA5, 0XF8, 0XBD, 0XFB, 0XDE, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7E, 0XEF, 202 | 0XBB, 0XD6, 0XF8, 0XBD, 0XB6, 0XAD, 0X75, 0XAD, 0X34, 0XA5, 0X33, 0X9D, 0X34, 0X9D, 0X35, 0XA5, 203 | 0XB7, 0XAD, 0X79, 0XC6, 0X3C, 0XE7, 0XBE, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 204 | }; 205 | 206 | const unsigned char PROGMEM icon_40x40[3200] = { /* 0X00,0X10,0X28,0X00,0X28,0X00,0X01,0X1B, */ 207 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 208 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 209 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 210 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 211 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 212 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 213 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X5D, 0XEF, 0X71, 0X8C, 0X31, 0X84, 0X31, 0X84, 214 | 0X93, 0XC5, 0X92, 0XCD, 0X91, 0XCD, 0X91, 0XD5, 0X91, 0XD5, 0X91, 0XCD, 0X72, 0XCD, 0X72, 0XC5, 215 | 0X56, 0XDE, 0XBE, 0XFF, 0XDB, 0XDE, 0XFB, 0XDE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 216 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 217 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 218 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XCE, 0X7B, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 219 | 0X00, 0X5A, 0X20, 0XDD, 0X20, 0XDD, 0X20, 0XDD, 0X20, 0XDD, 0X20, 0XDD, 0XE0, 0XD4, 0XA0, 0XD4, 220 | 0X61, 0XA3, 0XA7, 0X39, 0XE5, 0X18, 0X05, 0X21, 0X92, 0X94, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 221 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 222 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 223 | 0XFF, 0XFF, 0XFF, 0XFF, 0XF9, 0XEE, 0XEB, 0X9B, 0XA1, 0X18, 0X23, 0X73, 0X81, 0XC5, 0X21, 0X9C, 224 | 0X61, 0X39, 0X81, 0XEE, 0X40, 0XFF, 0XE0, 0XFE, 0XE0, 0XFE, 0XE0, 0XFE, 0X40, 0XFF, 0XC0, 0XF6, 225 | 0XC0, 0X49, 0XA0, 0X18, 0X00, 0X42, 0X60, 0X18, 0X00, 0X00, 0X74, 0XB5, 0XFF, 0XFF, 0XFF, 0XFF, 226 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 227 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 228 | 0XFF, 0XFF, 0X93, 0XCD, 0XC3, 0XBB, 0XA0, 0X51, 0XE1, 0X39, 0XC2, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 229 | 0X63, 0XBD, 0X61, 0XE6, 0X40, 0XFF, 0XE0, 0XFE, 0XE0, 0XFE, 0XC0, 0XFE, 0X60, 0XFF, 0X21, 0X73, 230 | 0XE1, 0X28, 0X81, 0XEE, 0X61, 0XFF, 0X21, 0XEE, 0XA0, 0X41, 0X20, 0X08, 0X90, 0XCD, 0XDE, 0XFF, 231 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 232 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X5C, 0XF7, 233 | 0X0B, 0XAC, 0XC0, 0XB3, 0XA1, 0XEE, 0XC3, 0X5A, 0X22, 0X8C, 0XE1, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 234 | 0XC0, 0XFF, 0X80, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 0X20, 0XFF, 0XA1, 0XAC, 235 | 0X21, 0XC5, 0X20, 0XFF, 0X60, 0XFE, 0X00, 0XFF, 0X02, 0XDE, 0XE0, 0X20, 0X40, 0X82, 0X49, 0XBC, 236 | 0X3B, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 237 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X5C, 0XF7, 0X67, 0X9B, 238 | 0XE0, 0XB3, 0X81, 0XFF, 0XC3, 0XFF, 0X83, 0X9C, 0X82, 0XDE, 0XC0, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 239 | 0X40, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 0X60, 0XFF, 240 | 0X40, 0XFF, 0XA0, 0XFE, 0X80, 0XFE, 0X40, 0XFE, 0XE0, 0XFE, 0XA2, 0XB4, 0X41, 0XBC, 0X20, 0XCC, 241 | 0X87, 0XA3, 0XB8, 0XE6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 242 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X9D, 0XF7, 0XA8, 0XA3, 0X60, 0XBC, 243 | 0XA2, 0XFF, 0XA5, 0XFF, 0X44, 0XFF, 0XA1, 0XFF, 0XA0, 0XFF, 0X60, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 244 | 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 245 | 0X00, 0XFF, 0XC0, 0XFE, 0XA0, 0XFE, 0X80, 0XFE, 0X40, 0XFE, 0X60, 0XFE, 0X20, 0XFE, 0X40, 0XFE, 246 | 0XE0, 0XCB, 0XE3, 0X92, 0X7C, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 247 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X4C, 0XAC, 0XC0, 0XB3, 0XA4, 0XFF, 248 | 0XA6, 0XFF, 0X45, 0XFF, 0X62, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 249 | 0XA0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 250 | 0X20, 0XFF, 0XE0, 0XFE, 0XC0, 0XFE, 0X80, 0XFE, 0X60, 0XFE, 0X40, 0XFE, 0X20, 0XFE, 0X00, 0XFE, 251 | 0XE0, 0XFD, 0XE0, 0XC3, 0X2A, 0XAC, 0X7D, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 252 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XD4, 0XD5, 0X40, 0XAB, 0X43, 0XFF, 0XA8, 0XFF, 253 | 0X67, 0XFF, 0X62, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 254 | 0XC0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 255 | 0X40, 0XFF, 0X00, 0XFF, 0XE0, 0XFE, 0XA0, 0XFE, 0X80, 0XFE, 0X40, 0XFE, 0X20, 0XFE, 0XE0, 0XFD, 256 | 0XE0, 0XFD, 0XC0, 0XFD, 0XA0, 0XA2, 0X11, 0XBD, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 257 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XDA, 0XE6, 0XE4, 0X9A, 0XE1, 0XE5, 0XE8, 0XFF, 0X69, 0XFF, 258 | 0X65, 0XFF, 0X60, 0XFF, 0X80, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 259 | 0XE0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 260 | 0X40, 0XFF, 0X00, 0XFF, 0X00, 0XFF, 0X20, 0XFF, 0XE0, 0XFE, 0X60, 0XFE, 0X20, 0XFE, 0X00, 0XFE, 261 | 0XC0, 0XFD, 0XE0, 0XFD, 0XE0, 0XE4, 0X85, 0XAB, 0XFA, 0XE6, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 262 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X2B, 0XB4, 0XC0, 0XB3, 0XC8, 0XFF, 0X8C, 0XFF, 0X68, 0XFF, 263 | 0X61, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XE0, 0XFF, 0XE1, 0XFF, 0XA1, 0XDE, 0X61, 0XEF, 264 | 0XE1, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 265 | 0X40, 0XFF, 0X60, 0XFF, 0XC0, 0XFF, 0X61, 0XDE, 0X00, 0XE6, 0X80, 0XFE, 0X40, 0XFE, 0X00, 0XFE, 266 | 0XE0, 0XFD, 0XC0, 0XFD, 0XE0, 0XFD, 0XC0, 0XC3, 0XE9, 0XAB, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 267 | 0XFF, 0XFF, 0XFF, 0XFF, 0X5D, 0XEF, 0XA3, 0XAB, 0XA3, 0XF6, 0XCC, 0XFF, 0X4C, 0XFF, 0X64, 0XFF, 268 | 0X80, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XE0, 0XFF, 0X61, 0XEF, 0X22, 0X6B, 0X82, 0X5A, 0X82, 0XB5, 269 | 0XE2, 0XFF, 0XE1, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 270 | 0XA0, 0XFF, 0XE1, 0XFF, 0X42, 0X8C, 0XC1, 0X41, 0X21, 0XA4, 0XA0, 0XFE, 0X80, 0XFE, 0X20, 0XFE, 271 | 0XE0, 0XFD, 0XC0, 0XFD, 0XA0, 0XFD, 0X20, 0XF5, 0XC0, 0X9A, 0X35, 0XD6, 0XFF, 0XFF, 0XFF, 0XFF, 272 | 0XFF, 0XFF, 0XFF, 0XFF, 0X51, 0XC5, 0X60, 0XBC, 0XC9, 0XFF, 0X8E, 0XFF, 0X6A, 0XFF, 0X61, 0XFF, 273 | 0X80, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XE1, 0XFF, 0XE1, 0X62, 0X80, 0X10, 0X05, 0XE7, 0XA4, 0XF7, 274 | 0XE4, 0XFF, 0XE3, 0XFF, 0XE2, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 275 | 0XC1, 0XFF, 0XE2, 0X83, 0X40, 0X08, 0X22, 0XCE, 0X60, 0XF7, 0XA0, 0XFE, 0X60, 0XFE, 0X20, 0XFE, 276 | 0XE0, 0XFD, 0XC0, 0XFD, 0X80, 0XFD, 0XA0, 0XFD, 0XA0, 0XC3, 0XAC, 0XBC, 0XFF, 0XFF, 0XFF, 0XFF, 277 | 0XFF, 0XFF, 0XDE, 0XFF, 0XA7, 0XAB, 0X81, 0XDD, 0XED, 0XFF, 0XB0, 0XFF, 0X69, 0XFF, 0X60, 0XFF, 278 | 0X80, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 0X61, 0XD6, 0X22, 0X29, 0XA6, 0X31, 0XE3, 0X7B, 0X46, 0XEF, 279 | 0XE6, 0XFF, 0XE4, 0XFF, 0XE2, 0XFF, 0XE1, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 280 | 0X81, 0XD6, 0XA0, 0X18, 0XC4, 0X18, 0XA1, 0X62, 0XC1, 0XCD, 0X40, 0XFF, 0X60, 0XFE, 0X20, 0XFE, 281 | 0XE0, 0XFD, 0XC0, 0XFD, 0X80, 0XFD, 0X80, 0XFD, 0XA0, 0XEC, 0X48, 0XBC, 0XDF, 0XFF, 0XFF, 0XFF, 282 | 0XFF, 0XFF, 0XF9, 0XE6, 0XE3, 0X9A, 0X67, 0XEE, 0XD1, 0XFF, 0XB0, 0XFF, 0X86, 0XFF, 0X60, 0XFF, 283 | 0X80, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 0X60, 0X94, 0X91, 0X73, 0XD9, 0XBD, 0X00, 0X00, 0X05, 0X84, 284 | 0XE8, 0XFF, 0XE5, 0XFF, 0XE3, 0XFF, 0XE1, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 285 | 0X20, 0XAD, 0XE9, 0X41, 0XB7, 0XB5, 0X01, 0X00, 0X60, 0X62, 0X21, 0XFF, 0X80, 0XFE, 0X20, 0XFE, 286 | 0XE0, 0XFD, 0XC0, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X20, 0XF5, 0XE3, 0XBB, 0XD9, 0XE6, 0XFF, 0XFF, 287 | 0XFF, 0XFF, 0XD3, 0XCD, 0X40, 0XA3, 0X2B, 0XF7, 0XD3, 0XFF, 0XB0, 0XFF, 0X63, 0XFF, 0X60, 0XFF, 288 | 0X80, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 0XA0, 0X9C, 0X30, 0X6B, 0X97, 0XB5, 0X00, 0X00, 0X83, 0X52, 289 | 0XC6, 0XFF, 0XE5, 0XFF, 0XE3, 0XFF, 0XE1, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 290 | 0X20, 0XAD, 0XEA, 0X41, 0X77, 0XAD, 0X01, 0X00, 0XC0, 0X49, 0XE0, 0XF6, 0XA0, 0XFE, 0X20, 0XFE, 291 | 0XE0, 0XFD, 0XC0, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 0XA0, 0XBB, 0XD3, 0XCD, 0XFF, 0XFF, 292 | 0XFF, 0XFF, 0X50, 0XCD, 0X00, 0XB4, 0X8E, 0XFF, 0XF4, 0XFF, 0XB0, 0XFF, 0X42, 0XFF, 0X60, 0XFF, 293 | 0X80, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 0XA1, 0XDE, 0X01, 0X21, 0X00, 0X00, 0X00, 0X00, 0X25, 0X8C, 294 | 0XE5, 0XFF, 0XE3, 0XFF, 0XE2, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 295 | 0XE1, 0XDE, 0X01, 0X21, 0X00, 0X00, 0X00, 0X00, 0X61, 0X5A, 0X20, 0XFF, 0X80, 0XFE, 0X20, 0XFE, 296 | 0X00, 0XFE, 0XE0, 0XFD, 0XA0, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0XC0, 0XCB, 0X71, 0XCD, 0XFF, 0XFF, 297 | 0XFF, 0XFF, 0X50, 0XCD, 0X40, 0XC4, 0XB0, 0XFF, 0XF5, 0XFF, 0X8F, 0XFF, 0X41, 0XFF, 0X80, 0XFF, 298 | 0XA0, 0XFF, 0XC0, 0XFF, 0XE0, 0XFF, 0XE1, 0XFF, 0X21, 0X8C, 0X60, 0X10, 0X43, 0X6B, 0X44, 0XEF, 299 | 0XE2, 0XFF, 0XE2, 0XFF, 0XE1, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 300 | 0XE1, 0XFF, 0XC1, 0XA4, 0XC2, 0X18, 0XA2, 0X39, 0XA1, 0XCD, 0X20, 0XFF, 0X60, 0XFE, 0X20, 0XFE, 301 | 0XC0, 0XFD, 0X80, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0XE0, 0XCB, 0X91, 0XCD, 0XFF, 0XFF, 302 | 0XFF, 0XFF, 0X50, 0XCD, 0X40, 0XC4, 0XD2, 0XFF, 0XF7, 0XFF, 0XAF, 0XFF, 0X01, 0XFF, 0X00, 0XFF, 303 | 0X00, 0XFF, 0X40, 0XFF, 0XA0, 0XFF, 0XE0, 0XFF, 0XA1, 0XFF, 0X82, 0XD6, 0XC2, 0XFF, 0XE0, 0XFF, 304 | 0XE0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 305 | 0X60, 0XFF, 0XC1, 0XFF, 0X82, 0XDE, 0XC2, 0XEE, 0X61, 0XFF, 0X80, 0XFE, 0XC0, 0XFD, 0X20, 0XFD, 306 | 0XA1, 0XFC, 0X61, 0XFC, 0X61, 0XFC, 0XC0, 0XFC, 0X60, 0XFD, 0XE0, 0XCB, 0X51, 0XC5, 0XFF, 0XFF, 307 | 0XFF, 0XFF, 0X50, 0XCD, 0X60, 0XC4, 0XD4, 0XFF, 0XF9, 0XFF, 0X2D, 0XFF, 0X00, 0XFE, 0XC0, 0XFD, 308 | 0XA1, 0XFD, 0X21, 0XFE, 0XE0, 0XFE, 0XC0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 0XE0, 0XFF, 309 | 0XE0, 0XFF, 0XE0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 310 | 0X40, 0XFF, 0X40, 0XFF, 0X80, 0XFF, 0X20, 0XFF, 0XA0, 0XFE, 0X20, 0XFE, 0X01, 0XFD, 0X01, 0XFC, 311 | 0X62, 0XFB, 0X42, 0XFB, 0X82, 0XFB, 0X21, 0XFC, 0X20, 0XFD, 0X00, 0XD4, 0X71, 0XC5, 0XFF, 0XFF, 312 | 0XFF, 0XFF, 0X50, 0XCD, 0X20, 0XC4, 0XD4, 0XFF, 0XBA, 0XFF, 0X2E, 0XFE, 0XE1, 0XFC, 0X61, 0XFC, 313 | 0X61, 0XFC, 0X01, 0XFD, 0X01, 0XFE, 0X20, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0XC0, 0XFF, 0XC0, 0XFF, 314 | 0XC0, 0XFF, 0XC0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 315 | 0X40, 0XFF, 0X00, 0XFF, 0XC0, 0XFE, 0XA0, 0XFE, 0X80, 0XFE, 0X80, 0XFD, 0X61, 0XFC, 0X62, 0XFB, 316 | 0XA3, 0XFA, 0XA3, 0XFA, 0X42, 0XFB, 0X01, 0XFC, 0XE0, 0XFC, 0XE0, 0XCB, 0X71, 0XCD, 0XFF, 0XFF, 317 | 0XFF, 0XFF, 0X50, 0XCD, 0XC0, 0XB3, 0XB3, 0XFF, 0X7A, 0XFF, 0X91, 0XFD, 0X03, 0XFC, 0X02, 0XFB, 318 | 0X22, 0XFB, 0X62, 0XFC, 0X81, 0XFD, 0XC0, 0XFE, 0XA0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 0XA0, 0XFF, 319 | 0XA0, 0XFF, 0XA0, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 320 | 0X20, 0XFF, 0XE0, 0XFE, 0XC0, 0XFE, 0XA0, 0XFE, 0X60, 0XFE, 0X60, 0XFD, 0X41, 0XFC, 0X62, 0XFB, 321 | 0XC3, 0XFA, 0XA3, 0XFA, 0X42, 0XFB, 0X01, 0XFC, 0X20, 0XFD, 0XC0, 0XCB, 0X91, 0XCD, 0XFF, 0XFF, 322 | 0XFF, 0XFF, 0X14, 0XD6, 0X20, 0XAB, 0X51, 0XF7, 0XBE, 0XFF, 0X17, 0XFE, 0X65, 0XFC, 0X61, 0XFB, 323 | 0XA2, 0XFB, 0XA1, 0XFC, 0XC1, 0XFD, 0X00, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 324 | 0X80, 0XFF, 0X80, 0XFF, 0X80, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 325 | 0X00, 0XFF, 0XC0, 0XFE, 0XA0, 0XFE, 0X80, 0XFE, 0X60, 0XFE, 0XC0, 0XFD, 0XC0, 0XFC, 0X41, 0XFC, 326 | 0XC1, 0XFB, 0XA2, 0XFB, 0X01, 0XFC, 0XA0, 0XFC, 0X40, 0XFD, 0XA0, 0XC3, 0XF4, 0XD5, 0XFF, 0XFF, 327 | 0XFF, 0XFF, 0X5B, 0XEF, 0X24, 0X9B, 0X49, 0XE6, 0XB8, 0XFF, 0X92, 0XFE, 0X25, 0XFD, 0XA0, 0XFC, 328 | 0X02, 0XFD, 0XE1, 0XFD, 0XE0, 0XFE, 0X40, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 329 | 0X60, 0XFF, 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 330 | 0XC0, 0XFE, 0XA0, 0XFE, 0X80, 0XFE, 0X40, 0XFE, 0X40, 0XFE, 0X00, 0XFE, 0X80, 0XFD, 0X01, 0XF5, 331 | 0X41, 0XFD, 0X01, 0XFD, 0XC0, 0XFC, 0X40, 0XFD, 0X00, 0XF5, 0XC4, 0XBB, 0XFA, 0XE6, 0XFF, 0XFF, 332 | 0XFF, 0XFF, 0XFF, 0XFF, 0X2A, 0XB4, 0XA0, 0XD4, 0XA2, 0XFE, 0X20, 0XFE, 0XE0, 0XFD, 0X00, 0XFE, 333 | 0X80, 0XFE, 0X21, 0XEE, 0X41, 0XE6, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 334 | 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 0XE0, 0XFE, 0XC0, 0XFE, 335 | 0XA0, 0XFE, 0X80, 0XFE, 0X60, 0XFE, 0X40, 0XFE, 0X00, 0XFE, 0X00, 0XFE, 0X00, 0XFE, 0X40, 0XCC, 336 | 0XE1, 0XAB, 0XC1, 0XED, 0X80, 0XFD, 0X60, 0XFD, 0X60, 0XE4, 0X29, 0XB4, 0XFF, 0XFF, 0XFF, 0XFF, 337 | 0XFF, 0XFF, 0XFF, 0XFF, 0X15, 0XD6, 0XE0, 0XBB, 0X60, 0XFE, 0XC8, 0XFE, 0XC8, 0XFE, 0X02, 0XFF, 338 | 0X60, 0XDD, 0X40, 0XA3, 0XA1, 0XDD, 0X40, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 339 | 0X20, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 0XE0, 0XFE, 0XC0, 0XFE, 0XC0, 0XFE, 0XA0, 0XFE, 340 | 0X80, 0XFE, 0X60, 0XFE, 0X40, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X40, 0XED, 341 | 0XC0, 0X9A, 0X40, 0XA3, 0X80, 0XF5, 0X60, 0XFD, 0X60, 0XBB, 0XEE, 0XBC, 0XFF, 0XFF, 0XFF, 0XFF, 342 | 0XFF, 0XFF, 0XFF, 0XFF, 0XDF, 0XFF, 0X63, 0XAB, 0X42, 0XE5, 0XB4, 0XFF, 0X97, 0XFF, 0XAA, 0XF6, 343 | 0X80, 0XAB, 0XA0, 0X92, 0XA1, 0XDD, 0X41, 0XFF, 0X40, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 0X60, 0XFF, 344 | 0X60, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X40, 0XFF, 0X20, 0XFF, 0X20, 0XFF, 0X00, 0XFF, 0XE0, 0XFE, 345 | 0XC0, 0XFE, 0X80, 0XFE, 0X61, 0XFE, 0X00, 0XFE, 0XA0, 0XED, 0X20, 0XE5, 0X21, 0XCC, 0X80, 0XB3, 346 | 0X00, 0XBC, 0XE0, 0XC3, 0X40, 0XED, 0XC0, 0XEC, 0X60, 0X92, 0X97, 0XE6, 0XFF, 0XFF, 0XFF, 0XFF, 347 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X0F, 0XC5, 0X00, 0XA3, 0XAA, 0XF6, 0X93, 0XFF, 0X2D, 0XEE, 348 | 0X63, 0XDD, 0X80, 0XD5, 0X42, 0XB4, 0X82, 0XCC, 0X00, 0XCD, 0X40, 0XD5, 0XA0, 0XDD, 0XE1, 0XE5, 349 | 0XC1, 0XE5, 0XC1, 0XE5, 0XC1, 0XE5, 0XC1, 0XE5, 0X80, 0XDD, 0X60, 0XDD, 0X20, 0XD5, 0XC0, 0XCC, 350 | 0XA0, 0XCC, 0X61, 0XC4, 0X21, 0XC4, 0X01, 0XBC, 0X01, 0XBC, 0XE0, 0XBB, 0XC0, 0XBB, 0X60, 0XD4, 351 | 0X80, 0XFD, 0X40, 0XFD, 0X80, 0XFD, 0X80, 0XBB, 0X2B, 0XAC, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 352 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X9D, 0XF7, 0X87, 0XA3, 0X60, 0XD4, 0X0A, 0XFF, 0XCF, 0XFE, 353 | 0XC9, 0XFE, 0XC0, 0XFE, 0XC0, 0XF6, 0X40, 0XE6, 0X41, 0XCD, 0X42, 0XB4, 0XC1, 0XAB, 0X60, 0XA3, 354 | 0X60, 0XA3, 0X80, 0XA3, 0X80, 0XA3, 0X80, 0XA3, 0XA0, 0XAB, 0XC1, 0XAB, 0XE1, 0XB3, 0X22, 0XB4, 355 | 0X82, 0XC4, 0XC0, 0XCC, 0X00, 0XD5, 0X60, 0XE5, 0X81, 0XED, 0X80, 0XF5, 0X80, 0XFD, 0X80, 0XFD, 356 | 0X40, 0XFD, 0X80, 0XFD, 0X80, 0XE4, 0X85, 0XAB, 0X5C, 0XEF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 357 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFA, 0XE6, 0X23, 0XA3, 0XE0, 0XE4, 0XE8, 0XFE, 358 | 0X6A, 0XFE, 0X05, 0XFE, 0X40, 0XFE, 0XA0, 0XFE, 0XC0, 0XFE, 0XE1, 0XFE, 0XA0, 0XF6, 0XA0, 0XF6, 359 | 0XA0, 0XF6, 0XA0, 0XF6, 0X80, 0XF6, 0X80, 0XF6, 0X80, 0XF6, 0X60, 0XF6, 0X61, 0XFE, 0X81, 0XFE, 360 | 0X61, 0XFE, 0X20, 0XFE, 0X00, 0XFE, 0XC0, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 361 | 0X60, 0XFD, 0X20, 0XF5, 0XA0, 0XA2, 0XB4, 0XCD, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 362 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X52, 0XC5, 0XE0, 0XA2, 0XA1, 0XF5, 363 | 0X86, 0XFE, 0X06, 0XFE, 0XE2, 0XFD, 0XE0, 0XFD, 0X00, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 364 | 0X40, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X20, 0XFE, 0X00, 0XFE, 0XE0, 0XFD, 0XE0, 0XFD, 0XC0, 0XFD, 365 | 0XA0, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X40, 0XFD, 366 | 0X60, 0XFD, 0X60, 0XBB, 0X6C, 0XB4, 0XDE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 367 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X92, 0XCD, 0XC0, 0XA2, 368 | 0X20, 0XED, 0X22, 0XFE, 0XC1, 0XFD, 0XA0, 0XFD, 0XC0, 0XFD, 0XE0, 0XFD, 0XE0, 0XFD, 0XE0, 0XFD, 369 | 0XE0, 0XFD, 0XE0, 0XFD, 0XC0, 0XFD, 0XC0, 0XFD, 0XC0, 0XFD, 0XC0, 0XFD, 0XA0, 0XFD, 0X80, 0XFD, 370 | 0X80, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 371 | 0X20, 0XB3, 0XEA, 0XA3, 0X9D, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 372 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X8E, 0XBC, 373 | 0XE1, 0XA2, 0X00, 0XE5, 0XE0, 0XFD, 0XC0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 374 | 0XC0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0XA0, 0XFD, 0X80, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 375 | 0X40, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X80, 0XFD, 0X00, 0XF5, 0X40, 0XBB, 376 | 0X2B, 0XAC, 0X9D, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 377 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 378 | 0X35, 0XD6, 0XE2, 0X9A, 0XA0, 0XC3, 0XA0, 0XFD, 0XE0, 0XFD, 0X80, 0XFD, 0X60, 0XFD, 0X80, 0XFD, 379 | 0X80, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 380 | 0X20, 0XFD, 0X20, 0XFD, 0X40, 0XFD, 0X60, 0XFD, 0X60, 0XFD, 0X00, 0XD4, 0XC1, 0X9A, 0X10, 0XC5, 381 | 0XDE, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 382 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 383 | 0XFF, 0XFF, 0X98, 0XDE, 0X2B, 0XAC, 0X40, 0XB3, 0X00, 0XD4, 0X40, 0XFD, 0X80, 0XFD, 0X80, 0XFD, 384 | 0X60, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 0X40, 0XFD, 385 | 0X40, 0XFD, 0X60, 0XFD, 0X40, 0XFD, 0X40, 0XDC, 0X80, 0XBB, 0XE8, 0XAB, 0X57, 0XDE, 0XFF, 0XFF, 386 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 387 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 388 | 0XFF, 0XFF, 0XFF, 0XFF, 0XDF, 0XFF, 0X37, 0XD6, 0X86, 0XA3, 0XC0, 0X9A, 0XE0, 0XCB, 0X80, 0XEC, 389 | 0XE0, 0XF4, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X20, 0XFD, 0X00, 0XF5, 390 | 0XA0, 0XEC, 0X00, 0XD4, 0X40, 0XB3, 0X03, 0X9B, 0X92, 0XC5, 0XBD, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 391 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 392 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 393 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XBE, 0XF7, 0XF5, 0XCD, 0XAD, 0XBC, 0X69, 0XBC, 394 | 0X05, 0XBC, 0X03, 0XC4, 0X01, 0XC4, 0X01, 0XC4, 0X01, 0XC4, 0X01, 0XC4, 0XE2, 0XC3, 0X24, 0XC4, 395 | 0X68, 0XBC, 0XAC, 0XBC, 0XD3, 0XCD, 0X9E, 0XF7, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 396 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 397 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 398 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 399 | 0X5B, 0XEF, 0X98, 0XDE, 0X56, 0XD6, 0X57, 0XD6, 0X57, 0XD6, 0X56, 0XD6, 0X77, 0XDE, 0X1B, 0XEF, 400 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 401 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 402 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 403 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 404 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 405 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 406 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 407 | }; 408 | 409 | const unsigned char PROGMEM wifi_full[2048] = { 410 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x21, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 411 | 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 412 | 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 413 | 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x71, 0xC2, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 414 | 0x00, 0x00, 0x28, 0xA0, 0xCB, 0x23, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 415 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 416 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 417 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xC3, 0x03, 0x18, 0x60, 0x00, 0x00, 418 | 0x08, 0x20, 0xD3, 0x23, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 419 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 420 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 421 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xC3, 0x03, 0x00, 0x00, 422 | 0x59, 0x61, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 423 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 424 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 425 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x41, 0x01, 426 | 0x8A, 0x22, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 427 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 428 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 429 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 430 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 431 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 432 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 433 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 434 | 0x92, 0x42, 0xF4, 0x89, 0xFE, 0x34, 0xFE, 0xB7, 0xFF, 0x19, 0xFF, 0x3A, 0xFF, 0x3A, 0xFE, 0xD8, 435 | 0xFE, 0x76, 0xF5, 0xD1, 0xF5, 0x0C, 0xEB, 0xE6, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 436 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 437 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 438 | 0x92, 0x42, 0xF4, 0xEC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 439 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x19, 0xF5, 0x90, 0xEC, 0x06, 0xEB, 0xA4, 440 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 441 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 442 | 0x92, 0x42, 0xF4, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 443 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x54, 444 | 0xF4, 0x47, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 445 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 446 | 0x92, 0x42, 0xEB, 0xA4, 0xFF, 0x9D, 0xFF, 0xFF, 0xFF, 0xBD, 0xFF, 0x7C, 0xFF, 0x7C, 0xFF, 0x9D, 447 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 448 | 0xFF, 0xFF, 0xF6, 0x13, 0xEB, 0xE5, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 449 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 450 | 0x92, 0x42, 0xEB, 0xA4, 0xF4, 0x47, 0xEB, 0xE5, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 451 | 0xEB, 0xC4, 0xF4, 0x48, 0xF5, 0x2E, 0xFE, 0x55, 0xFF, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 452 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xF4, 0xAA, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 453 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 454 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 455 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xC4, 0xF5, 0x0C, 0xFE, 0xF9, 0xFF, 0xFF, 456 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xB1, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 457 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 458 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0x27, 0xF4, 0xCB, 0xF5, 0x0C, 0xF5, 0x0C, 459 | 0xF4, 0xAB, 0xF4, 0x27, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0xEC, 460 | 0xFF, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x34, 0xEB, 0xC4, 0xEB, 0xA4, 461 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 462 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xFE, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 463 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xFE, 0x76, 0xF4, 0xEC, 0xEB, 0xC4, 0xEB, 0xA4, 0xEB, 0xA4, 464 | 0xEB, 0xC5, 0xFE, 0x34, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x55, 0xEB, 0xA4, 465 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 466 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF6, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 467 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0xF5, 0x6F, 0xEB, 0xC4, 468 | 0xEB, 0xA4, 0xEB, 0xA4, 0xF5, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0xF2, 469 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 470 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0x69, 0xF5, 0x0C, 0xF4, 0xAA, 0xF4, 0x89, 471 | 0xF4, 0xCB, 0xF5, 0x6F, 0xFE, 0x55, 0xFF, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 472 | 0xF4, 0x48, 0xEB, 0xA4, 0xEB, 0xA4, 0xF5, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 473 | 0xF5, 0x0D, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 474 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 475 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xC4, 0xF4, 0xEC, 0xFF, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 476 | 0xFF, 0xDE, 0xF5, 0x0D, 0xEB, 0xA4, 0xEB, 0xA4, 0xF5, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 477 | 0xFF, 0xBE, 0xF4, 0x27, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 478 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 479 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF5, 0x4E, 0xFF, 0xDE, 480 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF5, 0x4E, 0xEB, 0xA4, 0xEB, 0xA4, 0xFE, 0x54, 0xFF, 0xFF, 0xFF, 0xFF, 481 | 0xFF, 0xFF, 0xFE, 0xB7, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 482 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xC4, 0xFF, 0x3A, 0xFF, 0x9D, 483 | 0xFF, 0x9C, 0xFF, 0x19, 0xF6, 0x13, 0xF4, 0xAA, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0x48, 484 | 0xFF, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xEC, 0xEB, 0xA4, 0xEB, 0xC5, 0xFF, 0x7C, 0xFF, 0xFF, 485 | 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xEC, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 486 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xFE, 0xD8, 0xFF, 0x19, 487 | 0xFF, 0x19, 0xFF, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0xF4, 0xAA, 0xEB, 0xA4, 0xEB, 0xA4, 488 | 0xF4, 0x47, 0xFF, 0x9D, 0xFF, 0xFF, 0xFF, 0xBE, 0xF4, 0x47, 0xEB, 0xA4, 0xF4, 0xEC, 0xFF, 0xFF, 489 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x19, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 490 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 491 | 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0x27, 0xF5, 0xD1, 0xFF, 0xBD, 0xFF, 0xFF, 0xF5, 0xD2, 0xEB, 0xA4, 492 | 0xEB, 0xA4, 0xF4, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xD8, 0xEB, 0xA4, 0xEB, 0xA4, 0xFE, 0xF9, 493 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xCB, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 494 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 495 | 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEC, 0x06, 0xFE, 0xB7, 0xFF, 0xFF, 0xFE, 0x34, 496 | 0xEB, 0xA4, 0xEB, 0xA4, 0xF6, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xEC, 0xEB, 0xA4, 0xF5, 0x0C, 497 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x55, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 498 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 499 | 0xF4, 0x27, 0xF5, 0x4E, 0xF5, 0x2D, 0xEB, 0xE5, 0xEB, 0xA4, 0xEB, 0xC4, 0xFE, 0x96, 0xFF, 0xFF, 500 | 0xF5, 0x6F, 0xEB, 0xA4, 0xEB, 0xE5, 0xFF, 0xBE, 0xFF, 0xFF, 0xFE, 0xF9, 0xEB, 0xA4, 0xEB, 0xC4, 501 | 0xFF, 0x9D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0xEB, 0xC5, 0xEB, 0xA4, 0xEB, 0xA4, 0x71, 0xC2, 502 | 0x92, 0x42, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xEB, 0xA4, 0xF4, 0xEC, 503 | 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9D, 0xEC, 0x48, 0xEB, 0x84, 0xEB, 0xC5, 0xFF, 0x5B, 504 | 0xFF, 0xDE, 0xEC, 0x07, 0xE3, 0x84, 0xF5, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0x28, 0xE3, 0x84, 505 | 0xF6, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xAB, 0xE3, 0x64, 0xE3, 0x64, 0x79, 0xE2, 506 | 0xAA, 0x64, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0xC5, 0xFF, 0xFF, 507 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x98, 0xB2, 0x84, 0xB2, 0x84, 0xC4, 0x0C, 508 | 0xFF, 0xFF, 0xDD, 0x93, 0xB2, 0x84, 0xBB, 0x69, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0x11, 0xB2, 0x84, 509 | 0xCC, 0x4D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x32, 0xB2, 0x84, 0xB2, 0x84, 0x92, 0x23, 510 | 0xAA, 0x64, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xC3, 0x8A, 0xFF, 0xFF, 511 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 512 | 0xF7, 0x3B, 0xFF, 0x9D, 0xB2, 0x85, 0xB2, 0x84, 0xF7, 0x5C, 0xEE, 0xFA, 0xD4, 0xD0, 0xB2, 0x84, 513 | 0xB2, 0xE6, 0xDD, 0x93, 0xCC, 0x6E, 0xBB, 0x68, 0xB2, 0x85, 0xB2, 0x84, 0xB2, 0x84, 0x92, 0x23, 514 | 0xAA, 0x64, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xBB, 0x07, 0xFF, 0xFF, 515 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0x5C, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 516 | 0xDD, 0x52, 0xEE, 0xD9, 0xBB, 0x07, 0xB2, 0x84, 0xB2, 0x85, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 517 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0x92, 0x23, 518 | 0xA2, 0x64, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xE5, 0xD5, 519 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xAF, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 520 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 521 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0x92, 0x23, 522 | 0x9A, 0x43, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0xA5, 523 | 0xD4, 0xF0, 0xEE, 0x99, 0xEE, 0x78, 0xCC, 0x4D, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 524 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 525 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0x79, 0xC3, 526 | 0x81, 0xE3, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 527 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 528 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 529 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0x59, 0x42, 530 | 0x79, 0xC3, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 531 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 532 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 533 | 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0xB2, 0x84, 0x59, 0x42, 534 | 0x51, 0x42, 0x79, 0xC3, 0x79, 0xC3, 0x9A, 0x23, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 535 | 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 536 | 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 537 | 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0xA2, 0x63, 0x92, 0x23, 0x79, 0xC3, 0x79, 0xC3, 0x38, 0xE1, 538 | }; 539 | -------------------------------------------------------------------------------- /examples/TFT_ArcFill_STM32/TFT_ArcFill_STM32.ino: -------------------------------------------------------------------------------- 1 | // Demo based on: 2 | // TFT_ArcFill by Bodmar 3 | // web: https://github.com/Bodmer/TFT_eSPI/tree/master/examples/320%20x%20240/TFT_ArcFill 4 | 5 | 6 | #include 7 | #include "STM32_TFT_8bit.h" 8 | 9 | STM32_TFT_8bit tft; 10 | 11 | 12 | #define DEG2RAD 0.0174532925 13 | 14 | #define LOOP_DELAY 10 // Loop delay to slow things down 15 | 16 | byte inc = 0; 17 | unsigned int col = 0; 18 | 19 | byte red = 31; // Red is the top 5 bits of a 16 bit colour value 20 | byte green = 0;// Green is the middle 6 bits 21 | byte blue = 0; // Blue is the bottom 5 bits 22 | byte state = 0; 23 | 24 | void setup(void) { 25 | Serial.begin(9600); 26 | uint32_t ID = tft.readID(); 27 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 28 | tft.begin(ID); 29 | 30 | tft.setRotation(1); 31 | 32 | tft.fillScreen(BLACK); 33 | 34 | } 35 | 36 | 37 | void loop() { 38 | 39 | // Continuous elliptical arc drawing 40 | fillArc(160, 120, inc * 6, 1, 140, 100, 10, rainbow(col)); 41 | 42 | // Continuous segmented (inc*2) elliptical arc drawing 43 | fillArc(160, 120, ((inc * 2) % 60) * 6, 1, 120, 80, 30, rainbow(col)); 44 | 45 | // Circle drawing using arc with arc width = radius 46 | fillArc(160, 120, inc * 6, 1, 42, 42, 42, rainbow(col)); 47 | 48 | inc++; 49 | col += 1; 50 | if (col > 191) col = 0; 51 | if (inc > 59) inc = 0; 52 | 53 | delay(LOOP_DELAY); 54 | } 55 | 56 | 57 | // ######################################################################### 58 | // Draw a circular or elliptical arc with a defined thickness 59 | // ######################################################################### 60 | 61 | // x,y == coords of centre of arc 62 | // start_angle = 0 - 359 63 | // seg_count = number of 6 degree segments to draw (60 => 360 degree arc) 64 | // rx = x axis outer radius 65 | // ry = y axis outer radius 66 | // w = width (thickness) of arc in pixels 67 | // colour = 16 bit colour value 68 | // Note if rx and ry are the same then an arc of a circle is drawn 69 | 70 | int fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w, unsigned int colour) 71 | { 72 | 73 | byte seg = 6; // Segments are 3 degrees wide = 120 segments for 360 degrees 74 | byte inc = 6; // Draw segments every 3 degrees, increase to 6 for segmented ring 75 | 76 | // Calculate first pair of coordinates for segment start 77 | float sx = cos((start_angle - 90) * DEG2RAD); 78 | float sy = sin((start_angle - 90) * DEG2RAD); 79 | uint16_t x0 = sx * (rx - w) + x; 80 | uint16_t y0 = sy * (ry - w) + y; 81 | uint16_t x1 = sx * rx + x; 82 | uint16_t y1 = sy * ry + y; 83 | 84 | // Draw colour blocks every inc degrees 85 | for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) { 86 | 87 | // Calculate pair of coordinates for segment end 88 | float sx2 = cos((i + seg - 90) * DEG2RAD); 89 | float sy2 = sin((i + seg - 90) * DEG2RAD); 90 | int x2 = sx2 * (rx - w) + x; 91 | int y2 = sy2 * (ry - w) + y; 92 | int x3 = sx2 * rx + x; 93 | int y3 = sy2 * ry + y; 94 | 95 | tft.fillTriangle(x0, y0, x1, y1, x2, y2, colour); 96 | tft.fillTriangle(x1, y1, x2, y2, x3, y3, colour); 97 | 98 | // Copy segment end to sgement start for next segment 99 | x0 = x2; 100 | y0 = y2; 101 | x1 = x3; 102 | y1 = y3; 103 | } 104 | } 105 | 106 | // ######################################################################### 107 | // Return the 16 bit colour with brightness 0-100% 108 | // ######################################################################### 109 | unsigned int brightness(unsigned int colour, int brightness) 110 | { 111 | byte red = colour >> 11; 112 | byte green = (colour & 0x7E0) >> 5; 113 | byte blue = colour & 0x1F; 114 | 115 | blue = (blue * brightness) / 100; 116 | green = (green * brightness) / 100; 117 | red = (red * brightness) / 100; 118 | 119 | return (red << 11) + (green << 5) + blue; 120 | } 121 | 122 | // ######################################################################### 123 | // Return a 16 bit rainbow colour 124 | // ######################################################################### 125 | unsigned int rainbow(byte value) 126 | { 127 | // Value is expected to be in range 0-127 128 | // The value is converted to a spectrum colour from 0 = blue through to 127 = red 129 | 130 | switch (state) { 131 | case 0: 132 | green ++; 133 | if (green == 64) { 134 | green = 63; 135 | state = 1; 136 | } 137 | break; 138 | case 1: 139 | red--; 140 | if (red == 255) { 141 | red = 0; 142 | state = 2; 143 | } 144 | break; 145 | case 2: 146 | blue ++; 147 | if (blue == 32) { 148 | blue = 31; 149 | state = 3; 150 | } 151 | break; 152 | case 3: 153 | green --; 154 | if (green == 255) { 155 | green = 0; 156 | state = 4; 157 | } 158 | break; 159 | case 4: 160 | red ++; 161 | if (red == 32) { 162 | red = 31; 163 | state = 5; 164 | } 165 | break; 166 | case 5: 167 | blue --; 168 | if (blue == 255) { 169 | blue = 0; 170 | state = 0; 171 | } 172 | break; 173 | } 174 | return red << 11 | green << 5 | blue; 175 | } 176 | 177 | -------------------------------------------------------------------------------- /examples/TFT_Meter_linear_STM32/TFT_Meter_linear_STM32.ino: -------------------------------------------------------------------------------- 1 | // Demo based on: 2 | // TFT_Meter_linear by Bodmar 3 | // web: https://github.com/Bodmer/TFT_eSPI/tree/master/examples/320%20x%20240/TFT_Meter_linear 4 | 5 | 6 | // Define meter size as 1 for tft.rotation(0) or 1.3333 for tft.rotation(1) 7 | #define M_SIZE 1.3333 8 | 9 | #include 10 | #include 11 | #include "STM32_TFT_8bit.h" 12 | 13 | STM32_TFT_8bit tft; 14 | 15 | #define TFT_GREY GRAY 16 | #define TFT_BLACK BLACK 17 | #define TFT_WHITE WHITE 18 | #define TFT_GREEN GREEN 19 | #define TFT_ORANGE ORANGE 20 | #define TFT_RED RED 21 | #define TFT_MAGENTA MAGENTA 22 | 23 | float ltx = 0; // Saved x coord of bottom of needle 24 | uint16_t osx = M_SIZE*120, osy = M_SIZE*120; // Saved x & y coords 25 | uint32_t updateTime = 0; // time for next update 26 | 27 | int old_analog = -999; // Value last displayed 28 | 29 | int value[6] = {0, 0, 0, 0, 0, 0}; 30 | int old_value[6] = { -1, -1, -1, -1, -1, -1}; 31 | int d = 0; 32 | 33 | void setup(void) { 34 | Serial.begin(9600); 35 | uint32_t ID = tft.readID(); 36 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 37 | tft.begin(ID); 38 | tft.setRotation(1); 39 | tft.fillScreen(TFT_BLACK); 40 | 41 | analogMeter(); // Draw analogue meter 42 | 43 | updateTime = millis(); // Next update time 44 | } 45 | 46 | 47 | void loop() { 48 | if (updateTime <= millis()) { 49 | updateTime = millis() + 35; // Update emter every 35 milliseconds 50 | 51 | // Create a Sine wave for testing 52 | d += 4; if (d >= 360) d = 0; 53 | value[0] = 50 + 50 * sin((d + 0) * 0.0174532925); 54 | 55 | plotNeedle(value[0], 0); // It takes between 2 and 12ms to replot the needle with zero delay 56 | } 57 | } 58 | 59 | 60 | // ######################################################################### 61 | // Draw the analogue meter on the screen 62 | // ######################################################################### 63 | void analogMeter() 64 | { 65 | 66 | // Meter outline 67 | tft.fillRect(0, 0, M_SIZE*239, M_SIZE*126, TFT_GREY); 68 | tft.fillRect(5, 3, M_SIZE*230, M_SIZE*119, TFT_WHITE); 69 | 70 | tft.setTextColor(TFT_BLACK); // Text colour 71 | 72 | // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing) 73 | for (int i = -50; i < 51; i += 5) { 74 | // Long scale tick length 75 | int tl = 15; 76 | 77 | // Coodinates of tick to draw 78 | float sx = cos((i - 90) * 0.0174532925); 79 | float sy = sin((i - 90) * 0.0174532925); 80 | uint16_t x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; 81 | uint16_t y0 = sy * (M_SIZE*100 + tl) + M_SIZE*140; 82 | uint16_t x1 = sx * M_SIZE*100 + M_SIZE*120; 83 | uint16_t y1 = sy * M_SIZE*100 + M_SIZE*140; 84 | 85 | // Coordinates of next tick for zone fill 86 | float sx2 = cos((i + 5 - 90) * 0.0174532925); 87 | float sy2 = sin((i + 5 - 90) * 0.0174532925); 88 | int x2 = sx2 * (M_SIZE*100 + tl) + M_SIZE*120; 89 | int y2 = sy2 * (M_SIZE*100 + tl) + M_SIZE*140; 90 | int x3 = sx2 * M_SIZE*100 + M_SIZE*120; 91 | int y3 = sy2 * M_SIZE*100 + M_SIZE*140; 92 | 93 | // Yellow zone limits 94 | //if (i >= -50 && i < 0) { 95 | // tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW); 96 | // tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW); 97 | //} 98 | 99 | // Green zone limits 100 | if (i >= 0 && i < 25) { 101 | tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN); 102 | tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN); 103 | } 104 | 105 | // Orange zone limits 106 | if (i >= 25 && i < 50) { 107 | tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE); 108 | tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE); 109 | } 110 | 111 | // Short scale tick length 112 | if (i % 25 != 0) tl = 8; 113 | 114 | // Recalculate coords incase tick lenght changed 115 | x0 = sx * (M_SIZE*100 + tl) + M_SIZE*120; 116 | y0 = sy * (M_SIZE*100 + tl) + M_SIZE*140; 117 | x1 = sx * M_SIZE*100 + M_SIZE*120; 118 | y1 = sy * M_SIZE*100 + M_SIZE*140; 119 | 120 | // Draw tick 121 | tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 122 | 123 | // Check if labels should be drawn, with position tweaks 124 | if (i % 25 == 0) { 125 | // Calculate label positions 126 | x0 = sx * (M_SIZE*100 + tl + 10) + M_SIZE*120; 127 | y0 = sy * (M_SIZE*100 + tl + 10) + M_SIZE*140; 128 | switch (i / 25) { 129 | #if 0 130 | case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break; 131 | case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break; 132 | case 0: tft.drawCentreString("50", x0, y0 - 7, 2); break; 133 | case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break; 134 | case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break; 135 | #endif 136 | case -2: _drawString("0", x0-10, y0 - 12, 2); break; 137 | case -1: _drawString("25", x0-10, y0 - 9, 2); break; 138 | case 0: _drawString("50", x0-10, y0 - 7, 2); break; 139 | case 1: _drawString("75", x0-10, y0 - 9, 2); break; 140 | case 2: _drawString("100", x0-10, y0 - 12, 2); break; 141 | } 142 | } 143 | 144 | // Now draw the arc of the scale 145 | sx = cos((i + 5 - 90) * 0.0174532925); 146 | sy = sin((i + 5 - 90) * 0.0174532925); 147 | x0 = sx * M_SIZE*100 + M_SIZE*120; 148 | y0 = sy * M_SIZE*100 + M_SIZE*140; 149 | // Draw scale arc, don't draw the last part 150 | if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 151 | } 152 | 153 | _drawString("%RH", M_SIZE*(5 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right 154 | //tft.drawString("%RH", M_SIZE*(5 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right 155 | 156 | //tft.drawCentreString("%RH", M_SIZE*120, M_SIZE*70, 4); // Comment out to avoid font 4 157 | 158 | tft.drawRect(5, 3, M_SIZE*230, M_SIZE*119, TFT_BLACK); // Draw bezel line 159 | plotNeedle(0, 0); // Put meter needle at 0 160 | } 161 | 162 | // ######################################################################### 163 | // Update needle position 164 | // This function is blocking while needle moves, time depends on ms_delay 165 | // 10ms minimises needle flicker if text is drawn within needle sweep area 166 | // Smaller values OK if text not in sweep area, zero for instant movement but 167 | // does not look realistic... (note: 100 increments for full scale deflection) 168 | // ######################################################################### 169 | void plotNeedle(int value, byte ms_delay) 170 | { 171 | tft.setTextColor(TFT_BLACK, TFT_WHITE); 172 | char buf[8]; dtostrf(value, 4, 0, buf); 173 | _drawString("%RH", M_SIZE*(5 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right 174 | //tft.drawString("%RH", M_SIZE*(5 + 230 - 40), M_SIZE*(119 - 20), 2); // Units at bottom right 175 | _drawString(buf, M_SIZE*40-40, M_SIZE*(119 - 20), 2); 176 | //tft.drawRightString(buf, M_SIZE*40, M_SIZE*(119 - 20), 2); 177 | 178 | if (value < -10) value = -10; // Limit value to emulate needle end stops 179 | if (value > 110) value = 110; 180 | 181 | // Move the needle until new value reached 182 | while (!(value == old_analog)) { 183 | if (old_analog < value) old_analog++; 184 | else old_analog--; 185 | 186 | if (ms_delay == 0) old_analog = value; // Update immediately if delay is 0 187 | 188 | float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 189 | // Calcualte tip of needle coords 190 | float sx = cos(sdeg * 0.0174532925); 191 | float sy = sin(sdeg * 0.0174532925); 192 | 193 | // Calculate x delta of needle start (does not start at pivot point) 194 | float tx = tan((sdeg + 90) * 0.0174532925); 195 | 196 | // Erase old needle image 197 | tft.drawLine(M_SIZE*(120 + 20 * ltx - 1), M_SIZE*(140 - 20), osx - 1, osy, TFT_WHITE); 198 | tft.drawLine(M_SIZE*(120 + 20 * ltx), M_SIZE*(140 - 20), osx, osy, TFT_WHITE); 199 | tft.drawLine(M_SIZE*(120 + 20 * ltx + 1), M_SIZE*(140 - 20), osx + 1, osy, TFT_WHITE); 200 | 201 | // Re-plot text under needle 202 | tft.setTextColor(TFT_BLACK); 203 | tft.setFont(&FreeMonoBold24pt7b); 204 | _drawString("%RH", M_SIZE*80, M_SIZE*100, 1); // // Comment out to avoid font 4 205 | tft.setFont(); 206 | //tft.drawCentreString("%RH", M_SIZE*120, M_SIZE*70, 4); // // Comment out to avoid font 4 207 | 208 | // Store new needle end coords for next erase 209 | ltx = tx; 210 | osx = M_SIZE*(sx * 98 + 120); 211 | osy = M_SIZE*(sy * 98 + 140); 212 | 213 | // Draw the needle in the new postion, magenta makes needle a bit bolder 214 | // draws 3 lines to thicken needle 215 | tft.drawLine(M_SIZE*(120 + 20 * ltx - 1), M_SIZE*(140 - 20), osx - 1, osy, TFT_RED); 216 | tft.drawLine(M_SIZE*(120 + 20 * ltx), M_SIZE*(140 - 20), osx, osy, TFT_MAGENTA); 217 | tft.drawLine(M_SIZE*(120 + 20 * ltx + 1), M_SIZE*(140 - 20), osx + 1, osy, TFT_RED); 218 | 219 | // Slow needle down slightly as it approaches new postion 220 | if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5; 221 | 222 | // Wait before next update 223 | delay(ms_delay); 224 | } 225 | } 226 | 227 | void _drawString(char *buf, int16_t x, int16_t y, int16_t size) 228 | { 229 | tft.setTextSize(size); 230 | tft.setCursor(x, y); 231 | tft.print(buf); 232 | } 233 | -------------------------------------------------------------------------------- /examples/TFT_Meters_STM32/TFT_Meters_STM32.ino: -------------------------------------------------------------------------------- 1 | // Demo based on: 2 | // TFT_Meters by Bodmar 3 | // web: https://github.com/Bodmer/TFT_eSPI/tree/master/examples/320%20x%20240/TFT_Meters 4 | 5 | 6 | 7 | #include 8 | #include 9 | #include "STM32_TFT_8bit.h" 10 | 11 | STM32_TFT_8bit tft; 12 | 13 | #define TFT_GREY GRAY 14 | #define TFT_BLACK BLACK 15 | #define TFT_WHITE WHITE 16 | #define TFT_GREEN GREEN 17 | #define TFT_ORANGE ORANGE 18 | #define TFT_RED RED 19 | #define TFT_CYAN CYAN 20 | #define TFT_MAGENTA MAGENTA 21 | 22 | #define LOOP_PERIOD 35 // Display updates every 35 ms 23 | 24 | float ltx = 0; // Saved x coord of bottom of needle 25 | uint16_t osx = 120, osy = 120; // Saved x & y coords 26 | uint32_t updateTime = 0; // time for next update 27 | int16_t LinearY = 150; 28 | 29 | int old_analog = -999; // Value last displayed 30 | int old_digital = -999; // Value last displayed 31 | 32 | int value[6] = {0, 0, 0, 0, 0, 0}; 33 | int old_value[6] = { -1, -1, -1, -1, -1, -1}; 34 | int d = 0; 35 | 36 | void setup(void) { 37 | Serial.begin(9600); 38 | uint32_t ID = tft.readID(); 39 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 40 | tft.begin(ID); 41 | tft.setRotation(0); 42 | Serial.begin(57600); // For debug 43 | tft.fillScreen(TFT_BLACK); 44 | 45 | analogMeter(); // Draw analogue meter 46 | 47 | // Draw 6 linear meters 48 | byte d = 40; 49 | plotLinear("A0", 0, LinearY); 50 | plotLinear("A1", 1 * d, LinearY); 51 | plotLinear("A2", 2 * d, LinearY); 52 | plotLinear("A3", 3 * d, LinearY); 53 | plotLinear("A4", 4 * d, LinearY); 54 | plotLinear("A5", 5 * d, LinearY); 55 | 56 | updateTime = millis(); // Next update time 57 | } 58 | 59 | 60 | void loop() { 61 | if (updateTime <= millis()) { 62 | updateTime = millis() + LOOP_PERIOD; 63 | 64 | d += 4; if (d >= 360) d = 0; 65 | 66 | //value[0] = map(analogRead(A0), 0, 1023, 0, 100); // Test with value form Analogue 0 67 | 68 | // Create a Sine wave for testing 69 | value[0] = 50 + 50 * sin((d + 0) * 0.0174532925); 70 | value[1] = 50 + 50 * sin((d + 60) * 0.0174532925); 71 | value[2] = 50 + 50 * sin((d + 120) * 0.0174532925); 72 | value[3] = 50 + 50 * sin((d + 180) * 0.0174532925); 73 | value[4] = 50 + 50 * sin((d + 240) * 0.0174532925); 74 | value[5] = 50 + 50 * sin((d + 300) * 0.0174532925); 75 | 76 | //unsigned long t = millis(); 77 | 78 | plotPointer(LinearY); 79 | 80 | plotNeedle(value[0], 0); 81 | 82 | //Serial.println(millis()-t); // Print time taken for meter update 83 | } 84 | } 85 | 86 | 87 | // ######################################################################### 88 | // Draw the analogue meter on the screen 89 | // ######################################################################### 90 | void analogMeter() 91 | { 92 | // Meter outline 93 | tft.fillRect(0, 0, 239, 126, TFT_GREY); 94 | tft.fillRect(5, 3, 230, 119, TFT_WHITE); 95 | 96 | tft.setTextColor(TFT_BLACK); // Text colour 97 | 98 | // Draw ticks every 5 degrees from -50 to +50 degrees (100 deg. FSD swing) 99 | for (int i = -50; i < 51; i += 5) { 100 | // Long scale tick length 101 | int tl = 15; 102 | 103 | // Coodinates of tick to draw 104 | float sx = cos((i - 90) * 0.0174532925); 105 | float sy = sin((i - 90) * 0.0174532925); 106 | uint16_t x0 = sx * (100 + tl) + 120; 107 | uint16_t y0 = sy * (100 + tl) + 140; 108 | uint16_t x1 = sx * 100 + 120; 109 | uint16_t y1 = sy * 100 + 140; 110 | 111 | // Coordinates of next tick for zone fill 112 | float sx2 = cos((i + 5 - 90) * 0.0174532925); 113 | float sy2 = sin((i + 5 - 90) * 0.0174532925); 114 | int x2 = sx2 * (100 + tl) + 120; 115 | int y2 = sy2 * (100 + tl) + 140; 116 | int x3 = sx2 * 100 + 120; 117 | int y3 = sy2 * 100 + 140; 118 | 119 | // Yellow zone limits 120 | //if (i >= -50 && i < 0) { 121 | // tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_YELLOW); 122 | // tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_YELLOW); 123 | //} 124 | 125 | // Green zone limits 126 | if (i >= 0 && i < 25) { 127 | tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_GREEN); 128 | tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_GREEN); 129 | } 130 | 131 | // Orange zone limits 132 | if (i >= 25 && i < 50) { 133 | tft.fillTriangle(x0, y0, x1, y1, x2, y2, TFT_ORANGE); 134 | tft.fillTriangle(x1, y1, x2, y2, x3, y3, TFT_ORANGE); 135 | } 136 | 137 | // Short scale tick length 138 | if (i % 25 != 0) tl = 8; 139 | 140 | // Recalculate coords incase tick lenght changed 141 | x0 = sx * (100 + tl) + 120; 142 | y0 = sy * (100 + tl) + 140; 143 | x1 = sx * 100 + 120; 144 | y1 = sy * 100 + 140; 145 | 146 | // Draw tick 147 | tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 148 | 149 | // Check if labels should be drawn, with position tweaks 150 | if (i % 25 == 0) { 151 | // Calculate label positions 152 | x0 = sx * (100 + tl + 10) + 120; 153 | y0 = sy * (100 + tl + 10) + 140; 154 | switch (i / 25) { 155 | #if 0 156 | case -2: tft.drawCentreString("0", x0, y0 - 12, 2); break; 157 | case -1: tft.drawCentreString("25", x0, y0 - 9, 2); break; 158 | case 0: tft.drawCentreString("50", x0, y0 - 6, 2); break; 159 | case 1: tft.drawCentreString("75", x0, y0 - 9, 2); break; 160 | case 2: tft.drawCentreString("100", x0, y0 - 12, 2); break; 161 | #endif 162 | case -2: _drawString("0", x0-10, y0 - 12, 2); break; 163 | case -1: _drawString("25", x0-10, y0 - 9, 2); break; 164 | case 0: _drawString("50", x0-10, y0 - 6, 2); break; 165 | case 1: _drawString("75", x0-10, y0 - 9, 2); break; 166 | case 2: _drawString("100", x0-15, y0 - 12, 2); break; 167 | } 168 | } 169 | 170 | // Now draw the arc of the scale 171 | sx = cos((i + 5 - 90) * 0.0174532925); 172 | sy = sin((i + 5 - 90) * 0.0174532925); 173 | x0 = sx * 100 + 120; 174 | y0 = sy * 100 + 140; 175 | // Draw scale arc, don't draw the last part 176 | if (i < 50) tft.drawLine(x0, y0, x1, y1, TFT_BLACK); 177 | } 178 | 179 | _drawString("%RH", 5 + 230 - 40, 119 - 20, 2); // Units at bottom right 180 | //tft.drawString("%RH", 5 + 230 - 40, 119 - 20, 2); // Units at bottom right 181 | //tft.drawCentreString("%RH", 120, 70, 4); // Comment out to avoid font 4 182 | tft.drawRect(5, 3, 230, 119, TFT_BLACK); // Draw bezel line 183 | 184 | plotNeedle(0, 0); // Put meter needle at 0 185 | } 186 | 187 | // ######################################################################### 188 | // Update needle position 189 | // This function is blocking while needle moves, time depends on ms_delay 190 | // 10ms minimises needle flicker if text is drawn within needle sweep area 191 | // Smaller values OK if text not in sweep area, zero for instant movement but 192 | // does not look realistic... (note: 100 increments for full scale deflection) 193 | // ######################################################################### 194 | void plotNeedle(int value, byte ms_delay) 195 | { 196 | tft.setTextColor(TFT_BLACK, TFT_WHITE); 197 | char buf[8]; dtostrf(value, 3, 0, buf); 198 | _drawString(buf, 10, 119 - 20, 2); 199 | //tft.drawRightString(buf, 40, 119 - 20, 2); 200 | 201 | if (value < -10) value = -10; // Limit value to emulate needle end stops 202 | if (value > 110) value = 110; 203 | 204 | // Move the needle util new value reached 205 | while (!(value == old_analog)) { 206 | if (old_analog < value) old_analog++; 207 | else old_analog--; 208 | 209 | if (ms_delay == 0) old_analog = value; // Update immediately id delay is 0 210 | 211 | float sdeg = map(old_analog, -10, 110, -150, -30); // Map value to angle 212 | // Calcualte tip of needle coords 213 | float sx = cos(sdeg * 0.0174532925); 214 | float sy = sin(sdeg * 0.0174532925); 215 | 216 | // Calculate x delta of needle start (does not start at pivot point) 217 | float tx = tan((sdeg + 90) * 0.0174532925); 218 | 219 | // Erase old needle image 220 | tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, TFT_WHITE); 221 | tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, TFT_WHITE); 222 | tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, TFT_WHITE); 223 | 224 | // Re-plot text under needle 225 | tft.setTextColor(TFT_BLACK); 226 | tft.setFont(&FreeMonoBold18pt7b); 227 | _drawString("%RH", 80, 100, 1); // // Comment out to avoid font 4 228 | tft.setFont(); 229 | //tft.drawCentreString("%RH", 120, 70, 4); // // Comment out to avoid font 4 230 | 231 | // Store new needle end coords for next erase 232 | ltx = tx; 233 | osx = sx * 98 + 120; 234 | osy = sy * 98 + 140; 235 | 236 | // Draw the needle in the new postion, magenta makes needle a bit bolder 237 | // draws 3 lines to thicken needle 238 | tft.drawLine(120 + 20 * ltx - 1, 140 - 20, osx - 1, osy, TFT_RED); 239 | tft.drawLine(120 + 20 * ltx, 140 - 20, osx, osy, TFT_MAGENTA); 240 | tft.drawLine(120 + 20 * ltx + 1, 140 - 20, osx + 1, osy, TFT_RED); 241 | 242 | // Slow needle down slightly as it approaches new postion 243 | if (abs(old_analog - value) < 10) ms_delay += ms_delay / 5; 244 | 245 | // Wait before next update 246 | delay(ms_delay); 247 | } 248 | } 249 | 250 | // ######################################################################### 251 | // Draw a linear meter on the screen 252 | // ######################################################################### 253 | void plotLinear(char *label, int x, int y) 254 | { 255 | int w = 36; 256 | tft.drawRect(x, y, w, 155, TFT_GREY); 257 | tft.fillRect(x + 2, y + 19, w - 3, 155 - 38, TFT_WHITE); 258 | tft.setTextColor(TFT_CYAN, TFT_BLACK); 259 | _drawString(label, (x + w / 2) - 10, y + 2, 2); 260 | //tft.drawCentreString(label, x + w / 2, y + 2, 2); 261 | 262 | for (int i = 0; i < 110; i += 10) 263 | { 264 | tft.drawFastHLine(x + 20, y + 27 + i, 6, TFT_BLACK); 265 | } 266 | 267 | for (int i = 0; i < 110; i += 50) 268 | { 269 | tft.drawFastHLine(x + 20, y + 27 + i, 9, TFT_BLACK); 270 | } 271 | 272 | tft.fillTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 - 5, TFT_RED); 273 | tft.fillTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 + 5, TFT_RED); 274 | 275 | //_drawString("---", (x + w / 2) - 18, y + 155 - 18, 2); 276 | //tft.drawCentreString("---", x + w / 2, y + 155 - 18, 2); 277 | } 278 | 279 | // ######################################################################### 280 | // Adjust 6 linear meter pointer positions 281 | // ######################################################################### 282 | void plotPointer(int y) 283 | { 284 | // int dy0 = 187; 285 | int dy0 = y + 27; 286 | byte pw = 16; 287 | 288 | tft.setTextColor(TFT_GREEN, TFT_BLACK); 289 | 290 | // Move the 6 pointers one pixel towards new value 291 | for (int i = 0; i < 6; i++) 292 | { 293 | char buf[8]; dtostrf(value[i], 3, 0, buf); 294 | // _drawString(buf, (i * 40 + 36 - 5) - 50, 187 - 27 + 155 - 18, 2); 295 | _drawString(buf, (i * 40 + 36 - 5) - 35, y + 137, 2); 296 | //tft.drawRightString(buf, i * 40 + 36 - 5, 187 - 27 + 155 - 18, 2); 297 | 298 | int dx = 3 + 40 * i; 299 | if (value[i] < 0) value[i] = 0; // Limit value to emulate needle end stops 300 | if (value[i] > 100) value[i] = 100; 301 | 302 | int dy; 303 | while (!(value[i] == old_value[i])) { 304 | //dy = 187 + 100 - old_value[i]; 305 | dy = dy0 + 100 - old_value[i]; 306 | if (old_value[i] > value[i]) 307 | { 308 | tft.drawLine(dx, dy - 5, dx + pw, dy, TFT_WHITE); 309 | old_value[i]--; 310 | tft.drawLine(dx, dy + 6, dx + pw, dy + 1, TFT_RED); 311 | } 312 | else 313 | { 314 | tft.drawLine(dx, dy + 5, dx + pw, dy, TFT_WHITE); 315 | old_value[i]++; 316 | tft.drawLine(dx, dy - 6, dx + pw, dy - 1, TFT_RED); 317 | } 318 | } 319 | } 320 | } 321 | 322 | void _drawString(char *buf, int16_t x, int16_t y, int16_t size) 323 | { 324 | tft.setTextSize(size); 325 | tft.setCursor(x, y); 326 | tft.print(buf); 327 | } 328 | -------------------------------------------------------------------------------- /examples/TFT_Pong_STM32/TFT_Pong_STM32.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Pong 3 | * Original Code from https://github.com/rparrett/pongclock 4 | * 5 | * Demo based on: 6 | * TFT_Pong by Bodmar 7 | * web: https://github.com/Bodmer/TFT_eSPI/tree/master/examples/320%20x%20240/TFT_Pong 8 | */ 9 | 10 | // Demo only - not playable 11 | 12 | #include 13 | #include "STM32_TFT_8bit.h" 14 | 15 | STM32_TFT_8bit tft; 16 | 17 | int16_t h = 240; 18 | int16_t w = 320; 19 | 20 | int dly = 5; 21 | 22 | int16_t paddle_h = 30; 23 | int16_t paddle_w = 4; 24 | 25 | int16_t lpaddle_x = 0; 26 | int16_t rpaddle_x = w - paddle_w; 27 | 28 | int16_t lpaddle_y = 0; 29 | int16_t rpaddle_y = h - paddle_h; 30 | 31 | int16_t lpaddle_d = 1; 32 | int16_t rpaddle_d = -1; 33 | 34 | int16_t lpaddle_ball_t = w - w / 4; 35 | int16_t rpaddle_ball_t = w / 4; 36 | 37 | int16_t target_y = 0; 38 | 39 | int16_t ball_x = 2; 40 | int16_t ball_y = 2; 41 | int16_t oldball_x = 2; 42 | int16_t oldball_y = 2; 43 | 44 | int16_t ball_dx = 1; 45 | int16_t ball_dy = 1; 46 | 47 | int16_t ball_w = 6; 48 | int16_t ball_h = 6; 49 | 50 | int16_t dashline_h = 4; 51 | int16_t dashline_w = 2; 52 | int16_t dashline_n = h / dashline_h; 53 | int16_t dashline_x = w / 2 - 1; 54 | int16_t dashline_y = dashline_h / 2; 55 | 56 | int16_t lscore = 12; 57 | int16_t rscore = 4; 58 | 59 | void setup(void) { 60 | 61 | //randomSeed(analogRead(0)*analogRead(1)); 62 | 63 | Serial.begin(9600); 64 | uint32_t ID = tft.readID(); 65 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 66 | tft.begin(ID); 67 | 68 | tft.setRotation(1); 69 | 70 | tft.fillScreen(BLACK); 71 | //tft.fillScreen(GREY); 72 | 73 | initgame(); 74 | 75 | tft.setTextColor(WHITE, BLACK); 76 | 77 | } 78 | 79 | void loop() { 80 | delay(dly); 81 | 82 | lpaddle(); 83 | rpaddle(); 84 | 85 | midline(); 86 | 87 | ball(); 88 | } 89 | 90 | void initgame() { 91 | lpaddle_y = random(0, h - paddle_h); 92 | rpaddle_y = random(0, h - paddle_h); 93 | 94 | // ball is placed on the center of the left paddle 95 | ball_y = lpaddle_y + (paddle_h / 2); 96 | 97 | calc_target_y(); 98 | 99 | midline(); 100 | 101 | tft.fillRect(0,h-26,w,239,GRAY); 102 | //tft.setTextDatum(TC_DATUM); 103 | tft.setTextColor(WHITE,GRAY); 104 | _drawString("STM32 example", 05, h-26 , 4); 105 | //tft.drawString("TFT_eSPI example", w/2, h-26 , 4); 106 | } 107 | 108 | void midline() { 109 | 110 | // If the ball is not on the line then don't redraw the line 111 | if ((ball_x dashline_x+dashline_w)) return; 112 | 113 | // Quick way to draw a dashed line 114 | for(int16_t i = 0; i < w; i+=10) { 115 | tft.drawFastVLine(dashline_x,i,5,WHITE); 116 | } 117 | //tft.setWindow(dashline_x,0,dashline_x+dashline_w-1,h); 118 | 119 | for(int16_t i = 0; i < dashline_n; i+=2) { 120 | //tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels 121 | //tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels 122 | } 123 | } 124 | 125 | void lpaddle() { 126 | 127 | if (lpaddle_d == 1) { 128 | tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, 1, BLACK); 129 | } 130 | else if (lpaddle_d == -1) { 131 | tft.fillRect(lpaddle_x, lpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); 132 | } 133 | 134 | lpaddle_y = lpaddle_y + lpaddle_d; 135 | 136 | if (ball_dx == 1) lpaddle_d = 0; 137 | else { 138 | if (lpaddle_y + paddle_h / 2 == target_y) lpaddle_d = 0; 139 | else if (lpaddle_y + paddle_h / 2 > target_y) lpaddle_d = -1; 140 | else lpaddle_d = 1; 141 | } 142 | 143 | if (lpaddle_y + paddle_h >= h && lpaddle_d == 1) lpaddle_d = 0; 144 | else if (lpaddle_y <= 0 && lpaddle_d == -1) lpaddle_d = 0; 145 | 146 | tft.fillRect(lpaddle_x, lpaddle_y, paddle_w, paddle_h, CYAN); 147 | } 148 | 149 | void rpaddle() { 150 | 151 | if (rpaddle_d == 1) { 152 | tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, 1, BLACK); 153 | } 154 | else if (rpaddle_d == -1) { 155 | tft.fillRect(rpaddle_x, rpaddle_y + paddle_h - 1, paddle_w, 1, BLACK); 156 | } 157 | 158 | rpaddle_y = rpaddle_y + rpaddle_d; 159 | 160 | if (ball_dx == -1) rpaddle_d = 0; 161 | else { 162 | if (rpaddle_y + paddle_h / 2 == target_y) rpaddle_d = 0; 163 | else if (rpaddle_y + paddle_h / 2 > target_y) rpaddle_d = -1; 164 | else rpaddle_d = 1; 165 | } 166 | 167 | if (rpaddle_y + paddle_h >= h && rpaddle_d == 1) rpaddle_d = 0; 168 | else if (rpaddle_y <= 0 && rpaddle_d == -1) rpaddle_d = 0; 169 | 170 | tft.fillRect(rpaddle_x, rpaddle_y, paddle_w, paddle_h, YELLOW); 171 | } 172 | 173 | void calc_target_y() { 174 | int16_t target_x; 175 | int16_t reflections; 176 | int16_t y; 177 | 178 | if (ball_dx == 1) { 179 | target_x = w - ball_w; 180 | } 181 | else { 182 | target_x = -1 * (w - ball_w); 183 | } 184 | 185 | y = abs(target_x * (ball_dy / ball_dx) + ball_y); 186 | 187 | reflections = floor(y / h); 188 | 189 | if (reflections % 2 == 0) { 190 | target_y = y % h; 191 | } 192 | else { 193 | target_y = h - (y % h); 194 | } 195 | } 196 | 197 | void ball() { 198 | ball_x = ball_x + ball_dx; 199 | ball_y = ball_y + ball_dy; 200 | 201 | if (ball_dx == -1 && ball_x == paddle_w && ball_y + ball_h >= lpaddle_y && ball_y <= lpaddle_y + paddle_h) { 202 | ball_dx = ball_dx * -1; 203 | dly = random(5); // change speed of ball after paddle contact 204 | calc_target_y(); 205 | } else if (ball_dx == 1 && ball_x + ball_w == w - paddle_w && ball_y + ball_h >= rpaddle_y && ball_y <= rpaddle_y + paddle_h) { 206 | ball_dx = ball_dx * -1; 207 | dly = random(5); // change speed of ball after paddle contact 208 | calc_target_y(); 209 | } else if ((ball_dx == 1 && ball_x >= w) || (ball_dx == -1 && ball_x + ball_w < 0)) { 210 | dly = 5; 211 | } 212 | 213 | if (ball_y > h - ball_w || ball_y < 0) { 214 | ball_dy = ball_dy * -1; 215 | ball_y += ball_dy; // Keep in bounds 216 | } 217 | 218 | //tft.fillRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); 219 | tft.drawRect(oldball_x, oldball_y, ball_w, ball_h, BLACK); // Less TFT refresh aliasing than line above for large balls 220 | tft.fillRect( ball_x, ball_y, ball_w, ball_h, RED); 221 | oldball_x = ball_x; 222 | oldball_y = ball_y; 223 | } 224 | 225 | void _drawString(char *buf, int16_t x, int16_t y, int16_t size) 226 | { 227 | tft.setTextSize(size); 228 | tft.setCursor(x, y); 229 | tft.print(buf); 230 | } 231 | -------------------------------------------------------------------------------- /examples/UTFT_demo_STM32/UTFT_demo_STM32.ino: -------------------------------------------------------------------------------- 1 | // Demo based on: 2 | // UTFT_Demo_320x240 by Henning Karlsen 3 | // web: http://www.henningkarlsen.com/electronics 4 | // 5 | 6 | #include 7 | #include "STM32_TFT_8bit.h" 8 | 9 | STM32_TFT_8bit myGLCD; 10 | 11 | 12 | #define TFT_GREY GRAY 13 | #define TFT_BLACK BLACK 14 | #define TFT_RED RED 15 | #define TFT_CYAN CYAN 16 | #define TFT_YELLOW YELLOW 17 | #define TFT_BLUE BLUE 18 | 19 | int sbuf[318]; 20 | int cbuf[318]; 21 | 22 | void setup() 23 | { 24 | Serial.begin(9600); 25 | uint32_t ID = myGLCD.readID(); 26 | Serial.print("Device ID: 0x"); Serial.println(ID, HEX); 27 | myGLCD.begin(ID); 28 | 29 | uint32_t width = myGLCD.width(); 30 | Serial.print("Width: "); Serial.println(width); 31 | uint32_t height = myGLCD.height(); 32 | Serial.print("Height: "); Serial.println(height); 33 | 34 | int buf[318]; 35 | 36 | // Clear the screen and draw the frame 37 | myGLCD.setRotation(3); 38 | myGLCD.setFont(); 39 | myGLCD.setTextSize(1); 40 | 41 | myGLCD.fillScreen(TFT_BLACK); 42 | myGLCD.fillRect(0, 0, 319, 14,TFT_RED); 43 | myGLCD.fillRect(0, 226, 319, 14,TFT_GREY); 44 | 45 | myGLCD.setTextColor(TFT_BLACK,TFT_RED); 46 | myGLCD.setCursor(100, 4); 47 | myGLCD.print("* STM32_TFT_8bit *"); 48 | myGLCD.setTextColor(TFT_YELLOW,TFT_GREY); 49 | myGLCD.setCursor(100, 230); 50 | myGLCD.print("Adapted by nopnop2002"); 51 | 52 | myGLCD.drawRect(0, 14, 319, 211, TFT_BLUE); 53 | 54 | // Draw crosshairs 55 | myGLCD.drawLine(159, 15, 159, 224,TFT_BLUE); 56 | myGLCD.drawLine(1, 119, 318, 119,TFT_BLUE); 57 | for (int i=9; i<310; i+=10) 58 | myGLCD.drawLine(i, 117, i, 121,TFT_BLUE); 59 | for (int i=19; i<220; i+=10) 60 | myGLCD.drawLine(157, i, 161, i,TFT_BLUE); 61 | 62 | // Draw sin-lines, cos-lines 63 | myGLCD.setTextColor(TFT_CYAN); 64 | _drawString("Sin", 5, 15,2); 65 | for (int i=1; i<318; i=i+2) 66 | { 67 | sbuf[i-1] = 119+(sin(((i*1.13)*3.14)/180)*95); 68 | myGLCD.drawPixel(i,sbuf[i-1],TFT_CYAN); 69 | } 70 | myGLCD.setTextColor(TFT_RED); 71 | _drawString("Cos", 5, 30,2); 72 | for (int i=1; i<318; i=i+2) 73 | { 74 | cbuf[i-1] = 119+(cos(((i*1.13)*3.14)/180)*95); 75 | myGLCD.drawPixel(i,cbuf[i-1],TFT_YELLOW); 76 | } 77 | 78 | } 79 | 80 | void loop() 81 | { 82 | static int delta = 0; 83 | 84 | // Erase sin-lines, cos-lines 85 | for (int i=1; i<318; i=i+2) 86 | { 87 | myGLCD.drawPixel(i,sbuf[i-1],TFT_BLACK); 88 | } 89 | for (int i=1; i<318; i=i+2) 90 | { 91 | myGLCD.drawPixel(i,cbuf[i-1],TFT_BLACK); 92 | } 93 | 94 | // Draw sin-lines, cos-lines 95 | delta++; 96 | if (delta == 318) delta = 0; 97 | for (int i=1; i<318; i=i+2) 98 | { 99 | sbuf[i-1] = 119+(sin((((i+delta)*1.13)*3.14)/180)*95); 100 | myGLCD.drawPixel(i,sbuf[i-1],TFT_CYAN); 101 | } 102 | for (int i=1; i<318; i=i+2) 103 | { 104 | cbuf[i-1] = 119+(cos((((i+delta)*1.13)*3.14)/180)*95); 105 | myGLCD.drawPixel(i,cbuf[i-1],TFT_YELLOW); 106 | } 107 | 108 | myGLCD.setTextColor(TFT_CYAN); 109 | // myGLCD.drawString("Sin", 5, 15,2); 110 | _drawString("Sin", 5, 15,2); 111 | myGLCD.setTextColor(TFT_YELLOW); 112 | // myGLCD.drawString("Cos", 5, 30,2); 113 | _drawString("Cos", 5, 30,2); 114 | myGLCD.drawLine(159, 15, 159, 224,TFT_BLUE); 115 | myGLCD.drawLine(1, 119, 318, 119,TFT_BLUE); 116 | } 117 | 118 | void _drawString(char *buf, int16_t x, int16_t y, int16_t size) 119 | { 120 | myGLCD.setTextSize(size); 121 | myGLCD.setCursor(x, y); 122 | myGLCD.print(buf); 123 | } 124 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=STM32_TFT_8bit 2 | version=1.3.0 3 | author=David Prentice :: Ported to Arduino_STM32 by nopnop2002 4 | maintainer=David Prentice and nopnop2002 (for porting to Arduino_STM32) 5 | sentence=TFT Library for 2.4, 2.8, 3.5, 3.6, 3.95 inch mcufriend UNO Shields 6 | paragraph=TFT Library for 2.4, 2.8, 3.5, 3.6, 3.95 inch mcufriend UNO Shields. Must have /RD pin to be readable. 7 | category=Display 8 | url=https://github.com/nopnop2002/STM32_TFT_8bit 9 | architectures=stm32 10 | --------------------------------------------------------------------------------