diff --git a/Extensions/Button.cpp b/Extensions/Button.cpp new file mode 100644 index 0000000..88a8bc0 --- /dev/null +++ b/Extensions/Button.cpp @@ -0,0 +1,76 @@ +/*************************************************************************************** +** Code for the GFX button UI element +** Grabbed from Adafruit_GFX library and enhanced to handle any label font +***************************************************************************************/ +TFT_eSPI_Button::TFT_eSPI_Button(void) { + _gfx = 0; +} + +// Classic initButton() function: pass center & size +void TFT_eSPI_Button::initButton( + TFT_eSPI *gfx, int16_t x, int16_t y, uint16_t w, uint16_t h, + uint16_t outline, uint16_t fill, uint16_t textcolor, + char *label, uint8_t textsize) +{ + // Tweak arguments and pass to the newer initButtonUL() function... + initButtonUL(gfx, x - (w / 2), y - (h / 2), w, h, outline, fill, + textcolor, label, textsize); +} + +// Newer function instead accepts upper-left corner & size +void TFT_eSPI_Button::initButtonUL( + TFT_eSPI *gfx, int16_t x1, int16_t y1, uint16_t w, uint16_t h, + uint16_t outline, uint16_t fill, uint16_t textcolor, + char *label, uint8_t textsize) +{ + _x1 = x1; + _y1 = y1; + _w = w; + _h = h; + _outlinecolor = outline; + _fillcolor = fill; + _textcolor = textcolor; + _textsize = textsize; + _gfx = gfx; + strncpy(_label, label, 9); +} + +void TFT_eSPI_Button::drawButton(boolean inverted) { + uint16_t fill, outline, text; + + if(!inverted) { + fill = _fillcolor; + outline = _outlinecolor; + text = _textcolor; + } else { + fill = _textcolor; + outline = _outlinecolor; + text = _fillcolor; + } + + uint8_t r = min(_w, _h) / 4; // Corner radius + _gfx->fillRoundRect(_x1, _y1, _w, _h, r, fill); + _gfx->drawRoundRect(_x1, _y1, _w, _h, r, outline); + + _gfx->setTextColor(text); + _gfx->setTextSize(_textsize); + + uint8_t tempdatum = _gfx->getTextDatum(); + _gfx->setTextDatum(MC_DATUM); + _gfx->drawString(_label, _x1 + (_w/2), _y1 + (_h/2)); + _gfx->setTextDatum(tempdatum); +} + +boolean TFT_eSPI_Button::contains(int16_t x, int16_t y) { + return ((x >= _x1) && (x < (_x1 + _w)) && + (y >= _y1) && (y < (_y1 + _h))); +} + +void TFT_eSPI_Button::press(boolean p) { + laststate = currstate; + currstate = p; +} + +boolean TFT_eSPI_Button::isPressed() { return currstate; } +boolean TFT_eSPI_Button::justPressed() { return (currstate && !laststate); } +boolean TFT_eSPI_Button::justReleased() { return (!currstate && laststate); } diff --git a/Extensions/Button.h b/Extensions/Button.h new file mode 100644 index 0000000..e44a8f4 --- /dev/null +++ b/Extensions/Button.h @@ -0,0 +1,38 @@ +/*************************************************************************************** +// The following button class has been ported over from the Adafruit_GFX library so +// should be compatible. +// A slightly different implementation in this TFT_eSPI library allows the button +// legends to be in any font +***************************************************************************************/ + +class TFT_eSPI_Button { + + public: + TFT_eSPI_Button(void); + // "Classic" initButton() uses center & size + void initButton(TFT_eSPI *gfx, int16_t x, int16_t y, + uint16_t w, uint16_t h, uint16_t outline, uint16_t fill, + uint16_t textcolor, char *label, uint8_t textsize); + + // New/alt initButton() uses upper-left corner & size + void initButtonUL(TFT_eSPI *gfx, int16_t x1, int16_t y1, + uint16_t w, uint16_t h, uint16_t outline, uint16_t fill, + uint16_t textcolor, char *label, uint8_t textsize); + void drawButton(boolean inverted = false); + boolean contains(int16_t x, int16_t y); + + void press(boolean p); + boolean isPressed(); + boolean justPressed(); + boolean justReleased(); + + private: + TFT_eSPI *_gfx; + int16_t _x1, _y1; // Coordinates of top-left corner + uint16_t _w, _h; + uint8_t _textsize; + uint16_t _outlinecolor, _fillcolor, _textcolor; + char _label[10]; + + boolean currstate, laststate; +}; diff --git a/Extensions/Smooth_font.cpp b/Extensions/Smooth_font.cpp new file mode 100644 index 0000000..ca1cb63 --- /dev/null +++ b/Extensions/Smooth_font.cpp @@ -0,0 +1,586 @@ + // Coded by Bodmer 10/2/18, see license in root directory. + // This is part of the TFT_eSPI class and is associated with anti-aliased font functions + + +//////////////////////////////////////////////////////////////////////////////////////// +// New anti-aliased (smoothed) font functions added below +//////////////////////////////////////////////////////////////////////////////////////// + +/*************************************************************************************** +** Function name: loadFont +** Description: loads parameters from a new font vlw file +*************************************************************************************x*/ +void TFT_eSPI::loadFont(String fontName, fs::FS &ffs) +{ + fontFS = ffs; + loadFont(fontName, false); +} +/*************************************************************************************** +** Function name: loadFont +** Description: loads parameters from a new font vlw file +*************************************************************************************x*/ +void TFT_eSPI::loadFont(String fontName, bool flash) +{ + /* + The vlw font format does not appear to be documented anywhere, so some reverse + engineering has been applied! + + Header of vlw file comprises 6 uint32_t parameters (24 bytes total): + 1. The gCount (number of character glyphs) + 2. A version number (0xB = 11 for the one I am using) + 3. The font size (in points, not pixels) + 4. Deprecated mboxY parameter (typically set to 0) + 5. Ascent in pixels from baseline to top of "d" + 6. Descent in pixels from baseline to bottom of "p" + + Next are gCount sets of values for each glyph, each set comprises 7 int32t parameters (28 bytes): + 1. Glyph Unicode stored as a 32 bit value + 2. Height of bitmap bounding box + 3. Width of bitmap bounding box + 4. gxAdvance for cursor (setWidth in Processing) + 5. dY = distance from cursor baseline to top of glyph bitmap (signed value +ve = up) + 6. dX = distance from cursor to left side of glyph bitmap (signed value -ve = left) + 7. padding value, typically 0 + + The bitmaps start next at 24 + (28 * gCount) bytes from the start of the file. + Each pixel is 1 byte, an 8 bit Alpha value which represents the transparency from + 0xFF foreground colour, 0x00 background. The sketch uses a linear interpolation + between the foreground and background RGB component colours. e.g. + pixelRed = ((fgRed * alpha) + (bgRed * (255 - alpha))/255 + To gain a performance advantage fixed point arithmetic is used with rounding and + division by 256 (shift right 8 bits is faster). + + After the bitmaps is: + 1 byte for font name string length (excludes null) + a zero terminated character string giving the font name + 1 byte for Postscript name string length + a zero/one terminated character string giving the font name + last byte is 0 for non-anti-aliased and 1 for anti-aliased (smoothed) + + Then the font name seen by Java when it's created + Then the postscript name of the font + Then a boolean to tell if smoothing is on or not. + + Glyph bitmap example is: + // Cursor coordinate positions for this and next character are marked by 'C' + // C<------- gxAdvance ------->C gxAdvance is how far to move cursor for next glyph cursor position + // | | + // | | ascent is top of "d", descent is bottom of "p" + // +-- gdX --+ ascent + // | +-- gWidth--+ | gdX is offset to left edge of glyph bitmap + // | + x@.........@x + | gdX may be negative e.g. italic "y" tail extending to left of + // | | @@.........@@ | | cursor position, plot top left corner of bitmap at (cursorX + gdX) + // | | @@.........@@ gdY | gWidth and gHeight are glyph bitmap dimensions + // | | .@@@.....@@@@ | | + // | gHeight ....@@@@@..@@ + + <-- baseline + // | | ...........@@ | + // | | ...........@@ | gdY is the offset to the top edge of the bitmap + // | | .@@.......@@. descent plot top edge of bitmap at (cursorY + yAdvance - gdY) + // | + x..@@@@@@@..x | x marks the corner pixels of the bitmap + // | | + // +---------------------------+ yAdvance is y delta for the next line, font size or (ascent + descent) + // some fonts can overlay in y direction so may need a user adjust value + + */ + + spiffs = flash; + + if(spiffs) fontFS = SPIFFS; + + unloadFont(); + + // Avoid a crash on the ESP32 if the file does not exist + if (fontFS.exists("/" + fontName + ".vlw") == false) { + Serial.println("Font file " + fontName + " not found!"); + return; + } + + fontFile = fontFS.open( "/" + fontName + ".vlw", "r"); + + if(!fontFile) return; + + fontFile.seek(0, fs::SeekSet); + + gFont.gCount = (uint16_t)readInt32(); // glyph count in file + readInt32(); // vlw encoder version - discard + gFont.yAdvance = (uint16_t)readInt32(); // Font size in points, not pixels + readInt32(); // discard + gFont.ascent = (uint16_t)readInt32(); // top of "d" + gFont.descent = (uint16_t)readInt32(); // bottom of "p" + + // These next gFont values might be updated when the Metrics are fetched + gFont.maxAscent = gFont.ascent; // Determined from metrics + gFont.maxDescent = gFont.descent; // Determined from metrics + gFont.yAdvance = gFont.ascent + gFont.descent; + gFont.spaceWidth = gFont.yAdvance / 4; // Guess at space width + + fontLoaded = true; + + // Fetch the metrics for each glyph + loadMetrics(gFont.gCount); + + //fontFile.close(); +} + + +/*************************************************************************************** +** Function name: loadMetrics +** Description: Get the metrics for each glyph and store in RAM +*************************************************************************************x*/ +//#define SHOW_ASCENT_DESCENT +void TFT_eSPI::loadMetrics(uint16_t gCount) +{ + uint32_t headerPtr = 24; + uint32_t bitmapPtr = 24 + gCount * 28; + +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) + { + gUnicode = (uint16_t*)ps_malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gHeight = (uint8_t*)ps_malloc( gCount ); // Height of glyph + gWidth = (uint8_t*)ps_malloc( gCount ); // Width of glyph + gxAdvance = (uint8_t*)ps_malloc( gCount ); // xAdvance - to move x cursor + gdY = (int16_t*)ps_malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character + gdX = (int8_t*)ps_malloc( gCount ); // offset for bitmap left edge relative to cursor X + gBitmap = (uint32_t*)ps_malloc( gCount * 4); // seek pointer to glyph bitmap in the file + } + else +#endif + { + gUnicode = (uint16_t*)malloc( gCount * 2); // Unicode 16 bit Basic Multilingual Plane (0-FFFF) + gHeight = (uint8_t*)malloc( gCount ); // Height of glyph + gWidth = (uint8_t*)malloc( gCount ); // Width of glyph + gxAdvance = (uint8_t*)malloc( gCount ); // xAdvance - to move x cursor + gdY = (int16_t*)malloc( gCount * 2); // offset from bitmap top edge from lowest point in any character + gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X + gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in the file + } + +#ifdef SHOW_ASCENT_DESCENT + Serial.print("ascent = "); Serial.println(gFont.ascent); + Serial.print("descent = "); Serial.println(gFont.descent); +#endif + + uint16_t gNum = 0; + fontFile.seek(headerPtr, fs::SeekSet); + while (gNum < gCount) + { + gUnicode[gNum] = (uint16_t)readInt32(); // Unicode code point value + gHeight[gNum] = (uint8_t)readInt32(); // Height of glyph + gWidth[gNum] = (uint8_t)readInt32(); // Width of glyph + gxAdvance[gNum] = (uint8_t)readInt32(); // xAdvance - to move x cursor + gdY[gNum] = (int16_t)readInt32(); // y delta from baseline + gdX[gNum] = (int8_t)readInt32(); // x delta from cursor + readInt32(); // ignored + + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gHeight = "); Serial.println(gHeight[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gWidth = "); Serial.println(gWidth[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gxAdvance = "); Serial.println(gxAdvance[gNum]); + //Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", gdY = "); Serial.println(gdY[gNum]); + + // Different glyph sets have different ascent values not always based on "d", so we could get + // the maximum glyph ascent by checking all characters. BUT this method can generate bad values + // for non-existant glyphs, so we will reply on processing for the value and disable this code for now... + /* + if (gdY[gNum] > gFont.maxAscent) + { + // Try to avoid UTF coding values and characters that tend to give duff values + if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0x7F)) || (gUnicode[gNum] > 0xA0)) + { + gFont.maxAscent = gdY[gNum]; +#ifdef SHOW_ASCENT_DESCENT + Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", maxAscent = "); Serial.println(gFont.maxAscent); +#endif + } + } + */ + + // Different glyph sets have different descent values not always based on "p", so get maximum glyph descent + if (((int16_t)gHeight[gNum] - (int16_t)gdY[gNum]) > gFont.maxDescent) + { + // Avoid UTF coding values and characters that tend to give duff values + if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF)) + { + gFont.maxDescent = gHeight[gNum] - gdY[gNum]; +#ifdef SHOW_ASCENT_DESCENT + Serial.print("Unicode = 0x"); Serial.print(gUnicode[gNum], HEX); Serial.print(", maxDescent = "); Serial.println(gHeight[gNum] - gdY[gNum]); +#endif + } + } + + gBitmap[gNum] = bitmapPtr; + + headerPtr += 28; + + bitmapPtr += gWidth[gNum] * gHeight[gNum]; + + gNum++; + yield(); + } + + gFont.yAdvance = gFont.maxAscent + gFont.maxDescent; + + gFont.spaceWidth = (gFont.ascent + gFont.descent) * 2/7; // Guess at space width +} + + +/*************************************************************************************** +** Function name: deleteMetrics +** Description: Delete the old glyph metrics and free up the memory +*************************************************************************************x*/ +void TFT_eSPI::unloadFont( void ) +{ + if (gUnicode) + { + free(gUnicode); + gUnicode = NULL; + } + + if (gHeight) + { + free(gHeight); + gHeight = NULL; + } + + if (gWidth) + { + free(gWidth); + gWidth = NULL; + } + + if (gxAdvance) + { + free(gxAdvance); + gxAdvance = NULL; + } + + if (gdY) + { + free(gdY); + gdY = NULL; + } + + if (gdX) + { + free(gdX); + gdX = NULL; + } + + if (gBitmap) + { + free(gBitmap); + gBitmap = NULL; + } + + if(fontFile) fontFile.close(); + fontLoaded = false; +} + + +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +/* Function moved to TFT_eSPI.cpp +#define DECODE_UTF8 +uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) +{ + byte c = buf[(*index)++]; + //Serial.print("Byte from string = 0x"); Serial.println(c, HEX); + +#ifdef DECODE_UTF8 + // 7 bit Unicode + if ((c & 0x80) == 0x00) return c; + + // 11 bit Unicode + if (((c & 0xE0) == 0xC0) && (remaining > 1)) + return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F); + + // 16 bit Unicode + if (((c & 0xF0) == 0xE0) && (remaining > 2)) + { + c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6); + return c | ((buf[(*index)++]&0x3F)); + } + + // 21 bit Unicode not supported so fall-back to extended ASCII + // if ((c & 0xF8) == 0xF0) return c; +#endif + + return c; // fall-back to extended ASCII +} +*/ + +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Serial UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +/* Function moved to TFT_eSPI.cpp +uint16_t TFT_eSPI::decodeUTF8(uint8_t c) +{ + +#ifdef DECODE_UTF8 + + // 7 bit Unicode + if ((c & 0x80) == 0x00) { + decoderState = 0; + return (uint16_t)c; + } + + if (decoderState == 0) + { + // 11 bit Unicode + if ((c & 0xE0) == 0xC0) + { + decoderBuffer = ((c & 0x1F)<<6); + decoderState = 1; + return 0; + } + + // 16 bit Unicode + if ((c & 0xF0) == 0xE0) + { + decoderBuffer = ((c & 0x0F)<<12); + decoderState = 2; + return 0; + } + // 21 bit Unicode not supported so fall-back to extended ASCII + if ((c & 0xF8) == 0xF0) return (uint16_t)c; + } + else + { + if (decoderState == 2) + { + decoderBuffer |= ((c & 0x3F)<<6); + decoderState--; + return 0; + } + else + { + decoderBuffer |= (c & 0x3F); + decoderState = 0; + return decoderBuffer; + } + } +#endif + + decoderState = 0; + return (uint16_t)c; // fall-back to extended ASCII +} +*/ + + + +/*************************************************************************************** +** Function name: alphaBlend +** Description: Blend foreground and background and return new colour +*************************************************************************************x*/ +uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) +{ + // For speed use fixed point maths and rounding to permit a power of 2 division + uint16_t fgR = ((fgc >> 10) & 0x3E) + 1; + uint16_t fgG = ((fgc >> 4) & 0x7E) + 1; + uint16_t fgB = ((fgc << 1) & 0x3E) + 1; + + uint16_t bgR = ((bgc >> 10) & 0x3E) + 1; + uint16_t bgG = ((bgc >> 4) & 0x7E) + 1; + uint16_t bgB = ((bgc << 1) & 0x3E) + 1; + + // Shift right 1 to drop rounding bit and shift right 8 to divide by 256 + uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9); + uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9); + uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9); + + // Combine RGB565 colours into 16 bits + //return ((r&0x18) << 11) | ((g&0x30) << 5) | ((b&0x18) << 0); // 2 bit greyscale + //return ((r&0x1E) << 11) | ((g&0x3C) << 5) | ((b&0x1E) << 0); // 4 bit greyscale + return (r << 11) | (g << 5) | (b << 0); +} + + +/*************************************************************************************** +** Function name: readInt32 +** Description: Get a 32 bit integer from the font file +*************************************************************************************x*/ +uint32_t TFT_eSPI::readInt32(void) +{ + uint32_t val = 0; + val |= fontFile.read() << 24; + val |= fontFile.read() << 16; + val |= fontFile.read() << 8; + val |= fontFile.read(); + return val; +} + + +/*************************************************************************************** +** Function name: getUnicodeIndex +** Description: Get the font file index of a Unicode character +*************************************************************************************x*/ +bool TFT_eSPI::getUnicodeIndex(uint16_t unicode, uint16_t *index) +{ + for (uint16_t i = 0; i < gFont.gCount; i++) + { + if (gUnicode[i] == unicode) + { + *index = i; + return true; + } + } + return false; +} + + +/*************************************************************************************** +** Function name: drawGlyph +** Description: Write a character to the TFT cursor position +*************************************************************************************x*/ +// Expects file to be open +void TFT_eSPI::drawGlyph(uint16_t code) +{ + if (code < 0x21) + { + if (code == 0x20) { + cursor_x += gFont.spaceWidth; + return; + } + + if (code == '\n') { + cursor_x = 0; + cursor_y += gFont.yAdvance; + if (cursor_y >= _height) cursor_y = 0; + return; + } + } + + uint16_t gNum = 0; + bool found = getUnicodeIndex(code, &gNum); + + uint16_t fg = textcolor; + uint16_t bg = textbgcolor; + + if (found) + { + + if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > _width)) + { + cursor_y += gFont.yAdvance; + cursor_x = 0; + } + if (textwrapY && ((cursor_y + gFont.yAdvance) >= _height)) cursor_y = 0; + if (cursor_x == 0) cursor_x -= gdX[gNum]; + + fontFile.seek(gBitmap[gNum], fs::SeekSet); // This is taking >30ms for a significant position shift + + uint8_t pbuffer[gWidth[gNum]]; + + int16_t xs = 0; + uint32_t dl = 0; + + int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; + int16_t cx = cursor_x + gdX[gNum]; + + startWrite(); // Avoid slow ESP32 transaction overhead for every pixel + + for (int y = 0; y < gHeight[gNum]; y++) + { + if (spiffs) + { + fontFile.read(pbuffer, gWidth[gNum]); + //Serial.println("SPIFFS"); + } + else + { + endWrite(); // Release SPI for SD card transaction + fontFile.read(pbuffer, gWidth[gNum]); + startWrite(); // Re-start SPI for TFT transaction + //Serial.println("Not SPIFFS"); + } + + for (int x = 0; x < gWidth[gNum]; x++) + { + uint8_t pixel = pbuffer[x]; //= width()) { + cursorX = -gdX[i]; + + cursorY += gFont.yAdvance; + if (cursorY + gFont.maxAscent + gFont.descent >= height()) { + cursorX = -gdX[i]; + cursorY = 0; + delay(timeDelay); + timeDelay = td; + fillScreen(textbgcolor); + } + } + + setCursor(cursorX, cursorY); + drawGlyph(gUnicode[i]); + cursorX += gxAdvance[i]; + //cursorX += printToSprite( cursorX, cursorY, i ); + yield(); + } + + delay(timeDelay); + fillScreen(textbgcolor); + //fontFile.close(); + +} diff --git a/Extensions/Smooth_font.h b/Extensions/Smooth_font.h new file mode 100644 index 0000000..a7e2ca6 --- /dev/null +++ b/Extensions/Smooth_font.h @@ -0,0 +1,50 @@ + // Coded by Bodmer 10/2/18, see license in root directory. + // This is part of the TFT_eSPI class and is associated with anti-aliased font functions + + public: + + // These are for the new antialiased fonts + void loadFont(String fontName, fs::FS &ffs); + void loadFont(String fontName, bool flash = true); + void unloadFont( void ); + bool getUnicodeIndex(uint16_t unicode, uint16_t *index); + + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + + virtual void drawGlyph(uint16_t code); + + void showFont(uint32_t td); + + // This is for the whole font + typedef struct + { + uint16_t gCount; // Total number of characters + uint16_t yAdvance; // Line advance + uint16_t spaceWidth; // Width of a space character + int16_t ascent; // Height of top of 'd' above baseline, other characters may be taller + int16_t descent; // Offset to bottom of 'p', other characters may have a larger descent + uint16_t maxAscent; // Maximum ascent found in font + uint16_t maxDescent; // Maximum descent found in font + } fontMetrics; + +fontMetrics gFont = { 0, 0, 0, 0, 0, 0, 0 }; + + // These are for the metrics for each individual glyph (so we don't need to seek this in file and waste time) + uint16_t* gUnicode = NULL; //UTF-16 code, the codes are searched so do not need to be sequential + uint8_t* gHeight = NULL; //cheight + uint8_t* gWidth = NULL; //cwidth + uint8_t* gxAdvance = NULL; //setWidth + int16_t* gdY = NULL; //topExtent + int8_t* gdX = NULL; //leftExtent + uint32_t* gBitmap = NULL; //file pointer to greyscale bitmap + + bool fontLoaded = false; // Flags when a anti-aliased font is loaded + fs::File fontFile; + + private: + + void loadMetrics(uint16_t gCount); + uint32_t readInt32(void); + + fs::FS &fontFS = SPIFFS; + bool spiffs = true; \ No newline at end of file diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp new file mode 100644 index 0000000..2c8573e --- /dev/null +++ b/Extensions/Sprite.cpp @@ -0,0 +1,2006 @@ +/************************************************************************************** +// The following class creates Sprites in RAM, graphics can then be drawn in the Sprite +// and rendered quickly onto the TFT screen. The class inherits the graphics functions +// from the TFT_eSPI class. Some functions are overridden by this class so that the +// graphics are written to the Sprite rather than the TFT. +// Coded by Bodmer, see license file in root folder +***************************************************************************************/ +/*************************************************************************************** +// Color bytes are swapped when writing to RAM, this introduces a small overhead but +// there is a nett performance gain by using swapped bytes. +***************************************************************************************/ + +/*************************************************************************************** +** Function name: TFT_eSprite +** Description: Class constructor +*************************************************************************************x*/ +TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) +{ + _tft = tft; // Pointer to tft class so we can call member functions + + _iwidth = 0; // Initialise width and height to 0 (it does not exist yet) + _iheight = 0; + _bpp = 16; + _iswapBytes = false; // Do not swap pushImage colour bytes by default + + _created = false; + + _xs = 0; // window bounds for pushColor + _ys = 0; + _xe = 0; + _ye = 0; + + _xptr = 0; // pushColor coordinate + _yptr = 0; + + _xpivot = 0; + _ypivot = 0; + + this->cursor_y = this->cursor_x = 0; // Text cursor position +} + + +/*************************************************************************************** +** Function name: createSprite +** Description: Create a sprite (bitmap) of defined width and height +*************************************************************************************x*/ +// cast returned value to (uint8_t*) for 8 bit or (uint16_t*) for 16 bit colours +void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) +{ + + if ( _created ) return _img8_1; + + if ( w < 1 || h < 1 ) return NULL; + + _iwidth = _dwidth = _bitwidth = w; + _iheight = _dheight = h; + + this->cursor_x = 0; + this->cursor_y = 0; + + // Default scroll rectangle and gap fill colour + _sx = 0; + _sy = 0; + _sw = w; + _sh = h; + _scolor = TFT_BLACK; + + _xpivot = w/2; + _ypivot = h/2; + + _img8 = (uint8_t*) callocSprite(w, h, frames); + _img8_1 = _img8; + _img8_2 = _img8; + _img = (uint16_t*) _img8; + + // This is to make it clear what pointer size is expected to be used + // but casting in the user sketch is needed due to the use of void* + if (_bpp == 1) + { + w = (w+7) & 0xFFF8; + _img8_2 = _img8 + ( (w>>3) * h + 1 ); + } + + if (_img8) + { + _created = true; + return _img8; + } + + return NULL; +} + + +/*************************************************************************************** +** Function name: callocSprite +** Description: Allocate a memory area for the Sprite and return pointer +*************************************************************************************x*/ + +void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) +{ + // Add one extra "off screen" pixel to point out-of-bounds setWindow() coordinates + // this means push/writeColor functions do not need additional bounds checks and + // hence will run faster in normal circumstances. + uint8_t* ptr8 = NULL; + + if (_bpp == 16) + { + +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint16_t)); + else +#endif + ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); + } + + else if (_bpp == 8) + { +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(w * h + 1, sizeof(uint8_t)); + else +#endif + ptr8 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); + } + + else // Must be 1 bpp + { + //_dwidth Display width+height in pixels always in rotation 0 orientation + //_dheight Not swapped for sprite rotations + // Note: for 1bpp _iwidth and _iheight are swapped during Sprite rotations + + w = (w+7) & 0xFFF8; // width should be the multiple of 8 bits to be compatible with epdpaint + _iwidth = w; // _iwidth is rounded up to be multiple of 8, so might not be = _dwidth + _bitwidth = w; + + if (frames > 2) frames = 2; // Currently restricted to 2 frame buffers + if (frames < 1) frames = 1; +#if defined (ESP32) && defined (CONFIG_SPIRAM_SUPPORT) + if ( psramFound() ) ptr8 = ( uint8_t*) ps_calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); + else +#endif + ptr8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); + } + + return ptr8; +} + +/*************************************************************************************** +** Function name: frameBuffer +** Description: For 1 bpp Sprites, select the frame used for graphics +*************************************************************************************x*/ +// Frames are numbered 1 and 2 +void* TFT_eSprite::frameBuffer(int8_t f) +{ + if (!_created) return NULL; + + if (_bpp == 16) return _img; + + if (_bpp == 8) return _img8; + + if ( f == 2 ) _img8 = _img8_2; + else _img8 = _img8_1; + + return _img8; +} + +/*************************************************************************************** +** Function name: setColorDepth +** Description: Set bits per pixel for colour (1, 8 or 16) +*************************************************************************************x*/ + +void* TFT_eSprite::setColorDepth(int8_t b) +{ + // Can't change an existing sprite's colour depth so delete it + if (_created) free(_img8_1); + + // Now define the new colour depth + if ( b > 8 ) _bpp = 16; // Bytes per pixel + else if ( b > 1 ) _bpp = 8; + else _bpp = 1; + + // If it existed, re-create the sprite with the new colour depth + if (_created) + { + _created = false; + return createSprite(_iwidth, _iheight); + } + + return NULL; +} + + +/*************************************************************************************** +** Function name: getColorDepth +** Description: Get bits per pixel for colour (1, 8 or 16) +*************************************************************************************x*/ + +int8_t TFT_eSprite::getColorDepth(void) +{ + if (_created) return _bpp; + else return 0; +} + + +/*************************************************************************************** +** Function name: setBitmapColor +** Description: Set the foreground foreground and background colour +***************************************************************************************/ +void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) +{ + if (c == b) b = ~c; + _tft->bitmap_fg = c; + _tft->bitmap_bg = b; +} + + +/*************************************************************************************** +** Function name: deleteSprite +** Description: Delete the sprite to free up memory (RAM) +*************************************************************************************x*/ +void TFT_eSprite::deleteSprite(void) +{ + if (!_created ) return; + + free(_img8_1); + + _created = false; +} + + +/*************************************************************************************** +** Function name: setPivot +** Description: Set the pivot point in this Sprite +*************************************************************************************x*/ +void TFT_eSprite::setPivot(int16_t x, int16_t y) +{ + _xpivot = x; + _ypivot = y; +} + + +/*************************************************************************************** +** Function name: getPivotX +** Description: Get the x pivot position +***************************************************************************************/ +int16_t TFT_eSprite::getPivotX(void) +{ + return _xpivot; +} + + +/*************************************************************************************** +** Function name: getPivotY +** Description: Get the y pivot position +***************************************************************************************/ +int16_t TFT_eSprite::getPivotY(void) +{ + return _ypivot; +} + + +/*************************************************************************************** +** Function name: pushRotated +** Description: Push a rotated copy of the Sprite to TFT screen +*************************************************************************************x*/ +bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) +{ + if ( !_created ) return false; + + // Trig values for the rotation + float radAngle = -angle * 0.0174532925; // Convert degrees to radians + float sinra = sin(radAngle); + float cosra = cos(radAngle); + + // Bounding box parameters + int16_t min_x; + int16_t min_y; + int16_t max_x; + int16_t max_y; + + // Get the bounding box of this rotated source Sprite relative to Sprite pivot + getRotatedBounds(sinra, cosra, width(), height(), _xpivot, _ypivot, &min_x, &min_y, &max_x, &max_y); + + // Move bounding box so source Sprite pivot coincides with TFT pivot + min_x += _tft->_xpivot; + max_x += _tft->_xpivot; + min_y += _tft->_ypivot; + max_y += _tft->_ypivot; + + // Test only to show bounding box on TFT + // _tft->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); + + // Return if bounding box is outside of TFT area + if (min_x > _tft->width()) return true; + if (min_y > _tft->height()) return true; + if (max_x < 0) return true; + if (max_y < 0) return true; + + // Clip bounding box to be within TFT area + if (min_x < 0) min_x = 0; + if (min_y < 0) min_y = 0; + if (max_x > _tft->width()) max_x = _tft->width(); + if (max_y > _tft->height()) max_y = _tft->height(); + + _tft->startWrite(); // ESP32: avoid transaction overhead for every tft pixel + + // Scan destination bounding box and fetch transformed pixels from source Sprite + for (int32_t x = min_x; x <= max_x; x++) { + int32_t xt = x - _tft->_xpivot; + float cxt = cosra * xt + _xpivot; + float sxt = sinra * xt + _ypivot; + bool column_drawn = false; + for (int32_t y = min_y; y <= max_y; y++) { + int32_t yt = y - _tft->_ypivot; + int32_t xs = (int32_t)round(cxt - sinra * yt); + // Do not calculate ys unless xs is in bounds + if (xs >= 0 && xs < width()) + { + int32_t ys = (int32_t)round(sxt + cosra * yt); + // Check if ys is in bounds + if (ys >= 0 && ys < height()) { + int32_t rp = readPixel(xs, ys); + if (rp != transp) _tft->drawPixel(x, y, rp); + column_drawn = true; + } + } + else if (column_drawn) y = max_y; // Skip remaining column pixels + } + } + + _tft->endWrite(); // ESP32: end transaction + + return true; +} + + +/*************************************************************************************** +** Function name: pushRotated +** Description: Push a rotated copy of the Sprite to another Sprite +*************************************************************************************x*/ +bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) +{ + if ( !_created ) return false; // Check this Sprite is created + if ( !spr->_created ) return false; // Ckeck destination Sprite is created + + // Trig values for the rotation + float radAngle = -angle * 0.0174532925; // Convert degrees to radians + float sinra = sin(radAngle); + float cosra = cos(radAngle); + + // Bounding box parameters + int16_t min_x; + int16_t min_y; + int16_t max_x; + int16_t max_y; + + // Get the bounding box of this rotated source Sprite + getRotatedBounds(sinra, cosra, width(), height(), _xpivot, _ypivot, &min_x, &min_y, &max_x, &max_y); + + // Move bounding box so source Sprite pivot coincides with destination Sprite pivot + min_x += spr->_xpivot; + max_x += spr->_xpivot; + min_y += spr->_ypivot; + max_y += spr->_ypivot; + + // Test only to show bounding box + // spr->fillSprite(TFT_BLACK); + // spr->drawRect(min_x, min_y, max_x - min_x + 1, max_y - min_y + 1, TFT_GREEN); + + // Return if bounding box is completely outside of destination Sprite + if (min_x > spr->width()) return true; + if (min_y > spr->height()) return true; + if (max_x < 0) return true; + if (max_y < 0) return true; + + // Clip bounding box if it is partially within destination Sprite + if (min_x < 0) min_x = 0; + if (min_y < 0) min_y = 0; + if (max_x > spr->width()) max_x = spr->width(); + if (max_y > spr->height()) max_y = spr->height(); + + // Scan destination bounding box and fetch transformed pixels from source Sprite + for (int32_t x = min_x; x <= max_x; x++) + { + int32_t xt = x - spr->_xpivot; + float cxt = cosra * xt + _xpivot; + float sxt = sinra * xt + _ypivot; + bool column_drawn = false; + for (int32_t y = min_y; y <= max_y; y++) + { + int32_t yt = y - spr->_ypivot; + int32_t xs = (int32_t)round(cxt - sinra * yt); + // Do not calculate ys unless xs is in bounds + if (xs >= 0 && xs < width()) + { + int32_t ys = (int32_t)round(sxt + cosra * yt); + // Check if ys is in bounds + if (ys >= 0 && ys < height()) + { + int32_t rp = readPixel(xs, ys); + if (rp != transp) spr->drawPixel(x, y, rp); + column_drawn = true; + } + } + else if (column_drawn) y = max_y; // Skip the remaining pixels below the Sprite + } + } + + return true; +} + + +/*************************************************************************************** +** Function name: rotatedBounds +** Description: Get bounding box of a rotated Sprite wrt pivot +*************************************************************************************x*/ +void TFT_eSprite::getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y) +{ + w -= xp; // w is now right edge coordinate relative to xp + h -= yp; // h is now bottom edge coordinate relative to yp + + // Calculate new corner coordinates + int16_t x0 = -xp * cosa - yp * sina; + int16_t y0 = xp * sina - yp * cosa; + + int16_t x1 = w * cosa - yp * sina; + int16_t y1 = -w * sina - yp * cosa; + + int16_t x2 = h * sina + w * cosa; + int16_t y2 = h * cosa - w * sina; + + int16_t x3 = h * sina - xp * cosa; + int16_t y3 = h * cosa + xp * sina; + + // Find bounding box extremes, enlarge box to accomodate rounding errors + *min_x = x0-2; + if (x1 < *min_x) *min_x = x1-2; + if (x2 < *min_x) *min_x = x2-2; + if (x3 < *min_x) *min_x = x3-2; + + *max_x = x0+2; + if (x1 > *max_x) *max_x = x1+2; + if (x2 > *max_x) *max_x = x2+2; + if (x3 > *max_x) *max_x = x3+2; + + *min_y = y0-2; + if (y1 < *min_y) *min_y = y1-2; + if (y2 < *min_y) *min_y = y2-2; + if (y3 < *min_y) *min_y = y3-2; + + *max_y = y0+2; + if (y1 > *max_y) *max_y = y1+2; + if (y2 > *max_y) *max_y = y2+2; + if (y3 > *max_y) *max_y = y3+2; + +} + + +/*************************************************************************************** +** Function name: pushSprite +** Description: Push the sprite to the TFT at x, y +*************************************************************************************x*/ +void TFT_eSprite::pushSprite(int32_t x, int32_t y) +{ + if (!_created) return; + + if (_bpp == 16) + { + bool oldSwapBytes = _tft->getSwapBytes(); + _tft->setSwapBytes(false); + _tft->pushImage(x, y, _iwidth, _iheight, _img ); + _tft->setSwapBytes(oldSwapBytes); + } + + else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); +} + + +/*************************************************************************************** +** Function name: pushSprite +** Description: Push the sprite to the TFT at x, y with transparent colour +*************************************************************************************x*/ +void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) +{ + if (!_created) return; + + if (_bpp == 16) + { + bool oldSwapBytes = _tft->getSwapBytes(); + _tft->setSwapBytes(false); + _tft->pushImage(x, y, _iwidth, _iheight, _img, transp ); + _tft->setSwapBytes(oldSwapBytes); + } + else if (_bpp == 8) + { + transp = (uint8_t)((transp & 0xE000)>>8 | (transp & 0x0700)>>6 | (transp & 0x0018)>>3); + _tft->pushImage(x, y, _dwidth, _dheight, _img8, (uint8_t)transp, (bool)true); + } + else _tft->pushImage(x, y, _dwidth, _dheight, _img8, 0, (bool)false); +} + + +/*************************************************************************************** +** Function name: readPixel +** Description: Read 565 colour of a pixel at defined coordinates +*************************************************************************************x*/ +uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) +{ + if ((x < 0) || (x >= _iwidth) || (y < 0) || (y >= _iheight) || !_created) return 0; + + if (_bpp == 16) + { + uint16_t color = _img[x + y * _iwidth]; + return (color >> 8) | (color << 8); + } + + if (_bpp == 8) + { + uint16_t color = _img8[x + y * _iwidth]; + if (color != 0) + { + uint8_t blue[] = {0, 11, 21, 31}; + color = (color & 0xE0)<<8 | (color & 0xC0)<<5 + | (color & 0x1C)<<6 | (color & 0x1C)<<3 + | blue[color & 0x03]; + } + return color; + } + + if (_rotation == 1) + { + uint16_t tx = x; + x = _dwidth - y - 1; + y = tx; + } + else if (_rotation == 2) + { + x = _dwidth - x - 1; + y = _dheight - y - 1; + } + else if (_rotation == 3) + { + uint16_t tx = x; + x = y; + y = _dheight - tx - 1; + } + + uint16_t color = (_img8[(x + y * _bitwidth)>>3] << (x & 0x7)) & 0x80; + + return color >> 7; +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: push 565 colour image into a defined area of a sprite +*************************************************************************************x*/ +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) +{ + if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + if ((x + w < 0) || (y + h < 0)) return; + + int32_t xo = 0; + int32_t yo = 0; + + int32_t xs = x; + int32_t ys = y; + + uint32_t ws = w; + uint32_t hs = h; + + if (x < 0) { xo = -x; ws += x; xs = 0; } + if (y < 0) { yo = -y; hs += y; ys = 0; } + + if (xs + ws >= _iwidth) ws = _iwidth - xs; + if (ys + hs >= _iheight) hs = _iheight - ys; + + if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite + { + for (uint32_t yp = yo; yp < yo + hs; yp++) + { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) + { + uint16_t color = data[xp + yp * w]; + if(!_iswapBytes) color = color<<8 | color>>8; + _img[x + ys * _iwidth] = color; + x++; + } + ys++; + } + } + else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite + { + for (uint32_t yp = yo; yp < yo + hs; yp++) + { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) + { + uint16_t color = data[xp + yp * w]; + if(_iswapBytes) color = color<<8 | color>>8; + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + x++; + } + ys++; + } + } + + else // 1bpp + { + // Move coordinate rotation to support fn + if (_rotation == 1) + { + int32_t tx = x; + x = _dwidth - y - 1; + y = tx; + } + else if (_rotation == 2) + { + x = _dwidth - x - 1; + y = _dheight - y - 1; + } + else if (_rotation == 3) + { + int32_t tx = x; + x = y; + y = _dheight - tx - 1; + } + // Plot a 1bpp image into a 1bpp Sprite + uint8_t* pdata = (uint8_t* ) data; + uint32_t ww = (w+7) & 0xFFF8; + for (int32_t yp = 0; yp>3; + uint32_t yyp = y + yp; + for (int32_t xp = 0; xp>3) + yw] & (0x80 >> (xp & 0x7)) ); + drawPixel(x+xp, yyp, readPixel); + } + } + } +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: push 565 colour FLASH (PROGMEM) image into a defined area +*************************************************************************************x*/ +void TFT_eSprite::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) +{ +#ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*) data); +#else + // Partitioned memory FLASH processor + if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + if ((x + w < 0) || (y + h < 0)) return; + + int32_t xo = 0; + int32_t yo = 0; + + int32_t xs = x; + int32_t ys = y; + + uint32_t ws = w; + uint32_t hs = h; + + if (x < 0) { xo = -x; ws += x; xs = 0; } + if (y < 0) { yo = -y; hs += y; ys = 0; } + + if (xs + ws >= _iwidth) ws = _iwidth - xs; + if (ys + hs >= _iheight) hs = _iheight - ys; + + if (_bpp == 16) // Plot a 16 bpp image into a 16 bpp Sprite + { + for (uint32_t yp = yo; yp < yo + hs; yp++) + { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) + { + uint16_t color = pgm_read_word(data + xp + yp * w); + if(!_iswapBytes) color = color<<8 | color>>8; + _img[x + ys * _iwidth] = color; + x++; + } + ys++; + } + } + + else if (_bpp == 8) // Plot a 16 bpp image into a 8 bpp Sprite + { + for (uint32_t yp = yo; yp < yo + hs; yp++) + { + x = xs; + for (uint32_t xp = xo; xp < xo + ws; xp++) + { + uint16_t color = pgm_read_word(data + xp + yp * w); + if(_iswapBytes) color = color<<8 | color>>8; + _img8[x + ys * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + x++; + } + ys++; + } + } + + else // 1bpp + { + // Move coordinate rotation to support fn + if (_rotation == 1) + { + int32_t tx = x; + x = _dwidth - y - 1; + y = tx; + } + else if (_rotation == 2) + { + x = _dwidth - x - 1; + y = _dheight - y - 1; + } + else if (_rotation == 3) + { + int32_t tx = x; + x = y; + y = _dheight - tx - 1; + } + // Plot a 1bpp image into a 1bpp Sprite + const uint8_t* pdata = (const uint8_t* ) data; + uint32_t ww = (w+7) & 0xFFF8; + for (int32_t yp = 0; yp x1) swap_coord(x0, x1); + if (y0 > y1) swap_coord(y0, y1); + + if ((x0 >= _iwidth) || (x1 < 0) || (y0 >= _iheight) || (y1 < 0)) + { // Point to that extra "off screen" pixel + _xs = 0; + _ys = _iheight; + _xe = 0; + _ye = _iheight; + } + else + { + if (x0 < 0) x0 = 0; + if (x1 >= _iwidth) x1 = _iwidth - 1; + if (y0 < 0) y0 = 0; + if (y1 >= _iheight) y1 = _iheight - 1; + + _xs = x0; + _ys = y0; + _xe = x1; + _ye = y1; + } + + _xptr = _xs; + _yptr = _ys; +} + + +/*************************************************************************************** +** Function name: pushColor +** Description: Send a new pixel to the set window +*************************************************************************************x*/ +void TFT_eSprite::pushColor(uint32_t color) +{ + if (!_created ) return; + + // Write the colour to RAM in set window + if (_bpp == 16) + _img [_xptr + _yptr * _iwidth] = (uint16_t) (color >> 8) | (color << 8); + + else if (_bpp == 8) + _img8[_xptr + _yptr * _iwidth] = (uint8_t )((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + + else drawPixel(_xptr, _yptr, color); + + // Increment x + _xptr++; + + // Wrap on x and y to start, increment y if needed + if (_xptr > _xe) + { + _xptr = _xs; + _yptr++; + if (_yptr > _ye) _yptr = _ys; + } + +} + + +/*************************************************************************************** +** Function name: pushColor +** Description: Send a "len" new pixels to the set window +*************************************************************************************x*/ +void TFT_eSprite::pushColor(uint32_t color, uint16_t len) +{ + if (!_created ) return; + + uint16_t pixelColor; + + if (_bpp == 16) + pixelColor = (uint16_t) (color >> 8) | (color << 8); + + else if (_bpp == 8) + pixelColor = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + + else pixelColor = (uint16_t) color; // for 1bpp + + while(len--) writeColor(pixelColor); +} + + +/*************************************************************************************** +** Function name: writeColor +** Description: Write a pixel with pre-formatted colour to the set window +*************************************************************************************x*/ +void TFT_eSprite::writeColor(uint16_t color) +{ + if (!_created ) return; + + // Write 16 bit RGB 565 encoded colour to RAM + if (_bpp == 16) _img [_xptr + _yptr * _iwidth] = color; + + // Write 8 bit RGB 332 encoded colour to RAM + else if (_bpp == 8) _img8[_xptr + _yptr * _iwidth] = (uint8_t) color; + + else drawPixel(_xptr, _yptr, color); + + // Increment x + _xptr++; + + // Wrap on x and y to start, increment y if needed + if (_xptr > _xe) + { + _xptr = _xs; + _yptr++; + if (_yptr > _ye) _yptr = _ys; + } +} + + +/*************************************************************************************** +** Function name: setScrollRect +** Description: Set scroll area within the sprite and the gap fill colour +*************************************************************************************x*/ +void TFT_eSprite::setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color) +{ + if ((x >= _iwidth) || (y >= _iheight) || !_created ) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _iwidth ) w = _iwidth - x; + if ((y + h) > _iheight) h = _iheight - y; + + if ( w < 1 || h < 1) return; + + _sx = x; + _sy = y; + _sw = w; + _sh = h; + + _scolor = color; +} + + +/*************************************************************************************** +** Function name: scroll +** Description: Scroll dx,dy pixels, positive right,down, negative left,up +*************************************************************************************x*/ +void TFT_eSprite::scroll(int16_t dx, int16_t dy) +{ + if (abs(dx) >= _sw || abs(dy) >= _sh) + { + fillRect (_sx, _sy, _sw, _sh, _scolor); + return; + } + + // Fetch the scroll area width and height set by setScrollRect() + uint32_t w = _sw - abs(dx); // line width to copy + uint32_t h = _sh - abs(dy); // lines to copy + int32_t iw = _iwidth; // width of sprite + + // Fetch the x,y origin set by setScrollRect() + uint32_t tx = _sx; // to x + uint32_t fx = _sx; // from x + uint32_t ty = _sy; // to y + uint32_t fy = _sy; // from y + + // Adjust for x delta + if (dx <= 0) fx -= dx; + else tx += dx; + + // Adjust for y delta + if (dy <= 0) fy -= dy; + else + { // Scrolling down so start copy from bottom + ty = ty + _sh - 1; // "To" pointer + iw = -iw; // Pointer moves backwards + fy = ty - dy; // "From" pointer + } + + // Calculate "from y" and "to y" pointers in RAM + uint32_t fyp = fx + fy * _iwidth; + uint32_t typ = tx + ty * _iwidth; + + // Now move the pixels in RAM + if (_bpp == 16) + { + while (h--) + { // move pixel lines (to, from, byte count) + memmove( _img + typ, _img + fyp, w<<1); + typ += iw; + fyp += iw; + } + } + else if (_bpp == 8) + { + while (h--) + { // move pixel lines (to, from, byte count) + memmove( _img8 + typ, _img8 + fyp, w); + typ += iw; + fyp += iw; + } + } + else if (_bpp == 1) + { + if (dx > 0) { tx += w; fx += w; } // Start from right edge + while (h--) + { // move pixels one by one + for (uint16_t xp = 0; xp < w; xp++) + { + if (dx <= 0) drawPixel(tx + xp, ty, readPixel(fx + xp, fy)); + if (dx > 0) drawPixel(tx - xp, ty, readPixel(fx - xp, fy)); + } + if (dy <= 0) { ty++; fy++; } + else { ty--; fy--; } + } + } + else return; // Not 1, 8 or 16 bpp + + // Fill the gap left by the scrolling + if (dx > 0) fillRect(_sx, _sy, dx, _sh, _scolor); + if (dx < 0) fillRect(_sx + _sw + dx, _sy, -dx, _sh, _scolor); + if (dy > 0) fillRect(_sx, _sy, _sw, dy, _scolor); + if (dy < 0) fillRect(_sx, _sy + _sh + dy, _sw, -dy, _scolor); +} + + +/*************************************************************************************** +** Function name: fillSprite +** Description: Fill the whole sprite with defined colour +*************************************************************************************x*/ +void TFT_eSprite::fillSprite(uint32_t color) +{ + if (!_created ) return; + + // Use memset if possible as it is super fast + if(( (uint8_t)color == (uint8_t)(color>>8) ) && _bpp == 16) + memset(_img, (uint8_t)color, _iwidth * _iheight * 2); + else if (_bpp == 8) + { + color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + memset(_img8, (uint8_t)color, _iwidth * _iheight); + } + else if (_bpp == 1) + { + if(color) memset(_img8, 0xFF, (_iwidth>>3) * _iheight + 1); + else memset(_img8, 0x00, (_iwidth>>3) * _iheight + 1); + } + + else fillRect(0, 0, _iwidth, _iheight, color); +} + + +/*************************************************************************************** +** Function name: setCursor +** Description: Set the sprite text cursor x,y position +*************************************************************************************x*/ +// Not needed - using TFT_eSPI class function and this->cursor_x/y +//void TFT_eSprite::setCursor(int16_t x, int16_t y) +//{ +// this->cursor_x = x; +// this->cursor_y = y; +//} + + +/*************************************************************************************** +** Function name: width +** Description: Return the width of sprite +*************************************************************************************x*/ +// Return the size of the display +int16_t TFT_eSprite::width(void) +{ + if (!_created ) return 0; + + if (_bpp > 1) return _iwidth; + + if (_rotation == 1 || _rotation == 3) return _dheight; + + return _dwidth; +} + + +/*************************************************************************************** +** Function name: height +** Description: Return the height of sprite +*************************************************************************************x*/ +int16_t TFT_eSprite::height(void) +{ + if (!_created ) return 0; + + if (_bpp > 1) return _iheight; + + if (_rotation == 1 || _rotation == 3) return _dwidth; + + return _dheight; +} + + +/*************************************************************************************** +** Function name: setRotation +** Description: Rotate coordinate frame for 1bpp sprite +*************************************************************************************x*/ +// Does nothing for 8 and 16 bpp sprites. TODO allow rotation of these sprites +void TFT_eSprite::setRotation(uint8_t rotation) +{ + if (_bpp != 1) return; + + _rotation = rotation; + if (rotation == 0 && _iwidth > _iheight) swap_coord(_iwidth, _iheight); + if (rotation == 1 && _iwidth < _iheight) swap_coord(_iwidth, _iheight); + if (rotation == 2 && _iwidth > _iheight) swap_coord(_iwidth, _iheight); + if (rotation == 3 && _iwidth < _iheight) swap_coord(_iwidth, _iheight); +} + + +/*************************************************************************************** +** Function name: getRotation +** Description: Get rotation for 1bpp sprite +*************************************************************************************x*/ + +uint8_t TFT_eSprite::getRotation(void) +{ + return _rotation; +} + + +/*************************************************************************************** +** Function name: drawPixel +** Description: push a single pixel at an arbitrary position +*************************************************************************************x*/ +void TFT_eSprite::drawPixel(int32_t x, int32_t y, uint32_t color) +{ + // Range checking + if ((x < 0) || (y < 0) || !_created) return; + if ((x >= _iwidth) || (y >= _iheight)) return; + + if (_bpp == 16) + { + color = (color >> 8) | (color << 8); + _img[x+y*_iwidth] = (uint16_t) color; + } + else if (_bpp == 8) + { + _img8[x+y*_iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + } + else // 1 bpp + { + if (_rotation == 1) + { + uint16_t tx = x; + x = _dwidth - y - 1; + y = tx; + } + else if (_rotation == 2) + { + x = _dwidth - x - 1; + y = _dheight - y - 1; + } + else if (_rotation == 3) + { + uint16_t tx = x; + x = y; + y = _dheight - tx - 1; + } + + if (color) _img8[(x + y * _bitwidth)>>3] |= (0x80 >> (x & 0x7)); + else _img8[(x + y * _bitwidth)>>3] &= ~(0x80 >> (x & 0x7)); + } +} + + +/*************************************************************************************** +** Function name: drawLine +** Description: draw a line between 2 arbitrary points +*************************************************************************************x*/ +void TFT_eSprite::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) +{ + if (!_created ) return; + + boolean steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) { + swap_coord(x0, y0); + swap_coord(x1, y1); + } + + if (x0 > x1) { + swap_coord(x0, x1); + swap_coord(y0, y1); + } + + int32_t dx = x1 - x0, dy = abs(y1 - y0);; + + int32_t err = dx >> 1, ystep = -1, xs = x0, dlen = 0; + + if (y0 < y1) ystep = 1; + + // Split into steep and not steep for FastH/V separation + if (steep) { + for (; x0 <= x1; x0++) { + dlen++; + err -= dy; + if (err < 0) { + err += dx; + if (dlen == 1) drawPixel(y0, xs, color); + else drawFastVLine(y0, xs, dlen, color); + dlen = 0; y0 += ystep; xs = x0 + 1; + } + } + if (dlen) drawFastVLine(y0, xs, dlen, color); + } + else + { + for (; x0 <= x1; x0++) { + dlen++; + err -= dy; + if (err < 0) { + err += dx; + if (dlen == 1) drawPixel(xs, y0, color); + else drawFastHLine(xs, y0, dlen, color); + dlen = 0; y0 += ystep; xs = x0 + 1; + } + } + if (dlen) drawFastHLine(xs, y0, dlen, color); + } +} + + +/*************************************************************************************** +** Function name: drawFastVLine +** Description: draw a vertical line +*************************************************************************************x*/ +void TFT_eSprite::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) +{ + + if ((x < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) return; + + if (y < 0) { h += y; y = 0; } + + if ((y + h) > _iheight) h = _iheight - y; + + if (h < 1) return; + + if (_bpp == 16) + { + color = (color >> 8) | (color << 8); + int32_t yp = x + _iwidth * y; + while (h--) {_img[yp] = (uint16_t) color; yp += _iwidth;} + } + else if (_bpp == 8) + { + color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + while (h--) _img8[x + _iwidth * y++] = (uint8_t) color; + } + else + { + while (h--) + { + drawPixel(x, y, color); + y++; + } + } +} + + +/*************************************************************************************** +** Function name: drawFastHLine +** Description: draw a horizontal line +*************************************************************************************x*/ +void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) +{ + + if ((y < 0) || (x >= _iwidth) || (y >= _iheight) || !_created) return; + + if (x < 0) { w += x; x = 0; } + + if ((x + w) > _iwidth) w = _iwidth - x; + + if (w < 1) return; + + if (_bpp == 16) + { + color = (color >> 8) | (color << 8); + while (w--) _img[_iwidth * y + x++] = (uint16_t) color; + } + else if (_bpp == 8) + { + color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + memset(_img8+_iwidth * y + x, (uint8_t)color, w); + } + else + { + while (w--) + { + drawPixel(x, y, color); + x++; + } + } +} + + +/*************************************************************************************** +** Function name: fillRect +** Description: draw a filled rectangle +*************************************************************************************x*/ +void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) +{ + if (!_created ) return; + + if ((x >= _iwidth) || (y >= _iheight)) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _iwidth) w = _iwidth - x; + if ((y + h) > _iheight) h = _iheight - y; + + if ((w < 1) || (h < 1)) return; + + int32_t yp = _iwidth * y + x; + + if (_bpp == 16) + { + color = (color >> 8) | (color << 8); + uint32_t iw = w; + int32_t ys = yp; + if(h--) {while (iw--) _img[yp++] = (uint16_t) color;} + yp = ys; + while (h--) + { + yp += _iwidth; + memcpy( _img+yp, _img+ys, w<<1); + } + } + else if (_bpp == 8) + { + color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; + while (h--) + { + memset(_img8 + yp, (uint8_t)color, w); + yp += _iwidth; + } + } + else + { + while (h--) + { + int32_t ww = w; + int32_t xx = x; + while (ww--) drawPixel(xx++, y, color); + y++; + } + } +} + + +/*************************************************************************************** +** Function name: write +** Description: draw characters piped through serial stream +*************************************************************************************x*/ +size_t TFT_eSprite::write(uint8_t utf8) +{ + uint16_t uniCode = decodeUTF8(utf8); + + if (!uniCode) return 1; + + if (utf8 == '\r') return 1; + +#ifdef SMOOTH_FONT + if(this->fontLoaded) + { + if (uniCode < 32 && utf8 != '\n') return 1; + + //fontFile = SPIFFS.open( _gFontFilename, "r" ); + //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); + + //if(!fontFile) + //{ + // fontLoaded = false; + // return 1; + //} + //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); + + drawGlyph(uniCode); + + //fontFile.close(); + return 1; + } +#endif + + if (!_created ) return 1; + + if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (uniCode < 32) return 1; + + uint16_t width = 0; + uint16_t height = 0; + +//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + //Serial.print((uint8_t) uniCode); // Debug line sends all printed TFT text to serial port + //Serial.println(uniCode, HEX); // Debug line sends all printed TFT text to serial port + //delay(5); // Debug optional wait for serial port to flush through +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ DEBUG ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +#ifdef LOAD_GFXFF + if(!gfxFont) { +#endif +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + +#ifdef LOAD_FONT2 + if (textfont == 2) + { + if (utf8 > 127) return 1; + + width = pgm_read_byte(widtbl_f16 + uniCode-32); + height = chr_hgt_f16; + // Font 2 is rendered in whole byte widths so we must allow for this + width = (width + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change + width = width * 8; // Width converted back to pixles + } + #ifdef LOAD_RLE + else + #endif +#endif + +#ifdef LOAD_RLE + { + if ((textfont>2) && (textfont<9)) + { + if (utf8 > 127) return 1; + // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements + width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); + height= pgm_read_byte( &fontdata[textfont].height ); + } + } +#endif + +#ifdef LOAD_GLCD + if (textfont==1) + { + width = 6; + height = 8; + } +#else + if (textfont==1) return 1; +#endif + + height = height * textsize; + + if (utf8 == '\n') + { + this->cursor_y += height; + this->cursor_x = 0; + } + else + { + if (textwrapX && (this->cursor_x + width * textsize > _iwidth)) + { + this->cursor_y += height; + this->cursor_x = 0; + } + if (textwrapY && (this->cursor_y >= _iheight)) this->cursor_y = 0; + this->cursor_x += drawChar(uniCode, this->cursor_x, this->cursor_y, textfont); + } + +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +#ifdef LOAD_GFXFF + } // Custom GFX font + else + { + if(utf8 == '\n') { + this->cursor_x = 0; + this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } else { + if (uniCode > pgm_read_word(&gfxFont->last )) return 1; + if (uniCode < pgm_read_word(&gfxFont->first)) return 1; + + uint8_t c2 = uniCode - pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + if((w > 0) && (h > 0)) { // Is there an associated bitmap? + int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); + if(textwrapX && ((this->cursor_x + textsize * (xo + w)) > _iwidth)) { + // Drawing character would go off right edge; wrap to new line + this->cursor_x = 0; + this->cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } + if (textwrapY && (this->cursor_y >= _iheight)) this->cursor_y = 0; + drawChar(this->cursor_x, this->cursor_y, uniCode, textcolor, textbgcolor, textsize); + } + this->cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; + } + } +#endif // LOAD_GFXFF +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< + + return 1; +} + + +/*************************************************************************************** +** Function name: drawChar +** Description: draw a single character in the Adafruit GLCD or freefont +*************************************************************************************x*/ +void TFT_eSprite::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size) +{ + if (!_created ) return; + + if ((x >= _iwidth) || // Clip right + (y >= _iheight) || // Clip bottom + ((x + 6 * size - 1) < 0) || // Clip left + ((y + 8 * size - 1) < 0)) // Clip top + return; + + if (c < 32) return; +#ifdef LOAD_GLCD +//>>>>>>>>>>>>>>>>>> +#ifdef LOAD_GFXFF + if(!gfxFont) { // 'Classic' built-in font +#endif +//>>>>>>>>>>>>>>>>>> + + boolean fillbg = (bg != color); + + if ((size==1) && fillbg) + { + uint8_t column[6]; + uint8_t mask = 0x1; + + for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); + column[5] = 0; + + int8_t j, k; + for (j = 0; j < 8; j++) { + for (k = 0; k < 5; k++ ) { + if (column[k] & mask) { + drawPixel(x + k, y + j, color); + } + else { + drawPixel(x + k, y + j, bg); + } + } + + mask <<= 1; + + drawPixel(x + k, y + j, bg); + } + } + else + { + for (int8_t i = 0; i < 6; i++ ) { + uint8_t line; + if (i == 5) + line = 0x0; + else + line = pgm_read_byte(font + (c * 5) + i); + + if (size == 1) // default size + { + for (int8_t j = 0; j < 8; j++) { + if (line & 0x1) drawPixel(x + i, y + j, color); + line >>= 1; + } + } + else { // big size + for (int8_t j = 0; j < 8; j++) { + if (line & 0x1) fillRect(x + (i * size), y + (j * size), size, size, color); + else if (fillbg) fillRect(x + i * size, y + j * size, size, size, bg); + line >>= 1; + } + } + } + } + +//>>>>>>>>>>>>>>>>>>>>>>>>>>> +#ifdef LOAD_GFXFF + } else { // Custom font +#endif +//>>>>>>>>>>>>>>>>>>>>>>>>>>> +#endif // LOAD_GLCD + +#ifdef LOAD_GFXFF + // Filter out bad characters not present in font + if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) + { +//>>>>>>>>>>>>>>>>>>>>>>>>>>> + + c -= pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); + uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); + + uint32_t bo = pgm_read_word(&glyph->bitmapOffset); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + //xa = pgm_read_byte(&glyph->xAdvance); + int8_t xo = pgm_read_byte(&glyph->xOffset), + yo = pgm_read_byte(&glyph->yOffset); + uint8_t xx, yy, bits=0, bit=0; + int16_t xo16 = 0, yo16 = 0; + + if(size > 1) { + xo16 = xo; + yo16 = yo; + } + + uint16_t hpc = 0; // Horizontal foreground pixel count + for(yy=0; yy>= 1; + } + // Draw pixels for this line as we are about to increment yy + if (hpc) { + if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); + else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); + hpc=0; + } + } + } +#endif + + +#ifdef LOAD_GLCD + #ifdef LOAD_GFXFF + } // End classic vs custom font + #endif +#endif + +} + + +/*************************************************************************************** +** Function name: drawChar +** Description: draw a unicode onto the screen +*************************************************************************************x*/ + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y) +{ + return drawChar(uniCode, x, y, textfont); +} + + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSprite::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) +{ + if (!_created ) return 0; + + if (!uniCode) return 0; + + if (font==1) + { +#ifdef LOAD_GLCD + #ifndef LOAD_GFXFF + drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); + return 6 * textsize; + #endif +#else + #ifndef LOAD_GFXFF + return 0; + #endif +#endif + +#ifdef LOAD_GFXFF + drawChar(x, y, uniCode, textcolor, textbgcolor, textsize); + if(!gfxFont) { // 'Classic' built-in font + #ifdef LOAD_GLCD + return 6 * textsize; + #else + return 0; + #endif + } + else + { + if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) + { + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + return pgm_read_byte(&glyph->xAdvance) * textsize; + } + else + { + return 0; + } + } +#endif + } + + if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; + + int32_t width = 0; + int32_t height = 0; + uint32_t flash_address = 0; + uniCode -= 32; + +#ifdef LOAD_FONT2 + if (font == 2) + { + // This is faster than using the fontdata structure + flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); + width = pgm_read_byte(widtbl_f16 + uniCode); + height = chr_hgt_f16; + } + #ifdef LOAD_RLE + else + #endif +#endif + +#ifdef LOAD_RLE + { + if ((font>2) && (font<9)) + { + // This is slower than above but is more convenient for the RLE fonts + flash_address = pgm_read_dword( (const void*) (pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *)) ); + width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); + height= pgm_read_byte( &fontdata[font].height ); + } + } +#endif + + int32_t w = width; + int32_t pX = 0; + int32_t pY = y; + uint8_t line = 0; + +#ifdef LOAD_FONT2 // chop out code if we do not need it + if (font == 2) { + w = w + 6; // Should be + 7 but we need to compensate for width increment + w = w / 8; + if (x + width * textsize >= _iwidth) return width * textsize ; + + for (int32_t i = 0; i < height; i++) + { + if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); + + for (int32_t k = 0; k < w; k++) + { + line = pgm_read_byte((uint8_t *)flash_address + w * i + k); + if (line) { + if (textsize == 1) { + pX = x + k * 8; + if (line & 0x80) drawPixel(pX, pY, textcolor); + if (line & 0x40) drawPixel(pX + 1, pY, textcolor); + if (line & 0x20) drawPixel(pX + 2, pY, textcolor); + if (line & 0x10) drawPixel(pX + 3, pY, textcolor); + if (line & 0x08) drawPixel(pX + 4, pY, textcolor); + if (line & 0x04) drawPixel(pX + 5, pY, textcolor); + if (line & 0x02) drawPixel(pX + 6, pY, textcolor); + if (line & 0x01) drawPixel(pX + 7, pY, textcolor); + } + else { + pX = x + k * 8 * textsize; + if (line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor); + if (line & 0x40) fillRect(pX + textsize, pY, textsize, textsize, textcolor); + if (line & 0x20) fillRect(pX + 2 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x10) fillRect(pX + 3 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x08) fillRect(pX + 4 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x04) fillRect(pX + 5 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x02) fillRect(pX + 6 * textsize, pY, textsize, textsize, textcolor); + if (line & 0x01) fillRect(pX + 7 * textsize, pY, textsize, textsize, textcolor); + } + } + } + pY += textsize; + } + } + + #ifdef LOAD_RLE + else + #endif +#endif //FONT2 + +#ifdef LOAD_RLE //674 bytes of code + // Font is not 2 and hence is RLE encoded + { + w *= height; // Now w is total number of pixels in the character + + if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor); + int16_t color = textcolor; + if (_bpp == 16) color = (textcolor >> 8) | (textcolor << 8); + else if (_bpp == 8) color = ((textcolor & 0xE000)>>8 | (textcolor & 0x0700)>>6 | (textcolor & 0x0018)>>3); + int32_t px = 0, py = pY; // To hold character block start and end column and row values + int32_t pc = 0; // Pixel count + uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel + uint8_t tnp = 0; // Temporary copy of np for while loop + uint8_t ts = textsize - 1; // Temporary copy of textsize + // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area + // w is total number of pixels to plot to fill character block + while (pc < w) + { + line = pgm_read_byte((uint8_t *)flash_address); + flash_address++; // 20 bytes smaller by incrementing here + if (line & 0x80) { + line &= 0x7F; + line++; + if (ts) { + px = x + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow + py = y + textsize * (pc / width); + } + else { + px = x + pc % width; // Keep these px and py calculations outside the loop as they are slow + py = y + pc / width; + } + while (line--) { + pc++; + setWindow(px, py, px + ts, py + ts); + if (ts) { tnp = np; while (tnp--) writeColor(color); } + else writeColor(color); + + px += textsize; + + if (px >= (x + width * textsize)) + { + px = x; + py += textsize; + } + } + } + else { + line++; + pc += line; + } + } + } + // End of RLE font rendering +#endif + return width * textsize; // x + +} + +#ifdef SMOOTH_FONT +/*************************************************************************************** +** Function name: drawGlyph +** Description: Write a character to the sprite cursor position +*************************************************************************************x*/ +void TFT_eSprite::drawGlyph(uint16_t code) +{ + if (code < 0x21) + { + if (code == 0x20) { + if (_created) this->cursor_x += this->gFont.spaceWidth; + else this->cursor_x += this->gFont.spaceWidth; + return; + } + + if (code == '\n') { + if (_created) + { + this->cursor_x = 0; + this->cursor_y += this->gFont.yAdvance; + if (this->cursor_y >= _height) this->cursor_y = 0; + return; + } + else + { + cursor_x = 0; + cursor_y += gFont.yAdvance; + if (cursor_y >= _height) cursor_y = 0; + return; + } + } + } + + uint16_t gNum = 0; + bool found = this->getUnicodeIndex(code, &gNum); + + uint16_t fg = this->textcolor; + uint16_t bg = this->textbgcolor; + + if (found) + { + + bool newSprite = !_created; + + if (newSprite) + { + createSprite(this->gWidth[gNum], this->gFont.yAdvance); + if(bg) fillSprite(bg); + this->cursor_x = -this->gdX[gNum]; + this->cursor_y = 0; + } + + this->fontFile.seek(this->gBitmap[gNum], fs::SeekSet); // This is slow for a significant position shift! + + uint8_t pbuffer[this->gWidth[gNum]]; + + int16_t xs = 0; + uint16_t dl = 0; + + for (int32_t y = 0; y < this->gHeight[gNum]; y++) + { + this->fontFile.read(pbuffer, this->gWidth[gNum]); + for (int32_t x = 0; x < this->gWidth[gNum]; x++) + { + uint8_t pixel = pbuffer[x]; + if (pixel) + { + if (pixel != 0xFF) + { + if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } + if (_bpp != 1) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); + else if (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], fg); + } + else + { + if (dl==0) xs = x + this->cursor_x + this->gdX[gNum]; + dl++; + } + } + else + { + if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } + } + } + if (dl) { drawFastHLine( xs, y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], dl, fg); dl = 0; } + } + + if (newSprite) + { + pushSprite(this->cursor_x + this->gdX[gNum], this->cursor_y, bg); + deleteSprite(); + this->cursor_x += this->gxAdvance[gNum]; + } + else this->cursor_x += this->gxAdvance[gNum]; + } + else + { + // Not a Unicode in font so draw a rectangle and move on cursor + drawRect(this->cursor_x, this->cursor_y + this->gFont.maxAscent - this->gFont.ascent, this->gFont.spaceWidth, this->gFont.ascent, fg); + this->cursor_x += this->gFont.spaceWidth + 1; + } +} + + +/*************************************************************************************** +** Function name: printToSprite +** Description: Write a string to the sprite cursor position +*************************************************************************************x*/ +void TFT_eSprite::printToSprite(String string) +{ + if(!this->fontLoaded) return; + uint16_t len = string.length(); + char cbuffer[len + 1]; // Add 1 for the null + string.toCharArray(cbuffer, len + 1); // Add 1 for the null, otherwise characters get dropped + printToSprite(cbuffer, len); + //printToSprite((char*)string.c_str(), string.length()); +} + + +/*************************************************************************************** +** Function name: printToSprite +** Description: Write a string to the sprite cursor position +*************************************************************************************x*/ +void TFT_eSprite::printToSprite(char *cbuffer, uint16_t len) //String string) +{ + if(!this->fontLoaded) return; + + //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); + + if(!this->fontFile) + { + this->fontLoaded = false; + return; + } + + uint16_t n = 0; + bool newSprite = !_created; + + if (newSprite) + { + int16_t sWidth = 0; + uint16_t index = 0; + + while (n < len) + { + uint16_t unicode = decodeUTF8((uint8_t*)cbuffer, &n, len - n); + if (this->getUnicodeIndex(unicode, &index)) + { + if (n == 0) sWidth -= this->gdX[index]; + if (n == len-1) sWidth += ( this->gWidth[index] + this->gdX[index]); + else sWidth += this->gxAdvance[index]; + } + else sWidth += this->gFont.spaceWidth + 1; + } + + createSprite(sWidth, this->gFont.yAdvance); + + if (this->textbgcolor != TFT_BLACK) fillSprite(this->textbgcolor); + } + + n = 0; + + while (n < len) + { + uint16_t unicode = decodeUTF8((uint8_t*)cbuffer, &n, len - n); + //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); + //Serial.print("n = ");Serial.println(n); + drawGlyph(unicode); + } + + if (newSprite) + { // The sprite had to be created so place at TFT cursor + pushSprite(_tft->cursor_x, _tft->cursor_y); + deleteSprite(); + } + + //fontFile.close(); +} + + +/*************************************************************************************** +** Function name: printToSprite +** Description: Print character in a Sprite, create sprite if needed +*************************************************************************************x*/ +int16_t TFT_eSprite::printToSprite(int16_t x, int16_t y, uint16_t index) +{ + bool newSprite = !_created; + int16_t sWidth = this->gWidth[index]; + + if (newSprite) + { + createSprite(sWidth, this->gFont.yAdvance); + + if (this->textbgcolor != TFT_BLACK) fillSprite(this->textbgcolor); + + drawGlyph(this->gUnicode[index]); + + pushSprite(x + this->gdX[index], y, this->textbgcolor); + deleteSprite(); + } + + else drawGlyph(this->gUnicode[index]); + + return this->gxAdvance[index]; +} +#endif diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h new file mode 100644 index 0000000..5dea24e --- /dev/null +++ b/Extensions/Sprite.h @@ -0,0 +1,146 @@ +/*************************************************************************************** +// The following class creates Sprites in RAM, graphics can then be drawn in the Sprite +// and rendered quickly onto the TFT screen. The class inherits the graphics functions +// from the TFT_eSPI class. Some functions are overridden by this class so that the +// graphics are written to the Sprite rather than the TFT. +***************************************************************************************/ + +class TFT_eSprite : public TFT_eSPI { + + public: + + TFT_eSprite(TFT_eSPI *tft); + + // Create a sprite of width x height pixels, return a pointer to the RAM area + // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed + // RAM required is 1 byte per pixel for 8 bit colour depth, 2 bytes for 16 bit + void* createSprite(int16_t width, int16_t height, uint8_t frames = 1); + + // Delete the sprite to free up the RAM + void deleteSprite(void); + + // Select the frame buffer for graphics + void* frameBuffer(int8_t f); + + // Set or get the colour depth to 8 or 16 bits. Can be used to change depth an existing + // sprite, but clears it to black, returns a new pointer if sprite is re-created. + void* setColorDepth(int8_t b); + int8_t getColorDepth(void); + + void setBitmapColor(uint16_t c, uint16_t b); + + void drawPixel(int32_t x, int32_t y, uint32_t color); + + void drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), + + fillSprite(uint32_t color), + + // Define a window to push 16 bit colour pixels into in a raster order + // Colours are converted to 8 bit if depth is set to 8 + setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1), + pushColor(uint32_t color), + pushColor(uint32_t color, uint16_t len), + // Push a pixel preformatted as a 8 or 16 bit colour (avoids conversion overhead) + writeColor(uint16_t color), + + // Set the scroll zone, top left corner at x,y with defined width and height + // The colour (optional, black is default) is used to fill the gap after the scroll + setScrollRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t color = TFT_BLACK), + // Scroll the defined zone dx,dy pixels. Negative values left,up, positive right,down + // dy is optional (default is then no up/down scroll). + // The sprite coordinate frame does not move because pixels are moved + scroll(int16_t dx, int16_t dy = 0), + + drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), + drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), + drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), + + fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); + + // Set the sprite text cursor position for print class (does not change the TFT screen cursor) + //setCursor(int16_t x, int16_t y); + + // Set the rotation of the Sprite (for 1bpp Sprites only) + void setRotation(uint8_t rotation); + uint8_t getRotation(void); + + // Push a rotated copy of Sprite to TFT with optional transparent colour + bool pushRotated(int16_t angle, int32_t transp = -1); + // Push a rotated copy of Sprite to another different Sprite with optional transparent colour + bool pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp = -1); + // Set and get the pivot point for this Sprite + void setPivot(int16_t x, int16_t y); + int16_t getPivotX(void), + getPivotY(void); + + // Get the bounding box for a rotated copy of this Sprite + void getRotatedBounds(float sina, float cosa, int16_t w, int16_t h, int16_t xp, int16_t yp, + int16_t *min_x, int16_t *min_y, int16_t *max_x, int16_t *max_y); + + // Read the colour of a pixel at x,y and return value in 565 format + uint16_t readPixel(int32_t x0, int32_t y0); + + // Write an image (colour bitmap) to the sprite + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); + + // Swap the byte order for pushImage() - corrects different image endianness + void setSwapBytes(bool swap); + bool getSwapBytes(void); + + // Push the sprite to the TFT screen, this fn calls pushImage() in the TFT class. + // Optionally a "transparent" colour can be defined, pixels of that colour will not be rendered + void pushSprite(int32_t x, int32_t y); + void pushSprite(int32_t x, int32_t y, uint16_t transparent); + + int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y); + + // Return the width and height of the sprite + int16_t width(void), + height(void); + + // Used by print class to print text to cursor position + size_t write(uint8_t); + + // Functions associated with anti-aliased fonts + void drawGlyph(uint16_t code); + void printToSprite(String string); + void printToSprite(char *cbuffer, uint16_t len); + int16_t printToSprite(int16_t x, int16_t y, uint16_t index); + + private: + + TFT_eSPI *_tft; + + // Reserve memory for the Sprite and return a pointer + void* callocSprite(int16_t width, int16_t height, uint8_t frames = 1); + + protected: + + uint8_t _bpp; // bits per pixel (1, 8 or 16) + uint16_t *_img; // pointer to 16 bit sprite + uint8_t *_img8; // pointer to 8 bit sprite + uint8_t *_img8_1; // pointer to frame 1 + uint8_t *_img8_2; // pointer to frame 2 + + int16_t _xpivot; // x pivot point coordinate + int16_t _ypivot; // y pivot point coordinate + + bool _created; // A Sprite has been created and memory reserved + bool _gFont = false; + +// int32_t _icursor_x, _icursor_y; + uint8_t _rotation = 0; + int32_t _xs, _ys, _xe, _ye, _xptr, _yptr; // for setWindow + int32_t _sx, _sy; // x,y for scroll zone + uint32_t _sw, _sh; // w,h for scroll zone + uint32_t _scolor; // gap fill colour for scroll zone + + boolean _iswapBytes; // Swap the byte order for Sprite pushImage() + + int32_t _iwidth, _iheight; // Sprite memory image bit width and height (swapped during rotations) + int32_t _dwidth, _dheight; // Real display width and height (for <8bpp Sprites) + int32_t _bitwidth; // Sprite image bit width for drawPixel (for <8bpp Sprites, not swapped) + +}; diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp new file mode 100644 index 0000000..cb253be --- /dev/null +++ b/Extensions/Touch.cpp @@ -0,0 +1,305 @@ +// The following touch screen support code by maxpautsch was merged 1/10/17 +// https://github.com/maxpautsch + +// Define TOUCH_CS is the user setup file to enable this code + +// A demo is provided in examples Generic folder + +// Additions by Bodmer to double sample, use Z value to improve detection reliability +// and to correct rotation handling + +// See license in root directory. + +/*************************************************************************************** +** Function name: getTouchRaw +** Description: read raw touch position. Always returns true. +***************************************************************************************/ +uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ + uint16_t tmp; + + spi_begin_touch(); + + // Start YP sample request for x position, read 4 times and keep last sample + spi.transfer(0xd0); // Start new YP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0xd0); // Read last 8 bits and start new YP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0xd0); // Read last 8 bits and start new YP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0xd0); // Read last 8 bits and start new YP conversion + + tmp = spi.transfer(0); // Read first 8 bits + tmp = tmp <<5; + tmp |= 0x1f & (spi.transfer(0x90)>>3); // Read last 8 bits and start new XP conversion + + *x = tmp; + + // Start XP sample request for y position, read 4 times and keep last sample + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + spi.transfer(0); // Read first 8 bits + spi.transfer(0x90); // Read last 8 bits and start new XP conversion + + tmp = spi.transfer(0); // Read first 8 bits + tmp = tmp <<5; + tmp |= 0x1f & (spi.transfer(0)>>3); // Read last 8 bits + + *y = tmp; + + spi_end_touch(); + + return true; +} + +/*************************************************************************************** +** Function name: getTouchRawZ +** Description: read raw pressure on touchpad and return Z value. +***************************************************************************************/ +uint16_t TFT_eSPI::getTouchRawZ(void){ + + spi_begin_touch(); + + // Z sample request + int16_t tz = 0xFFF; + spi.transfer(0xb0); // Start new Z1 conversion + tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion + tz -= spi.transfer16(0x00) >> 3; // Read Z2 + + spi_end_touch(); + + return (uint16_t)tz; +} + +/*************************************************************************************** +** Function name: validTouch +** Description: read validated position. Return false if not pressed. +***************************************************************************************/ +#define _RAWERR 20 // Deadband error allowed in successive position samples +uint8_t TFT_eSPI::validTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ + uint16_t x_tmp, y_tmp, x_tmp2, y_tmp2; + + // Wait until pressure stops increasing to debounce pressure + uint16_t z1 = 1; + uint16_t z2 = 0; + while (z1 > z2) + { + z2 = z1; + z1 = getTouchRawZ(); + delay(1); + } + + // Serial.print("Z = ");Serial.println(z1); + + if (z1 <= threshold) return false; + + getTouchRaw(&x_tmp,&y_tmp); + + // Serial.print("Sample 1 x,y = "); Serial.print(x_tmp);Serial.print(",");Serial.print(y_tmp); + // Serial.print(", Z = ");Serial.println(z1); + + delay(1); // Small delay to the next sample + if (getTouchRawZ() <= threshold) return false; + + delay(2); // Small delay to the next sample + getTouchRaw(&x_tmp2,&y_tmp2); + + // Serial.print("Sample 2 x,y = "); Serial.print(x_tmp2);Serial.print(",");Serial.println(y_tmp2); + // Serial.print("Sample difference = ");Serial.print(abs(x_tmp - x_tmp2));Serial.print(",");Serial.println(abs(y_tmp - y_tmp2)); + + if (abs(x_tmp - x_tmp2) > _RAWERR) return false; + if (abs(y_tmp - y_tmp2) > _RAWERR) return false; + + *x = x_tmp; + *y = y_tmp; + + return true; +} + +/*************************************************************************************** +** Function name: getTouch +** Description: read callibrated position. Return false if not pressed. +***************************************************************************************/ +#define Z_THRESHOLD 350 // Touch pressure threshold for validating touches +uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y, uint16_t threshold){ + uint16_t x_tmp, y_tmp; + + if (threshold<20) threshold = 20; + if (_pressTime > millis()) threshold=20; + + uint8_t n = 5; + uint8_t valid = 0; + while (n--) + { + if (validTouch(&x_tmp, &y_tmp, threshold)) valid++;; + } + + if (valid<1) { _pressTime = 0; return false; } + + _pressTime = millis() + 50; + + convertRawXY(&x_tmp, &y_tmp); + + if (x_tmp >= _width || y_tmp >= _height) return false; + + _pressX = x_tmp; + _pressY = y_tmp; + *x = _pressX; + *y = _pressY; + return valid; +} + +/*************************************************************************************** +** Function name: convertRawXY +** Description: convert raw touch x,y values to screen coordinates +***************************************************************************************/ +void TFT_eSPI::convertRawXY(uint16_t *x, uint16_t *y) +{ + uint16_t x_tmp = *x, y_tmp = *y, xx, yy; + + if(!touchCalibration_rotate){ + xx=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1; + yy=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1; + if(touchCalibration_invert_x) + xx = _width - xx; + if(touchCalibration_invert_y) + yy = _height - yy; + } else { + xx=(y_tmp-touchCalibration_x0)*_width/touchCalibration_x1; + yy=(x_tmp-touchCalibration_y0)*_height/touchCalibration_y1; + if(touchCalibration_invert_x) + xx = _width - xx; + if(touchCalibration_invert_y) + yy = _height - yy; + } + *x = xx; + *y = yy; +} + +/*************************************************************************************** +** Function name: calibrateTouch +** Description: generates calibration parameters for touchscreen. +***************************************************************************************/ +void TFT_eSPI::calibrateTouch(uint16_t *parameters, uint32_t color_fg, uint32_t color_bg, uint8_t size){ + int16_t values[] = {0,0,0,0,0,0,0,0}; + uint16_t x_tmp, y_tmp; + + + + for(uint8_t i = 0; i<4; i++){ + fillRect(0, 0, size+1, size+1, color_bg); + fillRect(0, _height-size-1, size+1, size+1, color_bg); + fillRect(_width-size-1, 0, size+1, size+1, color_bg); + fillRect(_width-size-1, _height-size-1, size+1, size+1, color_bg); + + if (i == 5) break; // used to clear the arrows + + switch (i) { + case 0: // up left + drawLine(0, 0, 0, size, color_fg); + drawLine(0, 0, size, 0, color_fg); + drawLine(0, 0, size , size, color_fg); + break; + case 1: // bot left + drawLine(0, _height-size-1, 0, _height-1, color_fg); + drawLine(0, _height-1, size, _height-1, color_fg); + drawLine(size, _height-size-1, 0, _height-1 , color_fg); + break; + case 2: // up right + drawLine(_width-size-1, 0, _width-1, 0, color_fg); + drawLine(_width-size-1, size, _width-1, 0, color_fg); + drawLine(_width-1, size, _width-1, 0, color_fg); + break; + case 3: // bot right + drawLine(_width-size-1, _height-size-1, _width-1, _height-1, color_fg); + drawLine(_width-1, _height-1-size, _width-1, _height-1, color_fg); + drawLine(_width-1-size, _height-1, _width-1, _height-1, color_fg); + break; + } + + // user has to get the chance to release + if(i>0) delay(1000); + + for(uint8_t j= 0; j<8; j++){ + // Use a lower detect threshold as corners tend to be less sensitive + while(!validTouch(&x_tmp, &y_tmp, Z_THRESHOLD/2)); + values[i*2 ] += x_tmp; + values[i*2+1] += y_tmp; + } + values[i*2 ] /= 8; + values[i*2+1] /= 8; + } + + + // from case 0 to case 1, the y value changed. + // If the measured delta of the touch x axis is bigger than the delta of the y axis, the touch and TFT axes are switched. + touchCalibration_rotate = false; + if(abs(values[0]-values[2]) > abs(values[1]-values[3])){ + touchCalibration_rotate = true; + touchCalibration_x0 = (values[1] + values[3])/2; // calc min x + touchCalibration_x1 = (values[5] + values[7])/2; // calc max x + touchCalibration_y0 = (values[0] + values[4])/2; // calc min y + touchCalibration_y1 = (values[2] + values[6])/2; // calc max y + } else { + touchCalibration_x0 = (values[0] + values[2])/2; // calc min x + touchCalibration_x1 = (values[4] + values[6])/2; // calc max x + touchCalibration_y0 = (values[1] + values[5])/2; // calc min y + touchCalibration_y1 = (values[3] + values[7])/2; // calc max y + } + + // in addition, the touch screen axis could be in the opposite direction of the TFT axis + touchCalibration_invert_x = false; + if(touchCalibration_x0 > touchCalibration_x1){ + values[0]=touchCalibration_x0; + touchCalibration_x0 = touchCalibration_x1; + touchCalibration_x1 = values[0]; + touchCalibration_invert_x = true; + } + touchCalibration_invert_y = false; + if(touchCalibration_y0 > touchCalibration_y1){ + values[0]=touchCalibration_y0; + touchCalibration_y0 = touchCalibration_y1; + touchCalibration_y1 = values[0]; + touchCalibration_invert_y = true; + } + + // pre calculate + touchCalibration_x1 -= touchCalibration_x0; + touchCalibration_y1 -= touchCalibration_y0; + + if(touchCalibration_x0 == 0) touchCalibration_x0 = 1; + if(touchCalibration_x1 == 0) touchCalibration_x1 = 1; + if(touchCalibration_y0 == 0) touchCalibration_y0 = 1; + if(touchCalibration_y1 == 0) touchCalibration_y1 = 1; + + // export parameters, if pointer valid + if(parameters != NULL){ + parameters[0] = touchCalibration_x0; + parameters[1] = touchCalibration_x1; + parameters[2] = touchCalibration_y0; + parameters[3] = touchCalibration_y1; + parameters[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2); + } +} + + +/*************************************************************************************** +** Function name: setTouch +** Description: imports calibration parameters for touchscreen. +***************************************************************************************/ +void TFT_eSPI::setTouch(uint16_t *parameters){ + touchCalibration_x0 = parameters[0]; + touchCalibration_x1 = parameters[1]; + touchCalibration_y0 = parameters[2]; + touchCalibration_y1 = parameters[3]; + + if(touchCalibration_x0 == 0) touchCalibration_x0 = 1; + if(touchCalibration_x1 == 0) touchCalibration_x1 = 1; + if(touchCalibration_y0 == 0) touchCalibration_y0 = 1; + if(touchCalibration_y1 == 0) touchCalibration_y1 = 1; + + touchCalibration_rotate = parameters[4] & 0x01; + touchCalibration_invert_x = parameters[4] & 0x02; + touchCalibration_invert_y = parameters[4] & 0x04; +} diff --git a/Extensions/Touch.h b/Extensions/Touch.h new file mode 100644 index 0000000..de4ade7 --- /dev/null +++ b/Extensions/Touch.h @@ -0,0 +1,33 @@ + // Coded by Bodmer 10/2/18, see license in root directory. + // This is part of the TFT_eSPI class and is associated with the Touch Screen handlers + + public: + // Get raw x,y ADC values from touch controller + uint8_t getTouchRaw(uint16_t *x, uint16_t *y); + // Get raw z (i.e. pressure) ADC value from touch controller + uint16_t getTouchRawZ(void); + // Convert raw x,y values to calibrated and correctly rotated screen coordinates + void convertRawXY(uint16_t *x, uint16_t *y); + // Get the screen touch coordinates, returns true if screen has been touched + // if the touch cordinates are off screen then x and y are not updated + uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + + // Run screen calibration and test, report calibration values to the serial port + void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size); + // Set the screen calibration values + void setTouch(uint16_t *data); + + private: + // Handlers for the SPI settings and clock speed change + inline void spi_begin_touch() __attribute__((always_inline)); + inline void spi_end_touch() __attribute__((always_inline)); + + // Private function to validate a touch, allow settle time and reduce spurious coordinates + uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + + // Initialise with example calibration values so processor does not crash if setTouch() not called in setup() + uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600; + uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0; + + uint32_t _pressTime; // Press and hold time-out + uint16_t _pressX, _pressY; // For future use (last sampled calibrated coordinates) diff --git a/Fonts/Font16.c b/Fonts/Font16.c index a69c2c1..0f9167f 100644 --- a/Fonts/Font16.c +++ b/Fonts/Font16.c @@ -15,7 +15,8 @@ PROGMEM const unsigned char widtbl_f16[96] = // character width table 8, 4, 8, 8, 7, 10, 8, 8, // char 72 - 79 8, 8, 8, 8, 8, 8, 8, 10, // char 80 - 87 8, 8, 8, 4, 7, 4, 7, 9, // char 88 - 95 - 4, 7, 7, 7, 7, 7, 6, 7, // char 96 - 103 +// 4, 7, 7, 7, 7, 7, 6, 7, // char 96 - 103 grave see lines 411-414 + 5, 7, 7, 7, 7, 7, 6, 7, // char 96 - 103 celcius 7, 4, 5, 6, 4, 8, 7, 8, // char 104 - 111 7, 8, 6, 6, 5, 7, 8, 8, // char 112 - 119 6, 7, 7, 5, 3, 5, 8, 6 // char 120 - 127 @@ -407,8 +408,10 @@ PROGMEM const unsigned char chr_f16_5F[32] = // 1 unsigned chars per row PROGMEM const unsigned char chr_f16_60[16] = // 1 unsigned char per row { - 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, // row 1 - 11 - 0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16 +// 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, // row 1 - 11 grave +// 0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16 + 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, // row 1 - 11 Celcius + 0x00, 0x00, 0x00, 0x00, 0x00 }; PROGMEM const unsigned char chr_f16_61[16] = // 1 unsigned char per row diff --git a/Fonts/Font72x53rle.c b/Fonts/Font72x53rle.c new file mode 100644 index 0000000..bcce9cb --- /dev/null +++ b/Fonts/Font72x53rle.c @@ -0,0 +1,247 @@ +// Font 8 +// +// This font has been 8 bit Run Length Encoded to save FLASH space +// +// It is a Arial 75 pixel height font intended to display large numbers +// Width for numerals reduced from 55 to 53 (to fit in 160 pixel screens) +// This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : - . +// All other characters print as a space + +#include + + +PROGMEM const unsigned char widtbl_f72[96] = // character width table +{ + 29, 29, 29, 29, 29, 29, 29, 29, // char 32 - 39 + 29, 29, 29, 29, 29, 29, 29, 29, // char 40 - 47 + 53, 53, 53, 53, 53, 53, 53, 53, // char 48 - 55 + 53, 53, 29, 29, 29, 29, 29, 29, // char 56 - 63 + 29, 29, 29, 29, 29, 29, 29, 29, // char 64 - 71 + 29, 29, 29, 29, 29, 29, 29, 29, // char 72 - 79 + 29, 29, 29, 29, 29, 29, 29, 29, // char 80 - 87 + 29, 29, 29, 29, 29, 29, 29, 29, // char 88 - 95 + 29, 29, 29, 29, 29, 29, 29, 29, // char 96 - 103 + 29, 29, 29, 29, 29, 29, 29, 29, // char 104 - 111 + 29, 29, 29, 29, 29, 29, 29, 29, // char 112 - 119 + 29, 29, 29, 29, 29, 29, 29, 29 // char 120 - 127 +}; + +// Row format, MSB left + +PROGMEM const unsigned char chr_f72_20[] = +{ +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +0x7E +}; + +PROGMEM const unsigned char chr_f72_2D[] = +{ +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +0x36, 0x91, 0x0A, 0x91, 0x0A, 0x91, 0x0A, 0x91, +0x0A, 0x91, 0x0A, 0x91, 0x0A, 0x91, 0x7F, 0x7F, +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x07 +}; + +PROGMEM const unsigned char chr_f72_2E[] = +{ +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x48, 0x88, +0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, +0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, +0x44 +}; + +PROGMEM const unsigned char chr_f72_30[] = +{ +0x7F, 0x68, 0x8A, 0x26, 0x90, 0x21, 0x94, 0x1D, 0x98, 0x1A, 0x9A, 0x18, 0x9C, 0x16, 0x9E, 0x14, +0xA0, 0x13, 0x8C, 0x06, 0x8C, 0x12, 0x8B, 0x0A, 0x8B, 0x10, 0x8A, 0x0E, 0x89, 0x10, 0x89, 0x10, +0x89, 0x0F, 0x88, 0x12, 0x88, 0x0E, 0x89, 0x12, 0x89, 0x0D, 0x88, 0x14, 0x88, 0x0C, 0x89, 0x14, +0x88, 0x0C, 0x88, 0x16, 0x88, 0x0B, 0x88, 0x16, 0x88, 0x0B, 0x88, 0x16, 0x88, 0x0A, 0x88, 0x18, +0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, +0x88, 0x09, 0x88, 0x18, 0x88, 0x08, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x08, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, +0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x0A, 0x88, 0x16, +0x88, 0x0B, 0x88, 0x16, 0x88, 0x0B, 0x88, 0x16, 0x88, 0x0B, 0x89, 0x14, 0x89, 0x0C, 0x88, 0x14, +0x88, 0x0D, 0x89, 0x12, 0x89, 0x0E, 0x88, 0x12, 0x88, 0x0F, 0x89, 0x10, 0x89, 0x0F, 0x8A, 0x0E, +0x8A, 0x10, 0x8B, 0x0A, 0x8B, 0x12, 0x8C, 0x06, 0x8C, 0x13, 0xA0, 0x14, 0x9E, 0x16, 0x9C, 0x18, +0x9A, 0x1A, 0x98, 0x1D, 0x94, 0x21, 0x90, 0x26, 0x8A, 0x49 +}; + +PROGMEM const unsigned char chr_f72_31[] = +{ +0x7F, 0x70, 0x85, 0x2D, 0x86, 0x2D, 0x86, 0x2C, 0x87, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, 0x29, +0x8A, 0x28, 0x8B, 0x27, 0x8C, 0x25, 0x8E, 0x24, 0x8F, 0x23, 0x90, 0x22, 0x91, 0x20, 0x93, 0x1E, +0x95, 0x1C, 0x8D, 0x00, 0x88, 0x1B, 0x8C, 0x02, 0x88, 0x1B, 0x8B, 0x03, 0x88, 0x1B, 0x8A, 0x04, +0x88, 0x1B, 0x88, 0x06, 0x88, 0x1B, 0x87, 0x07, 0x88, 0x1B, 0x85, 0x09, 0x88, 0x1B, 0x83, 0x0B, +0x88, 0x1B, 0x81, 0x0D, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x7B +}; + +PROGMEM const unsigned char chr_f72_32[] = +{ +0x7F, 0x67, 0x8A, 0x25, 0x92, 0x1F, 0x96, 0x1B, 0x9A, 0x18, 0x9C, 0x16, 0x9E, 0x14, 0xA0, 0x12, +0xA2, 0x10, 0x8E, 0x07, 0x8D, 0x0F, 0x8B, 0x0C, 0x8C, 0x0D, 0x8A, 0x10, 0x8A, 0x0D, 0x89, 0x12, +0x8A, 0x0B, 0x89, 0x14, 0x89, 0x0B, 0x89, 0x14, 0x89, 0x0B, 0x88, 0x16, 0x89, 0x0A, 0x88, 0x16, +0x89, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, 0x88, 0x18, 0x88, 0x0D, 0x84, 0x18, +0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, 0x2A, 0x88, 0x2A, 0x89, 0x2A, 0x89, 0x29, +0x89, 0x2A, 0x89, 0x29, 0x89, 0x29, 0x8A, 0x28, 0x8A, 0x28, 0x8B, 0x27, 0x8B, 0x27, 0x8B, 0x27, +0x8B, 0x27, 0x8B, 0x27, 0x8C, 0x26, 0x8C, 0x26, 0x8C, 0x26, 0x8C, 0x26, 0x8C, 0x25, 0x8C, 0x26, +0x8C, 0x26, 0x8C, 0x26, 0x8C, 0x26, 0x8C, 0x25, 0x8D, 0x25, 0x8D, 0x25, 0x8C, 0x26, 0x8C, 0x26, +0x8C, 0x27, 0x8B, 0x27, 0x8B, 0x27, 0x8A, 0x28, 0x8A, 0x29, 0x89, 0x29, 0x8A, 0x29, 0x89, 0x29, +0x89, 0x2A, 0xAA, 0x08, 0xAB, 0x08, 0xAB, 0x08, 0xAB, 0x07, 0xAC, 0x07, 0xAC, 0x07, 0xAC, 0x07, +0xAC, 0x07, 0xAC, 0x6E +}; + +PROGMEM const unsigned char chr_f72_33[] = +{ +0x7F, 0x67, 0x89, 0x27, 0x90, 0x21, 0x94, 0x1D, 0x97, 0x1B, 0x9A, 0x18, 0x9C, 0x16, 0x9E, 0x14, +0xA0, 0x13, 0x8C, 0x06, 0x8C, 0x12, 0x8B, 0x0A, 0x8B, 0x10, 0x8A, 0x0E, 0x89, 0x10, 0x89, 0x10, +0x89, 0x0F, 0x88, 0x12, 0x88, 0x0E, 0x89, 0x12, 0x89, 0x0D, 0x88, 0x14, 0x88, 0x0D, 0x88, 0x14, +0x88, 0x0C, 0x89, 0x14, 0x88, 0x0C, 0x88, 0x15, 0x88, 0x10, 0x84, 0x15, 0x88, 0x2B, 0x88, 0x2B, +0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2A, 0x89, 0x29, 0x89, 0x29, 0x89, 0x28, 0x8B, 0x26, 0x8C, 0x21, +0x91, 0x22, 0x8F, 0x24, 0x8D, 0x26, 0x8F, 0x23, 0x92, 0x21, 0x94, 0x1F, 0x95, 0x1E, 0x81, 0x07, +0x8C, 0x29, 0x8B, 0x2A, 0x8A, 0x2A, 0x89, 0x2B, 0x89, 0x2B, 0x89, 0x2A, 0x89, 0x2B, 0x88, 0x2B, +0x89, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x0B, 0x84, 0x1A, +0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x89, 0x18, 0x89, 0x07, 0x89, 0x18, 0x88, 0x09, 0x88, 0x18, +0x88, 0x09, 0x89, 0x16, 0x89, 0x09, 0x89, 0x15, 0x89, 0x0B, 0x89, 0x14, 0x89, 0x0B, 0x8A, 0x12, +0x89, 0x0D, 0x8A, 0x10, 0x8A, 0x0D, 0x8B, 0x0D, 0x8B, 0x0F, 0x8D, 0x07, 0x8D, 0x11, 0xA2, 0x12, +0xA0, 0x14, 0x9D, 0x17, 0x9B, 0x19, 0x99, 0x1C, 0x95, 0x20, 0x91, 0x26, 0x89, 0x4A +}; + +PROGMEM const unsigned char chr_f72_34[] = +{ +0x7F, 0x7F, 0x2A, 0x86, 0x2C, 0x87, 0x2B, 0x88, 0x2A, 0x89, 0x2A, 0x89, 0x29, 0x8A, 0x28, 0x8B, +0x27, 0x8C, 0x26, 0x8D, 0x26, 0x8D, 0x25, 0x8E, 0x24, 0x8F, 0x23, 0x90, 0x23, 0x90, 0x22, 0x91, +0x21, 0x92, 0x20, 0x93, 0x20, 0x93, 0x1F, 0x8A, 0x00, 0x88, 0x1E, 0x8A, 0x01, 0x88, 0x1D, 0x8A, +0x02, 0x88, 0x1C, 0x8B, 0x02, 0x88, 0x1C, 0x8A, 0x03, 0x88, 0x1B, 0x8A, 0x04, 0x88, 0x1A, 0x8A, +0x05, 0x88, 0x19, 0x8A, 0x06, 0x88, 0x19, 0x8A, 0x06, 0x88, 0x18, 0x8A, 0x07, 0x88, 0x17, 0x8A, +0x08, 0x88, 0x16, 0x8A, 0x09, 0x88, 0x16, 0x8A, 0x09, 0x88, 0x15, 0x8A, 0x0A, 0x88, 0x14, 0x8A, +0x0B, 0x88, 0x13, 0x8A, 0x0C, 0x88, 0x13, 0x8A, 0x0C, 0x88, 0x12, 0x8A, 0x0D, 0x88, 0x11, 0x8A, +0x0E, 0x88, 0x10, 0x8A, 0x0F, 0x88, 0x0F, 0x8B, 0x0F, 0x88, 0x0F, 0x8A, 0x10, 0x88, 0x0E, 0x8A, +0x11, 0x88, 0x0D, 0x8A, 0x12, 0x88, 0x0C, 0x8A, 0x13, 0x88, 0x0C, 0xAF, 0x04, 0xAF, 0x04, 0xAF, +0x04, 0xAF, 0x04, 0xAF, 0x04, 0xAF, 0x04, 0xAF, 0x04, 0xAF, 0x04, 0xAF, 0x23, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x75 +}; + +PROGMEM const unsigned char chr_f72_35[] = +{ +0x7F, 0x7F, 0x14, 0xA0, 0x13, 0xA0, 0x12, 0xA1, 0x12, 0xA1, 0x12, 0xA1, 0x12, 0xA1, 0x12, 0xA1, +0x11, 0xA2, 0x11, 0xA2, 0x11, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, 0x2A, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, +0x06, 0x88, 0x1A, 0x89, 0x03, 0x8E, 0x17, 0x88, 0x02, 0x92, 0x15, 0x88, 0x00, 0x96, 0x13, 0xA1, +0x11, 0xA3, 0x10, 0xA4, 0x0F, 0xA5, 0x0E, 0x8F, 0x07, 0x8E, 0x0D, 0x8C, 0x0D, 0x8C, 0x0B, 0x8B, +0x11, 0x8A, 0x0B, 0x8A, 0x13, 0x8A, 0x0A, 0x89, 0x15, 0x89, 0x0E, 0x84, 0x17, 0x89, 0x2A, 0x89, +0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x89, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x0B, 0x84, 0x1A, 0x88, 0x07, 0x88, 0x19, 0x88, +0x08, 0x89, 0x18, 0x88, 0x08, 0x89, 0x18, 0x88, 0x09, 0x88, 0x17, 0x89, 0x09, 0x89, 0x16, 0x88, +0x0A, 0x89, 0x15, 0x89, 0x0B, 0x89, 0x13, 0x89, 0x0C, 0x8A, 0x11, 0x8A, 0x0C, 0x8B, 0x0F, 0x8A, +0x0E, 0x8B, 0x0D, 0x8A, 0x10, 0x8D, 0x07, 0x8D, 0x10, 0xA2, 0x12, 0xA0, 0x14, 0x9E, 0x17, 0x9B, +0x19, 0x98, 0x1D, 0x95, 0x20, 0x90, 0x26, 0x8A, 0x4A +}; + +PROGMEM const unsigned char chr_f72_36[] = +{ +0x7F, 0x6A, 0x89, 0x26, 0x90, 0x21, 0x95, 0x1C, 0x98, 0x1A, 0x9A, 0x18, 0x9C, 0x16, 0x9E, 0x14, +0xA0, 0x12, 0x8D, 0x06, 0x8D, 0x10, 0x8B, 0x0B, 0x8B, 0x10, 0x8A, 0x0E, 0x8A, 0x0E, 0x89, 0x11, +0x89, 0x0D, 0x8A, 0x12, 0x89, 0x0C, 0x89, 0x13, 0x89, 0x0C, 0x88, 0x15, 0x88, 0x0B, 0x89, 0x15, +0x89, 0x0A, 0x88, 0x16, 0x89, 0x09, 0x89, 0x17, 0x88, 0x09, 0x88, 0x18, 0x84, 0x0D, 0x88, 0x2B, +0x87, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x0A, 0x88, 0x17, 0x87, 0x08, 0x8E, 0x14, +0x87, 0x06, 0x92, 0x11, 0x88, 0x04, 0x96, 0x0F, 0x88, 0x03, 0x98, 0x0E, 0x88, 0x02, 0x9A, 0x0D, +0x88, 0x01, 0x9C, 0x0C, 0x88, 0x00, 0x9E, 0x0B, 0x92, 0x07, 0x8E, 0x0A, 0x90, 0x0C, 0x8C, 0x09, +0x8E, 0x10, 0x8A, 0x09, 0x8D, 0x12, 0x8A, 0x08, 0x8C, 0x14, 0x89, 0x08, 0x8B, 0x16, 0x89, 0x07, +0x8A, 0x17, 0x89, 0x07, 0x89, 0x19, 0x88, 0x07, 0x89, 0x19, 0x88, 0x07, 0x89, 0x19, 0x89, 0x06, +0x88, 0x1B, 0x88, 0x06, 0x88, 0x1B, 0x88, 0x06, 0x88, 0x1B, 0x88, 0x06, 0x88, 0x1B, 0x88, 0x07, +0x87, 0x1B, 0x88, 0x07, 0x87, 0x1B, 0x88, 0x07, 0x87, 0x1B, 0x88, 0x07, 0x87, 0x1B, 0x88, 0x07, +0x88, 0x1A, 0x88, 0x08, 0x87, 0x19, 0x89, 0x08, 0x87, 0x19, 0x88, 0x09, 0x88, 0x18, 0x88, 0x09, +0x88, 0x17, 0x89, 0x0A, 0x88, 0x16, 0x88, 0x0B, 0x88, 0x15, 0x89, 0x0C, 0x88, 0x14, 0x89, 0x0C, +0x89, 0x12, 0x89, 0x0E, 0x89, 0x10, 0x8A, 0x0E, 0x8B, 0x0C, 0x8B, 0x10, 0x8C, 0x07, 0x8D, 0x12, +0xA1, 0x13, 0x9F, 0x15, 0x9D, 0x17, 0x9B, 0x1A, 0x97, 0x1D, 0x95, 0x21, 0x8F, 0x27, 0x89, 0x49 + +}; + +PROGMEM const unsigned char chr_f72_37[] = +{ +0x7F, 0x7F, 0x0D, 0xAB, 0x08, 0xAB, 0x08, 0xAB, 0x08, 0xAB, 0x08, 0xAB, 0x08, 0xAB, 0x08, 0xAB, +0x08, 0xAB, 0x08, 0xAA, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x87, 0x2B, 0x87, 0x2B, 0x87, 0x2B, 0x87, +0x2C, 0x87, 0x2B, 0x87, 0x2B, 0x87, 0x2C, 0x87, 0x2B, 0x87, 0x2B, 0x88, 0x2B, 0x87, 0x2B, 0x87, +0x2B, 0x88, 0x2B, 0x87, 0x2B, 0x88, 0x2B, 0x87, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2A, 0x88, +0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, +0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, +0x2B, 0x88, 0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2A, 0x89, +0x2A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x7F, 0x06 +}; + +PROGMEM const unsigned char chr_f72_38[] = +{ +0x7F, 0x68, 0x89, 0x26, 0x91, 0x20, 0x95, 0x1C, 0x99, 0x19, 0x9B, 0x17, 0x9D, 0x15, 0x9F, 0x13, +0xA1, 0x11, 0x8D, 0x07, 0x8C, 0x11, 0x8B, 0x0B, 0x8B, 0x0F, 0x8A, 0x0F, 0x8A, 0x0E, 0x89, 0x11, +0x89, 0x0E, 0x88, 0x13, 0x88, 0x0D, 0x89, 0x13, 0x89, 0x0C, 0x88, 0x15, 0x88, 0x0C, 0x88, 0x15, +0x88, 0x0C, 0x88, 0x15, 0x88, 0x0C, 0x88, 0x15, 0x88, 0x0C, 0x88, 0x15, 0x88, 0x0C, 0x88, 0x15, +0x88, 0x0C, 0x88, 0x15, 0x88, 0x0D, 0x88, 0x13, 0x88, 0x0E, 0x88, 0x13, 0x88, 0x0E, 0x89, 0x11, +0x89, 0x0F, 0x89, 0x0F, 0x89, 0x11, 0x89, 0x0D, 0x89, 0x13, 0x8B, 0x07, 0x8C, 0x14, 0x9D, 0x17, +0x9B, 0x1A, 0x97, 0x1E, 0x93, 0x1E, 0x96, 0x1B, 0x9A, 0x18, 0x9D, 0x15, 0x9F, 0x13, 0x8C, 0x07, +0x8C, 0x11, 0x8A, 0x0C, 0x8B, 0x0F, 0x8A, 0x0F, 0x8A, 0x0D, 0x8A, 0x11, 0x89, 0x0D, 0x89, 0x13, +0x89, 0x0B, 0x89, 0x15, 0x88, 0x0B, 0x89, 0x15, 0x89, 0x0A, 0x88, 0x17, 0x88, 0x0A, 0x88, 0x17, +0x88, 0x09, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, +0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x88, 0x19, +0x88, 0x08, 0x88, 0x19, 0x88, 0x08, 0x89, 0x17, 0x89, 0x09, 0x88, 0x17, 0x88, 0x0A, 0x89, 0x15, +0x89, 0x0A, 0x89, 0x15, 0x89, 0x0B, 0x89, 0x13, 0x89, 0x0C, 0x8A, 0x11, 0x8A, 0x0D, 0x8A, 0x0F, +0x8A, 0x0E, 0x8C, 0x0C, 0x8B, 0x0F, 0x8D, 0x07, 0x8D, 0x11, 0xA1, 0x13, 0x9F, 0x15, 0x9D, 0x17, +0x9B, 0x19, 0x99, 0x1C, 0x95, 0x20, 0x91, 0x26, 0x89, 0x4A +}; + +PROGMEM const unsigned char chr_f72_39[] = +{ +0x7F, 0x68, 0x88, 0x27, 0x90, 0x21, 0x94, 0x1E, 0x97, 0x1A, 0x9A, 0x18, 0x9C, 0x16, 0x9E, 0x14, +0xA0, 0x12, 0x8E, 0x07, 0x8B, 0x11, 0x8C, 0x0B, 0x8A, 0x0F, 0x8B, 0x0F, 0x88, 0x0F, 0x8A, 0x11, +0x88, 0x0D, 0x8A, 0x13, 0x88, 0x0C, 0x89, 0x14, 0x88, 0x0B, 0x89, 0x16, 0x87, 0x0B, 0x89, 0x17, +0x87, 0x0A, 0x88, 0x18, 0x87, 0x0A, 0x88, 0x18, 0x87, 0x09, 0x89, 0x19, 0x87, 0x08, 0x88, 0x1A, +0x87, 0x08, 0x88, 0x1A, 0x87, 0x08, 0x88, 0x1A, 0x87, 0x08, 0x88, 0x1A, 0x87, 0x08, 0x88, 0x1A, +0x87, 0x08, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, 0x88, 0x07, 0x88, 0x1A, +0x88, 0x07, 0x89, 0x18, 0x89, 0x08, 0x88, 0x18, 0x89, 0x08, 0x88, 0x18, 0x89, 0x08, 0x89, 0x16, +0x8A, 0x08, 0x89, 0x16, 0x8A, 0x09, 0x89, 0x14, 0x8B, 0x09, 0x8A, 0x12, 0x8C, 0x0A, 0x8A, 0x10, +0x8D, 0x0A, 0x8C, 0x0C, 0x8F, 0x0B, 0x8E, 0x07, 0x91, 0x0C, 0x9D, 0x00, 0x88, 0x0D, 0x9B, 0x01, +0x88, 0x0E, 0x99, 0x02, 0x88, 0x0F, 0x97, 0x03, 0x88, 0x10, 0x95, 0x04, 0x88, 0x11, 0x92, 0x06, +0x87, 0x14, 0x8E, 0x08, 0x87, 0x17, 0x88, 0x0A, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, 0x88, 0x2B, +0x87, 0x2B, 0x88, 0x0E, 0x84, 0x17, 0x88, 0x0A, 0x88, 0x17, 0x88, 0x0A, 0x89, 0x15, 0x88, 0x0B, +0x89, 0x15, 0x88, 0x0C, 0x88, 0x14, 0x89, 0x0C, 0x89, 0x13, 0x88, 0x0D, 0x89, 0x12, 0x89, 0x0E, +0x89, 0x10, 0x89, 0x0F, 0x8A, 0x0E, 0x8A, 0x0F, 0x8B, 0x0B, 0x8B, 0x11, 0x8C, 0x07, 0x8C, 0x13, +0x9F, 0x14, 0x9E, 0x16, 0x9C, 0x18, 0x9A, 0x1B, 0x97, 0x1D, 0x94, 0x21, 0x90, 0x26, 0x89, 0x4C +}; + +PROGMEM const unsigned char chr_f72_3A[] = +{ +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x23, 0x88, 0x13, +0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x13, +0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x7F, +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x33, 0x88, +0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, +0x13, 0x88, 0x13, 0x88, 0x13, 0x88, 0x13, 0x88, +0x44 +}; +PROGMEM const unsigned char * const chrtbl_f72[96] = // character pointer table +{ + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_2D, chr_f72_2E, chr_f72_20, + chr_f72_30, chr_f72_31, chr_f72_32, chr_f72_33, chr_f72_34, chr_f72_35, chr_f72_36, chr_f72_37, + chr_f72_38, chr_f72_39, chr_f72_3A, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, + chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20, chr_f72_20 +}; diff --git a/Fonts/Font72x53rle.h b/Fonts/Font72x53rle.h new file mode 100644 index 0000000..b7ce1c9 --- /dev/null +++ b/Fonts/Font72x53rle.h @@ -0,0 +1,10 @@ +#include + +#define nr_chrs_f72 96 +#define chr_hgt_f72 75 +#define baseline_f72 73 +#define data_size_f72 8 +#define firstchr_f72 32 + +extern const unsigned char widtbl_f72[96]; +extern const unsigned char* const chrtbl_f72[96]; diff --git a/Fonts/Font7srle.c b/Fonts/Font7srle.c index 6235093..bb292d7 100644 --- a/Fonts/Font7srle.c +++ b/Fonts/Font7srle.c @@ -12,7 +12,7 @@ PROGMEM const unsigned char widtbl_f7s[96] = // character width table { 12, 12, 12, 12, 12, 12, 12, 12, // char 32 - 39 - 12, 12, 12, 12, 12, 17, 12, 12, // char 40 - 47 + 12, 12, 12, 12, 12, 32, 12, 12, // char 40 - 47 32, 32, 32, 32, 32, 32, 32, 32, // char 48 - 55 32, 32, 12, 12, 12, 12, 12, 12, // char 56 - 63 12, 12, 12, 12, 12, 12, 12, 12, // char 64 - 71 @@ -32,10 +32,12 @@ PROGMEM const unsigned char chr_f7s_20[] = 0x7F, 0x7F, 0x7F, 0x7F, 0x3F }; +// Make - sign look like a segment PROGMEM const unsigned char chr_f7s_2D[] = { -0x7F, 0x7F, 0x45, 0x8A, 0x05, 0x8A, 0x05, 0x8A, -0x05, 0x8A, 0x7F, 0x7F, 0x7F, 0x2B +0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x27, 0x8E, 0x0E, +0x92, 0x0A, 0x96, 0x09, 0x94, 0x0C, 0x90, 0x7F, +0x7F, 0x7F, 0x7F, 0x7F, 0x47 }; PROGMEM const unsigned char chr_f7s_2E[] = diff --git a/Fonts/GFXFF/gfxfont.h b/Fonts/GFXFF/gfxfont.h index eae3997..cd2bccc 100644 --- a/Fonts/GFXFF/gfxfont.h +++ b/Fonts/GFXFF/gfxfont.h @@ -12,7 +12,7 @@ #ifdef LOAD_GFXFF typedef struct { // Data stored PER GLYPH - uint16_t bitmapOffset; // Pointer into GFXfont->bitmap + uint32_t bitmapOffset; // Pointer into GFXfont->bitmap uint8_t width, height; // Bitmap dimensions in pixels uint8_t xAdvance; // Distance to advance cursor (x axis) int8_t xOffset, yOffset; // Dist from cursor pos to UL corner @@ -21,7 +21,7 @@ typedef struct { // Data stored PER GLYPH typedef struct { // Data stored for FONT AS A WHOLE: uint8_t *bitmap; // Glyph bitmaps, concatenated GFXglyph *glyph; // Glyph array - uint8_t first, last; // ASCII extents + uint16_t first, last; // ASCII extents uint8_t yAdvance; // Newline distance (y axis) } GFXfont; diff --git a/README.md b/README.md index 54051fa..6852147 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,104 @@ + +# News + +1. Sprites can now by pushed to the screen (or another Sprite) with a rotation angle. The new function is pushRotated(). Three new examples (Rotate_Sprite_1/2/3) have been added to show how the functions can be used to rotate text, images and to draw animated dials with moving needles. + +2. A new TFT_eFEX support library has been created which includes extra functions such as drawing a BMP or Jpeg to the screen. This library will simplify the examples. It will be expanded at a future date to include meters, dials and GUI elements like progress bars, graphs and animated buttons: +https://github.com/Bodmer/TFT_eFEX + +3. androdlang has published a really nice companion library to extend the graphics capabilities of TFT_eSPI, you can find this here: +https://github.com/androdlang/TFTShape + +4. I have created a user updateable graphics extension library template that can be used to create your own graphics extensions. The Library contains examples and is commented so it should be clear what you need to do to add functions. You can find it here: +https://github.com/Bodmer/TFT_eFX + +5. The capability to read from an ST7789V TFT with a single bidirectional SDA pin has been added. At the moment this **ONLY** works with an ESP32. It is enabled with a #define TFT_SDA_READ in the setup file. + +6. ST7789V and ILI9341 displays are manufactured in two variants that have the red and blue pixels swapped, this is catered for by a new option in the setup file: + //#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue + //#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + # TFT_eSPI -An Arduino IDE compatible graphics and fonts library for ESP8266 processors with a driver for ILI9341, ILI9163, ST7735 and S6D02A1 based TFT displays that support SPI. +An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with drivers for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, ILI9488, HX8357D and ST7789 based TFT displays that support SPI. The library can be loaded using the Arduino IDE's Library Manager. -The library also supports TFT displays designed for the Raspberry Pi that are based on a ILI9486 driver chip with a 480 x 320 pixel screen. This display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral). +8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with an ESP32. -The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. The library has been tested with the NodeMCU (ESP8266 based) +The library supports TFT displays designed for the Raspberry Pi that are based on a ILI9486 driver chip with a 480 x 320 pixel screen. This display must be of the Waveshare design and use a 16 bit serial interface based on the 74HC04, 74HC4040 and 2 x 74HC4094 logic chips. A modification to these displays is possible (see mod image in Tools folder) to make many graphics functions much faster (e.g. 23ms to clear the screen, 1.2ms to draw a 72 pixel high numeral). -The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are a significant number of example sketches to demonstrate the different features. +Some displays permit the internal TFT screen RAM to be read. The library supports reading from ILI9341, ST7789 and ILI9488 SPI displays for the ESP32 and ESP8266. The 8 bit parallel displays used with the ESP32 can usually can be read too. The TFT_Screen_Capture example allows full screens to be captured and sent to a PC, this is handy to create program documentation. -Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder. Fonts and features can easily be disabled by commenting out lines. +Support has been added recently for Waveshare 2 and 3 colour ePaper displays using full frame buffers. This addition is currently relatively immature and thus only one example has been provided. Further examples will be added soon. + +The library includes a "Sprite" class, this enables flicker free updates of complex graphics. Direct writes to the TFT with graphics functions are still available, so existing sketches do not need to be changed. + +A Sprite is notionally an invisible graphics screen that is kept in the processors RAM. Graphics can be drawn into the Sprite just as they can be drawn directly to the screen. Once the Sprite is completed it can be plotted onto the screen in any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. Sprites by default use 16 bit colours, the bit depth can be set to 8 bits (256 colours) , or 1 bit (any 2 colours) to reduce the RAM needed. On an ESP8266 the largest 16 bit colour Sprite that can be created is about 160x128 pixels, this consumes 40Kbytes of RAM. On an ESP32 the workspace RAM is more limited than the datsheet implies so a 16 bit colour Sprite is limited to about 200x200 pixels (~80Kbytes), an 8 bit sprite to 320x240 pixels (~76kbytes). A 1 bit per pixel Sprite requires only 9600 bytes for a full 320 x 240 screen buffer, this is ideal for supporting use with 2 colour bitmap fonts. + +One or more sprites can be created, a sprite can be any pixel width and height, limited only by available RAM. The RAM needed for a 16 bit colour depth Sprite is (2 x width x height) bytes, for a Sprite with 8 bit colour depth the RAM needed is (width x height) bytes. Sprites can be created and deleted dynamically as needed in the sketch, this means RAM can be freed up after the Sprite has been plotted on the screen, more RAM intensive WiFi based code can then be run and normal graphics operations still work. + +Drawing graphics into a sprite is very fast, for those familiar with the Adafruit "graphicstest" example, this whole test completes in 18ms in a 160x128 sprite. Examples of sprite use can be found in the "examples/Sprite" folder. + +Sprites can be plotted to the TFT with one colour being specified as "transparent", see Transparent_Sprite_Demo example. + +If an ESP32 board has SPIRAM (i.e. PSRAM) fitted then Sprites will use the PSRAM memory and large full screen buffer Sprites can be created. Full screen Sprites take longer to render (~45ms for a 320 x 240 16 bit Sprite), so bear that in mind. + +The XPT2046 touch screen controller is supported. The SPI bus for the touch controller is shared with the TFT and only an additional chip select line is needed. + +The Button class from Adafruit_GFX is incorporated, with the enhancement that the button labels can be in any font. + +The library supports SPI overlap on the ESP8266 so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH, this frees up GPIO pins for other uses. + +The library contains proportional fonts, different sizes can be enabled/disabled at compile time to optimise the use of FLASH memory. Anti-alased (smooth) font files in vlw format stored in SPIFFS are supported. Any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. + +The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266/ESP32 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. + +Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting your own configuration in the "User_Setup_Selet,h" file. Fonts and features can easily be enabled/disabled by commenting out lines. + + +# Anti-aliased Fonts + +Anti-aliased (smooth) font files in "vlw" format are generated by the free [Processing IDE](https://processing.org/) using a sketch included in the library Tools folder. This sketch with the Processing IDE can be used to generate font files from your computer's font set or any TrueType (.ttf) font, the font file can include **any** combination of 16 bit Unicode characters. This means Greek, Japanese and any other UCS-2 glyphs can be used. Character arrays and Strings in UTF-8 format are supported. + +Here is the Adafruit_GFX "FreeSans12pt" bitmap font compared to the same font drawn as anti-aliased: + +![Smooth_font](https://i.imgur.com/gAeDPFY.png) + +The smooth font example displays the following screen: + +![Example](https://i.imgur.com/xJF0Oz7.png) + +It would be possible to compress the vlw font files but the rendering performance to a TFT is still good when storing the font file(s) in SPIFFS. + +Here is an example screenshot showing the anti-aliased Hiragana character Unicode block (0x3041 to 0x309F) in 24pt from the Microsoft Yahei font: + +![Hiragana glyphs](https://i.imgur.com/jeXf2st.png) + + + +# ESP32 with 8 bit Mcufriend UNO shields + +The ESP32 board I have been using for testing has the following pinout: + +![Example](https://i.imgur.com/bvM6leE.jpg) + +UNO style boards with a Wemos R32(ESP32) label are also available at low cost with the same pin-out. + +Unfortunately the typical UNO/mcufriend TFT display board maps LCD_RD, LCD_CS and LCD_RST signals to the ESP32 analogue pins 35, 34 and 36 which are input only. To solve this I linked in the 3 spare pins IO15, IO33 and IO32 by adding wires to the bottom of the board as follows: + +IO15 wired to IO35 + +IO33 wired to IO34 + +IO32 wired to IO36 + +![Example](https://i.imgur.com/pUZn6lF.jpg) + +If the display board is fitted with a resistance based touch screen then this can be used by performing the modifications described here and the fork of the Adafruit library: +https://github.com/s60sc/Adafruit_TouchScreen + +# ePaper displays + +The library was intended to support only TFT displays but using a Sprite as a 1 bit per pixel screen buffer permits support for the Waveshare 2 and 3 colour SPI ePaper displays. This addition to the library is experimental and only one example is provided. Further examples will be added. + +![Example](https://i.imgur.com/L2tV129.jpg?1) diff --git a/README.txt b/README.txt index c7211cf..03ec449 100644 --- a/README.txt +++ b/README.txt @@ -5,10 +5,14 @@ This library has been derived from the Adafruit_GFX and driver library with further code from other authors. It is not compatible with legacy versions of the IDE (e.g. 1.0.6 and -older. Use the latest 1.6.x version. +older. Use the latest version. New functions have been added in particular it contains proportional fonts in addition to the original Adafruit font. -Note: This version of the library might not be fully compatible with the original. +A sprite class has been added to aid the generation of flicker free complex +graphics. + +Note: This version of the library might not be fully compatible with the +original. diff --git a/TFT_Drivers/EPD_Defines.h b/TFT_Drivers/EPD_Defines.h new file mode 100644 index 0000000..6a6838c --- /dev/null +++ b/TFT_Drivers/EPD_Defines.h @@ -0,0 +1,27 @@ +// Null set for ePaper +#define TFT_WIDTH 1000 +#define TFT_HEIGHT 1000 + +#define TFT_INIT_DELAY 0 + +#define TFT_NOP 0x00 +#define TFT_SWRST 0x00 + +#define TFT_CASET 0x00 +#define TFT_PASET 0x00 +#define TFT_RAMWR 0x00 + +#define TFT_RAMRD 0x00 +#define TFT_IDXRD 0x00 + +#define TFT_MADCTL 0x00 +#define TFT_MAD_MY 0x00 +#define TFT_MAD_MX 0x00 +#define TFT_MAD_MV 0x00 +#define TFT_MAD_ML 0x00 +#define TFT_MAD_BGR 0x00 +#define TFT_MAD_MH 0x00 +#define TFT_MAD_RGB 0x00 + +#define TFT_INVOFF 0x00 +#define TFT_INVON 0x00 diff --git a/TFT_Drivers/HX8357D_Defines.h b/TFT_Drivers/HX8357D_Defines.h new file mode 100644 index 0000000..7dcbdad --- /dev/null +++ b/TFT_Drivers/HX8357D_Defines.h @@ -0,0 +1,86 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPar.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read + + +#define HX8357_NOP 0x00 +#define HX8357_SWRESET 0x01 +#define HX8357_RDDID 0x04 +#define HX8357_RDDST 0x09 + +#define HX8357_RDPOWMODE 0x0A +#define HX8357_RDMADCTL 0x0B +#define HX8357_RDCOLMOD 0x0C +#define HX8357_RDDIM 0x0D +#define HX8357_RDDSDR 0x0F + +#define HX8357_SLPIN 0x10 +#define HX8357_SLPOUT 0x11 + +#define HX8357_INVOFF 0x20 +#define HX8357_INVON 0x21 +#define HX8357_DISPOFF 0x28 +#define HX8357_DISPON 0x29 + +#define HX8357_CASET 0x2A +#define HX8357_PASET 0x2B +#define HX8357_RAMWR 0x2C +#define HX8357_RAMRD 0x2E + +#define HX8357_TEON 0x35 +#define HX8357_TEARLINE 0x44 +#define HX8357_MADCTL 0x36 +#define HX8357_COLMOD 0x3A + +#define HX8357_SETOSC 0xB0 +#define HX8357_SETPWR1 0xB1 +#define HX8357_SETRGB 0xB3 +#define HX8357D_SETCOM 0xB6 + +#define HX8357D_SETCYC 0xB4 +#define HX8357D_SETC 0xB9 + +#define HX8357D_SETSTBA 0xC0 + +#define HX8357_SETPANEL 0xCC + +#define HX8357D_SETGAMMA 0xE0 diff --git a/TFT_Drivers/HX8357D_Init.h b/TFT_Drivers/HX8357D_Init.h new file mode 100644 index 0000000..50389bb --- /dev/null +++ b/TFT_Drivers/HX8357D_Init.h @@ -0,0 +1,118 @@ + +// This is the command sequence that initialises the HX8357D driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure HX8357D display + + // setextc + writecommand(HX8357D_SETC); + writedata(0xFF); + writedata(0x83); + writedata(0x57); + delay(300); + + // setRGB which also enables SDO + writecommand(HX8357_SETRGB); + writedata(0x80); //enable SDO pin! +// writedata(0x00); //disable SDO pin! + writedata(0x0); + writedata(0x06); + writedata(0x06); + + writecommand(HX8357D_SETCOM); + writedata(0x25); // -1.52V + + writecommand(HX8357_SETOSC); + writedata(0x68); // Normal mode 70Hz, Idle mode 55 Hz + + writecommand(HX8357_SETPANEL); //Set Panel + writedata(0x05); // BGR, Gate direction swapped + + writecommand(HX8357_SETPWR1); + writedata(0x00); // Not deep standby + writedata(0x15); //BT + writedata(0x1C); //VSPR + writedata(0x1C); //VSNR + writedata(0x83); //AP + writedata(0xAA); //FS + + writecommand(HX8357D_SETSTBA); + writedata(0x50); //OPON normal + writedata(0x50); //OPON idle + writedata(0x01); //STBA + writedata(0x3C); //STBA + writedata(0x1E); //STBA + writedata(0x08); //GEN + + writecommand(HX8357D_SETCYC); + writedata(0x02); //NW 0x02 + writedata(0x40); //RTN + writedata(0x00); //DIV + writedata(0x2A); //DUM + writedata(0x2A); //DUM + writedata(0x0D); //GDON + writedata(0x78); //GDOFF + + writecommand(HX8357D_SETGAMMA); + writedata(0x02); + writedata(0x0A); + writedata(0x11); + writedata(0x1d); + writedata(0x23); + writedata(0x35); + writedata(0x41); + writedata(0x4b); + writedata(0x4b); + writedata(0x42); + writedata(0x3A); + writedata(0x27); + writedata(0x1B); + writedata(0x08); + writedata(0x09); + writedata(0x03); + writedata(0x02); + writedata(0x0A); + writedata(0x11); + writedata(0x1d); + writedata(0x23); + writedata(0x35); + writedata(0x41); + writedata(0x4b); + writedata(0x4b); + writedata(0x42); + writedata(0x3A); + writedata(0x27); + writedata(0x1B); + writedata(0x08); + writedata(0x09); + writedata(0x03); + writedata(0x00); + writedata(0x01); + + writecommand(HX8357_COLMOD); + writedata(0x55); // 16 bit + + writecommand(HX8357_MADCTL); + writedata(0xC0); + + writecommand(HX8357_TEON); // TE off + writedata(0x00); + + writecommand(HX8357_TEARLINE); // tear line + writedata(0x00); + writedata(0x02); + + writecommand(HX8357_SLPOUT); //Exit Sleep + delay(150); + + writecommand(HX8357_DISPON); // display on + delay(50); + +// End of HX8357D display configuration + + + diff --git a/TFT_Drivers/HX8357D_Rotation.h b/TFT_Drivers/HX8357D_Rotation.h new file mode 100644 index 0000000..9df230b --- /dev/null +++ b/TFT_Drivers/HX8357D_Rotation.h @@ -0,0 +1,26 @@ + // This is the command sequence that rotates the ILI9481 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_RGB); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_RGB); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_RGB); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } diff --git a/TFT_Drivers/ILI9163_Rotation.h b/TFT_Drivers/ILI9163_Rotation.h index a78a9c4..3323169 100644 --- a/TFT_Drivers/ILI9163_Rotation.h +++ b/TFT_Drivers/ILI9163_Rotation.h @@ -7,8 +7,8 @@ switch (rotation) { case 0: writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; #ifdef CGRAM_OFFSET colstart = 0; rowstart = 0; @@ -16,8 +16,8 @@ break; case 1: writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; #ifdef CGRAM_OFFSET colstart = 0; rowstart = 0; @@ -25,8 +25,8 @@ break; case 2: writedata(TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; #ifdef CGRAM_OFFSET colstart = 0; rowstart = 32; @@ -34,8 +34,8 @@ break; case 3: writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; #ifdef CGRAM_OFFSET colstart = 32; rowstart = 0; diff --git a/TFT_Drivers/ILI9341_Defines.h b/TFT_Drivers/ILI9341_Defines.h index bc58b7f..b675bfc 100644 --- a/TFT_Drivers/ILI9341_Defines.h +++ b/TFT_Drivers/ILI9341_Defines.h @@ -51,6 +51,16 @@ #define TFT_MAD_MH 0x04 #define TFT_MAD_RGB 0x00 +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR +#endif + #define TFT_INVOFF 0x20 #define TFT_INVON 0x21 diff --git a/TFT_Drivers/ILI9341_Init.h b/TFT_Drivers/ILI9341_Init.h index c867e4e..7c763e0 100644 --- a/TFT_Drivers/ILI9341_Init.h +++ b/TFT_Drivers/ILI9341_Init.h @@ -55,7 +55,11 @@ writedata(0x86); //-- writecommand(ILI9341_MADCTL); // Memory Access Control - writedata(0x48); +#ifdef M5STACK + writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); // Rotation 0 (portrait mode) +#else + writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); // Rotation 0 (portrait mode) +#endif writecommand(ILI9341_PIXFMT); writedata(0x55); @@ -116,4 +120,5 @@ spi_begin(); writecommand(ILI9341_DISPON); //Display on + } \ No newline at end of file diff --git a/TFT_Drivers/ILI9341_Rotation.h b/TFT_Drivers/ILI9341_Rotation.h index c856dea..f31b9df 100644 --- a/TFT_Drivers/ILI9341_Rotation.h +++ b/TFT_Drivers/ILI9341_Rotation.h @@ -6,45 +6,77 @@ writecommand(TFT_MADCTL); switch (rotation) { case 0: - writedata(TFT_MAD_MX | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#ifdef M5STACK + writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_width; + _height = _init_height; break; case 1: - writedata(TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#ifdef M5STACK + writedata(TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_height; + _height = _init_width; break; case 2: - writedata(TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#ifdef M5STACK + writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_width; + _height = _init_height; break; case 3: - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#ifdef M5STACK + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_height; + _height = _init_width; break; - // These next rotations are for bottum up BMP drawing + // These next rotations are for bottom up BMP drawing case 4: - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#ifdef M5STACK + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_width; + _height = _init_height; break; case 5: - writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#ifdef M5STACK + writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_height; + _height = _init_width; break; case 6: - writedata(TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#ifdef M5STACK + writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_COLOR_ORDER); +#endif + _width = _init_width; + _height = _init_height; break; case 7: - writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#ifdef M5STACK + writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); +#else + writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); +#endif + _width = _init_height; + _height = _init_width; break; - } \ No newline at end of file + } diff --git a/TFT_Drivers/ILI9481_Defines.h b/TFT_Drivers/ILI9481_Defines.h new file mode 100644 index 0000000..bd5fb88 --- /dev/null +++ b/TFT_Drivers/ILI9481_Defines.h @@ -0,0 +1,42 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/ILI9481_Init.h b/TFT_Drivers/ILI9481_Init.h new file mode 100644 index 0000000..038d1fd --- /dev/null +++ b/TFT_Drivers/ILI9481_Init.h @@ -0,0 +1,77 @@ + +// This is the command sequence that initialises the ILI9481 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure ILI9481 display + + writecommand(TFT_SLPOUT); + delay(20); + + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x18); + + writecommand(0xD1); + writedata(0x00); + writedata(0x07); + writedata(0x10); + + writecommand(0xD2); + writedata(0x01); + writedata(0x02); + + writecommand(0xC0); + writedata(0x10); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x11); + + writecommand(0xC5); + writedata(0x03); + + writecommand(0xC8); + writedata(0x00); + writedata(0x32); + writedata(0x36); + writedata(0x45); + writedata(0x06); + writedata(0x16); + writedata(0x37); + writedata(0x75); + writedata(0x77); + writedata(0x54); + writedata(0x0C); + writedata(0x00); + + writecommand(TFT_MADCTL); + writedata(0x0A); + + writecommand(0x3A); + writedata(0x55); + + writecommand(TFT_CASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(TFT_PASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDF); + + delay(120); + writecommand(TFT_DISPON); + + delay(25); +// End of ILI9481 display configuration + + + diff --git a/TFT_Drivers/ILI9481_Rotation.h b/TFT_Drivers/ILI9481_Rotation.h new file mode 100644 index 0000000..e80d08e --- /dev/null +++ b/TFT_Drivers/ILI9481_Rotation.h @@ -0,0 +1,27 @@ + // This is the command sequence that rotates the ILI9481 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_BGR | TFT_MAD_SS); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_BGR); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_BGR | TFT_MAD_GS); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MV | TFT_MAD_BGR | TFT_MAD_SS | TFT_MAD_GS); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } + \ No newline at end of file diff --git a/TFT_Drivers/RPI_ILI9486_Defines.h b/TFT_Drivers/ILI9486_Defines.h similarity index 97% rename from TFT_Drivers/RPI_ILI9486_Defines.h rename to TFT_Drivers/ILI9486_Defines.h index 5ba1007..31996e4 100644 --- a/TFT_Drivers/RPI_ILI9486_Defines.h +++ b/TFT_Drivers/ILI9486_Defines.h @@ -4,7 +4,7 @@ #define TFT_HEIGHT 480 // For Raspberry Pi ILI9486 only with a modified board to add a write strobe: -#ifdef TFT_WR +#if defined (TFT_WR) && defined (RPI_ILI9486_DRIVER) #define RPI_WRITE_STROBE #endif diff --git a/TFT_Drivers/RPI_ILI9486_Init.h b/TFT_Drivers/ILI9486_Init.h similarity index 100% rename from TFT_Drivers/RPI_ILI9486_Init.h rename to TFT_Drivers/ILI9486_Init.h diff --git a/TFT_Drivers/RPI_ILI9486_Rotation.h b/TFT_Drivers/ILI9486_Rotation.h similarity index 66% rename from TFT_Drivers/RPI_ILI9486_Rotation.h rename to TFT_Drivers/ILI9486_Rotation.h index cd6b0f7..495d675 100644 --- a/TFT_Drivers/RPI_ILI9486_Rotation.h +++ b/TFT_Drivers/ILI9486_Rotation.h @@ -5,43 +5,43 @@ switch (rotation) { case 0: // Portrait writedata(TFT_MAD_BGR | TFT_MAD_MX); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 1: // Landscape (Portrait + 90) writedata(TFT_MAD_BGR | TFT_MAD_MV); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 2: // Inverter portrait writedata( TFT_MAD_BGR | TFT_MAD_MY); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 3: // Inverted landscape writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 4: // Portrait writedata(TFT_MAD_BGR | TFT_MAD_MX | TFT_MAD_MY); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 5: // Landscape (Portrait + 90) writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MX); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 6: // Inverter portrait writedata( TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 7: // Inverted landscape writedata(TFT_MAD_BGR | TFT_MAD_MV | TFT_MAD_MY); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; } - \ No newline at end of file + diff --git a/TFT_Drivers/ILI9488_Defines.h b/TFT_Drivers/ILI9488_Defines.h new file mode 100644 index 0000000..bd5fb88 --- /dev/null +++ b/TFT_Drivers/ILI9488_Defines.h @@ -0,0 +1,42 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/ILI9488_Init.h b/TFT_Drivers/ILI9488_Init.h new file mode 100644 index 0000000..2297069 --- /dev/null +++ b/TFT_Drivers/ILI9488_Init.h @@ -0,0 +1,99 @@ + +// This is the command sequence that initialises the ILI9488 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure ILI9488 display + + writecommand(0xE0); // Positive Gamma Control + writedata(0x00); + writedata(0x03); + writedata(0x09); + writedata(0x08); + writedata(0x16); + writedata(0x0A); + writedata(0x3F); + writedata(0x78); + writedata(0x4C); + writedata(0x09); + writedata(0x0A); + writedata(0x08); + writedata(0x16); + writedata(0x1A); + writedata(0x0F); + + writecommand(0XE1); // Negative Gamma Control + writedata(0x00); + writedata(0x16); + writedata(0x19); + writedata(0x03); + writedata(0x0F); + writedata(0x05); + writedata(0x32); + writedata(0x45); + writedata(0x46); + writedata(0x04); + writedata(0x0E); + writedata(0x0D); + writedata(0x35); + writedata(0x37); + writedata(0x0F); + + writecommand(0XC0); // Power Control 1 + writedata(0x17); + writedata(0x15); + + writecommand(0xC1); // Power Control 2 + writedata(0x41); + + writecommand(0xC5); // VCOM Control + writedata(0x00); + writedata(0x12); + writedata(0x80); + + writecommand(TFT_MADCTL); // Memory Access Control + writedata(0x48); // MX, BGR + + writecommand(0x3A); // Pixel Interface Format +#if defined (ESP32_PARALLEL) + writedata(0x55); // 16 bit colour for parallel +#else + writedata(0x66); // 18 bit colour for SPI +#endif + + writecommand(0xB0); // Interface Mode Control + writedata(0x00); + + writecommand(0xB1); // Frame Rate Control + writedata(0xA0); + + writecommand(0xB4); // Display Inversion Control + writedata(0x02); + + writecommand(0xB6); // Display Function Control + writedata(0x02); + writedata(0x02); + writedata(0x3B); + + writecommand(0xB7); // Entry Mode Set + writedata(0xC6); + + writecommand(0xF7); // Adjust Control 3 + writedata(0xA9); + writedata(0x51); + writedata(0x2C); + writedata(0x82); + + writecommand(TFT_SLPOUT); //Exit Sleep +delay(120); + + writecommand(TFT_DISPON); //Display on +delay(25); + +// End of ILI9488 display configuration + + + diff --git a/TFT_Drivers/ILI9488_Rotation.h b/TFT_Drivers/ILI9488_Rotation.h new file mode 100644 index 0000000..6ab17bd --- /dev/null +++ b/TFT_Drivers/ILI9488_Rotation.h @@ -0,0 +1,27 @@ + // This is the command sequence that rotates the ILI9488 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_MX | TFT_MAD_BGR); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_BGR); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_MY | TFT_MAD_BGR); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } + \ No newline at end of file diff --git a/TFT_Drivers/R61581_Defines.h b/TFT_Drivers/R61581_Defines.h new file mode 100644 index 0000000..bd5fb88 --- /dev/null +++ b/TFT_Drivers/R61581_Defines.h @@ -0,0 +1,42 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/R61581_Init.h b/TFT_Drivers/R61581_Init.h new file mode 100644 index 0000000..929d680 --- /dev/null +++ b/TFT_Drivers/R61581_Init.h @@ -0,0 +1,80 @@ + +// This is the command sequence that initialises the R61581 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure R61581 display + + writecommand(TFT_SLPOUT); + delay(20); + + writecommand(0xB0); + writedata(0x00); + + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x18); + + writecommand(0xD1); + writedata(0x00); + writedata(0x07); + writedata(0x10); + + writecommand(0xD2); + writedata(0x01); + writedata(0x02); + + writecommand(0xC0); + writedata(0x12); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x11); + + writecommand(0xC5); + writedata(0x03); + + writecommand(0xC8); + writedata(0x00); + writedata(0x32); + writedata(0x36); + writedata(0x45); + writedata(0x06); + writedata(0x16); + writedata(0x37); + writedata(0x75); + writedata(0x77); + writedata(0x54); + writedata(0x0C); + writedata(0x00); + + writecommand(TFT_MADCTL); + writedata(0x0A); + + writecommand(0x3A); + writedata(0x55); + + writecommand(TFT_CASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(TFT_PASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDF); + + delay(120); + writecommand(TFT_DISPON); + + delay(25); +// End of R61581 display configuration + + + diff --git a/TFT_Drivers/R61581_Rotation.h b/TFT_Drivers/R61581_Rotation.h new file mode 100644 index 0000000..4d7dc61 --- /dev/null +++ b/TFT_Drivers/R61581_Rotation.h @@ -0,0 +1,27 @@ + // This is the command sequence that rotates the R61581 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_BGR | TFT_MAD_MX); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_BGR); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_BGR | TFT_MAD_GS); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MV | TFT_MAD_BGR | TFT_MAD_MX | TFT_MAD_GS); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } + \ No newline at end of file diff --git a/TFT_Drivers/RM68140_Defines.h b/TFT_Drivers/RM68140_Defines.h new file mode 100644 index 0000000..bd5fb88 --- /dev/null +++ b/TFT_Drivers/RM68140_Defines.h @@ -0,0 +1,42 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/RM68140_Init.h b/TFT_Drivers/RM68140_Init.h new file mode 100644 index 0000000..e5df339 --- /dev/null +++ b/TFT_Drivers/RM68140_Init.h @@ -0,0 +1,77 @@ + +// This is the command sequence that initialises the RM68140 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure RM68140 display + + writecommand(TFT_SLPOUT); + delay(20); + + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x18); + + writecommand(0xD1); + writedata(0x00); + writedata(0x07); + writedata(0x10); + + writecommand(0xD2); + writedata(0x01); + writedata(0x02); + + writecommand(0xC0); + writedata(0x10); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x11); + + writecommand(0xC5); + writedata(0x03); + + writecommand(0xC8); + writedata(0x00); + writedata(0x32); + writedata(0x36); + writedata(0x45); + writedata(0x06); + writedata(0x16); + writedata(0x37); + writedata(0x75); + writedata(0x77); + writedata(0x54); + writedata(0x0C); + writedata(0x00); + + writecommand(TFT_MADCTL); + writedata(0x0A); + + writecommand(0x3A); + writedata(0x55); + + writecommand(TFT_CASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(TFT_PASET); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDF); + + delay(120); + writecommand(TFT_DISPON); + + delay(25); +// End of RM68140 display configuration + + + diff --git a/TFT_Drivers/RM68140_Rotation.h b/TFT_Drivers/RM68140_Rotation.h new file mode 100644 index 0000000..2f83d61 --- /dev/null +++ b/TFT_Drivers/RM68140_Rotation.h @@ -0,0 +1,44 @@ + // This is the command sequence that rotates the RM68140 driver coordinate frame + + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_BGR); + writecommand(0xB6); + writedata(0); + writedata(0x22); + writedata(0x3B); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_MV | TFT_MAD_BGR); + writecommand(0xB6); + writedata(0); + writedata(0x02); + writedata(0x3B); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + case 2: // Inverter portrait + writedata(TFT_MAD_BGR); + writecommand(0xB6); + writedata(0); + writedata(0x42); + writedata(0x3B); + _width = TFT_WIDTH; + _height = TFT_HEIGHT; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_MV | TFT_MAD_BGR); + writecommand(0xB6); + writedata(0); + writedata(0x62); + writedata(0x3B); + _width = TFT_HEIGHT; + _height = TFT_WIDTH; + break; + } + diff --git a/TFT_Drivers/S6D02A1_Rotation.h b/TFT_Drivers/S6D02A1_Rotation.h index a3a2981..7fa6eec 100644 --- a/TFT_Drivers/S6D02A1_Rotation.h +++ b/TFT_Drivers/S6D02A1_Rotation.h @@ -7,22 +7,22 @@ switch (rotation) { case 0: writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 1: writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 2: writedata(TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 3: writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; } diff --git a/TFT_Drivers/ST7735_Defines.h b/TFT_Drivers/ST7735_Defines.h index e182cf4..494c673 100644 --- a/TFT_Drivers/ST7735_Defines.h +++ b/TFT_Drivers/ST7735_Defines.h @@ -9,13 +9,15 @@ // Enumerate the different configurations -#define INITR_GREENTAB 0x0 -#define INITR_REDTAB 0x1 -#define INITR_BLACKTAB 0x2 -#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display -#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen -#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 -#define INITB 0xB +#define INITR_GREENTAB 0x0 +#define INITR_REDTAB 0x1 +#define INITR_BLACKTAB 0x2 // Display with no offsets +#define INITR_GREENTAB2 0x3 // Use if you get random pixels on two edges of green tab display +#define INITR_GREENTAB3 0x4 // Use if you get random pixels on edge(s) of 128x128 screen +#define INITR_GREENTAB128 0x5 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_GREENTAB160x80 0x6 // Use if you only get part of 128x128 screen in rotation 0 & 1 +#define INITR_REDTAB160x80 0x7 // Added for https://www.aliexpress.com/item/ShengYang-1pcs-IPS-0-96-inch-7P-SPI-HD-65K-Full-Color-OLED-Module-ST7735-Drive/32918394604.html +#define INITB 0xB // Setup the tab color that will be used by the library setRotation() and setup command list @@ -38,7 +40,15 @@ #define TAB_COLOUR INITR_GREENTAB128 #define CGRAM_OFFSET -#elif defined (ST6635_REDTAB) +#elif defined (ST7735_GREENTAB160x80) + #define TAB_COLOUR INITR_GREENTAB160x80 + #define CGRAM_OFFSET + +#elif defined (ST7735_REDTAB160x80) + #define TAB_COLOUR INITR_REDTAB160x80 + #define CGRAM_OFFSET + +#elif defined (ST7735_REDTAB) #define TAB_COLOUR INITR_REDTAB #elif defined (ST7735_BLACKTAB) diff --git a/TFT_Drivers/ST7735_Init.h b/TFT_Drivers/ST7735_Init.h index 27b3253..a528785 100644 --- a/TFT_Drivers/ST7735_Init.h +++ b/TFT_Drivers/ST7735_Init.h @@ -24,7 +24,7 @@ 0x03, // 3 lines back porch 10, // 10 ms delay ST7735_MADCTL , 1 , // 5: Memory access ctrl (directions), 1 arg: - 0x08, // Row addr/col addr, bottom to top refresh + 0x40, // Row addr/col addr, bottom to top refresh ST7735_DISSET5, 2 , // 6: Display settings #5, 2 args, no delay: 0x15, // 1 clk cycle nonoverlap, 2 cycle gate // rise, 3 cycle osc equalize @@ -140,8 +140,6 @@ ST7735_DISPON , TFT_INIT_DELAY, // 4: Main screen turn on, no args w/delay 100 }; // 100 ms delay - tabcolor = TAB_COLOUR; - if (tabcolor == INITB) { commandList(Bcmd); @@ -175,6 +173,19 @@ colstart = 0; rowstart = 32; } + else if (tabcolor == INITR_GREENTAB160x80) + { + commandList(Rcmd2green); + writecommand(TFT_INVON); + colstart = 26; + rowstart = 1; + } + else if (tabcolor == INITR_REDTAB160x80) + { + commandList(Rcmd2green); + colstart = 24; + rowstart = 0; + } else if (tabcolor == INITR_REDTAB) { commandList(Rcmd2red); diff --git a/TFT_Drivers/ST7735_Rotation.h b/TFT_Drivers/ST7735_Rotation.h index 6b38560..6163abb 100644 --- a/TFT_Drivers/ST7735_Rotation.h +++ b/TFT_Drivers/ST7735_Rotation.h @@ -20,11 +20,21 @@ writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); colstart = 0; rowstart = 32; - } else { + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); + colstart = 26; + rowstart = 1; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); + colstart = 24; + rowstart = 0; + } else if(tabcolor == INITB) { + writedata(TFT_MAD_MX | TFT_MAD_RGB); + } else { writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); } - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 1: if (tabcolor == INITR_BLACKTAB) { @@ -41,11 +51,21 @@ writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 32; rowstart = 0; - } else { + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); + colstart = 1; + rowstart = 26; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); + colstart = 0; + rowstart = 24; + } else if(tabcolor == INITB) { + writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_RGB); + } else { writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); } - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 2: if (tabcolor == INITR_BLACKTAB) { @@ -62,11 +82,21 @@ writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; - } else { + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_BGR); + colstart = 0; + rowstart = 0; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_BGR); + colstart = 24; + rowstart = 0; + } else if(tabcolor == INITB) { + writedata(TFT_MAD_MY | TFT_MAD_RGB); + } else { writedata(TFT_MAD_BGR); } - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 3: if (tabcolor == INITR_BLACKTAB) { @@ -83,33 +113,43 @@ writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 0; rowstart = 0; - } else { + } else if(tabcolor == INITR_GREENTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); + colstart = 1; + rowstart = 26; + } else if(tabcolor == INITR_REDTAB160x80) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); + colstart = 0; + rowstart = 24; + } else if(tabcolor == INITB) { + writedata(TFT_MAD_MV | TFT_MAD_RGB); + } else { writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); } - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; // These next rotations are for bottum up BMP drawing /* case 4: writedata(ST7735_TFT_MAD_MX | ST7735_TFT_MAD_MY | ST7735_TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 5: writedata(ST7735_TFT_MAD_MV | ST7735_TFT_MAD_MX | ST7735_TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; case 6: writedata(ST7735_TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; + _width = _init_width; + _height = _init_height; break; case 7: writedata(ST7735_TFT_MAD_MY | ST7735_TFT_MAD_MV | ST7735_TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; + _width = _init_height; + _height = _init_width; break; */ - } \ No newline at end of file + } diff --git a/TFT_Drivers/ST7789_2_Defines.h b/TFT_Drivers/ST7789_2_Defines.h new file mode 100644 index 0000000..b777b69 --- /dev/null +++ b/TFT_Drivers/ST7789_2_Defines.h @@ -0,0 +1,143 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#ifndef TFT_WIDTH + #define TFT_WIDTH 240 +#endif +#ifndef TFT_HEIGHT + #define TFT_HEIGHT 320 +#endif + +#if (TFT_HEIGHT == 240) && (TFT_WIDTH == 240) + #define CGRAM_OFFSET +#endif + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 +#define TFT_NORON 0x13 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C +#define TFT_RAMRD 0x2E +#define TFT_MADCTL 0x36 +#define TFT_COLMOD 0x3A + +// Flags for TFT_MADCTL +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #ifdef CGRAM_OFFSET + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #endif +#endif + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read + +#define ST_CMD_DELAY 0x80 // special signifier for command lists +#define ST7789_240x240_XSTART 0 +#define ST7789_240x240_YSTART 0 + +// ST7789 specific commands used in init +#define ST7789_NOP 0x00 +#define ST7789_SWRESET 0x01 +#define ST7789_RDDID 0x04 +#define ST7789_RDDST 0x09 + +#define ST7789_RDDPM 0x0A // Read display power mode +#define ST7789_RDD_MADCTL 0x0B // Read display MADCTL +#define ST7789_RDD_COLMOD 0x0C // Read display pixel format +#define ST7789_RDDIM 0x0D // Read display image mode +#define ST7789_RDDSM 0x0E // Read display signal mode +#define ST7789_RDDSR 0x0F // Read display self-diagnostic result (ST7789V) + +#define ST7789_SLPIN 0x10 +#define ST7789_SLPOUT 0x11 +#define ST7789_PTLON 0x12 +#define ST7789_NORON 0x13 + +#define ST7789_INVOFF 0x20 +#define ST7789_INVON 0x21 +#define ST7789_GAMSET 0x26 // Gamma set +#define ST7789_DISPOFF 0x28 +#define ST7789_DISPON 0x29 +#define ST7789_CASET 0x2A +#define ST7789_RASET 0x2B +#define ST7789_RAMWR 0x2C +#define ST7789_RGBSET 0x2D // Color setting for 4096, 64K and 262K colors +#define ST7789_RAMRD 0x2E + +#define ST7789_PTLAR 0x30 +#define ST7789_VSCRDEF 0x33 // Vertical scrolling definition (ST7789V) +#define ST7789_TEOFF 0x34 // Tearing effect line off +#define ST7789_TEON 0x35 // Tearing effect line on +#define ST7789_MADCTL 0x36 // Memory data access control +#define ST7789_IDMOFF 0x38 // Idle mode off +#define ST7789_IDMON 0x39 // Idle mode on +#define ST7789_RAMWRC 0x3C // Memory write continue (ST7789V) +#define ST7789_RAMRDC 0x3E // Memory read continue (ST7789V) +#define ST7789_COLMOD 0x3A + +#define ST7789_RAMCTRL 0xB0 // RAM control +#define ST7789_RGBCTRL 0xB1 // RGB control +#define ST7789_PORCTRL 0xB2 // Porch control +#define ST7789_FRCTRL1 0xB3 // Frame rate control +#define ST7789_PARCTRL 0xB5 // Partial mode control +#define ST7789_GCTRL 0xB7 // Gate control +#define ST7789_GTADJ 0xB8 // Gate on timing adjustment +#define ST7789_DGMEN 0xBA // Digital gamma enable +#define ST7789_VCOMS 0xBB // VCOMS setting +#define ST7789_LCMCTRL 0xC0 // LCM control +#define ST7789_IDSET 0xC1 // ID setting +#define ST7789_VDVVRHEN 0xC2 // VDV and VRH command enable +#define ST7789_VRHS 0xC3 // VRH set +#define ST7789_VDVSET 0xC4 // VDV setting +#define ST7789_VCMOFSET 0xC5 // VCOMS offset set +#define ST7789_FRCTR2 0xC6 // FR Control 2 +#define ST7789_CABCCTRL 0xC7 // CABC control +#define ST7789_REGSEL1 0xC8 // Register value section 1 +#define ST7789_REGSEL2 0xCA // Register value section 2 +#define ST7789_PWMFRSEL 0xCC // PWM frequency selection +#define ST7789_PWCTRL1 0xD0 // Power control 1 +#define ST7789_VAPVANEN 0xD2 // Enable VAP/VAN signal output +#define ST7789_CMD2EN 0xDF // Command 2 enable +#define ST7789_PVGAMCTRL 0xE0 // Positive voltage gamma control +#define ST7789_NVGAMCTRL 0xE1 // Negative voltage gamma control +#define ST7789_DGMLUTR 0xE2 // Digital gamma look-up table for red +#define ST7789_DGMLUTB 0xE3 // Digital gamma look-up table for blue +#define ST7789_GATECTRL 0xE4 // Gate control +#define ST7789_SPI2EN 0xE7 // SPI2 enable +#define ST7789_PWCTRL2 0xE8 // Power control 2 +#define ST7789_EQCTRL 0xE9 // Equalize time control +#define ST7789_PROMCTRL 0xEC // Program control +#define ST7789_PROMEN 0xFA // Program mode enable +#define ST7789_NVMSET 0xFC // NVM setting +#define ST7789_PROMACT 0xFE // Program action + diff --git a/TFT_Drivers/ST7789_2_Init.h b/TFT_Drivers/ST7789_2_Init.h new file mode 100644 index 0000000..3cd9630 --- /dev/null +++ b/TFT_Drivers/ST7789_2_Init.h @@ -0,0 +1,22 @@ + +// This is the command sequence that initialises the ST7789 driver + +// Configure ST7789 display + +{ +static const uint8_t PROGMEM + st7789[] = { + 8, + TFT_SLPOUT, TFT_INIT_DELAY, 255, + TFT_COLMOD, 1+TFT_INIT_DELAY, 0x55, 10, + TFT_MADCTL, 1, 0x00, + TFT_CASET, 4, 0x00, 0x00, 0x00, 0xF0, + TFT_PASET, 4, 0x00, 0x00, 0x00, 0xF0, + TFT_INVON, TFT_INIT_DELAY, 10, + TFT_NORON, TFT_INIT_DELAY, 10, + TFT_DISPON, TFT_INIT_DELAY, 255 + }; + + commandList(st7789); +} +// End of ST7789 display configuration \ No newline at end of file diff --git a/TFT_Drivers/ST7789_2_Rotation.h b/TFT_Drivers/ST7789_2_Rotation.h new file mode 100644 index 0000000..d25cc0c --- /dev/null +++ b/TFT_Drivers/ST7789_2_Rotation.h @@ -0,0 +1,48 @@ + // This is the command sequence that rotates the ST7789 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait +#ifdef CGRAM_OFFSET + colstart = 0; + rowstart = 0; +#endif + writedata(TFT_MAD_COLOR_ORDER); + + _width = _init_width; + _height = _init_height; + break; + + case 1: // Landscape (Portrait + 90) +#ifdef CGRAM_OFFSET + colstart = 0; + rowstart = 0; +#endif + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + + _width = _init_height; + _height = _init_width; + break; + + case 2: // Inverter portrait +#ifdef CGRAM_OFFSET + colstart = 0; + rowstart = 80; +#endif + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + + _width = _init_width; + _height = _init_height; + break; + case 3: // Inverted landscape +#ifdef CGRAM_OFFSET + colstart = 80; + rowstart = 0; +#endif + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + + _width = _init_height; + _height = _init_width; + break; + } diff --git a/TFT_Drivers/ST7789_Defines.h b/TFT_Drivers/ST7789_Defines.h new file mode 100644 index 0000000..2695336 --- /dev/null +++ b/TFT_Drivers/ST7789_Defines.h @@ -0,0 +1,139 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#ifndef TFT_WIDTH + #define TFT_WIDTH 240 +#endif +#ifndef TFT_HEIGHT + #define TFT_HEIGHT 320 +#endif + +#if (TFT_HEIGHT == 240) && (TFT_WIDTH == 240) + #define CGRAM_OFFSET +#endif + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPI.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 +#define TFT_NORON 0x13 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C +#define TFT_RAMRD 0x2E +#define TFT_MADCTL 0x36 +#define TFT_COLMOD 0x3A + +// Flags for TFT_MADCTL +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #ifdef CGRAM_OFFSET + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #endif +#endif + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read + +// ST7789 specific commands used in init +#define ST7789_NOP 0x00 +#define ST7789_SWRESET 0x01 +#define ST7789_RDDID 0x04 +#define ST7789_RDDST 0x09 + +#define ST7789_RDDPM 0x0A // Read display power mode +#define ST7789_RDD_MADCTL 0x0B // Read display MADCTL +#define ST7789_RDD_COLMOD 0x0C // Read display pixel format +#define ST7789_RDDIM 0x0D // Read display image mode +#define ST7789_RDDSM 0x0E // Read display signal mode +#define ST7789_RDDSR 0x0F // Read display self-diagnostic result (ST7789V) + +#define ST7789_SLPIN 0x10 +#define ST7789_SLPOUT 0x11 +#define ST7789_PTLON 0x12 +#define ST7789_NORON 0x13 + +#define ST7789_INVOFF 0x20 +#define ST7789_INVON 0x21 +#define ST7789_GAMSET 0x26 // Gamma set +#define ST7789_DISPOFF 0x28 +#define ST7789_DISPON 0x29 +#define ST7789_CASET 0x2A +#define ST7789_RASET 0x2B +#define ST7789_RAMWR 0x2C +#define ST7789_RGBSET 0x2D // Color setting for 4096, 64K and 262K colors +#define ST7789_RAMRD 0x2E + +#define ST7789_PTLAR 0x30 +#define ST7789_VSCRDEF 0x33 // Vertical scrolling definition (ST7789V) +#define ST7789_TEOFF 0x34 // Tearing effect line off +#define ST7789_TEON 0x35 // Tearing effect line on +#define ST7789_MADCTL 0x36 // Memory data access control +#define ST7789_IDMOFF 0x38 // Idle mode off +#define ST7789_IDMON 0x39 // Idle mode on +#define ST7789_RAMWRC 0x3C // Memory write continue (ST7789V) +#define ST7789_RAMRDC 0x3E // Memory read continue (ST7789V) +#define ST7789_COLMOD 0x3A + +#define ST7789_RAMCTRL 0xB0 // RAM control +#define ST7789_RGBCTRL 0xB1 // RGB control +#define ST7789_PORCTRL 0xB2 // Porch control +#define ST7789_FRCTRL1 0xB3 // Frame rate control +#define ST7789_PARCTRL 0xB5 // Partial mode control +#define ST7789_GCTRL 0xB7 // Gate control +#define ST7789_GTADJ 0xB8 // Gate on timing adjustment +#define ST7789_DGMEN 0xBA // Digital gamma enable +#define ST7789_VCOMS 0xBB // VCOMS setting +#define ST7789_LCMCTRL 0xC0 // LCM control +#define ST7789_IDSET 0xC1 // ID setting +#define ST7789_VDVVRHEN 0xC2 // VDV and VRH command enable +#define ST7789_VRHS 0xC3 // VRH set +#define ST7789_VDVSET 0xC4 // VDV setting +#define ST7789_VCMOFSET 0xC5 // VCOMS offset set +#define ST7789_FRCTR2 0xC6 // FR Control 2 +#define ST7789_CABCCTRL 0xC7 // CABC control +#define ST7789_REGSEL1 0xC8 // Register value section 1 +#define ST7789_REGSEL2 0xCA // Register value section 2 +#define ST7789_PWMFRSEL 0xCC // PWM frequency selection +#define ST7789_PWCTRL1 0xD0 // Power control 1 +#define ST7789_VAPVANEN 0xD2 // Enable VAP/VAN signal output +#define ST7789_CMD2EN 0xDF // Command 2 enable +#define ST7789_PVGAMCTRL 0xE0 // Positive voltage gamma control +#define ST7789_NVGAMCTRL 0xE1 // Negative voltage gamma control +#define ST7789_DGMLUTR 0xE2 // Digital gamma look-up table for red +#define ST7789_DGMLUTB 0xE3 // Digital gamma look-up table for blue +#define ST7789_GATECTRL 0xE4 // Gate control +#define ST7789_SPI2EN 0xE7 // SPI2 enable +#define ST7789_PWCTRL2 0xE8 // Power control 2 +#define ST7789_EQCTRL 0xE9 // Equalize time control +#define ST7789_PROMCTRL 0xEC // Program control +#define ST7789_PROMEN 0xFA // Program mode enable +#define ST7789_NVMSET 0xFC // NVM setting +#define ST7789_PROMACT 0xFE // Program action + diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h new file mode 100644 index 0000000..d6b0b11 --- /dev/null +++ b/TFT_Drivers/ST7789_Init.h @@ -0,0 +1,124 @@ + +// This is the command sequence that initialises the ST7789 driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + +{ + writecommand(ST7789_SLPOUT); // Sleep out + delay(120); + + writecommand(ST7789_NORON); // Normal display mode on + + //------------------------------display and color format setting--------------------------------// + writecommand(ST7789_MADCTL); + //writedata(0x00); + writedata(TFT_MAD_COLOR_ORDER); + + // JLX240 display datasheet + writecommand(0xB6); + writedata(0x0A); + writedata(0x82); + + writecommand(ST7789_COLMOD); + writedata(0x55); + delay(10); + + //--------------------------------ST7789V Frame rate setting----------------------------------// + writecommand(ST7789_PORCTRL); + writedata(0x0c); + writedata(0x0c); + writedata(0x00); + writedata(0x33); + writedata(0x33); + + writecommand(ST7789_GCTRL); // Voltages: VGH / VGL + writedata(0x35); + + //---------------------------------ST7789V Power setting--------------------------------------// + writecommand(ST7789_VCOMS); + writedata(0x28); // JLX240 display datasheet + + writecommand(ST7789_LCMCTRL); + writedata(0x0C); + + writecommand(ST7789_VDVVRHEN); + writedata(0x01); + writedata(0xFF); + + writecommand(ST7789_VRHS); // voltage VRHS + writedata(0x10); + + writecommand(ST7789_VDVSET); + writedata(0x20); + + writecommand(ST7789_FRCTR2); + writedata(0x0f); + + writecommand(ST7789_PWCTRL1); + writedata(0xa4); + writedata(0xa1); + + //--------------------------------ST7789V gamma setting---------------------------------------// + writecommand(ST7789_PVGAMCTRL); + writedata(0xd0); + writedata(0x00); + writedata(0x02); + writedata(0x07); + writedata(0x0a); + writedata(0x28); + writedata(0x32); + writedata(0x44); + writedata(0x42); + writedata(0x06); + writedata(0x0e); + writedata(0x12); + writedata(0x14); + writedata(0x17); + + writecommand(ST7789_NVGAMCTRL); + writedata(0xd0); + writedata(0x00); + writedata(0x02); + writedata(0x07); + writedata(0x0a); + writedata(0x28); + writedata(0x31); + writedata(0x54); + writedata(0x47); + writedata(0x0e); + writedata(0x1c); + writedata(0x17); + writedata(0x1b); + writedata(0x1e); + + writecommand(ST7789_INVON); + + writecommand(ST7789_CASET); // Column address set + writedata(0x00); + writedata(0x00); + writedata(0x00); + writedata(0xE5); // 239 + + writecommand(ST7789_RASET); // Row address set + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); // 319 + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + spi_end(); + delay(120); + spi_begin(); + + writecommand(ST7789_DISPON); //Display on + delay(120); + +#ifdef TFT_BL + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); +#endif +} diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h new file mode 100644 index 0000000..707c775 --- /dev/null +++ b/TFT_Drivers/ST7789_Rotation.h @@ -0,0 +1,80 @@ + // This is the command sequence that rotates the ST7789 driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 4; + switch (rotation) { + case 0: // Portrait +#ifdef CGRAM_OFFSET + if (_init_width == 135) + { + colstart = 52; + rowstart = 40; + } + else + { + colstart = 0; + rowstart = 0; + } +#endif + writedata(TFT_MAD_COLOR_ORDER); + + _width = _init_width; + _height = _init_height; + break; + + case 1: // Landscape (Portrait + 90) +#ifdef CGRAM_OFFSET + if (_init_width == 135) + { + colstart = 40; + rowstart = 53; + } + else + { + colstart = 0; + rowstart = 0; + } +#endif + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + + _width = _init_height; + _height = _init_width; + break; + + case 2: // Inverter portrait +#ifdef CGRAM_OFFSET + if (_init_width == 135) + { + colstart = 53; + rowstart = 40; + } + else + { + colstart = 0; + rowstart = 80; + } +#endif + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + + _width = _init_width; + _height = _init_height; + break; + case 3: // Inverted landscape +#ifdef CGRAM_OFFSET + if (_init_width == 135) + { + colstart = 40; + rowstart = 52; + } + else + { + colstart = 80; + rowstart = 0; + } +#endif + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + + _width = _init_height; + _height = _init_width; + break; + } diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index d805ade..7414516 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -1,13 +1,9 @@ /*************************************************** - Arduino TFT graphics library targetted at ESP8266 - based boards. (ESP32 support is planned!) - - This library has been derived from the Adafruit_GFX - library and the associated driver library. See text - at the end of this file. + Arduino TFT graphics library targeted at ESP8266 + and ESP32 based boards. This is a standalone library that contains the - hardware driver, the graphics funtions and the + hardware driver, the graphics functions and the proportional fonts. The larger fonts are Run Length Encoded to reduce their @@ -17,46 +13,125 @@ Bodmer: Added RPi 16 bit display support ****************************************************/ + #include "TFT_eSPI.h" -#include +#if defined (ESP32) + #if !defined (ESP32_PARALLEL) + #ifdef USE_HSPI_PORT + SPIClass spi = SPIClass(HSPI); + #else // use default VSPI port + SPIClass& spi = SPI; + #endif + #endif +#else // ESP8266 + SPIClass& spi = SPI; +#endif -//#include -//#include "pins_arduino.h" -//#include "wiring_private.h" -#include + // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled +#if defined (ESP32) && !defined (SUPPORT_TRANSACTIONS) + #define SUPPORT_TRANSACTIONS +#endif // If it is a 16bit serial display we must transfer 16 bits every time #ifdef RPI_ILI9486_DRIVER - #define SEND_16_BITS - #define CMD_BITS 16-1 + #define CMD_BITS (16-1) #else - #define CMD_BITS 8-1 + #define CMD_BITS (8-1) #endif -// Fast SPI block write prototype -void spiWriteBlock(uint16_t color, uint32_t repeat); +// Fast block write prototype +void writeBlock(uint16_t color, uint32_t repeat); -// If the SPI library has transaction support, these functions -// establish settings and protect from interference from other -// libraries. Otherwise, they simply do nothing. +// Byte read prototype +uint8_t readByte(void); + +// GPIO parallel input/output control +void busDir(uint32_t mask, uint8_t mode); inline void TFT_eSPI::spi_begin(void){ -#ifdef SPI_HAS_TRANSACTION - #ifdef SUPPORT_TRANSACTIONS - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0));} - #endif +#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} +#else + CS_L; +#endif +#ifdef ESP8266 + SPI1U = SPI1U_WRITE; #endif } inline void TFT_eSPI::spi_end(void){ -#ifdef SPI_HAS_TRANSACTION - #ifdef SUPPORT_TRANSACTIONS - if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} +#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} + #ifdef ESP8266 + SPI1U = SPI1U_READ; #endif +#else + if(!inTransaction) {CS_H;} #endif } +inline void TFT_eSPI::spi_begin_read(void){ +#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_READ_FREQUENCY, MSBFIRST, TFT_SPI_MODE)); CS_L;} +#else + #if !defined(ESP32_PARALLEL) + spi.setFrequency(SPI_READ_FREQUENCY); + #endif + CS_L; +#endif +#ifdef ESP8266 + SPI1U = SPI1U_READ; +#endif +} + +inline void TFT_eSPI::spi_end_read(void){ +#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) + if(!inTransaction) {if (!locked) {locked = true; CS_H; spi.endTransaction();}} +#else + #if !defined(ESP32_PARALLEL) + spi.setFrequency(SPI_FREQUENCY); + #endif + if(!inTransaction) {CS_H;} +#endif +#ifdef ESP8266 + SPI1U = SPI1U_WRITE; +#endif +} + +#if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(ESP32_PARALLEL) + + inline void TFT_eSPI::spi_begin_touch(void){ + CS_H; // Just in case it has been left low + + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + #else + spi.setFrequency(SPI_TOUCH_FREQUENCY); + #endif + + #ifdef ESP8266 + SPI1U = SPI1U_READ; + #endif + + T_CS_L; + } + + inline void TFT_eSPI::spi_end_touch(void){ + T_CS_H; + + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} + #else + spi.setFrequency(SPI_FREQUENCY); + #endif + + #ifdef ESP8266 + SPI1U = SPI1U_WRITE; + #endif + } + +#endif /*************************************************************************************** ** Function name: TFT_eSPI @@ -73,6 +148,12 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) pinMode(TFT_CS, OUTPUT); #endif +// Configure chip select for touchscreen controller if present +#ifdef TOUCH_CS + digitalWrite(TOUCH_CS, HIGH); // Chip select high (inactive) + pinMode(TOUCH_CS, OUTPUT); +#endif + #ifdef TFT_WR digitalWrite(TFT_WR, HIGH); // Set write strobe high (inactive) pinMode(TFT_WR, OUTPUT); @@ -90,25 +171,68 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) } #endif - _width = w; // Set by specific xxxxx_Defines.h file or by users sketch - _height = h; // Set by specific xxxxx_Defines.h file or by users sketch +#ifdef ESP32_PARALLEL + + // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically + for (int32_t c = 0; c<256; c++) + { + xset_mask[c] = 0; + if ( c & 0x01 ) xset_mask[c] |= (1 << TFT_D0); + if ( c & 0x02 ) xset_mask[c] |= (1 << TFT_D1); + if ( c & 0x04 ) xset_mask[c] |= (1 << TFT_D2); + if ( c & 0x08 ) xset_mask[c] |= (1 << TFT_D3); + if ( c & 0x10 ) xset_mask[c] |= (1 << TFT_D4); + if ( c & 0x20 ) xset_mask[c] |= (1 << TFT_D5); + if ( c & 0x40 ) xset_mask[c] |= (1 << TFT_D6); + if ( c & 0x80 ) xset_mask[c] |= (1 << TFT_D7); + } + + // Make sure read is high before we set the bus to output + digitalWrite(TFT_RD, HIGH); + pinMode(TFT_RD, OUTPUT); + + GPIO.out_w1ts = set_mask(255); // Set data bus to 0xFF + + // Set TFT data bus lines to output + busDir(dir_mask, OUTPUT); + +#endif + + _init_width = _width = w; // Set by specific xxxxx_Defines.h file or by users sketch + _init_height = _height = h; // Set by specific xxxxx_Defines.h file or by users sketch rotation = 0; - cursor_y = cursor_x = 0; + cursor_y = cursor_x = 0; textfont = 1; textsize = 1; - textcolor = 0xFFFF; // White - textbgcolor = 0x0000; // Black + textcolor = bitmap_fg = 0xFFFF; // White + textbgcolor = bitmap_bg = 0x0000; // Black padX = 0; // No padding - textwrap = true; // Wrap text when using print stream + isDigits = false; // No bounding box adjustment + textwrapX = true; // Wrap text at end of line when using print stream + textwrapY = false; // Wrap text at bottom of screen when using print stream textdatum = TL_DATUM; // Top Left text alignment is default fontsloaded = 0; + _swapBytes = false; // Do not swap colour bytes by default + locked = true; // ESP32 transaction mutex lock flags inTransaction = false; + _booted = true; + _cp437 = true; + _utf8 = true; + addr_row = 0xFFFF; addr_col = 0xFFFF; + _xpivot = 0; + _ypivot = 0; + + cspinmask = 0; + dcpinmask = 0; + wrpinmask = 0; + sclkpinmask = 0; + #ifdef LOAD_GLCD fontsloaded = 0x0002; // Bit 1 set #endif @@ -133,6 +257,13 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) fontsloaded |= 0x0100; // Bit 8 set #endif +#ifdef LOAD_FONT8N + fontsloaded |= 0x0200; // Bit 9 set +#endif + +#ifdef SMOOTH_FONT + fontsloaded |= 0x8000; // Bit 15 set +#endif } @@ -140,72 +271,93 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h) ** Function name: begin ** Description: Included for backwards compatibility ***************************************************************************************/ -void TFT_eSPI::begin(void) +void TFT_eSPI::begin(uint8_t tc) { - init(); + init(tc); } /*************************************************************************************** -** Function name: init +** Function name: init (tc is tab colour for ST7735 displays only) ** Description: Reset, then initialise the TFT display registers ***************************************************************************************/ -void TFT_eSPI::init(void) +void TFT_eSPI::init(uint8_t tc) { + if (_booted) + { #if !defined (ESP32) - #ifdef TFT_CS + #if defined (TFT_CS) && (TFT_CS >= 0) cspinmask = (uint32_t) digitalPinToBitMask(TFT_CS); #endif - #ifdef TFT_DC + #if defined (TFT_DC) && (TFT_DC >= 0) dcpinmask = (uint32_t) digitalPinToBitMask(TFT_DC); #endif - #ifdef TFT_WR + #if defined (TFT_WR) && (TFT_WR >= 0) wrpinmask = (uint32_t) digitalPinToBitMask(TFT_WR); #endif - - SPI.begin(); // This will set MISO to input -#else - #ifdef TFT_MOSI - SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); - #else - SPI.begin(); - #endif - -#endif - - inTransaction = false; - locked = true; - -#ifndef SUPPORT_TRANSACTIONS - - SPI.setBitOrder(MSBFIRST); - SPI.setDataMode(SPI_MODE0); - SPI.setFrequency(SPI_FREQUENCY); - //SPI.setHwCs(1); // Use hardware SS toggling on GPIO15 (D8) - not supported - benefit is only ~0.8% performance boost - #ifdef ESP32 // Unlock the SPI hal mutex and set the lock management flags - SPI.beginTransaction(SPISettings(SPI_FREQUENCY, MSBFIRST, SPI_MODE0)); - inTransaction = true; // Flag to stop intermediate spi_end calls - locked = false; // Flag to stop repeat beginTransaction calls + #if defined (TFT_SCLK) && (TFT_SCLK >= 0) + sclkpinmask = (uint32_t) digitalPinToBitMask(TFT_SCLK); + #endif + + #ifdef TFT_SPI_OVERLAP + // Overlap mode SD0=MISO, SD1=MOSI, CLK=SCLK must use D3 as CS + // pins(int8_t sck, int8_t miso, int8_t mosi, int8_t ss); + //spi.pins( 6, 7, 8, 0); + spi.pins(6, 7, 8, 0); #endif + spi.begin(); // This will set HMISO to input + +#else + #if !defined(ESP32_PARALLEL) + #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) + spi.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); + #else + spi.begin(); + #endif + #endif #endif - // Set to output once again in case D6 (MISO) is used for CS -#ifdef TFT_CS - digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) - pinMode(TFT_CS, OUTPUT); + inTransaction = false; + locked = true; + + // SUPPORT_TRANSACTIONS is mandatory for ESP32 so the hal mutex is toggled + // so the code here is for ESP8266 only +#if !defined (SUPPORT_TRANSACTIONS) && defined (ESP8266) + spi.setBitOrder(MSBFIRST); + spi.setDataMode(TFT_SPI_MODE); + spi.setFrequency(SPI_FREQUENCY); +#endif + +#if defined(ESP32_PARALLEL) + digitalWrite(TFT_CS, LOW); // Chip select low permanently + pinMode(TFT_CS, OUTPUT); +#else + #ifdef TFT_CS + // Set to output once again in case D6 (MISO) is used for CS + digitalWrite(TFT_CS, HIGH); // Chip select high (inactive) + pinMode(TFT_CS, OUTPUT); + #else + spi.setHwCs(1); // Use hardware SS toggling + #endif #endif // Set to output once again in case D6 (MISO) is used for DC #ifdef TFT_DC - digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode - pinMode(TFT_DC, OUTPUT); + digitalWrite(TFT_DC, HIGH); // Data/Command high = data mode + pinMode(TFT_DC, OUTPUT); #endif + _booted = false; + spi_end(); + } // end of: if just _booted + // Toggle RST low to reset + spi_begin(); + #ifdef TFT_RST if (TFT_RST >= 0) { digitalWrite(TFT_RST, HIGH); @@ -213,15 +365,15 @@ void TFT_eSPI::init(void) digitalWrite(TFT_RST, LOW); delay(20); digitalWrite(TFT_RST, HIGH); - delay(150); } + else writecommand(TFT_SWRST); // Software reset +#else + writecommand(TFT_SWRST); // Software reset #endif - spi_begin(); - writecommand(TFT_SWRST); // Software reset spi_end(); - - delay(5); // Wait for software reset to complete + + delay(150); // Wait for reset to complete spi_begin(); @@ -230,6 +382,7 @@ void TFT_eSPI::init(void) #include "TFT_Drivers/ILI9341_Init.h" #elif defined (ST7735_DRIVER) + tabcolor = tc; #include "TFT_Drivers/ST7735_Init.h" #elif defined (ILI9163_DRIVER) @@ -239,12 +392,56 @@ void TFT_eSPI::init(void) #include "TFT_Drivers/S6D02A1_Init.h" #elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/RPI_ILI9486_Init.h" + #include "TFT_Drivers/ILI9486_Init.h" +#elif defined (ILI9486_DRIVER) + #include "TFT_Drivers/ILI9486_Init.h" + +#elif defined (ILI9481_DRIVER) + #include "TFT_Drivers/ILI9481_Init.h" + +#elif defined (ILI9488_DRIVER) + #include "TFT_Drivers/ILI9488_Init.h" + +#elif defined (HX8357D_DRIVER) + #include "TFT_Drivers/HX8357D_Init.h" + +#elif defined (ST7789_DRIVER) + #include "TFT_Drivers/ST7789_Init.h" + +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Init.h" + +#elif defined (RM68140_DRIVER) + #include "TFT_Drivers/RM68140_Init.h" + +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Init.h" + +#endif + +#ifdef TFT_INVERSION_ON + writecommand(TFT_INVON); +#endif + +#ifdef TFT_INVERSION_OFF + writecommand(TFT_INVOFF); #endif spi_end(); + setRotation(rotation); + +#if defined (TFT_BL) && defined (TFT_BACKLIGHT_ON) + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); + pinMode(TFT_BL, OUTPUT); +#else + #if defined (TFT_BL) && defined (M5STACK) + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); + #endif +#endif } @@ -271,7 +468,31 @@ void TFT_eSPI::setRotation(uint8_t m) #include "TFT_Drivers/S6D02A1_Rotation.h" #elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/RPI_ILI9486_Rotation.h" + #include "TFT_Drivers/ILI9486_Rotation.h" + +#elif defined (ILI9486_DRIVER) + #include "TFT_Drivers/ILI9486_Rotation.h" + +#elif defined (ILI9481_DRIVER) + #include "TFT_Drivers/ILI9481_Rotation.h" + +#elif defined (ILI9488_DRIVER) + #include "TFT_Drivers/ILI9488_Rotation.h" + +#elif defined (HX8357D_DRIVER) + #include "TFT_Drivers/HX8357D_Rotation.h" + +#elif defined (ST7789_DRIVER) + #include "TFT_Drivers/ST7789_Rotation.h" + +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Rotation.h" + +#elif defined (RM68140_DRIVER) + #include "TFT_Drivers/RM68140_Rotation.h" + +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Rotation.h" #endif @@ -294,8 +515,6 @@ void TFT_eSPI::commandList (const uint8_t *addr) uint8_t numArgs; uint8_t ms; - spi_begin(); - numCommands = pgm_read_byte(addr++); // Number of commands to follow while (numCommands--) // For each command... @@ -316,7 +535,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) delay( (ms==255 ? 500 : ms) ); } } - spi_end(); + } @@ -326,7 +545,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) ***************************************************************************************/ void TFT_eSPI::spiwrite(uint8_t c) { - SPI.transfer(c); + tft_Write_8(c); } @@ -336,14 +555,16 @@ void TFT_eSPI::spiwrite(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writecommand(uint8_t c) { + spi_begin(); // CS_L; + DC_C; - CS_L; - #ifdef SEND_16_BITS - SPI.transfer(0); - #endif - SPI.transfer(c); - CS_H; + + tft_Write_8(c); + DC_D; + + spi_end(); // CS_H; + } @@ -351,53 +572,75 @@ void TFT_eSPI::writecommand(uint8_t c) ** Function name: writedata ** Description: Send a 8 bit data value to the TFT ***************************************************************************************/ -void TFT_eSPI::writedata(uint8_t c) +void TFT_eSPI::writedata(uint8_t d) { - CS_L; - #ifdef SEND_16_BITS - SPI.transfer(0); - #endif - SPI.transfer(c); - CS_H; + spi_begin(); // CS_L; + + DC_D; // Play safe, but should already be in data mode + + tft_Write_8(d); + + CS_L; // Allow more hold time for low VDI rail + + spi_end(); // CS_H; } /*************************************************************************************** -** Function name: readcommand8 (for ILI9341 Interface II i.e. IM [3:0] = "1101") +** Function name: readcommand8 ** Description: Read a 8 bit data value from an indexed command register ***************************************************************************************/ - uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) +uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) { - spi_begin(); + uint8_t reg = 0; +#ifdef ESP32_PARALLEL + + writecommand(cmd_function); // Sets DC and CS high + + busDir(dir_mask, INPUT); + + CS_L; + + // Read nth parameter (assumes caller discards 1st parameter or points index to 2nd) + while(index--) reg = readByte(); + + busDir(dir_mask, OUTPUT); + + CS_H; + +#else + // for ILI9341 Interface II i.e. IM [3:0] = "1101" + spi_begin_read(); index = 0x10 + (index & 0x0F); DC_C; - CS_L; - SPI.transfer(0xD9); + tft_Write_8(0xD9); DC_D; - SPI.transfer(index); - CS_H; + tft_Write_8(index); + + CS_H; // Some displays seem to need CS to be pulsed here, or is just a delay needed? + CS_L; DC_C; - CS_L; - SPI.transfer(cmd_function); + tft_Write_8(cmd_function); DC_D; - uint8_t reg = SPI.transfer(0); - CS_H; + reg = tft_Read_8(); - spi_end(); + spi_end_read(); +#endif return reg; } /*************************************************************************************** -** Function name: readcommand16 (for ILI9341 Interface II i.e. IM [3:0] = "1101") +** Function name: readcommand16 ** Description: Read a 16 bit data value from an indexed command register ***************************************************************************************/ - uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) +uint16_t TFT_eSPI::readcommand16(uint8_t cmd_function, uint8_t index) { - uint32_t reg = 0; - reg |= (readcommand8(cmd_function, index + 0) << 8); + uint32_t reg; + + reg = (readcommand8(cmd_function, index + 0) << 8); reg |= (readcommand8(cmd_function, index + 1) << 0); return reg; @@ -405,10 +648,10 @@ void TFT_eSPI::writedata(uint8_t c) /*************************************************************************************** -** Function name: readcommand32 (for ILI9341 Interface II i.e. IM [3:0] = "1101") +** Function name: readcommand32 ** Description: Read a 32 bit data value from an indexed command register ***************************************************************************************/ - uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) +uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index) { uint32_t reg; @@ -427,113 +670,899 @@ void TFT_eSPI::writedata(uint8_t c) ***************************************************************************************/ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) { - spi_begin(); +#if defined(ESP32_PARALLEL) - readAddrWindow(x0, y0, x0, y0); // Sets CS low + readAddrWindow(x0, y0, 1, 1); // Sets CS low + + // Set masked pins D0- D7 to input + busDir(dir_mask, INPUT); // Dummy read to throw away don't care value - SPI.transfer(0); - - // Read window pixel 24 bit RGB values - uint8_t r = SPI.transfer(0); - uint8_t g = SPI.transfer(0); - uint8_t b = SPI.transfer(0); + readByte(); + + // Fetch the 16 bit BRG pixel + //uint16_t rgb = (readByte() << 8) | readByte(); + + #if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes + + // Read window pixel 24 bit RGB values and fill in LS bits + uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); CS_H; - spi_end(); - + // Set masked pins D0- D7 to output + busDir(dir_mask, OUTPUT); + + return rgb; + + #else // ILI9481 16 bit read + + // Fetch the 16 bit BRG pixel + uint16_t bgr = (readByte() << 8) | readByte(); + + CS_H; + + // Set masked pins D0- D7 to output + busDir(dir_mask, OUTPUT); + + // Swap Red and Blue (could check MADCTL setting to see if this is needed) + return (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); + #endif + +#else // Not ESP32_PARALLEL + + spi_begin_read(); + + readAddrWindow(x0, y0, 1, 1); // Sets CS low + + #ifdef TFT_SDA_READ + begin_SDA_Read(); + #endif + + // Dummy read to throw away don't care value + tft_Read_8(); + + //#if !defined (ILI9488_DRIVER) + + // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte + // as the TFT stores colours as 18 bits + uint8_t r = tft_Read_8(); + uint8_t g = tft_Read_8(); + uint8_t b = tft_Read_8(); +/* + #else + + // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse + // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left + uint8_t r = (tft_Read_8()&0x7E)<<1; + uint8_t g = (tft_Read_8()&0x7E)<<1; + uint8_t b = (tft_Read_8()&0x7E)<<1; + + #endif +*/ + CS_H; + + #ifdef TFT_SDA_READ + end_SDA_Read(); + #endif + + spi_end_read(); + return color565(r, g, b); + +#endif } +/*************************************************************************************** +** Function name: read byte - supports class functions +** Description: Read a byte from ESP32 8 bit data port +***************************************************************************************/ +// Bus MUST be set to input before calling this function! +uint8_t readByte(void) +{ + uint8_t b = 0; + +#ifdef ESP32_PARALLEL + RD_L; + uint32_t reg; // Read all GPIO pins 0-31 + reg = gpio_input_get(); // Read three times to allow for bus access time + reg = gpio_input_get(); + reg = gpio_input_get(); // Data should be stable now + RD_H; + + // Check GPIO bits used and build value + b = (((reg>>TFT_D0)&1) << 0); + b |= (((reg>>TFT_D1)&1) << 1); + b |= (((reg>>TFT_D2)&1) << 2); + b |= (((reg>>TFT_D3)&1) << 3); + b |= (((reg>>TFT_D4)&1) << 4); + b |= (((reg>>TFT_D5)&1) << 5); + b |= (((reg>>TFT_D6)&1) << 6); + b |= (((reg>>TFT_D7)&1) << 7); +#endif + + return b; +} + +/*************************************************************************************** +** Function name: masked GPIO direction control - supports class functions +** Description: Set masked ESP32 GPIO pins to input or output +***************************************************************************************/ +void busDir(uint32_t mask, uint8_t mode) +{ +#ifdef ESP32_PARALLEL + + // Supports GPIO 0 - 31 on ESP32 only + gpio_config_t gpio; + + gpio.pin_bit_mask = mask; + gpio.mode = GPIO_MODE_INPUT; + gpio.pull_up_en = GPIO_PULLUP_ENABLE; + gpio.pull_down_en = GPIO_PULLDOWN_DISABLE; + gpio.intr_type = GPIO_INTR_DISABLE; + + if (mode == OUTPUT) gpio.mode = GPIO_MODE_OUTPUT; + + gpio_config(&gpio); + +#endif +} /*************************************************************************************** ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read 565 pixel colours from a defined area ***************************************************************************************/ - void TFT_eSPI::readRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return; - - spi_begin(); - readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low +#if defined(ESP32_PARALLEL) + + readAddrWindow(x, y, w, h); // Sets CS low + + // Set masked pins D0- D7 to input + busDir(dir_mask, INPUT); // Dummy read to throw away don't care value - SPI.transfer(0); + readByte(); + + // Total pixel count + uint32_t len = w * h; + +#if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes + // Fetch the 24 bit RGB value + while (len--) { + // Assemble the RGB 16 bit colour + uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3); + + // Swapped byte order for compatibility with pushRect() + *data++ = (rgb<<8) | (rgb>>8); + } +#else // ILI9481 reads as 16 bits + // Fetch the 16 bit BRG pixels + while (len--) { + // Read the BRG 16 bit colour + uint16_t bgr = (readByte() << 8) | readByte(); + + // Swap Red and Blue (could check MADCTL setting to see if this is needed) + uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0); + + // Swapped byte order for compatibility with pushRect() + *data++ = (rgb<<8) | (rgb>>8); + } +#endif + CS_H; + + // Set masked pins D0- D7 to output + busDir(dir_mask, OUTPUT); + +#else // Not ESP32_PARALLEL + + spi_begin_read(); + + readAddrWindow(x, y, w, h); // Sets CS low + + #ifdef TFT_SDA_READ + begin_SDA_Read(); + #endif + + // Dummy read to throw away don't care value + tft_Read_8(); // Read window pixel 24 bit RGB values uint32_t len = w * h; while (len--) { + + #if !defined (ILI9488_DRIVER) + // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits - uint8_t r = SPI.transfer(0); - uint8_t g = SPI.transfer(0); - uint8_t b = SPI.transfer(0); + uint8_t r = tft_Read_8(); + uint8_t g = tft_Read_8(); + uint8_t b = tft_Read_8(); + + #else + + // The 6 colour bits are in LS 6 bits of each byte but we do not include the extra clock pulse + // so we use a trick and mask the middle 6 bits of the byte, then only shift 1 place left + uint8_t r = (tft_Read_8()&0x7E)<<1; + uint8_t g = (tft_Read_8()&0x7E)<<1; + uint8_t b = (tft_Read_8()&0x7E)<<1; + + #endif + // Swapped colour byte order for compatibility with pushRect() *data++ = (r & 0xF8) | (g & 0xE0) >> 5 | (b & 0xF8) << 5 | (g & 0x1C) << 11; } - // Write NOP command to stop read mode - //DC_C; - //SPI.transfer(TFT_NOP); - //DC_D; - CS_H; - spi_end(); + #ifdef TFT_SDA_READ + end_SDA_Read(); + #endif + + spi_end_read(); + +#endif } +/*************************************************************************************** +** Function name: tft_Read_8 +** Description: Software SPI to read bidirectional SDA line +***************************************************************************************/ +#if defined (ESP8266) && defined (TFT_SDA_READ) +uint8_t TFT_eSPI::tft_Read_8(void) +{ + uint8_t ret = 0; + uint32_t reg = 0; + + for (uint8_t i = 0; i < 8; i++) { // read results + ret <<= 1; + SCLK_L; + if (digitalRead(TFT_MOSI)) ret |= 1; + SCLK_H; + } + + return ret; +} +#endif + +/*************************************************************************************** +** Function name: beginSDA +** Description: Detach SPI from pin to permit software SPI +***************************************************************************************/ +#ifdef TFT_SDA_READ +void TFT_eSPI::begin_SDA_Read(void) +{ + #ifdef ESP32 + pinMatrixOutDetach(TFT_MOSI, false, false); + pinMode(TFT_MOSI, INPUT); + pinMatrixInAttach(TFT_MOSI, VSPIQ_IN_IDX, false); + #else // ESP8266 + #ifdef TFT_SPI_OVERLAP + // Reads in overlap mode not supported + #else + spi.end(); + #endif + #endif +} +#endif + +/*************************************************************************************** +** Function name: endSDA +** Description: Attach SPI pins after software SPI +***************************************************************************************/ +#ifdef TFT_SDA_READ +void TFT_eSPI::end_SDA_Read(void) +{ + #ifdef ESP32 + pinMode(TFT_MOSI, OUTPUT); + pinMatrixOutAttach(TFT_MOSI, VSPID_OUT_IDX, false, false); + pinMode(TFT_MISO, INPUT); + pinMatrixInAttach(TFT_MISO, VSPIQ_IN_IDX, false); + #else + #ifdef TFT_SPI_OVERLAP + spi.pins(6, 7, 8, 0); + #else + spi.begin(); + #endif + #endif +} +#endif /*************************************************************************************** ** Function name: push rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: push 565 pixel colours into a defined area ***************************************************************************************/ - void TFT_eSPI::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) { - if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return; + // Function deprecated, remains for backwards compatibility + // pushImage() is better as it will crop partly off-screen image blocks + pushImage(x, y, w, h, data); +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: plot 16 bit colour sprite or image onto TFT +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data) +{ + + if ((x >= _width) || (y >= _height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; spi_begin(); + inTransaction = true; - setAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low and sent RAMWR + setWindow(x, y, x + dw - 1, y + dh - 1); - uint32_t len = w * h * 2; - // Push pixels into window rectangle, data is a 16 bit pointer thus increment is halved - while ( len >=32 ) {SPI.writeBytes((uint8_t*)data, 32); data += 16; len -= 32; } - if (len) SPI.writeBytes((uint8_t*)data, len); + data += dx + dy * w; - CS_H; + while (dh--) + { + pushColors(data, dw, _swapBytes); + data += w; + } + inTransaction = false; spi_end(); } +/*************************************************************************************** +** Function name: pushImage +** Description: plot 16 bit sprite or image with 1 colour being transparent +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp) +{ + + if ((x >= _width) || (y >= _height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + data += dx + dy * w; + + int32_t xe = x + dw - 1, ye = y + dh - 1; + + uint16_t lineBuf[dw]; + + if (!_swapBytes) transp = transp >> 8 | transp << 8; + + while (dh--) + { + int32_t len = dw; + uint16_t* ptr = data; + int32_t px = x; + boolean move = true; + uint16_t np = 0; + + while (len--) + { + if (transp != *ptr) + { + if (move) { move = false; setWindow(px, y, xe, ye); } + lineBuf[np] = *ptr; + np++; + } + else + { + move = true; + if (np) + { + pushColors((uint16_t*)lineBuf, np, _swapBytes); + np = 0; + } + } + px++; + ptr++; + } + if (np) pushColors((uint16_t*)lineBuf, np, _swapBytes); + + y++; + data += w; + } + + inTransaction = false; + spi_end(); +} + + +/*************************************************************************************** +** Function name: pushImage - for FLASH (PROGMEM) stored images +** Description: plot 16 bit image +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data) +{ +#ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*)data); +#else + // Partitioned memory FLASH processor + if ((x >= _width) || (y >= _height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + data += dx + dy * w; + + uint16_t buffer[64]; + uint16_t* pix_buffer = buffer; + + setWindow(x, y, x + dw - 1, y + dh - 1); + + // Work out the number whole buffers to send + uint16_t nb = (dw * dh) / 64; + + // Fill and send "nb" buffers to TFT + for (int32_t i = 0; i < nb; i++) { + for (int32_t j = 0; j < 64; j++) { + pix_buffer[j] = pgm_read_word(&data[i * 64 + j]); + } + pushColors(pix_buffer, 64, _swapBytes); + } + + // Work out number of pixels not yet sent + uint16_t np = (dw * dh) % 64; + + // Send any partial buffer left over + if (np) { + for (int32_t i = 0; i < np; i++) + { + pix_buffer[i] = pgm_read_word(&data[nb * 64 + i]); + } + pushColors(pix_buffer, np, _swapBytes); + } + + inTransaction = false; + spi_end(); +#endif // if ESP32 else ESP8266 check +} + + +/*************************************************************************************** +** Function name: pushImage - for FLASH (PROGMEM) stored images +** Description: plot 16 bit image with 1 colour being transparent +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp) +{ +#ifdef ESP32 + pushImage(x, y, w, h, (uint16_t*) data, transp); +#else + // Partitioned memory FLASH processor + if ((x >= _width) || (y >= (int32_t)_height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + data += dx + dy * w; + + int32_t xe = x + dw - 1, ye = y + dh - 1; + + uint16_t lineBuf[dw]; + + if (!_swapBytes) transp = transp >> 8 | transp << 8; + + while (dh--) + { + int32_t len = dw; + uint16_t* ptr = (uint16_t*)data; + int32_t px = x; + boolean move = true; + + uint16_t np = 0; + + while (len--) + { + uint16_t color = pgm_read_word(ptr); + if (transp != color) + { + if (move) { move = false; setWindow(px, y, xe, ye); } + lineBuf[np] = color; + np++; + } + else + { + move = true; + if (np) + { + pushColors(lineBuf, np, _swapBytes); + np = 0; + } + } + px++; + ptr++; + } + if (np) pushColors(lineBuf, np, _swapBytes); + + y++; + data += w; + } + + inTransaction = false; + spi_end(); +#endif // if ESP32 else ESP8266 check +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: plot 8 bit image or sprite using a line buffer +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8) +{ + if ((x >= _width) || (y >= (int32_t)_height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR + + // Line buffer makes plotting faster + uint16_t lineBuf[dw]; + + if (bpp8) + { + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + + _lastColor = -1; // Set to illegal value + + // Used to store last shifted colour + uint8_t msbColor = 0; + uint8_t lsbColor = 0; + + data += dx + dy * w; + while (dh--) + { + uint32_t len = dw; + uint8_t* ptr = data; + uint8_t* linePtr = (uint8_t*)lineBuf; + + while(len--) + { + uint32_t color = *ptr++; + + // Shifts are slow so check if colour has changed first + if (color != _lastColor) { + // =====Green===== ===============Red============== + msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0); + // =====Green===== =======Blue====== + lsbColor = (color & 0x1C)<<3 | blue[color & 0x03]; + _lastColor = color; + } + + *linePtr++ = msbColor; + *linePtr++ = lsbColor; + } + + pushColors(lineBuf, dw, false); + + data += w; + } + } + else + { + while (dh--) + { + w = (w+7) & 0xFFF8; + + int32_t len = dw; + uint8_t* ptr = data; + uint8_t* linePtr = (uint8_t*)lineBuf; + uint8_t bits = 8; + while(len>0) + { + if (len < 8) bits = len; + uint32_t xp = dx; + for (uint16_t i = 0; i < bits; i++) + { + uint8_t col = (ptr[(xp + dy * w)>>3] << (xp & 0x7)) & 0x80; + if (col) {*linePtr++ = bitmap_fg>>8; *linePtr++ = (uint8_t) bitmap_fg;} + else {*linePtr++ = bitmap_bg>>8; *linePtr++ = (uint8_t) bitmap_bg;} + //if (col) drawPixel((dw-len)+xp,h-dh,bitmap_fg); + //else drawPixel((dw-len)+xp,h-dh,bitmap_bg); + xp++; + } + ptr++; + len -= 8; + } + + pushColors(lineBuf, dw, false); + + dy++; + } + } + + inTransaction = false; + spi_end(); +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: plot 8 or 1 bit image or sprite with a transparent colour +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8) +{ + if ((x >= _width) || (y >= _height)) return; + + int32_t dx = 0; + int32_t dy = 0; + int32_t dw = w; + int32_t dh = h; + + if (x < 0) { dw += x; dx = -x; x = 0; } + if (y < 0) { dh += y; dy = -y; y = 0; } + + if ((x + dw) > _width ) dw = _width - x; + if ((y + dh) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + int32_t xe = x + dw - 1, ye = y + dh - 1; + + // Line buffer makes plotting faster + uint16_t lineBuf[dw]; + + if (bpp8) + { + data += dx + dy * w; + + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + + _lastColor = -1; // Set to illegal value + + // Used to store last shifted colour + uint8_t msbColor = 0; + uint8_t lsbColor = 0; + + //int32_t spx = x, spy = y; + + while (dh--) + { + int32_t len = dw; + uint8_t* ptr = data; + uint8_t* linePtr = (uint8_t*)lineBuf; + + int32_t px = x; + boolean move = true; + uint16_t np = 0; + + while (len--) + { + if (transp != *ptr) + { + if (move) { move = false; setWindow(px, y, xe, ye);} + uint8_t color = *ptr; + + // Shifts are slow so check if colour has changed first + if (color != _lastColor) { + // =====Green===== ===============Red============== + msbColor = (color & 0x1C)>>2 | (color & 0xC0)>>3 | (color & 0xE0); + // =====Green===== =======Blue====== + lsbColor = (color & 0x1C)<<3 | blue[color & 0x03]; + _lastColor = color; + } + *linePtr++ = msbColor; + *linePtr++ = lsbColor; + np++; + } + else + { + move = true; + if (np) + { + pushColors(lineBuf, np, false); + linePtr = (uint8_t*)lineBuf; + np = 0; + } + } + px++; + ptr++; + } + + if (np) pushColors(lineBuf, np, false); + + y++; + data += w; + } + } + else + { + w = (w+7) & 0xFFF8; + while (dh--) + { + int32_t px = x; + boolean move = true; + uint16_t np = 0; + int32_t len = dw; + uint8_t* ptr = data; + uint8_t bits = 8; + while(len>0) + { + if (len < 8) bits = len; + uint32_t xp = dx; + uint32_t yp = (dy * w)>>3; + for (uint16_t i = 0; i < bits; i++) + { + //uint8_t col = (ptr[(xp + dy * w)>>3] << (xp & 0x7)) & 0x80; + if ((ptr[(xp>>3) + yp] << (xp & 0x7)) & 0x80) + { + if (move) + { + move = false; + setWindow(px, y, xe, ye); + } + np++; + } + else + { + if (np) + { + pushColor(bitmap_fg, np); + np = 0; + move = true; + } + } + px++; + xp++; + } + ptr++; + len -= 8; + } + if (np) pushColor(bitmap_fg, np); + y++; + dy++; + } + } + + inTransaction = false; + spi_end(); +} + + +/*************************************************************************************** +** Function name: setSwapBytes +** Description: Used by 16 bit pushImage() to swap byte order in colours +***************************************************************************************/ +void TFT_eSPI::setSwapBytes(bool swap) +{ + _swapBytes = swap; +} + + +/*************************************************************************************** +** Function name: getSwapBytes +** Description: Return the swap byte order for colours +***************************************************************************************/ +bool TFT_eSPI::getSwapBytes(void) +{ + return _swapBytes; +} /*************************************************************************************** ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read RGB pixel colours from a defined area ***************************************************************************************/ // If w and h are 1, then 1 pixel is read, *data array size must be 3 bytes per pixel - void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) +void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data) { - spi_begin(); +#if defined(ESP32_PARALLEL) - readAddrWindow(x0, y0, x0 + w - 1, y0 + h - 1); // Sets CS low + // ESP32 parallel bus supported yet + +#else // Not ESP32_PARALLEL + + spi_begin_read(); + + readAddrWindow(x0, y0, w, h); // Sets CS low + + #ifdef TFT_SDA_READ + begin_SDA_Read(); + #endif // Dummy read to throw away don't care value - SPI.transfer(0); - + tft_Read_8(); + // Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h uint32_t len = w * h; while (len--) { + + #if !defined (ILI9488_DRIVER) + // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits - *data++ = SPI.transfer(0); - *data++ = SPI.transfer(0); - *data++ = SPI.transfer(0); + *data++ = tft_Read_8(); + *data++ = tft_Read_8(); + *data++ = tft_Read_8(); + + #else + + // The 6 colour bits are in MS 6 bits of each byte, but the ILI9488 needs an extra clock pulse + // so bits appear shifted right 1 bit, so mask the middle 6 bits then shift 1 place left + *data++ = (tft_Read_8()&0x7E)<<1; + *data++ = (tft_Read_8()&0x7E)<<1; + *data++ = (tft_Read_8()&0x7E)<<1; + + #endif + } + CS_H; - spi_end(); + #ifdef TFT_SDA_READ + end_SDA_Read(); + #endif + + spi_end_read(); + +#endif } @@ -541,41 +1570,6 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) ** Function name: drawCircle ** Description: Draw a circle outline ***************************************************************************************/ -/* -// Midpoint circle algorithm, we can optimise this since y = 0 on first pass -// and we can eliminate the multiply as well -void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t radius, uint32_t color) -{ - int32_t x = radius; - int32_t y = 0; - int32_t err = 0; - - while (x >= y) - { - drawPixel(x0 + x, y0 + y, color); - drawPixel(x0 + x, y0 - y, color); - drawPixel(x0 - x, y0 - y, color); - drawPixel(x0 - x, y0 + y, color); - - drawPixel(x0 + y, y0 + x, color); - drawPixel(x0 + y, y0 - x, color); - drawPixel(x0 - y, y0 - x, color); - drawPixel(x0 - y, y0 + x, color); - - if (err <= 0) - { - y += 1; - err += 2*y + 1; - } - if (err > 0) - { - x -= 1; - err -= 2*x + 1; - } - } -} -*/ - // Optimised midpoint circle algorithm void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) { @@ -584,7 +1578,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t dy = r+r; int32_t p = -(r>>1); - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // These are ordered to minimise coordinate changes in x or y @@ -621,7 +1615,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -669,27 +1663,18 @@ void TFT_eSPI::drawCircleHelper( int32_t x0, int32_t y0, int32_t r, uint8_t corn ** Function name: fillCircle ** Description: draw a filled circle ***************************************************************************************/ -/* +// Optimised midpoint circle algorithm, changed to horizontal lines (faster in sprites) void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) -{ - drawFastVLine(x0, y0 - r, r + r + 1, color); - fillCircleHelper(x0, y0, r, 3, 0, color); -} -*/ - -// Optimised midpoint circle algorithm -void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) - { int32_t x = 0; int32_t dx = 1; int32_t dy = r+r; int32_t p = -(r>>1); - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; - drawFastVLine(x0, y0 - r, dy+1, color); + drawFastHLine(x0 - r, y0, dy+1, color); while(x= 0) { r--; ddF_y += 2; f += ddF_y; } - x++; + y++; + //x++; ddF_x += 2; f += ddF_x; - if (cornername & 0x1) { - drawFastVLine(x0 + x, y0 - r, r + r + delta, color); - drawFastVLine(x0 + r, y0 - x, x + x + delta, color); + if (cornername & 0x1) + { + drawFastHLine(x0 - r, y0 + y, r + r + delta, color); + drawFastHLine(x0 - y, y0 + r, y + y + delta, color); } if (cornername & 0x2) { - drawFastVLine(x0 - x, y0 - r, r + r + delta, color); - drawFastVLine(x0 - r, y0 - x, x + x + delta, color); + drawFastHLine(x0 - r, y0 - y, r + r + delta, color); // 11995, 1090 + drawFastHLine(x0 - y, y0 - r, y + y + delta, color); } } } @@ -771,7 +1742,7 @@ void TFT_eSPI::fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t corne ** Function name: drawEllipse ** Description: Draw a ellipse outline ***************************************************************************************/ -void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color) +void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { if (rx<2) return; if (ry<2) return; @@ -782,7 +1753,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) @@ -818,7 +1789,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -826,7 +1797,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 ** Function name: fillEllipse ** Description: draw a filled ellipse ***************************************************************************************/ -void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color) +void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color) { if (rx<2) return; if (ry<2) return; @@ -837,7 +1808,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) @@ -867,7 +1838,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint1 } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -888,16 +1859,17 @@ void TFT_eSPI::fillScreen(uint32_t color) // Draw a rectangle void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; drawFastHLine(x, y, w, color); drawFastHLine(x, y + h - 1, w, color); - drawFastVLine(x, y, h, color); - drawFastVLine(x + w - 1, y, h, color); + // Avoid drawing corner pixels twice + drawFastVLine(x, y+1, h-2, color); + drawFastVLine(x + w - 1, y+1, h-2, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -908,7 +1880,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col // Draw a rounded rectangle void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // smarter version @@ -923,7 +1895,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t drawCircleHelper(x + r , y + h - r - 1, r, 8, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -931,21 +1903,21 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t ** Function name: fillRoundRect ** Description: Draw a rounded corner filled rectangle ***************************************************************************************/ -// Fill a rounded rectangle +// Fill a rounded rectangle, changed to horizontal lines (faster in sprites) void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; // smarter version - fillRect(x + r, y, w - r - r, h, color); + fillRect(x, y + r, w, h - r - r, color); // draw four corners - fillCircleHelper(x + w - r - 1, y + r, r, 1, h - r - r - 1, color); - fillCircleHelper(x + r , y + r, r, 2, h - r - r - 1, color); - + fillCircleHelper(x + r, y + h - r - 1, r, 1, w - r - r - 1, color); + fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color); + inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -956,7 +1928,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t // Draw a triangle void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; drawLine(x0, y0, x1, y1, color); @@ -964,7 +1936,7 @@ void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3 drawLine(x2, y2, x0, y0, color); inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -977,9 +1949,6 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in { int32_t a, b, y, last; - spi_begin(); - inTransaction = true; - // Sort coordinates by Y order (y2 >= y1 >= y0) if (y0 > y1) { swap_coord(y0, y1); swap_coord(x0, x1); @@ -1001,6 +1970,9 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in return; } + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + inTransaction = true; + int32_t dx01 = x1 - x0, dy01 = y1 - y0, @@ -1045,7 +2017,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } @@ -1053,9 +2025,9 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in ** Function name: drawBitmap ** Description: Draw an image stored in an array on the TFT ***************************************************************************************/ -void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { - - spi_begin(); +void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) +{ + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -1069,7 +2041,55 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function +} + + +/*************************************************************************************** +** Function name: drawXBitmap +** Description: Draw an image stored in an XBM array onto the TFT +***************************************************************************************/ +void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) +{ + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + inTransaction = true; + + int32_t i, j, byteWidth = (w + 7) / 8; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++ ) { + if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7))) { + drawPixel(x + i, y + j, color); + } + } + } + + inTransaction = false; + spi_end(); // Does nothing if Sprite class uses this function +} + + +/*************************************************************************************** +** Function name: drawXBitmap +** Description: Draw an XBM image with foreground and background colors +***************************************************************************************/ +void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor) +{ + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + inTransaction = true; + + int32_t i, j, byteWidth = (w + 7) / 8; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++ ) { + if (pgm_read_byte(bitmap + j * byteWidth + i / 8) & (1 << (i & 7))) + drawPixel(x + i, y + j, color); + else drawPixel(x + i, y + j, bgcolor); + } + } + + inTransaction = false; + spi_end(); // Does nothing if Sprite class uses this function } @@ -1096,6 +2116,25 @@ void TFT_eSPI::setCursor(int16_t x, int16_t y, uint8_t font) } +/*************************************************************************************** +** Function name: getCursorX +** Description: Get the text cursor x position +***************************************************************************************/ +int16_t TFT_eSPI::getCursorX(void) +{ + return cursor_x; +} + +/*************************************************************************************** +** Function name: getCursorY +** Description: Get the text cursor y position +***************************************************************************************/ +int16_t TFT_eSPI::getCursorY(void) +{ + return cursor_y; +} + + /*************************************************************************************** ** Function name: setTextSize ** Description: Set the text size multiplier @@ -1130,13 +2169,57 @@ void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) } +/*************************************************************************************** +** Function name: setPivot +** Description: Set the pivot point on the TFT +*************************************************************************************x*/ +void TFT_eSPI::setPivot(int16_t x, int16_t y) +{ + _xpivot = x; + _ypivot = y; +} + + +/*************************************************************************************** +** Function name: getPivotX +** Description: Get the x pivot position +***************************************************************************************/ +int16_t TFT_eSPI::getPivotX(void) +{ + return _xpivot; +} + + +/*************************************************************************************** +** Function name: getPivotY +** Description: Get the y pivot position +***************************************************************************************/ +int16_t TFT_eSPI::getPivotY(void) +{ + return _ypivot; +} + + +/*************************************************************************************** +** Function name: setBitmapColor +** Description: Set the foreground foreground and background colour +***************************************************************************************/ +void TFT_eSPI::setBitmapColor(uint16_t c, uint16_t b) +{ + if (c == b) b = ~c; + bitmap_fg = c; + bitmap_bg = b; +} + + /*************************************************************************************** ** Function name: setTextWrap ** Description: Define if text should wrap at end of line ***************************************************************************************/ -void TFT_eSPI::setTextWrap(boolean w) +void TFT_eSPI::setTextWrap(boolean wrapX, boolean wrapY) { - textwrap = w; + textwrapX = wrapX; + textwrapY = wrapY; } @@ -1169,6 +2252,15 @@ uint8_t TFT_eSPI::getRotation(void) return rotation; } +/*************************************************************************************** +** Function name: getTextDatum +** Description: Return the text datum value (as used by setTextDatum()) +***************************************************************************************/ +uint8_t TFT_eSPI::getTextDatum(void) +{ + return textdatum; +} + /*************************************************************************************** ** Function name: width @@ -1203,7 +2295,7 @@ int16_t TFT_eSPI::textWidth(const String& string) return textWidth(buffer, textfont); } -int16_t TFT_eSPI::textWidth(const String& string, int font) +int16_t TFT_eSPI::textWidth(const String& string, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -1216,22 +2308,51 @@ int16_t TFT_eSPI::textWidth(const char *string) return textWidth(string, textfont); } -int16_t TFT_eSPI::textWidth(const char *string, int font) +int16_t TFT_eSPI::textWidth(const char *string, uint8_t font) { - unsigned int str_width = 0; - char uniCode; - char *widthtable; + int32_t str_width = 0; + uint16_t uniCode = 0; + +#ifdef SMOOTH_FONT + if(fontLoaded) + { + while (*string) + { + uniCode = decodeUTF8(*string++); + if (uniCode) + { + if (uniCode == 0x20) str_width += gFont.spaceWidth; + else + { + uint16_t gNum = 0; + bool found = getUnicodeIndex(uniCode, &gNum); + if (found) + { + if(str_width == 0 && gdX[gNum] < 0) str_width -= gdX[gNum]; + if (*string || isDigits) str_width += gxAdvance[gNum]; + else str_width += (gdX[gNum] + gWidth[gNum]); + } + else str_width += gFont.spaceWidth + 1; + } + } + } + isDigits = false; + return str_width; + } +#endif if (font>1 && font<9) { - widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop + char *widthtable = (char *)pgm_read_dword( &(fontdata[font].widthtbl ) ) - 32; //subtract the 32 outside the loop while (*string) { uniCode = *(string++); - - str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subract 32 from uniCode + if (uniCode > 31 && uniCode < 128) + str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subtract 32 from uniCode + else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width } + } else { @@ -1241,14 +2362,16 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) { while (*string) { - uniCode = *(string++); - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last)) uniCode = pgm_read_byte(&gfxFont->first); - uniCode -= pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); - // If this is not the last character then use xAdvance - if (*string) str_width += pgm_read_byte(&glyph->xAdvance); - // Else use the offset plus width since this can be bigger than xAdvance - else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width)); + uniCode = decodeUTF8(*string++); + if ((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last ))) + { + uniCode -= pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[uniCode]); + // If this is not the last character or is a digit then use xAdvance + if (*string || isDigits) str_width += pgm_read_byte(&glyph->xAdvance); + // Else use the offset plus width since this can be bigger than xAdvance + else str_width += ((int8_t)pgm_read_byte(&glyph->xOffset) + pgm_read_byte(&glyph->width)); + } } } else @@ -1259,6 +2382,7 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) #endif } } + isDigits = false; return str_width * textsize; } @@ -1281,6 +2405,10 @@ uint16_t TFT_eSPI::fontsLoaded(void) ***************************************************************************************/ int16_t TFT_eSPI::fontHeight(int16_t font) { +#ifdef SMOOTH_FONT + if(fontLoaded) return gFont.yAdvance; +#endif + #ifdef LOAD_GFXFF if (font==1) { @@ -1293,19 +2421,24 @@ int16_t TFT_eSPI::fontHeight(int16_t font) return pgm_read_byte( &fontdata[font].height ) * textsize; } +int16_t TFT_eSPI::fontHeight(void) +{ + return fontHeight(textfont); +} /*************************************************************************************** ** Function name: drawChar ** Description: draw a single character in the Adafruit GLCD font ***************************************************************************************/ -void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size) +void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size) { - if ((x >= (int16_t)_width) || // Clip right - (y >= (int16_t)_height) || // Clip bottom + if ((x >= _width) || // Clip right + (y >= _height) || // Clip bottom ((x + 6 * size - 1) < 0) || // Clip left ((y + 8 * size - 1) < 0)) // Clip top return; + if (c < 32) return; #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> #ifdef LOAD_GFXFF @@ -1317,18 +2450,19 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u if ((size==1) && fillbg) { - byte column[6]; - byte mask = 0x1; + uint8_t column[6]; + uint8_t mask = 0x1; spi_begin(); - setAddrWindow(x, y, x+5, y+8); + + setWindow(x, y, x+5, y+8); + for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i); column[5] = 0; -#if defined (ESP8266) +#if defined (ESP8266) && !defined (ILI9488_DRIVER) color = (color >> 8) | (color << 8); bg = (bg >> 8) | (bg << 8); - uint32_t spimask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - SPI1U1 = (SPI1U1 & spimask) | (15 << SPILMOSI) | (15 << SPILMISO); + for (int8_t j = 0; j < 8; j++) { for (int8_t k = 0; k < 5; k++ ) { if (column[k] & mask) { @@ -1347,28 +2481,24 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } -#else // for ESP32 +#else // for ESP32 or ILI9488 + for (int8_t j = 0; j < 8; j++) { for (int8_t k = 0; k < 5; k++ ) { - if (column[k] & mask) { - SPI.write16(color); - } - else { - SPI.write16(bg); - } + if (column[k] & mask) {tft_Write_16(color);} + else {tft_Write_16(bg);} } - mask <<= 1; - - SPI.write16(bg); + tft_Write_16(bg); } + #endif - CS_H; + spi_end(); } else { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; for (int8_t i = 0; i < 6; i++ ) { uint8_t line; @@ -1393,7 +2523,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u } } inTransaction = false; - spi_end(); + spi_end(); // Does nothing if Sprite class uses this function } //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -1404,30 +2534,30 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u #endif // LOAD_GLCD #ifdef LOAD_GFXFF - spi_begin(); - inTransaction = true; + // Filter out bad characters not present in font + if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) + { + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + inTransaction = true; //>>>>>>>>>>>>>>>>>>>>>>>>>>> - // Character is assumed previously filtered by write() to eliminate - // newlines, returns, non-printable characters, etc. Calling drawChar() - // directly with 'bad' characters of font may cause mayhem! - if (c > pgm_read_byte(&gfxFont->last)) c = pgm_read_byte(&gfxFont->first);; - c -= pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); - uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); - uint16_t bo = pgm_read_word(&glyph->bitmapOffset); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height), - xa = pgm_read_byte(&glyph->xAdvance); - int8_t xo = pgm_read_byte(&glyph->xOffset), - yo = pgm_read_byte(&glyph->yOffset); - uint8_t xx, yy, bits, bit=0; - int16_t xo16, yo16; + c -= pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c]); + uint8_t *bitmap = (uint8_t *)pgm_read_dword(&gfxFont->bitmap); - if(size > 1) { - xo16 = xo; - yo16 = yo; - } + uint32_t bo = pgm_read_word(&glyph->bitmapOffset); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + //xa = pgm_read_byte(&glyph->xAdvance); + int8_t xo = pgm_read_byte(&glyph->xOffset), + yo = pgm_read_byte(&glyph->yOffset); + uint8_t xx, yy, bits=0, bit=0; + int16_t xo16 = 0, yo16 = 0; + + if(size > 1) { + xo16 = xo; + yo16 = yo; + } // Here we have 3 versions of the same function just for evaluation purposes // Comment out the next two #defines to revert to the slower Adafruit implementation @@ -1448,90 +2578,91 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u //FIXED_SIZE is an option in User_Setup.h that only works with FAST_LINE enabled #ifdef FIXED_SIZE - x+=xo; // Save 88 bytes of FLASH - y+=yo; + x+=xo; // Save 88 bytes of FLASH + y+=yo; #endif #ifdef FAST_HLINE #ifdef FAST_SHIFT - uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy>= 1; - } - // Draw pixels for this line as we are about to increment yy - if (hpc) { + if(bits & bit) hpc++; + else { + if (hpc) { #ifndef FIXED_SIZE - if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); - else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); + if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); + else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); #else - drawFastHLine(x+xx-hpc, y+yy, hpc, color); + drawFastHLine(x+xx-hpc, y+yy, hpc, color); #endif - hpc=0; + hpc=0; + } + } + bit >>= 1; + } + // Draw pixels for this line as we are about to increment yy + if (hpc) { +#ifndef FIXED_SIZE + if(size == 1) drawFastHLine(x+xo+xx-hpc, y+yo+yy, hpc, color); + else fillRect(x+(xo16+xx-hpc)*size, y+(yo16+yy)*size, size*hpc, size, color); +#else + drawFastHLine(x+xx-hpc, y+yy, hpc, color); +#endif + hpc=0; + } } - } #else - uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); SPI1CMD |= SPIBUSY; @@ -1604,7 +2731,7 @@ inline void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET; SPI1CMD |= SPIBUSY; @@ -1612,7 +2739,7 @@ inline void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); SPI1CMD |= SPIBUSY; @@ -1621,33 +2748,30 @@ inline void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t // write to RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); //spi_end(); } #elif defined (ESP8266) && !defined (RPI_WRITE_STROBE) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; addr_row = 0xFFFF; // Column addr set DC_C; - CS_L; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET<<8; SPI1CMD |= SPIBUSY; @@ -1655,13 +2779,13 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t xBin[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (xs>>8), 0, (uint8_t) (xs>>0), 0, (uint8_t) (xe>>8), 0, (uint8_t) (xe>>0), }; + spi.writePattern(&xb[0], 8, 1); // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET<<8; SPI1CMD |= SPIBUSY; @@ -1669,33 +2793,33 @@ void TFT_eSPI::setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - uint8_t yBin[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (ys>>8), 0, (uint8_t) (ys>>0), 0, (uint8_t) (ye>>8), 0, (uint8_t) (ye>>0), }; + spi.writePattern(&yb[0], 8, 1); // write to RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR<<8; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; + // Re-instate SPI flags settings corrupted by SPI library writePattern() call + SPI1U = SPI1U_WRITE; + //spi_end(); } #else #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow - CS_L; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // Column addr set DC_C; @@ -1765,9 +2889,9 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t #else // This is for the ESP32 -inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { - //spi_begin(); + //spi_begin(); // Must be called before setWimdow addr_col = 0xFFFF; addr_row = 0xFFFF; @@ -1779,58 +2903,37 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; -#endif - - // Column addr set DC_C; - CS_L; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_CASET); -#else - SPI.write(TFT_CASET); -#endif + tft_Write_8(TFT_CASET); DC_D; - #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x0>>8), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; + spi.writePattern(&xb[0], 8, 1); #else - SPI.write32(xaw); + tft_Write_32(SPI_32(x0, x1)); #endif + DC_C; + // Row addr set - DC_C; - -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_PASET); -#else - SPI.write(TFT_PASET); -#endif + tft_Write_8(TFT_PASET); DC_D; - #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y0>>8), 0, (uint8_t) (y0>>0), 0, (uint8_t) (y1>>8), 0, (uint8_t) (y1>>0), }; + spi.writePattern(&yb[0], 8, 1); #else - SPI.write32(yaw); + tft_Write_32(SPI_32(y0, y1)); #endif - // write to RAM DC_C; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_RAMWR); -#else - SPI.write(TFT_RAMWR); -#endif + // write to RAM + tft_Write_8(TFT_RAMWR); DC_D; @@ -1846,28 +2949,26 @@ inline void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t ***************************************************************************************/ // Chip select stays low #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - //spi_begin(); + + int32_t xe = xs + w - 1; + int32_t ye = ys + h - 1; addr_col = 0xFFFF; addr_row = 0xFFFF; #ifdef CGRAM_OFFSET - xs+=colstart; - xe+=colstart; - ys+=rowstart; - ye+=rowstart; + xs += colstart; + xe += colstart; + ys += rowstart; + ye += rowstart; #endif // Column addr set DC_C; - CS_L; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET; SPI1CMD |= SPIBUSY; @@ -1875,7 +2976,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (xs >> 8) | (uint16_t)(xs << 8) | ((uint8_t)(xe >> 8)<<16 | (xe << 24)); SPI1CMD |= SPIBUSY; @@ -1884,7 +2985,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // Row addr set DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET; SPI1CMD |= SPIBUSY; @@ -1892,7 +2993,7 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) DC_D; - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go SPI1W0 = (ys >> 8) | (uint16_t)(ys << 8) | ((uint8_t)(ye >> 8)<<16 | (ye << 24)); SPI1CMD |= SPIBUSY; @@ -1901,58 +3002,57 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye) // read from RAM DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMRD; SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} DC_D; - //spi_end(); + } #else //ESP32 -void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) +void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h) { - //spi_begin(); + + int32_t xe = xs + w - 1; + int32_t ye = ys + h - 1; addr_col = 0xFFFF; addr_row = 0xFFFF; #ifdef CGRAM_OFFSET - x0+=colstart; - x1+=colstart; - y0+=rowstart; - y1+=rowstart; +xs += colstart; +xe += colstart; +ys += rowstart; +ye += rowstart; #endif - uint32_t xaw = ((uint32_t)x0 << 16) | x1; - uint32_t yaw = ((uint32_t)y0 << 16) | y1; - // Column addr set DC_C; - CS_L; - SPI.write(TFT_CASET); + tft_Write_8(TFT_CASET); DC_D; - SPI.write32(xaw); + tft_Write_32(SPI_32(xs, xe)); // Row addr set DC_C; - SPI.write(TFT_PASET); + tft_Write_8(TFT_PASET); DC_D; - SPI.write32(yaw); + tft_Write_32(SPI_32(ys, ye)); DC_C; - SPI.transfer(TFT_RAMRD); // Read CGRAM command + + tft_Write_8(TFT_RAMRD); // Read CGRAM command + DC_D; - //spi_end(); } #endif @@ -1962,11 +3062,11 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) ** Description: push a single pixel at an arbitrary position ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; - + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + #ifdef CGRAM_OFFSET x+=colstart; y+=rowstart; @@ -1974,16 +3074,12 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) spi_begin(); - CS_L; - - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_CASET<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} @@ -1992,9 +3088,9 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte uint8_t cBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0)}; - SPI.writePattern(&cBin[0], 4, 2); + spi.writePattern(&cBin[0], 4, 2); #else - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go uint32_t xswap = (x >> 8) | (uint16_t)(x << 8); SPI1W0 = xswap | (xswap << 16); @@ -2010,7 +3106,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_PASET<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; @@ -2020,9 +3116,9 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits per byte uint8_t cBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0)}; - SPI.writePattern(&cBin[0], 4, 2); + spi.writePattern(&cBin[0], 4, 2); #else - SPI1U1 = mask | (31 << SPILMOSI) | (31 << SPILMISO); + SPI1U1 = (31 << SPILMOSI) | (31 << SPILMISO); // Load the two coords as a 32 bit value and shift in one go uint32_t yswap = (y >> 8) | (uint16_t)(y << 8); SPI1W0 = yswap | (yswap << 16); @@ -2035,7 +3131,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); SPI1W0 = TFT_RAMWR<<(CMD_BITS + 1 - 8); SPI1CMD |= SPIBUSY; @@ -2043,13 +3139,15 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_D; - SPI1U1 = mask | (15 << SPILMOSI) | (15 << SPILMISO); +#if defined (ILI9488_DRIVER) + tft_Write_16(color); +#else + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); SPI1W0 = (color >> 8) | (color << 8); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} - - CS_H; +#endif spi_end(); } @@ -2058,16 +3156,14 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) #if defined (ESP8266) && defined (RPI_ILI9486_DRIVER) // This is for the RPi display that needs 16 bits -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + spi_begin(); - CS_L; - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = SPI1U1 & mask; - SPI1U1 = mask | (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); + SPI1U1 = (CMD_BITS << SPILMOSI) | (CMD_BITS << SPILMISO); // No need to send x if it has not changed (speeds things up) if (addr_col != x) { DC_C; @@ -2136,17 +3232,16 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} - CS_H; - spi_end(); } #else // ESP32 -void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) +void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) { - // Faster range checking, possible because x and y are unsigned - if ((x >= _width) || (y >= _height)) return; + // Range checking + if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return; + spi_begin(); #ifdef CGRAM_OFFSET @@ -2154,72 +3249,52 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) y+=rowstart; #endif -#if !defined (RPI_ILI9486_DRIVER) - uint32_t xaw = ((uint32_t)x << 16) | x; - uint32_t yaw = ((uint32_t)y << 16) | y; -#endif - - CS_L; + DC_C; // No need to send x if it has not changed (speeds things up) if (addr_col != x) { - DC_C; - -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_CASET); -#else - SPI.write(TFT_CASET); -#endif + tft_Write_8(TFT_CASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t xBin[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; - SPI.writePattern(&xBin[0], 8, 1); + uint8_t xb[] = { 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), 0, (uint8_t) (x>>8), 0, (uint8_t) (x>>0), }; + spi.writePattern(&xb[0], 8, 1); #else - SPI.write32(xaw); + tft_Write_32(SPI_32(x, x)); #endif - + + DC_C; + addr_col = x; } // No need to send y if it has not changed (speeds things up) if (addr_row != y) { - DC_C; - -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_PASET); -#else - SPI.write(TFT_PASET); -#endif + tft_Write_8(TFT_PASET); DC_D; #if defined (RPI_ILI9486_DRIVER) - uint8_t yBin[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; - SPI.writePattern(&yBin[0], 8, 1); + uint8_t yb[] = { 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), 0, (uint8_t) (y>>8), 0, (uint8_t) (y>>0), }; + spi.writePattern(&yb[0], 8, 1); #else - SPI.write32(yaw); + tft_Write_32(SPI_32(y, y)); #endif + DC_C; + addr_row = y; } - DC_C; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_RAMWR); -#else - SPI.write(TFT_RAMWR); -#endif + tft_Write_8(TFT_RAMWR); DC_D; - SPI.write16(color); - - CS_H; + tft_Write_16(color); spi_end(); } @@ -2235,11 +3310,7 @@ void TFT_eSPI::pushColor(uint16_t color) { spi_begin(); - CS_L; - - SPI.write16(color); - - CS_H; + tft_Write_16(color); spi_end(); } @@ -2249,115 +3320,188 @@ void TFT_eSPI::pushColor(uint16_t color) ** Function name: pushColor ** Description: push a single colour to "len" pixels ***************************************************************************************/ -void TFT_eSPI::pushColor(uint16_t color, uint16_t len) +void TFT_eSPI::pushColor(uint16_t color, uint32_t len) { spi_begin(); - CS_L; - #ifdef RPI_WRITE_STROBE uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; - if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; + if(len) spi.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else - spiWriteBlock(color, len); + #if defined (ESP32_PARALLEL) + while (len--) {tft_Write_16(color);} + #else + writeBlock(color, len); + #endif #endif - CS_H; - spi_end(); } - /*************************************************************************************** -** Function name: pushColors -** Description: push an aray of pixels for BMP image drawing +** Function name: startWrite +** Description: begin transaction with CS low, MUST later call endWrite ***************************************************************************************/ -// Sends an array of 16-bit color values to the TFT; used -// externally by BMP examples. Assumes that setWindow() has -// previously been called to define the bounds. Max 255 pixels at -// a time (BMP examples read in small chunks due to limited RAM). - -void TFT_eSPI::pushColors(uint16_t *data, uint8_t len) +void TFT_eSPI::startWrite(void) { spi_begin(); + inTransaction = true; +} - CS_L; - -#if defined (ESP32) - - while (len--) SPI.write16(*(data++)); - -#else - - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - - SPI1U1 = (SPI1U1 & mask) | (63 << SPILMOSI) | (63 << SPILMISO); - while(len>3) - { - uint32_t color0 = (*(data) >> 8) | (uint16_t)(*(data) << 8); - data++; - color0 |= ((*(data) >> 8) | (*(data) << 8)) << 16; - data++; - uint32_t color1 = (*(data) >> 8) | (uint16_t)(*(data) << 8); - data++; - color1 |= ((*(data) >> 8) | (*(data) << 8)) << 16; - - data++; len -= 4; - while(SPI1CMD & SPIBUSY) {} - SPI1W0 = color0; - SPI1W1 = color1; - SPI1CMD |= SPIBUSY; - } - if (len) - { - while(SPI1CMD & SPIBUSY) {} - SPI1U1 = (SPI1U1 & mask) | (15 << SPILMOSI) | (15 << SPILMISO); - while(len--) - { - uint16_t color = (*(data) >> 8) | (*(data) << 8); - data++; - while(SPI1CMD & SPIBUSY) {} - SPI1W0 = color; - SPI1CMD |= SPIBUSY; - } - } - while(SPI1CMD & SPIBUSY) {} - -#endif - - CS_H; - +/*************************************************************************************** +** Function name: endWrite +** Description: end transaction with CS high +***************************************************************************************/ +void TFT_eSPI::endWrite(void) +{ + inTransaction = false; spi_end(); } +/*************************************************************************************** +** Function name: writeColor (use startWrite() and endWrite() before & after) +** Description: raw write of "len" pixels avoiding transaction check +***************************************************************************************/ +void TFT_eSPI::writeColor(uint16_t color, uint32_t len) +{ +#ifdef RPI_WRITE_STROBE + uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color }; + if(len) spi.writePattern(&colorBin[0], 2, 1); len--; + while(len--) {WR_L; WR_H;} +#else + #if defined (ESP32_PARALLEL) + while (len--) {tft_Write_16(color);} + #else + writeBlock(color, len); + #endif +#endif +} /*************************************************************************************** ** Function name: pushColors -** Description: push an aray of pixels for 16 bit raw image drawing +** Description: push an array of pixels for 16 bit raw image drawing ***************************************************************************************/ -// Assumed that setWindow() has previously been called +// Assumed that setAddrWindow() has previously been called void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) { spi_begin(); - CS_L; - #if defined (RPI_WRITE_STROBE) - //while ( len ) {SPI.writePattern(data, 2, 1); data += 2; len -= 2; } - while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } - if (len) SPI.writePattern(data, len, 1); + while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } + if (len) spi.writePattern(data, len, 1); #else - #if (SPI_FREQUENCY == 80000000) - while ( len >=64 ) {SPI.writePattern(data, 64, 1); data += 64; len -= 64; } - if (len) SPI.writePattern(data, len, 1); + #ifdef ESP32_PARALLEL + while (len--) {tft_Write_8(*data); data++;} + #elif defined (ILI9488_DRIVER) + uint16_t color; + while (len>1) {color = (*data++); color |= ((*data++)<<8); tft_Write_16(color); len-=2;} #else - SPI.writeBytes(data, len); + #if (SPI_FREQUENCY == 80000000) + while ( len >=64 ) {spi.writePattern(data, 64, 1); data += 64; len -= 64; } + if (len) spi.writePattern(data, len, 1); + #else + spi.writeBytes(data, len); + #endif #endif #endif - CS_H; + spi_end(); +} + + +/*************************************************************************************** +** Function name: pushColors +** Description: push an array of pixels, for image drawing +***************************************************************************************/ +void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) +{ + spi_begin(); + +#if defined (ESP32) || defined (ILI9488_DRIVER) + #if defined (ESP32_PARALLEL) || defined (ILI9488_DRIVER) + if (swap) while ( len-- ) {tft_Write_16(*data); data++;} + else while ( len-- ) {tft_Write_16S(*data); data++;} + #else + if (swap) spi.writePixels(data,len<<1); + else spi.writeBytes((uint8_t*)data,len<<1); + #endif +#else + + uint32_t color[8]; + + SPI1U1 = (255 << SPILMOSI) | (255 << SPILMISO); + + + while(len>15) + { + + if (swap) + { + uint32_t i = 0; + while(i<8) + { + color[i] = (*data >> 8) | (uint16_t)(*data << 8); + data++; + color[i] |= ((*data >> 8) | (*data << 8)) << 16; + data++; + i++; + } + } + else + { + memcpy(color,data,32); + data+=16; + } + + len -= 16; + + // ESP8266 wait time here at 40MHz SPI is ~5.45us + while(SPI1CMD & SPIBUSY) {} + SPI1W0 = color[0]; + SPI1W1 = color[1]; + SPI1W2 = color[2]; + SPI1W3 = color[3]; + SPI1W4 = color[4]; + SPI1W5 = color[5]; + SPI1W6 = color[6]; + SPI1W7 = color[7]; + SPI1CMD |= SPIBUSY; + } + + if(len) + { + uint32_t bits = (len*16-1); // bits left to shift - 1 + if (swap) + { + uint16_t* ptr = (uint16_t*)color; + while(len--) + { + *ptr++ = (*(data) >> 8) | (uint16_t)(*(data) << 8); + data++; + } + } + else + { + memcpy(color,data,len<<1); + } + while(SPI1CMD & SPIBUSY) {} + SPI1U1 = (bits << SPILMOSI) | (bits << SPILMISO); + SPI1W0 = color[0]; + SPI1W1 = color[1]; + SPI1W2 = color[2]; + SPI1W3 = color[3]; + SPI1W4 = color[4]; + SPI1W5 = color[5]; + SPI1W6 = color[6]; + SPI1W7 = color[7]; + SPI1CMD |= SPIBUSY; + } + + while(SPI1CMD & SPIBUSY) {} + +#endif spi_end(); } @@ -2368,13 +3512,13 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) ** Description: draw a line between 2 arbitrary points ***************************************************************************************/ // Bresenham's algorithm - thx wikipedia - speed enhanced by Bodmer to use -// an eficient FastH/V Line draw routine for line segments of 2 pixels or more +// an efficient FastH/V Line draw routine for line segments of 2 pixels or more -#if defined (RPI_ILI9486_DRIVER) || defined (ESP32) || defined (RPI_WRITE_STROBE) +#if defined (RPI_ILI9486_DRIVER) || defined (ESP32) || defined (RPI_WRITE_STROBE) || defined (HX8357D_DRIVER) || defined (ILI9488_DRIVER) void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { - spi_begin(); + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() inTransaction = true; boolean steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { @@ -2430,7 +3574,6 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t // This is a weeny bit faster void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { - spi_begin(); boolean steep = abs(y1 - y0) > abs(x1 - x0); @@ -2453,14 +3596,13 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t int16_t err = dx / 2; int8_t ystep = (y0 < y1) ? 1 : (-1); - uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); - mask = (SPI1U1 & mask) | (15 << SPILMOSI) | (15 << SPILMISO); - SPI1U = SPIUMOSI | SPIUSSE; + spi_begin(); + int16_t swapped_color = (color >> 8) | (color << 8); if (steep) // y increments every iteration (y0 is x-axis, and x0 is y-axis) { - if (x1 >= _height) x1 = _height - 1; + if (x1 >= (int32_t)_height) x1 = _height - 1; for (; x0 <= x1; x0++) { if ((x0 >= 0) && (y0 >= 0) && (y0 < _width)) break; @@ -2471,10 +3613,9 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t } } - if (x0 > x1) return; + if (x0 > x1) {spi_end(); return;} - setAddrWindow(y0, x0, y0, _height); - SPI1U1 = mask; + setWindow(y0, x0, y0, _height); SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { while(SPI1CMD & SPIBUSY) {} @@ -2486,8 +3627,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if ((y0 < 0) || (y0 >= _width)) break; err += dx; while(SPI1CMD & SPIBUSY) {} - setAddrWindow(y0, x0+1, y0, _height); - SPI1U1 = mask; + setWindow(y0, x0+1, y0, _height); SPI1W0 = swapped_color; } } @@ -2497,7 +3637,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t if (x1 >= _width) x1 = _width - 1; for (; x0 <= x1; x0++) { - if ((x0 >= 0) && (y0 >= 0) && (y0 < _height)) break; + if ((x0 >= 0) && (y0 >= 0) && (y0 < (int32_t)_height)) break; err -= dy; if (err < 0) { err += dx; @@ -2505,10 +3645,9 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t } } - if (x0 > x1) return; + if (x0 > x1) {spi_end(); return;} - setAddrWindow(x0, y0, _width, y0); - SPI1U1 = mask; + setWindow(x0, y0, _width, y0); SPI1W0 = swapped_color; for (; x0 <= x1; x0++) { while(SPI1CMD & SPIBUSY) {} @@ -2517,21 +3656,20 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t err -= dy; if (err < 0) { y0 += ystep; - if ((y0 < 0) || (y0 >= _height)) break; + if ((y0 < 0) || (y0 >= (int32_t)_height)) break; err += dx; while(SPI1CMD & SPIBUSY) {} - setAddrWindow(x0+1, y0, _width, y0); - SPI1U1 = mask; - SPI1W0 = swapped_color; + setWindow(x0+1, y0, _width, y0); + SPI1W0 = swapped_color; } } } while(SPI1CMD & SPIBUSY) {} - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; - CS_H; + spi_end(); } + #endif @@ -2542,18 +3680,21 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (h < 1)) return; - if ((y + h - 1) >= _height) h = _height - y; + // Clipping + if ((x < 0) || (x >= _width) || (y >= _height)) return; + + if (y < 0) { h += y; y = 0; } + + if ((y + h) > _height) h = _height - y; + + if (h < 1) return; spi_begin(); - setAddrWindow(x, y, x, y + h - 1); + setWindow(x, y, x, y + h - 1); - spiWriteBlock(color, h); + writeBlock(color, h); - CS_H; - spi_end(); } @@ -2561,13 +3702,18 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (h < 1)) return; - if ((y + h - 1) >= _height) h = _height - y; + // Clipping + if ((x < 0) || (x >= _width) || (y >= _height)) return; + + if (y < 0) { h += y; y = 0; } + + if ((y + h) > _height) h = _height - y; + + if (h < 1) return; spi_begin(); - setAddrWindow(x, y, x, y + h - 1); + setWindow(x, y, x, y + h - 1); #ifdef RPI_WRITE_STROBE #if defined (ESP8266) @@ -2575,17 +3721,18 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} #else - SPI.write16(color); + tft_Write_16(color); #endif - h--; - while(h--) {WR_L; WR_H;} + h--; + while(h--) {WR_L; WR_H;} #else - //while(h--) SPI.write16(color); - spiWriteBlock(color, h); + #ifdef ESP32_PARALLEL + while (h--) {tft_Write_16(color);} + #else + writeBlock(color, h); + #endif #endif - CS_H; - spi_end(); } #endif @@ -2597,18 +3744,21 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (w < 1)) return; - if ((x + w - 1) >= _width) w = _width - x; + // Clipping + if ((y < 0) || (x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + + if ((x + w) > _width) w = _width - x; + + if (w < 1) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y); + setWindow(x, y, x + w - 1, y); - spiWriteBlock(color, w); + writeBlock(color, w); - CS_H; - spi_end(); } @@ -2616,12 +3766,18 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) { - // Rudimentary clipping - if ((x >= _width) || (y >= _height) || (w < 1)) return; - if ((x + w - 1) >= _width) w = _width - x; + // Clipping + if ((y < 0) || (x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + + if ((x + w) > _width) w = _width - x; + + if (w < 1) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y); + + setWindow(x, y, x + w - 1, y); #ifdef RPI_WRITE_STROBE #if defined (ESP8266) @@ -2629,17 +3785,18 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} #else - SPI.write16(color); + tft_Write_16(color); #endif - w--; - while(w--) {WR_L; WR_H;} + w--; + while(w--) {WR_L; WR_H;} #else - //while(w--) SPI.write16(color); - spiWriteBlock(color, w); + #ifdef ESP32_PARALLEL + while (w--) {tft_Write_16(color);} + #else + writeBlock(color, w); + #endif #endif - CS_H; - spi_end(); } #endif @@ -2651,18 +3808,23 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - // rudimentary clipping (drawChar w/big text requires this) - if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; - if ((x + w - 1) > _width) w = _width - x; - if ((y + h - 1) > _height) h = _height - y; + // Clipping + if ((x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _width) w = _width - x; + if ((y + h) > _height) h = _height - y; + + if ((w < 1) || (h < 1)) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y + h - 1); - spiWriteBlock(color, w * h); + setWindow(x, y, x + w - 1, y + h - 1); + + writeBlock(color, w * h); - CS_H; - spi_end(); } @@ -2670,26 +3832,44 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - // rudimentary clipping (drawChar w/big text requires this) - if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; - if ((x + w - 1) > _width) w = _width - x; - if ((y + h - 1) > _height) h = _height - y; + + // Clipping + if ((x >= _width) || (y >= _height)) return; + + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + + if ((x + w) > _width) w = _width - x; + if ((y + h) > _height) h = _height - y; + + if ((w < 1) || (h < 1)) return; spi_begin(); - setAddrWindow(x, y, x + w - 1, y + h - 1); + + setWindow(x, y, x + w - 1, y + h - 1); uint32_t n = (uint32_t)w * (uint32_t)h; #ifdef RPI_WRITE_STROBE - if(n) {SPI.write16(color); n--;} + tft_Write_16(color); while(n--) {WR_L; WR_H;} #else - //while(n--) SPI.write16(color); - spiWriteBlock(color, n); + #ifdef ESP32_PARALLEL + if (color>>8 == (uint8_t)color) + { + tft_Write_8(color); + n--; WR_L; WR_H; + while (n) {WR_L; WR_H; n--; WR_L; WR_H;} + } + else + { + while (n--) {tft_Write_16(color);} + } + #else + writeBlock(color, n); + #endif #endif - CS_H; - spi_end(); } #endif @@ -2704,6 +3884,34 @@ uint16_t TFT_eSPI::color565(uint8_t r, uint8_t g, uint8_t b) } +/*************************************************************************************** +** Function name: color16to8 +** Description: convert 16 bit colour to an 8 bit 332 RGB colour value +***************************************************************************************/ +uint8_t TFT_eSPI::color16to8(uint16_t c) +{ + return ((c & 0xE000)>>8) | ((c & 0x0700)>>6) | ((c & 0x0018)>>3); +} + + +/*************************************************************************************** +** Function name: color8to16 +** Description: convert 8 bit colour to a 16 bit 565 colour value +***************************************************************************************/ +uint16_t TFT_eSPI::color8to16(uint8_t color) +{ + uint8_t blue[] = {0, 11, 21, 31}; // blue 2 to 5 bit colour lookup table + uint16_t color16 = 0; + + // =====Green===== ===============Red============== + color16 = (color & 0x1C)<<6 | (color & 0xC0)<<5 | (color & 0xE0)<<8; + // =====Green===== =======Blue====== + color16 |= (color & 0x1C)<<3 | blue[color & 0x03]; + + return color16; +} + + /*************************************************************************************** ** Function name: invertDisplay ** Description: invert the display colours i = 1 invert, i = 0 normal @@ -2718,6 +3926,136 @@ void TFT_eSPI::invertDisplay(boolean i) } +/************************************************************************** +** Function name: setAttribute +** Description: Sets a control parameter of an attribute +**************************************************************************/ +void TFT_eSPI::setAttribute(uint8_t attr_id, uint8_t param) { + switch (attr_id) { + break; + case 1: + _cp437 = param; + break; + case 2: + _utf8 = param; + decoderState = 0; + break; + //case 3: // TBD future feature control + // _tbd = param; + // break; + } +} + + +/************************************************************************** +** Function name: getAttribute +** Description: Get value of an attribute (control parameter) +**************************************************************************/ +uint8_t TFT_eSPI::getAttribute(uint8_t attr_id) { + switch (attr_id) { + case 1: // ON/OFF control of full CP437 character set + return _cp437; + break; + case 2: // ON/OFF control of UTF-8 decoding + return _utf8; + break; + //case 3: // TBD future feature control + // return _tbd; + // break; + } + + return false; +} + +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Serial UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +#define DECODE_UTF8 // Test only, comment out to stop decoding +uint16_t TFT_eSPI::decodeUTF8(uint8_t c) +{ +#ifdef DECODE_UTF8 + // 7 bit Unicode Code Point + if ((c & 0x80) == 0x00) { + decoderState = 0; + return (uint16_t)c; + } + + if (decoderState == 0) + { + // 11 bit Unicode Code Point + if ((c & 0xE0) == 0xC0) + { + decoderBuffer = ((c & 0x1F)<<6); + decoderState = 1; + return 0; + } + + // 16 bit Unicode Code Point + if ((c & 0xF0) == 0xE0) + { + decoderBuffer = ((c & 0x0F)<<12); + decoderState = 2; + return 0; + } + // 21 bit Unicode Code Point not supported so fall-back to extended ASCII + // if ((c & 0xF8) == 0xF0) return (uint16_t)c; + } + else + { + if (decoderState == 2) + { + decoderBuffer |= ((c & 0x3F)<<6); + decoderState--; + return 0; + } + else + { + decoderBuffer |= (c & 0x3F); + decoderState = 0; + return decoderBuffer; + } + } + + decoderState = 0; +#endif + + return (uint16_t)c; // fall-back to extended ASCII +} + + +/*************************************************************************************** +** Function name: decodeUTF8 +** Description: Line buffer UTF-8 decoder with fall-back to extended ASCII +*************************************************************************************x*/ +uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) +{ + uint16_t c = buf[(*index)++]; + //Serial.print("Byte from string = 0x"); Serial.println(c, HEX); + +#ifdef DECODE_UTF8 + // 7 bit Unicode + if ((c & 0x80) == 0x00) return c; + + // 11 bit Unicode + if (((c & 0xE0) == 0xC0) && (remaining > 1)) + return ((c & 0x1F)<<6) | (buf[(*index)++]&0x3F); + + // 16 bit Unicode + if (((c & 0xF0) == 0xE0) && (remaining > 2)) + { + c = ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6); + return c | ((buf[(*index)++]&0x3F)); + } + + // 21 bit Unicode not supported so fall-back to extended ASCII + // if ((c & 0xF8) == 0xF0) return c; +#endif + + return c; // fall-back to extended ASCII +} + + /*************************************************************************************** ** Function name: write ** Description: draw characters piped through serial stream @@ -2726,8 +4064,35 @@ size_t TFT_eSPI::write(uint8_t utf8) { if (utf8 == '\r') return 1; - uint8_t uniCode = utf8; // Work with a copy - if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors + uint16_t uniCode = utf8; + + if (_utf8) uniCode = decodeUTF8(utf8); + + if (uniCode == 0) return 1; + +#ifdef SMOOTH_FONT + if(fontLoaded) + { + //Serial.print("UniCode="); Serial.println(uniCode); + //Serial.print("UTF8 ="); Serial.println(utf8); + + //fontFile = SPIFFS.open( _gFontFilename, "r" ); + + //if(!fontFile) + //{ + // fontLoaded = false; + // return 1; + //} + + drawGlyph(uniCode); + + //fontFile.close(); + return 1; + } +#endif + + if (uniCode == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (uniCode < 32) return 1; uint16_t width = 0; uint16_t height = 0; @@ -2747,12 +4112,13 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { - // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) + if (uniCode > 127) return 1; + width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; // Font 2 is rendered in whole byte widths so we must allow for this width = (width + 6) / 8; // Width in whole bytes for font 2, should be + 7 but must allow for font width change - width = width * 8; // Width converted back to pixles + width = width * 8; // Width converted back to pixels } #ifdef LOAD_RLE else @@ -2763,8 +4129,8 @@ size_t TFT_eSPI::write(uint8_t utf8) { if ((textfont>2) && (textfont<9)) { + if (uniCode > 127) return 1; // Uses the fontinfo struct array to avoid lots of 'if' or 'switch' statements - // A tad slower than above but this is not significant and is more convenient for the RLE fonts width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[textfont].widthtbl ) ) + uniCode-32 ); height= pgm_read_byte( &fontdata[textfont].height ); } @@ -2778,7 +4144,7 @@ size_t TFT_eSPI::write(uint8_t utf8) height = 8; } #else - if (textfont==1) return 0; + if (textfont==1) return 1; #endif height = height * textsize; @@ -2789,11 +4155,12 @@ size_t TFT_eSPI::write(uint8_t utf8) } else { - if (textwrap && (cursor_x + width * textsize > _width)) + if (textwrapX && (cursor_x + width * textsize > _width)) { cursor_y += height; cursor_x = 0; } + if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0; cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont); } @@ -2802,33 +4169,31 @@ size_t TFT_eSPI::write(uint8_t utf8) } // Custom GFX font else { - if(utf8 == '\n') { cursor_x = 0; cursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); - } else if(uniCode != '\r') { - if (uniCode > (uint8_t)pgm_read_byte(&gfxFont->last)) uniCode = pgm_read_byte(&gfxFont->first); + } else { + if (uniCode > pgm_read_word(&gfxFont->last )) return 1; + if (uniCode < pgm_read_word(&gfxFont->first)) return 1; - if(uniCode >= pgm_read_byte(&gfxFont->first)) { - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height); - if((w > 0) && (h > 0)) { // Is there an associated bitmap? - int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); - if(textwrap && ((cursor_x + textsize * (xo + w)) > _width)) { - // Drawing character would go off right edge; wrap to new line - cursor_x = 0; - cursor_y += (int16_t)textsize * - (uint8_t)pgm_read_byte(&gfxFont->yAdvance); - } - drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize); + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + uint8_t w = pgm_read_byte(&glyph->width), + h = pgm_read_byte(&glyph->height); + if((w > 0) && (h > 0)) { // Is there an associated bitmap? + int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); + if(textwrapX && ((cursor_x + textsize * (xo + w)) > _width)) { + // Drawing character would go off right edge; wrap to new line + cursor_x = 0; + cursor_y += (int16_t)textsize * + (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } - cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; + if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0; + drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize); } + cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize; } - } #endif // LOAD_GFXFF //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @@ -2839,15 +4204,18 @@ size_t TFT_eSPI::write(uint8_t utf8) /*************************************************************************************** ** Function name: drawChar -** Description: draw a unicode onto the screen +** Description: draw a Unicode glyph onto the screen ***************************************************************************************/ -int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y) + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y) { - return drawChar(uniCode, x, y, textfont); + return drawChar(uniCode, x, y, textfont); } -int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) + // Any UTF-8 decoding must be done before calling drawChar() +int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) { + if (!uniCode) return 0; if (font==1) { @@ -2873,11 +4241,9 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } else { - if (uniCode > pgm_read_byte(&gfxFont->last)) uniCode = pgm_read_byte(&gfxFont->first); - - if(uniCode >= pgm_read_byte(&gfxFont->first)) + if((uniCode >= pgm_read_word(&gfxFont->first)) && (uniCode <= pgm_read_word(&gfxFont->last) )) { - uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); + uint16_t c2 = uniCode - pgm_read_word(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); return pgm_read_byte(&glyph->xAdvance) * textsize; } @@ -2889,15 +4255,16 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) #endif } - int width = 0; - int height = 0; + if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; + + int32_t width = 0; + int32_t height = 0; uint32_t flash_address = 0; uniCode -= 32; #ifdef LOAD_FONT2 if (font == 2) { - // This is faster than using the fontdata structure flash_address = pgm_read_dword(&chrtbl_f16[uniCode]); width = pgm_read_byte(widtbl_f16 + uniCode); height = chr_hgt_f16; @@ -2911,18 +4278,17 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) { if ((font>2) && (font<9)) { - // This is slower than above but is more convenient for the RLE fonts - flash_address = pgm_read_dword( pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *) ); + flash_address = pgm_read_dword( (const void*)(pgm_read_dword( &(fontdata[font].chartbl ) ) + uniCode*sizeof(void *)) ); width = pgm_read_byte( (uint8_t *)pgm_read_dword( &(fontdata[font].widthtbl ) ) + uniCode ); height= pgm_read_byte( &fontdata[font].height ); } } #endif - int w = width; - int pX = 0; - int pY = y; - byte line = 0; + int32_t w = width; + int32_t pX = 0; + int32_t pY = y; + uint8_t line = 0; #ifdef LOAD_FONT2 // chop out code if we do not need it if (font == 2) { @@ -2931,12 +4297,14 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) if (x + width * textsize >= (int16_t)_width) return width * textsize ; if (textcolor == textbgcolor || textsize != 1) { + //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + inTransaction = true; - for (int i = 0; i < height; i++) + for (int32_t i = 0; i < height; i++) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); - for (int k = 0; k < w; k++) + for (int32_t k = 0; k < w; k++) { line = pgm_read_byte((uint8_t *)flash_address + w * i + k); if (line) { @@ -2966,35 +4334,35 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } pY += textsize; } + + inTransaction = false; + spi_end(); } else // Faster drawing of characters and background using block write { spi_begin(); - setAddrWindow(x, y, (x + w * 8) - 1, y + height - 1); - byte mask; - for (int i = 0; i < height; i++) + setWindow(x, y, x + width - 1, y + height - 1); + + uint8_t mask; + for (int32_t i = 0; i < height; i++) { - for (int k = 0; k < w; k++) + pX = width; + for (int32_t k = 0; k < w; k++) { - line = pgm_read_byte((uint8_t *)flash_address + w * i + k); - pX = x + k * 8; + line = pgm_read_byte((uint8_t *) (flash_address + w * i + k) ); mask = 0x80; - while (mask) { - if (line & mask) { - SPI.write16(textcolor); - } - else { - SPI.write16(textbgcolor); - } + while (mask && pX) { + if (line & mask) {tft_Write_16(textcolor);} + else {tft_Write_16(textbgcolor);} + pX--; mask = mask >> 1; } } - pY += textsize; + if (pX) {tft_Write_16(textbgcolor);} } - CS_H; spi_end(); } } @@ -3008,22 +4376,23 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) // Font is not 2 and hence is RLE encoded { spi_begin(); + inTransaction = true; w *= height; // Now w is total number of pixels in the character if ((textsize != 1) || (textcolor == textbgcolor)) { if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor); - int px = 0, py = pY; // To hold character block start and end column and row values - int pc = 0; // Pixel count - byte np = textsize * textsize; // Number of pixels in a drawn pixel + int32_t px = 0, py = pY; // To hold character block start and end column and row values + int32_t pc = 0; // Pixel count + uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel - byte tnp = 0; // Temporary copy of np for while loop - byte ts = textsize - 1; // Temporary copy of textsize + uint8_t tnp = 0; // Temporary copy of np for while loop + uint8_t ts = textsize - 1; // Temporary copy of textsize // 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area // w is total number of pixels to plot to fill character block while (pc < w) { line = pgm_read_byte((uint8_t *)flash_address); - flash_address++; // 20 bytes smaller by incrementing here + flash_address++; if (line & 0x80) { line &= 0x7F; line++; @@ -3037,17 +4406,13 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) } while (line--) { // In this case the while(line--) is faster pc++; // This is faster than putting pc+=line before while()? - setAddrWindow(px, py, px + ts, py + ts); + setWindow(px, py, px + ts, py + ts); if (ts) { tnp = np; - while (tnp--) { - SPI.write16(textcolor); - } - } - else { - SPI.write16(textcolor); + while (tnp--) {tft_Write_16(textcolor);} } + else {tft_Write_16(textcolor);} px += textsize; if (px >= (x + width * textsize)) @@ -3062,18 +4427,16 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) pc += line; } } - - CS_H; - spi_end(); } else // Text colour != background && textsize = 1 // so use faster drawing of characters and background using block write { - //spi_begin(); - setAddrWindow(x, y, x + width - 1, y + height - 1); + setWindow(x, y, x + width - 1, y + height - 1); +#ifdef RPI_WRITE_STROBE uint8_t textcolorBin[] = { (uint8_t) (textcolor >> 8), (uint8_t) textcolor }; uint8_t textbgcolorBin[] = { (uint8_t) (textbgcolor >> 8), (uint8_t) textbgcolor }; +#endif // Maximum font size is equivalent to 180x180 pixels in area while (w > 0) @@ -3083,25 +4446,33 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) line &= 0x7F; line++; w -= line; #ifdef RPI_WRITE_STROBE - SPI.writePattern(&textcolorBin[0], 2, 1); line--; + spi.writePattern(&textcolorBin[0], 2, 1); line--; while(line--) {WR_L; WR_H;} #else - spiWriteBlock(textcolor,line); + #ifdef ESP32_PARALLEL + while (line--) {tft_Write_16(textcolor);} + #else + writeBlock(textcolor,line); + #endif #endif } else { line++; w -= line; #ifdef RPI_WRITE_STROBE - SPI.writePattern(&textbgcolorBin[0], 2, 1); line--; + spi.writePattern(&textbgcolorBin[0], 2, 1); line--; while(line--) {WR_L; WR_H;} #else - spiWriteBlock(textbgcolor,line); + #ifdef ESP32_PARALLEL + while (line--) {tft_Write_16(textbgcolor);} + #else + writeBlock(textbgcolor,line); + #endif #endif } } - CS_H; - spi_end(); } + inTransaction = false; + spi_end(); } // End of RLE font rendering #endif @@ -3114,7 +4485,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) ** Description : draw string with padding if it is defined ***************************************************************************************/ // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const String& string, int poX, int poY) +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY) { int16_t len = string.length() + 2; char buffer[len]; @@ -3122,7 +4493,7 @@ int16_t TFT_eSPI::drawString(const String& string, int poX, int poY) return drawString(buffer, poX, poY, textfont); } // With font number -int16_t TFT_eSPI::drawString(const String& string, int poX, int poY, int font) +int16_t TFT_eSPI::drawString(const String& string, int32_t poX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -3131,43 +4502,56 @@ int16_t TFT_eSPI::drawString(const String& string, int poX, int poY, int font) } // Without font number, uses font set by setTextFont() -int16_t TFT_eSPI::drawString(const char *string, int poX, int poY) +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY) { return drawString(string, poX, poY, textfont); } -// With font number -int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) + +// With font number. Note: font number is over-ridden if a smooth font is loaded +int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8_t font) { int16_t sumX = 0; uint8_t padding = 1, baseline = 0; uint16_t cwidth = textWidth(string, font); // Find the pixel width of the string in the font - uint16_t cheight = 8; + uint16_t cheight = 8 * textsize; #ifdef LOAD_GFXFF - if (font == 1) { - if(gfxFont) { - cheight = glyph_ab * textsize; - poY += cheight; // Adjust for baseline datum of free fonts - baseline = cheight; - padding =101; // Different padding method used for Free Fonts + #ifdef SMOOTH_FONT + bool freeFont = (font == 1 && gfxFont && !fontLoaded); + #else + bool freeFont = (font == 1 && gfxFont); + #endif - // We need to make an adjustment for the botom of the string (eg 'y' character) - if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) { - cheight += glyph_bb * textsize; - } + if (freeFont) { + cheight = glyph_ab * textsize; + poY += cheight; // Adjust for baseline datum of free fonts + baseline = cheight; + padding =101; // Different padding method used for Free Fonts + + // We need to make an adjustment for the bottom of the string (eg 'y' character) + if ((textdatum == BL_DATUM) || (textdatum == BC_DATUM) || (textdatum == BR_DATUM)) { + cheight += glyph_bb * textsize; } } #endif + + // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font +#ifdef SMOOTH_FONT + if(fontLoaded) { + baseline = gFont.maxAscent; + cheight = fontHeight(); + } + else +#endif + if (font!=1) { + baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; + cheight = fontHeight(font); + } + if (textdatum || padX) { - // If it is not font 1 (GLCD or free font) get the basline and pixel height of the font - if (font!=1) { - baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; - cheight = fontHeight(font); - } - switch(textdatum) { case TC_DATUM: poX -= cwidth/2; @@ -3222,33 +4606,72 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) } // Check coordinates are OK, adjust if not if (poX < 0) poX = 0; - if (poX+cwidth>_width) poX = _width - cwidth; + if (poX+cwidth > width()) poX = width() - cwidth; if (poY < 0) poY = 0; - if (poY+cheight-baseline>_height) poY = _height - cheight; + if (poY+cheight-baseline> height()) poY = height() - cheight; } int8_t xo = 0; #ifdef LOAD_GFXFF - if ((font == 1) && (gfxFont) && (textcolor!=textbgcolor)) + if (freeFont && (textcolor!=textbgcolor)) { cheight = (glyph_ab + glyph_bb) * textsize; // Get the offset for the first character only to allow for negative offsets - uint8_t c2 = *string - pgm_read_byte(&gfxFont->first); - GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); - xo = pgm_read_byte(&glyph->xOffset) * textsize; - // Adjust for negative xOffset, also see line 3095 below - //if (xo < 0) - cwidth -= xo; - // Add 1 pixel of padding all round - //cheight +=2; - //fillRect(poX+xo-1, poY - 1 - glyph_ab * textsize, cwidth+2, cheight, textbgcolor); - fillRect(poX+xo, poY - glyph_ab * textsize, cwidth, cheight, textbgcolor); + uint16_t c2 = 0; + uint16_t len = strlen(string); + uint16_t n = 0; + + while (n < len && c2 == 0) c2 = decodeUTF8((uint8_t*)string, &n, len - n); + + if((c2 >= pgm_read_word(&gfxFont->first)) && (c2 <= pgm_read_word(&gfxFont->last) )) + { + c2 -= pgm_read_word(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); + xo = pgm_read_byte(&glyph->xOffset) * textsize; + // Adjust for negative xOffset + if (xo > 0) xo = 0; + else cwidth -= xo; + // Add 1 pixel of padding all round + //cheight +=2; + //fillRect(poX+xo-1, poY - 1 - glyph_ab * textsize, cwidth+2, cheight, textbgcolor); + fillRect(poX+xo, poY - glyph_ab * textsize, cwidth, cheight, textbgcolor); + } padding -=100; } #endif - while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); + uint16_t len = strlen(string); + uint16_t n = 0; + +#ifdef SMOOTH_FONT + if(fontLoaded) + { + if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor); + //drawLine(poX - 5, poY, poX + 5, poY, TFT_GREEN); + //drawLine(poX, poY - 5, poX, poY + 5, TFT_GREEN); + //fontFile = SPIFFS.open( _gFontFilename, "r"); + if(!fontFile) return 0; + + setCursor(poX, poY); + + while (n < len) + { + uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n); + drawGlyph(uniCode); + } + sumX += cwidth; + //fontFile.close(); + } + else +#endif + { + while (n < len) + { + uint16_t uniCode = decodeUTF8((uint8_t*)string, &n, len - n); + sumX += drawChar(uniCode, poX+sumX, poY, font); + } + } //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Switch on debugging for the padding areas @@ -3261,10 +4684,11 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) { int16_t padXc = poX+cwidth+xo; #ifdef LOAD_GFXFF - if ((font == 1) && (gfxFont)) + if (freeFont) { poX +=xo; // Adjust for negative offset start character poY -= glyph_ab * textsize; + sumX += poX; } #endif switch(padding) { @@ -3325,7 +4749,7 @@ return sumX; ** Function name: drawCentreString (deprecated, use setTextDatum()) ** Descriptions: draw string centred on dX ***************************************************************************************/ -int16_t TFT_eSPI::drawCentreString(const String& string, int dX, int poY, int font) +int16_t TFT_eSPI::drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -3333,10 +4757,10 @@ int16_t TFT_eSPI::drawCentreString(const String& string, int dX, int poY, int fo return drawCentreString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawCentreString(const char *string, int dX, int poY, int font) +int16_t TFT_eSPI::drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font) { - static byte tempdatum = textdatum; - int sumX = 0; + uint8_t tempdatum = textdatum; + int32_t sumX = 0; textdatum = TC_DATUM; sumX = drawString(string, dX, poY, font); textdatum = tempdatum; @@ -3348,7 +4772,7 @@ int16_t TFT_eSPI::drawCentreString(const char *string, int dX, int poY, int font ** Function name: drawRightString (deprecated, use setTextDatum()) ** Descriptions: draw string right justified to dX ***************************************************************************************/ -int16_t TFT_eSPI::drawRightString(const String& string, int dX, int poY, int font) +int16_t TFT_eSPI::drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font) { int16_t len = string.length() + 2; char buffer[len]; @@ -3356,9 +4780,9 @@ int16_t TFT_eSPI::drawRightString(const String& string, int dX, int poY, int fon return drawRightString(buffer, dX, poY, font); } -int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) +int16_t TFT_eSPI::drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font) { - static byte tempdatum = textdatum; + uint8_t tempdatum = textdatum; int16_t sumX = 0; textdatum = TR_DATUM; sumX = drawString(string, dX, poY, font); @@ -3371,15 +4795,17 @@ int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) ** Function name: drawNumber ** Description: draw a long integer ***************************************************************************************/ -int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY) +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY) { + isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); return drawString(str, poX, poY, textfont); } -int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font) +int16_t TFT_eSPI::drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font) { + isDigits = true; // Eliminate jiggle in monospaced fonts char str[12]; ltoa(long_num, str, 10); return drawString(str, poX, poY, font); @@ -3392,13 +4818,14 @@ int16_t TFT_eSPI::drawNumber(long long_num, int poX, int poY, int font) ***************************************************************************************/ // Assemble and print a string, this permits alignment relative to a datum // looks complicated but much more compact and actually faster than using print class -int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY) +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY) { return drawFloat(floatNumber, dp, poX, poY, textfont); } -int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int font) +int16_t TFT_eSPI::drawFloat(float floatNumber, uint8_t dp, int32_t poX, int32_t poY, uint8_t font) { + isDigits = true; char str[14]; // Array to contain decimal string uint8_t ptr = 0; // Initialise pointer for array int8_t digits = 1; // Count the digits to avoid array overflow @@ -3427,7 +4854,7 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int fon // No chance of overflow from here on // Get integer part - unsigned long temp = (unsigned long)floatNumber; + uint32_t temp = (uint32_t)floatNumber; // Put integer part into array ltoa(temp, str + ptr, 10); @@ -3470,12 +4897,18 @@ int16_t TFT_eSPI::drawFloat(float floatNumber, int dp, int poX, int poY, int fon void TFT_eSPI::setFreeFont(const GFXfont *f) { + if (f == nullptr) // Fix issue #400 (ESP32 crash) + { + setTextFont(1); // Use GLCD font + return; + } + textfont = 1; gfxFont = (GFXfont *)f; glyph_ab = 0; glyph_bb = 0; - uint8_t numChars = pgm_read_byte(&gfxFont->last) - pgm_read_byte(&gfxFont->first); + uint16_t numChars = pgm_read_word(&gfxFont->last) - pgm_read_word(&gfxFont->first); // Find the biggest above and below baseline offsets for (uint8_t c = 0; c < numChars; c++) @@ -3527,17 +4960,20 @@ void TFT_eSPI::setTextFont(uint8_t f) /*************************************************************************************** -** Function name: spiBlockWrite +** Function name: writeBlock ** Description: Write a block of pixels of the same colour ***************************************************************************************/ -#if defined (ESP8266) && (SPI_FREQUENCY != 80000000) -void spiWriteBlock(uint16_t color, uint32_t repeat) +//Clear screen test 76.8ms theoretical. 81.5ms TFT_eSPI, 967ms Adafruit_ILI9341 +//Performance 26.15Mbps@26.66MHz, 39.04Mbps@40MHz, 75.4Mbps@80MHz SPI clock +//Efficiency: +// TFT_eSPI 98.06% 97.59% 94.24% +// Adafruit_GFX 19.62% 14.31% 7.94% +// +#if defined (ESP8266) && !defined (ILI9488_DRIVER) +void writeBlock(uint16_t color, uint32_t repeat) { uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; - uint32_t mask = ~(SPIMMOSI << SPILMOSI); - mask = SPI1U1 & mask; - SPI1U = SPIUMOSI | SPIUSSE; SPI1W0 = color32; SPI1W1 = color32; @@ -3566,9 +5002,12 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) } if (repeat > 31) { - SPI1U1 = mask | (511 << SPILMOSI); + SPI1U1 = (511 << SPILMOSI); while(repeat>31) { +#if defined SPI_FREQUENCY && (SPI_FREQUENCY == 80000000) + if(SPI1CMD & SPIBUSY) // added to sync with flag change +#endif while(SPI1CMD & SPIBUSY) {} SPI1CMD |= SPIBUSY; repeat -= 32; @@ -3579,185 +5018,355 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) if (repeat) { repeat = (repeat << 4) - 1; - SPI1U1 = mask | (repeat << SPILMOSI); + SPI1U1 = (repeat << SPILMOSI); SPI1CMD |= SPIBUSY; while(SPI1CMD & SPIBUSY) {} } - SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE; -} -#elif ESP8266 // ESP32 or a ESP8266 running at 80MHz SPI so slow things down - -#define BUFFER_SIZE 64 -void spiWriteBlock(uint16_t color, uint32_t repeat) -{ - - uint8_t colorBin[] = { (uint8_t) (color >> 8), (uint8_t) color}; - SPI.writePattern(&colorBin[0], 2, repeat); - } -#else // Low level register based ESP32 code +#elif defined (ILI9488_DRIVER) -#include "soc/spi_reg.h" -#define SPI_NUM 0x3 - -void spiWriteBlock(uint16_t color, uint32_t repeat) +#ifdef ESP8266 +void writeBlock(uint16_t color, uint32_t repeat) { - uint16_t color16 = (color >> 8) | (color << 8); - uint32_t color32 = color16 | color16 << 16; - if (repeat > 15) + // Split out the colours + uint8_t r = (color & 0xF800)>>8; + uint8_t g = (color & 0x07E0)>>3; + uint8_t b = (color & 0x001F)<<3; + // Concatenate 4 pixels into three 32 bit blocks + uint32_t r0 = r<<24 | b<<16 | g<<8 | r; + uint32_t r1 = g<<24 | r<<16 | b<<8 | g; + uint32_t r2 = b<<24 | g<<16 | r<<8 | b; + + SPI1W0 = r0; + SPI1W1 = r1; + SPI1W2 = r2; + + if (repeat > 4) { - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, 255, SPI_USR_MOSI_DBITLEN_S); + SPI1W3 = r0; + SPI1W4 = r1; + SPI1W5 = r2; + } + if (repeat > 8) + { + SPI1W6 = r0; + SPI1W7 = r1; + SPI1W8 = r2; + } + if (repeat > 12) + { + SPI1W9 = r0; + SPI1W10 = r1; + SPI1W11 = r2; + SPI1W12 = r0; + SPI1W13 = r1; + SPI1W14 = r2; + SPI1W15 = r0; + } - while(repeat>15) + if (repeat > 20) + { + SPI1U1 = (503 << SPILMOSI); + while(repeat>20) { - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); - for (uint32_t i=0; i<16; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - repeat -= 16; + while(SPI1CMD & SPIBUSY) {} + SPI1CMD |= SPIBUSY; + repeat -= 21; } - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + while(SPI1CMD & SPIBUSY) {} } if (repeat) { - repeat = (repeat << 4) - 1; - SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_NUM), SPI_USR_MOSI_DBITLEN, repeat, SPI_USR_MOSI_DBITLEN_S); - for (uint32_t i=0; i<16; i++) WRITE_PERI_REG((SPI_W0_REG(SPI_NUM) + (i << 2)), color32); - SET_PERI_REG_MASK(SPI_CMD_REG(SPI_NUM), SPI_USR); - while (READ_PERI_REG(SPI_CMD_REG(SPI_NUM))&SPI_USR); + repeat = (repeat * 24) - 1; + SPI1U1 = (repeat << SPILMOSI); + SPI1CMD |= SPIBUSY; + while(SPI1CMD & SPIBUSY) {} + } + +} +#else // Now the code for ESP32 and ILI9488 + +void writeBlock(uint16_t color, uint32_t repeat) +{ + // Split out the colours + uint32_t r = (color & 0xF800)>>8; + uint32_t g = (color & 0x07E0)<<5; + uint32_t b = (color & 0x001F)<<19; + // Concatenate 4 pixels into three 32 bit blocks + uint32_t r0 = r<<24 | b | g | r; + uint32_t r1 = r0>>8 | g<<16; + uint32_t r2 = r1>>8 | b<<8; + + if (repeat > 19) + { + SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, 479, SPI_USR_MOSI_DBITLEN_S); + + while(repeat>19) + { + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + repeat -= 20; + } + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + } + + if (repeat) + { + SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(SPI_PORT), SPI_USR_MOSI_DBITLEN, (repeat * 24) - 1, SPI_USR_MOSI_DBITLEN_S); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), r2); + if (repeat > 8 ) + { + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), r2); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), r0); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), r1); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), r2); + } + + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); } } #endif -/*************************************************** - The majority of code in this file is "FunWare", the only condition of use of - those portions is that users have fun! Most of the effort has been spent on - the creation and incorporation of the proportional Run Length Encoded fonts - that can be rendered over an SPI bus at high speeds. - - A significant number of new features have been added to the original source - libraries. Functions names have been retained where practical to allow old - Adafruit_GFX TFT screen compatible sketches to be easily adapted. - - A significant level of effort has been made to optimise the library for speed - so that graphics intensive sketches can run at an acceptable speed over the - SPI bus. SPI bus speeds up to 80MHz can be used with some driver chips. At - this clock rate screen and block clears can achieve an average bit rate of - 75Mbps. - - The functions incldued are comaptible with the JPEGDecoder library here: - https://github.com/Bodmer/JPEGDecoder +#else // Low level register based ESP32 code for 16 bit colour SPI TFTs - This allows allows the ESP8266 (or ESP32) sketches to retrieve images from the - internet, store them in SPIFFS and render the images to the screen at an - acceptable speed. So some really cool IoT sketches are possible without tedious - manual loading of images. - - Other portions of code are protected by the licenses as noted below. +void writeBlock(uint16_t color, uint32_t repeat) +{ + uint32_t color32 = COL_32(color, color); - The library would not have been created without the initial inspiration from - Adafruit_ILI9341 and Adafruit_GFX libraries. + if (repeat > 31) // Revert legacy toggle buffer change + { + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 511); + while(repeat>31) + { + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W1_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W2_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W3_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W4_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W5_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W6_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W7_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W8_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W9_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W10_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W11_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W12_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W13_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W14_REG(SPI_PORT), color32); + WRITE_PERI_REG(SPI_W15_REG(SPI_PORT), color32); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + repeat -= 32; + } + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + } + + if (repeat) + { + // Revert toggle buffer change + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), (repeat << 4) - 1); + for (uint32_t i=0; i <= (repeat>>1); i++) WRITE_PERI_REG((SPI_W0_REG(SPI_PORT) + (i << 2)), color32); + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + } +} +#endif - If any other conditions of use have been missed then please raise this as an - issue on GitHub: +/*************************************************************************************** +** Function name: getSPIinstance +** Description: Get the instance of the SPI class (for ESP32 only) +***************************************************************************************/ +#ifndef ESP32_PARALLEL +SPIClass& TFT_eSPI::getSPIinstance(void) +{ + return spi; +} +#endif -/*************************************************** - The Adafruit_ILI9341 library has been used as a starting point - for this library. +/*************************************************************************************** +** Function name: getSetup +** Description: Get the setup details for diagnostic and sketch access +***************************************************************************************/ +void TFT_eSPI::getSetup(setup_t &tft_settings) +{ +// tft_settings.version is set in header file - ORIGINAL LIBRARY HEADER +#if defined (ESP8266) + tft_settings.esp = 8266; +#elif defined (ESP32) + tft_settings.esp = 32; +#else + tft_settings.esp = -1; +#endif - This is our library for the Adafruit ILI9341 Breakout and Shield - ----> http://www.adafruit.com/products/1651 +#if defined (SUPPORT_TRANSACTIONS) + tft_settings.trans = true; +#else + tft_settings.trans = false; +#endif - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! +#if defined (ESP32_PARALLEL) + tft_settings.serial = false; + tft_settings.tft_spi_freq = 0; +#else + tft_settings.serial = true; + tft_settings.tft_spi_freq = SPI_FREQUENCY/100000; + #ifdef SPI_READ_FREQUENCY + tft_settings.tft_rd_freq = SPI_READ_FREQUENCY/100000; + #endif +#endif - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution +#if defined(TFT_SPI_OVERLAP) + tft_settings.overlap = true; +#else + tft_settings.overlap = false; +#endif - ****************************************************/ + tft_settings.tft_driver = TFT_DRIVER; + tft_settings.tft_width = _init_width; + tft_settings.tft_height = _init_height; +#ifdef CGRAM_OFFSET + tft_settings.r0_x_offset = colstart; + tft_settings.r0_y_offset = rowstart; + tft_settings.r1_x_offset = 0; + tft_settings.r1_y_offset = 0; + tft_settings.r2_x_offset = 0; + tft_settings.r2_y_offset = 0; + tft_settings.r3_x_offset = 0; + tft_settings.r3_y_offset = 0; +#else + tft_settings.r0_x_offset = 0; + tft_settings.r0_y_offset = 0; + tft_settings.r1_x_offset = 0; + tft_settings.r1_y_offset = 0; + tft_settings.r2_x_offset = 0; + tft_settings.r2_y_offset = 0; + tft_settings.r3_x_offset = 0; + tft_settings.r3_y_offset = 0; +#endif -/**************************************************** +#if defined (TFT_MOSI) + tft_settings.pin_tft_mosi = TFT_MOSI; +#else + tft_settings.pin_tft_mosi = -1; +#endif - Some member funtions have been imported from the Adafruit_GFX - library. The license associated with these is reproduced below. +#if defined (TFT_MISO) + tft_settings.pin_tft_miso = TFT_MISO; +#else + tft_settings.pin_tft_miso = -1; +#endif - ORIGINAL LIBRARY HEADER from Adafruit_GFX.cpp +#if defined (TFT_SCLK) + tft_settings.pin_tft_clk = TFT_SCLK; +#else + tft_settings.pin_tft_clk = -1; +#endif - This is the core graphics library for all our displays, providing a common - set of graphics primitives (points, lines, circles, etc.). It needs to be - paired with a hardware-specific library for each display device we carry - (to handle the lower-level functions). +#if defined (TFT_CS) + tft_settings.pin_tft_cs = TFT_CS; +#else + tft_settings.pin_tft_cs = -1; +#endif - Adafruit invests time and resources providing this open source code, please - support Adafruit & open-source hardware by purchasing products from Adafruit! +#if defined (TFT_DC) + tft_settings.pin_tft_dc = TFT_DC; +#else + tft_settings.pin_tft_dc = -1; +#endif - Copyright (c) 2013 Adafruit Industries. All rights reserved. +#if defined (TFT_RD) + tft_settings.pin_tft_rd = TFT_RD; +#else + tft_settings.pin_tft_rd = -1; +#endif - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: +#if defined (TFT_WR) + tft_settings.pin_tft_wr = TFT_WR; +#else + tft_settings.pin_tft_wr = -1; +#endif -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. +#if defined (TFT_RST) + tft_settings.pin_tft_rst = TFT_RST; +#else + tft_settings.pin_tft_rst = -1; +#endif - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. +#if defined (ESP32_PARALLEL) + tft_settings.pin_tft_d0 = TFT_D0; + tft_settings.pin_tft_d1 = TFT_D1; + tft_settings.pin_tft_d2 = TFT_D2; + tft_settings.pin_tft_d3 = TFT_D3; + tft_settings.pin_tft_d4 = TFT_D4; + tft_settings.pin_tft_d5 = TFT_D5; + tft_settings.pin_tft_d6 = TFT_D6; + tft_settings.pin_tft_d7 = TFT_D7; +#else + tft_settings.pin_tft_d0 = -1; + tft_settings.pin_tft_d1 = -1; + tft_settings.pin_tft_d2 = -1; + tft_settings.pin_tft_d3 = -1; + tft_settings.pin_tft_d4 = -1; + tft_settings.pin_tft_d5 = -1; + tft_settings.pin_tft_d6 = -1; + tft_settings.pin_tft_d7 = -1; +#endif - ****************************************************/ +#if defined (TOUCH_CS) + tft_settings.pin_tch_cs = TOUCH_CS; + tft_settings.tch_spi_freq = SPI_TOUCH_FREQUENCY/100000; +#else + tft_settings.pin_tch_cs = -1; + tft_settings.tch_spi_freq = 0; +#endif +} +//////////////////////////////////////////////////////////////////////////////////////// +#ifdef TOUCH_CS + #include "Extensions/Touch.cpp" + #include "Extensions/Button.cpp" +#endif -/**************************************************** +#include "Extensions/Sprite.cpp" - In compliance with the licence.txt file for the Adafruit_GFX library the - following is included. +#ifdef SMOOTH_FONT + #include "Extensions/Smooth_font.cpp" +#endif - Software License Agreement (BSD License) +//////////////////////////////////////////////////////////////////////////////////////// - Copyright (c) 2012 Adafruit Industries. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - -- Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. -- Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - - *****************************************************/ diff --git a/TFT_eSPI.h b/TFT_eSPI.h index d85df05..7f7622d 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -1,13 +1,9 @@ /*************************************************** - Arduino TFT graphics library targetted at ESP8266 - based boards. (ESP32 support is planned!) - - This library has been derived from the Adafruit_GFX - library and the associated driver library. See text - at the end of this file. + Arduino TFT graphics library targeted at ESP8266 + and ESP32 based boards. This is a standalone library that contains the - hardware driver, the graphics funtions and the + hardware driver, the graphics functions and the proportional fonts. The larger fonts are Run Length Encoded to reduce @@ -19,17 +15,47 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ +#define TFT_ESPI_VERSION "1.4.20" + //#define ESP32 //Just used to test ESP32 options // Include header file that defines the fonts loaded, the TFT drivers // available and the pins to be used #include +#ifndef TAB_COLOUR + #define TAB_COLOUR 0 +#endif + // If the frequency is not defined, set a default #ifndef SPI_FREQUENCY #define SPI_FREQUENCY 20000000 #endif +// If the frequency is not defined, set a default +#ifndef SPI_READ_FREQUENCY + #define SPI_READ_FREQUENCY SPI_FREQUENCY +#endif + +#if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) + #define TFT_SPI_MODE SPI_MODE3 +#else + #define TFT_SPI_MODE SPI_MODE0 +#endif + +// If the frequency is not defined, set a default +#ifndef SPI_TOUCH_FREQUENCY + #define SPI_TOUCH_FREQUENCY 2500000 +#endif + +// Use GLCD font in error case where user requests a smooth font file +// that does not exist (this is a temporary fix to stop ESP32 reboot) +#ifdef SMOOTH_FONT + #ifndef LOAD_GLCD + #define LOAD_GLCD + #endif +#endif + // Only load the fonts defined in User_Setup.h (to save space) // Set flag so RLE rendering code is optionally compiled #ifdef LOAD_GLCD @@ -64,6 +90,12 @@ #ifndef LOAD_RLE #define LOAD_RLE #endif +#elif defined LOAD_FONT8N + #define LOAD_FONT8 + #include + #ifndef LOAD_RLE + #define LOAD_RLE + #endif #endif #include @@ -73,49 +105,309 @@ #include -#if defined (ESP8266) && defined (D0_USED_FOR_DC) - #define DC_C digitalWrite(TFT_DC, LOW) - #define DC_D digitalWrite(TFT_DC, HIGH) -#elif defined (ESP32) - //#define DC_C digitalWrite(TFT_DC, HIGH); GPIO.out_w1tc = (1 << TFT_DC)//digitalWrite(TFT_DC, LOW) - //#define DC_D digitalWrite(TFT_DC, LOW); GPIO.out_w1ts = (1 << TFT_DC)//digitalWrite(TFT_DC, HIGH) - #define DC_C GPIO.out_w1ts = (1 << TFT_DC); GPIO.out_w1ts = (1 << TFT_DC); GPIO.out_w1tc = (1 << TFT_DC) - #define DC_D GPIO.out_w1tc = (1 << TFT_DC); GPIO.out_w1ts = (1 << TFT_DC) +#ifdef ESP32 + #include "soc/spi_reg.h" + #ifdef USE_HSPI_PORT + #define SPI_PORT HSPI + #else + #define SPI_PORT VSPI + #endif +#endif + +#ifdef SMOOTH_FONT + // Call up the SPIFFS FLASH filing system for the anti-aliased fonts + #define FS_NO_GLOBALS + #include + + #ifdef ESP32 + #include "SPIFFS.h" + #endif +#endif + +#ifndef TFT_DC + #define DC_C // No macro allocated so it generates no code + #define DC_D // No macro allocated so it generates no code #else - #define DC_C GPOC=dcpinmask - #define DC_D GPOS=dcpinmask + #if defined (ESP8266) && (TFT_DC == 16) + #define DC_C digitalWrite(TFT_DC, LOW) + #define DC_D digitalWrite(TFT_DC, HIGH) + #elif defined (ESP32) + #if defined (ESP32_PARALLEL) + #define DC_C GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC) + + #else + #if TFT_DC >= 32 + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower DC change + #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #else + #define DC_C GPIO.out1_w1tc.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) + #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) + #endif + #else + #if TFT_DC >= 0 + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower DC change + #define DC_C GPIO.out_w1ts = (1 << TFT_DC); \ + GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) + #else + #define DC_C GPIO.out_w1tc = (1 << TFT_DC)//;GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1ts = (1 << TFT_DC)//;GPIO.out_w1ts = (1 << TFT_DC) + #endif + #else + #define DC_C + #define DC_D + #endif + #endif + #endif + #else + #define DC_C GPOC=dcpinmask + #define DC_D GPOS=dcpinmask + #endif +#endif + +#if defined (TFT_SPI_OVERLAP) + #undef TFT_CS + #define SPI1U_WRITE (SPIUMOSI | SPIUSSE | SPIUCSSETUP | SPIUCSHOLD) + #define SPI1U_READ (SPIUMOSI | SPIUSSE | SPIUCSSETUP | SPIUCSHOLD | SPIUDUPLEX) +#else + #ifdef ESP8266 + #define SPI1U_WRITE (SPIUMOSI | SPIUSSE) + #define SPI1U_READ (SPIUMOSI | SPIUSSE | SPIUDUPLEX) + #endif #endif #ifndef TFT_CS #define CS_L // No macro allocated so it generates no code #define CS_H // No macro allocated so it generates no code #else - #if defined (ESP8266) && defined (D0_USED_FOR_CS) + #if defined (ESP8266) && (TFT_CS == 16) #define CS_L digitalWrite(TFT_CS, LOW) #define CS_H digitalWrite(TFT_CS, HIGH) #elif defined (ESP32) - //#define CS_L digitalWrite(TFT_CS, HIGH); GPIO.out_w1tc = (1 << TFT_CS)//digitalWrite(TFT_CS, LOW) - //#define CS_H digitalWrite(TFT_CS, LOW); GPIO.out_w1ts = (1 << TFT_CS)//digitalWrite(TFT_CS, HIGH) - #define CS_L GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) - #define CS_H GPIO.out_w1ts = (1 << TFT_CS) + #if defined (ESP32_PARALLEL) + #define CS_L // The TFT CS is set permanently low during init() + #define CS_H + #else + #if TFT_CS >= 32 + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CS change + #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ + GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #else + #define CS_L GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) + #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) + #endif + #else + #if TFT_CS >= 0 + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CS change + #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) + #else + #define CS_L GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1ts = (1 << TFT_CS)//;GPIO.out_w1ts = (1 << TFT_CS) + #endif + #else + #define CS_L + #define CS_H + #endif + #endif + #endif #else #define CS_L GPOC=cspinmask #define CS_H GPOS=cspinmask #endif #endif +// Use single register write for CS_L and DC_C if pins are both in range 0-31 +#ifdef ESP32 + #ifdef TFT_CS + #if (TFT_CS >= 0) && (TFT_CS < 32) && (TFT_DC >= 0) && (TFT_DC < 32) + #ifdef RPI_ILI9486_DRIVER // RPi display needs a slower CD and DC change + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); \ + GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #else + #define CS_L_DC_C GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)); GPIO.out_w1tc = ((1 << TFT_CS) | (1 << TFT_DC)) + #endif + #else + #define CS_L_DC_C CS_L; DC_C + #endif + #else + #define CS_L_DC_C CS_L; DC_C + #endif +#else // ESP8266 + #define CS_L_DC_C CS_L; DC_C +#endif + +// chip select signal for touchscreen +#ifndef TOUCH_CS + #define T_CS_L // No macro allocated so it generates no code + #define T_CS_H // No macro allocated so it generates no code +#else + #define T_CS_L digitalWrite(TOUCH_CS, LOW) + #define T_CS_H digitalWrite(TOUCH_CS, HIGH) +#endif + + #ifdef TFT_WR #if defined (ESP32) #define WR_L GPIO.out_w1tc = (1 << TFT_WR) - //digitalWrite(TFT_WR, LOW) #define WR_H GPIO.out_w1ts = (1 << TFT_WR) - //digitalWrite(TFT_WR, HIGH) #else #define WR_L GPOC=wrpinmask #define WR_H GPOS=wrpinmask #endif #endif +#ifdef ESP8266 + // Concatenate two 16 bit values for the SPI 32 bit register write + #define SPI_32(H,L) ( (H)<<16 | (L) ) + #define COL_32(H,L) ( (H)<<16 | (L) ) +#else + #if defined (ESP32_PARALLEL) || defined (ILI9488_DRIVER) + #define SPI_32(H,L) ( (H)<<16 | (L) ) + #else + #define SPI_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) + #endif + // Swap byte order for concatenated 16 bit colors + // AB CD -> DCBA for 32 bit register write + #define COL_32(H,L) ( ((H)<<8 | (H)>>8) | (((L)<<8 | (L)>>8)<<16 ) ) +#endif + +#if defined (ESP32) && defined (ESP32_PARALLEL) + // Mask for the 8 data bits to set pin directions + #define dir_mask ((1 << TFT_D0) | (1 << TFT_D1) | (1 << TFT_D2) | (1 << TFT_D3) | (1 << TFT_D4) | (1 << TFT_D5) | (1 << TFT_D6) | (1 << TFT_D7)) + + // Data bits and the write line are cleared to 0 in one step + #define clr_mask (dir_mask | (1 << TFT_WR)) + + // A lookup table is used to set the different bit patterns, this uses 1kByte of RAM + #define set_mask(C) xset_mask[C] // 63fps Sprite rendering test 33% faster, graphicstest only 1.8% faster than shifting in real time + + // Real-time shifting alternative to above to save 1KByte RAM, 47 fps Sprite rendering test + /*#define set_mask(C) ((C&0x80)>>7)<>6)<>5)<>4)<>3)<>2)<>1)<>0)<> 0)); WR_H + #else + #define tft_Write_16(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 8)); WR_H; \ + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t)(C >> 0)); WR_H + #endif + + // 16 bit write with swapped bytes + #define tft_Write_16S(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 0)); WR_H; \ + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 8)); WR_H + + // Write 32 bits to TFT + #define tft_Write_32(C) GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 24)); WR_H; \ + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 16)); WR_H; \ + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 8)); WR_H; \ + GPIO.out_w1tc = clr_mask; GPIO.out_w1ts = set_mask((uint8_t) (C >> 0)); WR_H + + #ifdef TFT_RD + #define RD_L GPIO.out_w1tc = (1 << TFT_RD) + //#define RD_L digitalWrite(TFT_WR, LOW) + #define RD_H GPIO.out_w1ts = (1 << TFT_RD) + //#define RD_H digitalWrite(TFT_WR, HIGH) + #endif + +#elif defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB + + // Write 8 bits to TFT + #define tft_Write_8(C) spi.transfer(C) + + // Convert 16 bit colour to 18 bit and write in 3 bytes + #define tft_Write_16(C) spi.transfer((C & 0xF800)>>8); \ + spi.transfer((C & 0x07E0)>>3); \ + spi.transfer((C & 0x001F)<<3) + + // Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes + #define tft_Write_16S(C) spi.transfer(C & 0xF8); \ + spi.transfer((C & 0xE000)>>11 | (C & 0x07)<<5); \ + spi.transfer((C & 0x1F00)>>5) + // Write 32 bits to TFT + #define tft_Write_32(C) spi.write32(C) + +#elif defined (RPI_ILI9486_DRIVER) + + #define tft_Write_8(C) spi.transfer(0); spi.transfer(C) + #define tft_Write_16(C) spi.write16(C) + #define tft_Write_16S(C) spi.write16(C<<8 | C>>8) + #define tft_Write_32(C) spi.write32(C) + +#elif defined ESP8266 + + #define tft_Write_8(C) spi.write(C) + #define tft_Write_16(C) spi.write16(C) + #define tft_Write_32(C) spi.write32(C) + +#else // ESP32 using SPI with 16 bit color display + + // ESP32 low level SPI writes for 8, 16 and 32 bit values + // to avoid the function call overhead + + // Write 8 bits + #define tft_Write_8(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 8-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + + // Write 16 bits with corrected endianess for 16 bit colours + #define tft_Write_16(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C<<8 | C>>8); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + + // Write 16 bits + #define tft_Write_16S(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 16-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + + // Write 32 bits + #define tft_Write_32(C) \ + WRITE_PERI_REG(SPI_MOSI_DLEN_REG(SPI_PORT), 32-1); \ + WRITE_PERI_REG(SPI_W0_REG(SPI_PORT), C); \ + SET_PERI_REG_MASK(SPI_CMD_REG(SPI_PORT), SPI_USR); \ + while (READ_PERI_REG(SPI_CMD_REG(SPI_PORT))&SPI_USR); + +#endif + + +#if !defined (ESP32_PARALLEL) + + // Read from display using SPI or software SPI + #if defined (ESP8266) && defined (TFT_SDA_READ) + // Use a bit banged function call for ESP8266 and bi-directional SDA pin + #define SCLK_L GPOC=sclkpinmask + #define SCLK_H GPOS=sclkpinmask + #else + // Use a SPI read transfer + #define tft_Read_8() spi.transfer(0) + #endif + + // Make sure TFT_MISO is defined if not used to avoid an error message + #ifndef TFT_MISO + #define TFT_MISO -1 + #endif + +#endif + + #ifdef LOAD_GFXFF // We can include all the free fonts and they will only be built into // the sketch if they are used @@ -227,18 +519,89 @@ #define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ #define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ #define TFT_WHITE 0xFFFF /* 255, 255, 255 */ -#define TFT_ORANGE 0xFD20 /* 255, 165, 0 */ -#define TFT_GREENYELLOW 0xAFE5 /* 173, 255, 47 */ -#define TFT_PINK 0xF81F +#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ +#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ +#define TFT_PINK 0xFC9F +// Next is a special 16 bit colour value that encodes to 8 bits +// and will then decode back to the same 16 bit value. +// Convenient for 8 bit and 16 bit transparent sprites. +#define TFT_TRANSPARENT 0x0120 // Swap any type template static inline void swap_coord(T& a, T& b) { T t = a; a = b; b = t; } -// This is a structure to conveniently hold infomation on the default fonts +#ifndef min + // Return minimum of two numbers, may already be defined + #define min(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +// This structure allows sketches to retrieve the user setup parameters at runtime +// by calling getSetup(), zero impact on code size unless used, mainly for diagnostics +typedef struct +{ +String version = TFT_ESPI_VERSION; +int16_t esp; +uint8_t trans; +uint8_t serial; +uint8_t overlap; + +#if defined (ESP32) + #if defined (USE_HSPI_PORT) + uint8_t port = HSPI; + #else + uint8_t port = VSPI; + #endif +#endif + +uint16_t tft_driver; // Hexadecimal code +uint16_t tft_width; // Rotation 0 width and height +uint16_t tft_height; + +uint8_t r0_x_offset; // Offsets, not all used yet +uint8_t r0_y_offset; +uint8_t r1_x_offset; +uint8_t r1_y_offset; +uint8_t r2_x_offset; +uint8_t r2_y_offset; +uint8_t r3_x_offset; +uint8_t r3_y_offset; + +int8_t pin_tft_mosi; +int8_t pin_tft_miso; +int8_t pin_tft_clk; +int8_t pin_tft_cs; + +int8_t pin_tft_dc; +int8_t pin_tft_rd; +int8_t pin_tft_wr; +int8_t pin_tft_rst; + +int8_t pin_tft_d0; +int8_t pin_tft_d1; +int8_t pin_tft_d2; +int8_t pin_tft_d3; +int8_t pin_tft_d4; +int8_t pin_tft_d5; +int8_t pin_tft_d6; +int8_t pin_tft_d7; + +int8_t pin_tch_cs; + +int16_t tft_spi_freq; +int16_t tft_rd_freq; +int16_t tch_spi_freq; +} setup_t; + +// This is a structure to conveniently hold information on the default fonts // Stores pointer to font character image address table, width table and height +// Create a null set in case some fonts not used (to prevent crash) +const uint8_t widtbl_null[1] = {0}; +PROGMEM const uint8_t chr_null[1] = {0}; +PROGMEM const uint8_t* const chrtbl_null[1] = {chr_null}; + typedef struct { const uint8_t *chartbl; const uint8_t *widthtbl; @@ -248,50 +611,52 @@ typedef struct { // Now fill the structure const PROGMEM fontinfo fontdata [] = { - { 0, 0, 0, 0 }, - + #ifdef LOAD_GLCD + { (const uint8_t *)font, widtbl_null, 0, 0 }, + #else + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, + #endif // GLCD font (Font 1) does not have all parameters - { 0, 0, 8, 7 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 8, 7 }, #ifdef LOAD_FONT2 { (const uint8_t *)chrtbl_f16, widtbl_f16, chr_hgt_f16, baseline_f16}, #else - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #endif // Font 3 current unused - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #ifdef LOAD_FONT4 { (const uint8_t *)chrtbl_f32, widtbl_f32, chr_hgt_f32, baseline_f32}, #else - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #endif // Font 5 current unused - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #ifdef LOAD_FONT6 { (const uint8_t *)chrtbl_f64, widtbl_f64, chr_hgt_f64, baseline_f64}, #else - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #endif #ifdef LOAD_FONT7 { (const uint8_t *)chrtbl_f7s, widtbl_f7s, chr_hgt_f7s, baseline_f7s}, #else - { 0, 0, 0, 0 }, + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 }, #endif #ifdef LOAD_FONT8 { (const uint8_t *)chrtbl_f72, widtbl_f72, chr_hgt_f72, baseline_f72} #else - { 0, 0, 0, 0 } + { (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 } #endif }; - // Class functions and variables class TFT_eSPI : public Print { @@ -299,27 +664,31 @@ class TFT_eSPI : public Print { TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); - void init(void), begin(void); // Same - begin included for backwards compatibility + void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); // Same - begin included for backwards compatibility - void drawPixel(uint32_t x, uint32_t y, uint32_t color); + // These are virtual so the TFT_eSprite class can override them with sprite specific functions + virtual void drawPixel(int32_t x, int32_t y, uint32_t color), + drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), + drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), + drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), + drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), + fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); - void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t font), - setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1), + virtual int16_t drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font), + drawChar(uint16_t uniCode, int32_t x, int32_t y), + height(void), + width(void); + // The TFT_eSprite class inherits the following functions + void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye), pushColor(uint16_t color), - pushColor(uint16_t color, uint16_t len), - - pushColors(uint16_t *data, uint8_t len), + pushColor(uint16_t color, uint32_t len), + pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option pushColors(uint8_t *data, uint32_t len), - fillScreen(uint32_t color), + fillScreen(uint32_t color); - drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), - drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), - drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), - - drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), - fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), + void drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), drawRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, uint32_t color), fillRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, uint32_t color), @@ -331,21 +700,24 @@ class TFT_eSPI : public Print { fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color), fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), - drawEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color), - fillEllipse(int16_t x0, int16_t y0, int16_t rx, int16_t ry, uint16_t color), + drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), + fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), fillTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color), - + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color), + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), + setBitmapColor(uint16_t fgcolor, uint16_t bgcolor), // For 1bpp sprites + setPivot(int16_t x, int16_t y), setCursor(int16_t x, int16_t y), setCursor(int16_t x, int16_t y, uint8_t font), setTextColor(uint16_t color), setTextColor(uint16_t fgcolor, uint16_t bgcolor), setTextSize(uint8_t size), - setTextWrap(boolean wrap), + setTextWrap(boolean wrapX, boolean wrapY = false), setTextDatum(uint8_t datum), setTextPadding(uint16_t x_width), @@ -359,121 +731,192 @@ class TFT_eSPI : public Print { spiwrite(uint8_t), writecommand(uint8_t c), writedata(uint8_t d), + commandList(const uint8_t *addr); - uint8_t readcommand8(uint8_t cmd_function, uint8_t index); - uint16_t readcommand16(uint8_t cmd_function, uint8_t index); - uint32_t readcommand32(uint8_t cmd_function, uint8_t index); + uint8_t readcommand8(uint8_t cmd_function, uint8_t index = 0); + uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); + uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // Read the colour of a pixel at x,y and return value in 565 format uint16_t readPixel(int32_t x0, int32_t y0); // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location // Read a block of pixels to a data buffer, buffer is 16 bit and the array size must be at least w * h - void readRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void readRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); // Write a block of pixels to the screen - void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void pushRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + + // These are used to render images or sprites stored in RAM arrays + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); + + // These are used to render images stored in FLASH (PROGMEM) + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); + + // These are used by pushSprite for 1 and 8 bit colours + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true); + void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true); + + // Swap the byte order for pushImage() - corrects endianness + void setSwapBytes(bool swap); + bool getSwapBytes(void); // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes // It reads a screen area and returns the RGB 8 bit colour values of each pixel // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes void readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data); - uint8_t getRotation(void); + uint8_t getRotation(void), + getTextDatum(void), + color16to8(uint16_t color565); // Convert 16 bit colour to 8 bits + + int16_t getCursorX(void), + getCursorY(void); + + int16_t getPivotX(void), + getPivotY(void); uint16_t fontsLoaded(void), - color565(uint8_t r, uint8_t g, uint8_t b); + color565(uint8_t red, uint8_t green, uint8_t blue), // Convert 8 bit red, green and blue to 16 bits + color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits + + int16_t drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font), + drawNumber(long long_num, int32_t poX, int32_t poY), + drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY, uint8_t font), + drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY), - int16_t drawChar(unsigned int uniCode, int x, int y, int font), - drawChar(unsigned int uniCode, int x, int y), - drawNumber(long long_num,int poX, int poY, int font), - drawNumber(long long_num,int poX, int poY), - drawFloat(float floatNumber,int decimal,int poX, int poY, int font), - drawFloat(float floatNumber,int decimal,int poX, int poY), - // Handle char arrays - drawString(const char *string, int poX, int poY, int font), - drawString(const char *string, int poX, int poY), - drawCentreString(const char *string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const char *string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() + drawString(const char *string, int32_t poX, int32_t poY, uint8_t font), + drawString(const char *string, int32_t poX, int32_t poY), + drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() // Handle String type - drawString(const String& string, int poX, int poY, int font), - drawString(const String& string, int poX, int poY), - drawCentreString(const String& string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const String& string, int dX, int poY, int font); // Deprecated, use setTextDatum() and drawString() - - int16_t height(void), - width(void), - textWidth(const char *string, int font), + drawString(const String& string, int32_t poX, int32_t poY, uint8_t font), + drawString(const String& string, int32_t poX, int32_t poY), + drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font); // Deprecated, use setTextDatum() and drawString() + + int16_t textWidth(const char *string, uint8_t font), textWidth(const char *string), - textWidth(const String& string, int font), + textWidth(const String& string, uint8_t font), textWidth(const String& string), - fontHeight(int16_t font); + fontHeight(int16_t font), + fontHeight(void); - void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); - virtual size_t write(uint8_t); + // Compatibility additions + void startWrite(void); // Begin SPI transaction + void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead + void endWrite(void); // End SPI transaction - private: + uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining); + uint16_t decodeUTF8(uint8_t c); + size_t write(uint8_t); -inline void spi_begin() __attribute__((always_inline)); -inline void spi_end() __attribute__((always_inline)); +#ifdef TFT_SDA_READ + #if defined (ESP8266) && defined (TFT_SDA_READ) + uint8_t tft_Read_8(void); + #endif + void begin_SDA_Read(void); + void end_SDA_Read(void); +#endif - void readAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); - - uint8_t tabcolor, - colstart = 0, rowstart = 0; // some ST7735 displays need this changed + // Set or get an arbitrary library attribute or configuration option + void setAttribute(uint8_t id = 0, uint8_t a = 0); + uint8_t getAttribute(uint8_t id = 0); - volatile uint32_t *dcport, *csport;//, *mosiport, *clkport, *rsport; + void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate - uint32_t cspinmask, dcpinmask, wrpinmask;//, mosipinmask, clkpinmask; + static SPIClass& getSPIinstance(void); - uint32_t lastColor = 0xFFFF; + int32_t cursor_x, cursor_y, padX; + uint32_t textcolor, textbgcolor; - protected: + uint32_t bitmap_fg, bitmap_bg; - int32_t cursor_x, cursor_y, win_xe, win_ye, padX; - - uint32_t _width, _height; // Display w/h as modified by current rotation - uint32_t textcolor, textbgcolor, fontsloaded, addr_row, addr_col; - - uint8_t glyph_ab, // glyph height above baseline - glyph_bb, // glyph height below baseline - textfont, // Current selected font + uint8_t textfont, // Current selected font textsize, // Current font size multiplier textdatum, // Text reference datum rotation; // Display rotation (0-3) - boolean textwrap; // If set, 'wrap' text at right edge of display + int16_t _xpivot; // x pivot point coordinate + int16_t _ypivot; // x pivot point coordinate - boolean locked, inTransaction; // Transaction and mutex lock flags for ESP32 + uint8_t decoderState = 0; // UTF8 decoder state + uint16_t decoderBuffer; // Unicode code-point buffer + + private: + + inline void spi_begin() __attribute__((always_inline)); + inline void spi_end() __attribute__((always_inline)); + + inline void spi_begin_read() __attribute__((always_inline)); + inline void spi_end_read() __attribute__((always_inline)); + + void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); + + uint8_t tabcolor, + colstart = 0, rowstart = 0; // some ST7735 displays need this changed + + volatile uint32_t *dcport, *csport; + + uint32_t cspinmask, dcpinmask, wrpinmask, sclkpinmask; + +#if defined(ESP32_PARALLEL) + uint32_t xclr_mask, xdir_mask, xset_mask[256]; +#endif + + uint32_t lastColor = 0xFFFF; + + + protected: + + int32_t win_xe, win_ye; + + int32_t _init_width, _init_height; // Display w/h as input, used by setRotation() + int32_t _width, _height; // Display w/h as modified by current rotation + int32_t addr_row, addr_col; + + uint32_t fontsloaded; + + uint8_t glyph_ab, // glyph delta Y (height) above baseline + glyph_bb; // glyph delta Y (height) below baseline + + bool isDigits; // adjust bounding box for numbers to reduce visual jiggling + bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display + bool _swapBytes; // Swap the byte order for TFT pushImage() + bool locked, inTransaction; // Transaction and mutex lock flags for ESP32 + + bool _booted; // init() or begin() has already run once + bool _cp437; // If set, use correct CP437 charset (default is ON) + bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON) + + uint32_t _lastColor; // Buffered value of last colour used #ifdef LOAD_GFXFF - GFXfont - *gfxFont; + GFXfont *gfxFont; #endif -}; - +// Load the Touch extension +#ifdef TOUCH_CS + #include "Extensions/Touch.h" #endif -/*************************************************** +// Load the Anti-aliased font extension +#ifdef SMOOTH_FONT + #include "Extensions/Smooth_font.h" +#endif - ORIGINAL LIBRARY HEADER +}; // End of class TFT_eSPI - This is our library for the Adafruit ILI9341 Breakout and Shield - ----> http://www.adafruit.com/products/1651 +// Load the Button Class +#include "Extensions/Button.h" - Check out the links above for our tutorials and wiring diagrams - These displays use SPI to communicate, 4 or 5 pins are required to - interface (RST is optional) - Adafruit invests time and resources providing this open source code, - please support Adafruit and open-source hardware by purchasing - products from Adafruit! +// Load the Sprite Class +#include "Extensions/Sprite.h" - Written by Limor Fried/Ladyada for Adafruit Industries. - MIT license, all text above must be included in any redistribution - - Updated with new functions by Bodmer 14/4/15 - ****************************************************/ +#endif diff --git a/Tools/Create_Smooth_Font/Create_font/Create_font.pde b/Tools/Create_Smooth_Font/Create_font/Create_font.pde new file mode 100644 index 0000000..6832248 --- /dev/null +++ b/Tools/Create_Smooth_Font/Create_font/Create_font.pde @@ -0,0 +1,523 @@ +// This is a Processing sketch, see https://processing.org/ to download the IDE + +// Select the font, size and character ranges in the user configuration section +// of this sketch, which starts at line 120. Instructions start at line 50. + + +/* +Software License Agreement (FreeBSD License) + + Copyright (c) 2018 Bodmer (https://github.com/Bodmer) + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + The views and conclusions contained in the software and documentation are those + of the authors and should not be interpreted as representing official policies, + either expressed or implied, of the FreeBSD Project. + */ + +//////////////////////////////////////////////////////////////////////////////////////////////// + +// This is a processing sketch to create font files for the TFT_eSPI library: + +// https://github.com/Bodmer/TFT_eSPI + +// Coded by Bodmer January 2018, updated 10/2/19 +// Version 0.8 + +// >>>>>>>>>>>>>>>>>>>> INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< + +// See comments below in code for specifying the font parameters (point size, +// unicode blocks to include etc). Ranges of characters (glyphs) and specific +// individual glyphs can be included in the created "*.vlw" font file. + +// Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to +// see that folder location. + +// 16 bit Unicode point codes in the range 0x0000 - 0xFFFF are supported. +// Codes 0-31 are control codes such as "tab" and "carraige return" etc. +// and 32 is a "space", these should NOT be included. + +// The sketch will convert True Type (a .ttf or .otf file) file stored in the +// sketches "Data" folder as well as your computers' system fonts. + +// To maximise rendering performance and the memory consumed only include the characters +// you will use. Characters at the start of the file will render faster than those at +// the end due to the buffering and file seeking overhead. + +// The inclusion of "non-existant" characters in a font may give unpredicatable results +// when rendering with the TFT_eSPI library. The Processing sketch window that pops up +// to show the font characters will print "boxes" (also known as Tofu!) for non existant +// characters. + +// Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory +// using the Arduino IDE plugin detailed here: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// When the sketch is run it will generate a file called "System_Font_List.txt" in the +// sketch "FontFiles" folder, press Ctrl+K to see it. Open the file in a text editor to +// view it. This list provides the font reference number needed below to locate that +// font on your system. + +// The sketch also lists all the available system fonts to the console, you can increase +// the console line count (in preferences.txt) to stop some fonts scrolling out of view. +// See link in File>Preferences to locate "preferences.txt" file. You must close +// Processing then edit the file lines. If Processing is not closed first then the +// edits will be overwritten by defaults! Edit "preferences.txt" as follows for +// 3000 lines, then save, then run Processing again: + +// console.length=3000; // Line 4 in file +// console.scrollback.lines=3000; // Line 7 in file + + +// Useful links: +/* + + https://en.wikipedia.org/wiki/Unicode_font + + https://www.gnu.org/software/freefont/ + https://www.gnu.org/software/freefont/sources/ + https://www.gnu.org/software/freefont/ranges/ + http://savannah.gnu.org/projects/freefont/ + + http://www.google.com/get/noto/ + + https://github.com/Bodmer/TFT_eSPI + https://github.com/esp8266/arduino-esp8266fs-plugin + https://github.com/me-no-dev/arduino-esp32fs-plugin + + >>>>>>>>>>>>>>>>>>>> END OF INSTRUCTIONS <<<<<<<<<<<<<<<<<<<< */ + + +import java.awt.Desktop; // Required to allow sketch to open file windows + + +//////////////////////////////////////////////////////////////////////////////////////////////// + +// >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<< + +// Use font number or name, -1 for fontNumber means use fontName below, a value >=0 means use system font number from list. +// When the sketch is run it will generate a file called "systemFontList.txt" in the sketch folder, press Ctrl+K to see it. +// Open the "systemFontList.txt" in a text editor to view the font files and reference numbers for your system. + +int fontNumber = -1; // << Use [Number] in brackets from the fonts listed. + +// OR use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts +// the font numbers are listed when the sketch is run. +// | 1 2 | Maximum filename size for SPIFFS is 31 including leading / +// 1234567890123456789012345 and added point size and .vlw extension, so max is 25 +String fontName = "Final-Frontier"; // Manually crop the filename length later after creation if needed + // Note: SPIFFS does NOT accept underscore in a filename! +String fontType = ".ttf"; +//String fontType = ".otf"; + + +// Define the font size in points for the TFT_eSPI font file +int fontSize = 20; + +// Font size to use in the Processing sketch display window that pops up (can be different to above) +int displayFontSize = 28; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Next we specify which unicode blocks from the the Basic Multilingual Plane (BMP) are included in the final font file. // +// Note: The ttf/otf font file MAY NOT contain all possible Unicode characters, refer to the fonts online documentation. // +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static final int[] unicodeBlocks = { + // The list below has been created from the table here: https://en.wikipedia.org/wiki/Unicode_block + // Remove // at start of lines below to include that unicode block, different code ranges can also be specified by + // editting the start and end-of-range values. Multiple lines from the list below can be included, limited only by + // the final font file size! + + // Block range, //Block name, Code points, Assigned characters, Scripts + // First, last, //Range is inclusive of first and last codes + 0x0021, 0x007E, //Basic Latin, 128, 128, Latin (52 characters), Common (76 characters) + //0x0080, 0x00FF, //Latin-1 Supplement, 128, 128, Latin (64 characters), Common (64 characters) + //0x0100, 0x017F, //Latin Extended-A, 128, 128, Latin + //0x0180, 0x024F, //Latin Extended-B, 208, 208, Latin + //0x0250, 0x02AF, //IPA Extensions, 96, 96, Latin + //0x02B0, 0x02FF, //Spacing Modifier Letters, 80, 80, Bopomofo (2 characters), Latin (14 characters), Common (64 characters) + //0x0300, 0x036F, //Combining Diacritical Marks, 112, 112, Inherited + //0x0370, 0x03FF, //Greek and Coptic, 144, 135, Coptic (14 characters), Greek (117 characters), Common (4 characters) + //0x0400, 0x04FF, //Cyrillic, 256, 256, Cyrillic (254 characters), Inherited (2 characters) + //0x0500, 0x052F, //Cyrillic Supplement, 48, 48, Cyrillic + //0x0530, 0x058F, //Armenian, 96, 89, Armenian (88 characters), Common (1 character) + //0x0590, 0x05FF, //Hebrew, 112, 87, Hebrew + //0x0600, 0x06FF, //Arabic, 256, 255, Arabic (237 characters), Common (6 characters), Inherited (12 characters) + //0x0700, 0x074F, //Syriac, 80, 77, Syriac + //0x0750, 0x077F, //Arabic Supplement, 48, 48, Arabic + //0x0780, 0x07BF, //Thaana, 64, 50, Thaana + //0x07C0, 0x07FF, //NKo, 64, 59, Nko + //0x0800, 0x083F, //Samaritan, 64, 61, Samaritan + //0x0840, 0x085F, //Mandaic, 32, 29, Mandaic + //0x0860, 0x086F, //Syriac Supplement, 16, 11, Syriac + //0x08A0, 0x08FF, //Arabic Extended-A, 96, 73, Arabic (72 characters), Common (1 character) + //0x0900, 0x097F, //Devanagari, 128, 128, Devanagari (124 characters), Common (2 characters), Inherited (2 characters) + //0x0980, 0x09FF, //Bengali, 128, 95, Bengali + //0x0A00, 0x0A7F, //Gurmukhi, 128, 79, Gurmukhi + //0x0A80, 0x0AFF, //Gujarati, 128, 91, Gujarati + //0x0B00, 0x0B7F, //Oriya, 128, 90, Oriya + //0x0B80, 0x0BFF, //Tamil, 128, 72, Tamil + //0x0C00, 0x0C7F, //Telugu, 128, 96, Telugu + //0x0C80, 0x0CFF, //Kannada, 128, 88, Kannada + //0x0D00, 0x0D7F, //Malayalam, 128, 117, Malayalam + //0x0D80, 0x0DFF, //Sinhala, 128, 90, Sinhala + //0x0E00, 0x0E7F, //Thai, 128, 87, Thai (86 characters), Common (1 character) + //0x0E80, 0x0EFF, //Lao, 128, 67, Lao + //0x0F00, 0x0FFF, //Tibetan, 256, 211, Tibetan (207 characters), Common (4 characters) + //0x1000, 0x109F, //Myanmar, 160, 160, Myanmar + //0x10A0, 0x10FF, //Georgian, 96, 88, Georgian (87 characters), Common (1 character) + //0x1100, 0x11FF, //Hangul Jamo, 256, 256, Hangul + //0x1200, 0x137F, //Ethiopic, 384, 358, Ethiopic + //0x1380, 0x139F, //Ethiopic Supplement, 32, 26, Ethiopic + //0x13A0, 0x13FF, //Cherokee, 96, 92, Cherokee + //0x1400, 0x167F, //Unified Canadian Aboriginal Syllabics, 640, 640, Canadian Aboriginal + //0x1680, 0x169F, //Ogham, 32, 29, Ogham + //0x16A0, 0x16FF, //Runic, 96, 89, Runic (86 characters), Common (3 characters) + //0x1700, 0x171F, //Tagalog, 32, 20, Tagalog + //0x1720, 0x173F, //Hanunoo, 32, 23, Hanunoo (21 characters), Common (2 characters) + //0x1740, 0x175F, //Buhid, 32, 20, Buhid + //0x1760, 0x177F, //Tagbanwa, 32, 18, Tagbanwa + //0x1780, 0x17FF, //Khmer, 128, 114, Khmer + //0x1800, 0x18AF, //Mongolian, 176, 156, Mongolian (153 characters), Common (3 characters) + //0x18B0, 0x18FF, //Unified Canadian Aboriginal Syllabics Extended, 80, 70, Canadian Aboriginal + //0x1900, 0x194F, //Limbu, 80, 68, Limbu + //0x1950, 0x197F, //Tai Le, 48, 35, Tai Le + //0x1980, 0x19DF, //New Tai Lue, 96, 83, New Tai Lue + //0x19E0, 0x19FF, //Khmer Symbols, 32, 32, Khmer + //0x1A00, 0x1A1F, //Buginese, 32, 30, Buginese + //0x1A20, 0x1AAF, //Tai Tham, 144, 127, Tai Tham + //0x1AB0, 0x1AFF, //Combining Diacritical Marks Extended, 80, 15, Inherited + //0x1B00, 0x1B7F, //Balinese, 128, 121, Balinese + //0x1B80, 0x1BBF, //Sundanese, 64, 64, Sundanese + //0x1BC0, 0x1BFF, //Batak, 64, 56, Batak + //0x1C00, 0x1C4F, //Lepcha, 80, 74, Lepcha + //0x1C50, 0x1C7F, //Ol Chiki, 48, 48, Ol Chiki + //0x1C80, 0x1C8F, //Cyrillic Extended-C, 16, 9, Cyrillic + //0x1CC0, 0x1CCF, //Sundanese Supplement, 16, 8, Sundanese + //0x1CD0, 0x1CFF, //Vedic Extensions, 48, 42, Common (15 characters), Inherited (27 characters) + //0x1D00, 0x1D7F, //Phonetic Extensions, 128, 128, Cyrillic (2 characters), Greek (15 characters), Latin (111 characters) + //0x1D80, 0x1DBF, //Phonetic Extensions Supplement, 64, 64, Greek (1 character), Latin (63 characters) + //0x1DC0, 0x1DFF, //Combining Diacritical Marks Supplement, 64, 63, Inherited + //0x1E00, 0x1EFF, //Latin Extended Additional, 256, 256, Latin + //0x1F00, 0x1FFF, //Greek Extended, 256, 233, Greek + //0x2000, 0x206F, //General Punctuation, 112, 111, Common (109 characters), Inherited (2 characters) + //0x2070, 0x209F, //Superscripts and Subscripts, 48, 42, Latin (15 characters), Common (27 characters) + //0x20A0, 0x20CF, //Currency Symbols, 48, 32, Common + //0x20D0, 0x20FF, //Combining Diacritical Marks for Symbols, 48, 33, Inherited + //0x2100, 0x214F, //Letterlike Symbols, 80, 80, Greek (1 character), Latin (4 characters), Common (75 characters) + //0x2150, 0x218F, //Number Forms, 64, 60, Latin (41 characters), Common (19 characters) + //0x2190, 0x21FF, //Arrows, 112, 112, Common + //0x2200, 0x22FF, //Mathematical Operators, 256, 256, Common + //0x2300, 0x23FF, //Miscellaneous Technical, 256, 256, Common + //0x2400, 0x243F, //Control Pictures, 64, 39, Common + //0x2440, 0x245F, //Optical Character Recognition, 32, 11, Common + //0x2460, 0x24FF, //Enclosed Alphanumerics, 160, 160, Common + //0x2500, 0x257F, //Box Drawing, 128, 128, Common + //0x2580, 0x259F, //Block Elements, 32, 32, Common + //0x25A0, 0x25FF, //Geometric Shapes, 96, 96, Common + //0x2600, 0x26FF, //Miscellaneous Symbols, 256, 256, Common + //0x2700, 0x27BF, //Dingbats, 192, 192, Common + //0x27C0, 0x27EF, //Miscellaneous Mathematical Symbols-A, 48, 48, Common + //0x27F0, 0x27FF, //Supplemental Arrows-A, 16, 16, Common + //0x2800, 0x28FF, //Braille Patterns, 256, 256, Braille + //0x2900, 0x297F, //Supplemental Arrows-B, 128, 128, Common + //0x2980, 0x29FF, //Miscellaneous Mathematical Symbols-B, 128, 128, Common + //0x2A00, 0x2AFF, //Supplemental Mathematical Operators, 256, 256, Common + //0x2B00, 0x2BFF, //Miscellaneous Symbols and Arrows, 256, 207, Common + //0x2C00, 0x2C5F, //Glagolitic, 96, 94, Glagolitic + //0x2C60, 0x2C7F, //Latin Extended-C, 32, 32, Latin + //0x2C80, 0x2CFF, //Coptic, 128, 123, Coptic + //0x2D00, 0x2D2F, //Georgian Supplement, 48, 40, Georgian + //0x2D30, 0x2D7F, //Tifinagh, 80, 59, Tifinagh + //0x2D80, 0x2DDF, //Ethiopic Extended, 96, 79, Ethiopic + //0x2DE0, 0x2DFF, //Cyrillic Extended-A, 32, 32, Cyrillic + //0x2E00, 0x2E7F, //Supplemental Punctuation, 128, 74, Common + //0x2E80, 0x2EFF, //CJK Radicals Supplement, 128, 115, Han + //0x2F00, 0x2FDF, //Kangxi Radicals, 224, 214, Han + //0x2FF0, 0x2FFF, //Ideographic Description Characters, 16, 12, Common + //0x3000, 0x303F, //CJK Symbols and Punctuation, 64, 64, Han (15 characters), Hangul (2 characters), Common (43 characters), Inherited (4 characters) + //0x3040, 0x309F, //Hiragana, 96, 93, Hiragana (89 characters), Common (2 characters), Inherited (2 characters) + //0x30A0, 0x30FF, //Katakana, 96, 96, Katakana (93 characters), Common (3 characters) + //0x3100, 0x312F, //Bopomofo, 48, 42, Bopomofo + //0x3130, 0x318F, //Hangul Compatibility Jamo, 96, 94, Hangul + //0x3190, 0x319F, //Kanbun, 16, 16, Common + //0x31A0, 0x31BF, //Bopomofo Extended, 32, 27, Bopomofo + //0x31C0, 0x31EF, //CJK Strokes, 48, 36, Common + //0x31F0, 0x31FF, //Katakana Phonetic Extensions, 16, 16, Katakana + //0x3200, 0x32FF, //Enclosed CJK Letters and Months, 256, 254, Hangul (62 characters), Katakana (47 characters), Common (145 characters) + //0x3300, 0x33FF, //CJK Compatibility, 256, 256, Katakana (88 characters), Common (168 characters) + //0x3400, 0x4DBF, //CJK Unified Ideographs Extension A, 6,592, 6,582, Han + //0x4DC0, 0x4DFF, //Yijing Hexagram Symbols, 64, 64, Common + //0x4E00, 0x9FFF, //CJK Unified Ideographs, 20,992, 20,971, Han + //0xA000, 0xA48F, //Yi Syllables, 1,168, 1,165, Yi + //0xA490, 0xA4CF, //Yi Radicals, 64, 55, Yi + //0xA4D0, 0xA4FF, //Lisu, 48, 48, Lisu + //0xA500, 0xA63F, //Vai, 320, 300, Vai + //0xA640, 0xA69F, //Cyrillic Extended-B, 96, 96, Cyrillic + //0xA6A0, 0xA6FF, //Bamum, 96, 88, Bamum + //0xA700, 0xA71F, //Modifier Tone Letters, 32, 32, Common + //0xA720, 0xA7FF, //Latin Extended-D, 224, 160, Latin (155 characters), Common (5 characters) + //0xA800, 0xA82F, //Syloti Nagri, 48, 44, Syloti Nagri + //0xA830, 0xA83F, //Common Indic Number Forms, 16, 10, Common + //0xA840, 0xA87F, //Phags-pa, 64, 56, Phags Pa + //0xA880, 0xA8DF, //Saurashtra, 96, 82, Saurashtra + //0xA8E0, 0xA8FF, //Devanagari Extended, 32, 30, Devanagari + //0xA900, 0xA92F, //Kayah Li, 48, 48, Kayah Li (47 characters), Common (1 character) + //0xA930, 0xA95F, //Rejang, 48, 37, Rejang + //0xA960, 0xA97F, //Hangul Jamo Extended-A, 32, 29, Hangul + //0xA980, 0xA9DF, //Javanese, 96, 91, Javanese (90 characters), Common (1 character) + //0xA9E0, 0xA9FF, //Myanmar Extended-B, 32, 31, Myanmar + //0xAA00, 0xAA5F, //Cham, 96, 83, Cham + //0xAA60, 0xAA7F, //Myanmar Extended-A, 32, 32, Myanmar + //0xAA80, 0xAADF, //Tai Viet, 96, 72, Tai Viet + //0xAAE0, 0xAAFF, //Meetei Mayek Extensions, 32, 23, Meetei Mayek + //0xAB00, 0xAB2F, //Ethiopic Extended-A, 48, 32, Ethiopic + //0xAB30, 0xAB6F, //Latin Extended-E, 64, 54, Latin (52 characters), Greek (1 character), Common (1 character) + //0xAB70, 0xABBF, //Cherokee Supplement, 80, 80, Cherokee + //0xABC0, 0xABFF, //Meetei Mayek, 64, 56, Meetei Mayek + //0xAC00, 0xD7AF, //Hangul Syllables, 11,184, 11,172, Hangul + //0xD7B0, 0xD7FF, //Hangul Jamo Extended-B, 80, 72, Hangul + //0xD800, 0xDB7F, //High Surrogates, 896, 0, Unknown + //0xDB80, 0xDBFF, //High Private Use Surrogates, 128, 0, Unknown + //0xDC00, 0xDFFF, //Low Surrogates, 1,024, 0, Unknown + //0xE000, 0xF8FF, //Private Use Area, 6,400, 6,400, Unknown + //0xF900, 0xFAFF, //CJK Compatibility Ideographs, 512, 472, Han + //0xFB00, 0xFB4F, //Alphabetic Presentation Forms, 80, 58, Armenian (5 characters), Hebrew (46 characters), Latin (7 characters) + //0xFB50, 0xFDFF, //Arabic Presentation Forms-A, 688, 611, Arabic (609 characters), Common (2 characters) + //0xFE00, 0xFE0F, //Variation Selectors, 16, 16, Inherited + //0xFE10, 0xFE1F, //Vertical Forms, 16, 10, Common + //0xFE20, 0xFE2F, //Combining Half Marks, 16, 16, Cyrillic (2 characters), Inherited (14 characters) + //0xFE30, 0xFE4F, //CJK Compatibility Forms, 32, 32, Common + //0xFE50, 0xFE6F, //Small Form Variants, 32, 26, Common + //0xFE70, 0xFEFF, //Arabic Presentation Forms-B, 144, 141, Arabic (140 characters), Common (1 character) + //0xFF00, 0xFFEF, //Halfwidth and Fullwidth Forms, 240, 225, Hangul (52 characters), Katakana (55 characters), Latin (52 characters), Common (66 characters) + //0xFFF0, 0xFFFF, //Specials, 16, 5, Common + + //0x0030, 0x0039, //Example custom range (numbers 0-9) + //0x0041, 0x005A, //Example custom range (Upper case A-Z) + //0x0061, 0x007A, //Example custom range (Lower case a-z) +}; + +// Here we specify particular individual Unicodes to be included (appended at end of selected range) +static final int[] specificUnicodes = { + + // Commonly used codes, add or remove // in next line + // 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω € + + // Numbers and characters for showing time, change next line to //* to use +/* + 0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4 + 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m + 0x0070, // p + //*/ + + // More characters for TFT_eSPI test sketches, change next line to //* to use + /* + 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x010C, 0x010D, + 0x010E, 0x010F, 0x0110, 0x0111, 0x0118, 0x0119, 0x011A, 0x011B, + + 0x0131, 0x0139, 0x013A, 0x013D, 0x013E, 0x0141, 0x0142, 0x0143, + 0x0144, 0x0147, 0x0148, 0x0150, 0x0151, 0x0152, 0x0153, 0x0154, + 0x0155, 0x0158, 0x0159, 0x015A, 0x015B, 0x015E, 0x015F, 0x0160, + 0x0161, 0x0162, 0x0163, 0x0164, 0x0165, 0x016E, 0x016F, 0x0170, + 0x0171, 0x0178, 0x0179, 0x017A, 0x017B, 0x017C, 0x017D, 0x017E, + 0x0192, + + 0x02C6, 0x02C7, 0x02D8, 0x02D9, 0x02DA, 0x02DB, 0x02DC, 0x02DD, + 0x03A9, 0x03C0, 0x2013, 0x2014, 0x2018, 0x2019, 0x201A, 0x201C, + 0x201D, 0x201E, 0x2020, 0x2021, 0x2022, 0x2026, 0x2030, 0x2039, + 0x203A, 0x2044, 0x20AC, + + 0x2122, 0x2202, 0x2206, 0x220F, + + 0x2211, 0x221A, 0x221E, 0x222B, 0x2248, 0x2260, 0x2264, 0x2265, + 0x25CA, + + 0xF8FF, 0xFB01, 0xFB02, + //*/ +}; + +// >>>>>>>>>> USER CONFIGURED PARAMETERS END HERE <<<<<<<<<< + +//////////////////////////////////////////////////////////////////////////////////////////////// + +// Variable to hold the inclusive Unicode range (16 bit values only for this sketch) +int firstUnicode = 0; +int lastUnicode = 0; + +PFont myFont; + +PrintWriter logOutput; + +void setup() { + logOutput = createWriter("FontFiles/System_Font_List.txt"); + + size(1000, 800); + + // Print the available fonts to the console as a list: + String[] fontList = PFont.list(); + printArray(fontList); + + // Save font list to file + for (int x = 0; x < fontList.length; x++) + { + logOutput.print("[" + x + "] "); + logOutput.println(fontList[x]); + } + logOutput.flush(); // Writes the remaining data to the file + logOutput.close(); // Finishes the file + + // Set the fontName from the array number or the defined fontName + if (fontNumber >= 0) + { + fontName = fontList[fontNumber]; + fontType = ""; + } + + char[] charset; + int index = 0, count = 0; + + int blockCount = unicodeBlocks.length; + + for (int i = 0; i < blockCount; i+=2) { + firstUnicode = unicodeBlocks[i]; + lastUnicode = unicodeBlocks[i+1]; + if (lastUnicode < firstUnicode) { + delay(100); + System.err.println("ERROR: Bad Unicode range secified, last < first!"); + System.err.print("first in range = 0x" + hex(firstUnicode, 4)); + System.err.println(", last in range = 0x" + hex(lastUnicode, 4)); + while (true); + } + // calculate the number of characters + count += (lastUnicode - firstUnicode + 1); + } + + count += specificUnicodes.length; + + println(); + println("====================="); + println("Creating font file..."); + println("Unicode blocks included = " + (blockCount/2)); + println("Specific unicodes included = " + specificUnicodes.length); + println("Total number of characters = " + count); + + if (count == 0) { + delay(100); + System.err.println("ERROR: No Unicode range or specific codes have been defined!"); + while (true); + } + + // allocate memory + charset = new char[count]; + + for (int i = 0; i < blockCount; i+=2) { + firstUnicode = unicodeBlocks[i]; + lastUnicode = unicodeBlocks[i+1]; + + // loading the range specified + for (int code = firstUnicode; code <= lastUnicode; code++) { + charset[index] = Character.toChars(code)[0]; + index++; + } + } + + // loading the specific point codes + for (int i = 0; i < specificUnicodes.length; i++) { + charset[index] = Character.toChars(specificUnicodes[i])[0]; + index++; + } + + // Make font smooth (anti-aliased) + boolean smooth = true; + + // Create the font in memory + myFont = createFont(fontName+fontType, displayFontSize, smooth, charset); + + // Print characters to the sketch window + fill(0, 0, 0); + textFont(myFont); + + // Set the left and top margin + int margin = displayFontSize; + translate(margin/2, margin); + + int gapx = displayFontSize*10/8; + int gapy = displayFontSize*10/8; + index = 0; + fill(0); + + textSize(displayFontSize); + + for (int y = 0; y < height-gapy; y += gapy) { + int x = 0; + while (x < width) { + + int unicode = charset[index]; + float cwidth = textWidth((char)unicode) + 2; + if ( (x + cwidth) > (width - gapx) ) break; + + // Draw the glyph to the screen + text(new String(Character.toChars(unicode)), x, y); + + // Move cursor + x += cwidth; + // Increment the counter + index++; + if (index >= count) break; + } + if (index >= count) break; + } + + + // creating font to save as a file + PFont font; + + font = createFont(fontName+fontType, fontSize, smooth, charset); + + println("Created font " + fontName + str(fontSize) + ".vlw"); + + // creating file + try { + print("Saving to sketch FontFiles folder... "); + + OutputStream output = createOutput("FontFiles/" + fontName + str(fontSize) + ".vlw"); + font.save(output); + output.close(); + + println("OK!"); + + delay(100); + + // Open up the FontFiles folder to access the saved file + String path = sketchPath(); + Desktop.getDesktop().open(new File(path+"/FontFiles")); + + System.err.println("All done! Note: Rectangles are displayed for non-existant characters."); + } + catch(IOException e) { + println("Doh! Failed to create the file"); + } +} diff --git a/Tools/Create_Smooth_Font/Create_font/FontFiles/Final-Frontier28.vlw b/Tools/Create_Smooth_Font/Create_font/FontFiles/Final-Frontier28.vlw new file mode 100644 index 0000000..2872fd5 Binary files /dev/null and b/Tools/Create_Smooth_Font/Create_font/FontFiles/Final-Frontier28.vlw differ diff --git a/Tools/Create_Smooth_Font/Create_font/data/Final-Frontier.ttf b/Tools/Create_Smooth_Font/Create_font/data/Final-Frontier.ttf new file mode 100644 index 0000000..823b9a5 Binary files /dev/null and b/Tools/Create_Smooth_Font/Create_font/data/Final-Frontier.ttf differ diff --git a/Tools/ESP32 UNO board mod/ESP32 UNO board mod.jpg b/Tools/ESP32 UNO board mod/ESP32 UNO board mod.jpg new file mode 100644 index 0000000..1063331 Binary files /dev/null and b/Tools/ESP32 UNO board mod/ESP32 UNO board mod.jpg differ diff --git a/Tools/ESP32 UNO board mod/ESP32 UNO board pinout.jpg b/Tools/ESP32 UNO board mod/ESP32 UNO board pinout.jpg new file mode 100644 index 0000000..3b10b76 Binary files /dev/null and b/Tools/ESP32 UNO board mod/ESP32 UNO board pinout.jpg differ diff --git a/Tools/PlatformIO/Configuring options.txt b/Tools/PlatformIO/Configuring options.txt new file mode 100644 index 0000000..3d0a02c --- /dev/null +++ b/Tools/PlatformIO/Configuring options.txt @@ -0,0 +1,33 @@ +PlatformIO User notes: + +It is possible to load settings from the calling program rather than modifying +the library for each project by modifying the "platformio.ini" file. + +The User_Setup_Select.h file will not load the user setting header files if +USER_SETUP_LOADED is defined. + +Instead of using #define, use the -D prefix, for example: + +[env:esp32dev] +platform = https://github.com/platformio/platform-espressif32.git#feature/stage +board = esp32dev +framework = arduino +upload_port = ESP32-Test-2481CE9C.local + +build_flags = + -Os + -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG + -DUSER_SETUP_LOADED=1 + -DILI9163_DRIVER=1 + -DTFT_WIDTH=128 + -DTFT_HEIGHT=160 + -DTFT_MISO=19 + -DTFT_MOSI=23 + -DTFT_SCLK=18 + -DTFT_CS=5 + -DTFT_DC=19 + -DTFT_RST=-1 + -DLOAD_GLCD=1 + -DSPI_FREQUENCY=27000000 + +lib_extra_dirs = B:\Projects\ESP32\ESP32Lib diff --git a/Tools/RPi_TFT_Connections.png b/Tools/RPi_TFT_Connections.png index 96bad1e..4e82b2c 100644 Binary files a/Tools/RPi_TFT_Connections.png and b/Tools/RPi_TFT_Connections.png differ diff --git a/User_Setup.h b/User_Setup.h index 8154475..95b3ef1 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -4,26 +4,56 @@ // See the User_Setup_Select.h file if you wish to be able to define multiple // setups and then easily select which setup file is used by the compiler. // -// If this file is editted correctly then all the library example sketches should +// If this file is edited correctly then all the library example sketches should // run without the need to make any more changes for a particular hardware setup! +// Note that some sketches are designed for a particular TFT pixel width/height + // ################################################################################## // -// Section 0. Call up the right driver file and any options for it +// Section 1. Call up the right driver file and any options for it // // ################################################################################## // Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER +//#define ST7735_DRIVER // Define additional parameters below for this display +//#define ILI9163_DRIVER // Define additional parameters below for this display //#define S6D02A1_DRIVER //#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9486_DRIVER +//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) +//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display +//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display +//#define R61581_DRIVER +//#define RM68140_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 +// Some displays support SPI reads via the MISO pin, other displays have a single +// bi-directional SDA pin and the library will try to read this via the MOSI line. +// To use the SDA line for reading data from the TFT uncomment the following line: + +// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only + +// For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display + +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below + +// #define M5STACK + +// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// #define TFT_WIDTH 80 +// #define TFT_WIDTH 128 +// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 +// #define TFT_HEIGHT 160 +// #define TFT_HEIGHT 128 +// #define TFT_HEIGHT 240 // ST7789 240 x 240 +// #define TFT_HEIGHT 320 // ST7789 240 x 320 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -32,22 +62,38 @@ // Comment out ALL BUT ONE of these options for a ST7735 display driver, save this // this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB +// #define ST7735_INITB +// #define ST7735_GREENTAB +// #define ST7735_GREENTAB2 +// #define ST7735_GREENTAB3 +// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) +// #define ST7735_REDTAB +// #define ST7735_BLACKTAB +// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset + +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. + +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + +// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options // ################################################################################## // -// Section 1. Define the pins that are used to interface with the display here +// Section 2. Define the pins that are used to interface with the display here // // ################################################################################## // We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : +// Typical setup for ESP8266 NodeMCU ESP-12 is : // // Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) // Display LED to NodeMCU pin VIN (or 5V, see below) @@ -61,31 +107,51 @@ // // The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin // -// The DC (Data Command) pin may be labelled AO or RS (Register Select) +// The DC (Data Command) pin may be labeled AO or RS (Register Select) // // With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS // line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin // to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. // // The NodeMCU D0 pin can be used for RST // -// See Section 2. below if DC or CS is connected to D0 // // Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin // If 5V is not available at a pin you can use 3.3V but backlight brightness // will be lower. + // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### -// For ModeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation - +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) + +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only // ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### @@ -95,25 +161,55 @@ //#define TFT_MISO 19 //#define TFT_MOSI 23 //#define TFT_SCLK 18 -//#define TFT_CS 5 // Chip select control pin +//#define TFT_CS 15 // Chip select control pin //#define TFT_DC 2 // Data Command control pin //#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) -// -// ################################################################################## +//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light (required for M5Stack) + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS // ################################################################################## // @@ -122,49 +218,64 @@ // ################################################################################## // Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT // ################################################################################## // -// Section 5. Other options +// Section 4. Other options // // ################################################################################## -// Define the SPI clock frequency +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. // With an ILI9341 display 40MHz works OK, 80MHz sometimes fails // With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display TBD MHz works OK, +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. // #define SPI_FREQUENCY 1000000 // #define SPI_FREQUENCY 5000000 // #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 20000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + +// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. +// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) +// then uncomment the following line: +//#define USE_HSPI_PORT // Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will +// supported. When commented out the code size will be smaller and sketches will // run slightly faster, so leave it commented out unless you need it! + // Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect // #define SUPPORT_TRANSACTIONS diff --git a/User_Setup_Select.h b/User_Setup_Select.h index e83f73b..fc620ac 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -1,7 +1,7 @@ // This header file contains a list of user setup files and defines which one the -// compliler uses when the IDE performs a Verify/Compile or Upload. +// compiler uses when the IDE performs a Verify/Compile or Upload. // -// Users can create configurations for different Espressiff boards and TFT displays. +// Users can create configurations for different Espressif boards and TFT displays. // This makes selecting between hardware setups easy by "uncommenting" one line. // The advantage of this hardware configuration method is that the examples provided @@ -9,12 +9,15 @@ // changes being needed. It also improves the portability of users sketches to other // hardware configurations and compatible libraries. // -// Create a shortcut to this file on your desktop to permit quick access for editting. +// Create a shortcut to this file on your desktop to permit quick access for editing. // Re-compile and upload after making and saving any changes to this file. // Customised User_Setup files are stored in the "User_Setups" folder. -// Only ONE line should be uncommented. Add extra lines and files as needed. +#ifndef USER_SETUP_LOADED // Lets PlatformIO users define settings in + // platformio.ini, see notes in "Tools" folder. + +// Only ONE line below should be uncommented. Add extra lines and files as needed. #include // Default setup is root library folder @@ -22,12 +25,40 @@ //#include // Setup file configured for my ST7735 //#include // Setup file configured for my ILI9163 //#include // Setup file configured for my S6D02A1 -//#include // Setup file configured for my stock RPi TFT -//#include // Setup file configured for my modified RPi TFT -//#include // Setup file configured for my ST7735 128x128 display -//#include // Setup file configured for my ILI9163 128x128 display +//#include // Setup file configured for my stock RPi TFT +//#include // Setup file configured for my modified RPi TFT +//#include // Setup file configured for my ST7735 128x128 display +//#include // Setup file configured for my ILI9163 128x128 display +//#include // Setup file configured for my ST7735 +//#include // Setup file configured for ESP8266 and RPi TFT with touch -//#include // Setup file template for copying/editting +//#include // Setup file configured for ESP32 and RPi TFT with touch +//#include // Setup file for the ESP32 based M5Stack +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file configured for HX8357D (untested) +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file for any Waveshare ePaper display +//#include // Setup file configured for ST7789 + +//#include // Setup file configured for RM68140 with parallel bus + +//#include // Setup file for ESP8266 and ILI9488 SPI bus TFT +//#include // Setup file for ESP32 and ILI9488 SPI bus TFT + +//#include // Setup file for ESP32 and TTGO T4 (BTC) ILI9341 SPI bus TFT +//#include // Setup file for ESP32 and TTGO TM ST7789 SPI bus TFT +//#include // Setup file configured for ST7789 240 x 240 +//#include // Setup file for ESP32 and TTGO T-Display ST7789V SPI bus TFT + +//#include // Setup file configured for my ST7735S 80x160 + +//#include // Setup file for ESP8266 and ST7789 125 x 240 TFT + +//#include + + +#endif // USER_SETUP_LOADED @@ -39,28 +70,80 @@ ///////////////////////////////////////////////////////////////////////////////////// +// Identical looking TFT displays may have a different colour ordering in the 16 bit colour +#define TFT_BGR 0 // Colour order Blue-Green-Red +#define TFT_RGB 1 // Colour order Red-Green-Blue + + // Load the right driver definition - do not tinker here ! #if defined (ILI9341_DRIVER) #include + #define TFT_DRIVER 0x9341 #elif defined (ST7735_DRIVER) #include + #define TFT_DRIVER 0x7735 #elif defined (ILI9163_DRIVER) #include + #define TFT_DRIVER 0x9163 #elif defined (S6D02A1_DRIVER) #include + #define TFT_DRIVER 0x6D02 #elif defined (RPI_ILI9486_DRIVER) - #include + #include + #define TFT_DRIVER 0x9486 +#elif defined (ILI9486_DRIVER) + #include + #define TFT_DRIVER 0x9486 +#elif defined (ILI9481_DRIVER) + #include + #define TFT_DRIVER 0x9481 +#elif defined (ILI9488_DRIVER) + #include + #define TFT_DRIVER 0x9488 +#elif defined (HX8357D_DRIVER) + #include "TFT_Drivers/HX8357D_Defines.h" + #define TFT_DRIVER 0x8357 +#elif defined (EPD_DRIVER) + #include "TFT_Drivers/EPD_Defines.h" + #define TFT_DRIVER 0xE9D +#elif defined (ST7789_DRIVER) + #include "TFT_Drivers/ST7789_Defines.h" + #define TFT_DRIVER 0x7789 +#elif defined (R61581_DRIVER) + #include "TFT_Drivers/R61581_Defines.h" + #define TFT_DRIVER 0x6158 +#elif defined (ST7789_2_DRIVER) + #include "TFT_Drivers/ST7789_2_Defines.h" + #define TFT_DRIVER 0x778B +#elif defined (RM68140_DRIVER) + #include "TFT_Drivers/RM68140_Defines.h" + #define TFT_DRIVER 0x6814 +#elif defined (XYZZY_DRIVER) // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE + #include "TFT_Drivers/XYZZY_Defines.h" + #define TFT_DRIVER 0x0000 +#else + #define TFT_DRIVER 0x0000 #endif -// These are the pins for all ESP8266 boards -#define PIN_D0 16 -#define PIN_D1 5 -#define PIN_D2 4 -#define PIN_D3 0 -#define PIN_D4 2 -#define PIN_D5 14 -#define PIN_D6 12 -#define PIN_D7 13 -#define PIN_D8 15 -#define PIN_D9 3 -#define PIN_D10 1 + +// These are the pins for ESP8266 boards +// Name GPIO NodeMCU Function +#define PIN_D0 D0 // GPIO16 WAKE +#define PIN_D1 D1 // GPIO5 User purpose +#define PIN_D2 D2 // GPIO4 User purpose +#define PIN_D3 D3 // GPIO0 Low on boot means enter FLASH mode +#define PIN_D4 D4 // GPIO2 TXD1 (must be high on boot to go to UART0 FLASH mode) +#define PIN_D5 D5 // GPIO14 HSCLK +#define PIN_D6 D6 // GPIO12 HMISO +#define PIN_D7 D7 // GPIO13 HMOSI RXD2 +#define PIN_D8 D8 // GPIO15 HCS TXD0 (must be low on boot to enter UART0 FLASH mode) +#define PIN_D9 3 // RXD0 +#define PIN_D10 1 // TXD0 + +#define PIN_MOSI 8 // SD1 FLASH and overlap mode +#define PIN_MISO 7 // SD0 +#define PIN_SCLK 6 // CLK +#define PIN_HWCS 0 // D3 + +#define PIN_D11 9 // SD2 +#define PIN_D12 10 // SD4 diff --git a/User_Setups/Setup10_RPi_touch_ILI9486.h b/User_Setups/Setup10_RPi_touch_ILI9486.h new file mode 100644 index 0000000..ffe2f71 --- /dev/null +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -0,0 +1,31 @@ +// See SetupX_Template.h for all options available + +#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +#define SPI_FREQUENCY 16000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup11_RPi_touch_ILI9486.h b/User_Setups/Setup11_RPi_touch_ILI9486.h new file mode 100644 index 0000000..e2edbb3 --- /dev/null +++ b/User_Setups/Setup11_RPi_touch_ILI9486.h @@ -0,0 +1,30 @@ +// See SetupX_Template.h for all options available + +#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + + +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 15 // Chip select control pin +#define TFT_DC 2 // Data Command control pin +#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +#define SPI_FREQUENCY 20000000 + +#define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setups/Setup12_M5Stack.h b/User_Setups/Setup12_M5Stack.h new file mode 100644 index 0000000..a1b564f --- /dev/null +++ b/User_Setups/Setup12_M5Stack.h @@ -0,0 +1,32 @@ +// See SetupX_Template.h for all options available + +#define ILI9341_DRIVER + + +#define M5STACK + + +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 14 // Chip select control pin +#define TFT_DC 27 // Data Command control pin +#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +#define TFT_BL 32 // LED back-light + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +#define SPI_FREQUENCY 27000000 + +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 5000000 \ No newline at end of file diff --git a/User_Setups/Setup135_ST7789.h b/User_Setups/Setup135_ST7789.h new file mode 100644 index 0000000..e87abad --- /dev/null +++ b/User_Setups/Setup135_ST7789.h @@ -0,0 +1,56 @@ +// ST7789 135 x 240 display with no chip select line + +#define ST7789_DRIVER // Configure all registers + +#define TFT_WIDTH 135 +#define TFT_HEIGHT 240 + +#define CGRAM_OFFSET // Library will add offsets required + +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + +// DSTIKE stepup +//#define TFT_DC 23 +//#define TFT_RST 32 +//#define TFT_MOSI 26 +//#define TFT_SCLK 27 + +// Generic ESP32 setup +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS -1 // Not connected +//#define TFT_DC 2 +//#define TFT_RST 4 // Connect reset to ensure display initialises + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS -1 // Define as not used +#define TFT_DC PIN_D1 // Data Command control pin +//#define TFT_RST PIN_D4 // TFT reset pin (could connect to NodeMCU RST, see next line) +#define TFT_RST -1 // TFT reset pin connect to NodeMCU RST, must also then add 10K pull down to TFT SCK + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 27000000 +#define SPI_FREQUENCY 40000000 + +#define SPI_READ_FREQUENCY 20000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + +// #define SUPPORT_TRANSACTIONS \ No newline at end of file diff --git a/User_Setups/Setup13_ILI9481_Parallel.h b/User_Setups/Setup13_ILI9481_Parallel.h new file mode 100644 index 0000000..1758420 --- /dev/null +++ b/User_Setups/Setup13_ILI9481_Parallel.h @@ -0,0 +1,35 @@ +// See SetupX_Template.h for all options available + +#define ESP32_PARALLEL + + +#define ILI9481_DRIVER + + +// ESP32 pins used for UNO format board +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +#define TFT_RD 2 + +#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +#define TFT_D1 13 // so a single register write sets/clears all bits +#define TFT_D2 26 +#define TFT_D3 25 +#define TFT_D4 17 +#define TFT_D5 16 +#define TFT_D6 27 +#define TFT_D7 14 + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT diff --git a/User_Setups/Setup14_ILI9341_Parallel.h b/User_Setups/Setup14_ILI9341_Parallel.h new file mode 100644 index 0000000..d19a827 --- /dev/null +++ b/User_Setups/Setup14_ILI9341_Parallel.h @@ -0,0 +1,35 @@ +// See SetupX_Template.h for all options available + +#define ESP32_PARALLEL + + +#define ILI9341_DRIVER + + +// ESP32 pins used for the parallel interface TFT +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +#define TFT_RD 2 + +#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +#define TFT_D1 13 // so a single register write sets/clears all bits +#define TFT_D2 26 +#define TFT_D3 25 +#define TFT_D4 17 +#define TFT_D5 16 +#define TFT_D6 27 +#define TFT_D7 14 + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT diff --git a/User_Setups/Setup15_HX8357D.h b/User_Setups/Setup15_HX8357D.h new file mode 100644 index 0000000..f4ee614 --- /dev/null +++ b/User_Setups/Setup15_HX8357D.h @@ -0,0 +1,31 @@ +// See SetupX_Template.h for all options available + +#define HX8357D_DRIVER + + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup16_ILI9488_Parallel.h b/User_Setups/Setup16_ILI9488_Parallel.h new file mode 100644 index 0000000..5d3cb58 --- /dev/null +++ b/User_Setups/Setup16_ILI9488_Parallel.h @@ -0,0 +1,35 @@ +// See SetupX_Template.h for all options available + +#define ESP32_PARALLEL + + +#define ILI9488_DRIVER + + +// ESP32 pins used +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +#define TFT_RD 2 + +#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +#define TFT_D1 13 // so a single register write sets/clears all bits +#define TFT_D2 26 +#define TFT_D3 25 +#define TFT_D4 17 +#define TFT_D5 16 +#define TFT_D6 27 +#define TFT_D7 14 + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT diff --git a/User_Setups/Setup17_ePaper.h b/User_Setups/Setup17_ePaper.h new file mode 100644 index 0000000..86d0e65 --- /dev/null +++ b/User_Setups/Setup17_ePaper.h @@ -0,0 +1,40 @@ +// See SetupX_Template.h for all options available + +#define EPD_DRIVER // ePaper driver + + +// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + +// Note: Pin allocations for the ePaper signals are defined in +// the ePaper library's epdif.h file. There follows the default +// pins already included in epdif.h file for the ESP8266: + +/////////////////////////////////////////////////////////////////// +// For ESP8266 connect as follows: // +// Display 3.3V to NodeMCU 3V3 // +// Display GND to NodeMCU GND // +// // +// Display GPIO NodeMCU pin // +// BUSY 5 D1 // +// RESET 4 D2 // +// DC 0 D3 // +// CS 2 D4 // +// CLK 14 D5 // +// D6 (MISO not connected to display) // +// DIN 13 D7 // +// // +/////////////////////////////////////////////////////////////////// + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT diff --git a/User_Setups/Setup18_ST7789.h b/User_Setups/Setup18_ST7789.h new file mode 100644 index 0000000..1f9be03 --- /dev/null +++ b/User_Setups/Setup18_ST7789.h @@ -0,0 +1,44 @@ +// See SetupX_Template.h for all options available + +#define ST7789_DRIVER + +// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only + +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// For ST7789 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + + +// My ST7789 display has TCT_CS wired permananently low so the pin is not defined here + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +// #define SPI_FREQUENCY 80000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + + +//#define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup19_RM68140_Parallel.h b/User_Setups/Setup19_RM68140_Parallel.h new file mode 100644 index 0000000..85300ae --- /dev/null +++ b/User_Setups/Setup19_RM68140_Parallel.h @@ -0,0 +1,35 @@ +// See SetupX_Template.h for all options available + +#define ESP32_PARALLEL + + +#define RM68140_DRIVER + + +// ESP32 pins used for UNO format board +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +#define TFT_RD 2 + +#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +#define TFT_D1 13 // so a single register write sets/clears all bits +#define TFT_D2 26 +#define TFT_D3 25 +#define TFT_D4 17 +#define TFT_D5 16 +#define TFT_D6 27 +#define TFT_D7 14 + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT diff --git a/User_Setups/Setup1_ILI9341.h b/User_Setups/Setup1_ILI9341.h index 82b0469..82d69c5 100644 --- a/User_Setups/Setup1_ILI9341.h +++ b/User_Setups/Setup1_ILI9341.h @@ -1,113 +1,13 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -117,36 +17,17 @@ #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## + +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 - #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 27000000 +#define SPI_FREQUENCY 40000000 // #define SPI_FREQUENCY 80000000 +#define SPI_READ_FREQUENCY 20000000 + +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup20_ILI9488.h b/User_Setups/Setup20_ILI9488.h new file mode 100644 index 0000000..7d1eaf1 --- /dev/null +++ b/User_Setups/Setup20_ILI9488.h @@ -0,0 +1,32 @@ +// See SetupX_Template.h for all options available + +#define ILI9488_DRIVER + + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 + + +#define SPI_TOUCH_FREQUENCY 2500000 + + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup21_ILI9488.h b/User_Setups/Setup21_ILI9488.h new file mode 100644 index 0000000..358eef4 --- /dev/null +++ b/User_Setups/Setup21_ILI9488.h @@ -0,0 +1,34 @@ +// See SetupX_Template.h for all options available + +#define ILI9488_DRIVER + +//#define TFT_INVERSION_OFF + +#define TFT_MISO 19 // (leave TFT SDO disconnected if other SPI devices share MISO) +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 15 // Chip select control pin +#define TFT_DC 2 // Data Command control pin +#define TFT_RST 4 // Reset pin (could connect to RST pin) + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +// #define SPI_FREQUENCY 80000000 + +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 16000000 + +#define SPI_TOUCH_FREQUENCY 2500000 diff --git a/User_Setups/Setup22_TTGO_T4.h b/User_Setups/Setup22_TTGO_T4.h new file mode 100644 index 0000000..a62af13 --- /dev/null +++ b/User_Setups/Setup22_TTGO_T4.h @@ -0,0 +1,30 @@ +// Setup for the TTGO T4 ("Bitcoin Tracker") ESP32 board with 2.2" ILI9341 display + +// See SetupX_Template.h for all options available + +#define ILI9341_DRIVER + +#define TFT_MISO 12 +#define TFT_MOSI 23 +#define TFT_SCLK 18 + +#define TFT_CS 27 +#define TFT_DC 26 +#define TFT_RST 5 + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF + +#define SMOOTH_FONT + +//#define SPI_FREQUENCY 27000000 + #define SPI_FREQUENCY 40000000 // Maximum for ILI9341 + +#define USE_HSPI_PORT + +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V diff --git a/User_Setups/Setup23_TTGO_TM.h b/User_Setups/Setup23_TTGO_TM.h new file mode 100644 index 0000000..58468d5 --- /dev/null +++ b/User_Setups/Setup23_TTGO_TM.h @@ -0,0 +1,36 @@ +// Setup for the TTGO TM (Music) ESP32 board with 2.4" ST7789V display + +// See SetupX_Template.h for all options available + +#define ST7789_DRIVER + +#define TFT_SDA_READ // Read from display, it only provides an SDA pin + +#define TFT_MISO 19 // Must be defined even though it is not used +#define TFT_MOSI 23 // Connected to display SDA line +#define TFT_SCLK 18 + +#define TFT_CS 05 +#define TFT_DC 16 +#define TFT_RST 17 + +#define TFT_WIDTH 240 +#define TFT_HEIGHT 320 + +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF + +#define SMOOTH_FONT + +#define SPI_FREQUENCY 40000000 // This display also seems to work reliably at 80MHz +#define SPI_FREQUENCY 80000000 + +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V diff --git a/User_Setups/Setup24_ST7789.h b/User_Setups/Setup24_ST7789.h new file mode 100644 index 0000000..44e4343 --- /dev/null +++ b/User_Setups/Setup24_ST7789.h @@ -0,0 +1,54 @@ +// ST7789 240 x 240 display with no chip select line + +#define ST7789_DRIVER // Configure all registers + +#define TFT_WIDTH 240 +#define TFT_HEIGHT 240 + +//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +//#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +//#define TFT_INVERSION_ON +//#define TFT_INVERSION_OFF + +// DSTIKE stepup +//#define TFT_DC 23 +//#define TFT_RST 32 +//#define TFT_MOSI 26 +//#define TFT_SCLK 27 + +// Generic ESP32 setup +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS -1 // Not connected +//#define TFT_DC 2 +//#define TFT_RST 4 // Connect reset to ensure display initialises + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS -1 // Define as not used +#define TFT_DC PIN_D1 // Data Command control pin +#define TFT_RST PIN_D4 // TFT reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // TFT reset pin connect to NodeMCU RST, must also then add 10K pull down to TFT SCK + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 27000000 +#define SPI_FREQUENCY 40000000 + +#define SPI_READ_FREQUENCY 20000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + +// #define SUPPORT_TRANSACTIONS \ No newline at end of file diff --git a/User_Setups/Setup25_TTGO_T_Display.h b/User_Setups/Setup25_TTGO_T_Display.h new file mode 100644 index 0000000..18a0c2d --- /dev/null +++ b/User_Setups/Setup25_TTGO_T_Display.h @@ -0,0 +1,38 @@ +// Setup for the TTGO T4 ("Bitcoin Tracker") ESP32 board with 2.2" ILI9341 display + +// See SetupX_Template.h for all options available + +#define ST7789_DRIVER + +#define TFT_WIDTH 135 +#define TFT_HEIGHT 240 + +#define CGRAM_OFFSET // Library will add offsets required + +//#define TFT_MISO -1 + +#define TFT_MOSI 19 +#define TFT_SCLK 18 +#define TFT_CS 5 +#define TFT_DC 16 +#define TFT_RST 23 + +#define TFT_BL 4 // Display backlight control pin + +#define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options + +#define LOAD_GLCD +#define LOAD_FONT2 +#define LOAD_FONT4 +#define LOAD_FONT6 +#define LOAD_FONT7 +#define LOAD_FONT8 +#define LOAD_GFXFF + +#define SMOOTH_FONT + +//#define SPI_FREQUENCY 27000000 + #define SPI_FREQUENCY 40000000 // Maximum for ILI9341 + + +#define SPI_READ_FREQUENCY 6000000 // 6 MHz is the maximum SPI read speed for the ST7789V diff --git a/User_Setups/Setup2_ST7735.h b/User_Setups/Setup2_ST7735.h index 8f1c1c2..b9e618f 100644 --- a/User_Setups/Setup2_ST7735.h +++ b/User_Setups/Setup2_ST7735.h @@ -1,114 +1,21 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation + #define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 #define ST7735_REDTAB -//#define ST7735_BLACKTAB -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not test/supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -116,38 +23,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Maximum for my ST7735. It is actually 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup3_ILI9163.h b/User_Setups/Setup3_ILI9163.h index 56cfccd..f9b2656 100644 --- a/User_Setups/Setup3_ILI9163.h +++ b/User_Setups/Setup3_ILI9163.h @@ -1,101 +1,18 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER #define ILI9163_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation + #define TFT_WIDTH 128 #define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -103,39 +20,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display TBD MHz works OK, - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup43_ST7735.h b/User_Setups/Setup43_ST7735.h new file mode 100644 index 0000000..8865f54 --- /dev/null +++ b/User_Setups/Setup43_ST7735.h @@ -0,0 +1,37 @@ +// Setup for ESP32 and ST7735 80 x 160 TFT + +// See SetupX_Template.h for all options available + +#define ST7735_DRIVER + + +#define TFT_WIDTH 80 +#define TFT_HEIGHT 160 + + +#define ST7735_GREENTAB160x80 + + +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 15 // Chip select control pin +#define TFT_DC 2 // Data Command control pin +#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +//#define SPI_FREQUENCY 20000000 + #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 diff --git a/User_Setups/Setup4_S6D02A1.h b/User_Setups/Setup4_S6D02A1.h index 72a6fe4..233117c 100644 --- a/User_Setups/Setup4_S6D02A1.h +++ b/User_Setups/Setup4_S6D02A1.h @@ -1,97 +1,14 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER #define S6D02A1_DRIVER -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -99,39 +16,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display TBD MHz works OK, - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +// #define SPI_FREQUENCY 40000000 +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup5_RPi_ILI9486.h b/User_Setups/Setup5_RPi_ILI9486.h index 5517041..ba21c31 100644 --- a/User_Setups/Setup5_RPi_ILI9486.h +++ b/User_Setups/Setup5_RPi_ILI9486.h @@ -1,119 +1,14 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// For ST7735 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -123,37 +18,12 @@ #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## +#define SPI_FREQUENCY 20000000 -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display TBD MHz works OK, +#define SPI_TOUCH_FREQUENCY 2500000 -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 - #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup6_RPi_Wr_ILI9486.h b/User_Setups/Setup6_RPi_Wr_ILI9486.h index 2f1552a..abeaddb 100644 --- a/User_Setups/Setup6_RPi_Wr_ILI9486.h +++ b/User_Setups/Setup6_RPi_Wr_ILI9486.h @@ -1,119 +1,16 @@ -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER -//#define ILI9163_DRIVER -//#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_GREENTAB3 -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB - -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only +#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -123,37 +20,12 @@ #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## +#define SPI_FREQUENCY 20000000 -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display TBD MHz works OK, +#define SPI_TOUCH_FREQUENCY 2500000 -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 - #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 - - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup7_ST7735_128x128.h b/User_Setups/Setup7_ST7735_128x128.h index 6d9140e..6821f47 100644 --- a/User_Setups/Setup7_ST7735_128x128.h +++ b/User_Setups/Setup7_ST7735_128x128.h @@ -1,117 +1,21 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER #define ST7735_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation + #define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB // No display -//#define ST7735_GREENTAB // 2 pixel left border -//#define ST7735_GREENTAB2 // Colours wrong RB swap -//#define ST7735_GREENTAB3 // 2 pixel left border #define ST7735_GREENTAB128 // For 128 x 128 display -//#define ST7735_REDTAB // colours wrong rotation 0 needs y shift of 32, 1 an x shift of 32 -//#define ST7735_BLACKTAB -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labell AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not test/supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -119,40 +23,17 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## + +#define SMOOTH_FONT - - -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Maximum for my ST7735. It is actually 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup8_ILI9163_128x128.h b/User_Setups/Setup8_ILI9163_128x128.h index f5d6607..da42ec3 100644 --- a/User_Setups/Setup8_ILI9163_128x128.h +++ b/User_Setups/Setup8_ILI9163_128x128.h @@ -1,101 +1,18 @@ -// USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! +// See SetupX_Template.h for all options available -// ################################################################################## -// -// Section 0. Call up the right driver file and any options for it -// -// ################################################################################## - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -//#define ST7735_DRIVER #define ILI9163_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation + #define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 -// ################################################################################## -// -// Section 1. Define the pins that are used to interface with the display here -// -// ################################################################################## -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// See Section 2. below if DC or CS is connected to D0 -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### - -// ModeMCU +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## - -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test - -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters @@ -103,39 +20,16 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +#define SMOOTH_FONT -// ################################################################################## -// -// Section 5. Other options -// -// ################################################################################## - -// Define the SPI clock frequency -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 40 MHz works OK, - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 - #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 -// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS -// #define SPI_FREQUENCY 80000000 +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +#define SPI_TOUCH_FREQUENCY 2500000 -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! -// Transaction support is needed to work with SD library but not needed with TFT_SdFat // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup9_ST7735_Overlap.h b/User_Setups/Setup9_ST7735_Overlap.h new file mode 100644 index 0000000..2237893 --- /dev/null +++ b/User_Setups/Setup9_ST7735_Overlap.h @@ -0,0 +1,41 @@ +// See SetupX_Template.h for all options available + +#define ST7735_DRIVER + + +#define TFT_WIDTH 128 +#define TFT_HEIGHT 160 + + +#define ST7735_REDTAB + + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +#define TFT_CS PIN_D3 +#define TFT_DC PIN_D5 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +#define TFT_SPI_OVERLAP + + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + + +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 + +#define SPI_TOUCH_FREQUENCY 2500000 + + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index cc28faa..a902f8b 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -1,28 +1,58 @@ // USER DEFINED SETTINGS -// -// The User_Setup header that will be called up is defined in User_Setup_Select.h -// This file is a default template that can be copied to create new setup files -// Add the new header file to the list in User_Setup_Select.h -// // Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// If this file is editted correctly then all the library example sketches should +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should // run without the need to make any more changes for a particular hardware setup! +// Note that some sketches are designed for a particular TFT pixel width/height + // ################################################################################## // -// Section 0. Call up the right driver file and any options for it +// Section 1. Call up the right driver file and any options for it // // ################################################################################## // Only define one driver, the other ones must be commented out #define ILI9341_DRIVER -//#define ST7735_DRIVER +//#define ST7735_DRIVER // Define additional parameters below for this display +//#define ILI9163_DRIVER // Define additional parameters below for this display +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9486_DRIVER +//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) +//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display +//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display +//#define R61581_DRIVER -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -//#define TFT_WIDTH 128 -//#define TFT_HEIGHT 160 -//#define TFT_HEIGHT 128 +// Some displays support SPI reads via the MISO pin, other displays have a single +// bi-directional SDA pin and the library will try to read this via the MOSI line. +// To use the SDA line for reading data from the TFT uncomment the following line: + +// #define TFT_SDA_READ // This option if for ESP32 ONLY, tested with ST7789 display only + +// For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display +// Try ONE option at a time to find the correct colour order for your display + +// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue +// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red + +// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below + +// #define M5STACK + +// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// #define TFT_WIDTH 80 +// #define TFT_WIDTH 128 +// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 +// #define TFT_HEIGHT 160 +// #define TFT_HEIGHT 128 +// #define TFT_HEIGHT 240 // ST7789 240 x 240 +// #define TFT_HEIGHT 320 // ST7789 240 x 320 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -31,26 +61,44 @@ // Comment out ALL BUT ONE of these options for a ST7735 display driver, save this // this User_Setup file, then rebuild and upload the sketch to the board again: -//#define ST7735_INITB -//#define ST7735_GREENTAB -//#define ST7735_GREENTAB2 -//#define ST7735_REDTAB -//#define ST7735_BLACKTAB +// #define ST7735_INITB +// #define ST7735_GREENTAB +// #define ST7735_GREENTAB2 +// #define ST7735_GREENTAB3 +// #define ST7735_GREENTAB128 // For 128 x 128 display +// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) +// #define ST7735_REDTAB +// #define ST7735_BLACKTAB +// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset + +// If colours are inverted (white shows as black) then uncomment one of the next +// 2 lines try both options, one of the options should correct the inversion. + +// #define TFT_INVERSION_ON +// #define TFT_INVERSION_OFF + +// If a backlight control signal is available then define the TFT_BL pin in Section 2 +// below. The backlight will be turned ON when tft.begin() is called, but the library +// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be +// driven with a PWM signal or turned OFF/ON then this must be handled by the user +// sketch. e.g. with digitalWrite(TFT_BL, LOW); + +// #define TFT_BACKLIGHT_ON HIGH // HIGH or LOW are options // ################################################################################## // -// Section 1. Define the pins that are used to interface with the display here +// Section 2. Define the pins that are used to interface with the display here // // ################################################################################## // We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 is : +// Typical setup for ESP8266 NodeMCU ESP-12 is : // // Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) // Display LED to NodeMCU pin VIN (or 5V, see below) // Display SCK to NodeMCU pin D5 // Display SDI/MOSI to NodeMCU pin D7 -// Display DC (or AO)to NodeMCU pin D3 +// Display DC (RS/AO)to NodeMCU pin D3 // Display RESET to NodeMCU pin D4 (or RST, see below) // Display CS to NodeMCU pin D8 (or GND, see below) // Display GND to NodeMCU pin GND (0V) @@ -58,47 +106,109 @@ // // The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin // +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// // With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI deivces (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS // line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin // to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. // // The NodeMCU D0 pin can be used for RST // -// See Section 2. below if DC or CS is connected to D0 // // Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin // If 5V is not available at a pin you can use 3.3V but backlight brightness // will be lower. -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR SETUP ###### -// ModeMCU +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation #define TFT_CS PIN_D8 // Chip select control pin D8 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) + +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board (planned, not supported yet) -//#define TFT_CS 5 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to Arduino RESET pin) + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST -// ################################################################################## -// -// Section 2. Define the way the DC and/or CS lines are driven -// -// ################################################################################## +//#define TFT_BL 32 // LED back-light (only for ST7789 with backlight control pin) -// Normally the library uses direct register access for the DC and CS lines for speed -// If D0 (GPIO16) is used for CS or DC then a different slower method must be used -// Uncomment one line if D0 is used for DC or CS -// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test -// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light (required for M5Stack) + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 -// #define D0_USED_FOR_DC -// #define D0_USED_FOR_CS // ################################################################################## // @@ -107,48 +217,64 @@ // ################################################################################## // Comment out the #defines below with // to stop that font being loaded -// The ESP8366 had plenty of memory so commenting out fonts is not normally necessary -// If all fonts are loaded the extra FLASH space required is about 17Kbytes... -// To save FLASH space only enable the fonts you need! +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! #define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH #define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters #define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts -// ################################################################################## -// -// Section 4. Not used -// -// ################################################################################## +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT // ################################################################################## // -// Section 5. Other options +// Section 4. Other options // // ################################################################################## -// Define the SPI clock frequency +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. // With an ILI9341 display 40MHz works OK, 80MHz sometimes fails // With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. // #define SPI_FREQUENCY 1000000 // #define SPI_FREQUENCY 5000000 // #define SPI_FREQUENCY 10000000 // #define SPI_FREQUENCY 20000000 -// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 - #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +// Optional reduced SPI frequency for reading TFT +#define SPI_READ_FREQUENCY 20000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + +// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. +// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) +// then uncomment the following line to use the HSPI port: +//#define USE_HSPI_PORT // Comment out the following #define if "SPI Transactions" do not need to be -// supported. Tranaction support is required if other SPI devices are connected. -// When commented out the code size will be smaller and sketches will +// supported. When commented out the code size will be smaller and sketches will // run slightly faster, so leave it commented out unless you need it! + // Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect // #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/User_Custom_Fonts.h b/User_Setups/User_Custom_Fonts.h index ef9e0ae..f2dc3d3 100644 --- a/User_Setups/User_Custom_Fonts.h +++ b/User_Setups/User_Custom_Fonts.h @@ -13,9 +13,10 @@ ^^^^ */ -// When font files are placed in the Custom folder then they must also be #included here: +// When font files are placed in the Custom folder (TFT_eSPI\Fonts\Custom) then they must +// also be #included here: -// The comment added is a shorthand reference but this is not essential +// The CF_OL24 etc are a shorthand reference, but this is not essential to use the fonts #ifdef LOAD_GFXFF diff --git a/examples/160 x 128/Flash_Bitmap2/Alert.h b/examples/160 x 128/Flash_Bitmap2/Alert.h deleted file mode 100644 index 54d013d..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Alert.h +++ /dev/null @@ -1,42 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t alertWidth = 32; -const uint16_t alertHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short alert[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1080,0xAC66,0xEDE8,0xFE69,0xC4C6,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xBCC6,0xFE68,0xFE68,0xFE6A,0xFE68,0xEDE8,0x18A1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8344,0xFE48,0xFE8C,0xFFDD,0xFFFF,0xFEF0,0xFE48,0xB466,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1880,0xEDC7,0xFE48,0xFF99,0xFFBC,0xFF9B,0xFFBD,0xFE6A,0xFE48,0x5A23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BE5,0xFE28,0xFED0,0xFFBC,0xFF7A,0xFF9A,0xFF9B,0xFF35,0xFE28,0xBCA6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3962,0xFE28,0xFE28,0xFF9A,0xFF79,0xFF9A,0xFF9B,0xFF9A,0xFFBD,0xFE6B,0xFE28,0x72E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xB465,0xFE28,0xFEF2,0xFF7A,0xFF79,0xFF7A,0xFF9A,0xFF7A,0xFF7A,0xFF78,0xFE28,0xDD67,0x0860,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5A22,0xFE07,0xFE29,0xFF9B,0xFF37,0xFF58,0xFF79,0xFF79,0xFF79,0xFF58,0xFF9B,0xFEAE,0xFE07,0x93A4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xC4A5,0xFE07,0xFF15,0xFF37,0xFF36,0xAD11,0x2965,0x2965,0xCDF4,0xFF37,0xFF37,0xFF79,0xFE07,0xFE07,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7B03,0xFDE7,0xFE4B,0xFF79,0xFEF4,0xFF15,0xB552,0x2945,0x2945,0xDE55,0xFF16,0xFF15,0xFF58,0xFED1,0xFDE7,0xAC25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0xDD26,0xFDE7,0xFF57,0xFED3,0xFED2,0xFEF4,0xBD93,0x2124,0x2124,0xDE75,0xFF14,0xFED3,0xFED3,0xFF7A,0xFE08,0xFDE7,0x49A2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 11, 384 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BA4,0xFDC6,0xFE6E,0xFF36,0xFE90,0xFEB1,0xFED3,0xC592,0x2124,0x2124,0xE675,0xFED3,0xFEB2,0xFEB1,0xFEF3,0xFEF3,0xFDC6,0xBC45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 12, 416 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3141,0xF5C6,0xF5C7,0xFF58,0xFE90,0xFE6F,0xFE8F,0xFEB1,0xCDB2,0x2104,0x2104,0xF6B4,0xFEB1,0xFE90,0xFE8F,0xFE90,0xFF58,0xFE0A,0xF5C6,0x72A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 13, 448 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xABE4,0xF5A6,0xFEB1,0xFED3,0xFE4E,0xFE6E,0xFE6F,0xFE90,0xD5F2,0x18E3,0x18E3,0xFED4,0xFE90,0xFE6F,0xFE6F,0xFE6E,0xFE91,0xFF36,0xF5A6,0xCCA5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 14, 480 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x5202,0xF5A6,0xF5C7,0xFF58,0xFE4D,0xFE4D,0xFE4D,0xFE4E,0xFE6F,0xDE11,0x18C3,0x18C3,0xFED3,0xFE6F,0xFE6E,0xFE4E,0xFE4D,0xFE4D,0xFF16,0xFE2C,0xF5A6,0x9363,0x0000,0x0000,0x0000,0x0000,0x0000, // row 15, 512 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0xBC44,0xF585,0xFED3,0xFE6F,0xFE2C,0xFE2C,0xFE2D,0xFE4D,0xFE4E,0xE630,0x10A2,0x2104,0xFED1,0xFE4E,0xFE4D,0xFE4D,0xFE2D,0xFE2C,0xFE4D,0xFF37,0xF586,0xF585,0x28E1,0x0000,0x0000,0x0000,0x0000, // row 16, 544 pixels -0x0000,0x0000,0x0000,0x0000,0x7282,0xF565,0xF5EA,0xFF16,0xFE0B,0xFE0B,0xFE0B,0xFE2C,0xFE2C,0xFE4D,0xF670,0x1082,0x2924,0xFEB0,0xFE2D,0xFE2C,0xFE2C,0xFE2C,0xFE0B,0xFE0B,0xFEB2,0xFE6F,0xF565,0xA383,0x0000,0x0000,0x0000,0x0000, // row 17, 576 pixels -0x0000,0x0000,0x0000,0x0840,0xD4C4,0xF565,0xFEF5,0xFE0C,0xFDE9,0xFDEA,0xFE0A,0xFE0B,0xFE0B,0xFE2C,0xFE8F,0x0861,0x2964,0xFE8F,0xFE2C,0xFE0B,0xFE0B,0xFE0B,0xFE0A,0xFDEA,0xFE0B,0xFF37,0xF586,0xF565,0x4181,0x0000,0x0000,0x0000, // row 18, 608 pixels -0x0000,0x0000,0x0000,0x9343,0xF545,0xF60C,0xFED3,0xFDC8,0xFDC8,0xFDC9,0xFDE9,0xFDEA,0xFDEA,0xFE0B,0xFE8E,0x0861,0x3184,0xFE6D,0xFE0B,0xFE0A,0xFDEA,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFE4E,0xFEB2,0xF545,0xB3E3,0x0000,0x0000,0x0000, // row 19, 640 pixels -0x0000,0x0000,0x28E0,0xF544,0xF545,0xFF17,0xFDC8,0xFDA7,0xFDA7,0xFDC8,0xFDC8,0xFDC9,0xFDC9,0xFDE9,0xFE6C,0x10A2,0x39C4,0xFE4C,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFDC8,0xFDC8,0xFDA7,0xFDA8,0xFF16,0xF588,0xF544,0x6222,0x0000,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xA383,0xF524,0xF64E,0xFE4E,0xFD86,0xFD86,0xFD87,0xFDA7,0xFDA7,0xFDA8,0xFDC8,0xFDC8,0xFE2A,0xA469,0xB4EA,0xFE2A,0xFDC9,0xFDC8,0xFDC8,0xFDA8,0xFDA7,0xFDA7,0xFD87,0xFD86,0xFDEA,0xFED3,0xF524,0xC443,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x51C1,0xF504,0xF546,0xFF16,0xF565,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDA7,0xFDA7,0xFDE8,0xFE6A,0xFE4A,0xFDE8,0xFDA7,0xFDA7,0xFDA7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFEB2,0xF5CA,0xF504,0x8AE2,0x0000, // row 22, 736 pixels -0x0000,0xB3A2,0xED03,0xFE92,0xFDC9,0xF543,0xF544,0xFD44,0xFD65,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDC7,0xFDC7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFD65,0xFD44,0xF544,0xFD86,0xFEF5,0xED03,0xE4C3,0x1880, // row 23, 768 pixels -0x7241,0xECE3,0xF567,0xFED3,0xF523,0xF523,0xF523,0xF543,0xF544,0xF544,0xFD65,0xFD65,0xFD65,0xFD65,0xD4E6,0x39C5,0x39A5,0xD4E6,0xFD86,0xFD65,0xFD65,0xFD65,0xFD65,0xF544,0xF544,0xF543,0xF523,0xF523,0xFE2E,0xF5EC,0xECE3,0x9B42, // row 24, 800 pixels -0xD443,0xECE3,0xFED4,0xF565,0xF502,0xF502,0xF522,0xF523,0xF523,0xF543,0xF544,0xF544,0xF544,0xFD65,0x8B64,0x18C3,0x18C3,0x8344,0xFD85,0xFD44,0xF544,0xF544,0xF544,0xF543,0xF523,0xF523,0xF522,0xF502,0xF523,0xFEF5,0xED04,0xECE3, // row 25, 832 pixels -0xECC3,0xF5AB,0xFE6F,0xF501,0xF4E1,0xF501,0xF502,0xF502,0xF522,0xF522,0xF523,0xF523,0xF523,0xFD84,0xC504,0x20E1,0x18E1,0xC4E4,0xFD84,0xF543,0xF523,0xF523,0xF523,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xFDC9,0xF62F,0xECC3, // row 26, 864 pixels -0xECC2,0xFE92,0xF523,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF502,0xF502,0xF522,0xF522,0xF543,0xFDE3,0xFEA5,0xF6A4,0xFE04,0xF543,0xF522,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E1,0xFED4,0xECC2, // row 27, 896 pixels -0xECA2,0xF5EC,0xF4E0,0xF4C0,0xF4E0,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF501,0xF502,0xF502,0xF542,0xFDA2,0xFDA2,0xF542,0xF502,0xF502,0xF502,0xF501,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E0,0xF4E0,0xF4C0,0xF5A9,0xECA2, // row 28, 928 pixels -0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels -0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels -0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/160 x 128/Flash_Bitmap2/Close.h b/examples/160 x 128/Flash_Bitmap2/Close.h deleted file mode 100644 index c16d522..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Close.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t closeWidth = 32; -const uint16_t closeHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short close[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x58E3,0xC228,0xFC10,0xFD34,0xFE18,0xFE59,0xFE79,0xFE9A,0xFE9A,0xFE9A,0xFE9A,0xFE59,0xFD75,0xFC51,0xC28A,0x5904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2041,0x8945,0xF34D,0xFD34,0xFDB6,0xFD75,0xFD55,0xFD55,0xFD96,0xFDD7,0xFDF7,0xFDF7,0xFDB6,0xFDB6,0xFDD7,0xFDF7,0xFD75,0xF38E,0x8965,0x2041,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x4082,0xE208,0xF410,0xFD34,0xFC92,0xFBEF,0xFBAE,0xFBEF,0xFC71,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC92,0xFC51,0xFC71,0xFCF3,0xFD75,0xFC30,0xEA28,0x40A2,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x3861,0xE1E7,0xF451,0xFC92,0xFB4D,0xFA49,0xFA49,0xFAEB,0xFBAE,0xFC71,0xFD34,0xFDB6,0xFE18,0xFDB6,0xFD34,0xFC71,0xFBAE,0xFB0C,0xFAEB,0xFBAE,0xFCD3,0xFC71,0xE208,0x4082,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x1020,0xD986,0xF430,0xFC30,0xFA28,0xF924,0xF965,0xFA8A,0xFB0C,0xFBAE,0xFC51,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC51,0xFC71,0xFBEF,0xFA28,0xF9C7,0xFA8A,0xFC51,0xF430,0xD9A6,0x1020,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x78A2,0xEB6D,0xFC30,0xF9C7,0xF861,0xF8A2,0xFA08,0xFEDB,0xFD55,0xFB4D,0xFC10,0xFC92,0xFD14,0xFD34,0xFD14,0xFC92,0xFCB2,0xFF7D,0xFF7D,0xFB2C,0xF945,0xF8E3,0xF9E7,0xFC30,0xEB8E,0x78C3,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x3841,0xD9E7,0xF492,0xF208,0xF041,0xF800,0xF945,0xFE9A,0xFFFF,0xFFFF,0xFD75,0xFB8E,0xFC10,0xFC51,0xFC71,0xFC51,0xFCB2,0xFF7D,0xFFFF,0xFFFF,0xFF3C,0xFA8A,0xF882,0xF841,0xFA08,0xFC92,0xDA08,0x3841,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x88A2,0xEBCF,0xF2EB,0xF061,0xF000,0xF8E3,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD75,0xFB4D,0xFBAE,0xFBAE,0xFC71,0xFF7D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFEFB,0xFA28,0xF800,0xF061,0xF2EB,0xEBEF,0x90C3,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x2820,0xD1C7,0xF410,0xE945,0xE800,0xF000,0xFE9A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD34,0xFAEB,0xFBCF,0xFF5D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFF1C,0xF986,0xF000,0xF145,0xF410,0xD1E7,0x2820,0x0000, // row 10, 352 pixels -0x0000,0x6841,0xDB2C,0xEACB,0xE041,0xE800,0xF000,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD14,0xFF1C,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFBCF,0xF082,0xF000,0xE841,0xEACB,0xE34D,0x7061,0x0000, // row 11, 384 pixels -0x0000,0x9861,0xE3CF,0xE186,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE986,0xEBCF,0xA082,0x0000, // row 12, 416 pixels -0x0800,0xB8A2,0xE3AE,0xD8A2,0xD800,0xE000,0xE800,0xE800,0xF145,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE0A2,0xEBAE,0xC0C3,0x0800, // row 13, 448 pixels -0x1800,0xC124,0xE30C,0xD020,0xD800,0xE000,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD820,0xE30C,0xC124,0x1800, // row 14, 480 pixels -0x2800,0xC165,0xDAAA,0xC800,0xD000,0xD800,0xE000,0xE000,0xE800,0xE800,0xF124,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB6D,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xDAAA,0xC165,0x2800, // row 15, 512 pixels -0x2000,0xB924,0xD269,0xC800,0xD000,0xD000,0xD800,0xE000,0xE000,0xE800,0xE924,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF36D,0xE800,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xD000,0xDA69,0xC145,0x2800, // row 16, 544 pixels -0x1000,0xB0A2,0xD28A,0xC000,0xC800,0xD000,0xD000,0xD800,0xD800,0xE165,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF3AE,0xE000,0xE000,0xD800,0xD800,0xD000,0xD000,0xC800,0xD28A,0xB8C3,0x1000, // row 17, 576 pixels -0x0000,0xA800,0xD2AA,0xB800,0xC000,0xC800,0xC800,0xD000,0xD965,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBAE,0xD800,0xD800,0xD000,0xC800,0xC800,0xC000,0xD2AA,0xB020,0x0000, // row 18, 608 pixels -0x0000,0x8000,0xCA69,0xB841,0xB800,0xC000,0xC800,0xD186,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBCF,0xD000,0xC800,0xC800,0xC000,0xC041,0xCA69,0x8000,0x0000, // row 19, 640 pixels -0x0000,0x4800,0xC1C7,0xB8E3,0xB800,0xB800,0xC000,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBEF,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE410,0xC841,0xC000,0xB800,0xC0E3,0xC1C7,0x4800,0x0000, // row 20, 672 pixels -0x0000,0x1000,0xB061,0xC1E7,0xB000,0xB000,0xB800,0xD269,0xFFBE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xD000,0xD965,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xC020,0xB800,0xB000,0xC1E7,0xB061,0x1000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x6000,0xB9C7,0xB061,0xB000,0xB000,0xB800,0xCA49,0xFF9E,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xC800,0xC800,0xC800,0xD186,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xB800,0xB800,0xB000,0xB061,0xC1C7,0x6000,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x1800,0xB041,0xB986,0xA800,0xA800,0xB000,0xB000,0xCA49,0xFF7D,0xFFFF,0xDB8E,0xC000,0xC000,0xC000,0xC000,0xC000,0xC986,0xF6DB,0xFFFF,0xFFFF,0xD30C,0xB800,0xB000,0xB000,0xA800,0xB986,0xB041,0x1800,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x5800,0xB0E3,0xA8C3,0xA800,0xA800,0xA800,0xB000,0xCACB,0xD38E,0xB000,0xB800,0xB800,0xB800,0xB800,0xB800,0xB800,0xC145,0xF6DB,0xD34D,0xB000,0xB000,0xA800,0xA800,0xB0C3,0xB0E3,0x5800,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x6000,0xB124,0xA882,0xA000,0xA800,0xA800,0xA800,0xA800,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xA800,0xA800,0xA800,0xA800,0xA882,0xB124,0x6000,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB104,0xA882,0xA000,0xA000,0xA000,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA000,0xA000,0xA882,0xB104,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB0A2,0xA8C3,0xA020,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA020,0xA8C3,0xB0A2,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4800,0xA800,0xB0C3,0xA0A2,0x9800,0x9800,0x9800,0x9800,0xA000,0xA000,0xA000,0x9800,0x9800,0x9800,0xA082,0xB0E3,0xA800,0x4800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5800,0xA800,0xB0A2,0xA8E3,0xA0A2,0xA041,0x9800,0x9800,0xA041,0xA0A2,0xA8E3,0xB0A2,0xA800,0x5800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3000,0x6000,0x8800,0xA000,0xA800,0xA800,0xA000,0x8800,0x6000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino b/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino deleted file mode 100644 index 3cf517a..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino +++ /dev/null @@ -1,110 +0,0 @@ -// Code partly derived from ILI9341_Due library example - -// Draws the 3 icons across the middle of the screen and pauses. -// Then draws 300 icons at random locations, clears screen and repeats -// -// This demonstrates drawing icons from FLASH - -// Icons are stored in tabs, e.g. Alert.h etc -// more than one icon can be in a header file. - -// Original sketch header follow: -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - This sketch does not use/need any fonts at all... - - Arrays containing FLASH images can be created with UTFT library tool: - (libraries\UTFT\Tools\ImageConverter565.exe) - Convert to .c format then copy into a new tab - - The number and size of icons is limited by available FLASH memory. The icon array will - use width x height x 2 bytes of FLASH, i.e. 32 x 32 icon uses ~2048 bytes - -*/ -#include // Graphics and font library for ST7735 driver chip -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h - -// Include the header files that contain the icons -#include "alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.init(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, (tft.width() - infoWidth)/2 - 50, (tft.height() - infoHeight)/2, infoWidth, infoHeight); - drawIcon(alert, (tft.width() - alertWidth)/2, (tft.height() - alertHeight)/2, alertWidth, alertHeight); - drawIcon(close, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(4000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(close, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, int8_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setAddrWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/160 x 128/Flash_Bitmap2/Info.h b/examples/160 x 128/Flash_Bitmap2/Info.h deleted file mode 100644 index c4ee633..0000000 --- a/examples/160 x 128/Flash_Bitmap2/Info.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t infoWidth = 32; -const uint16_t infoHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short info[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0861,0x4A69,0x8C71,0xA514,0xBDF7,0xBDF7,0xA514,0x8C71,0x4A69,0x0861,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x39E7,0x9CF3,0xEF7D,0xF79E,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xF79E,0xEF7D,0x9CF3,0x39E7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2965,0x9492,0xF79E,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xF79E,0x9492,0x2965,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xD75F,0xB6BF,0x9E5F,0x963F,0x963F,0x9E5F,0xB6BF,0xD75F,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xEF7D,0xFFDF,0xFFFF,0xFFDF,0xBEDF,0x7DBF,0x7DBF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x7DBE,0xBEBF,0xFFDF,0xFFFF,0xFFDF,0xEF7D,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFFF,0xFFFF,0xE77F,0x7DBE,0x759E,0x759F,0x7DBF,0x7DDF,0x7DDF,0x85FF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x759E,0x6D7E,0x7DBE,0xDF7F,0xFFFF,0xFFFF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x31A6,0xEF5D,0xFFDF,0xFFFF,0xCF1E,0x6D7E,0x6D7E,0x759E,0x759F,0x7DBF,0x7DDF,0x8E1F,0xBEDF,0xC6FF,0x8DFF,0x75BF,0x759F,0x759E,0x6D7E,0x655E,0x655D,0xCF1E,0xFFFF,0xFFDF,0xEF5D,0x31A6,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x94B2,0xF7BE,0xFFFF,0xDF5E,0x655D,0x655D,0x6D7E,0x6D7E,0x759E,0x75BF,0x759F,0xEFBF,0xFFFF,0xFFFF,0xEFBF,0x759F,0x759E,0x6D7E,0x6D7E,0x655D,0x653D,0x653D,0xDF5E,0xFFFF,0xF7BE,0x94B2,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x4228,0xEF7D,0xFFFF,0xF7BF,0x6D5D,0x653D,0x655D,0x6D5E,0x6D7E,0x759E,0x759E,0x85DF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8DFE,0x6D7E,0x6D7E,0x6D5E,0x655D,0x653D,0x5D1D,0x6D5D,0xF7BF,0xFFFF,0xEF7D,0x4228,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0xA534,0xFFDF,0xFFDF,0xA65D,0x5D1D,0x5D1D,0x653D,0x655E,0x6D7E,0x6D7E,0x6D7E,0x651E,0xE77F,0xFFFF,0xFFFF,0xF7BF,0x5CFE,0x6D7E,0x6D7E,0x655E,0x653D,0x5D1D,0x5D1D,0x54FC,0xA65D,0xFFDF,0xFFDF,0xA534,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x18E3,0xEF5D,0xFFFF,0xEF9E,0x5CFC,0x54FC,0x5D1D,0x5D3D,0x653D,0x655E,0x6D7E,0x6D7E,0x653E,0x6D3E,0xB67E,0xBEBE,0x755E,0x5D1E,0x6D5E,0x655E,0x653D,0x5D3D,0x5D1D,0x54FC,0x54DC,0x54FC,0xEF9E,0xFFFF,0xEF5D,0x18E3,0x0000, // row 11, 384 pixels -0x0000,0x630C,0xEF7D,0xFFDF,0xB69D,0x54DC,0x54FC,0x5CFC,0x5D1D,0x653D,0x653D,0x655E,0x6D5E,0x655E,0x5CFE,0x4C9D,0x4C7D,0x54DD,0x653E,0x655E,0x653D,0x653D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0xB69D,0xFFDF,0xEF7D,0x630C,0x0000, // row 12, 416 pixels -0x0000,0x94B2,0xF7BE,0xFFDF,0x85BC,0x4CBC,0x54DC,0x54FC,0x5CFD,0x5D1D,0x5D3D,0x653D,0x655D,0x653D,0x85DE,0xC6FE,0xC6FE,0x85BE,0x653D,0x653D,0x5D3D,0x5D1D,0x5CFD,0x54FC,0x54DC,0x4CBC,0x4CBB,0x85BC,0xFFDF,0xF7BE,0x94B2,0x0000, // row 13, 448 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x651C,0x4CBB,0x4CBC,0x54DC,0x54FC,0x5CFC,0x5D1D,0x5D1D,0x653D,0x5D1D,0xE77E,0xFFDF,0xFFDF,0xEF9E,0x5CFD,0x5D1D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x651B,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 14, 480 pixels -0x0000,0xC638,0xFFDF,0xF7BE,0x54DB,0x449B,0x4CBB,0x4CBC,0x54DC,0x54FC,0x54FC,0x5D1D,0x5D1D,0x7D7D,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x7D7D,0x5CFD,0x54FC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x447B,0x54BB,0xF7BE,0xFFDF,0xC638,0x0000, // row 15, 512 pixels -0x0000,0xC638,0xFFDF,0xF79E,0x4CBB,0x449B,0x449B,0x4CBB,0x4CBC,0x54DC,0x54DC,0x54FC,0x54DC,0x753C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x753C,0x54DC,0x54DC,0x54DC,0x4CBC,0x4CBB,0x449B,0x449B,0x3C7B,0x4C9B,0xF79E,0xFFDF,0xC638,0x0000, // row 16, 544 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x5CFB,0x3C7B,0x447B,0x449B,0x4CBB,0x4CBC,0x4CBC,0x4CDC,0x4CBC,0x6D1C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x6CFC,0x4CBC,0x4CBC,0x4CBC,0x4CBB,0x449B,0x447B,0x3C7B,0x3C5A,0x54DB,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 17, 576 pixels -0x0000,0x94B2,0xF7BE,0xF7BE,0x755B,0x3C5A,0x3C7B,0x447B,0x449B,0x449B,0x4CBB,0x4CBB,0x4C9B,0x6CFB,0xF79E,0xF79E,0xF79E,0xF79E,0x64FB,0x449B,0x4CBB,0x449B,0x449B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x753B,0xF7BE,0xF7BE,0x9CD3,0x0000, // row 18, 608 pixels -0x0000,0x6B4D,0xEF7D,0xF7BE,0xA61C,0x3C5A,0x3C5A,0x3C7B,0x447B,0x447B,0x449B,0x449B,0x447B,0x64DB,0xF79E,0xF79E,0xF79E,0xF79E,0x64DB,0x447B,0x449B,0x447B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x343A,0xA61C,0xF7BE,0xEF7D,0x6B4D,0x0000, // row 19, 640 pixels -0x0000,0x2124,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x3C5A,0x3C5A,0x3C7B,0x3C7B,0x447B,0x3C5B,0x64BA,0xF79E,0xF79E,0xF79E,0xF79E,0x64BA,0x3C5B,0x3C7B,0x3C7B,0x3C5A,0x3C5A,0x343A,0x343A,0x343A,0xDF3D,0xFFDF,0xE71C,0x2124,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xAD75,0xF7BE,0xF79E,0x859B,0x343A,0x343A,0x345A,0x3C5A,0x3C5A,0x3C5A,0x3C5A,0x5C9A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x5C9A,0x3C3A,0x3C5A,0x3C5A,0x345A,0x343A,0x343A,0x341A,0x859B,0xF79E,0xF7BE,0xAD75,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x528A,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x343A,0x343A,0x343A,0x3C5A,0x343A,0x4C5A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x4C59,0x343A,0x343A,0x343A,0x343A,0x343A,0x341A,0x3C5A,0xDF3D,0xFFDF,0xE71C,0x528A,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x0000,0x9CD3,0xF79E,0xF7BE,0xBE7C,0x3419,0x341A,0x341A,0x343A,0x343A,0x341A,0x2B99,0xC69C,0xEF7D,0xEF7D,0xD6DC,0x2398,0x341A,0x343A,0x341A,0x341A,0x2C19,0x2C19,0xBE7C,0xF7BE,0xF79E,0x9CD3,0x0000,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x39E7,0xDEDB,0xFFDF,0xF79E,0x9DFB,0x2C19,0x2C19,0x2C1A,0x341A,0x341A,0x2BB9,0x2B57,0x6459,0x74B9,0x2337,0x2BB9,0x341A,0x2C1A,0x2C19,0x2C19,0x2C19,0x9DFB,0xF79E,0xFFDF,0xDEDB,0x39E7,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x632C,0xDEFB,0xFFDF,0xEF7D,0xB65C,0x3C39,0x2BF9,0x2C19,0x2C19,0x2BF9,0x2398,0x1B58,0x1B37,0x2398,0x2BF9,0x2C19,0x2BF9,0x2BF9,0x3439,0xB65C,0xEF7D,0xFFDF,0xDEFB,0x632C,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xDEFB,0xF7BE,0xF79E,0xDF1C,0x7D5A,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x23D9,0x23D9,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x7D5A,0xDF1C,0xF79E,0xF7BE,0xDEFB,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x632C,0xDEDB,0xF79E,0xFFDF,0xEF7D,0xD6FC,0x9DFB,0x5CDA,0x4C9A,0x3419,0x3419,0x4C9A,0x5CDA,0x9DFB,0xD6FC,0xEF7D,0xFFDF,0xF79E,0xDEDB,0x632C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x94B2,0xDEFB,0xF7BE,0xFFDF,0xF7BE,0xF79E,0xEF7D,0xEF5D,0xEF5D,0xEF7D,0xF79E,0xF7BE,0xFFDF,0xF7BE,0xDEFB,0x94B2,0x4208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x528A,0xA534,0xDEDB,0xE73C,0xF79E,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0xF79E,0xE73C,0xDEDB,0xA534,0x528A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x18C3,0x5AEB,0x8C71,0xAD55,0xBDD7,0xBDD7,0xAD55,0x8C71,0x5AEB,0x18C3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/160 x 128/Pong_v3/Pong_v3.ino b/examples/160 x 128/Pong_v3/Pong_v3.ino index 7c51299..318c851 100644 --- a/examples/160 x 128/Pong_v3/Pong_v3.ino +++ b/examples/160 x 128/Pong_v3/Pong_v3.ino @@ -107,13 +107,17 @@ void midline() { // If the ball is not on the line then don't redraw the line if ((ball_x dashline_x+dashline_w)) return; + tft.startWrite(); + // Quick way to draw a dashed line - tft.setAddrWindow(dashline_x,0,dashline_x+dashline_w-1,h); + tft.setAddrWindow(dashline_x, 0, dashline_w, h); for(int16_t i = 0; i < dashline_n; i+=2) { tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels } + + tft.endWrite(); } void lpaddle() { diff --git a/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino b/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino new file mode 100644 index 0000000..313a2f6 --- /dev/null +++ b/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino @@ -0,0 +1,191 @@ +/*==================================================================================== + This sketch contains support functions to render the Jpeg images. + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +// Return the minimum of two values a and b +#define minimum(a,b) (((a) < (b)) ? (a) : (b)) + +//==================================================================================== +// Opens the image file and prime the Jpeg decoder +//==================================================================================== +void drawJpeg(const char *filename, int xpos, int ypos) { + + Serial.println("==========================="); + Serial.print("Drawing file: "); Serial.println(filename); + Serial.println("==========================="); + + // Open the named file (the Jpeg decoder library will close it after rendering image) + fs::File jpegFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS + // File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library + + if ( !jpegFile ) { + Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); + return; + } + + // Use one of the three following methods to initialise the decoder: + //boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder, + //boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder, + boolean decoded = JpegDec.decodeFsFile(filename); // or pass the filename (leading / distinguishes SPIFFS files) + // Note: the filename can be a String or character array type + if (decoded) { + // print information about the image to the serial port + jpegInfo(); + + // render the image onto the screen at given coordinates + jpegRender(xpos, ypos); + } + else { + Serial.println("Jpeg file format not supported!"); + } +} + +//==================================================================================== +// Decode and render the Jpeg image onto the TFT screen +//==================================================================================== +void jpegRender(int xpos, int ypos) { + + // retrieve infomration about the image + uint16_t *pImg; + uint16_t mcu_w = JpegDec.MCUWidth; + uint16_t mcu_h = JpegDec.MCUHeight; + uint32_t max_x = JpegDec.width; + uint32_t max_y = JpegDec.height; + + // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) + // Typically these MCUs are 16x16 pixel blocks + // Determine the width and height of the right and bottom edge image blocks + uint32_t min_w = minimum(mcu_w, max_x % mcu_w); + uint32_t min_h = minimum(mcu_h, max_y % mcu_h); + + // save the current image block size + uint32_t win_w = mcu_w; + uint32_t win_h = mcu_h; + + // record the current time so we can measure how long it takes to draw an image + uint32_t drawTime = millis(); + + // save the coordinate of the right and bottom edges to assist image cropping + // to the screen size + max_x += xpos; + max_y += ypos; + + // read each MCU block until there are no more + while ( JpegDec.readSwappedBytes()) { // Swap byte order so the SPI buffer can be used + + // save a pointer to the image block + pImg = JpegDec.pImage; + + // calculate where the image block should be drawn on the screen + int mcu_x = JpegDec.MCUx * mcu_w + xpos; // Calculate coordinates of top left corner of current MCU + int mcu_y = JpegDec.MCUy * mcu_h + ypos; + + // check if the image block size needs to be changed for the right edge + if (mcu_x + mcu_w <= max_x) win_w = mcu_w; + else win_w = min_w; + + // check if the image block size needs to be changed for the bottom edge + if (mcu_y + mcu_h <= max_y) win_h = mcu_h; + else win_h = min_h; + + // copy pixels into a contiguous block + if (win_w != mcu_w) + { + uint16_t *cImg; + int p = 0; + cImg = pImg + win_w; + for (int h = 1; h < win_h; h++) + { + p += mcu_w; + for (int w = 0; w < win_w; w++) + { + *cImg = *(pImg + w + p); + cImg++; + } + } + } + + // draw image MCU block only if it will fit on the screen + if ( ( mcu_x + win_w) <= tft.width() && ( mcu_y + win_h) <= tft.height()) + { + tft.pushRect(mcu_x, mcu_y, win_w, win_h, pImg); + } + + else if ( ( mcu_y + win_h) >= tft.height()) JpegDec.abort(); + + } + + // calculate how long it took to draw the image + drawTime = millis() - drawTime; // Calculate the time it took + + // print the results to the serial port + Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms"); + Serial.println("====================================="); + +} + +//==================================================================================== +// Print information decoded from the Jpeg image +//==================================================================================== +void jpegInfo() { + + Serial.println("==============="); + Serial.println("JPEG image info"); + Serial.println("==============="); + Serial.print ("Width :"); Serial.println(JpegDec.width); + Serial.print ("Height :"); Serial.println(JpegDec.height); + Serial.print ("Components :"); Serial.println(JpegDec.comps); + Serial.print ("MCU / row :"); Serial.println(JpegDec.MCUSPerRow); + Serial.print ("MCU / col :"); Serial.println(JpegDec.MCUSPerCol); + Serial.print ("Scan type :"); Serial.println(JpegDec.scanType); + Serial.print ("MCU width :"); Serial.println(JpegDec.MCUWidth); + Serial.print ("MCU height :"); Serial.println(JpegDec.MCUHeight); + Serial.println("==============="); + Serial.println(""); +} + +//==================================================================================== +// Open a Jpeg file and send it to the Serial port in a C array compatible format +//==================================================================================== +void createArray(const char *filename) { + + // Open the named file + fs::File jpgFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS + // File jpgFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library + + if ( !jpgFile ) { + Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); + return; + } + + uint8_t data; + byte line_len = 0; + Serial.println(""); + Serial.println("// Generated by a JPEGDecoder library example sketch:"); + Serial.println("// https://github.com/Bodmer/JPEGDecoder"); + Serial.println(""); + Serial.println("#include "); + Serial.println("// Remove leading / from array name!"); + Serial.print ("const uint8_t "); + while (*filename != '.') Serial.print(*filename++); + Serial.println("[] PROGMEM = {"); // PROGMEM added for AVR processors, it is ignored by Due + + while ( jpgFile.available()) { + + data = jpgFile.read(); + Serial.print("0x"); if (abs(data) < 16) Serial.print("0"); + Serial.print(data, HEX); Serial.print(",");// Add value and comma + line_len++; + if ( line_len >= 32) { + line_len = 0; + Serial.println(); + } + + } + + Serial.println("};\r\n"); + jpgFile.close(); +} +//==================================================================================== diff --git a/examples/320 x 240/weather-station-v8/SPIFFS_Support.ino b/examples/160 x 128/TFT_SPIFFS_Jpeg/SPIFFS_functions.ino similarity index 83% rename from examples/320 x 240/weather-station-v8/SPIFFS_Support.ino rename to examples/160 x 128/TFT_SPIFFS_Jpeg/SPIFFS_functions.ino index 37eefe1..a0f8225 100644 --- a/examples/320 x 240/weather-station-v8/SPIFFS_Support.ino +++ b/examples/160 x 128/TFT_SPIFFS_Jpeg/SPIFFS_functions.ino @@ -14,8 +14,7 @@ void listFiles(void) { fs::Dir dir = SPIFFS.openDir("/"); // Root directory String line = "====================================="; - uint32_t totalBytes = 0; - + Serial.println(line); Serial.println(" File name Size"); Serial.println(line); @@ -27,13 +26,8 @@ void listFiles(void) { while (spaces--) Serial.print(" "); fs::File f = dir.openFile("r"); Serial.print(f.size()); Serial.println(" bytes"); - totalBytes += f.size(); } - Serial.println(); Serial.print("Total = "); - int spaces = 25 - 8; // Tabulate nicely - while (spaces--) Serial.print(" "); - Serial.print(totalBytes); Serial.println(" bytes"); - + Serial.println(line); Serial.println(); delay(1000); diff --git a/examples/160 x 128/TFT_SPIFFS_Jpeg/TFT_SPIFFS_Jpeg.ino b/examples/160 x 128/TFT_SPIFFS_Jpeg/TFT_SPIFFS_Jpeg.ino new file mode 100644 index 0000000..f500a47 --- /dev/null +++ b/examples/160 x 128/TFT_SPIFFS_Jpeg/TFT_SPIFFS_Jpeg.ino @@ -0,0 +1,129 @@ +/*==================================================================================== + + This sketch demonstrates loading images which have been stored as files in the + built-in FLASH memory on a NodeMCU 1.0 (ESP8266 based, ESP-12E Module) rendering the + images onto a 160 x 128 pixel TFT screen. + + The images are stored in the SPI FLASH Filing System (SPIFFS), which effectively + functions like a tiny "hard drive". This filing system is built into the ESP8266 + Core that can be loaded from the IDE "Boards manager" menu option. This is at + version 2.3.0 at the time of sketch creation. + + The size of the SPIFFS partition can be set in the IDE as 1Mbyte or 3Mbytes. Either + will work with this sketch. Typically most sketches easily fit within 1 Mbyte so a + 3 Mbyte SPIFS partition can be used, in which case it can contain 100's of Jpeg + full screem images. + + The Jpeg library can be found here: + https://github.com/Bodmer/JPEGDecoder + + Images in the Jpeg format can be created using Paint or IrfanView or other picture + editting software. + + Place the images inside the sketch folder, in a folder called "Data". Then upload + all the files in the folder using the Arduino IDE "ESP8266 Sketch Data Upload" option + in the "Tools" menu: + http://www.esp8266.com/viewtopic.php?f=32&t=10081 + https://github.com/esp8266/arduino-esp8266fs-plugin/releases + + This takes some time, but the SPIFFS content is not altered when a new sketch is + uploaded, so there is no need to upload the same files again! + Note: If open, you must close the "Serial Monitor" window to upload data to SPIFFS! + + The IDE will not copy the "data" folder with the sketch if you save the sketch under + another name. It is necessary to manually make a copy and place it in the sketch + folder. + + This sketch includes example images in the Data folder. + + Saving images, uploading and rendering on the TFT screen couldn't be much easier! + + Created by Bodmer 24th Jan 2017 - Tested in Arduino IDE 1.8.0 esp8266 Core 2.3.0 + ==================================================================================*/ + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the SPIFFS FLASH filing system this is part of the ESP Core +#define FS_NO_GLOBALS +#include + +// JPEG decoder library +#include + +// SPI library, built into IDE +#include + +// Call up the TFT library +#include // Hardware-specific library for ESP8266 +// The TFT control pins are set in the User_Setup.h file <<<<<<<<<<<<<<<<< NOTE! +// that can be found in the "src" folder of the library + +// Invoke TFT library +TFT_eSPI tft = TFT_eSPI(); + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(250000); // Used for messages and the C array generator + + delay(10); + Serial.println("NodeMCU decoder test!"); + + tft.begin(); + tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape + tft.fillScreen(TFT_BLACK); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nInitialisation done."); + listFiles(); // Lists the files so you can see what is in the SPIFFS + +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + // Note the / before the SPIFFS file name must be present, this means the file is in + // the root directory of the SPIFFS, e.g. "/Tiger.jpg" for a file called "Tiger.jpg" + + tft.setRotation(0); // portrait + tft.fillScreen(random(0xFFFF)); + + drawJpeg("/EagleEye160.jpg", 0, 16); + delay(2000); + + tft.fillScreen(random(0xFFFF)); + drawJpeg("/tiger160.jpg", 4, 0); + delay(2000); + + tft.setRotation(1); // landscape + //tft.fillScreen(random(0xFFFF)); + drawJpeg("/arduino160.jpg", 0, 0); + delay(2000); + + tft.fillScreen(TFT_BLACK); + drawJpeg("/Baboon160.jpg", 0, 4); + delay(2000); + + tft.fillScreen(random(0xFFFF)); + drawJpeg("/Mouse160.jpg", 0, 11); + delay(2000); + + // Create arrays from the jpeg images and send them to the serial port for copy and + // pasting into a sketch (used to make arrays fot the TFT_FLASH_Jpeg sketch) + + //createArray("/EagleEye160.jpg"); + //createArray("/tiger160.jpg"); + //createArray("/Baboon160.jpg"); + //createArray("/Mouse160.jpg"); + //while(1) yield(); // Stay here +} +//==================================================================================== + diff --git a/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino b/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino new file mode 100644 index 0000000..7179945 --- /dev/null +++ b/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino @@ -0,0 +1,212 @@ +// Sketch to display images on a 160 x 128 TFT + +// Renders images stored in an array in program (FLASH) +// The JPEG images are stored in header files (see jpeg1.h etc) + +// As well as the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI +// the sketch needs the JPEG Decoder library. This can be loaded via the Library Manager. +// or can be downloaded here: +// https://github.com/Bodmer/JPEGDecoder + +//---------------------------------------------------------------------------------------------------- + +#include +#include + +TFT_eSPI tft = TFT_eSPI(); + + +// JPEG decoder library +#include + +// Return the minimum of two values a and b +#define minimum(a,b) (((a) < (b)) ? (a) : (b)) + +// Include the sketch header file that contains the image stored as an array of bytes +// More than one image array could be stored in each header file. +#include "jpeg1.h" +#include "jpeg2.h" +#include "jpeg3.h" +#include "jpeg4.h" + +// Count how many times the image is drawn for test purposes +uint32_t icount = 0; +//---------------------------------------------------------------------------------------------------- + + +//#################################################################################################### +// Setup +//#################################################################################################### +void setup() { + Serial.begin(115200); + tft.begin(); +} + +//#################################################################################################### +// Main loop +//#################################################################################################### +void loop() { + + tft.setRotation(0); // portrait + tft.fillScreen(TFT_BLACK); + + drawArrayJpeg(EagleEye, sizeof(EagleEye), 0, 16); // Draw a jpeg image stored in memory at x,y + delay(2000); + + tft.setRotation(0); // portrait + tft.fillScreen(TFT_BLACK); + drawArrayJpeg(Tiger, sizeof(Tiger), 4, 0); // Draw a jpeg image stored in memory + delay(2000); + + tft.setRotation(1); // landscape + tft.fillScreen(TFT_BLACK); + drawArrayJpeg(Baboon, sizeof(Baboon), 0, 4); // Draw a jpeg image stored in memory + delay(2000); + + tft.setRotation(1); // landscape + tft.fillScreen(TFT_BLACK); + drawArrayJpeg(Mouse160, sizeof(Mouse160), 0, 11); // Draw a jpeg image stored in memory + + delay(2000); +} + +//#################################################################################################### +// Draw a JPEG on the TFT pulled from a program memory array +//#################################################################################################### +void drawArrayJpeg(const uint8_t arrayname[], uint32_t array_size, int xpos, int ypos) { + + int x = xpos; + int y = ypos; + + JpegDec.decodeArray(arrayname, array_size); + + jpegInfo(); // Print information from the JPEG file (could comment this line out) + + renderJPEG(x, y); + + Serial.println("#########################"); +} + +//#################################################################################################### +// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit +//#################################################################################################### +// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not +// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. +void renderJPEG(int xpos, int ypos) { + + // retrieve infomration about the image + uint16_t *pImg; + uint16_t mcu_w = JpegDec.MCUWidth; + uint16_t mcu_h = JpegDec.MCUHeight; + uint32_t max_x = JpegDec.width; + uint32_t max_y = JpegDec.height; + + // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) + // Typically these MCUs are 16x16 pixel blocks + // Determine the width and height of the right and bottom edge image blocks + uint32_t min_w = minimum(mcu_w, max_x % mcu_w); + uint32_t min_h = minimum(mcu_h, max_y % mcu_h); + + // save the current image block size + uint32_t win_w = mcu_w; + uint32_t win_h = mcu_h; + + // record the current time so we can measure how long it takes to draw an image + uint32_t drawTime = millis(); + + // save the coordinate of the right and bottom edges to assist image cropping + // to the screen size + max_x += xpos; + max_y += ypos; + + // read each MCU block until there are no more + while (JpegDec.readSwappedBytes()) { + + // save a pointer to the image block + pImg = JpegDec.pImage ; + + // calculate where the image block should be drawn on the screen + int mcu_x = JpegDec.MCUx * mcu_w + xpos; // Calculate coordinates of top left corner of current MCU + int mcu_y = JpegDec.MCUy * mcu_h + ypos; + + // check if the image block size needs to be changed for the right edge + if (mcu_x + mcu_w <= max_x) win_w = mcu_w; + else win_w = min_w; + + // check if the image block size needs to be changed for the bottom edge + if (mcu_y + mcu_h <= max_y) win_h = mcu_h; + else win_h = min_h; + + // copy pixels into a contiguous block + if (win_w != mcu_w) + { + uint16_t *cImg; + int p = 0; + cImg = pImg + win_w; + for (int h = 1; h < win_h; h++) + { + p += mcu_w; + for (int w = 0; w < win_w; w++) + { + *cImg = *(pImg + w + p); + cImg++; + } + } + } + + // draw image MCU block only if it will fit on the screen + if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height()) + { + tft.pushRect(mcu_x, mcu_y, win_w, win_h, pImg); + } + else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding + } + + // calculate how long it took to draw the image + drawTime = millis() - drawTime; + + // print the results to the serial port + Serial.print(F( "Total render time was : ")); Serial.print(drawTime); Serial.println(F(" ms")); + Serial.println(F("")); +} + +//#################################################################################################### +// Print image information to the serial port (optional) +//#################################################################################################### +void jpegInfo() { + Serial.println(F("===============")); + Serial.println(F("JPEG image info")); + Serial.println(F("===============")); + Serial.print(F( "Width :")); Serial.println(JpegDec.width); + Serial.print(F( "Height :")); Serial.println(JpegDec.height); + Serial.print(F( "Components :")); Serial.println(JpegDec.comps); + Serial.print(F( "MCU / row :")); Serial.println(JpegDec.MCUSPerRow); + Serial.print(F( "MCU / col :")); Serial.println(JpegDec.MCUSPerCol); + Serial.print(F( "Scan type :")); Serial.println(JpegDec.scanType); + Serial.print(F( "MCU width :")); Serial.println(JpegDec.MCUWidth); + Serial.print(F( "MCU height :")); Serial.println(JpegDec.MCUHeight); + Serial.println(F("===============")); +} + +//#################################################################################################### +// Show the execution time (optional) +//#################################################################################################### +// WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for +// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries. + +// The Due will work fine with the HX8357_Due library. + +void showTime(uint32_t msTime) { + //tft.setCursor(0, 0); + //tft.setTextFont(1); + //tft.setTextSize(2); + //tft.setTextColor(TFT_WHITE, TFT_BLACK); + //tft.print(F(" JPEG drawn in ")); + //tft.print(msTime); + //tft.println(F(" ms ")); + Serial.print(F(" JPEG drawn in ")); + Serial.print(msTime); + Serial.println(F(" ms ")); +} + diff --git a/examples/160 x 128/TFT_flash_jpg/jpeg1.h b/examples/160 x 128/TFT_flash_jpg/jpeg1.h new file mode 100644 index 0000000..66920f9 --- /dev/null +++ b/examples/160 x 128/TFT_flash_jpg/jpeg1.h @@ -0,0 +1,212 @@ +// We need this header file to use FLASH as storage with PROGMEM directive +#include + +const uint8_t EagleEye[] PROGMEM = { +0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0xB4,0x00,0xB4,0x00,0x00,0xFF,0xDB,0x00,0x43,0x00,0x04,0x03,0x03,0x03,0x03,0x02,0x04, +0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x06,0x0A,0x06,0x06,0x05,0x05,0x06,0x0C,0x08,0x09,0x07,0x0A,0x0E,0x0C,0x0F,0x0E,0x0E,0x0C,0x0D,0x0D,0x0F,0x11,0x16,0x13,0x0F, +0x10,0x15,0x11,0x0D,0x0D,0x13,0x1A,0x13,0x15,0x17,0x18,0x19,0x19,0x19,0x0F,0x12,0x1B,0x1D,0x1B,0x18,0x1D,0x16,0x18,0x19,0x18,0xFF,0xDB,0x00,0x43,0x01,0x04,0x04, +0x04,0x06,0x05,0x06,0x0B,0x06,0x06,0x0B,0x18,0x10,0x0D,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xC0, +0x00,0x11,0x08,0x00,0x80,0x00,0x80,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xFF,0xC4,0x00,0x1D,0x00,0x00,0x03,0x01,0x00,0x03,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x07,0x04,0x02,0x03,0x08,0x01,0x09,0x00,0xFF,0xC4,0x00,0x3F,0x10,0x00,0x02,0x01,0x02,0x04,0x03,0x06,0x05,0x01,0x05,0x07, +0x03,0x05,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x11,0x00,0x05,0x12,0x21,0x06,0x31,0x41,0x13,0x14,0x22,0x51,0x61,0x71,0x07,0x32,0x81,0x91,0xA1,0xB1,0x23,0x42,0xC1, +0xD1,0xF0,0x15,0x24,0x25,0x33,0x52,0x62,0x72,0x08,0x34,0x92,0x16,0x43,0x53,0xA2,0xE1,0xFF,0xC4,0x00,0x1A,0x01,0x00,0x02,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x03,0x00,0x01,0x04,0x05,0x06,0xFF,0xC4,0x00,0x28,0x11,0x00,0x02,0x02,0x01,0x04,0x01,0x04,0x01,0x05,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x01,0x02,0x00,0x11,0x03,0x04,0x12,0x21,0x31,0x13,0x05,0x22,0x32,0x41,0x51,0x14,0x15,0x61,0x71,0x81,0x91,0xFF,0xDA,0x00,0x0C,0x03,0x01,0x00,0x02,0x11, +0x03,0x11,0x00,0x3F,0x00,0x6C,0x4C,0xFE,0x4C,0xAB,0x2B,0x4A,0x65,0xB5,0x2B,0x01,0x74,0x58,0x90,0x24,0x30,0x13,0x6D,0xEC,0x3F,0x7B,0xD7,0x9E,0x34,0x53,0xE7,0x51, +0x8D,0x15,0x11,0x42,0xD3,0x4A,0xA7,0x50,0x91,0x9F,0x48,0x66,0xF3,0x37,0xDC,0x9F,0xA7,0xDB,0x13,0xFC,0xE3,0x3D,0xA0,0xAC,0xCC,0x84,0x39,0x74,0x46,0x34,0x43,0x76, +0x9A,0x49,0x0B,0x28,0x3E,0xE4,0x0B,0xFD,0x00,0xF7,0x38,0x6B,0xE1,0x9C,0xF3,0x86,0x29,0x20,0x66,0xAB,0xA4,0x7A,0xD9,0x2C,0x2F,0x34,0xB2,0x68,0x43,0x6F,0xF7,0x58, +0x9B,0x7A,0x2E,0x38,0xAE,0x8C,0x00,0x27,0xB9,0xE8,0x43,0x83,0xF1,0x8C,0x73,0x71,0xB5,0x5E,0x59,0x46,0x8F,0x57,0x2B,0xB9,0x67,0x2B,0xD8,0xC7,0xE1,0xD4,0x4E,0xFC, +0xB9,0x91,0xEA,0xD8,0x16,0x2B,0xF3,0xEE,0x28,0xAA,0x4E,0xF3,0x53,0xDD,0x29,0x57,0x60,0x01,0x0A,0xAA,0x3F,0x4C,0x0B,0xAA,0xCD,0x78,0x4E,0x59,0x5E,0x70,0x89,0x08, +0x0D,0x71,0x69,0x1D,0x8F,0x3E,0x40,0xB3,0x1D,0xBD,0x80,0xC6,0xCA,0x0C,0xDE,0x3A,0x97,0x58,0xF2,0xAC,0xBA,0x5A,0x89,0x01,0xBA,0xEA,0x21,0x45,0xFA,0x1F,0x15,0xB0, +0x46,0xEB,0x88,0x3C,0x5D,0xCA,0x77,0x08,0xC1,0x96,0xE5,0x71,0xDB,0x2D,0x53,0x99,0x56,0x1E,0x73,0xB8,0x2B,0x1A,0x1E,0x5F,0x31,0xDD,0xBA,0xF2,0xBF,0x2E,0x78,0x25, +0x9B,0xE7,0xD9,0x95,0x04,0xD2,0x45,0x51,0x53,0x1B,0x80,0x36,0x85,0x06,0x94,0x3E,0x44,0x8F,0xE7,0x7C,0x22,0xC3,0x98,0x71,0x7D,0x2C,0x5A,0xCF,0x78,0x90,0x91,0xA7, +0xB1,0xA0,0x84,0x39,0xFF,0x00,0xC8,0x9E,0x9E,0x98,0x5C,0xAE,0xE2,0x5A,0xE3,0x9C,0x32,0x54,0x43,0x1D,0x35,0x41,0xF9,0x9A,0xA9,0x8C,0x92,0xDB,0xD5,0x4D,0xBF,0x8E, +0x23,0x29,0x65,0xAB,0x90,0x28,0xBB,0x8F,0xA2,0xBA,0xA3,0x36,0x74,0x7A,0xFE,0xED,0x28,0x53,0xE0,0x1F,0x30,0x51,0xE9,0x7B,0x5B,0xEF,0x86,0x38,0x33,0x7C,0xAF,0x26, +0xA4,0x12,0x54,0xB8,0x43,0x7D,0xA3,0x45,0x63,0xF8,0x17,0xFD,0x31,0x32,0xCB,0x12,0x7A,0xA9,0xE3,0xED,0xE6,0xCD,0x24,0x57,0x5D,0x43,0xB0,0x8C,0x42,0xBF,0xC3,0x0D, +0xB1,0x65,0x19,0x3C,0x22,0x36,0x58,0xC0,0x95,0xB9,0x34,0xB5,0x57,0x72,0x3D,0xB4,0x9B,0xF3,0xF3,0xC6,0x73,0x8C,0x77,0x77,0x1F,0xB8,0x9E,0x2A,0x30,0xBF,0x1B,0x65, +0x95,0xF2,0x68,0x8B,0x2E,0xA9,0xA9,0x07,0xE5,0x09,0x12,0xED,0xEA,0x4B,0x72,0xFB,0x1C,0x74,0xD7,0xAA,0x66,0x8C,0xAD,0x0F,0x0E,0x18,0x85,0xB7,0x33,0x4C,0x01,0xF5, +0xE5,0xB7,0xF5,0xB6,0x08,0x65,0xD4,0x70,0x50,0x46,0xB2,0x99,0x69,0x5A,0xE2,0xDD,0x98,0x4B,0x11,0xEB,0x72,0x6D,0xF8,0xC0,0x3E,0x2E,0xCF,0xF8,0x96,0x29,0x0C,0x79, +0x5E,0x4F,0x2C,0xF1,0xA7,0x36,0xA7,0xF1,0x93,0xCB,0xA5,0xBF,0x43,0xE7,0x82,0xC6,0x87,0x20,0xA6,0x13,0x3E,0x43,0xB5,0xB8,0x87,0x68,0xF8,0x46,0x86,0x37,0xED,0x99, +0xE1,0xA6,0x52,0x05,0x83,0x48,0xD2,0x8F,0xD4,0x5B,0x04,0x64,0xAF,0xCA,0x28,0xA1,0xEC,0x19,0xA9,0xE7,0xD3,0x71,0xFB,0x32,0x14,0x7B,0xD9,0xAE,0x3F,0x18,0x90,0xD3, +0xF1,0x07,0x12,0x55,0x32,0xC3,0x36,0x4B,0x99,0x87,0xE4,0x5A,0x65,0x65,0x00,0x7E,0x76,0xC1,0x24,0xCB,0xEB,0xEA,0xC7,0x69,0xA2,0x9A,0x26,0x03,0x70,0xDA,0x98,0xAE, +0xDB,0x78,0x74,0x8C,0x3B,0xC7,0x8D,0x20,0x16,0x66,0xEC,0xC7,0xF7,0xCC,0x32,0xAA,0x98,0x13,0xB2,0x9F,0xBB,0x9B,0xEC,0x4C,0xAB,0x6F,0xB0,0x00,0x63,0x1B,0x45,0x54, +0x6A,0xC2,0xD1,0x66,0x54,0x73,0x5B,0x61,0x78,0xF5,0x7E,0x16,0xC4,0xE1,0x6B,0x2E,0xA7,0xAA,0xE4,0x66,0x85,0x82,0x90,0x35,0x0A,0x57,0x52,0x3E,0xAC,0x45,0xF1,0x40, +0xE1,0xBC,0xB2,0xA9,0xA4,0xED,0x66,0xAB,0x6E,0x7F,0x2C,0x8D,0x1A,0xED,0xE9,0xCC,0x81,0x84,0xDA,0xB9,0xDA,0x3B,0x8C,0x2A,0x71,0x8B,0x33,0xEE,0x55,0x3F,0x11,0x51, +0x80,0xC6,0x92,0x9A,0x7B,0xF5,0x55,0x74,0xFB,0x82,0x76,0xC3,0x1B,0x4F,0x57,0x55,0x02,0x3E,0x61,0x45,0xDD,0x5C,0x7F,0xF1,0xB9,0x03,0xF4,0xC1,0x25,0x80,0x0A,0x62, +0xAC,0xE2,0xE3,0x90,0x49,0x2E,0x48,0xFC,0x60,0x64,0xF4,0xF4,0x82,0x76,0x92,0xA6,0xB0,0xA5,0x8E,0xA1,0xAD,0x98,0xFE,0x3F,0x96,0x36,0x10,0x55,0x6A,0x63,0x2E,0x1D, +0xAE,0x7E,0x7D,0x51,0xD3,0xB4,0xD6,0x73,0x3A,0xA2,0xAA,0x8B,0xEA,0x60,0xA1,0x47,0x4F,0x7C,0x74,0xD5,0xF6,0xB3,0x59,0x1E,0xAE,0x48,0x69,0xD7,0x90,0x06,0xDA,0xCD, +0xF9,0x91,0x84,0x61,0x98,0x66,0x51,0x47,0xFE,0x61,0x13,0x11,0xB1,0x3F,0x2C,0x6B,0xE6,0x3D,0x7D,0x71,0xB3,0x2D,0xCC,0xEA,0xAA,0x67,0x58,0xA9,0xEA,0x43,0x48,0xA7, +0x79,0x0B,0x02,0x47,0xFC,0x6F,0xD7,0x0C,0x08,0x3B,0x26,0x5A,0xBD,0xFB,0x40,0x8D,0x75,0x93,0xCB,0x96,0x4B,0x1B,0xB4,0x33,0x3A,0xBF,0xCA,0xEE,0xA4,0x29,0xFA,0x9C, +0x14,0xCB,0xF8,0xD4,0xE5,0xCD,0x18,0x92,0x46,0x0D,0x20,0xF9,0x23,0x3A,0x40,0xFE,0x38,0x51,0xAF,0x6C,0xC2,0xB2,0xAF,0xFC,0x63,0x32,0x96,0x8E,0x25,0x5F,0xD9,0x40, +0xCD,0xDA,0xC8,0xC7,0xD8,0x72,0xBE,0x30,0x35,0x05,0x5C,0x68,0xD3,0x35,0x35,0x5C,0x3B,0x17,0x43,0xD9,0x30,0x24,0x0F,0x32,0x05,0xC7,0xBE,0x2F,0xD8,0xDC,0x42,0xDC, +0x54,0xCB,0x1D,0x07,0x19,0x33,0x09,0x0A,0xD3,0x42,0x74,0x8D,0x5A,0xAA,0x5D,0xA4,0x22,0xDB,0xEC,0x09,0xFE,0xAF,0x8E,0xEA,0x4E,0x31,0xCB,0x2B,0xA6,0x96,0xB3,0x30, +0xA6,0x7A,0x7D,0x3E,0x18,0xE4,0x89,0x82,0xDC,0xF2,0x1E,0x1D,0x0D,0xF6,0xBE,0x22,0x19,0x6D,0x5D,0x29,0xAB,0x59,0x59,0x65,0xED,0x6E,0x3C,0x08,0xAD,0xEF,0xBD,0xAE, +0x6F,0xF7,0xC3,0x6D,0x33,0xD0,0xD4,0x65,0x8D,0x98,0x4B,0x9B,0xA2,0x44,0xAD,0x74,0x11,0xC7,0xA9,0xD1,0xB9,0xE9,0x3A,0xD6,0xE0,0xFA,0x83,0x84,0x38,0x17,0x40,0x43, +0x5C,0x97,0xF7,0x1E,0x33,0x5F,0x88,0xD9,0x9E,0x52,0xE2,0x28,0x29,0xE6,0x70,0xC4,0x30,0xED,0xA5,0xB1,0xD2,0x7F,0xDA,0x1B,0x9F,0xD0,0x60,0x52,0xF1,0xF5,0x45,0x4D, +0x72,0xB4,0x94,0x72,0x76,0x8D,0xF3,0x33,0x35,0xC1,0xFF,0x00,0xEB,0x8E,0xBC,0xA3,0x84,0x32,0x1C,0xFF,0x00,0x34,0x12,0xE6,0x39,0xAC,0xBA,0x19,0x75,0x42,0xF3,0x96, +0x0D,0x25,0xC1,0xF0,0x8E,0x45,0x8D,0xF6,0xD9,0x85,0xB0,0x53,0x87,0xFE,0x12,0x66,0xF2,0xD0,0x87,0xAF,0xA8,0x31,0x33,0xC8,0x58,0xA3,0xF6,0xEA,0xF1,0xA0,0xF9,0x5E, +0xF7,0xD3,0xE2,0x07,0xCC,0xE2,0x0C,0xB8,0xD5,0x68,0xC0,0x39,0x0D,0xF7,0x0B,0x1E,0x3B,0xA3,0xA4,0xA6,0x88,0xD4,0x45,0x40,0x8D,0x6B,0x18,0x96,0x7B,0xCB,0x6F,0x3D, +0x27,0x97,0xDB,0x02,0xF8,0x83,0x8E,0xA4,0xAE,0x30,0xC2,0xCE,0xBD,0xD9,0xFC,0x49,0xFD,0xDB,0x5E,0xA1,0xD0,0x8F,0x5E,0x9B,0x61,0xB3,0x3A,0xF8,0x6D,0xC3,0x51,0xF0, +0xAF,0x7C,0xCF,0xA5,0xA7,0xA4,0x68,0x63,0x11,0xB1,0x39,0x99,0x9C,0x97,0x0D,0xE2,0x6B,0x6C,0xA3,0x62,0x06,0xDB,0x6D,0x89,0xFD,0x63,0x7C,0x2B,0xA3,0xA2,0x96,0x0A, +0x4C,0xF5,0x83,0xB4,0x80,0x04,0x17,0x7F,0x08,0xBE,0xE0,0xA9,0x21,0x6D,0xB7,0x53,0x7C,0x2C,0xE7,0x50,0x7E,0x26,0x4D,0xD7,0x0B,0xE5,0xFC,0x44,0xD0,0xD2,0xAD,0x5D, +0x3C,0xB7,0x2A,0x6C,0xC8,0xF9,0x7C,0x8D,0xA4,0x79,0x9E,0x60,0x72,0xC1,0x78,0x3E,0x24,0x66,0x46,0x99,0x52,0x9A,0x90,0x37,0x8F,0x79,0x2C,0xD1,0xDF,0xA5,0xAE,0x0F, +0xF0,0xC2,0x36,0x7B,0x59,0x92,0x54,0xE4,0xD0,0x8E,0x1C,0xCE,0x24,0x16,0x90,0xDA,0x15,0x0F,0x21,0x03,0x50,0x08,0xB7,0x64,0xE7,0xB9,0xE5,0xCF,0x6C,0x64,0xA6,0xE2, +0x3E,0x23,0xC8,0x62,0x9E,0x91,0xE7,0xCC,0xDD,0x67,0x43,0x1C,0xF1,0xC9,0x01,0x4D,0x26,0xD7,0x17,0x0E,0x01,0x3B,0x5A,0xDC,0xBD,0x0E,0x2D,0x33,0x06,0xEC,0x57,0xF7, +0x08,0x19,0x6B,0xE1,0xDF,0x89,0x52,0x41,0x28,0x6A,0xBA,0x07,0x7B,0x9B,0xB3,0x77,0x99,0x0A,0xFD,0x80,0xC5,0x4B,0x27,0xF8,0x90,0xAE,0x8B,0x28,0xA7,0xAC,0x89,0x58, +0xD8,0x2B,0x90,0x76,0xF3,0x1A,0x80,0xDB,0x1E,0x38,0xA3,0xE3,0xE9,0xA9,0xEA,0xDE,0x9E,0xAB,0x30,0x92,0x32,0x48,0x67,0x8E,0xA0,0x58,0xF2,0xD8,0x5A,0xDF,0xCF,0x0F, +0xDC,0x3F,0xC6,0x94,0x91,0xCC,0xB3,0xC9,0x11,0x64,0xD8,0x93,0x4E,0x74,0x10,0x3A,0x9D,0x8D,0xFF,0x00,0xAF,0xBD,0x32,0x6D,0xF7,0x28,0x8D,0x52,0x1B,0xE5,0x3D,0x79, +0x45,0xC4,0xCF,0x57,0x0A,0x34,0xBD,0xA6,0x96,0xB7,0xCC,0xA8,0x30,0x41,0xA2,0xEF,0xA8,0xAD,0x0D,0x9D,0x41,0xB9,0x54,0x09,0xAA,0xFE,0x63,0x7C,0x79,0xEB,0x23,0xE3, +0x5C,0xBE,0x4A,0xB5,0xEE,0x55,0xE5,0x37,0x04,0xAF,0x6A,0x41,0x07,0x6B,0x8D,0xD4,0x79,0xF3,0xC3,0xC5,0x2F,0x14,0xF1,0x0C,0x35,0x62,0x65,0x68,0x2A,0x69,0x24,0x6B, +0x45,0x22,0x11,0xA8,0xFF,0x00,0xCB,0xC5,0xB7,0x5E,0x57,0xC2,0xEC,0xB7,0xCA,0x51,0xC4,0x3B,0x49,0xF9,0xED,0x3E,0x70,0xD9,0x92,0xA5,0x2C,0xBA,0xBB,0x15,0x16,0x62, +0x16,0xC5,0x8F,0x3F,0x61,0xF9,0xC6,0xAC,0x86,0xA7,0x23,0x6A,0xBE,0xC2,0xBA,0x29,0x52,0x21,0x20,0x01,0x52,0x75,0x82,0xEB,0xFE,0xE6,0x20,0xD8,0x7B,0x60,0xD4,0x7C, +0x1B,0x05,0x54,0x81,0x23,0x65,0x65,0x06,0xC8,0x81,0x77,0xBF,0x9B,0x1E,0x40,0x13,0x7E,0xBC,0x94,0xE3,0x54,0xDF,0x0E,0x65,0x34,0xAE,0x91,0xEA,0xD6,0x00,0xDA,0x35, +0xDD,0xCF,0x41,0xA8,0xF3,0x3B,0xF2,0xFE,0x44,0xE3,0x5F,0x95,0x07,0x13,0x10,0xF2,0x5D,0xCE,0x72,0xF1,0x05,0x3A,0x67,0xE8,0x94,0xEB,0x96,0x42,0xB4,0xC8,0x4D,0x3A, +0x51,0xCA,0xAA,0xC6,0xE3,0xAB,0xE9,0x21,0x8F,0x2F,0x5F,0x2C,0x2F,0x56,0x71,0x44,0x94,0xAE,0xD3,0x0E,0xCE,0xAD,0xA4,0x3E,0x28,0x1A,0x47,0x5E,0xCC,0xF5,0xBD,0xAD, +0xCF,0xD3,0x03,0x6B,0x78,0x52,0xA2,0x87,0x3D,0x8B,0x2E,0x94,0x3A,0x55,0x1D,0xCA,0x75,0xB9,0x36,0x03,0xFA,0xF2,0xC7,0xDA,0x8E,0x1C,0xAA,0xA7,0x6E,0xCE,0x4A,0x49, +0xA5,0x62,0xDA,0x2E,0xA2,0xE0,0x7B,0x7A,0xEC,0x70,0x40,0xE3,0xAE,0x24,0x3B,0xCC,0x21,0x9A,0x7C,0x42,0x97,0x30,0xA2,0x8A,0x08,0xF2,0xB4,0x85,0xE3,0x42,0x9A,0xE3, +0x95,0xEC,0x56,0xE3,0xC2,0x7D,0x2C,0x2C,0x05,0xFE,0xF8,0x15,0xFF,0x00,0xAB,0xB3,0xB9,0x68,0xFB,0x80,0x82,0x9C,0xD3,0x10,0x08,0x8B,0xB2,0xBE,0x9B,0x0B,0x6D,0xD7, +0x05,0xE9,0x38,0x58,0xC3,0x34,0x5D,0xF2,0x07,0x90,0x3E,0xA3,0xDD,0xB5,0x69,0xD1,0xE1,0xD8,0x9D,0xB9,0x83,0x63,0x6F,0xA6,0x0F,0x49,0x43,0x94,0xF0,0xCD,0x1D,0x25, +0x7C,0xD1,0xC1,0x52,0xEC,0xCC,0x86,0x89,0xD7,0xC6,0xC2,0xC7,0xC6,0xDF,0xE9,0x1B,0xFD,0xC0,0xB6,0x33,0xE6,0xD4,0xE3,0x43,0xB0,0x0B,0x63,0x2D,0x70,0xB1,0x16,0x62, +0xF5,0x1E,0x69,0xC6,0x89,0x45,0x04,0x89,0x53,0xDC,0xA9,0x20,0xBA,0xAC,0x85,0x40,0x45,0xBD,0xCD,0x8D,0xF9,0xF5,0xDB,0xD4,0xE3,0x7C,0x5F,0x15,0x38,0xBF,0x2B,0x83, +0xB1,0xA7,0xE3,0x0C,0xDC,0xFE,0xD0,0x3B,0xA5,0x34,0xA6,0x34,0x20,0x0B,0x0D,0xC1,0x1B,0x5B,0x60,0x2D,0x6C,0x2F,0xE6,0x95,0x99,0x8E,0x65,0x53,0x23,0x54,0x3B,0x08, +0x8D,0x99,0x63,0x4F,0x0A,0x2E,0xDB,0x58,0x60,0x34,0xB4,0xF5,0x0B,0x24,0x61,0xE0,0x91,0x9E,0x4E,0x5B,0x6C,0x70,0x78,0x6D,0xBE,0x47,0xFE,0x4A,0x6D,0xA0,0xD0,0x11, +0xC3,0x31,0xF8,0x85,0x26,0x7B,0x57,0x5B,0x98,0x67,0x09,0x2E,0x61,0x23,0x69,0x58,0xCD,0x75,0x4B,0xBB,0xA7,0x4D,0xBC,0xEC,0x07,0xE4,0x63,0x66,0x53,0xC7,0x19,0x04, +0x15,0x90,0xCF,0x2E,0x40,0x22,0x2A,0x82,0x30,0xD1,0xA8,0x22,0xDA,0xAF,0xA8,0xFF,0x00,0xA8,0xDB,0x6C,0x29,0x47,0x96,0x39,0x81,0x5E,0x4A,0x29,0x2E,0x08,0x36,0x55, +0xBE,0xDE,0xB8,0x68,0xCA,0x78,0x7F,0xBF,0x00,0x05,0x2B,0x20,0x41,0x73,0x6B,0x5F,0x7C,0x2B,0x2A,0xE1,0xA3,0x66,0xBF,0xD9,0x6A,0xEC,0x7E,0xA3,0xFE,0x51,0xC5,0x9C, +0x15,0x57,0x9B,0xCB,0x3C,0x35,0x42,0x3B,0x21,0x65,0x86,0xA5,0x01,0xD6,0xED,0xD0,0x93,0xBD,0xAE,0x39,0xF3,0x00,0xFD,0x70,0xF8,0xB5,0x14,0xD5,0x73,0x45,0x4D,0x31, +0x8E,0xA6,0x1A,0xB5,0xBA,0x4A,0x8C,0x16,0xD2,0x03,0x76,0xD8,0xFE,0xF0,0x06,0xD7,0xE4,0x6F,0xCF,0x12,0x84,0xF8,0x6B,0x0D,0x7E,0x46,0x64,0x89,0x94,0x55,0xA8,0xED, +0x07,0x69,0xE1,0xE9,0xC8,0x1F,0x3E,0x7D,0x77,0xBE,0x30,0x49,0xC4,0x12,0x77,0xEA,0x2C,0x9A,0xB2,0x8A,0x3C,0xAA,0xA2,0x8A,0x11,0x02,0x4F,0x48,0x8D,0x79,0x8F,0xFA, +0xA4,0x04,0x95,0x24,0x8F,0x20,0x09,0xF3,0xC0,0x63,0xC0,0x1C,0x56,0x33,0x7F,0xDC,0x22,0xF5,0xF2,0xE2,0x51,0x73,0x0E,0x07,0xCB,0x33,0xAA,0x9B,0x3D,0x22,0x39,0x3A, +0x9D,0x2A,0x15,0x4B,0x12,0x3C,0x88,0xD8,0x9E,0x77,0xB0,0xF2,0xB5,0xB1,0x3A,0xE2,0x2C,0x8B,0x33,0xE1,0xBC,0xDB,0xBA,0x52,0x4F,0xDB,0x22,0x3E,0xAE,0xCA,0x32,0x43, +0x80,0x3A,0x8E,0xA0,0x60,0xEF,0x0E,0x7C,0x4B,0x8A,0x8F,0x88,0x57,0x27,0xCC,0x2A,0x7B,0x78,0x89,0x55,0xEF,0x40,0x59,0x5C,0x5B,0x90,0x07,0xE5,0xDC,0xEF,0xFF,0x00, +0xEE,0x2B,0x39,0x9F,0x09,0xE5,0x3C,0x57,0x90,0xD2,0xE6,0x80,0xB3,0xA8,0x1E,0x3B,0xD8,0x9D,0x82,0x8B,0x5C,0x1B,0x81,0xB8,0xE5,0xBF,0xA1,0xC5,0x2E,0x53,0x89,0xB6, +0x34,0x7E,0xC2,0x46,0xE1,0xCC,0x85,0xE4,0x7C,0x4D,0x9E,0x51,0xA0,0x44,0xA9,0x66,0x76,0xBD,0x8C,0xBE,0x19,0x06,0xE3,0x91,0x3F,0x5E,0x58,0xA3,0x70,0xF7,0x12,0x55, +0x55,0x65,0xEA,0xF0,0xD6,0x97,0x2B,0xE2,0x54,0x9A,0xEC,0x09,0xB5,0x8A,0xDF,0x9A,0x9E,0x83,0x6F,0x2C,0x04,0xAE,0xE0,0x81,0x4D,0x9A,0x3A,0xC3,0x0C,0xDA,0x54,0xD9, +0x22,0xAA,0x6B,0xA8,0x17,0xBF,0x86,0x51,0xB5,0xEF,0xEC,0x7D,0xF0,0x22,0x6A,0x15,0xA0,0x83,0x55,0x33,0x3E,0xAD,0x64,0xDD,0x0F,0x8E,0x3E,0x5B,0x6F,0xD3,0x0E,0x39, +0x15,0x87,0x12,0xD7,0xDA,0x79,0x94,0x8A,0x5E,0x19,0x96,0x8E,0x7E,0xDD,0xE0,0xED,0x5A,0xA1,0x89,0xD2,0xAB,0x7B,0xE9,0xB8,0xD2,0xDE,0xB7,0x00,0xDB,0x90,0xD5,0xE7, +0xC8,0xCE,0x4F,0x92,0x35,0x5C,0xD1,0xCF,0x1A,0x1E,0xEF,0x1C,0xA1,0x74,0x84,0xB9,0xD4,0x4D,0xF4,0xAF,0xBD,0x94,0x7B,0x73,0xD8,0x93,0x87,0x3E,0x1C,0x92,0x2C,0xDD, +0x33,0x1A,0x69,0xA3,0x92,0x9D,0x0C,0x77,0x89,0xF4,0x9B,0xE9,0x0E,0xA5,0x8E,0xAB,0x7C,0xCC,0x4D,0xCF,0xB8,0xC1,0x7A,0xD3,0x1D,0x3D,0x6D,0x33,0x51,0x46,0xB2,0x2D, +0x42,0x9D,0x30,0xD2,0x8E,0x48,0x00,0x17,0x1E,0x40,0xF2,0xBF,0x97,0x95,0xF1,0x97,0x69,0x1C,0x19,0x5C,0x4F,0x34,0x71,0x75,0x32,0x27,0xC6,0x7A,0x79,0xD2,0x68,0x92, +0x7E,0xC3,0x5B,0x3E,0x9B,0x84,0x62,0x2E,0x2D,0xF4,0x22,0xDF,0x4E,0xB8,0xC5,0x9B,0xCE,0xD4,0x79,0xAC,0x6D,0x1D,0xFB,0x72,0xE9,0x24,0x64,0xA9,0x0A,0x35,0x21,0x23, +0x9F,0x36,0xDC,0x7B,0x58,0xE1,0xC7,0xE2,0x2E,0x5A,0x68,0xF3,0x24,0xE2,0x59,0xF4,0x24,0x93,0xAB,0x34,0x6A,0xA9,0x63,0x7E,0x87,0x91,0xE6,0x2F,0xCF,0x90,0x23,0x08, +0x39,0x1C,0x15,0x99,0xA5,0x7C,0x99,0xC6,0x6D,0x22,0x53,0xD2,0x52,0x21,0x98,0x3C,0xD7,0x20,0x8B,0xDC,0x80,0x47,0x52,0x6F,0x6C,0x4C,0xDA,0x81,0x8F,0x1D,0xCB,0x4C, +0x65,0x8F,0xF1,0x1A,0xB2,0x9C,0xA7,0x32,0x8A,0x7A,0x3C,0xA6,0x3C,0xAE,0x2A,0x9C,0xEE,0xBA,0x33,0xDD,0x69,0x65,0x1E,0x08,0x10,0x27,0xFD,0xC1,0xF2,0x00,0x0B,0xDB, +0xA9,0x03,0xCF,0x05,0x26,0xF8,0x57,0x96,0x65,0xB4,0xD2,0x55,0xE6,0x7D,0xBE,0x65,0x3B,0x5D,0xA4,0x92,0x5F,0x08,0x04,0x1D,0xC1,0x1F,0xC0,0x7B,0x60,0xBF,0xC1,0x3C, +0xF4,0x71,0x46,0x73,0xC5,0xFC,0x49,0x2C,0x4E,0xD5,0xAF,0x0C,0x74,0xB4,0x20,0x12,0x5A,0x28,0x94,0x92,0x40,0xEB,0xB9,0x09,0xFF,0x00,0x88,0xC1,0xAC,0xE7,0x33,0xA8, +0x87,0x87,0x4A,0xCF,0x33,0x09,0x5C,0x98,0x44,0x3C,0xEF,0xE2,0x1B,0xB0,0xE6,0x76,0x23,0x1E,0x43,0x55,0xA9,0xC8,0x99,0xBC,0x4A,0x69,0xB8,0xBF,0xF6,0x74,0xF1,0xE0, +0x39,0x17,0x75,0x71,0x24,0xF9,0xDA,0x65,0xB9,0x6E,0x56,0x2B,0xA5,0xCA,0x29,0xC4,0x20,0xE8,0x58,0x54,0x69,0x69,0x18,0x8E,0x77,0xC4,0xBB,0x3C,0x97,0x32,0xCC,0xE2, +0xED,0x66,0xA8,0x65,0x48,0xC1,0xD1,0x0C,0x7B,0x58,0x5A,0xD6,0x1F,0x4C,0x1A,0xF8,0xCD,0xC5,0xB9,0xA4,0x5C,0x4F,0x4D,0x97,0x2D,0xD5,0x60,0x80,0x7C,0xF1,0x90,0x6E, +0x7D,0x3C,0xB1,0x32,0x87,0x88,0x26,0x9A,0xA1,0x0E,0x63,0xAE,0x68,0xD4,0xDF,0x48,0x00,0x03,0xF4,0xC7,0xBD,0xF4,0x7D,0x26,0x35,0xC2,0x32,0x37,0x24,0xCF,0x3F,0xAF, +0xCA,0xDE,0x42,0x8B,0xC0,0x13,0xE4,0x19,0xDE,0x67,0x94,0xD5,0xBB,0x41,0x5A,0xE4,0x93,0xBA,0x86,0xB8,0xF6,0xFC,0x62,0x99,0xC2,0x5C,0x6B,0x2E,0x6F,0x54,0x0C,0x91, +0xA2,0xCA,0x14,0x24,0xAB,0xD1,0x87,0x2D,0x40,0x74,0xF5,0xC4,0xEF,0x31,0xCD,0xF2,0xCC,0xC0,0xB2,0xBD,0x03,0xA2,0x86,0x06,0x3D,0x04,0x2E,0xD6,0x00,0x83,0xF6,0xC7, +0x1E,0x1C,0xAC,0x86,0x93,0x8A,0xE1,0x92,0x35,0x31,0xC4,0xEC,0x14,0xAE,0xAB,0xEC,0x7D,0x71,0xB3,0x57,0xA3,0xC7,0x95,0x0D,0x88,0x9D,0x36,0x62,0xAC,0x01,0x9E,0xB7, +0xE1,0xCE,0x10,0xAB,0xE2,0x30,0x3B,0x8C,0x35,0x75,0x52,0x18,0xF5,0x84,0xA6,0x89,0xAC,0x17,0x6B,0xF2,0xDA,0xDB,0xDA,0xF8,0x42,0xF8,0xA5,0xC2,0xF2,0xD1,0x7F,0x89, +0xF7,0x5E,0xCE,0x78,0x16,0xD2,0x12,0x77,0x2A,0x7E,0x52,0x6D,0xE4,0x71,0x56,0xF8,0x4B,0xF1,0x73,0x32,0xE0,0x9C,0xB2,0x4A,0x1A,0x58,0xA2,0xAA,0xA6,0x60,0x74,0xA4, +0x8B,0xB8,0x3B,0x72,0x6E,0x76,0xDB,0xDB,0x00,0xB8,0xEF,0x34,0x19,0xD2,0x54,0x09,0x8A,0xCD,0x55,0x59,0x1B,0x19,0x43,0xED,0x6D,0xB5,0x7D,0xBF,0x96,0x3C,0xB8,0x38, +0xF4,0xB9,0x11,0xB1,0xB5,0xB7,0xE3,0xF1,0x3B,0x7E,0x26,0xCA,0x18,0x15,0xE2,0x41,0x66,0x97,0x2D,0xA8,0xCA,0xA8,0xA4,0x92,0x9A,0x51,0x37,0x6A,0x0B,0xCF,0x19,0xB0, +0x0A,0x41,0x00,0x5B,0xCE,0xF6,0xDF,0x17,0x4F,0x86,0x79,0xAC,0x93,0xF0,0x05,0x45,0x2C,0xE1,0xC4,0x88,0x7B,0x30,0x74,0x73,0x00,0xEE,0x43,0x5F,0xC3,0xCB,0xAF,0x4C, +0x79,0xF6,0xA2,0xAE,0x46,0xA4,0x97,0x4C,0x51,0xC6,0x91,0xB9,0x40,0xA9,0x7B,0x0B,0x1E,0x78,0xF5,0xAF,0xC3,0x3C,0x9E,0x66,0xC8,0x06,0x53,0x4E,0x8C,0x28,0xDB,0x2F, +0x82,0xA1,0x83,0x1B,0x89,0x25,0x72,0x43,0x13,0xD0,0x12,0x9D,0x3A,0x80,0x3C,0xF1,0xDC,0xF5,0x24,0x1B,0x46,0x40,0x3A,0x98,0xB4,0xEC,0x28,0xA9,0x98,0xB2,0xB8,0xA1, +0xAB,0x9E,0x48,0x5A,0xA9,0x1C,0x4A,0x40,0x91,0x1D,0x44,0xAA,0x4E,0xFB,0x11,0xBD,0xF9,0xF5,0x04,0xFB,0x8B,0x1C,0x00,0xCD,0xB8,0x42,0x96,0xB3,0x36,0x91,0x29,0xA3, +0x14,0xE8,0x8C,0x74,0x46,0xA8,0xF6,0xE5,0xC9,0x4F,0x3E,0xB7,0xF2,0xF4,0x18,0x66,0xCB,0x72,0x6A,0xD8,0x69,0x5F,0x30,0xA7,0x99,0xF4,0x8A,0xAD,0x01,0x96,0xEC,0x57, +0x6B,0x05,0xD3,0xD6,0xE0,0x1F,0xAE,0x36,0xD1,0x57,0x36,0x65,0x4B,0x2D,0x14,0xF4,0xA5,0xC2,0xF8,0x16,0x40,0x81,0x9A,0xFB,0xDF,0x90,0xE7,0xEE,0x6C,0x3A,0xE3,0x20, +0x7E,0x23,0x8C,0xA5,0x43,0x1C,0x74,0xBC,0x2E,0xD4,0x40,0x87,0xA8,0x91,0xD6,0x08,0xF4,0x2F,0x31,0x6F,0x11,0xB7,0xB9,0x2B,0xFC,0xF1,0xF2,0x82,0x33,0x43,0x95,0xCB, +0x2C,0xC4,0x9A,0xB9,0x27,0x11,0x07,0xEA,0x88,0x3C,0x2B,0xE9,0x60,0x01,0xD2,0x39,0x5F,0xA6,0xD8,0x16,0xBC,0x4F,0x57,0x49,0x3D,0x3D,0x0C,0xD4,0xE9,0x2C,0x85,0x5A, +0x67,0xA9,0x85,0x6E,0xB1,0xBC,0x9B,0x85,0xE5,0xB5,0x81,0x27,0x7E,0xB8,0x29,0x5B,0x58,0xD4,0xEC,0xAD,0xA8,0x46,0x18,0xEB,0x40,0xCC,0x41,0x27,0x9E,0xC4,0xAF,0xEE, +0x8B,0x01,0x60,0x79,0x1E,0x58,0x1C,0x8C,0x20,0xAA,0xF3,0xCC,0x93,0x7C,0x59,0xA2,0x4C,0xD2,0xBA,0x82,0x09,0xE9,0x41,0x33,0x54,0x22,0x2B,0xB5,0xF7,0x53,0x70,0x76, +0xBD,0x99,0x8E,0xDB,0xDA,0xDD,0x31,0x3C,0xF8,0xAD,0x95,0x66,0x33,0x70,0x45,0x3E,0x5D,0xC1,0xF0,0x43,0x57,0x96,0xD1,0x6A,0xA9,0xAE,0xEE,0xF7,0x57,0x45,0x06,0xC0, +0x30,0x3C,0xD4,0x73,0xF4,0xBF,0xA6,0x2B,0x5C,0x6D,0x0C,0x79,0x96,0x53,0x98,0x3C,0xD5,0x22,0x3A,0xBE,0xC4,0x84,0x60,0x4C,0x8E,0xDE,0x20,0xC1,0x6F,0xA4,0x01,0x6D, +0x2B,0x6B,0x7F,0x1C,0x48,0xF8,0x3F,0x89,0xB3,0x3E,0x1F,0x15,0xD2,0x66,0xD9,0x79,0xAD,0xA1,0x8E,0x36,0xA7,0x78,0x82,0x02,0x41,0xD8,0x80,0xDD,0x6D,0x6B,0x83,0xEF, +0x8E,0x6B,0x62,0x7D,0xC3,0x20,0x17,0x46,0xEA,0x3F,0x80,0x2A,0x75,0xFF,0x00,0xD3,0x63,0x14,0xE2,0xFA,0xEA,0x68,0x49,0x49,0x65,0xCB,0xD9,0x6C,0x5A,0xCB,0x71,0x26, +0xAF,0xA9,0xDC,0x7E,0x7D,0x71,0x43,0xE2,0x68,0xE6,0x5C,0xB2,0xA6,0x96,0x85,0xCB,0x4D,0x1B,0xAC,0xF2,0x31,0x37,0xB1,0x04,0x91,0xBF,0x9E,0xDC,0xBD,0x31,0x28,0xCB, +0xF2,0xF8,0x6A,0x38,0xA6,0x2C,0xF7,0x80,0xEA,0x4D,0x05,0x7C,0x5F,0xB6,0x34,0x73,0x38,0x0A,0x4F,0x50,0x8C,0x7D,0x3C,0xFD,0x71,0x40,0xFE,0xDD,0x4C,0xFA,0x81,0x2A, +0x69,0x61,0x78,0x65,0x47,0x06,0xBA,0x19,0x76,0x65,0x90,0x13,0x75,0x3D,0x6C,0x7A,0x63,0x83,0xEA,0xB8,0x9F,0xF5,0x5F,0xAA,0x51,0xC1,0xEF,0xF8,0xA9,0xD6,0xD1,0x95, +0x38,0xFC,0x77,0xCC,0x82,0x7C,0x68,0xCA,0x25,0x19,0xAC,0x19,0xC4,0x72,0x34,0xC8,0x62,0x09,0x23,0xDE,0xE6,0xE7,0x71,0x7F,0x4D,0xF1,0x26,0x4B,0x16,0x37,0xC7,0xAD, +0x73,0xDC,0x9E,0x9B,0x33,0xA8,0x9E,0x82,0x7A,0x78,0xE5,0xA7,0x98,0x7E,0xD1,0x98,0x05,0x29,0x7E,0x57,0x1D,0x31,0x14,0xCF,0xBE,0x11,0xE6,0x34,0xF9,0x84,0x83,0x24, +0x9E,0x2A,0x88,0xB5,0x00,0x15,0xCE,0x96,0x17,0xDB,0xF5,0x23,0xEF,0x8F,0x61,0xE8,0xFE,0xA9,0x8F,0xC6,0x31,0xB9,0xAA,0x9C,0x3D,0x7E,0x81,0xF7,0x97,0x5E,0x4C,0x9C, +0x47,0xA4,0x4A,0x58,0x80,0x6D,0xCA,0xF8,0x3B,0xC2,0x59,0x4C,0xD9,0x87,0x13,0x45,0x32,0x53,0xF6,0xB0,0xC2,0x7B,0x47,0x1A,0x49,0x16,0xF2,0x38,0x29,0x07,0xC3,0x3C, +0xFF,0x00,0xBF,0x76,0x15,0xFD,0x8D,0x20,0x06,0xCC,0x5D,0xAE,0x7C,0xF6,0xC5,0x0B,0x87,0xF2,0x28,0x38,0x69,0x85,0x25,0x3D,0x41,0x09,0x20,0x3A,0xAA,0x19,0x6D,0x71, +0xE7,0xFA,0x63,0xA1,0xAA,0xF5,0x3C,0x4A,0x84,0x21,0xB3,0x31,0xE9,0xB4,0x0E,0xD9,0x2D,0x85,0x46,0x6C,0xB5,0xE8,0xF4,0x30,0x96,0x27,0x84,0x32,0x85,0x5D,0x27,0x68, +0xFD,0x06,0x08,0x66,0x50,0x11,0x93,0xD7,0x66,0x1D,0xF1,0x5D,0x69,0xE9,0xD9,0x35,0x9B,0x16,0xB1,0x5B,0x01,0xCB,0xD7,0x1D,0x32,0xE5,0xB0,0x0A,0x76,0x73,0x5E,0x67, +0x95,0x80,0xB4,0x69,0xE1,0x5F,0x3C,0x2E,0xF1,0x55,0x44,0x54,0x1C,0x3E,0x32,0x85,0x98,0x3D,0x7D,0x59,0x0A,0xF0,0xC6,0x49,0x28,0x97,0xB8,0xD8,0x1E,0xBF,0xC7,0x1E, +0x47,0x0A,0x0D,0x46,0x71,0xB4,0xF2,0x4C,0xF4,0x2E,0xC3,0x16,0x33,0x27,0xF4,0x99,0x6D,0x55,0x5C,0x51,0x52,0x0B,0x2B,0xD4,0x4C,0x54,0x13,0xC8,0x5C,0xDA,0xFF,0x00, +0x4C,0x7B,0x3F,0xE1,0xCE,0x53,0x3D,0x27,0x07,0xD7,0xB5,0x2C,0xAE,0x29,0xAB,0xA5,0x44,0x81,0x25,0xF9,0xFB,0x34,0x04,0x2B,0x11,0xEC,0x47,0x2E,0x46,0xF8,0x8A,0xFC, +0x35,0xF8,0x47,0x99,0x66,0xF5,0x50,0xE7,0x59,0xCC,0x12,0x25,0x0D,0x37,0xED,0x16,0x94,0xA9,0xB9,0x00,0x03,0xA9,0xBD,0x37,0xC7,0xAA,0x28,0x8E,0x49,0x41,0x1D,0x2D, +0x6C,0x0D,0x2C,0x14,0xF4,0xE0,0xC4,0x90,0x25,0xEE,0xC4,0x80,0x00,0xB2,0xDC,0xF5,0x3B,0x75,0xC7,0xA4,0xD6,0x65,0xF2,0x91,0x89,0x3A,0xFC,0xCE,0x26,0x15,0xA0,0x49, +0x93,0x4C,0xDE,0x3A,0xCE,0x1D,0x99,0xA8,0xA0,0x80,0xC0,0x63,0x73,0x7A,0xC5,0xF0,0x6E,0xD7,0xE4,0x3C,0xEC,0x6C,0x39,0x90,0x05,0xCF,0x30,0x30,0x67,0x84,0x29,0xE8, +0x20,0x71,0x53,0x2C,0x80,0x36,0x9D,0x28,0xAA,0xC3,0xDC,0xDC,0xF4,0xDF,0x7B,0x7D,0xF0,0x03,0xE2,0x23,0xCF,0x9D,0xE6,0xF1,0x8A,0x09,0xDE,0x52,0x80,0x2B,0x6F,0xBA, +0x28,0x1F,0xBD,0x6F,0x97,0xF5,0xF7,0xC6,0x1C,0xB6,0x56,0xC9,0x72,0xC1,0x13,0x78,0xC8,0xBE,0x94,0xBD,0xD9,0xF7,0xDA,0xCB,0xFA,0x0F,0x3D,0xF6,0xC2,0x7E,0x3D,0xCD, +0x82,0x99,0x6A,0xA5,0x23,0x35,0x82,0x3A,0x2C,0xD4,0x53,0xD2,0x19,0xA9,0x63,0xAB,0x91,0x95,0xA4,0xA7,0x84,0xA2,0xBF,0x5F,0x10,0xB5,0xD9,0xBD,0x79,0x60,0x17,0x14, +0x54,0xD4,0x51,0xC1,0xDD,0x29,0x65,0xA8,0x47,0x56,0xBC,0x33,0x9D,0x76,0x3C,0x80,0xF9,0xCE,0xC7,0xCC,0x8F,0xBE,0x19,0x6A,0x26,0x8F,0x3D,0xC9,0xA1,0xA4,0xA4,0x31, +0xCB,0x16,0x90,0xD3,0x52,0xD7,0x06,0x32,0x3D,0xC0,0x27,0x44,0x83,0x7E,0xB7,0xFB,0x72,0xC0,0x2E,0x2F,0xA7,0xA6,0x5E,0x18,0x78,0x60,0x5A,0x82,0xD0,0x85,0x71,0x11, +0x87,0xB4,0x74,0xEB,0x70,0xD7,0x0C,0x45,0xFD,0xF7,0x1C,0xF0,0xC3,0x8A,0x8D,0x4C,0xC1,0xEE,0x2C,0x4F,0x5D,0x59,0x5D,0x42,0x90,0xC9,0x58,0x1B,0x30,0x58,0xFC,0x41, +0xE3,0xB1,0x3C,0xEE,0x6C,0x1A,0xDC,0x8F,0x3E,0x78,0x8F,0xE6,0x39,0xBD,0x56,0x4F,0xC5,0x52,0xC7,0x57,0x97,0x45,0x51,0x34,0xDA,0x92,0x59,0x35,0x04,0x2E,0x87,0x63, +0x65,0x22,0xEA,0x4D,0xED,0x71,0xB5,0xAF,0x8A,0x64,0x39,0xBE,0x57,0x34,0xA2,0x19,0x19,0x2A,0xD6,0x44,0x04,0x80,0xD2,0x24,0x88,0x77,0xE4,0x5C,0x9B,0xFB,0x7E,0x70, +0xA5,0xC7,0x3C,0x2B,0x4F,0x9D,0x70,0xFC,0xB9,0x9E,0x47,0x32,0x19,0xE9,0xED,0x74,0x98,0x08,0xE4,0x5E,0x9B,0x10,0x6C,0x45,0xF6,0xC1,0xA2,0x10,0xDD,0x4B,0x2D,0x62, +0x61,0xEE,0x19,0x7E,0x67,0x51,0x45,0x2F,0x0D,0xC4,0xF4,0xEB,0x2B,0x76,0xAC,0x93,0x5F,0xFB,0xBE,0xE3,0x52,0xD9,0x77,0x61,0x61,0xF3,0x00,0x36,0x1C,0x86,0x3E,0xE5, +0xF5,0xB2,0x55,0xE7,0x81,0x73,0xF9,0x1B,0x2E,0xA9,0x70,0xCE,0x73,0x73,0x73,0xAB,0x48,0x3E,0x16,0x03,0x67,0x5D,0x40,0x03,0x7B,0xE2,0x69,0x95,0x71,0x6D,0x66,0x45, +0x9D,0x32,0xD7,0x42,0xE5,0xD6,0xE1,0x40,0x60,0xAC,0xBE,0x7C,0xBD,0x07,0xE7,0x15,0x3A,0x7E,0x22,0xA2,0xE3,0x3C,0xB1,0xD6,0xAA,0x49,0xE2,0x99,0xAD,0xA7,0x53,0x76, +0x8B,0x38,0x08,0xAA,0xEE,0xE2,0xE4,0x86,0xD4,0xA0,0x92,0x3E,0xBD,0x4E,0x26,0x7D,0x0A,0xE4,0xEC,0x71,0x2B,0x1E,0xA4,0xA3,0x7B,0x7B,0x9D,0xF5,0x52,0xCF,0x3C,0xB1, +0xBB,0xAB,0xCC,0x84,0xBC,0xBD,0xA4,0x2C,0x35,0x3A,0xEB,0x24,0xB9,0x53,0x66,0x0A,0x4E,0xFB,0x8E,0xBE,0xB8,0x01,0x9C,0x54,0x2B,0x4D,0x3B,0x42,0x2A,0x23,0x37,0x52, +0xB7,0x8D,0xC0,0x7B,0x6F,0x60,0x6D,0x6E,0x7B,0xE3,0x56,0x5F,0x42,0x33,0x3C,0x9B,0x30,0xAB,0xA0,0x47,0x2E,0xA3,0xB1,0xDF,0x99,0x51,0x72,0x59,0xD5,0x6D,0x61,0xE1, +0x3C,0xED,0x72,0x56,0xD7,0xDF,0x07,0xB2,0x6F,0xED,0x15,0x4C,0xB5,0xD8,0x42,0xF0,0xD2,0xA3,0xB4,0x7A,0xA3,0x2C,0x4A,0x92,0x08,0xBA,0x9E,0xAC,0x58,0x7D,0xC6,0x39, +0x69,0xE9,0x43,0x09,0x3B,0x09,0x13,0x6F,0xEE,0x0C,0xC2,0x9B,0x98,0x82,0xF9,0x8C,0x0F,0x52,0xD1,0xB8,0x91,0xDC,0x90,0x75,0x68,0x2D,0x7F,0xEB,0x9E,0x09,0x55,0xD5, +0xCB,0x53,0x0C,0x71,0xE5,0x59,0x5D,0x4D,0x4C,0x97,0x11,0xBB,0x18,0xCA,0x2B,0x82,0x2D,0x6F,0x7E,0x78,0x7B,0x5C,0xB6,0xA2,0x09,0xE7,0x8A,0x5A,0x79,0x5A,0x79,0x81, +0x53,0x32,0xC2,0x40,0x0A,0x4F,0x8B,0x98,0xF0,0xDA,0xC7,0xED,0x86,0x3E,0x17,0xCA,0xEB,0x9F,0x2F,0x86,0xBE,0x85,0x69,0xA0,0x68,0x19,0x66,0x44,0x91,0xFF,0x00,0xEE, +0x1B,0x51,0x50,0xC0,0xB7,0x87,0xF7,0xC7,0xD3,0xA6,0x21,0xD0,0x86,0x23,0x71,0xBA,0x82,0x7D,0x41,0x87,0x0A,0x24,0xA3,0x22,0xF8,0x75,0xC6,0xB5,0x75,0xD3,0x15,0x8B, +0xBA,0x3A,0x80,0xC4,0x37,0x89,0x88,0x6E,0x41,0x57,0xAE,0xC7,0xCF,0x0F,0xD9,0x77,0xC3,0x8C,0x83,0x87,0x44,0x79,0xC5,0x6D,0x4B,0x55,0x67,0x32,0x3A,0x87,0x79,0x40, +0x62,0xC4,0xDE,0xDA,0x7E,0xC3,0x90,0xFE,0x18,0x76,0xA9,0x99,0x24,0xA2,0xA8,0xCC,0xAA,0xEB,0x6A,0x04,0xF4,0xC1,0xBB,0x57,0x41,0xA5,0x09,0x20,0x35,0xF5,0x2D,0xFA, +0x93,0xB6,0xC2,0xD6,0xDB,0x1D,0xD4,0xF9,0x8C,0x8B,0xC3,0x54,0xA6,0xA6,0x6A,0x10,0x95,0x23,0xF6,0x4A,0xF2,0xAA,0xBA,0x2B,0xDB,0x53,0x6D,0xAC,0xAF,0x87,0xC8,0x83, +0xE7,0x73,0x8D,0x2B,0xA7,0xDA,0x6C,0x71,0x10,0xD9,0x99,0xC7,0xBA,0x6F,0xA6,0x35,0xF0,0x2C,0x11,0xCD,0x1A,0x52,0xC2,0xA9,0xAD,0x04,0x7F,0x33,0x06,0x1F,0xB8,0x09, +0x0C,0xDD,0x7D,0x2C,0xDB,0x9B,0x8B,0x60,0x7E,0x6D,0xC4,0x91,0x25,0x0C,0xF4,0xB9,0x42,0x14,0x2C,0x09,0x24,0x4C,0x42,0x81,0xE6,0xC3,0x99,0x3E,0x96,0x00,0x60,0x5E, +0x7F,0xC4,0xC2,0x83,0x3A,0x7A,0x4C,0x9B,0x30,0x54,0x82,0xA2,0x25,0x13,0x2C,0x26,0xE3,0x61,0xD5,0xED,0xA8,0x9F,0xAE,0x16,0x17,0x31,0xD5,0x52,0x4D,0x10,0x88,0x20, +0x17,0xED,0x9C,0x8D,0xDA,0xDB,0xB9,0xBE,0xE4,0x5E,0xF6,0x1B,0x1F,0xAE,0x1B,0xB3,0x67,0x52,0xD4,0x5C,0x21,0x02,0xC7,0x4F,0x04,0xC9,0x51,0x38,0x31,0x9B,0x33,0x2A, +0xDC,0x6A,0x24,0xD8,0xF9,0x9F,0xB9,0xBF,0xD7,0x19,0x86,0x69,0x0D,0x2C,0xCF,0x23,0x0F,0xDA,0xDB,0xC0,0x84,0xEE,0x83,0xCC,0xFA,0x9F,0x7B,0xFA,0xE1,0x66,0xB7,0x3B, +0x8A,0x92,0xA1,0xCD,0x24,0x9D,0xE2,0xA1,0xB6,0xEF,0x0F,0x63,0xA7,0xFE,0x23,0x96,0x38,0x51,0xD5,0xA8,0xA9,0x5A,0x9A,0xE9,0xF5,0x03,0xE2,0x52,0x4D,0xB7,0xF3,0x1E, +0x67,0xD7,0x02,0x79,0x8D,0x59,0x68,0x92,0xA2,0x18,0x57,0xB7,0xCD,0x62,0x6A,0x4A,0x13,0x3B,0x43,0x4D,0x99,0x45,0xE2,0x60,0x57,0x93,0x3D,0xB7,0x23,0x6D,0x26,0xDC, +0xB9,0x8F,0xDE,0xC6,0x2C,0xEB,0x3B,0x32,0xF0,0xDD,0x65,0x2C,0xA1,0x6B,0x3B,0x44,0x2C,0x84,0x44,0x19,0x18,0x81,0xE2,0x3A,0x4F,0x89,0x48,0xEA,0x01,0x1E,0xDB,0xE0, +0x4E,0x5D,0x9C,0x66,0x0A,0x29,0xF2,0x2A,0x9A,0x85,0x7A,0x2A,0x44,0x4A,0x86,0x8E,0x51,0xE1,0x98,0x31,0x2A,0xCC,0x08,0xEA,0x00,0x04,0x7F,0xC0,0xF9,0xE0,0x2E,0x6F, +0x9A,0x3D,0x4C,0x83,0x25,0x4A,0x18,0xE4,0xA4,0xA7,0x70,0x3B,0x5D,0x5A,0x1D,0xF5,0x5C,0xAB,0x01,0xB5,0x87,0xFB,0xBC,0xFA,0xEF,0x8D,0xFD,0x09,0xCF,0x1D,0xC5,0x6C, +0xB2,0x3C,0xCA,0x5C,0xAE,0x44,0x30,0x56,0x2C,0x01,0x18,0x89,0x23,0x8C,0x4C,0x85,0x4F,0x3E,0x6D,0xB7,0xDB,0x0A,0xD9,0x86,0x99,0x29,0x62,0x85,0x6A,0xA3,0x9A,0x38, +0xC9,0xD4,0x12,0x37,0x1B,0xF9,0x78,0x6E,0x7A,0x61,0xCB,0x3A,0xA1,0xAD,0xAA,0x96,0x3C,0xC7,0x26,0x8D,0xEA,0x2A,0x14,0x69,0x78,0xBB,0x34,0x69,0x13,0x6E,0x64,0x82, +0xA6,0xE3,0xD5,0x4E,0xDB,0x82,0x70,0x0E,0xA8,0x56,0xD4,0x2F,0x61,0x9A,0xF7,0xE8,0x65,0xD2,0x6C,0x92,0xEA,0x9C,0x0B,0x1E,0x56,0x04,0x39,0x3F,0x8C,0x0E,0xEF,0xA8, +0xC2,0x2E,0x4B,0xB3,0xAC,0xB6,0x87,0x32,0x98,0xF7,0x38,0x3B,0x09,0xA2,0x07,0x50,0x88,0xBB,0xDF,0x7E,0x7E,0x2D,0xF0,0xBB,0xA7,0x3A,0xCB,0x2A,0x4B,0xD2,0xCD,0x2B, +0x0B,0x1F,0x93,0x66,0x02,0xF6,0xE9,0xBE,0x29,0x71,0x54,0xD1,0xD0,0xE6,0xB5,0x54,0x53,0xB4,0x8A,0x8D,0xCE,0x23,0x0C,0x94,0xFA,0x47,0xB1,0x61,0xF9,0xC7,0x1A,0xE9, +0xA8,0x25,0x8A,0x38,0xA9,0x2B,0xEA,0x26,0x57,0xBD,0xBF,0xBB,0x06,0x60,0x2D,0xCB,0xC6,0x3D,0x70,0xEF,0x31,0x15,0x71,0x47,0x0E,0xE3,0x01,0x64,0xDC,0x77,0x98,0xD3, +0x4B,0x09,0xAA,0xCB,0x44,0xE2,0x30,0x2D,0xAC,0x14,0xBD,0xBE,0x50,0x4F,0x22,0x01,0x00,0xE1,0x9F,0x2C,0xF8,0xA9,0x48,0xB2,0xA3,0xE6,0x14,0xF5,0x92,0x4A,0xCE,0xD2, +0xC8,0x16,0x72,0x2F,0x2D,0xAC,0x1A,0xC7,0x6B,0x01,0x60,0x07,0xA5,0xAF,0x80,0x74,0xD4,0x12,0x35,0x48,0x2B,0x96,0x8E,0xC8,0x1B,0x0E,0xF0,0x48,0x00,0xFD,0x2D,0xF7, +0xBD,0xB1,0xDB,0x36,0x65,0x95,0x3C,0x81,0xA4,0xA2,0x8A,0x32,0xA7,0x41,0x7D,0x23,0x9D,0xBF,0xD4,0x18,0x5F,0xEF,0x88,0x76,0x9E,0x84,0xA0,0xBB,0x7B,0x8F,0xB0,0xFC, +0x42,0xE1,0xB3,0x95,0xE4,0x94,0xD5,0x27,0x30,0xD1,0x10,0xFE,0xFC,0xA1,0xB5,0x89,0x85,0xF5,0x69,0xB1,0x3C,0xB5,0x74,0x04,0x5F,0x1A,0x5F,0xE2,0x2C,0xF9,0xCA,0x9C, +0xB7,0x28,0xA2,0xAC,0x14,0x33,0xCA,0x21,0x14,0xA0,0x84,0x0C,0x6E,0x34,0x80,0x4D,0xFA,0xDB,0x13,0xCE,0xF3,0x49,0x57,0x10,0x8A,0x92,0x92,0x79,0x99,0x98,0x03,0x2E, +0x8D,0x4C,0x3D,0xB9,0x00,0x3D,0xCE,0x0E,0xD2,0xD2,0xCD,0x47,0x1A,0xCD,0x53,0x0D,0x34,0x60,0x8D,0x51,0x76,0xB2,0x89,0x98,0x8B,0x73,0x08,0x80,0xFE,0x6F,0x80,0xDA, +0x39,0xE2,0x31,0x47,0xDC,0xA0,0xE4,0xB0,0xE6,0x79,0xAD,0x3B,0x97,0x86,0xA2,0x1A,0x75,0x62,0xD2,0x35,0x88,0x50,0x6F,0x7B,0x12,0x45,0xAF,0xE9,0x61,0x8C,0x99,0xA6, +0x61,0x54,0xD2,0x2A,0xAD,0x78,0x48,0x21,0x27,0x93,0x03,0x61,0xEB,0x6B,0x01,0xFA,0xFA,0x61,0x66,0x0E,0x2E,0xAC,0xA9,0x59,0xA9,0xCF,0x7B,0xA9,0x00,0x85,0x3D,0xAB, +0x5A,0x31,0xB7,0x45,0xF0,0xFE,0x77,0xC7,0x19,0xD6,0x59,0xA9,0x43,0x54,0xD6,0x53,0xC7,0x1F,0x35,0x45,0x1A,0xD8,0xFB,0x03,0x60,0x3E,0x97,0xC2,0x88,0x11,0x80,0x42, +0x75,0x3C,0x43,0x0C,0x59,0x7B,0x88,0x64,0x65,0x47,0x05,0x43,0x85,0xB9,0x90,0x7A,0x7A,0x7E,0x3D,0xF0,0x01,0x73,0x1A,0xEA,0xF9,0xFB,0x08,0x63,0x74,0x8E,0x4D,0xEE, +0x4D,0xC9,0xF7,0x38,0xEE,0x58,0x29,0x60,0x46,0x7E,0xCD,0xA5,0x98,0x8D,0xDE,0x56,0xE6,0x3C,0xB7,0xE5,0xED,0xB6,0x38,0x45,0x5A,0x61,0x04,0x2C,0xD1,0x53,0x8B,0xEE, +0xA9,0xD7,0xEA,0x71,0x2E,0xFA,0x11,0xAA,0x3F,0x30,0x95,0x3D,0x1D,0x3D,0x02,0x8A,0xAA,0x99,0x10,0x37,0x21,0xA9,0xB9,0xFD,0x3A,0x9F,0xEA,0xD8,0xD1,0x4F,0xDA,0x55, +0x95,0x92,0x9A,0x9C,0xEA,0x5F,0xFD,0xC7,0xD8,0x0D,0xFA,0x75,0xC6,0x6A,0x69,0xA8,0x98,0x87,0xD3,0x34,0xCC,0x4D,0xB5,0x10,0x58,0x03,0xEE,0x76,0xFC,0xE3,0x62,0xCD, +0x5C,0x11,0x60,0xCB,0xE8,0xDD,0xB9,0x8D,0x4E,0x40,0x3C,0xC7,0x41,0x8C,0xE5,0x4C,0x68,0x68,0xC1,0x9A,0xB2,0xC5,0xC4,0x8B,0x06,0x57,0x5D,0x25,0x53,0xBC,0x46,0x36, +0xA8,0xEC,0xC2,0x26,0xA6,0x91,0xAD,0xA5,0x40,0x00,0x28,0x0C,0x76,0x1E,0xB8,0x2B,0x25,0x3D,0x1C,0xE7,0x2E,0x96,0xA2,0x50,0xD5,0x54,0xF4,0xC9,0x10,0x96,0xDF,0xE4, +0x85,0x07,0xB2,0x2E,0x79,0x59,0x80,0x65,0x3C,0xF9,0x82,0x70,0x7F,0x30,0xE0,0x89,0xE8,0xB2,0xD8,0xE7,0xA4,0xA7,0xEC,0x91,0xE5,0xD1,0x3D,0x4B,0x9B,0xBC,0x84,0x92, +0xA4,0xA5,0xB9,0x2A,0xAB,0x11,0x7E,0xA7,0x09,0x59,0xC4,0x99,0x86,0x5A,0xAB,0x49,0x5B,0x1B,0xA4,0x15,0xDA,0x9C,0x4B,0x26,0xC1,0xA3,0x56,0xD3,0x7F,0xD0,0x60,0xD3, +0x52,0xAF,0xF7,0x31,0x04,0xFB,0x31,0x6B,0x3A,0x8D,0x2B,0x6A,0x6A,0x73,0x0A,0x56,0x7A,0x3A,0xD8,0x34,0x87,0x8E,0xFE,0x19,0x58,0x91,0x61,0x7B,0x75,0xB0,0x3C,0xED, +0xB1,0xC7,0x7D,0x35,0x6E,0x67,0x5F,0x45,0x35,0x2C,0x95,0x22,0x99,0xE3,0x5D,0x6F,0x4B,0x3A,0x07,0xB0,0xB8,0x07,0x49,0x66,0x17,0xBD,0xF9,0x2D,0xC7,0xA6,0x39,0x56, +0x9A,0x5A,0xFA,0x98,0x9A,0x9E,0x36,0x95,0x51,0x23,0x80,0xBE,0x9B,0x76,0x97,0x0C,0xC1,0x58,0x79,0xF8,0x5B,0x7F,0x41,0xE7,0x81,0x0E,0xD5,0x49,0x45,0x24,0xAE,0x7B, +0x46,0x25,0x81,0x8A,0x5D,0xCB,0x28,0x36,0xBA,0x8F,0x3B,0x9E,0x5E,0x98,0x33,0x94,0x54,0x30,0x20,0x9C,0xCA,0x79,0x29,0x33,0x2B,0xBB,0xC7,0x32,0xF2,0xD2,0x90,0xBA, +0x5B,0xCB,0x96,0x9F,0xE3,0x8C,0x35,0x72,0xD6,0x30,0x3D,0x95,0x0E,0x99,0x6D,0x74,0x77,0x2E,0x58,0xDF,0xCB,0x51,0xDB,0x6B,0xF4,0xC1,0x07,0x9E,0x89,0x32,0xE1,0x5B, +0x3E,0x5C,0xF2,0x40,0xCE,0x02,0xCF,0x4F,0x21,0x4E,0x5D,0x2F,0xD4,0xFA,0x36,0x3F,0xA7,0xAE,0xCB,0xAA,0x4F,0xF8,0x42,0x6A,0x2A,0x06,0x9E,0xD5,0xB4,0x35,0xFD,0x45, +0xED,0x7F,0xA6,0x2C,0x71,0xDC,0x65,0x54,0x06,0x32,0x2A,0xE9,0x22,0x2D,0x2C,0x0F,0xAF,0x4E,0xA2,0x65,0x60,0xBB,0x75,0xDA,0xE4,0xFE,0x98,0xEF,0x5E,0x1E,0x9A,0xA1, +0x3B,0xC4,0xF4,0xE9,0x23,0x8D,0xC4,0x93,0xC8,0xCF,0x61,0xE4,0x03,0x5B,0xF5,0xC3,0x06,0x55,0x21,0xCD,0x40,0xA5,0xA9,0x8E,0xBE,0x09,0x94,0x58,0xBD,0x29,0x8C,0xEA, +0x1E,0x5F,0x28,0x37,0xFA,0xE3,0xAA,0xBA,0x3C,0x9A,0x15,0x68,0xA7,0x8F,0x38,0x91,0xF7,0x00,0xCE,0x25,0x22,0xDF,0x7C,0x2D,0x9E,0x8F,0xF3,0x08,0x28,0x23,0x88,0xAF, +0x55,0x55,0x55,0x1C,0xB1,0xB4,0xDA,0x54,0xC6,0x6C,0x0A,0x13,0x1A,0x8F,0x60,0x08,0xB7,0xDF,0x06,0x67,0xCF,0xE9,0xEB,0xBB,0x29,0x62,0xA8,0x95,0x24,0x8A,0xD7,0x42, +0xC5,0xD7,0x63,0xD3,0x51,0xB9,0xFA,0x9C,0x0A,0xAC,0xA6,0xA4,0x8E,0x56,0x78,0x69,0xA3,0x50,0x0D,0xEE,0xF4,0xAE,0x6D,0xB7,0x99,0xC7,0x5C,0x33,0x53,0x4A,0x5A,0xF5, +0xA5,0x1C,0x30,0x50,0xBD,0x9B,0x28,0x3E,0xA3,0xD3,0x1A,0x15,0xB7,0x08,0xB2,0x00,0xEE,0x1A,0x9B,0x38,0xAE,0xAC,0x84,0x53,0xB0,0x22,0x3B,0xDF,0x4D,0xED,0xAB,0xDC, +0x01,0x8D,0x54,0xB2,0xB0,0x87,0xB3,0x88,0x41,0x4E,0xD6,0xDF,0xB2,0x8C,0xB3,0x13,0xEA,0x4E,0x07,0xC5,0x4E,0xA2,0xC5,0xE6,0x4B,0x83,0xB9,0xD0,0x58,0x9F,0xB9,0xC6, +0xF8,0x3F,0xB5,0x10,0x83,0x4C,0x91,0xB2,0xF4,0x3B,0x0C,0x43,0xD4,0x80,0xCC,0xA6,0x0E,0xD6,0x72,0xD5,0x95,0x15,0x6F,0xA6,0xD7,0x2C,0xDA,0x2F,0xEA,0x06,0x3B,0xA3, +0x8E,0x38,0x27,0x2F,0x05,0x33,0x05,0x26,0xF7,0x23,0x57,0xD6,0xFC,0xB1,0xDA,0xD5,0x39,0xB4,0x4C,0x75,0x44,0xA1,0x81,0xF9,0x8A,0x5A,0xFE,0xD6,0x1B,0xE3,0xA6,0x4E, +0xF8,0xD2,0x86,0x9A,0xA3,0xB2,0xB8,0xE4,0x11,0x71,0x70,0xB7,0xAF,0xE2,0x16,0xA3,0xAD,0x2F,0xA4,0x24,0x41,0xD8,0x1E,0x67,0x95,0xB0,0x6E,0x0A,0xC1,0x1D,0x38,0x59, +0x6B,0x61,0x80,0x11,0xC8,0xA6,0xDF,0xD7,0xAE,0x14,0xE0,0xA8,0x58,0x9C,0xC7,0xDB,0xC9,0x7B,0xF3,0x00,0x6F,0xF6,0xC7,0xC7,0xAC,0x70,0x42,0x69,0x91,0xF5,0x7C,0xA1, +0x93,0x9E,0xFC,0xEC,0x70,0xA6,0xC5,0x70,0xD5,0xC7,0xD0,0x9F,0xFF,0xD9,}; + diff --git a/examples/160 x 128/TFT_flash_jpg/jpeg2.h b/examples/160 x 128/TFT_flash_jpg/jpeg2.h new file mode 100644 index 0000000..1240af7 --- /dev/null +++ b/examples/160 x 128/TFT_flash_jpg/jpeg2.h @@ -0,0 +1,300 @@ +// We need this header file to use FLASH as storage with PROGMEM directive +#include + +const uint8_t Tiger[] PROGMEM = { +0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0xB4,0x00,0xB4,0x00,0x00,0xFF,0xDB,0x00,0x43,0x00,0x04,0x03,0x03,0x03,0x03,0x02,0x04, +0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x06,0x0A,0x06,0x06,0x05,0x05,0x06,0x0C,0x08,0x09,0x07,0x0A,0x0E,0x0C,0x0F,0x0E,0x0E,0x0C,0x0D,0x0D,0x0F,0x11,0x16,0x13,0x0F, +0x10,0x15,0x11,0x0D,0x0D,0x13,0x1A,0x13,0x15,0x17,0x18,0x19,0x19,0x19,0x0F,0x12,0x1B,0x1D,0x1B,0x18,0x1D,0x16,0x18,0x19,0x18,0xFF,0xDB,0x00,0x43,0x01,0x04,0x04, +0x04,0x06,0x05,0x06,0x0B,0x06,0x06,0x0B,0x18,0x10,0x0D,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xC0, +0x00,0x11,0x08,0x00,0xA0,0x00,0x78,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xFF,0xC4,0x00,0x1D,0x00,0x00,0x02,0x02,0x03,0x01,0x01,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x04,0x07,0x00,0x03,0x08,0x02,0x01,0x09,0xFF,0xC4,0x00,0x40,0x10,0x00,0x01,0x03,0x02,0x05,0x02,0x04,0x03,0x06,0x04,0x05, +0x02,0x07,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x11,0x00,0x06,0x12,0x21,0x31,0x07,0x41,0x13,0x22,0x51,0x61,0x14,0x71,0x81,0x08,0x15,0x23,0x32,0x91,0xA1,0x42, +0x62,0xB1,0xD1,0x33,0x52,0xC1,0xE1,0xF0,0x63,0x72,0x16,0x17,0x24,0x34,0x43,0x82,0x92,0xC2,0xFF,0xC4,0x00,0x1B,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x04,0x05,0x02,0x06,0x01,0x00,0x07,0xFF,0xC4,0x00,0x30,0x11,0x00,0x02,0x02,0x01,0x03,0x03,0x03,0x01,0x07,0x04,0x03,0x00, +0x00,0x00,0x00,0x00,0x01,0x02,0x00,0x03,0x11,0x04,0x12,0x21,0x31,0x41,0x51,0x05,0x13,0x22,0x61,0x14,0x23,0x42,0x71,0x81,0x91,0xB1,0x32,0xC1,0xD1,0xF0,0x33,0xA1, +0xE1,0xFF,0xDA,0x00,0x0C,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3F,0x00,0x75,0x87,0x3D,0xB4,0x20,0xC7,0x6D,0xB0,0xDE,0x9E,0x34,0xA7,0xB7,0x7B,0x83,0x81,0xE3, +0x30,0xAD,0xDA,0xBA,0x63,0xB2,0xC8,0x75,0x29,0x56,0x92,0xA4,0x10,0x40,0xFA,0x76,0x3F,0xF3,0xDF,0x00,0xB3,0x5C,0xBA,0xB8,0xF0,0x98,0xA4,0x18,0x6D,0x21,0xC3,0xA1, +0x6E,0xBE,0x6C,0x52,0x3B,0x9B,0x5F,0x73,0xFF,0x00,0x36,0xC0,0x6A,0x3B,0x49,0xCA,0xF4,0x79,0x2F,0x2A,0x58,0x99,0x29,0xD7,0x37,0x56,0x91,0xE7,0x59,0xE1,0x29,0x1D, +0xAF,0xFD,0xFB,0x63,0xF3,0x21,0x4F,0xC7,0x3D,0xCF,0x69,0xD5,0x6F,0x00,0xFD,0x21,0xFC,0xC7,0xD4,0x98,0x54,0x19,0xEC,0xD3,0x13,0x19,0xD9,0x95,0x17,0x9C,0xB1,0x89, +0x19,0x3B,0xB6,0xDD,0xFF,0x00,0xC4,0x51,0x3B,0x01,0xED,0x84,0xB6,0xBA,0xB9,0x9F,0xA0,0x4D,0x0D,0x55,0x72,0xF5,0x32,0x74,0x17,0x56,0x50,0x92,0xA6,0x14,0x82,0xA1, +0xB9,0xDF,0x73,0xF2,0xE3,0x0B,0xB5,0xCA,0xEC,0x7A,0x45,0x6C,0x29,0xE7,0xDB,0x45,0x42,0x5A,0x8A,0xE5,0x49,0xD9,0x76,0x3C,0x0B,0x7B,0x01,0x60,0x07,0xA2,0x46,0x2C, +0xFC,0x85,0x12,0x4E,0x61,0x8C,0xC3,0xF1,0xD9,0x4D,0x46,0x9E,0xE9,0x50,0xD6,0x0A,0x75,0x80,0x8B,0xEA,0x3A,0x49,0x1D,0xC5,0xBE,0xA9,0xFA,0x75,0x1A,0x3F,0x49,0x55, +0x4C,0x91,0x96,0x32,0x16,0xAB,0xD4,0x18,0xB6,0x41,0xE2,0x15,0xCB,0x13,0xBA,0x69,0x9C,0x5D,0x6A,0x32,0xE9,0x8A,0xA3,0xD5,0x1A,0x6C,0x15,0xC2,0x5E,0xA4,0xDC,0x1B, +0x59,0x48,0x23,0xCA,0x41,0x24,0x7A,0x1D,0xF7,0x18,0x25,0x5F,0x89,0x91,0xEB,0x5E,0x3C,0x14,0x57,0xA2,0xB5,0x3D,0x94,0x84,0x25,0x0B,0x74,0x58,0x11,0x6B,0x02,0x0F, +0xA6,0x90,0x30,0xBD,0xD4,0x2C,0x91,0x4B,0x8E,0xDC,0x7A,0xBC,0x15,0xBF,0x1D,0xB6,0x80,0x71,0x7A,0x54,0x10,0xAD,0x3C,0x94,0x83,0xDA,0xE3,0x8F,0x98,0xC1,0x0A,0xB6, +0x4F,0xE9,0x9C,0x5A,0x53,0xB5,0x0A,0x9C,0x78,0xE9,0x6D,0x60,0x15,0x4B,0x93,0x21,0x45,0x4B,0xF4,0x3A,0x8A,0xBB,0xE1,0x6D,0x4E,0xC4,0x3B,0x2E,0x66,0x38,0xED,0xD7, +0xF9,0x9A,0x4A,0xD7,0x50,0xB9,0x0A,0x20,0xB8,0x09,0xA7,0x39,0x11,0x9F,0x83,0x0D,0xD6,0xA7,0xD3,0x02,0x92,0xCC,0x86,0x0E,0xB5,0xB7,0xA4,0x9F,0x2F,0x37,0x0A,0xB9, +0x20,0x28,0x8B,0x27,0x91,0x73,0xA4,0xA6,0x0C,0x49,0xB3,0xE3,0x46,0x9E,0xFE,0x66,0x64,0xC3,0x8E,0x12,0x97,0x96,0x5D,0x51,0x2A,0x2B,0x04,0x13,0xCF,0x73,0xE8,0x3F, +0xCB,0x8A,0xB6,0x26,0x7D,0xC8,0xF9,0x5F,0xAA,0x6B,0xAB,0xD2,0x22,0x85,0x41,0x42,0x94,0xDB,0x6A,0x69,0x4B,0x04,0x00,0x2D,0xA8,0x02,0x48,0x50,0x3B,0xFA,0x60,0xBE, +0x78,0xFB,0x40,0x26,0x72,0xD0,0x8C,0xAE,0xDD,0x2A,0xA3,0x1C,0xA3,0xF1,0x5A,0x94,0xCA,0xD0,0xE8,0x20,0xEF,0x6B,0xEC,0xA0,0x47,0x6D,0xFB,0xE3,0x2D,0xA2,0x66,0x75, +0x5A,0xD4,0xED,0x3C,0xF8,0xFF,0x00,0x31,0x53,0xA5,0xA8,0x8D,0xC5,0xB9,0x12,0x7D,0x3F,0xAD,0xA8,0xA5,0xE7,0xC8,0xB5,0x4A,0x75,0x2D,0x87,0x63,0x44,0x74,0xA9,0x0C, +0xBC,0x2F,0xAC,0x10,0x42,0x8D,0xBB,0x13,0x72,0x71,0xD7,0xF9,0x6B,0xED,0x31,0xD3,0xFC,0xC5,0x45,0x4B,0xAA,0x9E,0xD4,0x19,0x1E,0x16,0xA7,0x23,0xC8,0x55,0x8A,0x0F, +0xA7,0xBE,0x3F,0x3F,0xE2,0x57,0x32,0x6E,0x6C,0x79,0x65,0x70,0xC5,0x1A,0x63,0x96,0x51,0x46,0xBB,0x24,0xAB,0x7B,0xE9,0x36,0x02,0xC7,0x01,0x66,0xD1,0xEA,0x31,0xA5, +0xAD,0x98,0xCB,0x2E,0x84,0x1B,0x82,0x0F,0x3F,0xF0,0x62,0xE5,0x06,0x8A,0xC6,0xC5,0x1B,0x0C,0x0F,0xD9,0xD9,0x3F,0xA3,0x99,0x6E,0xFD,0xAC,0x73,0x65,0x03,0x35,0xE7, +0x48,0x4E,0xE5,0xC7,0xD8,0x74,0xA1,0x8B,0x3C,0xB6,0xB7,0x17,0xBE,0xC0,0xE2,0x47,0x43,0xE9,0x2E,0xFF,0x00,0xE5,0x33,0xF2,0xDE,0xF0,0x23,0xC6,0x12,0x12,0x94,0xAD, +0xB5,0x94,0xBC,0xFA,0xAF,0x75,0x1B,0xF7,0xB0,0x20,0x0B,0x0F,0x5C,0x24,0xE5,0x1E,0x8D,0xE6,0x4C,0xC3,0xF0,0xD5,0x1A,0xC3,0x6B,0x87,0x0D,0xF5,0x0F,0x05,0x0E,0x9B, +0x39,0x20,0x7A,0x81,0xC8,0x4F,0xAA,0x8F,0xD2,0xF8,0xE9,0x39,0xD4,0x88,0xD9,0x73,0x24,0xC7,0xCA,0xD4,0xE8,0xCD,0xC5,0x6A,0x1B,0x05,0xC2,0xE5,0xB7,0x70,0xF2,0x79, +0x1D,0xCF,0xF6,0xC6,0x75,0x56,0xD3,0x65,0x66,0xB0,0x73,0x88,0xBE,0xA0,0x32,0x2E,0x0F,0x53,0x16,0xDF,0x71,0xF6,0x96,0xCB,0xED,0xB4,0xA7,0x63,0xF8,0x28,0x01,0xED, +0x7A,0x82,0x95,0xE2,0x58,0x8B,0xF7,0x36,0xEF,0xDF,0x12,0x96,0xF8,0x87,0x1A,0x4A,0x0C,0x92,0x12,0xE3,0x61,0x6B,0x0A,0x55,0xFF,0x00,0x89,0x23,0xFA,0x6F,0xF5,0x38, +0x1F,0x22,0x43,0x8A,0xF0,0xD8,0x75,0x44,0xC6,0x08,0x5B,0x84,0xB6,0x78,0x52,0x5C,0x1A,0x7F,0xDF,0x1A,0x66,0xBE,0x17,0x4F,0x9A,0xA9,0x0D,0x23,0x49,0x53,0x68,0x04, +0x8E,0x52,0x53,0xB8,0x3F,0xA0,0xFD,0x31,0xC4,0x32,0xE0,0x32,0x8F,0x3F,0xDE,0x0D,0xB2,0xB8,0xCF,0x89,0x19,0xB9,0x0C,0x54,0x50,0xB9,0xD1,0x9D,0x57,0x92,0x56,0x95, +0xDF,0xF8,0x95,0xED,0x7F,0x61,0x8C,0xC4,0x26,0x69,0x71,0xE3,0x20,0xB8,0xE3,0xEA,0x67,0xC0,0xB8,0x6D,0x90,0x7F,0x3A,0x94,0x90,0x47,0xE8,0x06,0x33,0x1A,0xB7,0x2A, +0x40,0x10,0x37,0xD5,0xB9,0xB3,0x02,0x66,0x1C,0xB5,0x93,0xE9,0x4B,0x76,0x6D,0x66,0xB3,0x25,0x60,0x6E,0xB0,0xB9,0x04,0xEA,0x26,0xFB,0x5B,0xBD,0xCE,0x11,0xE3,0x66, +0xAF,0xB9,0x25,0x47,0x97,0x0D,0x95,0x39,0x42,0x2F,0x16,0x23,0xDC,0x5C,0xF8,0xAA,0x49,0x24,0xEF,0x63,0x7B,0x5F,0xD7,0x9C,0x3B,0x64,0x4E,0x9D,0xC5,0x7A,0xB3,0x36, +0xA7,0x56,0x4B,0xAF,0x2E,0x38,0x4A,0x90,0xCB,0xAE,0xEB,0x0D,0x95,0x02,0x4A,0x97,0xEA,0x6D,0x6D,0xBD,0xF0,0xA7,0xD4,0x16,0x60,0x66,0x3E,0xB1,0xB3,0x94,0x40,0x54, +0x78,0x10,0x46,0x94,0x86,0x5A,0xD9,0x6E,0xDB,0x51,0xBD,0xAC,0x05,0xED,0x6D,0x47,0x80,0x0E,0x3A,0x1D,0x1D,0x60,0xDC,0x54,0x92,0xD8,0xE7,0x3D,0xBF,0x41,0x3A,0x5D, +0x43,0xFD,0xDE,0x40,0xC6,0x62,0x8E,0x7A,0x99,0x1E,0x66,0x66,0x63,0xC3,0x91,0xE1,0xBC,0xF9,0x4D,0xED,0x73,0xA5,0x26,0xDC,0x0F,0x6D,0xF1,0xD2,0x9D,0x0C,0x79,0xD9, +0x9D,0x3D,0xAB,0x40,0xA6,0xCC,0x63,0xE2,0x92,0xB0,0xEC,0x55,0x11,0x70,0xCA,0x37,0x49,0x6D,0x29,0xE4,0xA8,0x6B,0x49,0x3B,0x0B,0x6C,0x38,0xB0,0xC7,0x21,0x57,0x0A, +0x65,0xF5,0x21,0xD8,0xF2,0x9A,0x28,0x4B,0x72,0x92,0xDE,0x94,0x02,0xAB,0x36,0x9B,0x00,0x3C,0xBB,0x93,0xA4,0x6F,0x6E,0xF8,0xE9,0x4E,0x87,0xD7,0x65,0xD0,0xA3,0x4B, +0xA6,0x57,0x7C,0x66,0xDF,0x75,0xEF,0x04,0xBC,0xD8,0x43,0x2A,0x69,0x49,0x56,0x9B,0x8B,0x0B,0x84,0x5C,0x94,0xF7,0xE2,0xFB,0x76,0xE8,0xD3,0xE1,0x83,0x23,0xDA,0xB9, +0x40,0x25,0xE7,0x54,0x8B,0x0A,0x96,0xA9,0x54,0xA9,0xAE,0x22,0x73,0xA6,0x10,0x71,0x48,0x5A,0x75,0x16,0xCF,0x60,0x05,0xB6,0x01,0x49,0x27,0xDE,0xF8,0xE6,0x5C,0xC5, +0xD3,0xFA,0xA6,0x6F,0xCE,0x82,0x35,0x7B,0x36,0x8A,0x7D,0x21,0xB6,0x93,0xF0,0xCD,0x3A,0x8F,0xF0,0xC0,0xE4,0x14,0xDC,0x0E,0xC7,0x7B,0xFA,0x62,0xE6,0xAC,0xE6,0x39, +0x15,0xDA,0xFC,0xA2,0xD3,0x05,0xBD,0x36,0x41,0x52,0x8A,0x81,0x70,0x24,0xF9,0x82,0x81,0x36,0xE7,0x7E,0xFC,0xED,0xEE,0xC9,0x96,0xB2,0x9D,0x16,0xB7,0x25,0x2A,0xAD, +0x86,0xDD,0x6A,0x4B,0x44,0x16,0x08,0x0B,0x41,0x41,0xE7,0x51,0x3B,0x0E,0xC0,0x7C,0xFF,0x00,0x5E,0x7F,0x5D,0xA8,0x65,0xBF,0x75,0x7D,0x7C,0xCA,0x1A,0x34,0x51,0x5E, +0x1E,0x73,0x9C,0x18,0xFD,0x10,0xC8,0x66,0xA1,0x47,0xAA,0x56,0xD3,0x98,0x1F,0x71,0x00,0x19,0x08,0x8D,0xE2,0x23,0xFE,0xD0,0x37,0x00,0x8B,0x73,0x7E,0xF8,0x89,0x96, +0x22,0x74,0xD5,0xA9,0xE7,0x30,0xC1,0x88,0xD2,0x19,0x7D,0x61,0x29,0xF8,0xB4,0x58,0x32,0xE6,0xF6,0x09,0xD5,0xB0,0xBD,0xBB,0x7F,0x6C,0x5C,0x3D,0x42,0xC9,0x7F,0x66, +0x5C,0xB7,0x19,0xAA,0xB4,0x98,0x6C,0xC1,0x44,0x55,0xA9,0x83,0xE1,0xA9,0xC5,0x25,0xE7,0x45,0xD5,0xA7,0x48,0xFC,0xD6,0xB1,0x1F,0xB6,0x29,0x4E,0xAC,0xF5,0x13,0x25, +0xE6,0x3E,0x98,0x42,0xA1,0xD2,0x32,0xE4,0x9A,0x63,0xC9,0x7D,0x2F,0xC2,0x2A,0x68,0x34,0x85,0x35,0xE6,0x05,0x76,0x1D,0x8D,0xAC,0x07,0xCF,0x02,0x6A,0x5B,0x50,0xC0, +0x21,0x6F,0x97,0x53,0x9E,0x3F,0x68,0xD5,0x77,0x04,0x19,0x20,0x71,0xD0,0x62,0x1F,0xCD,0xB9,0xEE,0x3A,0x59,0x4B,0x31,0xFA,0x66,0xBA,0xDA,0x54,0xAF,0x08,0x3E,0xEB, +0x09,0x53,0x64,0xDB,0x6D,0x3A,0x42,0xAF,0xBF,0xCB,0x11,0x32,0x6D,0x4D,0xE7,0xFA,0xAD,0x4F,0xA7,0x56,0x7A,0x61,0x2A,0x96,0xCC,0xA1,0xA0,0xFE,0x77,0x1B,0x41,0x00, +0xE9,0x55,0x88,0xB5,0xAF,0xB1,0xFA,0x62,0xB6,0xCA,0x15,0xA9,0xB9,0x1E,0x84,0xFD,0x49,0x8A,0xE3,0xB1,0xEA,0x05,0xC4,0x29,0x98,0x12,0x0A,0x83,0x2F,0x20,0x8B,0xEF, +0xD8,0x1B,0x5E,0xD8,0x7A,0xCB,0x5D,0x68,0xAF,0xD7,0xAB,0xE8,0x5E,0x5E,0xA8,0xA2,0x89,0x5A,0xD3,0xF8,0x30,0xE6,0x7E,0x3C,0x39,0x6B,0xB7,0xE5,0x04,0xEE,0xDA,0x8F, +0x03,0x7B,0x1D,0xB1,0x9F,0xB2,0xB5,0x4A,0x55,0x17,0x2A,0x3F,0x16,0x4F,0xF1,0x3D,0x6B,0x77,0xF2,0x4F,0x3E,0x38,0x9D,0x75,0x0F,0x2C,0x57,0xC2,0x5F,0xAD,0x30,0xCA, +0x65,0x06,0xDB,0x01,0x90,0xED,0x90,0x00,0xB5,0xEC,0x2E,0x7D,0x79,0x3C,0x61,0x12,0xA9,0x9E,0x8D,0x46,0x94,0xBA,0x35,0x65,0xA6,0x90,0x56,0xAD,0x08,0x73,0x48,0xF2, +0x1E,0xC2,0xE7,0xDC,0x0E,0xFC,0xE1,0x7B,0xA7,0xDF,0x68,0x6A,0xAE,0x69,0x96,0xAA,0x2E,0x76,0xA6,0xA2,0x95,0x55,0xA7,0x3A,0x1B,0x01,0x96,0xCA,0x10,0x55,0xBE,0xD6, +0xBF,0x3F,0xAE,0xD8,0x3D,0xD4,0xBA,0x1A,0x5E,0x44,0x2A,0xB4,0x64,0xB4,0xDC,0x67,0x8A,0x6D,0xA4,0xEC,0x95,0x5C,0x92,0x6D,0xEF,0xA8,0xF7,0xE7,0x18,0xB6,0xC6,0xD3, +0xAE,0xC4,0x3C,0x8E,0xB2,0x36,0xBA,0x97,0xB3,0xEF,0x3A,0x48,0x31,0x18,0x65,0xAC,0xA7,0x50,0x17,0x05,0xC5,0x90,0x52,0xA3,0xB9,0x48,0x59,0xD5,0xDF,0xE7,0x85,0xA9, +0xF3,0x0C,0xC8,0x8E,0x42,0x48,0xB9,0x6F,0x4D,0xEF,0xDC,0xD8,0xF6,0xFA,0x60,0x8B,0x8D,0xBE,0xE6,0x51,0x42,0x22,0x5A,0xCF,0xA1,0x41,0x66,0xF6,0x26,0xC0,0x8F,0xD6, +0xF6,0xC0,0xB7,0x99,0x42,0x29,0x88,0x96,0xD8,0x5F,0x8C,0xB5,0x36,0xA7,0x4A,0x8F,0x60,0x39,0xFD,0xF1,0x0D,0x57,0x36,0x9F,0xA9,0x8B,0x5B,0x66,0xED,0x8A,0x7B,0x08, +0x42,0x04,0x26,0x6A,0x6E,0x36,0xFF,0x00,0x8C,0x13,0xE1,0xA5,0x2D,0xB8,0x87,0x2F,0xAC,0xDA,0xC0,0x8B,0xFA,0xEF,0xFB,0x63,0x31,0x1E,0x85,0x35,0x2E,0xD7,0x42,0x12, +0xE1,0x40,0x0A,0x25,0x41,0x63,0x75,0xA8,0x9B,0x03,0xFB,0x1C,0x66,0x1B,0x64,0x50,0x79,0x12,0x86,0x8A,0xCA,0x99,0x4E,0xF1,0xDE,0x58,0x79,0x7B,0x2B,0xC1,0xA0,0xD2, +0x19,0xA7,0xC5,0x05,0x65,0x43,0x5B,0xEF,0x2B,0x72,0xEA,0xB9,0xBA,0x8F,0xF7,0xEC,0x46,0x39,0xE6,0x5B,0xCE,0xC1,0xFB,0x41,0x56,0x61,0x3D,0x1D,0xA4,0xB7,0x25,0x4A, +0x4F,0xC4,0xB8,0x2C,0x50,0x9D,0xC6,0xDD,0xCD,0xEF,0xFB,0x0D,0xB1,0xD7,0x74,0xFA,0x42,0xE5,0x28,0xA9,0xC4,0x94,0x21,0x80,0x9B,0x94,0x9E,0x4D,0xEF,0x6F,0xD2,0xC3, +0xE4,0x4E,0x2A,0x7E,0xA2,0xE5,0x9A,0x68,0xCC,0xAF,0x54,0x92,0x94,0xB4,0xB7,0xD0,0xA6,0xDC,0xB2,0x6E,0xA5,0x0D,0x8D,0xB6,0xDC,0x76,0x3F,0xEC,0x71,0x47,0x45,0x78, +0x1B,0xB7,0x7E,0x29,0x43,0x52,0x32,0x40,0x1D,0xA2,0x9F,0x4D,0x7A,0x57,0x95,0x69,0xB5,0x23,0x98,0xAA,0x95,0x26,0xAB,0x15,0x47,0x9A,0x2E,0xB6,0xC2,0x12,0xA5,0x25, +0x2A,0x36,0x51,0x29,0x57,0x2A,0x36,0xB7,0xA6,0xD7,0x17,0xC3,0xCD,0x2B,0x2D,0xCA,0x2F,0x38,0xFF,0x00,0xDD,0x32,0xC7,0x88,0xE2,0x92,0xDC,0xA6,0xDB,0xBA,0xDA,0x40, +0x36,0x4D,0xF6,0xDA,0xE3,0x6B,0x9B,0xF1,0xDB,0x9C,0x0E,0xA4,0x52,0x9E,0xA3,0xD2,0x91,0x51,0x2D,0x29,0x96,0xD2,0x3C,0x46,0xC7,0xF1,0x04,0x80,0x2C,0x4D,0xC9,0xFF, +0x00,0x9F,0x2C,0x33,0xD4,0x73,0xCD,0x17,0x28,0xD2,0x9F,0xA8,0x57,0xAB,0x21,0x86,0x14,0x82,0xB4,0x37,0x20,0x0D,0x6A,0x07,0x8B,0x27,0x9D,0xD3,0xB5,0xB6,0xB6,0xDF, +0x2C,0x52,0x3A,0xED,0xC3,0x62,0xF5,0x88,0x7B,0x04,0x1D,0xC6,0x4B,0x81,0x95,0x1B,0x43,0xAA,0x93,0x55,0x78,0x43,0x56,0xAF,0xC3,0x74,0xEE,0xA5,0xDA,0xDB,0x6E,0x6C, +0x4E,0xC7,0xB7,0x6E,0xF8,0x54,0xEA,0x27,0x5B,0xF2,0xDE,0x55,0x84,0xF5,0x36,0x34,0xAB,0xBE,0x84,0x5B,0xC4,0x49,0x1A,0xB5,0x0B,0x82,0x13,0xB5,0xEF,0x84,0xD8,0xFD, +0x6D,0xAF,0x67,0xEA,0x84,0xC8,0xD9,0x66,0x1A,0x11,0x19,0x92,0x03,0x73,0x1D,0x1A,0x4B,0x60,0x03,0xBE,0xDC,0xEC,0x47,0xF4,0xB7,0x7C,0x53,0xD5,0x7A,0x8E,0x43,0x99, +0xD5,0x38,0x70,0x2B,0xDE,0x2C,0x84,0xB5,0x20,0xB7,0x22,0x42,0x4D,0x9A,0x17,0xDB,0x71,0xDC,0x5F,0xF6,0xC2,0x25,0x1A,0xDB,0x0A,0x30,0x3C,0x72,0x71,0xD6,0x34,0xAA, +0x10,0x06,0x32,0x5D,0x5F,0x2E,0xD7,0xBA,0x8B,0x5A,0xA5,0x66,0x1A,0xE4,0xE4,0x44,0xCB,0xCF,0x38,0x1B,0x8B,0x1F,0x7D,0x7A,0x54,0x6E,0x12,0x84,0xF7,0x5A,0xBD,0x7F, +0xB6,0x2D,0x7C,0xC1,0xD1,0xDA,0x2D,0x4D,0xC7,0x2B,0x55,0x48,0xAF,0xCF,0x91,0x11,0x80,0xD4,0x58,0x2C,0xB8,0x1A,0x6C,0x36,0x81,0x74,0x37,0xFB,0x1B,0xF6,0xF3,0x1C, +0x5E,0x19,0x47,0x27,0x53,0xE4,0xC9,0x82,0xCA,0x62,0x47,0x31,0x98,0x48,0x0C,0x10,0x2E,0x10,0x34,0xEF,0xA7,0xD3,0x6C,0x72,0xBF,0xDA,0x8F,0x3C,0xE6,0xAA,0x3F,0x5B, +0x2A,0xB9,0x3A,0x93,0x54,0x91,0x0A,0x99,0x09,0xB6,0x9B,0x0D,0xB3,0x74,0x15,0x15,0x36,0x95,0x92,0x4F,0x3F,0xC5,0xFF,0x00,0x37,0xC7,0xDA,0x74,0xD4,0x6A,0xC8,0xF6, +0xDB,0x68,0x10,0x8E,0xF5,0xD5,0x90,0x46,0x49,0x95,0x66,0x67,0x7E,0x75,0x57,0x30,0x56,0x9C,0xA9,0xD2,0xBE,0x0D,0x41,0xF4,0xB0,0xF4,0x76,0x88,0x52,0x5B,0xD0,0x0A, +0x40,0x49,0x00,0x0B,0x80,0x8D,0x8F,0x7F,0xAE,0x1E,0x7A,0x4B,0x95,0x61,0xD2,0xE0,0xCB,0xCC,0x15,0x3A,0x8D,0x1E,0x4D,0x1D,0xC3,0xA1,0x3F,0x12,0x01,0x0A,0x4F,0x73, +0x73,0xBA,0x14,0x01,0xFD,0xF0,0x81,0x42,0xA8,0x55,0xA7,0x74,0xF2,0xB7,0x0D,0xE7,0x75,0x47,0x61,0x6D,0x48,0x53,0xAE,0xEE,0x75,0x15,0xDE,0xE0,0xF7,0x36,0xD5,0xF3, +0xBE,0x23,0xC1,0xCB,0x0A,0xA9,0xCA,0x34,0xD6,0xAB,0xEC,0xD3,0xD9,0x94,0xE5,0xC3,0x12,0x4A,0x92,0x85,0x1E,0x76,0xED,0x7B,0x14,0x9B,0x7F,0x30,0xC3,0xDA,0x85,0xF8, +0x35,0x45,0xB6,0x81,0x8C,0xF7,0xE3,0x03,0xF6,0x98,0xAF,0x39,0x0C,0x06,0x4C,0xE9,0x6C,0xCD,0x97,0x20,0x56,0x9B,0x8D,0x5C,0xCB,0x35,0x38,0x8F,0x68,0x92,0xDA,0x5D, +0x53,0x4E,0x82,0x00,0xD3,0xA6,0xCA,0x20,0xFC,0xAD,0x7F,0x7C,0x38,0x54,0x2A,0x52,0x2A,0xDD,0x32,0x34,0x61,0x4F,0x7F,0xE2,0x12,0x7F,0x0D,0xD7,0x05,0xBC,0x42,0x9B, +0x1B,0xA7,0x7D,0xC1,0xB0,0xDF,0xDF,0xDF,0x1C,0xF9,0xD2,0x4C,0x89,0x9E,0xA9,0xF9,0xE2,0xB3,0x47,0x11,0x1C,0x5C,0x15,0xD3,0x1D,0x7E,0x43,0xA8,0x57,0xE1,0xA8,0x22, +0xCA,0x6D,0x69,0x3D,0xC8,0x58,0x48,0xF5,0xB6,0xAC,0x5D,0x51,0xAA,0x6B,0x7B,0x2B,0xD3,0xDB,0x64,0xA8,0xA9,0xB4,0xAA,0xCA,0x52,0xCD,0xD2,0x54,0x9D,0x5B,0x7A,0xFE, +0x41,0xDF,0xB9,0xC4,0x8D,0x4D,0x2B,0x52,0x80,0x8D,0xB8,0x1E,0x86,0x4F,0xF5,0x2B,0xAC,0x2A,0x50,0x8C,0x4D,0xB0,0x50,0xA5,0x64,0xFA,0x21,0x37,0x0E,0xA9,0x6E,0x38, +0xA4,0xFB,0x05,0x10,0x71,0x01,0xC2,0x85,0xA9,0x4C,0xB5,0xAC,0xA5,0x6C,0xA9,0xCD,0x40,0xEC,0x90,0x9F,0x5F,0x9E,0x08,0x49,0x7D,0xD6,0x3E,0xEC,0xA7,0xEA,0x68,0x3B, +0xA1,0x0B,0xD2,0x8D,0xED,0x72,0x54,0xAF,0xD9,0x62,0xD8,0x1B,0x70,0xC4,0x47,0x14,0x38,0xF8,0x32,0x00,0xF9,0x9F,0xF7,0xC4,0xAB,0x49,0xA8,0x9F,0x3C,0x49,0xAA,0xC3, +0xDD,0x50,0xC3,0xA4,0x87,0x4F,0x85,0x21,0xB9,0x05,0xE4,0x4C,0x52,0x00,0x7D,0x22,0xC1,0x00,0x95,0x24,0x1D,0x40,0x5F,0xB5,0xAE,0x77,0xC6,0x63,0xC3,0xF3,0xD6,0xD3, +0x01,0xD2,0xB0,0x3C,0x45,0xF7,0xD8,0x1D,0xBB,0xE3,0x30,0xDB,0x56,0xED,0xCA,0xC2,0xE8,0xED,0x01,0x4E,0xE9,0xD6,0x93,0x62,0xB9,0x4F,0xA5,0x2D,0x0D,0x28,0x21,0xA0, +0x92,0x91,0x60,0x77,0xF5,0x27,0x14,0xC6,0x6F,0x69,0x32,0xAB,0x69,0x8F,0x09,0xB2,0x64,0x48,0x5F,0x95,0x29,0x49,0x04,0x20,0x7E,0x72,0x4D,0x8D,0x86,0xD7,0xF7,0xB6, +0xD7,0xC5,0xDB,0x59,0x21,0xD6,0x86,0xB4,0xAF,0xC9,0x77,0x0A,0x54,0x40,0x00,0x03,0xB0,0xDF,0x6B,0xFF,0x00,0x41,0xBE,0x28,0x47,0x2A,0xD5,0x0C,0xC9,0x9B,0x6A,0xB4, +0xF8,0x35,0x05,0x31,0x25,0xA5,0x84,0xB4,0xB8,0xA9,0x00,0x58,0x9D,0x85,0xB7,0xD4,0x93,0x6B,0xDC,0xD8,0x6D,0x70,0x3D,0x5E,0xAA,0x83,0xBB,0x22,0x5C,0x7B,0x40,0x19, +0x31,0x8E,0x5C,0xEA,0x7F,0x89,0x1E,0x87,0x2A,0x9A,0xB7,0x12,0x84,0xFF,0x00,0x86,0x8B,0x12,0x0F,0xF3,0x13,0x72,0x3E,0x43,0x7E,0x7E,0x58,0xE5,0x8E,0xAE,0xA6,0xB3, +0xD4,0x7E,0xB8,0x47,0xCB,0x70,0x19,0x08,0xF0,0x6C,0xD2,0x11,0x6B,0x04,0x0F,0x7B,0x5F,0x80,0x06,0x2F,0x3C,0xCB,0x5F,0xA1,0xF4,0xA2,0x8C,0xFC,0xEA,0xAC,0xCF,0xBC, +0xB3,0x03,0xA9,0x21,0x11,0xD0,0x3C,0xA9,0x51,0x17,0x37,0xE0,0xDB,0x8D,0xB6,0x1C,0x73,0x81,0x1D,0x14,0xE9,0xD5,0x5A,0xA0,0xF4,0xAE,0xA4,0x66,0x62,0xDA,0xA6,0x54, +0x54,0xA7,0x9B,0x2E,0x91,0x74,0x36,0x77,0xD4,0x7D,0x2E,0x3F,0x61,0x87,0x51,0x4E,0x9D,0x4D,0xC4,0x73,0xDB,0xF3,0x81,0x46,0xDE,0xDB,0x73,0xC4,0x64,0xC8,0x5D,0x37, +0xA6,0x65,0x1C,0xB4,0xDD,0x19,0x96,0x87,0x8B,0xA7,0xF1,0x5D,0xB7,0xF8,0x8A,0x3C,0x9B,0x9F,0xF9,0xB6,0x38,0xE7,0xAA,0x39,0x22,0xA5,0x92,0xBA,0x93,0x3E,0x0C,0x96, +0x9C,0x31,0xD6,0xE2,0x9D,0x8C,0xFD,0xB6,0x71,0xB2,0x49,0x1B,0xFA,0x8E,0x0E,0x3A,0x17,0xA9,0x3F,0x68,0xA6,0x28,0x19,0x91,0x34,0x9C,0xAB,0x0E,0x2D,0x41,0x96,0x54, +0x03,0xEF,0xAD,0x77,0x4A,0xAD,0xC8,0x41,0x1F,0xD7,0xF6,0xC2,0xE5,0x5F,0xAE,0xF9,0x55,0xFC,0xC4,0xC0,0x99,0x4D,0x4D,0x5E,0x99,0x29,0x84,0x29,0x6D,0x3A,0xD0,0x2B, +0x88,0xE9,0x27,0x5A,0x49,0x50,0xF3,0x0E,0x38,0xC6,0x34,0x6B,0xAC,0xD3,0xB9,0xB4,0xA6,0xED,0xD1,0x8B,0x1E,0xAB,0x06,0x33,0x8C,0x4E,0x82,0xFB,0x29,0x67,0xCF,0xFC, +0x5B,0xD3,0xAF,0x84,0x79,0x0A,0xF8,0xEA,0x3F,0x86,0xC2,0xC2,0xB7,0x52,0xD3,0xA0,0x58,0xFE,0xCA,0xC5,0x9B,0x9E,0x3A,0x41,0xD1,0x79,0xF2,0xEA,0x3D,0x46,0xEA,0x15, +0x26,0x13,0x6E,0x2D,0xA4,0x19,0x32,0x67,0x3A,0x50,0x84,0x84,0xA0,0x25,0x3B,0x5E,0xD7,0xB0,0x1F,0xA6,0x39,0x1B,0xA4,0x35,0x5E,0xA4,0xE4,0xBC,0xC5,0x9B,0x6A,0xBD, +0x3E,0xCA,0xEE,0xD5,0xCC,0x8A,0x9B,0x6D,0x86,0x10,0xC2,0x9C,0x4A,0x1A,0x21,0x6B,0x49,0xB0,0xE2,0xE9,0x29,0x00,0x9D,0xB1,0x62,0x66,0x3E,0xBD,0x65,0x7E,0xAA,0x65, +0x7A,0xEE,0x48,0xEA,0xF6,0x57,0x99,0x43,0x99,0x4D,0x2D,0x48,0x65,0x88,0xEA,0x5F,0x88,0x4A,0x5C,0x48,0x71,0x3A,0x4E,0xE1,0x61,0x2A,0x57,0x23,0x8B,0xFA,0x62,0x9E, +0x96,0x94,0xE4,0x8E,0x9E,0x24,0xFB,0x98,0x83,0x2A,0x39,0xF5,0x4C,0x99,0x52,0xA3,0xE7,0x8A,0x8E,0x54,0xCA,0xCA,0x67,0x28,0xD3,0x1D,0x65,0xB8,0x6E,0x06,0xCD,0xDF, +0x71,0x4A,0x29,0x41,0x70,0x5E,0xE0,0x12,0x36,0xF6,0x1E,0xB8,0x45,0x25,0xC9,0xA2,0x4B,0xE9,0x86,0xD3,0x29,0x65,0x0C,0x3A,0xB0,0xEB,0x21,0x5E,0x52,0x8B,0x15,0x11, +0x6B,0xEA,0x4E,0xF7,0xF6,0x4E,0x3A,0xF3,0xA8,0x39,0x07,0xA5,0xD9,0x2E,0x83,0x91,0x9F,0xC8,0xD4,0x64,0x8C,0xB7,0x99,0xEA,0x6C,0xB3,0x50,0x71,0x32,0x1C,0x5B,0x72, +0x19,0x5B,0x77,0x6C,0x28,0x28,0x91,0xC9,0xD4,0x0F,0x20,0x8D,0xB9,0x38,0xA8,0xFA,0xCF,0x43,0x6F,0x23,0x75,0x72,0xA7,0x47,0xA7,0x53,0xD6,0xAF,0x05,0x2D,0x29,0x0B, +0x29,0xD9,0xD8,0x8E,0x28,0xAD,0xBF,0xFF,0x00,0x2A,0x0B,0x6A,0xFD,0xEC,0x3D,0x70,0x9E,0xAF,0x47,0xEC,0xEE,0x74,0x1D,0x7E,0xBD,0x3F,0xDC,0x47,0x34,0xDA,0x93,0x66, +0x11,0x8C,0x49,0xCA,0xB9,0x87,0xA8,0x03,0x3A,0xC1,0xCB,0xF0,0x66,0xB3,0x49,0xA8,0x68,0x4C,0x78,0x73,0x02,0x35,0x25,0x5E,0x22,0x4E,0x94,0x38,0x91,0x74,0xA9,0xA5, +0x11,0xA4,0xEC,0x74,0xDC,0x1E,0xD8,0xB8,0xB2,0xDD,0x29,0xE8,0x59,0x58,0xC0,0xAF,0x40,0x4C,0x7A,0x8B,0x48,0x4B,0xAB,0x49,0xDB,0xCA,0x11,0xC2,0x6C,0x7B,0x05,0x14, +0x9F,0xAE,0xFB,0x1C,0x50,0x6F,0xE7,0x55,0xD0,0xB3,0x7C,0x69,0x54,0xC8,0xEA,0x2D,0xC7,0x29,0x91,0x16,0x42,0x01,0x2E,0x44,0x78,0x6F,0x61,0xEA,0x80,0xA4,0x6E,0x9F, +0x4C,0x75,0x20,0xA6,0xC0,0xCC,0xA4,0xF5,0x0A,0x0B,0xEB,0x5D,0x16,0xB3,0x4B,0x45,0x55,0x0D,0x07,0x42,0x04,0x67,0x6E,0x02,0xDA,0x04,0xFA,0x2F,0x51,0x23,0xE7,0x80, +0x0D,0x39,0xBB,0x4E,0x70,0xB8,0x23,0x90,0x3F,0x98,0x9F,0xA9,0x81,0xBB,0x24,0xC4,0x09,0x76,0x7A,0xB0,0x8A,0xAB,0x88,0x5F,0x82,0x87,0x83,0x60,0xDC,0x02,0xA4,0x70, +0x3F,0xA7,0xF4,0xC7,0xAA,0xD3,0x80,0x31,0x20,0x30,0x9D,0x04,0xA5,0x28,0x4A,0x51,0x6F,0x28,0xBF,0x6B,0xFB,0x61,0x87,0x32,0x65,0x78,0x02,0x20,0xA9,0x51,0x6A,0x3E, +0x3D,0x39,0xC4,0x83,0xAD,0xF0,0x75,0x25,0x42,0xC1,0x43,0x6B,0xF0,0x7E,0x5F,0xD3,0x0A,0xF5,0x36,0xD9,0x90,0x8F,0x19,0xA9,0x61,0x69,0x53,0x9A,0x94,0x94,0x20,0x92, +0x8B,0x1B,0x77,0xF9,0xFE,0xD8,0x85,0x7D,0x2D,0xB8,0x6E,0xFA,0x48,0xEC,0x4E,0x49,0x30,0x1C,0xD6,0x9F,0x90,0xD4,0x76,0x16,0x52,0xDA,0x00,0x2A,0xD6,0x6E,0x48,0x37, +0xF4,0xF9,0x63,0x30,0xC1,0x0A,0x0D,0x16,0x6C,0xC4,0x25,0xD4,0x4B,0x9C,0xA6,0xAC,0x52,0xD2,0x12,0x10,0x8B,0x8D,0xC6,0xA2,0x4F,0x00,0xDC,0x9E,0x05,0x87,0x38,0xCC, +0x38,0xAA,0xDD,0x01,0x1F,0xBC,0x1D,0x76,0x15,0x18,0xC4,0xBB,0xFA,0x95,0x9B,0xCC,0x5A,0xBD,0x3F,0x28,0x50,0x58,0x71,0xF9,0x12,0x55,0xE1,0xAF,0xC2,0x4D,0x94,0x96, +0xFB,0xAB,0x7E,0x00,0xE7,0xDF,0xDF,0x8C,0x49,0xA5,0xE4,0xBC,0x9B,0xD3,0xF8,0x6A,0xAE,0x19,0x28,0xA6,0xBA,0xB4,0xF8,0x92,0xA6,0xC8,0x78,0x92,0x4D,0xB7,0xDD,0x47, +0x8F,0xA0,0xC1,0xFC,0xA5,0x94,0x8A,0x24,0x3B,0x9A,0x6B,0x2D,0x87,0xA7,0xBC,0x48,0x61,0x97,0x2D,0xF8,0x48,0xDB,0x61,0xE8,0x4F,0x72,0x3B,0x7B,0x13,0x7E,0x6C,0xFB, +0x60,0x67,0x56,0xD1,0x06,0x36,0x5D,0x62,0xA8,0x95,0x49,0xF1,0xC1,0x91,0x12,0x3B,0xDF,0x95,0x2A,0x41,0xFC,0xE0,0x6F,0xBF,0xEF,0xBE,0x3A,0xCA,0x74,0x8A,0x06,0xE3, +0x29,0x35,0xC5,0x8E,0xD1,0x23,0xD4,0xF2,0x7B,0xDD,0x6B,0xFB,0x41,0xC0,0x83,0x40,0x4B,0xB3,0x28,0x31,0x02,0x57,0x22,0x68,0x68,0xF8,0x7A,0x0F,0x9A,0xFF,0x00,0x5F, +0xF5,0xC5,0xB9,0xF6,0x9E,0xAC,0x3D,0xD3,0x1E,0x82,0xC5,0xA2,0x51,0xDB,0x53,0x2B,0xAA,0x2B,0xE1,0x0B,0xE8,0x1A,0x74,0x21,0x29,0xB9,0x17,0x16,0xDC,0x8D,0xBE,0x57, +0xC1,0x5F,0xB3,0x64,0xE8,0x10,0x3A,0x37,0x4A,0x76,0x95,0x4E,0xF8,0x30,0xB6,0xFC,0xC1,0x6A,0x2A,0x2A,0xDF,0x72,0x2F,0xBD,0xAF,0x7C,0x22,0x7D,0xAA,0x2A,0xF4,0x6E, +0xAB,0x66,0x9C,0x97,0xD3,0x6A,0x3D,0x65,0x87,0x6A,0xAA,0x9E,0xAF,0x89,0x6A,0x3A,0x83,0x81,0x84,0x11,0x62,0x55,0x6E,0x08,0xB1,0x36,0xE7,0x0C,0x0A,0x14,0xFD,0xE3, +0x0E,0x07,0x49,0x95,0xB7,0x9D,0x99,0x9C,0x8D,0x90,0x3A,0x71,0x59,0xEA,0x26,0x64,0x51,0x5F,0x89,0x1E,0x98,0xD1,0xBC,0x89,0xA4,0x6C,0x3F,0x94,0x13,0xC9,0xC3,0xD7, +0x50,0xFA,0x45,0x45,0x4D,0x2A,0x2C,0xBA,0x14,0xB8,0xB0,0x60,0xC4,0x49,0x41,0x70,0xB7,0x77,0x1E,0x55,0xEC,0x75,0x28,0x90,0x0E,0xE3,0x6F,0x9E,0x2F,0xB6,0xB2,0x35, +0x3A,0x91,0x4A,0xA9,0xE4,0x8C,0xBF,0x29,0x0D,0x33,0x47,0xF0,0x94,0xEA,0xE2,0xAC,0x07,0x1D,0xD8,0x2C,0x85,0x7A,0x15,0x10,0x41,0xC5,0x55,0xF6,0x92,0x08,0x39,0x7E, +0x87,0x96,0xE2,0x2D,0xF8,0xB3,0xDF,0x79,0xB7,0x57,0x11,0xC2,0x6C,0x42,0xC1,0xD3,0xB9,0xE2,0xCA,0x49,0xDB,0xB6,0x21,0x59,0x6E,0xA2,0xDD,0x48,0xDA,0x76,0x81,0xFF, +0x00,0x52,0xC5,0x6D,0x52,0xA6,0x31,0x9C,0xCF,0x9D,0x13,0xCE,0xD9,0xC3,0xA3,0xF3,0xEB,0x39,0xA9,0x88,0x13,0xF3,0x0D,0x11,0xA6,0xD2,0xC5,0x40,0x8B,0xA7,0xE1,0xD2, +0x93,0x64,0xA8,0x85,0x5B,0xD7,0x63,0xDF,0x0E,0xDD,0x41,0xEB,0x97,0x47,0xF3,0xAB,0xAD,0x55,0xAB,0xF9,0x0A,0x4C,0x2A,0xD3,0xA8,0x09,0x8F,0x51,0x54,0x64,0x87,0x00, +0x20,0x79,0x94,0xA6,0xD6,0x14,0xA0,0x3D,0x2E,0x6E,0x2E,0x3B,0x9C,0x55,0xD9,0x7F,0x34,0x42,0xCA,0x32,0x27,0xD2,0xEB,0xCF,0xCF,0x93,0x97,0xAA,0xF4,0xB3,0x41,0xAB, +0xAD,0x9B,0x95,0xC6,0x70,0x5C,0x07,0xB4,0x9D,0x95,0xA4,0x93,0xC7,0x65,0x1E,0x70,0x12,0xAF,0x07,0x33,0xBF,0x40,0x42,0x58,0xCA,0xE2,0xB1,0x1E,0x08,0x2D,0xB1,0x98, +0xE2,0x85,0x39,0x13,0xC3,0x03,0x67,0x3C,0xA9,0x36,0x36,0xB5,0xC1,0x22,0xC7,0x9F,0x4C,0x52,0xD3,0x5C,0xCD,0x52,0x90,0xA0,0xF9,0xED,0x11,0xD4,0x56,0x05,0x87,0x92, +0x27,0x53,0xC6,0x81,0x0B,0x37,0xE4,0xAE,0x9F,0x35,0x45,0xAA,0x42,0x9D,0x43,0xA3,0xD5,0x5A,0xAB,0x48,0x59,0x25,0xB6,0x92,0xDA,0x50,0xAB,0xA1,0x08,0xDE,0xDE,0x73, +0x7D,0x1F,0xC2,0x76,0xD8,0x00,0x31,0x54,0x75,0x9F,0x38,0x2F,0x35,0x7D,0xA9,0x04,0xCA,0x43,0x8D,0x3B,0x05,0xCA,0x52,0x62,0x2D,0x0B,0x37,0x28,0x4B,0x6B,0x2B,0x0A, +0x23,0x84,0x92,0xBE,0x37,0xED,0xF2,0xC3,0x3F,0xD9,0xA9,0x74,0xF8,0x39,0x1F,0x30,0x64,0x9A,0xAC,0xD6,0x1D,0x93,0x0D,0x83,0x3E,0x3B,0x8D,0x2C,0x9F,0x19,0xA5,0x02, +0x54,0x9B,0x7A,0x83,0x62,0x7F,0xEF,0xC2,0x6C,0x7A,0x2D,0x26,0x6D,0x41,0xE7,0x56,0x14,0x1D,0x71,0xC0,0xF0,0x74,0x91,0x65,0x2C,0x70,0x0E,0xF7,0x21,0x22,0xD6,0x16, +0xFF,0x00,0x65,0x7D,0x56,0xE6,0xAD,0x3D,0xBF,0x23,0x10,0x9A,0x0A,0xF2,0xC5,0xBC,0x4A,0xAE,0xA9,0x4F,0x10,0x6A,0xCE,0xBA,0x1C,0x69,0x87,0xD9,0x74,0x1B,0x1E,0x09, +0x07,0x5E,0xDF,0x3B,0x94,0xDB,0x16,0x66,0x4D,0xA9,0xBB,0x99,0x32,0x95,0x33,0x2F,0xBE,0x99,0x0B,0xA5,0xD2,0x96,0xE2,0x20,0xC3,0x65,0xCD,0x28,0x52,0x8A,0x8A,0xCA, +0x96,0x6C,0x4A,0x80,0x0A,0x36,0x1F,0xCA,0xAD,0xEF,0x7C,0x06,0xCC,0xB4,0x18,0xCD,0x57,0x98,0x88,0x86,0x8A,0x03,0x81,0x20,0xBA,0xE0,0xB1,0x51,0x2A,0xDC,0x9E,0x6C, +0x0D,0xCE,0xFB,0x77,0xDB,0x12,0x7A,0x7C,0xC5,0x46,0x95,0x94,0x1A,0x9F,0x1A,0xA0,0x22,0xC8,0x92,0xE9,0x4B,0x4D,0xA1,0x24,0xA5,0x09,0x4D,0xC0,0x02,0xC0,0xD8,0x5D, +0x4A,0xF9,0xDC,0x9E,0x4E,0xF2,0xE8,0xB4,0xAD,0x4C,0x43,0x60,0x9E,0x23,0x1E,0xA3,0x8F,0x88,0x96,0xBC,0x60,0x22,0x52,0xEA,0x54,0xB7,0x69,0x12,0x51,0x19,0xF4,0x38, +0xB6,0x9E,0x54,0xA4,0xA9,0x01,0x7A,0x4E,0x93,0xA7,0xC3,0xB8,0x07,0xE7,0xD8,0x7C,0xF0,0xB8,0x88,0x54,0xF9,0xAE,0xB7,0x10,0x29,0xF6,0x02,0x98,0x0F,0x3A,0xEE,0xB4, +0x59,0x3B,0xA6,0xE7,0x7B,0x58,0x73,0x7D,0xEF,0xE9,0x83,0x15,0x70,0xEC,0xAC,0xA2,0xD2,0xA5,0xCF,0x31,0x63,0x34,0xB0,0x5D,0x71,0x57,0x25,0x5B,0x6E,0x12,0x3B,0x9E, +0x2C,0x3F,0x5C,0x00,0xA4,0x56,0xA3,0x07,0xD2,0x8A,0xAC,0x06,0x64,0xD3,0xD0,0x90,0xC2,0xDA,0xD3,0x6D,0x41,0x5A,0x41,0x51,0x3C,0xEA,0xEE,0x3D,0x3B,0x77,0xC4,0xB7, +0x56,0x20,0x09,0x15,0x90,0x06,0x35,0x99,0xB2,0x44,0xEA,0x2C,0x5A,0x67,0xDD,0xF1,0xA6,0x4E,0x2C,0xAD,0x41,0x2F,0x3E,0xE4,0x70,0x16,0xF8,0xBF,0xA8,0x5D,0xC0,0xE3, +0xCB,0x63,0x7E,0x4F,0x6B,0x66,0x02,0x66,0x3A,0x64,0x48,0x33,0x24,0x53,0xD8,0x4A,0x92,0x95,0x9F,0x1A,0x33,0x88,0x37,0x4A,0xD0,0x77,0xDE,0xFB,0x83,0x6D,0xAD,0xEA, +0x0E,0x33,0x1E,0x65,0x81,0xE9,0x14,0xDA,0x80,0x90,0xE3,0x91,0x3B,0x46,0xB9,0x51,0x79,0x8C,0xBB,0x26,0x5B,0x12,0x9B,0x43,0x85,0x3A,0x12,0xE1,0xB0,0x4B,0x63,0xB9, +0xBF,0xA0,0xDC,0xE3,0xF3,0x9B,0xAB,0xD9,0x6E,0x2B,0xBD,0x4B,0x12,0x3E,0x2D,0xE9,0x8F,0xCF,0x96,0x02,0xD6,0x91,0xA8,0xA9,0x4A,0x36,0xB6,0xF8,0xED,0xFC,0xFB,0x55, +0x62,0x7C,0x75,0xD2,0x59,0x70,0x29,0x9D,0x3A,0x74,0xA9,0x41,0x29,0x57,0x3C,0x93,0xB0,0x1B,0x9D,0x8F,0x38,0xA4,0xF3,0x76,0x50,0xA5,0xBB,0x49,0x76,0x4D,0x42,0x32, +0x94,0xF3,0x88,0x5A,0x52,0x9D,0xDB,0x5B,0xF7,0x16,0x28,0x4A,0xAD,0x74,0xA0,0x8D,0x94,0xAE,0x48,0x3A,0x47,0x73,0x8E,0xFE,0xC3,0xD8,0x46,0xAA,0x6D,0xBC,0xC8,0xD4, +0xDC,0xFF,0x00,0x44,0x8B,0xF6,0x62,0xA9,0xC5,0x5C,0x9A,0x84,0x58,0x54,0xFB,0x40,0x6A,0x5C,0x20,0xA6,0xDC,0x16,0xB2,0x50,0xEA,0x7D,0x2F,0xB1,0x23,0xDC,0xE2,0x88, +0xE9,0x9F,0x4F,0x33,0x9D,0x67,0xAE,0x51,0x69,0xF4,0xAA,0xBF,0xDD,0x75,0x16,0x90,0x67,0xC7,0xA8,0x12,0x16,0x16,0x9B,0x79,0x5C,0x45,0xFF,0x00,0x38,0x37,0xF7,0xE4, +0xE0,0xAC,0x8A,0x76,0x73,0x9F,0x0D,0xCA,0x46,0x64,0x90,0xCB,0x99,0x78,0xB8,0x08,0xA7,0xD3,0xCA,0x5A,0x4B,0x76,0xFC,0xBA,0x6D,0xC8,0x16,0xE0,0x93,0x7E,0x4D,0xCE, +0xF8,0xB1,0x1B,0x6E,0xAC,0xFE,0x44,0xA6,0xA7,0x23,0xD3,0x9C,0x6E,0xB5,0x42,0x5A,0x57,0x4E,0x98,0xE3,0x89,0x53,0xC9,0x4F,0x0A,0x42,0x92,0xBE,0x52,0x41,0x3B,0x6E, +0x36,0xF6,0xC0,0xC5,0xAB,0x8D,0x80,0xC3,0x0F,0x8E,0x71,0xDE,0x22,0x51,0xB2,0x97,0xDA,0x09,0x1D,0x43,0xCE,0x74,0xB8,0x12,0xDF,0x72,0xA8,0x82,0x17,0x55,0x2E,0x2D, +0x03,0xE2,0xC1,0x55,0xD2,0x50,0x54,0x2D,0xE6,0x1B,0x8B,0x5B,0x6D,0xB1,0x60,0xE7,0x3C,0x9B,0x51,0xEA,0xB6,0x72,0xA1,0x75,0x07,0x2A,0xC4,0x6E,0x4B,0x8C,0x46,0x4C, +0x2A,0xED,0x19,0xC7,0xD2,0xD4,0x88,0x52,0x59,0xBE,0xC5,0x27,0x71,0x7B,0x6C,0x6D,0xDB,0x0E,0x94,0x1C,0xC5,0x51,0xCB,0xB9,0x9D,0x39,0xFB,0xA9,0xF5,0x98,0x14,0xB1, +0x22,0x02,0x20,0xCA,0x8A,0xC2,0x6E,0xA7,0xDE,0x42,0x89,0x49,0x40,0x4F,0xE6,0x36,0x3C,0x76,0xF9,0x60,0x63,0x59,0x23,0x2C,0xF5,0xAF,0xA8,0x93,0x33,0xA7,0x4A,0x33, +0x45,0x5B,0x2C,0xD6,0x98,0x5A,0x53,0x52,0x84,0xB0,0xB8,0xEA,0x94,0x8B,0x5B,0x58,0x09,0x52,0x4A,0x6E,0x36,0x3D,0x8D,0xBB,0x6F,0x7F,0x0A,0x8B,0x15,0x8F,0x99,0xA0, +0xE5,0x58,0x1F,0x12,0x80,0x7D,0x99,0x12,0xAB,0xF5,0x86,0x23,0x26,0xA5,0x19,0xC5,0xC8,0x2E,0x3F,0x4E,0x92,0x94,0x87,0x19,0x5E,0xE1,0x49,0x20,0xF6,0xBF,0xF1,0x0F, +0x4C,0x58,0xDD,0x23,0xAA,0xC9,0xC8,0x52,0x27,0x2C,0x3C,0xF2,0xE9,0x73,0xD8,0x5B,0x53,0xA2,0x36,0xAD,0x9C,0xF2,0x90,0x08,0x1F,0xE6,0xDF,0xB7,0xFA,0xE2,0x46,0x73, +0xE9,0x5E,0x7C,0xA7,0xE6,0x05,0x37,0x57,0xA1,0xD7,0x2B,0x69,0x8D,0x71,0x1A,0x7C,0x95,0x47,0x6D,0xDD,0x27,0xFE,0xA2,0x5C,0x25,0x47,0xD2,0xE3,0x12,0x68,0xD4,0xB7, +0x69,0xF4,0x35,0xB3,0x55,0x86,0xC4,0x39,0x4A,0x46,0xA1,0x1D,0x4F,0xA5,0xE5,0x81,0x7D,0xB5,0xAA,0xC0,0x1F,0x40,0x00,0xF5,0x37,0xDB,0x10,0xCD,0xED,0x43,0xF0,0x65, +0x7F,0x6D,0x6D,0x4C,0x19,0x58,0xD0,0xE5,0xD6,0x59,0xCC,0xAD,0x4E,0xA6,0xFC,0x55,0x39,0x5A,0x94,0xD2,0xF4,0x9F,0x32,0x9B,0x37,0xD9,0x56,0xE7,0x6B,0x7E,0x98,0xBE, +0x29,0x74,0xB2,0xD5,0x2D,0xB5,0x85,0x29,0x0B,0x4A,0x00,0x50,0x52,0x74,0xDE,0xFF,0x00,0xBE,0x06,0x51,0x32,0xB4,0x65,0xC6,0x12,0x1F,0x69,0x3A,0xDC,0x37,0x52,0x49, +0x17,0xFD,0x70,0xEA,0xC4,0x76,0x9A,0xCB,0xF2,0x16,0x1B,0x51,0x17,0xB6,0xFB,0x58,0x58,0x0E,0x3E,0x98,0xC6,0xBB,0x54,0xB7,0xB0,0x20,0x4F,0x74,0xF5,0x1A,0xC1,0x11, +0x07,0x31,0x53,0xBE,0xF1,0x53,0x08,0x16,0x70,0x92,0xA0,0xA5,0x0B,0xD9,0x00,0x8B,0xDF,0xD8,0xED,0xDF,0x13,0x28,0x89,0xA7,0x52,0xB2,0x84,0x67,0x2A,0x75,0x14,0x33, +0x19,0x08,0xF0,0xEC,0x82,0x52,0xB7,0x56,0x9D,0xEC,0x90,0x05,0xEC,0x38,0x2A,0xE3,0x6C,0x19,0x44,0x45,0xB3,0x4C,0x5C,0xC5,0x36,0x15,0xBE,0xFC,0xD9,0x3F,0xF3,0xFD, +0x30,0x9F,0x59,0xA8,0xA9,0xF8,0x0D,0x45,0x95,0x20,0x3E,0x12,0xA5,0x29,0x8B,0xA0,0x79,0x00,0xF2,0xE8,0x4F,0x1A,0x46,0x94,0xA0,0xDB,0x7B,0x9B,0x9E,0xF8,0x9C,0xF5, +0x82,0xB9,0x3D,0xB9,0x8B,0x7A,0x88,0x2C,0xA2,0x4D,0xAD,0xE6,0x09,0x23,0x2F,0xA1,0x6C,0x4A,0x09,0x43,0x8F,0x2D,0xBF,0x05,0x5A,0x55,0xB2,0x8E,0xC0,0x5D,0x37,0xB8, +0xE6,0xE0,0xE0,0x32,0x2A,0xB2,0x58,0x60,0x30,0xCA,0xD6,0x94,0x36,0x91,0xA0,0x92,0x7B,0xFA,0xDA,0xD8,0xD5,0x34,0xC4,0x35,0x38,0xEC,0x49,0x48,0x6D,0x94,0xD9,0xFF, +0x00,0x1F,0xC3,0xD7,0x65,0x29,0x09,0x00,0x5B,0xD8,0xDC,0xDB,0x1E,0x65,0xC7,0x96,0xF8,0x4B,0x07,0xE1,0xDA,0x5E,0xE9,0xBA,0x97,0x64,0x27,0x7B,0xDE,0xFB,0xED,0xDF, +0x01,0x73,0xBB,0x91,0x23,0xDE,0x80,0x39,0x71,0xD3,0xFF,0x00,0x24,0xF8,0xD5,0x37,0x64,0xD3,0x97,0xE2,0x3C,0x7E,0x30,0xA9,0xB2,0x16,0xB5,0x2A,0xC9,0x4E,0xB4,0x83, +0xEF,0x6E,0x6E,0x3D,0xF1,0x98,0x80,0x90,0x93,0x19,0x2D,0xC4,0x42,0x1F,0x75,0x04,0x94,0x3C,0x7F,0x29,0x1A,0xBB,0x26,0xD7,0xDF,0xDC,0xFD,0x31,0x98,0xC7,0x20,0x0C, +0x98,0x11,0xED,0xE0,0x16,0x59,0x6D,0x66,0x4C,0xE3,0x4B,0x6E,0x49,0x94,0xFB,0xE8,0x6D,0xB4,0x90,0x95,0x2A,0xD7,0xB0,0xBE,0xDA,0x41,0xEE,0x77,0x23,0xB9,0x02,0xFE, +0x51,0x8A,0xE6,0x5F,0x50,0x9F,0x9F,0x50,0x65,0xD9,0x91,0x93,0x36,0x9A,0xFB,0x8A,0x40,0x65,0xE2,0x49,0x0D,0xF1,0x64,0xAC,0x58,0x83,0x62,0x4F,0xA5,0xC9,0x36,0xBE, +0x14,0x6B,0xEE,0x4A,0x7D,0x96,0x5B,0xD6,0xE2,0xDB,0x0A,0xF2,0xA0,0xEF,0xA0,0x90,0x55,0xFB,0x83,0x7C,0x6A,0x7A,0x32,0x86,0x57,0xA3,0x16,0x54,0x35,0xAC,0x38,0xE6, +0x9F,0x6B,0x81,0x7B,0xFB,0xD8,0x8F,0xA6,0x2C,0x37,0xA8,0x58,0xE7,0x8E,0x23,0x0C,0x98,0xFD,0x31,0x1A,0xE6,0x8C,0xB0,0xEA,0x0A,0x22,0xCF,0x9B,0x4E,0x71,0x46,0xC1, +0x12,0x5A,0x12,0x19,0x48,0x3C,0x10,0xEA,0x2C,0xBB,0x1E,0x47,0xE1,0x93,0x63,0xCE,0x1F,0x59,0xA1,0x54,0xE0,0x9A,0x63,0x94,0x39,0x34,0xD9,0xAA,0xD0,0x90,0x14,0xD4, +0x94,0xA1,0xD7,0xEC,0xDA,0x75,0x69,0x6D,0xCD,0x2B,0x3B,0xEF,0xB2,0x4F,0xD3,0x15,0x33,0x24,0xCB,0xCB,0x30,0x64,0x90,0x4A,0xA3,0xA8,0xA1,0x76,0x06,0xE4,0x5A,0xE8, +0xBF,0xE8,0x47,0xC8,0x0C,0x3F,0x0C,0xAD,0x5B,0xAC,0x66,0xB6,0xD0,0xD4,0x09,0x2B,0x8D,0x77,0x07,0x8D,0xE0,0x9F,0x0D,0xB4,0x96,0xD2,0x8B,0x95,0x71,0xC2,0x3D,0x70, +0x2A,0xEE,0x6D,0xFB,0xB1,0x93,0xF4,0x99,0x4C,0xE0,0xF8,0xE2,0x2D,0xF5,0x75,0xDF,0xBC,0x9F,0x6E,0x89,0x58,0x6A,0x5D,0x1E,0x5B,0x2E,0xA5,0xF6,0xD4,0xE2,0x0A,0x55, +0xA9,0x26,0xC9,0x58,0x06,0xDB,0xEE,0x76,0xFF,0x00,0x6C,0x35,0x57,0x0B,0x79,0xCD,0x54,0xAC,0xC3,0x44,0xCD,0x93,0xB2,0xB6,0x62,0x83,0x1F,0xE1,0x9E,0xA8,0xC5,0x8C, +0xB0,0x99,0x0D,0x94,0x6A,0x1A,0x80,0xB5,0xC5,0xC5,0xC7,0x3C,0x91,0xCE,0x37,0x66,0x08,0xBD,0x55,0x93,0x16,0x7C,0x6A,0x7D,0x31,0x99,0x30,0x22,0x2C,0x06,0xA1,0xD4, +0x43,0x12,0xD8,0x91,0xA9,0x44,0xA8,0x94,0x3A,0x48,0x4F,0x6B,0x14,0xD8,0x8B,0x73,0x8D,0xF4,0x68,0xD5,0x95,0xE5,0x77,0x4D,0x67,0x23,0xCD,0xCB,0xB3,0x59,0x05,0x7E, +0x2D,0x32,0x42,0x64,0x30,0xAB,0x6F,0xE5,0x65,0xC7,0x0A,0xB9,0xFF,0x00,0xA9,0x61,0xD8,0x76,0xC7,0x41,0x56,0xE6,0x50,0xE8,0x79,0x8C,0x23,0x02,0x30,0xC2,0x29,0x1A, +0xF7,0x5C,0x92,0x1C,0xA2,0xBB,0x9D,0xB2,0xCE,0x68,0x8A,0xD5,0xCF,0xC5,0xC8,0x76,0xCE,0xB5,0xDB,0x4A,0xB4,0xD8,0x8F,0xAD,0xFE,0x78,0xD3,0x42,0xCB,0xF2,0x61,0x32, +0x3E,0xF1,0x99,0x19,0xE7,0x96,0x4A,0x9C,0x6A,0x0A,0x74,0xB6,0x95,0xFF,0x00,0x98,0x93,0x75,0x2C,0xFB,0xA8,0xDB,0xDB,0x07,0x73,0xFF,0x00,0x50,0xA1,0xD0,0x19,0x82, +0xAA,0x96,0x56,0x53,0xD5,0x15,0xC5,0x6C,0xBD,0x25,0xB8,0x4A,0x65,0xB9,0x0A,0x20,0x92,0x02,0x96,0x91,0x75,0x00,0x6F,0x6D,0xC6,0xFC,0xE1,0x6F,0x29,0xE6,0xCA,0x7E, +0x6A,0xA8,0x38,0x88,0x90,0x5F,0xA7,0x3E,0x92,0x35,0x47,0x90,0xB1,0x73,0xE8,0x6C,0x3E,0x98,0x8B,0xAD,0xAF,0x51,0xB8,0xBB,0x2E,0x07,0x99,0x6B,0x4B,0x65,0x61,0x40, +0x07,0x99,0x65,0xC6,0x2C,0x22,0x21,0xFE,0x3B,0x8D,0x3A,0x81,0xB1,0x3B,0x1E,0x3D,0xB1,0xB9,0x88,0xB2,0x27,0x31,0xF0,0xAA,0x59,0x42,0x4A,0xAD,0x6D,0xF8,0xE0,0x6F, +0xE9,0x81,0x15,0x55,0x39,0x4C,0xCB,0xCE,0x2F,0xC5,0x42,0x1C,0x2D,0x92,0xCB,0x80,0xD8,0x8B,0x83,0xBE,0x26,0x74,0xFA,0x7C,0xDA,0xA6,0x52,0x61,0xD9,0xEE,0xA5,0xC7, +0x12,0x0A,0x0B,0xA9,0x57,0xF8,0x96,0xDA,0xFB,0xF7,0x3E,0xD8,0x51,0x17,0x3C,0xC2,0xBB,0x62,0x12,0x9F,0x4E,0x6E,0x24,0x45,0x46,0x8E,0xB5,0x2D,0x2A,0x1A,0x48,0x26, +0xF6,0xFF,0x00,0x7C,0x21,0x54,0xE2,0x8A,0x28,0x9B,0x21,0xE8,0x82,0x44,0x14,0x38,0x96,0x65,0x25,0x57,0x0B,0x6D,0xA5,0xDB,0xF1,0x13,0xE8,0x42,0x90,0x9B,0x1F,0x51, +0x63,0xCE,0x2C,0x99,0xAE,0x47,0x4B,0x7A,0x16,0xE2,0x11,0xA8,0xEA,0xDC,0xEE,0x7D,0xF7,0xF7,0xC2,0x85,0x5E,0x5B,0xCC,0x66,0x08,0xF2,0x5A,0x63,0xC7,0x0A,0x6D,0x68, +0x71,0x95,0x10,0x52,0xFB,0x76,0x1A,0x92,0xAB,0xF6,0x3C,0x0F,0x72,0x31,0xE3,0xE1,0x46,0x4F,0x4E,0xF1,0x1D,0x5B,0x1F,0x6F,0x22,0x26,0x47,0x31,0x64,0x53,0x93,0x67, +0x0F,0x9B,0x74,0xAC,0x8D,0x94,0x42,0x88,0x1F,0x22,0x40,0xFD,0xBD,0xF1,0x09,0x4E,0x87,0x62,0x21,0x2B,0x49,0x36,0x25,0x44,0x93,0x72,0x4E,0xD8,0x74,0x6A,0x8B,0x49, +0x72,0xA3,0x2A,0x2C,0x74,0x91,0x15,0xD4,0x09,0x91,0x17,0x7D,0x20,0xB6,0xBB,0x02,0x3D,0x8A,0x56,0x94,0xED,0xFD,0xF0,0x12,0x15,0x39,0xA9,0x15,0x69,0x14,0x87,0x02, +0x1C,0x5A,0xA4,0x06,0xCB,0xA8,0x5F,0x99,0x07,0x70,0x6D,0x7B,0x02,0x2E,0x7B,0xE1,0x67,0xA9,0x81,0x18,0x9C,0xFB,0xBA,0xE3,0xAC,0x11,0x4D,0x6D,0xC7,0xAA,0x4C,0xBA, +0xD4,0x85,0x30,0xD2,0x5B,0x70,0x14,0x5A,0xD7,0x57,0x3C,0xFD,0x07,0xE9,0x8C,0xC1,0x88,0x94,0x79,0x32,0x1B,0xA7,0x88,0xF2,0x59,0x5A,0x08,0xD7,0xE0,0x95,0x04,0x29, +0xC2,0x76,0x36,0xD5,0x6B,0xDA,0xC7,0x8B,0xE3,0x31,0xA5,0xA5,0x8C,0x2D,0x1F,0x31,0xC4,0xD3,0x53,0xCD,0xD1,0x63,0xB9,0x4C,0x11,0x28,0x71,0xE5,0x38,0x23,0x87,0x2C, +0xEC,0x68,0xC5,0x2B,0x21,0x24,0x5C,0xA0,0x33,0x71,0xF2,0x4A,0xC7,0x7C,0x1B,0xA9,0xC8,0x95,0xF7,0xF3,0x31,0xD7,0x47,0xA2,0xD3,0x12,0xCA,0x92,0xDC,0x78,0x71,0xE9, +0x49,0x95,0x2D,0xE0,0x94,0x0B,0x94,0xB0,0xAB,0x84,0x82,0x6E,0xA0,0x16,0x51,0x70,0x76,0xBD,0xB0,0x32,0x26,0x60,0xCB,0xF0,0xEA,0x54,0x58,0xD4,0x2A,0x7B,0xCA,0x75, +0xD6,0x94,0xDF,0xC6,0xBC,0xAD,0x2B,0x1B,0x9B,0x80,0xA1,0x65,0x8E,0x76,0x52,0x0B,0x46,0xC6,0xCA,0x07,0x0A,0x92,0xF3,0x35,0x6A,0xB1,0x4D,0x30,0x1B,0x3E,0x12,0x5E, +0x5E,0x85,0xC5,0x86,0x8F,0x05,0xB7,0x75,0x90,0x40,0x58,0x4D,0x82,0xCD,0xC9,0x17,0x55,0xCF,0xBE,0x28,0x7B,0xAA,0xA0,0xEE,0x39,0x3F,0x41,0x0C,0x0E,0x54,0xE3,0xAC, +0xB6,0xA9,0xB9,0xD6,0xA9,0x10,0xB7,0x4C,0x34,0xFC,0xBF,0x45,0x69,0xD1,0xA5,0x4E,0x3A,0x86,0x1B,0x94,0x14,0x2E,0x47,0xE0,0xC5,0x42,0x54,0x8D,0xC0,0xBA,0x56,0x95, +0x6C,0x39,0xC4,0x85,0xF5,0x72,0x64,0xAA,0xC9,0xA6,0x8C,0xCE,0xF9,0x7A,0x43,0xAA,0xD2,0xBA,0x74,0x12,0x12,0x12,0x92,0x36,0x51,0x2E,0x37,0x7F,0x4B,0xE9,0x38,0xA7, +0xE9,0x14,0x9C,0xC0,0x9A,0xDC,0x47,0xD5,0x47,0x53,0x4D,0x23,0x50,0x4B,0xD2,0x2E,0xCB,0x43,0x63,0x73,0xAD,0x44,0x27,0xEB,0x7C,0x3C,0x50,0xE8,0x99,0x39,0x99,0xB0, +0xBE,0xF7,0xCC,0x0C,0x2E,0x4A,0x92,0x24,0x18,0xB4,0xD7,0xCA,0x90,0x4E,0xAB,0x9D,0x6E,0x24,0x28,0x0E,0xC3,0x7D,0xBD,0xF0,0x4A,0x35,0x37,0x31,0x3B,0x07,0x18,0xFC, +0xBF,0xC4,0x18,0x25,0x80,0x3F,0x58,0xCE,0x9C,0xD5,0x0A,0xB4,0x99,0xF1,0x6A,0x01,0x53,0x54,0x8D,0xD3,0xAD,0xC6,0xD4,0xA3,0xC1,0xB1,0x48,0x6D,0xCD,0x3B,0xF1,0x72, +0x4E,0x03,0x25,0xAC,0xD0,0xE5,0x55,0xE8,0x99,0x5B,0xA7,0xF5,0xB7,0x18,0x4A,0x35,0x2A,0x5B,0x8A,0x6D,0x86,0x13,0xEA,0x7C,0x40,0x00,0x36,0xF4,0x02,0xFE,0xD8,0x78, +0xA3,0x56,0x32,0x7D,0x29,0x3E,0x3E,0x53,0xCA,0x71,0xDB,0x7D,0x63,0xFF,0x00,0x7D,0x21,0x03,0x59,0x03,0xB9,0x04,0x92,0x7D,0x2E,0x48,0xD8,0x76,0xC0,0x9A,0xD5,0x2F, +0x30,0x67,0x8A,0x7A,0xE6,0x4F,0x97,0x53,0x79,0x95,0x2F,0x5C,0x3A,0x74,0x0D,0x29,0x2E,0xA4,0x1B,0x15,0xA1,0x6E,0x03,0xE1,0xA6,0xE0,0x02,0xB1,0x64,0xEF,0x74,0x95, +0x11,0x6C,0x5A,0xD1,0xBB,0x2B,0x61,0x9B,0xAF,0xFB,0xD6,0x0C,0x31,0xDE,0x44,0x47,0x39,0x8A,0x89,0x2D,0x0E,0x65,0xFC,0xFC,0xC4,0x4A,0xCC,0x66,0xD2,0xA6,0xDC,0x62, +0x9C,0x1B,0x7A,0x65,0x3C,0x71,0xA9,0xA7,0x42,0x82,0x8A,0x41,0xFE,0x12,0x92,0x7E,0x63,0x04,0x27,0xE5,0x64,0xD1,0xDC,0x46,0x65,0xE9,0x71,0x83,0x9A,0x60,0x30,0xC0, +0x43,0x90,0x65,0x14,0x89,0xCC,0xA8,0x5B,0x60,0xAB,0x5C,0x5A,0xFB,0x83,0xB8,0xC2,0xAD,0x57,0x2A,0x57,0x29,0x75,0x70,0xBA,0x1A,0x93,0x4D,0xD6,0xEA,0x59,0xD5,0x45, +0x51,0x52,0xD0,0xE2,0xCD,0xB4,0xAA,0x6A,0xCF,0x88,0xFA,0x8D,0x8E,0xA5,0x6A,0x0D,0x27,0x72,0x80,0xA0,0x14,0x94,0x91,0xA1,0xD2,0xA0,0xBA,0xEA,0x6A,0x52,0xA5,0x39, +0x97,0xAA,0x21,0x45,0xCA,0x6D,0x46,0x94,0x0A,0x97,0x21,0xBB,0x59,0x2E,0xCA,0x42,0x80,0x57,0x9B,0xC8,0xAB,0x10,0x35,0x03,0x70,0x91,0x7C,0x12,0xFD,0x30,0x7F,0xAC, +0x7D,0x2D,0x29,0xCE,0x61,0xEC,0xB9,0x2A,0x9B,0x9E,0xB3,0x5A,0x69,0x75,0x15,0x49,0xA5,0xCE,0x7B,0xCA,0xF5,0x3E,0x48,0x28,0x00,0x01,0xFC,0x09,0xFA,0xF2,0x30,0x17, +0x24,0x56,0x2A,0x34,0xDE,0xA6,0xE6,0x5C,0x9F,0x9A,0x5E,0x66,0x99,0x2A,0x2C,0xAB,0xC3,0x68,0x82,0x94,0x3C,0xC1,0x2A,0x01,0x49,0x3F,0xC5,0x6B,0x27,0x7F,0xE6,0x18, +0x6F,0x15,0x0A,0xCC,0x87,0x23,0xBF,0x5F,0xA6,0xE5,0xDC,0xC2,0xEC,0x5B,0x2D,0xB9,0xE5,0x2E,0x42,0x70,0xAB,0xF8,0x4A,0xAE,0x9B,0x13,0xB7,0x00,0x8C,0x29,0xF5,0xB7, +0xEE,0x9E,0xA6,0xB5,0x4C,0x10,0xA9,0x7F,0x07,0x56,0x8A,0xAF,0x34,0xB4,0xAB,0x60,0x2D,0xF9,0x45,0xAF,0x71,0x7F,0x7C,0x24,0x9A,0x4A,0xD1,0x58,0x58,0x71,0x08,0x75, +0x79,0x65,0x03,0xA4,0x35,0x5C,0xCC,0x49,0x84,0xFA,0xA3,0xD3,0x9C,0x62,0x54,0xAB,0xE9,0x42,0x14,0xF0,0x64,0x73,0xCE,0xA5,0xD8,0x7E,0xF8,0x54,0x7A,0x74,0x9A,0xC4, +0xB8,0xF5,0x2F,0x87,0x4C,0x59,0x6C,0x38,0xE2,0x7C,0x22,0xE3,0x65,0x3B,0x58,0xEC,0xA0,0xAB,0x10,0x42,0x4E,0x3C,0x51,0xBA,0x6E,0xF3,0x2C,0xC2,0x97,0x5F,0x75,0xD9, +0x31,0x18,0xD3,0xE2,0x32,0xE2,0x89,0xBE,0xF6,0x25,0x6A,0x04,0x6E,0x2E,0x3C,0xB7,0x06,0xD8,0x3B,0x53,0x85,0x4D,0xA4,0xD7,0xCB,0xD2,0x63,0x35,0x1A,0x94,0xE8,0x52, +0x92,0x86,0x92,0x14,0xA5,0x92,0x09,0x01,0xB4,0x8B,0x69,0xE6,0xDB,0x90,0x08,0x22,0xDB,0x8D,0xA6,0x6A,0xC2,0x6C,0x2A,0x07,0xEB,0x05,0xAC,0xBC,0x05,0xDA,0xA7,0x3F, +0xDA,0x4A,0xA7,0xD4,0xD5,0x50,0x05,0x82,0xB7,0x19,0x75,0x09,0x5F,0x84,0x37,0x0B,0x4D,0xB6,0x71,0xAF,0xD9,0x2A,0x1F,0x2F,0x7C,0x25,0x57,0x49,0xF8,0xE7,0xDC,0x61, +0x4A,0xF1,0x1E,0x3A,0xB6,0xF5,0xB7,0xF7,0xBE,0x37,0xFD,0xE5,0xF0,0x53,0x19,0x79,0xB9,0xB2,0x1E,0x09,0x75,0x2B,0x69,0x4E,0xAB,0xCC,0x52,0x41,0x1E,0x55,0x77,0x4D, +0x80,0x04,0x1D,0xC1,0xDA,0xFC,0xE2,0x14,0xDB,0x2D,0xE5,0x3A,0x0A,0x0B,0x48,0x25,0x45,0x27,0xD0,0xF1,0xBE,0x25,0x5E,0xE0,0x00,0x33,0x24,0xB1,0xF9,0x0C,0xC3,0x39, +0x66,0xBA,0xFD,0x1E,0x42,0x22,0xBE,0xDA,0x9F,0x84,0xE4,0x84,0xA1,0x48,0x5A,0x42,0x92,0x93,0x71,0x62,0x2F,0xB5,0xC1,0x24,0x8F,0xDB,0x19,0x81,0x71,0x4C,0x87,0x58, +0x2A,0x69,0x2C,0x29,0x1A,0x89,0xD2,0xA4,0x02,0x9B,0x03,0xFB,0x7C,0xC6,0x33,0x07,0xAA,0xC2,0xAA,0x00,0x30,0xD5,0x07,0x03,0x28,0xBC,0x41,0xF1,0x7C,0x33,0x2A,0x14, +0xD3,0x29,0xA6,0xDB,0x62,0x2B,0xF2,0x4A,0xF5,0x6A,0x20,0x86,0x8A,0xC8,0x09,0x1B,0x9B,0x14,0x9D,0xBD,0xB0,0x31,0xBA,0xEA,0x60,0x26,0x64,0x4A,0x43,0x25,0xA5,0xB8, +0x4A,0x44,0xB5,0x1F,0xC6,0x25,0x24,0x90,0x52,0x46,0xCD,0xEC,0x0E,0xC9,0xDC,0x5E,0xDA,0x8E,0x23,0xC2,0x5A,0x15,0x40,0xAB,0x38,0xA1,0xA4,0xB7,0x19,0x41,0x00,0x76, +0x2B,0x21,0x1F,0xBE,0xB3,0x80,0xAC,0x2B,0xC2,0x8E,0x5C,0x00,0xDF,0x92,0x46,0x0B,0x5E,0x14,0x12,0x23,0x7B,0x87,0x5F,0x31,0xF9,0xD8,0x94,0xF9,0x68,0xA2,0x66,0xBA, +0x23,0x73,0x03,0x73,0x12,0xE3,0x32,0xE3,0x4D,0x7B,0xE2,0x14,0xCC,0x84,0x22,0xE7,0xCE,0x40,0xBA,0x56,0x95,0x25,0x42,0xE2,0xF7,0xD4,0x37,0xB6,0x23,0x51,0x61,0x49, +0x67,0x3C,0xB5,0x4E,0x92,0xA4,0xB6,0xEA,0x54,0x83,0xE0,0x6E,0xA5,0x2C,0xAF,0x52,0x92,0x3C,0xA3,0x91,0x7D,0xEF,0x6B,0x58,0xF7,0xC6,0xDC,0x82,0xE2,0x54,0x2A,0x14, +0x77,0x89,0x52,0x5F,0x52,0x5E,0x8C,0x00,0xB9,0xF1,0x90,0x85,0x80,0x00,0xF7,0x42,0x96,0x3F,0x4C,0x31,0x50,0x21,0x31,0x95,0x33,0x4B,0x2C,0xC5,0x51,0x95,0x99,0xE6, +0x21,0x05,0xB5,0x20,0x6A,0xFB,0xB9,0x05,0xBF,0x2E,0x93,0xDD,0xD5,0x5E,0xE0,0x8F,0xC8,0x0A,0x48,0x25,0x4A,0x05,0x26,0xA9,0x77,0xB3,0x37,0x69,0xEA,0x15,0x50,0x07, +0x93,0x2C,0x25,0x45,0x34,0x1A,0x2C,0x5A,0x42,0x62,0xAA,0x65,0x76,0x5A,0x94,0xD0,0x84,0x95,0x24,0x88,0xC8,0xDE,0xE5,0xC2,0x41,0x48,0x50,0x1C,0xA4,0x83,0x6E,0xF6, +0xFC,0xC8,0x25,0x5D,0xCD,0x11,0x32,0xE4,0x74,0x51,0xDC,0x71,0xE7,0xDF,0x4A,0x42,0x65,0xF8,0x0E,0x29,0x4A,0x75,0x64,0x6E,0x84,0xA9,0x64,0x90,0x8D,0xEC,0x5C,0x57, +0x99,0x5C,0x0B,0x80,0x40,0x4C,0x8D,0x99,0xA9,0xF9,0x5E,0x8F,0x29,0x30,0x58,0x32,0xE6,0xC1,0x49,0x42,0x9E,0x69,0xCD,0x69,0x6D,0x60,0x85,0x69,0xF5,0x21,0x37,0x49, +0x2A,0xE0,0xAA,0xD6,0xB8,0x49,0x25,0x46,0x81,0x99,0xA2,0xC9,0xCC,0x6D,0x89,0x0C,0x2D,0xE5,0xA9,0x2A,0x97,0x27,0x54,0x8F,0xC8,0x94,0xA4,0xAD,0x4A,0xB9,0x1B,0xB8, +0xAB,0x1B,0x5F,0xB9,0x04,0xF6,0xBB,0xFE,0xF1,0xAC,0x8A,0xEB,0x1C,0xFF,0x00,0x02,0x2E,0xA9,0x96,0x33,0xA1,0x9A,0xAA,0xD1,0x93,0x4B,0x65,0xAA,0xDB,0x51,0x98,0x7D, +0xD6,0x0A,0xFC,0x0D,0x23,0xF0,0x10,0xE7,0x94,0xDD,0x3C,0xDD,0x56,0xB1,0xBF,0x20,0x5A,0xF6,0x2A,0xD3,0x55,0x67,0xDA,0x6C,0x6A,0xD5,0x71,0x4B,0xA7,0xBF,0x1E,0x2B, +0x4D,0xF9,0x96,0x9D,0x00,0xA9,0x56,0x26,0xC4,0xDF,0xD0,0x92,0x7E,0x6A,0x27,0xBE,0x17,0xE5,0xD5,0x25,0x55,0xEB,0xCC,0x3B,0x21,0x87,0xD2,0xBF,0x1F,0xC7,0x90,0xAF, +0x88,0x48,0x42,0x02,0x49,0xB0,0xB6,0x9B,0x04,0x04,0xA4,0x80,0x38,0x48,0xF9,0xE3,0x4A,0xEA,0x54,0xA6,0xAB,0x2E,0xA6,0x43,0xCA,0x6C,0xC8,0x29,0x0E,0x2C,0x9F,0x15, +0x01,0x36,0xD8,0xDD,0x23,0x63,0xB0,0x57,0x7F,0x9E,0xD8,0x29,0xD7,0xB1,0x04,0x01,0xC7,0x99,0xE5,0x6A,0xC4,0x9E,0x78,0x13,0xE3,0xD1,0x17,0x12,0x10,0xF8,0xBA,0xAB, +0xA9,0x6F,0xF2,0x0D,0x3E,0x5D,0x7E,0xC0,0x0F,0x7C,0x65,0x29,0xB7,0xAA,0xF5,0x46,0xE2,0xC1,0x29,0x61,0x94,0x20,0xEB,0x79,0xD1,0xAB,0xC2,0x48,0xE5,0x77,0xE0,0x1F, +0x73,0xB0,0xE6,0xE3,0x91,0xB6,0x15,0x26,0x27,0xC6,0x97,0xD7,0x54,0x69,0x60,0x59,0xDF,0x11,0xE4,0xDA,0x3C,0x64,0x12,0x2C,0xB7,0x37,0xB5,0xCF,0x60,0x01,0x27,0x8B, +0x73,0x87,0xB8,0xCB,0xC8,0x28,0xA3,0xBB,0x0A,0x55,0x6A,0x3A,0x21,0x92,0x95,0xBA,0xD3,0x7A,0xCA,0x9E,0x50,0x02,0xCA,0x25,0x1F,0x98,0xFF,0x00,0x22,0x4D,0x93,0xEE, +0x45,0xF0,0x91,0x67,0xBC,0xED,0x06,0x17,0x39,0x1C,0x4D,0x71,0xAB,0xD4,0xF8,0xB0,0xA4,0x53,0xE8,0xCB,0xF8,0xC7,0x9B,0x57,0x83,0x22,0x59,0x46,0xBD,0x17,0x3B,0x2B, +0x41,0xFC,0xE9,0xF2,0x80,0x4E,0xF6,0xB6,0xC4,0x03,0x7C,0x29,0x66,0x56,0x0D,0x52,0x19,0x71,0x9F,0x19,0xC9,0x31,0xC1,0x71,0xC4,0xA5,0xC2,0xE1,0xB6,0xDA,0xB4,0xA9, +0x5B,0x91,0xB2,0x4D,0x8E,0xE0,0x13,0xCE,0x37,0x54,0xDC,0x8B,0x1E,0xB1,0x35,0xDC,0xBD,0x12,0x1A,0x9A,0x69,0xD4,0xB8,0x1C,0x4A,0xD6,0x54,0xA1,0x65,0x1B,0x28,0x6A, +0xDB,0x93,0xF5,0xC4,0xFA,0xC4,0xD4,0xC3,0xA5,0xC3,0xAB,0xB0,0xFD,0x39,0xA0,0xE2,0x9B,0x75,0x51,0xD9,0x8E,0xA2,0xA4,0x05,0x5C,0x1B,0xAA,0xF6,0x23,0xCC,0xAD,0xAD, +0xB1,0xB8,0xED,0x73,0x9B,0x14,0x10,0x54,0xF6,0x98,0xF6,0xF2,0xBC,0xF5,0x95,0x84,0xB9,0x2B,0x01,0x28,0xE1,0xA4,0xAF,0x5B,0x69,0x26,0xE4,0x5F,0x9F,0xA9,0xE7,0xB7, +0x38,0x2B,0x09,0xA5,0xD4,0xA7,0xA1,0x98,0xAE,0x34,0xB6,0xAC,0x94,0xB8,0x85,0x0B,0x85,0x6A,0xB0,0x1B,0xFC,0xCD,0x8F,0xCF,0x03,0xAA,0xC2,0x23,0x35,0xA7,0x23,0x36, +0x95,0x25,0x17,0xD6,0x84,0xFB,0x5E,0xE3,0xE9,0x6C,0x6A,0x81,0x29,0x48,0xCC,0x6B,0x69,0x95,0xAD,0xA4,0xBC,0x12,0x14,0xA6,0x94,0x53,0xB1,0x00,0x93,0x88,0x2C,0x06, +0x70,0xD1,0x4E,0xBC,0x18,0x69,0x55,0x07,0x29,0xB4,0xB6,0x60,0xC5,0x28,0x53,0x81,0x47,0xC6,0x55,0xEE,0x11,0xE6,0xB8,0x40,0x1F,0x5D,0xF1,0x98,0xFA,0xED,0x2A,0x2B, +0x0D,0x19,0x0C,0xA2,0x4C,0x98,0xE8,0x58,0xD2,0xEC,0x75,0x27,0x4E,0x90,0xBB,0x2B,0x5A,0x4E,0xE7,0xB7,0x1C,0x1F,0x98,0xC6,0x61,0xB0,0x84,0x46,0x12,0xD2,0x46,0x3A, +0x62,0x24,0x16,0xDC,0x46,0x57,0xAB,0xBC,0x91,0xA4,0x6B,0x69,0xB4,0x94,0x9B,0xED,0xA8,0x2B,0xFF,0x00,0xE3,0x10,0x58,0x4A,0x5F,0x86,0xDA,0x50,0xB6,0xD2,0x54,0x52, +0x9F,0x3A,0x82,0x47,0x04,0xF7,0xF9,0x60,0xB0,0xA5,0xCA,0x14,0xDA,0x8C,0x14,0xB6,0xE0,0x53,0xEE,0x38,0x96,0xD0,0xAF,0xE2,0x2D,0x8E,0x47,0xFF,0x00,0x65,0xDB,0xE9, +0x85,0xF6,0x5B,0xD3,0x97,0xD0,0x5C,0xD2,0x80,0xA7,0xC8,0x4B,0x8B,0xE1,0x21,0x3D,0xFE,0x97,0x38,0x68,0xA4,0x3D,0xA8,0x54,0x02,0x65,0x97,0xD3,0xA6,0x4C,0x1A,0x9B, +0x15,0x5A,0x84,0x74,0x69,0x6C,0x29,0xB4,0xB6,0xE0,0xF3,0x3E,0xEA,0x50,0x6C,0xD8,0x04,0xDE,0xDA,0x74,0xA9,0x44,0x76,0xF2,0xDC,0x15,0x0C,0x1A,0x8E,0xB6,0xA9,0xD9, +0x97,0x32,0xCA,0x6E,0x43,0x8E,0x56,0x6E,0xE1,0x71,0xC7,0x2C,0x4B,0x17,0x41,0xF2,0x92,0x3F,0xF9,0x4F,0x2A,0xFF,0x00,0x2F,0x17,0x2A,0x27,0x4A,0xED,0x1E,0xA8,0xB6, +0xAB,0x31,0x60,0xD3,0xF4,0x26,0x2C,0x56,0x97,0xF0,0xEA,0x58,0x1A,0xC5,0xD0,0xAD,0x4E,0x5C,0xEE,0x16,0xA2,0x01,0x24,0x6E,0x05,0x80,0x36,0x48,0xB6,0xF8,0x25,0x4D, +0xE6,0xAA,0xE5,0x92,0x4A,0x5C,0x94,0xF1,0xD0,0x08,0x48,0x3A,0x46,0x9B,0x5C,0xFB,0x9B,0x7D,0x3D,0xF0,0x55,0x60,0x89,0x85,0x9B,0x65,0xCA,0x29,0x82,0x6B,0xAD,0x4B, +0xFC,0x1A,0x43,0x0E,0xF8,0x3F,0x87,0xE3,0x2E,0xE9,0xDD,0xD5,0x28,0x70,0x0F,0x04,0x0B,0x11,0x71,0x89,0x54,0x7A,0x62,0x20,0xC4,0xA8,0xD3,0x9A,0x42,0x15,0x39,0xC6, +0x52,0xDA,0x94,0xB2,0x14,0x45,0x96,0x1C,0x2A,0x59,0xBD,0x80,0x05,0xBB,0x11,0xB7,0x27,0xDF,0x11,0x63,0x54,0xE7,0xAB,0x33,0x06,0x1D,0x6D,0x01,0x89,0x6E,0x05,0x38, +0xD4,0x96,0xFC,0x46,0x92,0x85,0x24,0x12,0xA4,0x8B,0xFF,0x00,0x2D,0xEE,0x0D,0xC6,0xFC,0x58,0xE1,0x89,0x11,0x22,0x54,0x21,0x98,0x34,0xDA,0x8A,0x69,0xEF,0x38,0x4A, +0xFC,0x27,0x14,0x4B,0x64,0x9B,0x6D,0xAB,0x73,0xC5,0xCD,0xCD,0xF6,0xE4,0x80,0x2F,0x8D,0x72,0x3E,0x50,0xAD,0x4E,0x17,0x89,0xF6,0x89,0x32,0x25,0x44,0xA9,0x11,0x13, +0xA4,0x32,0x09,0x71,0x6B,0xD9,0x2F,0x1F,0xC8,0x02,0x6F,0xD8,0xFB,0x9E,0xF7,0xEF,0xB4,0x28,0x2D,0xB1,0x26,0xB6,0x5E,0xA9,0x4D,0x54,0x68,0x2C,0x05,0x87,0x56,0x10, +0x15,0xA9,0x64,0x8E,0xC4,0x8B,0xF2,0x05,0x87,0x1C,0x8E,0x70,0x6A,0x15,0x36,0x99,0x4C,0x2D,0x53,0xE6,0x78,0x81,0xD5,0x24,0x10,0xE2,0x9B,0xD0,0x97,0x49,0x48,0x3E, +0x51,0x62,0x95,0xDB,0x8D,0xC8,0x1A,0x89,0x16,0x55,0xF6,0x92,0x9A,0x1F,0xDE,0xB2,0x54,0xF2,0xD0,0xEC,0xF6,0x14,0x0F,0xFE,0xA0,0x28,0x32,0x84,0x04,0xED,0x72,0x4D, +0xF4,0x01,0xBD,0x81,0x16,0x1B,0xDB,0x9C,0x6B,0xFE,0x50,0x14,0xF0,0x20,0xB6,0xA6,0xEC,0x31,0xE2,0x79,0x99,0x0A,0x8D,0x54,0xA6,0x44,0xA6,0x46,0xAB,0xB6,0xDC,0x6D, +0xDC,0x6D,0x0A,0xD4,0x94,0xE9,0xDA,0xEA,0x71,0x44,0x72,0x37,0xDF,0xB0,0x26,0xDB,0x62,0x0B,0x79,0x4E,0x11,0x75,0xB6,0xA1,0x09,0x4E,0x5D,0x25,0x2A,0x7E,0x3A,0x02, +0x93,0xB1,0x3C,0x90,0x4E,0xE0,0x5A,0xD6,0xD8,0xDF,0x13,0xE3,0xD4,0x29,0x10,0xDD,0x7D,0x34,0x48,0x69,0x9F,0x2D,0x95,0x80,0x5E,0x7E,0xFE,0x12,0x0F,0x1F,0x86,0x08, +0xF3,0xF2,0x45,0xD5,0x6F,0xFB,0x7B,0xE2,0x36,0x61,0x7D,0xF9,0x90,0x8C,0xD6,0xE4,0xAC,0xA4,0xD8,0x84,0x2D,0xC5,0x5D,0xAF,0x60,0x9B,0xEC,0x01,0xB5,0xB6,0xB6,0x3D, +0xC6,0xC2,0x14,0x4F,0x05,0x98,0x6F,0x6F,0xA0,0x91,0xD2,0xF3,0x59,0x7F,0x31,0x25,0xDF,0xBA,0x2A,0xB3,0xDB,0x2D,0x24,0xA4,0xAD,0x6D,0xB0,0xCA,0x94,0x94,0x94,0x85, +0x10,0x55,0xB9,0xBA,0x78,0xBF,0x7C,0x46,0x45,0x66,0xB5,0x29,0xA9,0x46,0x42,0x8B,0x6C,0xC8,0x0E,0x27,0xC1,0x00,0x69,0x21,0x44,0x9B,0x03,0x7B,0x5C,0x7B,0x5F,0x7F, +0x9E,0x31,0xDA,0x80,0xAD,0xD0,0x51,0x4D,0xAF,0xB5,0x05,0x94,0x02,0x52,0xDB,0x8A,0x6D,0x2B,0xF1,0x3D,0x48,0x57,0x20,0x82,0x06,0xC4,0x9E,0x4E,0xDC,0x61,0x7D,0x14, +0xFA,0x44,0x15,0xAC,0xC2,0x93,0x29,0xC7,0x52,0xA2,0x3F,0x00,0x15,0x21,0x5B,0x6D,0xB0,0xD8,0x63,0x76,0xA8,0x61,0x91,0xC1,0x84,0x75,0x5D,0xB8,0x1D,0x67,0x9A,0xF4, +0x4A,0x9C,0x79,0x11,0xA6,0xCF,0x78,0x3D,0x70,0x94,0x21,0xC1,0xDD,0x25,0x20,0xA4,0x7D,0x06,0x23,0x87,0x63,0xB5,0x50,0x89,0xE1,0xEA,0x0F,0x12,0x54,0xAB,0xFE,0x83, +0x1A,0x6A,0x0E,0x3E,0x56,0xEA,0x14,0xE4,0x85,0x2B,0x52,0x17,0xE1,0x29,0x67,0x48,0x23,0xFC,0xA3,0xF7,0xF6,0xBE,0x35,0x3A,0x7C,0x45,0xA5,0xF4,0x1B,0x29,0x2A,0xB7, +0xA7,0x06,0xDF,0xE9,0x88,0x3A,0xA5,0xC3,0x49,0xB7,0x28,0xDD,0xC4,0x77,0xCB,0x89,0x96,0xB8,0xCE,0x53,0xD4,0xC9,0x6D,0x32,0xA4,0x8F,0x02,0x51,0x48,0x3E,0x02,0xCA, +0x93,0xE7,0x49,0x3C,0x70,0x7E,0x78,0xCC,0x08,0xA7,0x38,0x2E,0xB5,0x29,0x4E,0x5B,0x48,0x70,0x29,0x27,0x70,0xA1,0x6F,0xDF,0x19,0x86,0xAA,0xBF,0x6A,0xED,0x30,0x4E, +0x76,0x31,0x13,0xFF,0xD9,}; + diff --git a/examples/160 x 128/TFT_flash_jpg/jpeg3.h b/examples/160 x 128/TFT_flash_jpg/jpeg3.h new file mode 100644 index 0000000..3bae8c4 --- /dev/null +++ b/examples/160 x 128/TFT_flash_jpg/jpeg3.h @@ -0,0 +1,284 @@ +// We need this header file to use FLASH as storage with PROGMEM directive +#include + +const uint8_t Baboon[] PROGMEM = { +0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x48,0x00,0x48,0x00,0x00,0xFF,0xDB,0x00,0x43,0x00,0x04,0x03,0x03,0x03,0x03,0x02,0x04, +0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x06,0x0A,0x06,0x06,0x05,0x05,0x06,0x0C,0x08,0x09,0x07,0x0A,0x0E,0x0C,0x0F,0x0E,0x0E,0x0C,0x0D,0x0D,0x0F,0x11,0x16,0x13,0x0F, +0x10,0x15,0x11,0x0D,0x0D,0x13,0x1A,0x13,0x15,0x17,0x18,0x19,0x19,0x19,0x0F,0x12,0x1B,0x1D,0x1B,0x18,0x1D,0x16,0x18,0x19,0x18,0xFF,0xDB,0x00,0x43,0x01,0x04,0x04, +0x04,0x06,0x05,0x06,0x0B,0x06,0x06,0x0B,0x18,0x10,0x0D,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xC0, +0x00,0x11,0x08,0x00,0x78,0x00,0xA0,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xFF,0xC4,0x00,0x1C,0x00,0x00,0x03,0x00,0x03,0x01,0x01,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06,0x07,0x00,0x03,0x04,0x01,0x02,0x08,0xFF,0xC4,0x00,0x38,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x05,0x03,0x03,0x03,0x04, +0x03,0x01,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x11,0x00,0x12,0x21,0x06,0x31,0x13,0x22,0x41,0x51,0x07,0x14,0x32,0x61,0x81,0x71,0x91,0xA1,0x15,0x23,0x42,0x52,0xD1, +0xF0,0x24,0xB1,0xC1,0xE1,0x33,0x43,0x72,0xF1,0xFF,0xC4,0x00,0x1B,0x01,0x00,0x02,0x03,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x06, +0x03,0x04,0x07,0x02,0x08,0x00,0xFF,0xC4,0x00,0x36,0x11,0x00,0x01,0x03,0x02,0x04,0x04,0x03,0x05,0x07,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x03,0x04, +0x11,0x05,0x12,0x21,0x41,0x06,0x22,0x31,0x61,0x13,0x51,0xB1,0x14,0x32,0x71,0x81,0xC1,0x15,0x23,0x33,0x34,0x62,0xA1,0xF0,0x07,0x35,0x42,0x52,0xB2,0xF1,0xFF,0xDA, +0x00,0x0C,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3F,0x00,0xD7,0x7B,0xA8,0xB1,0xD3,0xDC,0xE6,0x80,0xDD,0x67,0xAC,0x86,0x80,0x4A,0xAA,0xE6,0x47,0x99,0x61,0x24, +0x83,0x20,0xD8,0xE3,0x95,0x8F,0x7B,0x71,0xCE,0xDD,0xA0,0x83,0xE5,0xE3,0xCA,0x6A,0xEA,0xCB,0x47,0x47,0xD4,0xC9,0x35,0x40,0xB9,0xAF,0xCD,0x63,0xC6,0x83,0xCF,0x2F, +0x8A,0x63,0x8C,0x15,0x55,0x2B,0xB8,0x12,0xF8,0x61,0x93,0x86,0xDF,0xF5,0x03,0x80,0x12,0x6D,0x77,0x39,0x2A,0x52,0x78,0x69,0x92,0x9A,0x69,0xAA,0xA4,0x66,0xA9,0xA6, +0xBA,0x4E,0x23,0x77,0x56,0x4F,0x33,0x00,0xBC,0xE7,0x70,0x00,0xAA,0xA8,0x20,0x92,0x1B,0x2A,0x48,0xD0,0xE8,0x6E,0x36,0x8B,0x55,0xDA,0x9E,0xB6,0xA6,0x2F,0x1B,0x60, +0xDB,0x07,0x89,0x29,0x2A,0xBC,0x28,0xDA,0x63,0xDC,0x5F,0x6E,0x0A,0x92,0x0E,0x33,0x86,0xC6,0x70,0x72,0x06,0x9E,0x30,0x1D,0xCE,0xAB,0xBE,0x23,0x97,0x45,0x4E,0xBA, +0x3C,0x30,0xD8,0x27,0xB6,0x49,0xD4,0x34,0x75,0x34,0xEB,0x20,0xF0,0xE0,0x60,0xB1,0x3C,0x65,0x70,0x42,0x63,0xB9,0x3B,0xD8,0x8C,0x2F,0xEC,0x07,0x60,0xB5,0x53,0x52, +0x4D,0x53,0x55,0x4B,0x05,0xBF,0xE6,0xEA,0xA4,0x95,0xAA,0x43,0x2D,0x3A,0xC7,0x4F,0xB8,0xAB,0x80,0x14,0x12,0x4F,0xF8,0x76,0x03,0x20,0xAA,0xFB,0x1D,0x26,0x4D,0xD5, +0xF5,0x52,0x4B,0x3B,0x3D,0x57,0xCD,0x06,0x98,0xD4,0x23,0x95,0x08,0x44,0x83,0x3E,0x51,0x8E,0x70,0x49,0x27,0x27,0x3E,0x98,0xEC,0x74,0x45,0xFA,0xF7,0xCB,0xE2,0x8F, +0x16,0x1A,0x69,0x0F,0xF7,0x0C,0x0A,0x21,0x04,0xA8,0x62,0x46,0x46,0x08,0x25,0xDB,0x76,0x70,0x39,0x23,0x1E,0xBA,0x32,0xC7,0xC6,0x05,0xEF,0x65,0x4C,0xD3,0xCA,0x08, +0x24,0x5D,0x77,0x5C,0x2E,0xB7,0x89,0x20,0x4B,0x33,0x40,0x90,0x9A,0xDD,0xF1,0x55,0x6D,0xA9,0x59,0xC0,0x50,0x08,0x58,0x9D,0x58,0xA8,0x49,0x54,0x01,0x83,0xD8,0x64, +0x60,0x83,0x9D,0x0F,0xB2,0x75,0x4D,0xCA,0xD9,0x4B,0x5B,0x0D,0xCE,0xB1,0x24,0x59,0x0A,0x24,0x8A,0xB7,0x05,0xA9,0xDD,0xB4,0x02,0x46,0x40,0x2C,0x0F,0x1D,0xF2,0x47, +0x38,0x39,0xD0,0xA1,0xD7,0x72,0xD4,0xDE,0x29,0xAB,0x2B,0x2A,0x4C,0x72,0xC6,0xC8,0xB2,0x41,0x32,0x89,0xE1,0x2A,0xA0,0xE1,0xB1,0xEB,0xB4,0x93,0x80,0xDB,0xBD,0xCF, +0xBE,0xB5,0x37,0x50,0xD1,0xCF,0x05,0x67,0xF4,0xD8,0xA8,0xAA,0x25,0x24,0x3C,0x53,0x55,0xC6,0x5A,0x58,0x8F,0x00,0x8C,0x9E,0x0E,0x42,0xE3,0x91,0x8E,0xFA,0xE2,0xEC, +0x6E,0xB7,0x53,0x06,0x3C,0xB7,0x28,0x1A,0x22,0x35,0xA3,0xA9,0xFA,0x9E,0x96,0x34,0x6A,0x34,0x7A,0x70,0xDB,0xD9,0xE6,0x02,0x41,0x1B,0xF8,0x71,0xA9,0xC3,0x46,0x32, +0x54,0xE1,0x78,0x19,0xEF,0xCF,0x6D,0x79,0x59,0x6D,0x5B,0x15,0x19,0x6A,0xD5,0x69,0xA7,0x9E,0x75,0x6A,0x86,0x88,0x33,0xD3,0x37,0x94,0x91,0xB3,0x00,0x15,0xC0,0x2A, +0xDB,0x70,0x38,0x03,0x1C,0x63,0x4B,0xB6,0xAE,0xA8,0xAD,0xB6,0x53,0xB4,0x54,0x75,0x12,0xC7,0x02,0x82,0x66,0x05,0x42,0x82,0x4E,0x46,0x71,0xDF,0x38,0xC7,0x9B,0x82, +0x31,0xC1,0xD3,0x75,0x83,0xAC,0xE1,0x9D,0x60,0xA0,0x5B,0x75,0x3C,0x71,0xC8,0x36,0x3C,0xAD,0x89,0x3C,0x68,0xF3,0xC2,0x36,0x76,0x90,0x3B,0x00,0x46,0x48,0x04,0x8F, +0x30,0x1A,0x92,0x33,0x1B,0xC7,0xBD,0x62,0xBB,0x96,0x39,0x19,0xFE,0x3C,0xA8,0x7B,0xDC,0xBA,0x95,0x7A,0x85,0x24,0xFE,0xDD,0x22,0xD7,0x2A,0x4E,0x4A,0x40,0x8A,0xA5, +0xB2,0xD8,0xDD,0x9C,0x9C,0xE4,0x95,0xC9,0xE7,0x1F,0xC0,0xF1,0x43,0x7B,0x85,0x4A,0x5D,0x2D,0x9E,0x34,0xF5,0x21,0xE1,0x81,0xD0,0x7F,0x6C,0xB2,0xB7,0x86,0x4A,0xB6, +0xE0,0x30,0x01,0x62,0x4E,0x3B,0x83,0xEC,0x4E,0xAB,0xD0,0xDD,0xBA,0x7A,0x82,0xCB,0x4D,0xFD,0x4A,0xD1,0x09,0xA7,0x55,0xD9,0x99,0xC2,0xC9,0xE2,0x12,0xAD,0x89,0x16, +0x56,0xC0,0x3D,0xF2,0x40,0x53,0xC9,0xE7,0xB3,0x69,0x76,0xF9,0x35,0xAE,0xE5,0x6E,0xA3,0x9A,0xC7,0x7D,0x8C,0xC1,0x0C,0x6E,0x22,0xB2,0xAC,0x67,0xC6,0x63,0x92,0xAF, +0x9C,0x36,0xEF,0x32,0x8D,0xC4,0x91,0xFF,0x00,0xD8,0x40,0xD4,0xB2,0x53,0x46,0x05,0xF3,0x2A,0xBE,0x3B,0x9C,0x40,0x0D,0x16,0x49,0x33,0xA7,0x55,0x86,0xA9,0xA6,0xBB, +0x5B,0x5F,0xC3,0x08,0x57,0xE5,0xDC,0x6D,0xDE,0xA1,0x83,0xF2,0x46,0x01,0x21,0xC0,0x3C,0x1F,0xFD,0xBB,0x45,0xD0,0xF7,0x7A,0x9A,0x48,0x20,0xA7,0xB5,0xCD,0x04,0xCF, +0x39,0x32,0xCF,0x51,0x29,0x94,0x49,0x8C,0x86,0x0C,0x30,0x30,0x17,0x2D,0xEA,0x32,0x40,0xE7,0x9C,0xEB,0xBE,0xDD,0xD7,0xD4,0x17,0x4A,0xCC,0xDB,0xA9,0x67,0x6F,0x95, +0x88,0xA5,0x42,0x08,0x84,0x8E,0xC7,0x39,0xC1,0xC8,0x52,0xCA,0x09,0x6E,0x40,0x27,0xEE,0x3D,0x4D,0x4B,0xF1,0x2E,0x8E,0xDB,0x3A,0x42,0x92,0xC5,0x02,0xC7,0x0F,0x85, +0xE1,0x4B,0x0B,0xAC,0x8A,0xCC,0xC1,0x89,0x71,0xC8,0x1F,0x48,0x5C,0x7B,0x93,0x9E,0x35,0x6A,0x18,0xE9,0xD9,0xAB,0xCD,0xD4,0x2F,0x7C,0xAE,0xF7,0x00,0x5A,0x9B,0xE1, +0xDD,0xDD,0xAC,0x12,0x6E,0xAF,0x9A,0xA6,0xF6,0xE0,0x42,0xAC,0x26,0x55,0xDC,0x99,0x05,0xB8,0x6C,0x79,0x41,0x2A,0x7B,0xFA,0x0C,0x73,0xA5,0xDB,0xA5,0xB2,0x83,0xA7, +0x20,0xA3,0x34,0x77,0xA9,0xA9,0x46,0x04,0x13,0xC9,0x31,0x3E,0x1C,0xA7,0x04,0x3E,0xCE,0xC6,0x46,0x19,0x1C,0x67,0xD8,0xF7,0x3C,0x83,0xEA,0x3F,0x88,0xD7,0x6B,0xC5, +0xD1,0x80,0xAB,0x48,0xD7,0x77,0x87,0x23,0x53,0xC8,0xE3,0xC7,0x50,0x77,0x15,0xC9,0x39,0x61,0xCF,0xAE,0x7D,0x7B,0x67,0x4B,0xEB,0x59,0x3D,0xD2,0xF1,0x05,0x4D,0x75, +0x75,0x58,0xA3,0x81,0x8C,0x94,0xF4,0xCF,0x33,0x4A,0x14,0x83,0x9E,0xDC,0x0C,0x7E,0x87,0xF1,0xAA,0x92,0xD5,0x41,0x7B,0x35,0x4B,0x1D,0x2C,0xA0,0x5D,0xFD,0x0A,0x75, +0xB5,0xF4,0xCC,0xB2,0xA5,0x25,0x55,0xBA,0x86,0xBC,0x3C,0x85,0xA4,0x46,0x48,0x96,0x9C,0x91,0xBB,0x24,0x3B,0x3B,0x26,0x7B,0x67,0x2A,0x4E,0x08,0xF2,0x8E,0xFA,0x35, +0x17,0x43,0xED,0xF9,0x8A,0xCC,0xD2,0x08,0xAB,0x1C,0x24,0x66,0xA2,0x41,0x52,0xCE,0x32,0xAC,0x57,0x0C,0x47,0x9C,0x6D,0x38,0x2B,0x9C,0xE3,0x19,0x00,0x1D,0x22,0xDC, +0x7A,0xD6,0xE1,0x4F,0x71,0x92,0xB1,0x2E,0x93,0xD3,0x54,0x30,0x0B,0xF3,0x30,0xA0,0xDE,0x17,0x77,0x76,0xF5,0x27,0x81,0xDC,0x9E,0xDE,0xDC,0x68,0x74,0xFD,0x5D,0x7F, +0xAC,0xB7,0x2C,0x30,0x5F,0x9D,0xE2,0x72,0x37,0xC7,0x24,0xAC,0xAD,0x27,0xF9,0x12,0x40,0x38,0xC6,0x0B,0x0C,0x72,0x39,0x38,0xC0,0xC6,0xBB,0x74,0xD0,0xAE,0x84,0x12, +0x95,0x5F,0xA7,0xE9,0xFA,0x7B,0x25,0xC3,0xC2,0x91,0xA9,0x8D,0x30,0x6D,0xF3,0x78,0x91,0x28,0x07,0xCC,0x02,0x90,0xE5,0x40,0xCE,0x19,0x8F,0x97,0x19,0xC8,0x39,0xEC, +0x4F,0x6C,0x75,0xF6,0x9A,0x69,0xEA,0x68,0xAD,0xB5,0xD2,0x4B,0x23,0xC4,0x76,0x4F,0xB4,0xCE,0x5C,0x32,0xA6,0x4A,0x6D,0x19,0x66,0x5E,0x49,0x1C,0x8F,0x38,0x27,0xDD, +0x62,0x50,0xF5,0x3D,0xE2,0xDB,0x50,0xB5,0x30,0xD6,0x05,0x66,0x52,0x9E,0x1C,0x2E,0xE5,0x37,0x6D,0x20,0x36,0xDC,0xB0,0xFF,0x00,0x23,0x8E,0x3F,0xF3,0xAE,0x79,0xBA, +0x82,0xE1,0x52,0xB4,0xE0,0xDC,0x6B,0x64,0x76,0x2D,0xB6,0x49,0xE7,0x07,0x1E,0x65,0x23,0x0F,0x95,0xC8,0xF2,0x8E,0x71,0xAE,0x4D,0x63,0x18,0x6C,0x54,0x9E,0xC8,0xFD, +0xD5,0xA2,0xE7,0x57,0x41,0x54,0x91,0xCB,0x43,0x3C,0x0F,0x56,0x68,0xBC,0x0F,0x12,0x58,0xBC,0x47,0xCA,0x96,0x61,0x84,0x20,0xED,0x66,0xDC,0x18,0xB0,0x53,0xCA,0x8C, +0xE8,0x05,0x3D,0xE6,0xA1,0x77,0xD9,0xE1,0xB7,0xD6,0x4C,0xB1,0x13,0x59,0x3C,0x15,0x05,0x25,0x97,0x69,0x05,0xB7,0x8F,0x44,0x63,0x80,0x3C,0xD9,0x65,0x51,0xE5,0x51, +0xE9,0x32,0xA8,0xBF,0x5E,0x63,0x94,0x4C,0xB1,0xCA,0x33,0x08,0x8C,0x24,0xF2,0x31,0x38,0x3C,0x0D,0x85,0xB9,0x0B,0x80,0x46,0x41,0xCF,0x38,0xCE,0x38,0xD7,0x64,0xF7, +0x68,0xA5,0x8A,0xAD,0x96,0xE9,0x4F,0x42,0x2B,0x8F,0x87,0x3D,0x34,0x28,0x1B,0x2A,0x1B,0x80,0x66,0x18,0x07,0x24,0x64,0xF6,0x04,0x85,0xCE,0x48,0x07,0x55,0xA5,0x78, +0x90,0xDC,0x15,0x24,0x51,0x16,0xF2,0x93,0x75,0xF1,0x5F,0x5F,0x2D,0x1F,0xCB,0xBC,0xF2,0x55,0xC6,0xCE,0x3C,0x1A,0xEA,0x7A,0x0F,0x0E,0x28,0xE3,0x52,0x1B,0x6A,0xC8, +0x81,0x08,0x04,0x12,0x30,0x49,0x24,0x80,0x41,0xD0,0x09,0x18,0xC2,0x8C,0x94,0x75,0x95,0x32,0xC0,0xD2,0x28,0x8D,0xA3,0x99,0x82,0x36,0xD0,0x46,0xC0,0x76,0x1C,0x38, +0x1F,0xB0,0xFD,0xB5,0x45,0x6E,0x83,0x5A,0x09,0xDE,0xB0,0xC3,0x3C,0x0A,0x5F,0xC6,0x4A,0xA6,0x8C,0x98,0xE1,0x44,0xC3,0x00,0xA5,0x94,0x97,0x72,0xCC,0x00,0xC1,0x23, +0xD4,0x92,0x17,0x05,0x4A,0x6E,0x96,0xAE,0x32,0xC0,0x4B,0xD6,0x3D,0x39,0x91,0xB6,0xC5,0x28,0xCB,0x46,0x53,0x20,0x92,0x3B,0xE4,0x88,0xC6,0x49,0x00,0xE3,0x1C,0x10, +0x0E,0xA2,0xF0,0xDA,0xAE,0x78,0x8D,0x69,0xB2,0x0C,0xCA,0xF1,0x45,0x12,0x4A,0x24,0x85,0x59,0xD8,0x89,0x10,0x3F,0x87,0xB0,0x13,0x9E,0x30,0x1B,0x19,0x04,0xF1,0xEF, +0xDB,0x41,0xE2,0xAE,0x86,0x1A,0x80,0x23,0xDF,0x3C,0x95,0x19,0x10,0xE0,0x64,0xB3,0x13,0x81,0xC1,0xCF,0x39,0xCF,0xA7,0x3D,0xFD,0x8E,0xAC,0x14,0x5D,0x05,0x51,0x51, +0x4C,0x95,0x14,0xB5,0x1E,0x03,0x10,0xB1,0xA4,0x81,0x77,0x3B,0x10,0x0E,0x33,0xB3,0x24,0x70,0x40,0xCF,0x7F,0xB0,0xCE,0xA7,0x37,0x39,0x2C,0x9D,0x35,0xF1,0x0E,0xD1, +0x3C,0xD0,0x09,0x2A,0xAD,0xB5,0xE9,0x2D,0x74,0x91,0xCE,0x65,0x49,0x55,0x65,0xDD,0x8D,0xAC,0xA3,0x04,0x05,0x00,0xE0,0xE3,0xD3,0xBF,0x3A,0xF8,0x31,0x97,0xB1,0x51, +0x32,0xA3,0xCD,0x74,0xD3,0x74,0x7F,0x59,0x31,0x3F,0x2F,0x6F,0x2C,0x44,0xAD,0x11,0xDD,0x50,0x89,0xB4,0x8E,0xE4,0x1D,0xD8,0x23,0x9E,0xFA,0xD0,0x3A,0x53,0xAA,0xA8, +0xE4,0x09,0x1D,0xBE,0x8E,0xA6,0x45,0x07,0x7A,0xC5,0x59,0x19,0x61,0x83,0xEA,0x32,0x7F,0xE7,0xBE,0xAD,0x76,0x55,0xA4,0xB8,0x40,0xD4,0x6B,0x54,0x4A,0x22,0x1A,0x76, +0x68,0x64,0x21,0x80,0x39,0x21,0xC1,0xF5,0x04,0x1C,0x82,0x3D,0x31,0xA5,0x7B,0x37,0xC3,0xCA,0xAB,0x34,0xC6,0x64,0xBA,0xC5,0x25,0x24,0x13,0xBC,0xE8,0x52,0x11,0xF3, +0x32,0x97,0x00,0x62,0x49,0x79,0x66,0x00,0x00,0x02,0xE4,0x00,0x46,0x40,0x19,0xD2,0x51,0xE2,0x57,0x47,0x2C,0xB0,0xCA,0x43,0x0B,0x4E,0x80,0xB4,0x9B,0xA7,0x9A,0x7C, +0x0D,0x92,0xC7,0x13,0xA3,0xBB,0xB3,0x0B,0x93,0x7E,0x8A,0x5D,0x5B,0x6F,0xEA,0x1A,0x3A,0x37,0x9A,0xBE,0xDF,0x24,0x11,0xF8,0x8A,0xA1,0x84,0x88,0xC0,0x16,0xC8,0x00, +0x90,0x71,0xDF,0x8E,0x75,0xF5,0x59,0x4F,0x5F,0x60,0x96,0x1F,0xEA,0x56,0x9A,0xBA,0x59,0xB7,0x17,0x1E,0x2A,0x1F,0x0E,0x45,0x18,0x3C,0x30,0x3C,0x8E,0x79,0xC7,0xDB, +0x54,0x1F,0x8A,0x17,0x5A,0x6B,0x4F,0xC2,0xEA,0x8B,0x5C,0x90,0x87,0xAC,0xAC,0x95,0x22,0x85,0x78,0x66,0x01,0x64,0x59,0x1D,0xBD,0x71,0x80,0x02,0xF3,0xEA,0xFF,0x00, +0xAE,0x97,0xBE,0x1D,0xDF,0xBF,0xAB,0x59,0xE2,0xB1,0x75,0x12,0x2B,0xC3,0x2C,0x6E,0xF4,0x92,0x4B,0x30,0xDB,0x24,0x60,0x3A,0xB2,0xE0,0x1D,0xD9,0x07,0x24,0x00,0x46, +0x46,0x78,0x3C,0x1D,0x36,0xD0,0xCE,0x67,0xA6,0x6C,0xD2,0x36,0xCE,0x29,0x67,0x13,0x8F,0xD9,0xAA,0x1F,0x14,0x66,0xED,0x04,0x04,0x0A,0x97,0xA9,0xEA,0x68,0x6A,0xD6, +0xE3,0x44,0xA1,0x9B,0x77,0xD0,0x39,0x52,0x08,0xE5,0x4F,0x39,0xC1,0xCF,0xBF,0x3A,0x21,0x6D,0x65,0xAB,0x62,0xB2,0xBF,0xC9,0x2D,0x4C,0x81,0xBC,0x9B,0x56,0x25,0xC9, +0x04,0xE7,0x9C,0x01,0xF8,0xF7,0xD0,0x2E,0xA8,0xB4,0x41,0x66,0xBC,0xCA,0x69,0x65,0x44,0xA6,0x8D,0xC9,0x10,0x6E,0x12,0x6E,0xC1,0x00,0x85,0x75,0xF2,0x92,0xB9,0x20, +0xFA,0x1C,0x64,0x1C,0x92,0x35,0x96,0xB9,0xE3,0xAA,0x70,0xAA,0xDB,0x3B,0x12,0x76,0x96,0xDC,0x7D,0x39,0xE3,0xD3,0xDB,0xFD,0xB5,0x24,0x92,0x00,0x2E,0x35,0x55,0x1E, +0xDC,0xCC,0xBA,0x71,0x4A,0x4B,0xAD,0x15,0x05,0x45,0x3D,0x0F,0x50,0xD1,0x2D,0x34,0x93,0x6C,0x30,0x43,0x21,0x22,0x43,0x9E,0x0E,0xD5,0x51,0xC7,0x23,0xFE,0x67,0x40, +0x2B,0x8B,0xC1,0xBE,0x9A,0x4D,0x95,0x55,0xD2,0x38,0x01,0x95,0xF0,0x72,0x71,0xEA,0x4F,0x7F,0x4E,0xFA,0xFA,0x68,0xA2,0x85,0xCC,0xAB,0x57,0x53,0x3F,0x98,0x23,0x4A, +0x06,0x10,0x9E,0x38,0xDA,0x7B,0x1F,0x4C,0x73,0xFA,0x9E,0x75,0xDB,0xD3,0x4A,0xE6,0xB2,0xA6,0x76,0xA5,0x9E,0x49,0x19,0x82,0x46,0x60,0x52,0x5D,0x58,0xE7,0x00,0x36, +0x3C,0xA4,0xE3,0xBF,0x07,0xEF,0xDF,0x51,0x19,0x5A,0x74,0xBE,0x8A,0x0A,0x76,0x3B,0x3E,0x8B,0xAA,0xC1,0xD0,0xD7,0xBA,0x9F,0x06,0xA2,0xEB,0x71,0x14,0x01,0xC9,0x6F, +0x0F,0xC3,0x26,0x40,0x80,0x67,0x71,0xC7,0x0A,0x7D,0x3F,0x23,0x5C,0xB7,0x7B,0x5D,0x34,0x3D,0x53,0x6F,0xB0,0x59,0x2E,0x15,0x97,0x1A,0xEA,0xA9,0x22,0x89,0xA6,0x66, +0xF2,0x44,0xCC,0x42,0x95,0xC0,0x00,0x60,0x13,0x8F,0x5C,0x01,0xA7,0x7E,0xA6,0xBA,0xD4,0xD9,0xAC,0x49,0x6C,0xA5,0x48,0x05,0xE9,0xD5,0xDA,0x48,0xC0,0x45,0x58,0x40, +0x50,0xC1,0x02,0xB1,0xE0,0x8D,0x87,0xB8,0xC9,0x24,0x77,0x27,0x51,0xC3,0x27,0x53,0x74,0xE7,0x50,0xDA,0x6F,0xB5,0x14,0xD2,0xC6,0x77,0xC5,0x72,0xA6,0x33,0xF1,0xE2, +0xA0,0x7E,0xFE,0x99,0x04,0x82,0xBF,0x8D,0x77,0x03,0x9B,0xA5,0xD7,0x6F,0x71,0x79,0x39,0x3A,0x0F,0x55,0x68,0x83,0xE1,0x75,0xA9,0x6D,0xE6,0xB2,0xB6,0xAA,0xAD,0xE3, +0xF3,0x48,0xCD,0xBC,0xA9,0xD8,0x3D,0x76,0x8F,0x53,0x9E,0xDE,0x9A,0xF6,0x9B,0xA3,0x3E,0x1F,0x5E,0x6B,0x96,0xD3,0x4D,0x67,0xBB,0x5B,0xEB,0x8C,0x02,0xA6,0x24,0xA9, +0x79,0x61,0xF1,0xA3,0xDC,0xC9,0xBC,0x67,0x07,0x19,0x56,0x19,0x1E,0xDD,0xF4,0xD7,0xD3,0x1D,0x49,0x65,0xBF,0x5A,0xD3,0x15,0xB1,0x4F,0x14,0x88,0x41,0x86,0x56,0x50, +0xC1,0x4F,0x74,0x6F,0x76,0x18,0xC1,0xFD,0x33,0xEA,0x35,0xBA,0x9F,0xA5,0x7A,0x77,0xA6,0x2B,0xDA,0xE9,0x41,0x43,0x2D,0x3C,0x8E,0x85,0x0C,0xB3,0x4C,0x4A,0xC7,0x1E, +0xED,0xD8,0x00,0x9E,0x06,0x49,0x20,0x01,0x8E,0x75,0x9B,0x56,0x62,0xD5,0x6C,0x9E,0x58,0xAA,0x5C,0xF1,0x25,0xF9,0x72,0xF4,0x4E,0x54,0x74,0x50,0x18,0xE3,0x92,0x30, +0xDC,0x84,0x6B,0x7E,0xAA,0x5F,0xD5,0x7F,0x0E,0xA2,0xB2,0x74,0xE5,0xCE,0xED,0x68,0xAE,0xAA,0x91,0x6D,0xF1,0xA4,0xE6,0x19,0x18,0x3E,0x22,0x2D,0xB1,0xBC,0xC4,0x67, +0x21,0x99,0x4F,0xDC,0x13,0xED,0xA0,0xDD,0x3D,0x64,0xBB,0xDD,0xEC,0x62,0xBB,0xC1,0xDF,0x33,0x12,0x40,0xA9,0x6F,0x3C,0xF1,0x95,0xC7,0x95,0x48,0x20,0x9D,0xA0,0xB0, +0x3D,0xB8,0xC6,0x4E,0x34,0xDB,0xF1,0x0B,0xAB,0x1A,0x2E,0x94,0xA8,0xE9,0x9A,0x43,0xF3,0x17,0x6B,0x9A,0xA4,0x0C,0xA1,0x40,0x68,0xA0,0x0E,0x1D,0x9D,0xF9,0xC2,0x96, +0x2A,0xB8,0x04,0xFD,0x2A,0x49,0xC6,0x46,0x9D,0xFE,0x15,0xD9,0xA4,0x83,0xA4,0xA1,0xF9,0xAD,0x95,0x71,0x02,0x4A,0x54,0x92,0xDC,0x36,0x02,0xE7,0x6B,0x73,0x82,0x59, +0x88,0x3F,0xE9,0x20,0xF1,0xC8,0xD6,0x85,0x86,0x36,0x63,0x49,0x1F,0xB4,0xEA,0xFB,0x6B,0xE7,0xFC,0xB2,0x53,0xAF,0x91,0x82,0x79,0x04,0x06,0xED,0xBE,0x9F,0x0D,0xFF, +0x00,0x7B,0xA8,0x8F,0xF4,0xFA,0xB8,0xA5,0x79,0xA2,0xA7,0x64,0x96,0x9B,0x1C,0x08,0xD6,0x4D,0x84,0x1E,0xE7,0xCB,0xB4,0x1E,0x06,0xBA,0x20,0xB1,0x4D,0x3D,0x1C,0x93, +0x7C,0xB4,0xA6,0x3C,0x17,0xDA,0x40,0xCE,0xCC,0x8E,0x49,0xC0,0x18,0xCE,0x07,0x7E,0x72,0x35,0x49,0xEA,0x8A,0x3A,0x39,0x6F,0x48,0xA9,0x54,0x0B,0x07,0x0A,0x11,0x51, +0x64,0x60,0x01,0x3E,0x5C,0x16,0xC6,0x7F,0xF2,0xC4,0xE4,0x7A,0xEA,0xB6,0xD0,0x1A,0xAA,0xC8,0x66,0x89,0xE9,0xD9,0x0A,0xB6,0xFA,0x88,0x14,0x87,0x47,0x78,0xF3,0xB5, +0x99,0x4E,0xE4,0x6C,0xAB,0xB6,0x76,0x9C,0x81,0xC0,0x6C,0x6D,0xD5,0xE6,0xC2,0x45,0x9C,0x55,0x13,0x31,0x20,0x10,0x9A,0x51,0x8D,0x4A,0x25,0x2C,0x31,0x5B,0xA6,0xA8, +0xA7,0x26,0x20,0x66,0xF1,0x1A,0x55,0x50,0xA4,0x91,0x04,0x20,0xB3,0x67,0x73,0x63,0x7B,0xB0,0xCF,0x72,0x3E,0x93,0xA0,0x75,0x94,0xB0,0xBD,0xED,0xE2,0x4F,0x0D,0x64, +0x0E,0xEB,0x3D,0x51,0x75,0x72,0x19,0x81,0xCA,0x84,0xC6,0xC7,0xF2,0xEF,0x00,0xA7,0x19,0x7F,0x5C,0xE7,0x4C,0x0F,0x4B,0x73,0xAA,0xA3,0x48,0x64,0xA3,0x7A,0x59,0x48, +0x67,0xA7,0x94,0x53,0xF8,0xA6,0x22,0xB8,0x21,0x50,0xC6,0xA1,0x37,0x9F,0x2E,0x79,0x20,0x67,0x1B,0xB8,0x20,0xF0,0x5D,0x45,0x33,0x55,0xC1,0x4C,0xF1,0x2A,0xD4,0x46, +0xA1,0xC5,0x34,0x48,0xEA,0x91,0x77,0x1B,0xA5,0x7C,0x20,0xC7,0x00,0xB1,0x2F,0x8C,0x9E,0xCB,0xBB,0x9E,0x29,0xE4,0x26,0xD7,0x5F,0x48,0x33,0x2F,0x6C,0x97,0x68,0xA0, +0x81,0x29,0xA4,0x2B,0xF3,0x32,0xC4,0x24,0x5F,0x96,0x5D,0xA2,0x30,0x41,0x6F,0xAB,0x23,0x70,0x07,0x8F,0x5C,0x71,0xC8,0xC6,0x90,0x7A,0xB3,0xE1,0xFD,0x15,0x7D,0xD6, +0x20,0xCF,0x54,0x0B,0x40,0x92,0x48,0xFC,0x3C,0xA4,0x61,0x95,0x0A,0x93,0xF5,0x60,0x2E,0x0A,0x82,0x73,0xB7,0xD0,0xF3,0xA6,0xE1,0x43,0xFD,0x4B,0xC5,0x9C,0x50,0xAA, +0xBC,0x6E,0xC8,0x23,0xE7,0x62,0xA2,0x16,0x50,0xB8,0x2A,0x36,0x85,0xE3,0x92,0x32,0x49,0x07,0xD3,0x95,0xBB,0xD5,0xF2,0xA6,0xCF,0x2A,0xFF,0x00,0x53,0xB5,0xC9,0x2C, +0x2A,0x87,0xC0,0x90,0x9C,0xE1,0xBB,0x9D,0xA4,0x92,0xDB,0x4A,0xEF,0x1C,0x76,0x19,0xE3,0x18,0xC4,0xD2,0x35,0xF7,0xCC,0x15,0x68,0x89,0x6B,0x8B,0x42,0x9C,0xD3,0x1E, +0xB5,0xE9,0x7A,0x97,0x82,0xCB,0x51,0x2D,0x74,0x50,0x86,0xDA,0x69,0xFC,0xF2,0x2A,0x8E,0x4A,0x94,0xFA,0xC0,0x19,0xFA,0x58,0x63,0xBE,0x3B,0x92,0x4B,0x4F,0xF1,0x2B, +0xE2,0xBC,0xB4,0xE9,0x6D,0x4B,0x4C,0xB1,0x4A,0xE3,0x00,0xAD,0x0B,0x46,0xC0,0x0E,0xE4,0x93,0x81,0xEB,0xEB,0xAA,0x35,0xA2,0x9F,0xA7,0xFA,0x9A,0x58,0x8D,0x65,0xE6, +0x96,0xE9,0x38,0x6C,0x29,0x7A,0x64,0x7A,0x90,0x30,0x48,0x05,0x93,0x6C,0x98,0x1C,0x02,0x48,0xE3,0xD4,0xF6,0x23,0xB2,0x8A,0x3A,0x18,0xE9,0x84,0x12,0x5D,0x69,0xC2, +0x86,0x4C,0x2C,0x35,0xB2,0xB9,0xE5,0xBE,0x9F,0x0D,0x08,0x60,0x41,0xF5,0x3C,0x65,0xBB,0xE7,0x00,0xD3,0x96,0x86,0x8E,0x67,0xF8,0x92,0xC6,0x0B,0xBC,0xEC,0x8A,0x41, +0x5D,0x5F,0x13,0x32,0x46,0xE3,0x95,0x41,0xA9,0xBA,0x77,0xAF,0x7A,0x9B,0xA9,0x23,0x6B,0xC5,0x9E,0xF0,0x16,0x67,0x08,0xF5,0x13,0xC1,0x96,0x8C,0x77,0xC2,0x23,0x15, +0xC9,0xC6,0x7C,0xB9,0x1D,0xF3,0xEE,0x75,0x5B,0x87,0xE1,0x77,0x52,0xD0,0x74,0xA4,0xBF,0x23,0x6C,0x92,0x48,0xDA,0x7F,0x11,0xA5,0x96,0xBA,0x96,0x04,0x0F,0x10,0x05, +0x37,0x21,0x95,0xB6,0xF0,0x64,0x04,0x6E,0x0D,0xE7,0x27,0x3E,0x5C,0x13,0x2D,0x5F,0x65,0xA0,0xAE,0x13,0x41,0x57,0x57,0x25,0x4A,0x12,0x04,0x10,0x49,0x3C,0xE7,0xCC, +0x00,0x60,0xF1,0x31,0x59,0x01,0xF4,0x38,0x66,0xCE,0x48,0xC1,0x1A,0x19,0x76,0xB9,0xAD,0xF1,0x26,0xA4,0x66,0x95,0x9A,0x38,0xB6,0xAB,0xCD,0x51,0x18,0xF0,0x13,0x0B, +0x80,0xC8,0x8C,0x3C,0x25,0x04,0x7D,0x20,0xEE,0x39,0x39,0xCF,0x3A,0xBE,0xEA,0x78,0xDE,0xD6,0xDB,0x65,0x0C,0x93,0xCC,0x09,0x24,0x75,0x4A,0x7F,0x11,0x22,0xE9,0x96, +0xA1,0x9E,0x18,0xEA,0x62,0x6B,0xC5,0x1D,0x52,0x53,0xCC,0x23,0x50,0x9E,0x2A,0x98,0xF3,0xBD,0x40,0x66,0xC9,0x04,0x05,0x3C,0x9C,0x76,0xEC,0x06,0x57,0x12,0xC9,0x57, +0x6D,0x7A,0x06,0x55,0x8D,0x65,0x75,0x0D,0xB1,0x09,0x20,0xE3,0xBF,0x88,0xAD,0xF4,0xE3,0x20,0xF0,0x4A,0xF2,0x08,0xF5,0xCF,0x54,0xB6,0x48,0x2E,0x7D,0x65,0x4B,0x69, +0xB3,0xC9,0x05,0x79,0x11,0xB3,0xCF,0x3D,0x4A,0x36,0xD3,0x20,0x52,0x4B,0x21,0x03,0x81,0x82,0x36,0xF1,0xFA,0xE9,0x9A,0xFF,0x00,0x43,0x9E,0xA2,0xA4,0x96,0x82,0xB9, +0xA9,0x27,0x86,0x94,0xA8,0x56,0x90,0xBA,0xAA,0x8E,0xF9,0xC9,0x3E,0x50,0x06,0x38,0x0B,0xD8,0x70,0x34,0x2E,0xB8,0x39,0x9E,0xE8,0xEA,0x8A,0x61,0x6C,0x64,0xCD,0xCA, +0xFD,0x57,0x1C,0x74,0x15,0xB5,0x5D,0x42,0x7F,0xAE,0xC3,0x0A,0x47,0x0C,0xCA,0xC2,0x3A,0x3C,0x78,0x58,0x6E,0x01,0xCC,0x5C,0x01,0x9F,0x6C,0xB1,0xF4,0xD1,0xDA,0x19, +0x07,0x4C,0xD7,0x4B,0x7D,0xA5,0xC4,0x54,0x33,0x23,0x49,0x0B,0x2C,0x58,0x0D,0x2F,0x87,0x85,0x00,0x16,0xCA,0xE1,0xD8,0x90,0x58,0x93,0xC2,0x96,0x00,0x91,0x83,0xD7, +0x6B,0x49,0xA3,0xB9,0xA7,0xCC,0x16,0x85,0x80,0x8A,0x45,0x10,0x41,0xB6,0x13,0x84,0x42,0x5B,0x1C,0x2E,0xEC,0x31,0xED,0xF9,0xD7,0x44,0x51,0x43,0x75,0x92,0xE5,0x61, +0xAD,0xA3,0xA6,0x35,0x54,0xA1,0x6A,0xE8,0xB2,0xA0,0x9D,0xA1,0x86,0x5B,0x01,0x40,0x00,0x67,0xBF,0x3F,0x50,0xC0,0x3A,0x8E,0x90,0x09,0x25,0x73,0x6F,0x65,0x26,0x25, +0x4D,0xEC,0xB4,0xC2,0x46,0x82,0x12,0x9F,0x4D,0x57,0xD7,0x5C,0x7E,0x20,0x47,0x78,0xF0,0xED,0x74,0x4F,0x4F,0x33,0x89,0x21,0xAF,0x55,0x98,0xD5,0x39,0x46,0x23,0x29, +0xC6,0x36,0xE3,0x82,0x30,0x77,0x1C,0x8E,0x70,0x47,0x37,0x56,0xFC,0x3D,0xB8,0x55,0xDD,0x67,0xA8,0x9A,0xEE,0x0C,0xA8,0xC4,0x9A,0x69,0x29,0x64,0x59,0x22,0x0E,0xCC, +0xC4,0xEC,0x76,0x67,0xF0,0xC3,0x1F,0xA8,0x06,0xE1,0xB3,0xEF,0xAD,0xD7,0xB9,0xA8,0xAD,0x1D,0x56,0x67,0x9A,0xEE,0x29,0x6E,0xD1,0x82,0x85,0xD1,0x15,0xA2,0xA9,0x50, +0x36,0x11,0x22,0xC6,0x09,0x0E,0x78,0xC9,0xDA,0x73,0x9C,0x80,0x4F,0x21,0xB2,0xD1,0x3F,0x57,0x5C,0x20,0x11,0x4B,0x64,0x9E,0x6A,0x2C,0xED,0x87,0xC7,0xA3,0x01,0x07, +0x38,0xF2,0x1C,0x73,0xC0,0xC8,0x2D,0x1E,0x7F,0x5F,0x43,0x31,0x51,0xB8,0xBB,0x30,0x69,0x3F,0x2B,0xA5,0x77,0x55,0x06,0x34,0x73,0x80,0x3B,0xA9,0x05,0x4F,0xC3,0xCB, +0xD5,0x1D,0x63,0x49,0x49,0xD5,0x7D,0x3D,0x4D,0xB4,0x0F,0xEF,0xA5,0xC9,0x50,0x9E,0x70,0x17,0x6F,0xD5,0xF7,0xE4,0x70,0x3D,0x74,0x4E,0x86,0xC9,0x79,0x6A,0x51,0x42, +0x7A,0xE2,0xAE,0xEF,0x5C,0xDE,0x58,0xA0,0xB4,0x45,0x34,0xEE,0x8F,0xEB,0x82,0xC8,0xAB,0x9F,0x62,0xAE,0x31,0xE8,0x0E,0x78,0xB3,0x55,0x5A,0x6B,0xCC,0x7E,0x35,0x5F, +0x49,0x48,0xF3,0x48,0x72,0x2A,0xA1,0x96,0x57,0x61,0x8E,0xE4,0x23,0x95,0x0A,0x7B,0x72,0x0E,0x7E,0xFF,0x00,0xE3,0xAE,0x5A,0xAE,0xBC,0xB3,0x74,0x85,0x03,0x96,0xB0, +0xD7,0xD2,0x4C,0x63,0x3E,0x2B,0xCD,0x28,0x3E,0x31,0x1C,0xF2,0xA4,0xBE,0xD1,0xBB,0x9E,0x09,0x27,0x3D,0xC6,0x06,0x64,0x92,0x8E,0xD6,0xCF,0x17,0x4E,0x86,0xDA,0xE9, +0xF1,0x0A,0xC4,0x15,0x46,0x56,0xE4,0x64,0xC3,0xE4,0x50,0xEB,0x07,0xC3,0xB8,0x6D,0x34,0x66,0x86,0xA6,0xDF,0x14,0x15,0x12,0xAE,0x6A,0x17,0xE6,0x1A,0xAA,0xA6,0xB3, +0x38,0x2C,0x66,0x75,0x3E,0x51,0x9C,0x1F,0x0C,0x00,0x09,0x3E,0x62,0x73,0xCB,0x07,0x52,0xF5,0x5D,0xBA,0xC5,0x68,0x6B,0x41,0xB8,0xAC,0x95,0x86,0x21,0x1B,0x0A,0x74, +0x6F,0xEC,0xB8,0xCB,0x18,0xF3,0xE6,0x04,0x79,0x93,0xEC,0x0E,0x73,0x8E,0xDA,0x4A,0x9B,0xE2,0x6D,0xE3,0xA9,0xE4,0xD9,0x43,0x6E,0xA3,0xB4,0x40,0xC0,0xA0,0x64,0x4F, +0x0D,0x8E,0x40,0xCE,0x64,0x3E,0x66,0x20,0x60,0xE7,0xDF,0x07,0xD4,0x63,0x75,0xBA,0xD9,0x4C,0x16,0x6A,0x4A,0x77,0x6A,0xA0,0x72,0x65,0xA8,0x01,0x67,0x62,0x70,0x77, +0x17,0x2F,0x91,0x8F,0xCF,0xFA,0x89,0xC6,0x30,0x23,0xC9,0x98,0x67,0x72,0xE4,0xE5,0x8B,0x96,0xF7,0x28,0x54,0x6B,0x70,0xB9,0x57,0x45,0x4D,0x00,0x67,0x3B,0xE3,0x64, +0x91,0x8C,0x52,0xB8,0x45,0xC7,0x31,0x0D,0xC0,0x6F,0xCE,0x01,0x50,0xC4,0x6D,0x2C,0x30,0x31,0xCB,0x5C,0x35,0x0F,0x3D,0xC9,0x96,0x96,0x19,0x69,0xE3,0x91,0x3C,0xF5, +0x54,0xC0,0x41,0x18,0x0A,0xCE,0xC0,0x07,0x74,0x07,0x63,0x13,0xB8,0xA0,0x7C,0x92,0x0F,0xD5,0xE5,0x24,0x76,0xE4,0x83,0xA6,0x5A,0x29,0x6A,0x48,0x9E,0x6D,0x8A,0xBF, +0x35,0x13,0x4B,0x13,0xB2,0x30,0x6C,0xA1,0x51,0x94,0x3E,0x62,0x43,0x73,0x82,0xFC,0x13,0xE6,0x1A,0x27,0xE0,0xDA,0x52,0x24,0xB7,0x46,0xD7,0x0A,0xAA,0xC9,0xB1,0x51, +0xF2,0x55,0xCA,0x8F,0x14,0x92,0x72,0xCC,0x81,0xCB,0x85,0xCE,0x1B,0x38,0x0A,0xF9,0xF4,0xDD,0x9D,0x46,0x0D,0x97,0x44,0x5D,0x37,0x5D,0xE1,0x6B,0x85,0x55,0x4A,0xDA, +0xEE,0x7B,0x9A,0x8A,0x2D,0xE9,0x49,0x1C,0xE7,0xCA,0x72,0x08,0x67,0x4C,0x09,0x17,0xB8,0xC1,0x25,0x4F,0xD5,0x85,0x39,0xC3,0x21,0xB5,0x75,0xCA,0x4B,0x94,0x90,0xDE, +0x10,0x4C,0xD4,0xE4,0x84,0x96,0xB6,0x1C,0x64,0xE4,0x05,0x27,0x01,0x91,0x1B,0x24,0xE0,0x30,0xDE,0x02,0xB0,0xC0,0x66,0xC3,0x1F,0xA1,0x58,0x7A,0x56,0xC9,0x24,0xD1, +0x4F,0x53,0x53,0x2A,0x92,0x0D,0xCE,0xA1,0x1C,0xB3,0x36,0x32,0x63,0xC0,0x38,0x43,0xE4,0xEE,0x14,0x8C,0x0E,0x5B,0x1A,0x58,0xEA,0x7A,0xC3,0x53,0xD0,0x68,0xF4,0x86, +0xDD,0xF3,0xC9,0x28,0xCA,0xC1,0x2B,0x1D,0xA5,0x41,0x7F,0x2A,0x83,0x92,0xC0,0x1E,0x58,0x81,0xB7,0x83,0x92,0x58,0x60,0x7D,0x29,0xC8,0x46,0xEA,0xDC,0xB1,0x5D,0xBC, +0xAB,0x4D,0xEA,0xB2,0x29,0x42,0x54,0xC1,0x50,0x95,0xD5,0x61,0x3C,0x08,0xA0,0x2E,0x55,0xA7,0x04,0x85,0x2F,0x92,0x00,0x5C,0x36,0x14,0x67,0x0A,0x7C,0xC4,0x0E,0x41, +0xD2,0xCF,0x51,0x5E,0xEE,0x66,0xDF,0x12,0x4F,0x14,0x4D,0x18,0xDC,0xAB,0x2C,0xB2,0x17,0x69,0x7B,0x8F,0x10,0x60,0x95,0xC6,0x39,0x07,0xFC,0xB9,0xF5,0xCE,0x7C,0x35, +0x93,0xC9,0xE0,0x3C,0xF1,0xD7,0x55,0xC4,0x19,0x59,0x69,0xD9,0x96,0x11,0x93,0xE6,0x01,0x37,0x29,0x39,0xC6,0x32,0x54,0xA9,0xC8,0x38,0xE3,0xBF,0xC3,0x2D,0xC2,0xFD, +0x78,0x79,0x6A,0x6D,0x29,0x25,0x1A,0x90,0x48,0x76,0x2C,0x11,0x43,0x6E,0x20,0x12,0x0A,0xB0,0x04,0x73,0x8C,0x96,0xFB,0xE3,0x45,0xA0,0x63,0xE5,0x20,0x37,0xE7,0xD9, +0x53,0x7B,0x9A,0xD1,0x77,0x21,0x76,0x3B,0x35,0x3F,0x50,0xDD,0xC5,0x1C,0x97,0x7A,0x6A,0x06,0x69,0x44,0x91,0x04,0x83,0x3B,0x89,0x25,0x47,0x9F,0x20,0xFA,0x0F,0x53, +0xC9,0xF4,0xD5,0x8E,0x93,0xE0,0x9D,0x34,0xB4,0x0B,0x15,0x4D,0xEE,0xB6,0x51,0x23,0x6F,0x78,0xC6,0xD6,0x5D,0xC4,0x92,0x72,0x08,0x3C,0x73,0xDB,0x4C,0x96,0x4E,0x8E, +0xE9,0xDA,0xBB,0x04,0x46,0x3A,0x08,0x5A,0x19,0x23,0x52,0x1D,0x00,0x05,0xB2,0x33,0xCE,0x3F,0x8F,0xC6,0x88,0xDB,0xED,0xB7,0x4E,0x99,0xB8,0xAB,0x2C,0xB2,0xD5,0xDA, +0xC9,0xC3,0xA4,0x8D,0x99,0x22,0x3E,0xE0,0xFA,0x8E,0xDC,0x1E,0x74,0xED,0x0E,0x19,0x05,0x3B,0x43,0x64,0x60,0x75,0xF7,0x09,0x5A,0xA3,0x17,0x92,0x77,0x16,0x53,0xB8, +0xB4,0x8D,0x8A,0x19,0x6B,0xF8,0x4B,0x64,0xB6,0x4B,0xB5,0xE9,0x28,0x6E,0x14,0xEC,0x30,0x60,0xAA,0xA6,0x07,0x9F,0x7E,0x30,0x07,0xED,0xA5,0xFF,0x00,0x88,0xBF,0x07, +0x3A,0x46,0x5E,0x91,0xAC,0xBA,0xD8,0xE0,0x96,0xCD,0x76,0xA5,0x0D,0x3C,0x69,0x11,0xDD,0x1B,0xFA,0xED,0xDA,0x72,0x00,0xFD,0x3F,0x9D,0x5D,0xA9,0x61,0x49,0xA9,0x96, +0x65,0xC1,0xE3,0xF7,0xFB,0xE9,0x6B,0xE2,0x0B,0x44,0x9D,0x22,0xF1,0x89,0x0F,0x8B,0x29,0x0A,0x84,0x80,0x40,0x6F,0x41,0xF6,0xF6,0xCE,0x7D,0x74,0x3F,0x11,0x74,0x11, +0x53,0xC8,0x72,0x8B,0x00,0xAE,0x61,0x71,0xD5,0x54,0x54,0xC7,0x19,0x71,0x25,0xC4,0x05,0x01,0xF8,0x57,0x4C,0x24,0xB6,0x9B,0xA3,0x15,0x96,0x72,0x05,0x2E,0xD5,0x8C, +0xA8,0xC9,0x55,0x50,0xC4,0x92,0x72,0x72,0xB2,0x03,0x8C,0x8C,0x77,0xC7,0x1A,0x5C,0xEB,0x49,0xCC,0x5F,0x11,0xA1,0x8E,0x2A,0x53,0x35,0x0D,0x0E,0x21,0x2B,0x36,0xEC, +0x92,0x14,0x83,0xB9,0xB3,0x9C,0x11,0xE7,0x38,0xE0,0xF2,0x39,0xCE,0x74,0xF5,0xF0,0x9E,0xDD,0x53,0x43,0x3D,0xCE,0x79,0x44,0x50,0x45,0x1E,0xE2,0x23,0x50,0xA0,0xF8, +0xC4,0xE0,0x13,0xCE,0x3B,0x16,0x00,0x63,0xBF,0xEB,0xA0,0x77,0x6A,0x38,0x2A,0x7A,0xEA,0xAD,0xB7,0x46,0xD1,0xB3,0x8C,0xAA,0x8C,0xAA,0x9C,0x72,0x31,0xDC,0x8F,0x4E, +0x3F,0x6D,0x67,0x75,0xB8,0x93,0x1C,0xF6,0x2D,0x87,0x0E,0xC0,0xA4,0x8E,0x27,0x17,0x6E,0x6C,0x9E,0x6F,0x73,0xC6,0xD7,0x68,0x61,0x8A,0x92,0x99,0x92,0x2A,0x38,0xA6, +0x77,0x11,0xE5,0x40,0x78,0xD7,0x03,0x38,0xE4,0x01,0xB8,0x69,0x7F,0xAC,0x64,0xAD,0xA1,0xB5,0xD0,0x75,0xAD,0xBA,0x74,0x8C,0xD3,0xCC,0x21,0x9D,0x90,0x67,0x6A,0x1C, +0x28,0x24,0xF3,0xDB,0x00,0xFE,0xAB,0xFB,0xB4,0xDE,0xA4,0x0C,0xB0,0xBC,0x64,0x7F,0x72,0x96,0x20,0x07,0x75,0x20,0x20,0xFE,0x38,0xE3,0x5C,0xB4,0x30,0x0B,0x8F,0x4D, +0xD5,0x51,0x54,0x2D,0x3C,0x90,0xC8,0x8D,0x1C,0xBC,0x15,0xCA,0x30,0x23,0x04,0x8E,0xFC,0x13,0xFF,0x00,0x3B,0x0A,0xA4,0xAD,0xCB,0x5B,0x25,0xF4,0x03,0xA7,0xF3,0xE6, +0x8E,0x62,0x78,0x01,0x76,0x1A,0xC0,0xDD,0x49,0x17,0x53,0x9F,0x83,0x54,0x35,0xF7,0x6F,0x8D,0x4F,0x5F,0x3D,0x1F,0xCC,0x42,0xC2,0x42,0xAD,0x34,0x40,0x84,0x50,0x78, +0xDA,0x4F,0x7E,0x71,0xDB,0xDC,0xEB,0xF5,0xDC,0x76,0x6A,0x68,0x69,0x44,0x95,0x92,0x6C,0xFF,0x00,0x47,0x23,0xF8,0x1F,0xEF,0xA8,0xFF,0x00,0xC0,0xDB,0x5C,0x54,0xB5, +0x97,0x1B,0x8C,0xE5,0xD4,0xC3,0x88,0x22,0x8C,0x67,0x08,0x32,0x4F,0xEB,0x92,0x78,0xD5,0x7A,0x7F,0x99,0xB8,0x56,0x78,0x95,0x38,0x58,0x97,0x88,0xE2,0x19,0xC6,0x39, +0xFB,0x73,0xDF,0x5A,0x8E,0x13,0x3C,0xBE,0xCE,0xD7,0x0D,0x33,0x6A,0xB0,0x9C,0x62,0x9D,0x82,0x72,0xC9,0x46,0xAD,0x00,0x5B,0x6B,0xA1,0x57,0x0A,0xD8,0x20,0x45,0x8A, +0x86,0x96,0x6A,0xC6,0x5E,0x32,0xB8,0x20,0x7D,0xF2,0x78,0xFD,0xB4,0x97,0x78,0x9F,0xA9,0xEA,0x62,0x96,0x3A,0x7B,0x45,0x10,0x89,0x97,0x85,0xA8,0x93,0x82,0x3D,0x38, +0xC7,0x3D,0xF1,0xCE,0xA8,0xD2,0x53,0xA8,0x52,0x15,0x30,0xA0,0x67,0xCA,0x00,0xC6,0x94,0x2E,0x57,0x58,0x45,0x70,0xA4,0xA0,0x8C,0xCD,0x29,0xFA,0xE5,0x3F,0x4A,0x77, +0x03,0xF3,0x9F,0x41,0xA3,0xA0,0x07,0x32,0xF2,0xC8,0x40,0xEC,0x97,0x64,0x25,0xB2,0xFD,0xDB,0x02,0x82,0x75,0x05,0xB6,0xF1,0x6C,0xA9,0x0B,0x17,0x48,0x51,0x5A,0xF0, +0xC7,0x15,0x74,0xAC,0x32,0x30,0x32,0xBC,0x71,0xEA,0x3B,0x9D,0x6F,0xA2,0xB8,0x2C,0x76,0xCF,0x0A,0x18,0x2A,0x55,0xE0,0x63,0x2C,0xD3,0xBC,0xA1,0xE4,0x52,0x41,0xF3, +0xE0,0x70,0x06,0x73,0x9C,0x10,0x71,0xB8,0x63,0x04,0x6A,0x8F,0x73,0xE9,0x5E,0xA2,0xBE,0x93,0x25,0x5D,0x44,0x68,0x4F,0xD0,0xC3,0x92,0xAA,0x0F,0x38,0x07,0xBF,0x03, +0xFF,0x00,0x7A,0x9E,0xDE,0xAC,0x17,0x7B,0x1D,0xFE,0x35,0x37,0x69,0x91,0x00,0xF2,0xB9,0x1E,0x64,0x3D,0xB1,0x95,0x00,0xE0,0x86,0x23,0x1F,0x7C,0xE9,0x72,0xBE,0x90, +0x86,0x99,0x43,0x4E,0x5E,0xFF,0x00,0xF8,0x98,0xA8,0xEB,0x23,0x90,0x06,0x12,0x2F,0xD9,0x6B,0x13,0xBA,0x74,0xDD,0x2B,0xA5,0x7C,0x55,0x4A,0xEC,0x29,0x61,0x59,0x55, +0x64,0x4D,0xC7,0x92,0x5C,0xE5,0x5B,0x73,0x01,0x81,0xC1,0x56,0xE3,0xB9,0x1A,0x6D,0xB7,0x25,0x65,0xD6,0xB4,0xC7,0x73,0x78,0xA9,0xEA,0xD9,0x97,0x14,0x70,0x39,0xFE, +0xE1,0x03,0x20,0x9D,0xC7,0x20,0x80,0x73,0xE6,0x56,0xC8,0x24,0x1D,0xE0,0x69,0x55,0x62,0xA5,0xA3,0xAE,0xA4,0xAC,0xA8,0xF0,0x1A,0x04,0x56,0x86,0xA2,0x36,0x94,0x46, +0x08,0xC1,0x0A,0xCD,0xB8,0xE4,0x90,0x31,0xEA,0x72,0x40,0xE4,0x1D,0x77,0x59,0x6B,0x6E,0x75,0x57,0x89,0x23,0xB8,0xA7,0xCB,0x96,0x57,0x4A,0x1A,0xF6,0xA7,0x99,0x43, +0x80,0x3D,0x06,0x38,0x21,0x72,0x33,0xC8,0xC8,0x20,0x83,0x8C,0x95,0xC9,0x1C,0x58,0xFB,0x0D,0x91,0x86,0x92,0xE1,0x70,0x17,0x7D,0xCD,0xA7,0xBE,0xD4,0xAD,0x04,0xB0, +0xD4,0x41,0x4F,0x2F,0x9B,0xC2,0x69,0x5D,0xEA,0x64,0x0C,0xA0,0x06,0x0B,0xE1,0x94,0x0B,0xCB,0x70,0xE4,0x70,0x7B,0x1E,0x32,0x2E,0xD5,0xD1,0xB4,0x36,0x35,0x92,0x4B, +0x97,0xC9,0x4E,0x69,0x89,0x8A,0x2A,0x55,0x8E,0x22,0x22,0x0C,0x46,0x09,0x63,0xB8,0xB7,0x00,0x7D,0x58,0x3D,0xB0,0x08,0xC6,0xA8,0x14,0x8F,0x5B,0x25,0xAC,0xD2,0xC8, +0x7E,0x7E,0xE9,0x29,0x76,0x1F,0x27,0xB2,0x18,0xC8,0x2D,0x92,0x4B,0x32,0x20,0x62,0x33,0xDC,0x79,0xBD,0xBD,0xB4,0x09,0xF7,0x52,0xD1,0xD4,0x57,0x67,0x36,0xEA,0x79, +0x9A,0x19,0x26,0x92,0xA1,0x5A,0x39,0x1B,0x1F,0x51,0x2A,0x9F,0xDC,0x39,0x3D,0x9B,0x76,0x33,0xD8,0x63,0x1A,0xA9,0x47,0x1B,0x45,0xDA,0xA7,0x96,0x52,0x5B,0xA2,0x9C, +0x5C,0xAE,0x54,0x31,0xD0,0xCD,0x1D,0x9A,0xDD,0x04,0x95,0x01,0x18,0x3E,0xC8,0x43,0x6C,0x00,0x64,0x33,0x15,0x5E,0x14,0x1D,0xC0,0xFA,0x8D,0xA3,0x81,0xC1,0xD5,0xCB, +0xA1,0xEC,0xB4,0x63,0xA2,0x28,0xA4,0x58,0xD6,0x48,0xA5,0x89,0x64,0x65,0x0B,0x8D,0xC5,0x86,0x4F,0x6E,0xFD,0xCF,0x3A,0x97,0x5C,0x28,0xA9,0x7A,0x86,0xB1,0x69,0x60, +0xA3,0xCC,0x6B,0x30,0xF9,0x6A,0x91,0x4E,0x62,0x8C,0xE3,0xEB,0x21,0x5F,0x07,0x3E,0x99,0x0A,0xBD,0xC6,0x3D,0xF5,0x5B,0xE8,0xB8,0xE6,0xA4,0xE9,0xD8,0x28,0x67,0x5D, +0xBF,0x2A,0x5A,0x9C,0xE1,0xB8,0x1B,0x58,0x80,0x7B,0xF3,0xC1,0x1C,0xFD,0xB4,0xF9,0x80,0x44,0x6C,0xFD,0x34,0x23,0x43,0xF0,0x4A,0xB8,0xEB,0xB9,0x1A,0x6F,0xAD,0xF5, +0x5D,0x16,0xDA,0x53,0x63,0xBC,0x49,0x45,0xE1,0x2A,0xD1,0xD4,0x83,0x2C,0x08,0x4F,0xD2,0xC0,0x0D,0xCB,0xCF,0x20,0xF1,0x91,0xFA,0x9D,0x34,0x88,0x96,0xA2,0x3D,0xB2, +0x00,0x08,0xEF,0xBC,0x1E,0x75,0xCD,0x72,0xA0,0x15,0x76,0xC5,0xA8,0x84,0xA8,0x9A,0x22,0x19,0x19,0x8E,0x36,0xB0,0xE7,0xFD,0xFF,0x00,0x7D,0x74,0xD0,0x54,0x3C,0xD4, +0x71,0x4B,0x14,0x67,0x90,0x32,0x33,0x9C,0x7B,0xFF,0x00,0x39,0xD1,0x82,0xE3,0xE1,0xE5,0x1B,0x20,0xF1,0xC5,0xF7,0x99,0x8E,0xFA,0xA2,0x16,0x84,0x48,0xE6,0x34,0x92, +0x1E,0x08,0x3B,0x7F,0xE7,0xDB,0x40,0x3E,0x26,0xA9,0x8F,0xA4,0x6A,0x30,0x4A,0x1D,0xCA,0xA7,0x6F,0xA7,0x3E,0x9F,0x7E,0x34,0x69,0x1C,0x09,0x44,0x91,0x90,0x08,0x20, +0x9C,0x9E,0x0F,0xBE,0x80,0x7C,0x59,0x6D,0xDD,0x1E,0xAC,0x5F,0x61,0x79,0x11,0x38,0x38,0xDD,0xDF,0x83,0xEF,0xFF,0x00,0xF7,0x4A,0xB8,0xE9,0x73,0x28,0xA7,0xEE,0xD2, +0x9E,0x78,0x59,0x82,0x5C,0x42,0x99,0xA3,0xFD,0xC2,0x9A,0x58,0xC8,0xA4,0xE8,0xA9,0x6A,0x0A,0x10,0xD5,0x12,0xBB,0x2B,0xA9,0xF3,0x36,0xD3,0x8F,0x7C,0xE3,0xCC,0x7B, +0xFE,0xBA,0x55,0x8E,0x9E,0x49,0x6F,0xA2,0x51,0xB5,0x18,0xF3,0x84,0x62,0x77,0x64,0xFA,0xFB,0x7E,0x34,0xE7,0x39,0x96,0x9E,0xC7,0x4D,0x09,0x70,0x57,0x69,0xDC,0x5B, +0x20,0x9C,0xE7,0x9F,0xF6,0xE4,0x77,0xD0,0xBB,0x64,0x54,0xD5,0x35,0x89,0x21,0x55,0x58,0x90,0x0C,0x2B,0x64,0xE7,0xD3,0x24,0x9F,0x5F,0xF6,0xD6,0x47,0x2C,0xAE,0xF1, +0x63,0x1D,0x82,0xF4,0x9B,0x29,0x1A,0x62,0x21,0xCD,0xD6,0xF7,0xD3,0xB2,0xEE,0xB9,0x3F,0x87,0x4B,0x09,0x97,0x71,0x65,0x8D,0x06,0xEC,0x9C,0x0C,0x0F,0xA7,0x9D,0x6E, +0xB6,0xCF,0x23,0xC6,0xF1,0xC4,0xAC,0x43,0x29,0x00,0x00,0x70,0x38,0xFE,0x47,0xBF,0xE3,0x5F,0x15,0x8F,0x0A,0xCE,0xCA,0x64,0x57,0x24,0x71,0x84,0x00,0x63,0xDB,0x8F, +0xD3,0x5E,0xDA,0x32,0xCE,0xE8,0xB2,0x76,0xF3,0x02,0x07,0xAE,0x38,0xE0,0xEA,0x20,0xE7,0x3A,0xBC,0xEB,0xD5,0x59,0x74,0x2C,0xF6,0x21,0xCB,0x6B,0x26,0x5F,0x86,0xD4, +0xA9,0x49,0x2D,0xE2,0x98,0xB8,0x2C,0xD5,0x42,0x42,0xA1,0x89,0xE4,0xAE,0xEE,0xDE,0x83,0x2C,0x75,0x4E,0x45,0x2E,0xA8,0x13,0xCC,0x7B,0x13,0xA4,0x0E,0x88,0x81,0x7F, +0xA9,0xDC,0xE6,0x52,0xA1,0xA5,0x92,0x35,0xF2,0xAE,0x30,0x04,0x63,0x8E,0x47,0xDF,0x54,0x70,0x9F,0x29,0x42,0xC1,0x80,0x1C,0x70,0xD9,0xF7,0xED,0xAD,0x97,0x08,0x70, +0x6D,0x04,0x36,0x1B,0x7D,0x4A,0xF3,0x0F,0x13,0x46,0x3E,0xD6,0xA8,0x03,0xA0,0x3F,0x40,0x80,0xDF,0x1E,0x5A,0x99,0xDA,0x8A,0x90,0x98,0xE3,0xC6,0x1E,0x50,0x39,0xFD, +0x01,0xF4,0x3F,0x7D,0x0A,0x16,0xD8,0x29,0x99,0x7C,0x30,0x02,0x72,0xCD,0xC0,0xE7,0xF5,0xD1,0xC5,0x81,0x15,0x0C,0xA1,0x42,0x96,0xF4,0x27,0xB6,0x87,0xD6,0x48,0xD1, +0x53,0x33,0xC6,0x3C,0xF2,0x70,0xAA,0x07,0xAF,0xDF,0x4D,0x14,0x61,0xA0,0x5D,0xC9,0x1E,0xBD,0x85,0xE6,0xE1,0x2F,0xDC,0xAF,0x20,0x5C,0xD6,0xD7,0x40,0x86,0x4A,0x92, +0x32,0x5C,0xF0,0xA9,0xFB,0x1E,0xDA,0x99,0x75,0x55,0xA6,0xE5,0x49,0x71,0x82,0xAE,0xB9,0xEA,0xE7,0x59,0x64,0x29,0x2B,0x41,0x85,0x2B,0xFF,0x00,0xE4,0xFA,0xFE,0x7B, +0xEA,0xB7,0x68,0xB3,0xC7,0x45,0xBA,0x66,0x07,0xC5,0x72,0x1D,0x8B,0x71,0xB9,0xB1,0xDC,0x11,0xF8,0xD0,0x5E,0xBA,0x31,0x7F,0x4E,0x12,0xCC,0x8B,0x23,0x6E,0x5D,0x9C, +0x9C,0xA9,0xCF,0xDB,0xF4,0xD5,0x7C,0x42,0x95,0xD3,0xB0,0xB9,0xEE,0xE8,0xA6,0xA3,0xA9,0x6D,0x3B,0xD8,0xC6,0xB6,0xE4,0xF5,0x48,0x49,0xF2,0x37,0x47,0x82,0x39,0xC2, +0x57,0xC9,0x00,0xC8,0x92,0x7D,0xE6,0x44,0x6C,0x71,0x95,0x3D,0xCF,0x39,0x27,0x96,0x1F,0xF7,0xE9,0x5B,0x2F,0xF5,0x0A,0x19,0x2D,0x94,0x15,0x94,0x53,0x52,0x89,0x9B, +0x73,0x54,0xBB,0x81,0x14,0xA3,0x03,0x6E,0x58,0x13,0x81,0xDC,0x0F,0x30,0x1C,0x67,0x00,0xE3,0x5D,0x14,0xF4,0xD4,0x94,0xF6,0xF3,0x3D,0x2C,0x93,0x46,0xC5,0xD9,0xDA, +0xA6,0x9A,0x65,0x2E,0xB9,0xCE,0x42,0xED,0x1B,0x87,0x1C,0x9C,0x06,0x3D,0xF9,0x1D,0xC1,0x7B,0x65,0x05,0xBD,0x28,0xCD,0x65,0x25,0x43,0x90,0x63,0xCB,0xFF,0x00,0xD3, +0xF9,0xA4,0x00,0x0C,0xE7,0x07,0x7E,0xEE,0x46,0x49,0xEC,0x39,0xE4,0x69,0x46,0xA2,0x22,0x4D,0xC8,0xE8,0x99,0xE3,0x90,0xE8,0xD0,0x50,0x4A,0x98,0xA1,0x8E,0xDD,0x34, +0x54,0x7B,0x29,0x18,0x29,0x77,0x79,0x5E,0x27,0x92,0x50,0xBF,0x57,0x91,0x77,0x7A,0xE7,0x2D,0x81,0x8C,0xFA,0x71,0x94,0x6B,0xB5,0xD8,0xCF,0x47,0x34,0x76,0x19,0x17, +0xC6,0x64,0x06,0xA1,0x26,0x8B,0x6D,0x4C,0x98,0x23,0x84,0xF1,0x15,0xB6,0x8F,0xCF,0x1C,0x67,0x19,0x18,0x63,0xA8,0xB2,0xC1,0x5F,0x70,0x85,0x2B,0xAD,0x77,0x18,0xA1, +0x9E,0x47,0x8A,0x57,0xA6,0x11,0xCF,0x51,0x54,0xC9,0xE6,0xF3,0x6D,0x2A,0x23,0x89,0x77,0x73,0x92,0x46,0x00,0xED,0xDF,0x42,0xFA,0xCE,0xF4,0x6C,0x14,0xD3,0x52,0xD3, +0xD0,0xD4,0x3C,0x0E,0x86,0x24,0x96,0xA2,0x36,0x10,0xC5,0xC7,0x28,0x36,0x93,0x96,0x5F,0x31,0x19,0x00,0x0C,0xF6,0x23,0x07,0x40,0xA9,0xDA,0x1A,0x2E,0x3D,0xE4,0x62, +0x40,0x36,0x2B,0xEF,0xE1,0x6D,0x1B,0x1E,0xB5,0x28,0xEF,0x51,0x52,0x5E,0x2C,0x48,0x2A,0x18,0x9F,0x0D,0x81,0xCF,0x97,0x24,0x8C,0x70,0x73,0x9C,0x83,0x9F,0xB6,0x35, +0x64,0xA0,0x89,0xA8,0x7A,0xA2,0xE1,0x4B,0x2B,0xB1,0xF1,0x02,0xD4,0xC6,0x87,0xB7,0x6D,0xAC,0x3F,0x18,0x1F,0xB8,0xD4,0xBF,0xE0,0x55,0x04,0x69,0x9A,0xE4,0xA8,0x57, +0xF9,0x96,0x96,0x5F,0x11,0x54,0x2A,0xED,0xC8,0x03,0xB2,0xA9,0x3C,0x1E,0xF8,0xD5,0x76,0xF3,0x28,0xA7,0xBB,0xDB,0x6A,0xCA,0xB1,0x52,0x5A,0x12,0x71,0xC7,0x99,0x4F, +0x7F,0xB6,0x40,0xD6,0x9D,0x86,0xC5,0xE1,0xD3,0xC6,0x0F,0x95,0xD2,0x2E,0x31,0x28,0x92,0xA1,0xE0,0x74,0x16,0x47,0x20,0x0A,0xD1,0x18,0x5D,0x01,0x1E,0xFD,0xB5,0xA6, +0xDB,0x1A,0xD3,0x55,0xCD,0x12,0xB3,0x3A,0xE4,0xB1,0xDC,0x31,0xCE,0xBC,0xA5,0x3B,0x95,0x77,0x72,0xA3,0xD4,0x76,0xD7,0x44,0x71,0x47,0x1D,0x53,0x18,0x43,0x79,0xBC, +0xCA,0x71,0xFB,0x8D,0x71,0x33,0x72,0xB9,0x7D,0x4A,0xEC,0xCD,0x0B,0xEB,0x63,0xF8,0x9B,0x19,0x8F,0x6E,0xC3,0xD7,0x9C,0x69,0x6B,0xE2,0x10,0x92,0xA3,0xA4,0x69,0x15, +0x8B,0x1F,0xFA,0x95,0x04,0x1F,0x5C,0x06,0xED,0xF8,0xC6,0x9B,0xAA,0x95,0x96,0x54,0x77,0x88,0x47,0x91,0x92,0x01,0xC9,0xD2,0x9F,0x5C,0xA7,0x8F,0x61,0xA6,0x88,0x1D, +0xA4,0xD5,0x2E,0x31,0xCF,0xF8,0x9E,0xDA,0x5E,0xE2,0x53,0x7C,0x36,0x57,0x76,0x4E,0x1C,0x10,0x2D,0x8D,0x53,0xB4,0xEC,0xEF,0x44,0x81,0x73,0x96,0x46,0xB4,0x87,0x20, +0x79,0x70,0x80,0x16,0xE4,0x64,0x1C,0x7A,0x76,0xD7,0x15,0x95,0x96,0x69,0xF6,0xCC,0xE0,0x20,0x53,0xE6,0x0B,0xFF,0x00,0x6F,0xCE,0xBC,0xBC,0x02,0x19,0x57,0x79,0xE7, +0x92,0xA7,0xB0,0x3D,0xB5,0xED,0x92,0x97,0xC6,0x60,0x84,0xAE,0xD7,0x39,0x3B,0x71,0xC0,0x3F,0x9F,0xE3,0x58,0xC0,0x61,0x9A,0xAC,0x58,0x74,0xB2,0xF5,0x4B,0xC0,0x8A, +0x02,0x49,0xF9,0xAE,0xCB,0x9C,0x26,0x16,0x8D,0xD8,0x1D,0xC4,0x03,0x8C,0x93,0xFF,0x00,0x7F,0xCE,0xB9,0xED,0x72,0x95,0xAB,0x2B,0x18,0x0A,0x5C,0x63,0x03,0xD7,0x44, +0x2E,0x54,0xF4,0xFF,0x00,0x2E,0xAC,0x67,0xDA,0xE0,0x7D,0x27,0x07,0x70,0x3E,0xFC,0xF0,0x3F,0x9D,0x09,0xA2,0x8C,0x7C,0xDA,0x28,0xDC,0x39,0xDB,0x95,0xD7,0x15,0x99, +0xA2,0xAD,0x6D,0x97,0x14,0xE4,0x4F,0x4E,0x43,0x95,0x2B,0xE1,0xA3,0x3D,0x54,0xF7,0x49,0x66,0x39,0xC4,0xC0,0x0F,0x36,0x4F,0xD0,0xA3,0x27,0x3F,0xF8,0xD3,0xF5,0xC5, +0xC4,0xD5,0x42,0x91,0x58,0x08,0xE1,0xC1,0x7C,0x0E,0xED,0xED,0xA4,0x8F,0x86,0xC4,0x41,0x43,0x77,0x9D,0x94,0x85,0x5A,0xA2,0x0E,0x46,0x3B,0x46,0x9F,0xED,0xA6,0xB5, +0x2F,0x2C,0x01,0xD9,0x00,0x79,0x5B,0x7B,0x7A,0x91,0x93,0x9E,0x3F,0x7D,0x6E,0x18,0x53,0x2F,0x04,0x39,0xB6,0x68,0x5E,0x5B,0xE2,0xA7,0xB4,0x62,0x95,0x39,0x77,0x71, +0xFA,0x2C,0x63,0xE2,0xB1,0x76,0xC9,0x89,0x73,0xC6,0x7B,0xE8,0x5A,0xC4,0xF5,0x55,0xC6,0xA1,0xC1,0x08,0xBC,0x2F,0xE3,0xBF,0xE4,0xF1,0xA2,0x77,0x19,0x63,0x8A,0x95, +0x62,0xDC,0x79,0x1E,0x61,0x9C,0xF0,0x75,0xAA,0x9E,0x9C,0xC7,0x49,0x81,0xB0,0x67,0x3C,0x8F,0x41,0xED,0x8D,0x1C,0x8E,0x4C,0xA2,0xC9,0x49,0xF1,0x03,0xCC,0x57,0x1D, +0x49,0x0D,0xE6,0x75,0x18,0x51,0xC6,0x32,0x02,0xE7,0xF4,0xD2,0xBD,0xCE,0x81,0x6E,0xB3,0x96,0x96,0x32,0xE9,0x1E,0x55,0x19,0x8F,0x73,0x8E,0x49,0xC7,0x38,0xE7,0x1D, +0xF4,0xC1,0x74,0xA8,0x5A,0x6B,0x64,0xD3,0xC8,0xDB,0xD5,0x0B,0x65,0x40,0x27,0x9F,0x4F,0xE7,0x5C,0x74,0xAB,0x22,0x5B,0xD5,0xD8,0x06,0x0E,0xBB,0x98,0xFF,0x00,0x3C, +0x0E,0x71,0xDF,0x44,0x0B,0x03,0xDA,0x1A,0x50,0x27,0x12,0x1E,0x5E,0x3A,0xED,0xF1,0x52,0x19,0x25,0x9A,0xD9,0x7C,0x68,0x24,0x66,0x90,0x06,0x28,0x16,0x1C,0x09,0x00, +0x3D,0x8E,0x0E,0x07,0xD4,0x78,0xFD,0x7D,0x08,0x18,0x61,0xA3,0xBD,0xCD,0x47,0x57,0x15,0xBE,0xE7,0x2B,0x56,0x53,0xCA,0x18,0x94,0x96,0x95,0xA3,0x90,0xF6,0x5F,0x3A, +0x96,0x0A,0x70,0x72,0x32,0x41,0xED,0xEF,0x81,0xA5,0x8E,0xA1,0xAC,0xE9,0xAB,0x77,0x57,0x48,0x97,0x09,0x04,0x6F,0xBC,0xB9,0x99,0x23,0xDD,0xB5,0x87,0xA9,0x2D,0x80, +0x47,0x6E,0xD9,0x3F,0x6D,0x33,0xD0,0xCD,0x25,0xCE,0xD3,0x0D,0x63,0xD4,0xAB,0xC5,0x22,0x95,0x86,0x59,0x24,0x68,0xD6,0x4C,0x0E,0xC5,0x54,0x82,0xAD,0x8E,0x38,0x3C, +0xE3,0xB7,0x03,0x48,0x15,0x27,0x2C,0xAE,0x6B,0x4D,0xC5,0xD3,0x7D,0x3B,0xB3,0x35,0xAF,0x78,0xB6,0x89,0x7A,0xE5,0xD4,0x54,0xD6,0xDB,0x2D,0x5D,0x53,0x57,0x01,0x1D, +0x12,0x17,0x96,0x1F,0x1D,0x2A,0x65,0x92,0x42,0x40,0x51,0x29,0x50,0xB8,0xC9,0x65,0xE3,0x9C,0xE3,0xE9,0xF6,0x9B,0xF5,0x9D,0x75,0xE6,0xEB,0x5C,0x6A,0xFF,0x00,0xA9, +0x9B,0xA5,0x32,0xC6,0xBB,0x80,0xDE,0x63,0x88,0x6D,0xC9,0x19,0xE0,0x77,0xE4,0x0C,0xE7,0x8C,0xF3,0xC6,0x8D,0xF5,0x45,0xDA,0x93,0xA9,0x23,0xA3,0x92,0x19,0x63,0xA4, +0xAA,0x89,0x43,0xCB,0x4E,0xD1,0x96,0xF0,0xC9,0x52,0xAA,0x41,0x5C,0x16,0x38,0xCE,0x09,0xCB,0x65,0xF8,0x2A,0x09,0x25,0x6A,0xFF,0x00,0x7C,0x78,0xAD,0x72,0xD3,0x55, +0x3C,0xF0,0xE6,0x36,0x8D,0x25,0x45,0xDA,0x95,0x60,0x0C,0x32,0x82,0x32,0xC3,0x27,0xD0,0x1C,0x70,0x7D,0xCE,0x83,0x52,0x30,0x17,0x37,0x64,0xCC,0xE1,0x61,0x75,0x70, +0xF8,0x7D,0x6E,0x8E,0xC9,0xD3,0x1D,0x3C,0x62,0x05,0x16,0xA6,0x9C,0x97,0xE7,0x38,0x67,0xC3,0x72,0x77,0x73,0xC6,0xA8,0xB7,0x6B,0x78,0xA8,0xB0,0x49,0x93,0xB0,0xA7, +0x99,0x46,0x48,0x0A,0x47,0x20,0xE7,0xDB,0x3A,0x9C,0xD9,0x6B,0x76,0xFC,0x22,0xB0,0x5D,0xE0,0x8C,0x81,0x07,0xCB,0xC9,0x22,0x28,0x24,0xAA,0x61,0x41,0xCF,0x3C,0x7D, +0x47,0xF6,0xD5,0x42,0xDF,0x30,0xAC,0xB6,0x18,0xD8,0xE4,0xBC,0x7D,0x87,0xA6,0x47,0x7D,0x6A,0xD2,0xE9,0x0B,0x7C,0x3D,0x80,0xF4,0x59,0xB1,0x17,0x9C,0x99,0x37,0x27, +0xD5,0x69,0xB1,0xD4,0x47,0x5D,0x6E,0x82,0x7F,0x36,0x5D,0x01,0x23,0x69,0xE1,0xBD,0x47,0xE0,0xF1,0xA3,0x53,0x9F,0x24,0x45,0x53,0xCE,0x87,0xCC,0x73,0xDC,0x7E,0x9A, +0x54,0xE9,0xC9,0x3F,0xA7,0xDC,0xE5,0xA0,0x98,0x3E,0xD6,0x93,0x7C,0x7B,0xD7,0xB1,0xE3,0x70,0xE7,0xF2,0x7F,0x3A,0x77,0xA9,0x8D,0x3E,0x48,0x93,0xBB,0x24,0x76,0xCF, +0xF3,0xA1,0xB5,0x6F,0xE6,0x08,0x95,0x33,0x32,0x82,0x7C,0x97,0xD5,0xC2,0x3C,0x51,0xC6,0xCC,0xA3,0x2B,0x9C,0x30,0xF5,0xD4,0xFB,0xAD,0xA7,0x73,0x4D,0x49,0xB5,0x14, +0x84,0x9B,0xC4,0xC7,0x3E,0x8B,0x8C,0xFF,0x00,0x3A,0xA0,0xD3,0xC8,0x2B,0x3A,0x70,0x47,0x82,0x24,0x0B,0x80,0x4F,0xBE,0x90,0x3A,0xB0,0xAE,0xDA,0x58,0x25,0x69,0x1E, +0x49,0x18,0x84,0x29,0xC0,0xE0,0xAE,0x73,0x9E,0xFF,0x00,0xA6,0x97,0x31,0xA7,0x13,0x86,0x48,0x0F,0x6F,0x50,0x9E,0xB8,0x35,0x83,0xED,0xC8,0x1E,0x07,0x5B,0x9F,0xD9, +0x4D,0x2E,0x7F,0xFC,0xC4,0x12,0x09,0x19,0x04,0x83,0x9C,0xE8,0x9F,0x4D,0x3C,0x89,0x53,0x1C,0xE2,0x15,0x67,0x42,0x08,0xED,0xCF,0x39,0xE4,0x7A,0x8C,0x03,0xA1,0xB7, +0x50,0xAF,0x5E,0x15,0x19,0x4E,0x32,0x30,0x39,0xED,0xEF,0xC0,0xD1,0xBE,0x90,0x3E,0x0D,0x71,0x95,0xA4,0xDB,0x1A,0x9F,0x33,0x86,0xDA,0x14,0x7D,0xF1,0x8C,0x9C,0xE7, +0x8D,0x65,0x18,0x3C,0x62,0x4C,0x40,0xB4,0xF9,0xAF,0x4A,0x62,0xCF,0xF0,0xB0,0xF7,0x3B,0xC8,0x22,0x97,0xA9,0x1A,0x56,0x91,0x2A,0xD5,0x92,0x45,0x62,0x42,0xB2,0xE7, +0x19,0xC1,0xCE,0x73,0xEF,0x9D,0x2C,0x81,0x4D,0xE3,0xF2,0xE3,0x9C,0xF1,0xB4,0x9E,0x78,0xE4,0x01,0xEB,0xA6,0x6E,0xAF,0x8E,0x98,0xDC,0x1D,0x92,0x55,0x0D,0x22,0xE7, +0x2A,0x18,0x81,0xC9,0x03,0xD7,0xED,0xFC,0xE9,0x34,0xA9,0x8B,0xC2,0x75,0x40,0x4F,0xD9,0xBB,0x73,0xED,0xAE,0x71,0xE6,0x78,0x75,0x84,0x37,0x65,0x43,0x00,0x22,0x5A, +0x46,0xBC,0x1E,0xAA,0xA3,0xD1,0x4D,0xE1,0x74,0x95,0x42,0x00,0xED,0xE3,0x56,0x10,0x47,0x6F,0x44,0xCE,0x7F,0x6D,0x3A,0x51,0xC0,0x27,0xAC,0x0E,0x1C,0xED,0x4F,0x31, +0x04,0xFF,0x00,0x1A,0x48,0xE8,0x94,0x90,0x74,0x84,0x61,0x9C,0x96,0x92,0xB1,0xD8,0xE7,0xB7,0x08,0x34,0xF1,0x47,0x8A,0x7B,0x34,0xD3,0x86,0x04,0x82,0x00,0xCF,0x1F, +0xAE,0xB6,0x6C,0x39,0xC4,0x61,0xF1,0x38,0x75,0x2D,0x0B,0xCD,0x7C,0x46,0xC0,0xEC,0x6A,0xA1,0xA7,0xA0,0x71,0x5C,0xB5,0x8A,0xD3,0x56,0x05,0xC3,0x0C,0xB6,0xE6,0xF2, +0xF7,0xE7,0x80,0x4F,0xE9,0xAF,0x59,0xCA,0xA8,0x03,0x85,0x5C,0x9F,0x37,0x05,0xB5,0xF5,0x4B,0x1B,0x4D,0x23,0x48,0x06,0x77,0x72,0x57,0x9F,0xE7,0x5A,0x2E,0x38,0xA6, +0x82,0x59,0xA4,0x38,0x8D,0x01,0x62,0x5B,0x8E,0xDA,0x29,0x4E,0xD0,0x4D,0x8E,0xC9,0x5A,0xA6,0xE0,0x5C,0x6E,0x81,0x57,0xD4,0xC5,0x57,0x75,0x8E,0xD4,0xCA,0xC7,0x3E, +0x79,0x00,0xCF,0x00,0x1E,0x06,0x47,0xE4,0xFE,0x35,0xDF,0x35,0x2A,0xC3,0x11,0xA7,0xC3,0x00,0x47,0x0D,0xD8,0x76,0xCF,0xFC,0xCE,0xB9,0x6C,0xB4,0x1E,0x3B,0xCB,0x73, +0x92,0x46,0x77,0x75,0x24,0x81,0x8F,0x2E,0x47,0x00,0x73,0xCE,0x06,0x3F,0x7D,0x6B,0xBE,0x55,0xFC,0xB5,0x2D,0x45,0x4C,0x99,0x06,0x9D,0x09,0x24,0x61,0x77,0x71,0xF8, +0xF4,0xC6,0x89,0xB2,0x41,0x67,0x1F,0x20,0x84,0xD4,0xC4,0x1A,0x00,0x23,0x52,0xA0,0xDD,0x43,0x59,0x14,0xDD,0x69,0x30,0x68,0xE1,0x9E,0x25,0x72,0x1D,0x24,0x59,0x48, +0xDB,0xBB,0x6E,0x32,0xA0,0x00,0x7E,0xD9,0xCF,0xEF,0xAE,0x8B,0x45,0xCA,0x9E,0x6A,0x88,0xED,0xF0,0xD2,0x9A,0xA8,0x99,0xB7,0x46,0xBE,0x21,0x93,0x6B,0x2E,0x38,0xDA, +0xD1,0x85,0xC8,0x1F,0xEA,0x6C,0x63,0xD7,0x3A,0x58,0x7B,0x8C,0x93,0x75,0x65,0x4D,0x5D,0x3A,0xC8,0xB2,0xCB,0x92,0x6A,0xE9,0xCA,0xF9,0x94,0x1E,0x41,0xC0,0x20,0x2F, +0xA6,0x7F,0x5E,0x74,0xF1,0x64,0xB7,0x9A,0x4A,0x96,0xB8,0xDA,0xA8,0xD1,0x6E,0x32,0x45,0xB5,0xA1,0x96,0x76,0x8E,0x36,0xC0,0x05,0x9C,0x31,0xF3,0x30,0xFB,0xB0,0x55, +0x1F,0x70,0x72,0x73,0x69,0x8D,0xE5,0x2F,0x4D,0xF0,0xC6,0x5B,0x1B,0x5A,0x7C,0x94,0x5A,0xBA,0x92,0x01,0x05,0x43,0x08,0x96,0x27,0x76,0x51,0x37,0x84,0xF2,0xF8,0x71, +0xE4,0xFA,0x2E,0xD6,0xC8,0x39,0xCF,0x3D,0xB0,0x70,0x3D,0x74,0x3F,0xAB,0xAE,0x9F,0x2F,0x4B,0x0C,0x74,0xF5,0x42,0xAE,0x28,0x95,0x57,0x06,0x06,0x8E,0x32,0x71,0xE8, +0x18,0x64,0xFA,0xFB,0x67,0xD8,0x6B,0x35,0x9A,0x82,0x9B,0xF1,0x02,0x61,0x5F,0xA5,0x7E,0x0C,0xD5,0x3F,0x51,0x7C,0x04,0xA1,0x5F,0x19,0x1B,0x74,0x6F,0x0E,0x38,0x1D, +0x98,0x8C,0x60,0x0E,0x38,0xD3,0x77,0x46,0xD7,0x49,0xF2,0x29,0x42,0xEE,0xC2,0x5A,0x67,0x34,0xEE,0x59,0xF2,0x0E,0xCE,0x33,0x8C,0x7B,0x60,0xFE,0x75,0x9A,0xCD,0x6A, +0x91,0x6B,0x18,0x1F,0xA4,0x7A,0x05,0x99,0x56,0x69,0x33,0xED,0xB3,0xFE,0xA5,0x1F,0xB8,0xD2,0xB2,0xD6,0x7C,0xCC,0x58,0x12,0x29,0x0C,0xB9,0xC7,0xD5,0xEA,0x3B,0x67, +0x91,0xA6,0x44,0x7F,0x9D,0xB6,0x24,0x8A,0x70,0x42,0xE4,0xEE,0xF5,0xD6,0x6B,0x34,0x12,0xA3,0x40,0x1D,0xDD,0x1C,0x85,0xA0,0x12,0xDF,0x30,0xB4,0xD9,0xE4,0xF2,0x55, +0xD3,0x87,0x01,0xD4,0x96,0x50,0x17,0xBE,0x40,0xD4,0xCF,0xE2,0x14,0x81,0x6E,0x34,0x2D,0x27,0x23,0x0E,0xC0,0x0C,0x8E,0xDE,0xD8,0xF4,0x3F,0xF3,0x8D,0x66,0xB3,0x4B, +0xBC,0x49,0xFD,0xBA,0x6F,0x97,0xAA,0x78,0xFE,0x9E,0x6B,0x8E,0x53,0x37,0xF4,0xBB,0xFE,0x54,0xFD,0x99,0xDE,0x47,0xA8,0x0D,0xC9,0x24,0xF6,0xE3,0xBF,0xFE,0xF4,0xCD, +0xD1,0xF4,0x82,0xA6,0x79,0x09,0x8D,0xC2,0x8C,0x0D,0xDB,0xB3,0x82,0x48,0xED,0xDF,0x9E,0x73,0xAC,0xD6,0x6B,0x34,0xE1,0x5F,0xBC,0xAA,0x0E,0x72,0xF4,0x3F,0x12,0x48, +0xE8,0xE8,0x1C,0xE6,0xA2,0x9D,0x58,0x76,0xCE,0x23,0x0E,0xF2,0x28,0x5D,0x83,0x2E,0x1F,0x91,0xDD,0xB3,0xEC,0x4F,0xBE,0x93,0xA6,0x39,0x89,0x5C,0xB6,0x4F,0x3C,0x7B, +0x7E,0x75,0x9A,0xCD,0x7D,0xC4,0x5F,0x9D,0x72,0xA9,0xC3,0x3F,0x90,0x8D,0x54,0xFA,0x33,0xCD,0xD1,0xF4,0x64,0x63,0x7B,0x4B,0x33,0x0C,0x0E,0xF8,0x3B,0x73,0x9F,0x5E, +0x74,0xE1,0x73,0x94,0x53,0xD0,0x52,0x51,0xC2,0x09,0x32,0xB7,0x20,0x6B,0x35,0x9A,0xD7,0xA8,0x35,0xA3,0x81,0xBD,0x87,0xA0,0x5E,0x6B,0xE2,0x1D,0x31,0x7A,0xC7,0x79, +0x38,0xFA,0xAE,0xFA,0x62,0x90,0x51,0x16,0x23,0x73,0x37,0xE3,0x4A,0x3D,0x4F,0x54,0x93,0x4F,0x1D,0xB2,0x31,0xB4,0x2B,0x6F,0x75,0xF6,0xE7,0xCA,0x33,0xF7,0x23,0x59, +0xAC,0xD5,0xDA,0x5F,0xC4,0x77,0xC5,0x05,0xAA,0xFC,0x36,0xA2,0x70,0x2B,0xD0,0xDA,0x62,0x50,0x77,0x21,0x5D,0xAE,0xED,0x9C,0x93,0xDC,0xE9,0x3B,0xE2,0x35,0x54,0x90, +0x74,0xAD,0x45,0x3C,0x51,0xEF,0x79,0x10,0xB3,0xED,0xC2,0x90,0xB8,0xEF,0xCE,0xB3,0x59,0xAB,0xA3,0x58,0x9E,0x7B,0x14,0x1E,0x4E,0x69,0xDA,0x0E,0xC4,0x2F,0xCE,0xB6, +0xBB,0x6C,0xF5,0x95,0x33,0xC1,0xE1,0xD5,0x24,0xE1,0x0B,0x47,0x3B,0xAB,0x91,0x8D,0xD9,0x23,0x85,0xCB,0x0E,0x4F,0xE9,0xA6,0x68,0x23,0xAF,0xB4,0xA8,0x6A,0x38,0x05, +0xC1,0x2A,0x93,0xFB,0xCC,0xEA,0xED,0x26,0xE0,0x48,0x04,0x8C,0x92,0xA7,0xEC,0x76,0x93,0xEC,0x35,0x9A,0xCD,0x67,0x73,0xEC,0x9A,0xDA,0xBF,0xFF,0xD9,}; + diff --git a/examples/160 x 128/TFT_flash_jpg/jpeg4.h b/examples/160 x 128/TFT_flash_jpg/jpeg4.h new file mode 100644 index 0000000..ef73296 --- /dev/null +++ b/examples/160 x 128/TFT_flash_jpg/jpeg4.h @@ -0,0 +1,168 @@ +// We need this header file to use FLASH as storage with PROGMEM directive +#include + +const uint8_t Mouse160[] PROGMEM = { +0xFF,0xD8,0xFF,0xE0,0x00,0x10,0x4A,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x48,0x00,0x48,0x00,0x00,0xFF,0xDB,0x00,0x43,0x00,0x04,0x03,0x03,0x03,0x03,0x02,0x04, +0x03,0x03,0x03,0x04,0x04,0x04,0x05,0x06,0x0A,0x06,0x06,0x05,0x05,0x06,0x0C,0x08,0x09,0x07,0x0A,0x0E,0x0C,0x0F,0x0E,0x0E,0x0C,0x0D,0x0D,0x0F,0x11,0x16,0x13,0x0F, +0x10,0x15,0x11,0x0D,0x0D,0x13,0x1A,0x13,0x15,0x17,0x18,0x19,0x19,0x19,0x0F,0x12,0x1B,0x1D,0x1B,0x18,0x1D,0x16,0x18,0x19,0x18,0xFF,0xDB,0x00,0x43,0x01,0x04,0x04, +0x04,0x06,0x05,0x06,0x0B,0x06,0x06,0x0B,0x18,0x10,0x0D,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xC0, +0x00,0x11,0x08,0x00,0x6B,0x00,0xA0,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xFF,0xC4,0x00,0x1D,0x00,0x00,0x02,0x03,0x00,0x03,0x01,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x05,0x03,0x06,0x07,0x00,0x02,0x08,0x01,0x09,0xFF,0xC4,0x00,0x3B,0x10,0x00,0x02,0x01,0x02,0x04,0x04,0x04,0x04,0x04,0x05,0x03, +0x04,0x03,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x11,0x00,0x05,0x12,0x21,0x06,0x13,0x31,0x41,0x22,0x51,0x61,0x71,0x07,0x14,0x81,0x91,0x23,0x32,0xA1,0xB1,0x08,0x15, +0x33,0x42,0xD1,0x52,0x62,0xC1,0x16,0x24,0x43,0xF1,0x82,0xB2,0xE1,0xFF,0xC4,0x00,0x19,0x01,0x00,0x03,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x02,0x03,0x01,0x04,0x05,0xFF,0xC4,0x00,0x22,0x11,0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02, +0x11,0x03,0x21,0x31,0x41,0x12,0x13,0x22,0x51,0x04,0x14,0x32,0xFF,0xDA,0x00,0x0C,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3F,0x00,0xF5,0x73,0xE6,0xCF,0x96,0xC7, +0x24,0xF9,0xDE,0x4F,0x48,0xF0,0xAD,0xAF,0x51,0x08,0x04,0x93,0x7F,0xF4,0x9D,0xFF,0x00,0x5C,0x34,0xC8,0xF8,0x9F,0x85,0xB3,0x88,0xD9,0x32,0xF9,0xA0,0x59,0x10,0xF8, +0xE0,0x91,0x02,0x3A,0xF9,0x1B,0x10,0x36,0x3E,0x78,0x97,0xE4,0xA0,0x9C,0xAB,0xC9,0x1A,0x4C,0xAA,0x06,0x9B,0x81,0x6B,0x7A,0x8F,0x2C,0x52,0x33,0x9E,0x08,0xA7,0x35, +0x72,0xD5,0x65,0xB2,0xF2,0x27,0x6B,0xAF,0x2F,0x70,0x42,0xF9,0x7B,0x6E,0x77,0xC6,0xA9,0xC9,0x6B,0xA2,0x6F,0x1F,0xD1,0xA7,0x2D,0x2D,0x23,0x0B,0xAC,0x31,0x91,0xE6, +0x14,0x60,0x5A,0x8C,0xBB,0x2F,0xA8,0x3F,0x89,0x49,0x13,0x8B,0x5B,0xC4,0x83,0x1E,0x3B,0x3F,0x1E,0x38,0xEB,0xE1,0x5F,0xC4,0x9A,0xEE,0x1C,0xE2,0x06,0xFE,0x79,0x95, +0xC3,0x51,0xA2,0xCC,0x2D,0x2A,0xA1,0xB5,0xAC,0xC4,0xDC,0xD8,0x1E,0xF8,0xF4,0xAE,0x49,0xC4,0xF5,0x5C,0x65,0xC2,0x74,0x39,0xED,0x04,0x13,0x53,0xD1,0xD6,0x46,0x25, +0x55,0x94,0x69,0x76,0x53,0xD2,0xF6,0xE8,0x3B,0xE2,0x9E,0xC8,0xC5,0x09,0xEB,0x61,0x3C,0x49,0x94,0x64,0x52,0xE5,0x52,0x51,0x24,0x14,0x8B,0x23,0x0B,0x10,0xAA,0x09, +0x02,0xFB,0xF4,0xC7,0x29,0x68,0xF8,0x6A,0x99,0x56,0x9E,0x08,0xA9,0x14,0x84,0x1F,0xF8,0xC2,0x93,0xFA,0x62,0x1A,0xA8,0xF9,0x04,0x34,0x8A,0xF1,0x93,0x72,0x34,0xAD, +0xC8,0x18,0xAF,0x57,0x51,0x4F,0x23,0xBB,0xBA,0x94,0x36,0xDA,0xF7,0x18,0x45,0x99,0xCB,0xA2,0xFF,0x00,0xAF,0x65,0xD2,0x3C,0xB7,0x2D,0xD0,0x0C,0x74,0xD0,0x95,0x3B, +0x82,0xAA,0x2D,0x88,0xBE,0x46,0x93,0x5E,0xA1,0x02,0x0F,0x65,0x03,0x19,0xF5,0x1E,0x71,0x98,0x64,0xAE,0xB0,0xAC,0xAC,0xE8,0x5A,0xDA,0x5B,0x7D,0xB1,0x7B,0xCB,0xB3, +0x4A,0x6C,0xC6,0x8C,0x4F,0x0B,0x82,0x41,0xB3,0x28,0xEA,0xA7,0x16,0x52,0x4F,0x82,0x52,0x83,0xC6,0xCE,0x35,0x1D,0x31,0x8D,0x64,0xD0,0x81,0x8D,0xC5,0x80,0xB7,0x4B, +0x7F,0x9C,0x0D,0xC9,0x8B,0xFD,0x03,0x06,0x49,0x24,0x4A,0xE5,0x55,0xAF,0x6C,0x08,0xD2,0x2A,0xB1,0x56,0x36,0xB6,0x18,0x90,0x2B,0x41,0x1A,0x9B,0x14,0x5C,0x0E,0xF4, +0xD1,0x2E,0xE1,0x05,0xB0,0x4B,0xCA,0xBA,0xFC,0x64,0x0C,0x40,0xEC,0x19,0xEE,0x31,0xCE,0xE6,0xD8,0x01,0xCB,0x0C,0x5C,0xCF,0xC8,0x3A,0x61,0x4E,0x69,0x55,0x0D,0x13, +0x47,0x1A,0x21,0x92,0xA2,0x53,0xA6,0x28,0x10,0xEE,0xC7,0xCF,0xD0,0x79,0x9C,0x45,0xC5,0x9C,0x53,0x45,0xC3,0x79,0x6F,0xCC,0xC9,0xF8,0xD3,0xBF,0x86,0x18,0x14,0xEE, +0xE7,0xFC,0x0B,0x8B,0x9C,0x22,0xF8,0x59,0x3E,0x65,0x9C,0xF1,0x15,0x7E,0x73,0x9A,0x48,0xF2,0xAA,0x26,0xC4,0xC6,0x36,0x37,0x1B,0x2F,0xA0,0xDA,0xD8,0xCB,0xD5,0x16, +0x82,0xB8,0xD1,0x63,0xA8,0xA1,0x92,0x91,0xA2,0xA7,0xA8,0xD0,0xD5,0x06,0x21,0x24,0x96,0x16,0x00,0x92,0x76,0x18,0x11,0xA0,0x8D,0x4D,0x8A,0x2E,0x0F,0xCD,0x26,0x41, +0xC4,0x05,0x1E,0x6D,0x72,0xB4,0x60,0x15,0xF2,0x23,0xB0,0x1F,0x5C,0x41,0x2B,0x0B,0x69,0xEF,0x8C,0x28,0x2E,0x9E,0x08,0x99,0xAC,0x50,0x60,0x39,0x69,0x20,0xE6,0x7E, +0x4E,0xD8,0x3D,0xD8,0x33,0xDC,0x60,0x69,0x7F,0xA9,0xF4,0xC0,0x02,0x59,0xB2,0x7A,0x03,0xA8,0x9A,0x38,0x4B,0x11,0x72,0x4A,0x83,0x85,0x15,0x7C,0x23,0xC3,0xF5,0x12, +0x6B,0x9B,0x29,0xA5,0x79,0x3B,0xB1,0x41,0x8B,0x2B,0x31,0x63,0x73,0x85,0xF2,0xB0,0xB6,0x9E,0xF8,0x00,0xF4,0x36,0x5F,0x50,0xE8,0x81,0xCA,0x24,0xC1,0x01,0xB9,0x09, +0x73,0xD3,0xC8,0x62,0x6A,0x99,0xE3,0xA9,0xA5,0x13,0x72,0x82,0xB2,0xEE,0xB2,0x46,0x01,0x23,0xCF,0x63,0x88,0xEB,0x32,0xFA,0x2C,0xB2,0x49,0x2A,0x29,0x2B,0x4C,0x2D, +0xD6,0xCC,0xB7,0x1F,0x7C,0x05,0xCD,0x8F,0x30,0xA4,0x47,0xA9,0x9A,0x0D,0x40,0x9B,0x33,0x0D,0x21,0x87,0x90,0x7D,0x8F,0xDF,0x1C,0xB0,0x9F,0x68,0xD7,0x5D,0x1E,0x3C, +0xFE,0x26,0x32,0x6C,0xBE,0x87,0xE2,0x1A,0xE7,0x70,0x42,0xA1,0x2B,0x51,0x4B,0xE8,0x16,0xFC,0x40,0x2C,0xC7,0x6E,0xFD,0x0F,0xD7,0x1E,0xC3,0xF8,0x67,0x49,0x47,0x55, +0xF0,0x67,0x85,0xEA,0x50,0x16,0x07,0x29,0xA6,0x37,0x3D,0x7F,0xA4,0xB8,0xCD,0x7E,0x32,0x7C,0x3E,0x4E,0x32,0xE0,0x99,0x69,0x21,0x51,0x35,0x65,0x10,0x35,0x11,0x0D, +0x0A,0x5A,0x4D,0xBA,0x29,0xEF,0xF4,0xC3,0x1F,0xE1,0xE3,0x8D,0xA9,0x33,0x4F,0x84,0x34,0x99,0x24,0x8A,0x20,0xAE,0xC9,0x89,0xA2,0x95,0x19,0x89,0xB8,0x04,0x95,0x6D, +0xF7,0xE8,0x6D,0xEE,0x0E,0x1F,0x1F,0x3B,0x0A,0xD5,0x9A,0x7D,0x7C,0x54,0xD0,0x07,0x76,0x08,0x58,0x6F,0xBF,0x6C,0x57,0x04,0x30,0x55,0x54,0x30,0x75,0x32,0xB1,0xD8, +0xFA,0x60,0xAC,0xFA,0xAE,0x46,0x52,0xE5,0xC3,0x17,0xD8,0x79,0x5B,0x1D,0xF2,0x5A,0x46,0x8A,0x01,0xA1,0x35,0x4C,0xFD,0x5F,0xC8,0xE2,0xD7,0xBA,0x2D,0x8F,0x81,0x36, +0x77,0xC1,0xCB,0x2D,0x01,0x9E,0xC1,0x5C,0x02,0x42,0x8E,0x87,0x19,0xA6,0x65,0x5B,0x9D,0xF0,0xFC,0xEF,0x36,0x59,0xF8,0x73,0xAB,0x04,0x92,0x19,0x45,0xD5,0x81,0x36, +0x1D,0x7A,0x78,0xAD,0xBF,0xFB,0xB1,0xBF,0x56,0x1C,0xBA,0x92,0x91,0x4D,0x6A,0x33,0xB3,0x75,0x20,0xFF,0x00,0x9C,0x65,0x1C,0x65,0x43,0x1D,0x59,0x9A,0x4A,0x37,0x2C, +0x18,0x00,0x88,0xBD,0x19,0xAE,0x0F,0x43,0xDC,0x5B,0x1A,0x4E,0xDC,0xB4,0x63,0x75,0xBF,0xC4,0x26,0x6F,0x4F,0x9A,0xCB,0x97,0x55,0xE4,0x4D,0x4D,0x57,0x16,0xA2,0xCA, +0x58,0xD8,0x15,0x62,0xA7,0xF6,0x38,0xEB,0x0F,0xF1,0x1B,0xF3,0x4E,0xF0,0xAE,0x49,0x31,0x91,0x53,0x58,0x41,0x70,0x5E,0xC3,0xC5,0x6B,0xDB,0xDC,0x7D,0xB1,0x75,0xF8, +0x83,0xC0,0x39,0x35,0x45,0x74,0x99,0xC5,0x14,0x5F,0x89,0x14,0x12,0x3C,0xAC,0x77,0x2F,0xE1,0xF0,0x83,0xE9,0xB0,0x1F,0x53,0x8C,0x2D,0x32,0xD6,0xCB,0x6A,0x09,0x9E, +0x9D,0x5E,0x04,0x45,0x95,0x4B,0x2E,0xEC,0x0D,0xC3,0x0B,0xFD,0x09,0xFA,0x0C,0x43,0x27,0xE4,0x6C,0x4C,0x78,0xD5,0x9A,0x2A,0x7C,0x7C,0x35,0x21,0xA3,0xFE,0x4B,0x56, +0x25,0x54,0x2D,0xA5,0x86,0xFA,0x86,0xC4,0x7B,0xDA,0xC4,0x7A,0xE1,0xB8,0xF8,0xA6,0x2B,0x3E,0x4E,0x3D,0x33,0xC4,0x92,0xA2,0x16,0x3B,0x5F,0x73,0x72,0x3A,0xEC,0x40, +0x07,0x19,0x64,0x75,0x14,0x79,0x65,0x6D,0x0C,0xF3,0x13,0xCF,0x99,0x96,0x49,0x13,0x4D,0xED,0xE2,0xD3,0x60,0x7D,0x40,0xFB,0xE2,0xC0,0xB1,0xD0,0xFC,0x85,0x43,0x23, +0x46,0xAB,0x0C,0x9A,0x5C,0x1D,0xB4,0x5F,0x50,0xF0,0xFD,0xEF,0x85,0x8E,0x7F,0x20,0x78,0xD4,0x5E,0x8B,0x4E,0x69,0x92,0xD5,0x67,0x39,0xE4,0x19,0xAC,0xF5,0x32,0xCA, +0x8C,0x0A,0xC7,0x16,0x92,0x79,0x6A,0x2F,0xB7,0xED,0xFA,0xE2,0xED,0xC1,0x6D,0xFC,0xAF,0x2F,0x68,0x0A,0xD9,0xEA,0x49,0x63,0xA6,0xF7,0xD9,0x85,0xEC,0x3E,0xA0,0xE0, +0x0E,0x06,0xE2,0x6C,0xA3,0x36,0xCC,0xA3,0xA1,0x58,0x16,0x6F,0x12,0x84,0x88,0x36,0x93,0x60,0xAC,0x4F,0xBE,0xEA,0x6F,0xEF,0x8B,0x8E,0x65,0x05,0x2D,0x5E,0x68,0x33, +0x3C,0xBA,0x45,0x02,0x10,0x62,0x90,0x2A,0xDB,0xC7,0xE1,0xBF,0xEA,0x3E,0xC3,0x17,0x83,0xB5,0xB3,0x6F,0x54,0x29,0xCF,0xF9,0x31,0xD6,0xAE,0x61,0x10,0x70,0xE2,0x40, +0x0B,0xD8,0x9F,0x05,0xB7,0xFF,0x00,0xDE,0x3A,0xF3,0xD2,0x58,0x96,0x60,0xC1,0x94,0x8E,0xAB,0xB8,0xC3,0x7C,0xF5,0x29,0xD7,0x26,0xF9,0xAA,0x52,0xB2,0x8D,0x1A,0xE4, +0x42,0x7C,0x24,0xE9,0xF1,0x0F,0xDF,0x15,0x6C,0xB2,0x90,0xD2,0x65,0x08,0x35,0x12,0x1B,0xF1,0x2C,0x7F,0xB6,0xFB,0xD8,0x61,0x8C,0x08,0x9A,0x53,0x76,0x1F,0xDC,0x36, +0xC0,0xAE,0xC5,0x56,0xE3,0xCF,0x1D,0xDD,0x99,0xDA,0xE5,0xB6,0x1D,0x06,0x06,0x76,0x0C,0xD7,0x18,0x0C,0x6A,0xC8,0xA7,0x93,0x51,0x2A,0x46,0xE0,0xF5,0xC0,0xB2,0xFF, +0x00,0x4F,0xEB,0x89,0xA4,0x7D,0x56,0x03,0xA1,0xC0,0x8E,0xC1,0x9A,0xE3,0x18,0xEF,0xA0,0x77,0xD1,0xBE,0x66,0x35,0x55,0xB5,0x3A,0x9E,0x0A,0x6D,0x2A,0x0E,0xDA,0xD8, +0x23,0x7B,0xF5,0xC4,0x55,0x10,0x4B,0x4F,0x43,0xCA,0x04,0x3B,0x3E,0xE6,0x2D,0x5A,0x3F,0x4D,0xC3,0x7D,0xB0,0xCD,0xE5,0x14,0x5C,0xA2,0x94,0x4D,0x25,0xBA,0xB1,0x2A, +0x00,0xF4,0xF3,0xC0,0x55,0xF2,0xA9,0x03,0x9D,0x96,0x4A,0x8B,0x21,0xB0,0x65,0x7B,0x0F,0xB7,0xF9,0xC7,0x94,0x75,0x82,0x64,0x74,0x51,0xC7,0x3B,0xA2,0xE9,0x8B,0x59, +0x37,0x49,0x08,0x2B,0x7F,0x20,0xBE,0x5E,0xD8,0xA9,0x66,0x3C,0x3B,0x47,0xC0,0x9F,0x15,0xA2,0xE2,0x8A,0x18,0xB9,0x39,0x4E,0x6F,0xF8,0x39,0x8C,0x51,0xAF,0x86,0x19, +0x3A,0xA4,0x96,0xDF,0x6D,0x5D,0x4F,0xA9,0xC6,0x93,0x95,0xE5,0xCA,0xD0,0x7C,0xCA,0xC2,0x0C,0x7D,0x46,0xB3,0xAC,0xAF,0xD3,0x0C,0x2B,0xE8,0x56,0x7A,0x27,0x35,0x10, +0x89,0x14,0xAE,0xEA,0x46,0xA5,0x23,0xD4,0x77,0xC5,0x7C,0xE5,0xFD,0x0A,0xE6,0x96,0x8A,0x26,0x75,0x5D,0x04,0x87,0x95,0x0B,0x6A,0x8D,0x0D,0xF5,0x03,0xFE,0x31,0x65, +0xE1,0x49,0x61,0x6C,0xAC,0x19,0xE4,0x1A,0xBD,0x70,0x83,0x32,0xC8,0x53,0x27,0xAD,0x67,0x48,0x1D,0xB2,0xF9,0x53,0x5C,0x52,0x2E,0xEB,0x1B,0x77,0x4F,0x31,0xE9,0x8E, +0xBC,0x3D,0x53,0x1C,0xB5,0x75,0x10,0xCA,0x5B,0x42,0x0D,0xB4,0xEC,0x17,0xD4,0xE3,0xB2,0x16,0xDD,0x98,0x92,0x6A,0x91,0x66,0xE2,0x41,0x0C,0xB9,0x74,0xA6,0x33,0x76, +0xEA,0x18,0x6F,0x6D,0xB1,0x96,0x66,0xD5,0x13,0xD6,0xE5,0xD4,0xF4,0xF4,0x09,0x6A,0xA5,0x71,0x0C,0xB1,0xDE,0xE1,0xD1,0xB7,0xD4,0x3D,0x41,0x43,0xF4,0xC5,0xC7,0x8B, +0x4C,0xD0,0x65,0x6B,0x55,0x4B,0x32,0x08,0xE6,0x65,0x89,0x64,0x2F,0xB5,0xC9,0xB0,0xDA,0xDE,0xBD,0x70,0x3D,0x16,0x47,0x4B,0x03,0xC7,0x2C,0xAC,0xC5,0x96,0xCF,0x1B, +0x92,0x7A,0x9E,0xB7,0xFB,0x91,0x89,0x64,0x9D,0xBA,0x89,0xBA,0x8A,0x14,0xD6,0x52,0x5B,0x84,0xDF,0x99,0x09,0x25,0xD5,0xA1,0x57,0x6F,0xCC,0x6C,0xDB,0x13,0xF4,0x1F, +0xAE,0x30,0xFE,0x29,0xA3,0xA6,0xA7,0x8D,0xB2,0xA8,0x60,0x2F,0xAC,0xB4,0x6A,0xF1,0x81,0xF8,0x46,0xFE,0x11,0xD3,0xFD,0xC4,0x63,0xD0,0x19,0xC0,0xAB,0xA9,0xAA,0x9E, +0x38,0xD9,0x63,0xA0,0x44,0x11,0x4C,0xC1,0x6F,0xC9,0x7B,0xDC,0x1F,0xD7,0xAF,0x98,0x18,0xA9,0x45,0xC2,0x0F,0x2E,0x65,0x34,0x55,0x50,0xA9,0x59,0xE2,0x05,0x25,0x53, +0x72,0xEE,0x84,0x91,0xF5,0xB5,0xB7,0xEF,0x71,0x8C,0x94,0x53,0xD3,0x23,0x07,0x4F,0x66,0x03,0x99,0xE5,0x70,0xD0,0xE4,0x51,0xAD,0x5A,0xF3,0x2B,0x29,0x69,0xD2,0x37, +0x41,0xDD,0xB5,0xDC,0x11,0xEA,0x14,0xDF,0xDC,0x60,0x4C,0xDA,0x82,0x9A,0x1C,0xB0,0xE7,0x10,0x57,0x12,0xD2,0x40,0xD3,0x3C,0x57,0xFF,0x00,0x68,0xD3,0xF7,0x04,0x7D, +0xF1,0xA8,0x71,0x47,0x0B,0x1F,0x94,0xAB,0xA8,0x11,0x82,0xC0,0xCF,0x7B,0xDC,0xB1,0x01,0x14,0x10,0x3B,0x6D,0x73,0xFA,0x63,0x31,0xCC,0xB8,0x5E,0x5A,0x5B,0x72,0xE6, +0x60,0xAA,0x51,0x80,0x63,0x70,0xC8,0x5A,0xCD,0x7F,0x40,0x05,0xF6,0xC2,0x7A,0x90,0xD7,0x72,0xD0,0x07,0xC3,0xCE,0x26,0x97,0x2A,0xE2,0xEA,0x1A,0xC9,0x98,0x88,0x63, +0x9C,0xC6,0xEA,0xA3,0x49,0x11,0xDC,0xB3,0x9F,0xB1,0x3F,0x7C,0x7A,0x43,0x28,0xAB,0x9A,0xA7,0x27,0x4F,0x97,0x78,0xE2,0x89,0x97,0xE6,0x27,0x91,0x89,0x66,0xD6,0xC4, +0xED,0x61,0xE8,0x3A,0x63,0x0E,0xCB,0xF8,0x52,0x92,0xB7,0x26,0x86,0xBE,0x14,0x92,0x19,0x65,0x56,0x46,0xDA,0xEA,0xAC,0xA1,0x77,0xB7,0x6B,0xDF,0xFE,0x71,0x60,0xE1, +0x1C,0xE2,0xAF,0x2D,0x57,0xC9,0xEB,0x25,0xE6,0x4F,0x15,0x4B,0x69,0x7B,0x0D,0x3C,0xA2,0x00,0x02,0xF7,0xDC,0x8D,0xC7,0xD3,0x14,0x26,0x6A,0x95,0xAB,0x3B,0xE5,0x53, +0x53,0x99,0xDC,0x29,0x5E,0x61,0x05,0x74,0xEE,0xC6,0xE0,0x7D,0xF7,0xC0,0x25,0xC0,0x8A,0x38,0x94,0x12,0x15,0x40,0x2C,0x7B,0xDB,0x1C,0x69,0x11,0xE3,0xB4,0x3A,0xF9, +0x6E,0x06,0xEC,0x6E,0x4F,0xAE,0x21,0x79,0x02,0x80,0x01,0x1A,0xBB,0x8C,0x75,0x18,0xD5,0x9C,0xA9,0x7B,0xCB,0xA5,0x7A,0x0E,0xB8,0x12,0x59,0x44,0x63,0xD7,0x12,0xC9, +0x11,0x2A,0x35,0x74,0x1E,0x58,0x0A,0x70,0x55,0x2C,0xC4,0x03,0xDB,0x00,0x6E,0xCE,0x34,0xEA,0xC6,0xE7,0xF6,0xC0,0x72,0xB2,0xDB,0x48,0x60,0x4F,0xA6,0x24,0x55,0x7E, +0x58,0x76,0x16,0xBF,0x4C,0x40,0xE9,0xA7,0x71,0xD3,0x09,0x36,0xB8,0x66,0x9E,0x96,0xCC,0xA9,0x20,0x50,0x19,0xCC,0x71,0xE9,0x17,0xD4,0xC5,0xB4,0xDF,0xDA,0xF8,0x12, +0x6A,0xC8,0x92,0x8B,0x97,0x33,0x5A,0x39,0x3C,0x37,0x8D,0x43,0x5E,0xFE,0x87,0x06,0x67,0xB1,0x7C,0xC4,0xD4,0xF1,0x84,0xD0,0x41,0x27,0x5B,0x90,0x74,0xFD,0x2F,0x84, +0xB5,0x79,0x41,0x68,0xFF,0x00,0x02,0xA5,0xE7,0xA8,0xB6,0xAD,0x52,0x48,0x42,0xA7,0xB0,0xED,0x8F,0x2E,0xF7,0x47,0x50,0xFF,0x00,0x87,0x79,0xEB,0x01,0x50,0x96,0x8F, +0xB1,0x7E,0xA7,0xF4,0xC1,0xF5,0xCB,0x2C,0xF1,0x78,0x26,0x9A,0x9C,0x9D,0x98,0x0F,0x5F,0x7C,0x20,0xCA,0x6B,0xFE,0x56,0xB5,0x61,0x9A,0xAD,0xE4,0x20,0x6E,0x11,0x18, +0xDB,0xEB,0xBE,0x1A,0xD7,0xE6,0x17,0x48,0xC8,0x76,0xB3,0x11,0x7B,0xA8,0xDC,0x7D,0x71,0xD5,0x85,0xD2,0x21,0x93,0x92,0x0A,0x8E,0x1E,0xCE,0x9E,0x0F,0x96,0x15,0x74, +0x55,0x31,0x01,0xB3,0x4E,0xAE,0xAC,0x7D,0xEC,0x6D,0xFA,0x61,0x74,0x1C,0x39,0x57,0x96,0xD4,0x55,0xC5,0x23,0xC2,0xCB,0x56,0x8A,0xA8,0xAB,0xD1,0x2C,0xB6,0x3E,0x5D, +0xF7,0xC5,0x91,0xF3,0x65,0x48,0x06,0x88,0x9D,0x89,0xDF,0x63,0x6F,0xDF,0x15,0x3E,0x20,0xCD,0xB3,0x00,0x5A,0x5E,0x6D,0x3A,0x12,0x6D,0x1A,0xF3,0x40,0x3E,0xD8,0xB2, +0x9D,0x21,0x09,0x66,0x9A,0x90,0x81,0x97,0x3C,0x49,0x24,0xC9,0x74,0x61,0xB5,0xAF,0xEA,0x3B,0xE2,0x37,0xA0,0x0B,0x44,0x94,0x70,0xA1,0x2C,0x1B,0x71,0x19,0x20,0x2D, +0xFC,0xAE,0x7C,0xF1,0x5C,0x85,0x5D,0xEA,0x35,0xDE,0x78,0xDE,0x57,0xBB,0x19,0xAE,0x00,0x3E,0x63,0xD3,0x0D,0x93,0x30,0x87,0x20,0xAB,0x59,0xAB,0xA5,0x92,0x71,0x3B, +0x00,0x14,0x38,0xBA,0x93,0xE4,0xDD,0x2D,0xE8,0x6D,0x84,0x35,0xBB,0x33,0xAF,0x8D,0x1F,0x17,0x72,0xCF,0x86,0x19,0x71,0xA7,0xA6,0x8A,0x1A,0xCC,0xE6,0x45,0x59,0x19, +0x25,0xB0,0x10,0x9D,0xB6,0x20,0x1F,0x11,0xB7,0x6C,0x65,0x7F,0x0E,0x7F,0x88,0x8C,0xC7,0x8B,0x38,0xB6,0x9B,0x21,0xCC,0xA9,0x29,0xB2,0xE9,0xE7,0x2E,0x90,0x54,0xC3, +0xF9,0x75,0x15,0x36,0x52,0xA7,0xBF,0x50,0x3E,0x98,0xCA,0xBF,0x88,0x5A,0xB9,0x73,0x0F,0x8E,0xB5,0xB5,0x75,0xF1,0x4C,0xB1,0xAD,0x5B,0xE9,0x57,0x36,0xD4,0x9A,0x86, +0x9F,0xD3,0x1A,0x27,0x0F,0x7C,0x3B,0xE1,0xEE,0x22,0x9E,0x2F,0x88,0xFC,0x23,0x40,0xD9,0x42,0x41,0x99,0x51,0xC5,0x4F,0x93,0xCC,0x4B,0x3B,0x84,0x50,0x65,0x97,0x51, +0xFE,0xD2,0x45,0xF6,0xB8,0xDC,0x8B,0xE3,0xA6,0x2A,0x91,0x87,0xA1,0xB3,0x3A,0x58,0x17,0x28,0x86,0x24,0x85,0xA7,0xD5,0x19,0x46,0x04,0xF9,0xA5,0x9C,0x93,0xEB,0xFF, +0x00,0x18,0xCF,0x38,0x8F,0x84,0x05,0x3A,0xB2,0x56,0xA3,0x37,0x2A,0xF0,0x2A,0xAD,0xFC,0x31,0xEE,0x2C,0x4F,0xA5,0xBA,0xE2,0xFD,0x59,0x58,0x29,0x16,0x3D,0x48,0x35, +0xCD,0x20,0x57,0xE6,0x0B,0x69,0xDF,0x62,0x0F,0x99,0x16,0xC1,0x0F,0x24,0x39,0xDD,0x5D,0x4C,0x33,0x05,0xE6,0x68,0x0B,0xBF,0x52,0xE4,0xFF,0x00,0x82,0x70,0xAF,0xE4, +0xB4,0x6A,0x74,0x64,0x3C,0x3F,0x56,0xE9,0x4F,0x15,0x37,0x2A,0x34,0x49,0x23,0xE6,0xA0,0xD8,0x0F,0x10,0x0A,0x6F,0x7E,0xD7,0xBF,0xDC,0x63,0x1B,0xCE,0xF8,0xD6,0x9F, +0x25,0xF8,0xB8,0xFC,0x3B,0x99,0xB1,0x89,0x20,0x64,0x8A,0x09,0xC1,0x01,0x0E,0xB5,0x56,0xF1,0x9E,0xBD,0x4F,0x5D,0xF1,0xE8,0x57,0xC9,0x10,0xD7,0xCB,0x24,0x69,0x64, +0x85,0xCA,0x24,0x2C,0x9A,0x40,0xD4,0xEA,0x16,0xD7,0xED,0x72,0x7E,0xB8,0xF3,0x67,0xC6,0xAE,0x05,0x9A,0xAF,0xE2,0x0E,0x53,0x55,0x4D,0x4E,0x0C,0x2F,0x12,0xA5,0x4C, +0x8A,0x46,0xFA,0x58,0x90,0x4F,0xFF,0x00,0x12,0x07,0xA5,0xB1,0x8A,0x1A,0xA6,0x61,0xE8,0xFC,0xB9,0x9E,0x5A,0x38,0xE7,0x9A,0x4D,0x6C,0x40,0xFC,0xBD,0x3A,0x6C,0x06, +0x19,0x94,0x28,0x6C,0x48,0x24,0x8D,0xF1,0x5C,0xE1,0x69,0x0D,0x4E,0x47,0x05,0x41,0xA9,0x25,0x51,0x79,0x60,0x29,0xEE,0x36,0xB9,0xEF,0xD3,0x0D,0x9E,0xB2,0x39,0x91, +0xB9,0x12,0x8D,0x20,0xD9,0x9F,0xF7,0xB6,0x28,0x04,0xB5,0x33,0x05,0xBC,0x69,0xE3,0x7B,0xF4,0x07,0xA7,0xBE,0x00,0x92,0x22,0xF3,0x97,0x9C,0xEB,0x7E,0x9B,0x1D,0x86, +0x3A,0x4B,0x3C,0x68,0x49,0x4B,0x2C,0x60,0x7E,0x66,0x6B,0xFD,0xF0,0x0C,0xD9,0x94,0x3C,0xD2,0xBC,0xCD,0x4C,0x3B,0xF6,0xC0,0x01,0xB2,0x3A,0xB2,0x58,0x60,0x39,0x18, +0x34,0x84,0x8E,0x9D,0xB1,0xF1,0xA7,0x0E,0x97,0x2C,0xAA,0x2F,0xEF,0x88,0x65,0xD2,0x1B,0x79,0x35,0x1F,0x3E,0xD8,0x84,0xDB,0xE1,0x81,0xE9,0xFC,0xD6,0x2A,0x63,0x5A, +0xCB,0x20,0xD6,0x41,0xBE,0x90,0x6D,0x6F,0xB6,0x12,0x66,0xC6,0xAA,0x2B,0x06,0x95,0x29,0xE3,0x6E,0xA9,0x1C,0x65,0xDB,0xEA,0x4D,0xED,0x8B,0x6C,0xB4,0xF0,0xA3,0x4B, +0x2E,0x98,0xCB,0xF4,0x2C,0x45,0xDA,0xDF,0xAE,0x2B,0x35,0xD4,0xF5,0x55,0x55,0x84,0x3C,0xBA,0xD7,0xB4,0x43,0xC2,0x00,0xFD,0xCF,0xB9,0xC7,0x9D,0x5F,0x2B,0x3A,0x85, +0xF9,0x32,0xE6,0x26,0x53,0x2F,0xF3,0x39,0x8A,0xDE,0xC2,0x24,0x83,0x55,0xBD,0xFB,0x0C,0x77,0xCC,0xE9,0xB3,0x29,0xEA,0x23,0x98,0x66,0x93,0x23,0x46,0x40,0x29,0x50, +0x42,0xDF,0x7F,0x2E,0xDD,0x70,0x6E,0x5B,0x44,0xB4,0x92,0xEA,0x69,0x0B,0x6F,0xF9,0x75,0x78,0x40,0xF3,0xDC,0xE0,0xBA,0xF9,0xD1,0x23,0x3A,0x62,0x66,0x24,0x58,0x00, +0x7F,0xF7,0x8B,0x62,0xE4,0x4C,0x9C,0x04,0xC6,0xF9,0x92,0x65,0x8A,0x86,0xAA,0x29,0x64,0x23,0xF2,0x93,0x75,0xFA,0x77,0xC5,0x37,0x35,0xCF,0xAB,0xE8,0x39,0xE2,0xB7, +0x24,0x13,0x8B,0xF8,0x5A,0x21,0x72,0x77,0xEC,0xB6,0xC5,0x89,0x26,0x5A,0x58,0x62,0x67,0x82,0x58,0xD9,0x85,0xC5,0xD9,0x74,0xB7,0xDC,0xDF,0x0B,0xB3,0x29,0x11,0xE1, +0x96,0xA4,0x47,0x0C,0x41,0x96,0xC4,0xB3,0x81,0xA8,0x7D,0xF1,0xD2,0xDD,0x90,0x10,0xFF,0x00,0xD4,0xA9,0x51,0x96,0xBB,0x4B,0x46,0x69,0xC2,0x25,0xD5,0x24,0x42,0xB6, +0xC2,0xFC,0xB5,0x2A,0x2A,0x5C,0x66,0x55,0x0A,0xB2,0x95,0x3E,0x0E,0x54,0xBE,0x18,0xFA,0xEF,0xA4,0x92,0x3A,0x1F,0x4C,0x7D,0xAB,0xCC,0xE0,0xE5,0x07,0x9B,0x25,0x57, +0x8D,0x4D,0x96,0x56,0x2A,0x2F,0xEA,0x0D,0xF1,0x0B,0xC8,0x15,0x05,0x4C,0xA6,0x68,0x65,0x2D,0x65,0x57,0xA9,0xD5,0x1B,0x7A,0x5E,0xE5,0xB0,0xB2,0x8D,0xE8,0x65,0x6B, +0x67,0x4C,0xFB,0x82,0x72,0xCE,0x27,0x9B,0x9F,0x53,0x95,0xE5,0xEB,0x58,0xDB,0xBC,0xD3,0x21,0x91,0x0A,0x5B,0xCA,0xC2,0xC7,0x07,0x45,0x1D,0x16,0x55,0x41,0xFC,0xAA, +0x38,0xBE,0x42,0x64,0x50,0xE2,0x61,0xE2,0x49,0xB4,0xDF,0xD2,0xC3,0xED,0xE5,0x89,0x20,0x7C,0xC9,0xE0,0x57,0xAA,0x58,0x4C,0x1A,0xBF,0xF1,0x31,0x72,0x41,0xF3,0x24, +0x5C,0xFE,0xB8,0x1F,0x3C,0xAF,0xA7,0xA3,0xC9,0x24,0xF9,0xAA,0x1A,0x8A,0xDA,0x52,0xA4,0x37,0x2F,0x4B,0x32,0x93,0xEF,0xDB,0xD4,0x6F,0x8A,0xE3,0x5D,0x98,0xD5,0x72, +0x03,0xC4,0x4E,0xE6,0x92,0x96,0x8D,0x67,0x15,0x06,0xAA,0x30,0xCD,0x2A,0x1B,0x84,0x20,0xEA,0x17,0x03,0xD4,0x7E,0xA7,0x10,0xE5,0x19,0xD0,0x8A,0x54,0xAB,0xAE,0xA6, +0xE4,0x43,0x19,0x40,0x00,0x37,0x77,0x00,0x90,0x48,0xF6,0xB6,0x2B,0xD4,0x39,0x57,0x31,0x20,0xAC,0xCB,0xE5,0x9A,0xA2,0x12,0x54,0x82,0xED,0xAA,0x48,0xC0,0xD8,0x86, +0x3B,0x5F,0x6B,0x58,0xFA,0x77,0xC3,0xCF,0xE5,0xE5,0x53,0x4C,0xE4,0x48,0xB7,0x36,0x94,0xAE,0xEA,0x3A,0xFF,0x00,0xFB,0x8A,0xD6,0xEC,0xD5,0x06,0xCE,0xD9,0xE5,0x4C, +0x74,0x1C,0x8C,0xEA,0x34,0x32,0x34,0x87,0x98,0xF0,0x90,0x00,0x74,0xBA,0x28,0x5F,0x70,0x6C,0x41,0xF4,0xC6,0x47,0xC7,0x39,0xA5,0x3E,0x65,0x41,0x9A,0x31,0xA2,0xE5, +0xC2,0x8A,0x64,0x86,0x4B,0x58,0xDD,0xC9,0xB9,0x3D,0x2C,0x00,0x16,0xB7,0xA8,0xC5,0xC3,0x88,0xEA,0x9E,0xAE,0x9D,0xE9,0x91,0x4B,0x98,0x86,0x94,0x70,0x4F,0x84,0x03, +0xB7,0xD6,0xF6,0xDB,0x00,0x0C,0xA6,0x3C,0xDB,0x85,0x6A,0x72,0xDA,0x70,0x08,0x93,0x4F,0x34,0x3E,0xED,0x7B,0x11,0xF5,0x16,0xBD,0x81,0xC6,0x2A,0x7B,0x40,0xE0,0xD1, +0x41,0xE1,0x6A,0xF9,0xD2,0x9D,0xE3,0xAB,0x9F,0x5D,0x21,0x3A,0x95,0xD9,0x74,0x93,0x7E,0xB6,0x23,0xFB,0x6F,0xE5,0x8B,0x22,0xF1,0x6D,0x1C,0x6E,0x29,0xE9,0xAC,0x54, +0x0E,0xBB,0xF8,0x7F,0xCE,0x33,0xBE,0x2D,0xE7,0x65,0xFC,0x59,0x16,0x5B,0x02,0x4D,0x1D,0x3D,0x24,0x62,0x23,0x1B,0x58,0x82,0xD6,0x1B,0xD8,0x77,0xF7,0xC4,0x50,0xD5, +0x4A,0xAB,0x66,0x70,0x96,0xED,0x7B,0x93,0xEF,0x86,0x14,0xD0,0x64,0xCF,0x01,0x66,0xE6,0x39,0x62,0x77,0x00,0xE1,0x44,0xB9,0xE3,0xF3,0x4E,0xC6,0xDD,0xB0,0x91,0x56, +0x46,0xB0,0x56,0x69,0x2E,0x2F,0xE1,0xBF,0xFC,0x63,0xAD,0x4C,0x52,0xC7,0x10,0x0D,0xB6,0xAE,0xF6,0xC0,0x05,0x98,0xE7,0xCC,0xB4,0x88,0x58,0xD8,0x61,0x7D,0x6F,0x16, +0x18,0xA9,0xCB,0x23,0x11,0x7D,0x86,0xF8,0x49,0x30,0x78,0xF2,0xC0,0xFA,0xAC,0xC7,0xB6,0x11,0xCD,0xAE,0x55,0x92,0x02,0xD7,0xBE,0xE0,0x9E,0xC7,0xBE,0x25,0x38,0x36, +0xC0,0xFD,0x28,0x97,0x5F,0x38,0x8F,0xED,0x2B,0xF9,0xAD,0xDF,0x0B,0x6A,0xBC,0x11,0x4B,0x15,0x19,0x1A,0xC0,0x21,0xE5,0xBD,0xC7,0x9E,0x1D,0x4F,0x0C,0x73,0xDA,0x4D, +0x82,0x76,0x4B,0xEE,0x70,0xA6,0xB7,0x91,0x0C,0x9A,0x52,0x3D,0x89,0xB9,0xBF,0xFC,0x63,0xCF,0x71,0x69,0xD3,0x2C,0xB2,0x7D,0x95,0x69,0xE9,0x2A,0x90,0x13,0xF3,0xAC, +0x0D,0xB5,0x36,0xDB,0x9F,0xF6,0x9C,0x4A,0x89,0xA6,0x99,0x5A,0xA1,0x99,0xD9,0x8E,0xA0,0x19,0xAE,0xD6,0xF6,0x1B,0xFD,0xF0,0xF1,0x12,0x3A,0xAD,0x5A,0x84,0x42,0xDD, +0xD4,0xDC,0x74,0xB5,0xB0,0x0C,0x32,0xAC,0x4E,0xC5,0xC8,0x2D,0x7B,0x97,0x3B,0x0D,0x87,0x9F,0x96,0x3A,0x21,0x1A,0x5B,0x07,0x28,0xB1,0x7C,0x9F,0xF6,0xF5,0x0A,0x6A, +0xA9,0xC1,0x88,0x6E,0xA4,0xA0,0x3B,0xF6,0xB9,0x3B,0xE2,0x63,0x4F,0x95,0xCD,0x2D,0xCC,0x43,0x4D,0xB7,0x58,0xF6,0x5F,0xB6,0x22,0xAD,0x26,0xBB,0x4C,0xDC,0xC4,0x64, +0x53,0x73,0xB6,0xC6,0xDD,0xFF,0x00,0x4C,0x47,0x15,0x40,0x91,0x04,0x46,0x55,0x72,0x6F,0xAB,0xB0,0x5C,0x32,0x69,0xED,0x13,0x71,0x6B,0x90,0x6A,0x88,0x60,0xE6,0xBC, +0x73,0xBA,0x53,0x53,0xA9,0xDB,0xC0,0x18,0x91,0xF5,0x07,0x0B,0xA5,0x9B,0x28,0xA1,0xAF,0x88,0x98,0xA6,0xA8,0x49,0x18,0x04,0x24,0x0B,0x13,0xED,0xD4,0xF4,0xC3,0xA6, +0xAA,0xA2,0x4B,0x00,0x8B,0x52,0xCD,0xB1,0xF0,0xDC,0x03,0xF5,0xC2,0xEA,0xA4,0x9E,0x35,0xE6,0x5F,0x94,0x4F,0x78,0xD4,0x0B,0x0F,0x7B,0x62,0x94,0x9F,0x02,0x96,0x3A, +0x1A,0xAC,0xBE,0xAE,0x36,0x32,0x51,0xB2,0xB5,0xB6,0x56,0x0B,0xFB,0x12,0x6D,0x8A,0x5F,0x1B,0x41,0x53,0x96,0x66,0x34,0xB9,0xDE,0x5B,0xA9,0x45,0xF9,0x6F,0x4E,0x84, +0xE9,0x75,0xEE,0x18,0x1D,0xB1,0xF2,0x96,0x8B,0x31,0xA7,0x9C,0x81,0x53,0x35,0x4C,0x6C,0x2E,0xAA,0x64,0xB1,0x5D,0xF7,0xF2,0xC4,0x35,0xF5,0x10,0x54,0x29,0xA4,0xAD, +0xA3,0x55,0x98,0x8D,0x3A,0x95,0xB5,0xB0,0xF6,0xDB,0x15,0x82,0xA5,0xB0,0x07,0xA6,0xA4,0xA4,0x9C,0x35,0x76,0x55,0x4C,0xF4,0xF0,0xB0,0x3C,0xC8,0x82,0xD9,0x45,0xCF, +0xF6,0xEC,0x3E,0xD8,0x9E,0x47,0x35,0x91,0xB5,0x25,0x2F,0x81,0x5E,0xCA,0xDA,0xFB,0x1F,0xA7,0x7C,0x73,0x2D,0x8A,0x9A,0x9A,0x54,0x82,0x47,0x92,0x35,0x40,0x03,0x2D, +0x3A,0xDF,0x7F,0x56,0x37,0xFB,0x01,0x87,0x07,0x86,0x24,0xA8,0x98,0x4D,0x0C,0xC4,0x03,0xE2,0x21,0x45,0x81,0x3B,0x6F,0x8D,0x77,0xD1,0x7C,0x2E,0x3C,0x48,0xA9,0x65, +0xDC,0x37,0x24,0xF4,0xF3,0xCE,0xE0,0x5D,0x58,0xC6,0xF7,0x1B,0x06,0xDE,0xDF,0x70,0x31,0xD3,0x27,0xC8,0xCE,0x57,0x9D,0xCE,0x2A,0x2C,0x91,0x3F,0x8D,0x8B,0x0B,0x5B, +0x4A,0xED,0xED,0xD7,0x17,0xAA,0xFC,0x96,0xB7,0xF0,0xA1,0x13,0x14,0x76,0xB0,0x3A,0x16,0xDA,0xED,0xD0,0x9F,0x5D,0xF1,0x58,0xE3,0x19,0xE1,0xE1,0xDC,0xBA,0xA2,0xB6, +0xB2,0xAE,0x29,0x6A,0x99,0x08,0x10,0x96,0xD3,0xCC,0xDA,0xC6,0xDE,0x76,0xC6,0x28,0x24,0x5B,0x34,0xE0,0xE3,0x56,0x79,0xF7,0x8F,0x32,0xEA,0x4A,0xAE,0x26,0xAC,0xAD, +0x8B,0x30,0xA4,0x97,0xC5,0xAA,0xCB,0x2E,0xAD,0x8F,0xB8,0xEC,0x71,0x43,0x99,0x9E,0x24,0xB0,0xB5,0x89,0xD8,0x83,0x7C,0x5B,0xDA,0xBD,0x9E,0xAA,0xAA,0x5A,0xC2,0x65, +0x0C,0x8C,0x46,0xAE,0xA3,0x7B,0x81,0xEB,0x8A,0xCD,0x7C,0x34,0xED,0x7D,0x00,0x46,0x42,0x8B,0x1F,0x71,0x7C,0x3B,0x76,0x71,0x1D,0x28,0x2A,0xDE,0x79,0xD4,0x73,0x08, +0xB1,0xE9,0x87,0xF4,0x39,0x85,0x88,0xA6,0xAB,0x84,0x4D,0x01,0xF3,0x1B,0x8F,0x63,0x84,0x79,0x64,0x5F,0x2B,0x3B,0x54,0x4D,0xA0,0x82,0x2C,0xB7,0xE8,0x70,0x49,0x96, +0xB1,0xE6,0x78,0xC2,0xDD,0x62,0x25,0x98,0xA8,0xE8,0x3C,0xFD,0xB1,0x80,0x32,0xCD,0x62,0x81,0x20,0x67,0xA6,0x94,0x10,0xA3,0xFA,0x67,0xAD,0xB0,0x86,0x9C,0xAF,0xCF, +0xA4,0x8E,0x40,0x1D,0x0E,0x0E,0x66,0x54,0x93,0x4C,0xAC,0x41,0x6D,0xD6,0xC2,0xFA,0xBD,0xB0,0x25,0x55,0x25,0x40,0x88,0xCD,0x4E,0xCB,0x23,0x7F,0xA3,0xB8,0xC0,0x07, +0xE8,0xB2,0xC8,0xA8,0x9E,0x19,0x8D,0xC8,0x37,0x24,0xF7,0xED,0x85,0xD5,0xD3,0xC5,0x55,0x30,0x8D,0xC1,0x5B,0x8F,0xCA,0x08,0x3F,0x5C,0x57,0x56,0xAE,0xA5,0xA1,0xB1, +0x99,0x88,0xBE,0x39,0x3C,0xB2,0x43,0x4B,0xCE,0x8D,0xAC,0xFB,0x1B,0xF5,0xFE,0xEB,0x63,0x8D,0x45,0x2D,0x00,0xEA,0xC9,0x4A,0xC0,0x23,0x85,0x53,0xDA,0xFD,0xBA,0x58, +0x63,0xBC,0xAD,0x4F,0x2C,0x3F,0x2E,0xFA,0x34,0x80,0x59,0xD4,0x7E,0xD8,0xAB,0x45,0x53,0x3C,0x92,0x21,0x79,0x19,0x88,0x7D,0xAF,0xEE,0x71,0xD3,0x32,0xA8,0x9D,0x21, +0x25,0x25,0x65,0x24,0x6E,0x41,0xB7,0x7C,0x52,0x0A,0xD8,0x0F,0x1E,0x11,0x2A,0x15,0x79,0x34,0xC2,0x17,0x7D,0x27,0xAF,0xA6,0x17,0x0A,0x1A,0x61,0xCC,0x85,0x26,0xD0, +0xA5,0x6E,0x58,0x01,0xA9,0x8F,0x90,0x38,0x55,0xF3,0xB5,0x5C,0x8F,0xEB,0xB7,0xE4,0xC7,0xC6,0x25,0x68,0xA9,0xE6,0x04,0x87,0x29,0xBB,0x61,0x3C,0x77,0x66,0xDE,0xA8, +0x32,0x48,0x45,0x39,0x91,0x69,0x8D,0x90,0x30,0x55,0x24,0x76,0x06,0xE7,0x03,0x55,0xB4,0x8E,0x9A,0x35,0xB0,0x50,0x77,0x8C,0x9E,0xBE,0x67,0x10,0xD4,0xBB,0xA4,0x57, +0x56,0x6E,0xA3,0xBD,0xFB,0xE0,0x79,0xDD,0x9D,0x81,0x66,0x24,0xB3,0x6F,0xEB,0x8A,0xC2,0x29,0xAB,0x30,0x9E,0x58,0xF5,0xD1,0x98,0x92,0x59,0x43,0xB7,0x64,0x6B,0x5C, +0xFB,0xE2,0xAD,0x98,0x65,0xF9,0xAC,0x39,0x80,0xA8,0x5A,0x89,0x23,0xBB,0x5D,0xFB,0x83,0xE9,0x7E,0xD7,0xC3,0xF8,0x27,0x95,0x46,0x81,0x21,0x0B,0xCB,0x26,0xD8,0x44, +0x95,0x13,0xD5,0xF3,0x63,0xA9,0x95,0x9D,0x4C,0xA1,0x48,0x26,0xDB,0x11,0xE9,0x8E,0x88,0x2B,0x74,0x2C,0x9D,0x2B,0x03,0x8B,0x89,0x6B,0x72,0xEC,0xEE,0x9E,0x19,0xD1, +0x54,0xC8,0x4F,0x31,0x95,0xAF,0xB0,0xD8,0x0B,0x1D,0x86,0xE7,0x76,0xEB,0x6C,0x5A,0xB2,0x8F,0x88,0x1C,0xDA,0x3D,0x4C,0xC2,0x15,0xD6,0xCA,0x14,0x8D,0xF6,0xB5,0xC0, +0x3D,0xF1,0x88,0xD4,0xD7,0x56,0x0E,0x20,0x96,0x4F,0x98,0x72,0xC9,0x50,0x55,0x6E,0x6F,0x60,0x51,0x81,0x1F,0x5B,0x0C,0x76,0xCA,0x2A,0x67,0x93,0x3A,0x91,0x5E,0x4B, +0x85,0x52,0x46,0xC3,0x63,0xAB,0x17,0x51,0x48,0x59,0xCD,0xA7,0x46,0x9F,0xC4,0xDF,0x14,0xF3,0x6A,0x03,0x34,0xD4,0xC8,0xB5,0x11,0x00,0xB6,0x00,0x5C,0xAF,0x51,0xEE, +0x31,0x93,0x71,0x47,0x16,0x55,0x71,0x31,0x77,0xCC,0x6A,0x57,0xE6,0x95,0x43,0x0D,0x1F,0xDB,0x71,0xFB,0xE1,0xC7,0x10,0xED,0x48,0x95,0x0B,0xE1,0x94,0x38,0xF1,0x2E, +0xDD,0x4A,0x83,0xD3,0xAE,0x29,0xD5,0x27,0xE6,0x83,0xD4,0x4E,0x15,0xE5,0xD6,0x46,0xAB,0x00,0x6D,0x73,0xE5,0x89,0x64,0x7D,0x0D,0x07,0x6A,0xCA,0x8C,0xF5,0x55,0x14, +0xEE,0x46,0xED,0x66,0xB8,0x0C,0x2F,0xDF,0x10,0x57,0x54,0xA5,0x4C,0xFC,0xD4,0x6F,0x0C,0xAC,0x5D,0x93,0xFD,0x3B,0xEE,0x31,0x62,0x6A,0x4A,0x7A,0x8A,0x8A,0x81,0x34, +0x41,0x82,0x53,0x4A,0xCB,0xB9,0x16,0x21,0x49,0x07,0x14,0xB4,0x45,0x5A,0xBB,0xA8,0xB7,0x80,0xE2,0x63,0x0F,0xE4,0x8D,0x1E,0xBE,0xE8,0xC1,0x63,0x30,0xC6,0xDA,0x6E, +0x36,0x62,0xA0,0x9F,0xD4,0xE1,0xFE,0x55,0x1C,0x2E,0xDF,0x3E,0xF4,0xEA,0x64,0x0A,0xCA,0xAA,0x3A,0x3B,0x11,0x6D,0xF1,0x50,0xAA,0x76,0x4C,0xC1,0x4A,0x9B,0x6C,0x3F, +0xFA,0x0C,0x59,0x32,0x09,0x1C,0xD0,0x50,0x5D,0xCF,0x8F,0x9F,0x23,0x6F,0xD5,0x95,0x45,0x8F,0xD3,0x14,0x84,0x13,0x40,0x11,0x9D,0x23,0xC9,0x47,0x1B,0xD3,0x46,0x87, +0x96,0x0A,0xDA,0x20,0x00,0x2C,0xB6,0x36,0x07,0xAD,0xB7,0xB6,0x2B,0xF9,0x14,0x95,0x34,0x39,0x84,0xD5,0x35,0xD0,0x13,0x1C,0x06,0xCE,0x87,0x61,0xE2,0x52,0x05,0xCF, +0x98,0xB8,0x38,0xF9,0xC3,0x95,0x13,0xD4,0x56,0x3C,0x33,0xCA,0xF2,0x20,0x46,0x60,0xAC,0x76,0x06,0xE7,0x7F,0xD3,0x0E,0x73,0xF5,0x55,0xCB,0xA1,0x89,0x54,0x04,0x96, +0xEC,0xE2,0xDF,0x98,0x80,0x37,0xC2,0xC9,0x53,0xA0,0x3F,0xFF,0xD9,}; + diff --git a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino index 325b9a4..1cb0515 100644 --- a/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino +++ b/examples/160 x 128/TFT_graphicstest_PDQ3/TFT_graphicstest_PDQ3.ino @@ -308,21 +308,23 @@ uint32_t testHaD() 0x0a, 0x2b, 0x0b, 0x41, 0x0a, 0x29, 0x0b, 0x43, 0x0a, 0x27, 0x0a, 0x46, 0x0a, 0x25, 0x0a, 0x49, 0x09, 0x23, 0x08, 0x4e, 0x08, 0x96, 0x12 }; - + tft.fillScreen(TFT_BLACK); uint32_t start = micros_start(); - + + tft.startWrite(); + for (int i = 0; i < 0x10; i++) { - tft.setAddrWindow(0, 0, tft.width()-1, tft.height()-1); + tft.setAddrWindow(0, 0, tft.width(), tft.height()); uint16_t cnt = 0; uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); uint16_t curcolor = 0; const uint8_t *cmp = &HaD_128x160[0]; - + tft.startWrite(); while (cmp < &HaD_128x160[sizeof(HaD_128x160)]) { cnt = pgm_read_byte(cmp++); @@ -333,8 +335,11 @@ uint32_t testHaD() curcolor ^= color; } + tft.endWrite(); } + tft.endWrite(); + uint32_t t = micros() - start; tft.setTextColor(TFT_YELLOW); @@ -405,7 +410,7 @@ uint32_t testPixels() int32_t h = tft.height(); uint32_t start = micros_start(); - + tft.startWrite(); for (uint16_t y = 0; y < h; y++) { for (uint16_t x = 0; x < w; x++) @@ -413,7 +418,7 @@ uint32_t testPixels() tft.drawPixel(x, y, tft.color565(x<<3, y<<3, x*y)); } } - + tft.endWrite(); return micros() - start; } diff --git a/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino b/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino new file mode 100644 index 0000000..a6c503f --- /dev/null +++ b/examples/320 x 240/Keypad_240x320/Keypad_240x320.ino @@ -0,0 +1,284 @@ +/* + The TFT_eSPI library incorporates an Adafruit_GFX compatible + button handling class, this sketch is based on the Arduin-o-phone + example. + + This example diplays a keypad where numbers can be entered and + send to the Serial Monitor window. + + The sketch has been tested on the ESP8266 (which supports SPIFFS) + + The minimum screen size is 320 x 240 as that is the keypad size. +*/ + +// The SPIFFS (FLASH filing system) is used to hold touch screen +// calibration data + +#include "FS.h" + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +// This is the file name used to store the calibration data +// You can change this to create new calibration files. +// The SPIFFS file name must start with "/". +#define CALIBRATION_FILE "/TouchCalData1" + +// Set REPEAT_CAL to true instead of false to run calibration +// again, otherwise it will only be done once. +// Repeat calibration if you change the screen rotation. +#define REPEAT_CAL false + +// Keypad start position, key sizes and spacing +#define KEY_X 40 // Centre of key +#define KEY_Y 96 +#define KEY_W 62 // Width and height +#define KEY_H 30 +#define KEY_SPACING_X 18 // X and Y gap +#define KEY_SPACING_Y 20 +#define KEY_TEXTSIZE 1 // Font size multiplier + +// Using two fonts since numbers are nice when bold +#define LABEL1_FONT &FreeSansOblique12pt7b // Key label font 1 +#define LABEL2_FONT &FreeSansBold12pt7b // Key label font 2 + +// Numeric display box size and location +#define DISP_X 1 +#define DISP_Y 10 +#define DISP_W 238 +#define DISP_H 50 +#define DISP_TSIZE 3 +#define DISP_TCOLOR TFT_CYAN + +// Number length, buffer for storing it and character index +#define NUM_LEN 12 +char numberBuffer[NUM_LEN + 1] = ""; +uint8_t numberIndex = 0; + +// We have a status line for messages +#define STATUS_X 120 // Centred on this +#define STATUS_Y 65 + +// Create 15 keys for the keypad +char keyLabel[15][5] = {"New", "Del", "Send", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "#" }; +uint16_t keyColor[15] = {TFT_RED, TFT_DARKGREY, TFT_DARKGREEN, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE + }; + +// Invoke the TFT_eSPI button class and create all the button objects +TFT_eSPI_Button key[15]; + +//------------------------------------------------------------------------------------------ + +void setup() { + // Use serial port + Serial.begin(9600); + + // Initialise the TFT screen + tft.init(); + + // Set the rotation before we calibrate + tft.setRotation(0); + + // Calibrate the touch screen and retrieve the scaling factors + touch_calibrate(); + + // Clear the screen + tft.fillScreen(TFT_BLACK); + + // Draw keypad background + tft.fillRect(0, 0, 240, 320, TFT_DARKGREY); + + // Draw number display area and frame + tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK); + tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE); + + // Draw keypad + drawKeypad(); +} + +//------------------------------------------------------------------------------------------ + +void loop(void) { + uint16_t t_x = 0, t_y = 0; // To store the touch coordinates + + // Pressed will be set true is there is a valid touch on the screen + boolean pressed = tft.getTouch(&t_x, &t_y); + + // / Check if any key coordinate boxes contain the touch coordinates + for (uint8_t b = 0; b < 15; b++) { + if (pressed && key[b].contains(t_x, t_y)) { + key[b].press(true); // tell the button it is pressed + } else { + key[b].press(false); // tell the button it is NOT pressed + } + } + + // Check if any key has changed state + for (uint8_t b = 0; b < 15; b++) { + + if (b < 3) tft.setFreeFont(LABEL1_FONT); + else tft.setFreeFont(LABEL2_FONT); + + if (key[b].justReleased()) key[b].drawButton(); // draw normal + + if (key[b].justPressed()) { + key[b].drawButton(true); // draw invert + + // if a numberpad button, append the relevant # to the numberBuffer + if (b >= 3) { + if (numberIndex < NUM_LEN) { + numberBuffer[numberIndex] = keyLabel[b][0]; + numberIndex++; + numberBuffer[numberIndex] = 0; // zero terminate + } + status(""); // Clear the old status + } + + // Del button, so delete last char + if (b == 1) { + numberBuffer[numberIndex] = 0; + if (numberIndex > 0) { + numberIndex--; + numberBuffer[numberIndex] = 0;//' '; + } + status(""); // Clear the old status + } + + if (b == 2) { + status("Sent value to serial port"); + Serial.println(numberBuffer); + } + // we dont really check that the text field makes sense + // just try to call + if (b == 0) { + status("Value cleared"); + numberIndex = 0; // Reset index to 0 + numberBuffer[numberIndex] = 0; // Place null in buffer + } + + // Update the number display field + tft.setTextDatum(TL_DATUM); // Use top left corner as text coord datum + tft.setFreeFont(&FreeSans18pt7b); // Choose a nicefont that fits box + tft.setTextColor(DISP_TCOLOR); // Set the font colour + + // Draw the string, the value returned is the width in pixels + int xwidth = tft.drawString(numberBuffer, DISP_X + 4, DISP_Y + 12); + + // Now cover up the rest of the line up by drawing a black rectangle. No flicker this way + // but it will not work with italic or oblique fonts due to character overlap. + tft.fillRect(DISP_X + 4 + xwidth, DISP_Y + 1, DISP_W - xwidth - 5, DISP_H - 2, TFT_BLACK); + + delay(10); // UI debouncing + } + } +} + +//------------------------------------------------------------------------------------------ + +void drawKeypad() +{ + // Draw the keys + for (uint8_t row = 0; row < 5; row++) { + for (uint8_t col = 0; col < 3; col++) { + uint8_t b = col + row * 3; + + if (b < 3) tft.setFreeFont(LABEL1_FONT); + else tft.setFreeFont(LABEL2_FONT); + + key[b].initButton(&tft, KEY_X + col * (KEY_W + KEY_SPACING_X), + KEY_Y + row * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text + KEY_W, KEY_H, TFT_WHITE, keyColor[b], TFT_WHITE, + keyLabel[b], KEY_TEXTSIZE); + key[b].drawButton(); + } + } +} + +//------------------------------------------------------------------------------------------ + +void touch_calibrate() +{ + uint16_t calData[5]; + uint8_t calDataOK = 0; + + // check file system exists + if (!SPIFFS.begin()) { + Serial.println("Formating file system"); + SPIFFS.format(); + SPIFFS.begin(); + } + + // check if calibration file exists and size is correct + if (SPIFFS.exists(CALIBRATION_FILE)) { + if (REPEAT_CAL) + { + // Delete if we want to re-calibrate + SPIFFS.remove(CALIBRATION_FILE); + } + else + { + File f = SPIFFS.open(CALIBRATION_FILE, "r"); + if (f) { + if (f.readBytes((char *)calData, 14) == 14) + calDataOK = 1; + f.close(); + } + } + } + + if (calDataOK && !REPEAT_CAL) { + // calibration data valid + tft.setTouch(calData); + } else { + // data not valid so recalibrate + tft.fillScreen(TFT_BLACK); + tft.setCursor(20, 0); + tft.setTextFont(2); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + tft.println("Touch corners as indicated"); + + tft.setTextFont(1); + tft.println(); + + if (REPEAT_CAL) { + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Set REPEAT_CAL to false to stop this running again!"); + } + + tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Calibration complete!"); + + // store data + File f = SPIFFS.open(CALIBRATION_FILE, "w"); + if (f) { + f.write((const unsigned char *)calData, 14); + f.close(); + } + } +} + +//------------------------------------------------------------------------------------------ + +// Print something in the mini status bar +void status(const char *msg) { + tft.setTextPadding(240); + //tft.setCursor(STATUS_X, STATUS_Y); + tft.setTextColor(TFT_WHITE, TFT_DARKGREY); + tft.setTextFont(0); + tft.setTextDatum(TC_DATUM); + tft.setTextSize(1); + tft.drawString(msg, STATUS_X, STATUS_Y); +} + +//------------------------------------------------------------------------------------------ + diff --git a/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino b/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino index 222904b..599d354 100644 --- a/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino +++ b/examples/320 x 240/Read_ID_bitbash/Read_ID_bitbash.ino @@ -4,6 +4,8 @@ // Bit bashes SPI so it does NOT assume hardware SPI wired up // No other libraries are needed +// NOTE: This sketch does not work with parallel displays! + // Original author unknown // Adapted by Bodmer 22/5/16, updated 16/9/16 diff --git a/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino b/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino deleted file mode 100644 index 081087c..0000000 --- a/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino +++ /dev/null @@ -1,106 +0,0 @@ -// Icons are stored in tabs ^ e.g. Alert.h etc above this line -// more than one icon can be in a header file - -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - Works with TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - This sketch does not use/need any fonts at all... - - Code derived from ILI9341_due example - - Make sure all the display driver and pin comnenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. - - ######################################################################### - ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### - ######################################################################### -*/ - -#include // Hardware-specific library - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library - -// Include the header files that contain the icons -#include "alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.begin(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, 100, 100, infoWidth, infoHeight); - drawIcon(alert, 140, 100, alertWidth, alertHeight); - drawIcon(close, 180, 100, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(2000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(close, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - //Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, int8_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino b/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino index 73e0afc..2a04556 100644 --- a/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino +++ b/examples/320 x 240/TFT_Mandlebrot/TFT_Mandlebrot.ino @@ -7,7 +7,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library -#define ILI9341_GREY 0x7BEF +#define TFT_GREY 0x7BEF unsigned long runTime = 0; @@ -16,8 +16,9 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0; void setup() { + Serial.begin(250000); //randomSeed(analogRead(A0)); - + Serial.println(); // Setup the LCD tft.init(); tft.setRotation(3); @@ -27,7 +28,8 @@ void loop() { runTime = millis(); - tft.fillScreen(ILI9341_BLACK); + tft.fillScreen(TFT_BLACK); + tft.startWrite(); for (int px = 1; px < 320; px++) { for (int py = 0; py < 240; py++) @@ -49,6 +51,9 @@ void loop() yield();tft.drawPixel(px, py, color); } } + tft.endWrite(); + + Serial.println(millis()-runTime); while(1) yield(); } diff --git a/examples/320 x 240/TFT_Pong/TFT_Pong.ino b/examples/320 x 240/TFT_Pong/TFT_Pong.ino index 6cf91f2..5bcd880 100644 --- a/examples/320 x 240/TFT_Pong/TFT_Pong.ino +++ b/examples/320 x 240/TFT_Pong/TFT_Pong.ino @@ -108,13 +108,17 @@ void midline() { // If the ball is not on the line then don't redraw the line if ((ball_x dashline_x+dashline_w)) return; + tft.startWrite(); + // Quick way to draw a dashed line - tft.setWindow(dashline_x,0,dashline_x+dashline_w-1,h); + tft.setAddrWindow(dashline_x, 0, dashline_w, h); for(int16_t i = 0; i < dashline_n; i+=2) { tft.pushColor(WHITE, dashline_w*dashline_h); // push dash pixels tft.pushColor(BLACK, dashline_w*dashline_h); // push gap pixels } + + tft.endWrite(); } void lpaddle() { diff --git a/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino b/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino deleted file mode 100644 index d791b0f..0000000 --- a/examples/320 x 240/TFT_Screen_Capture/TFT_Screen_Capture.ino +++ /dev/null @@ -1,188 +0,0 @@ -/* - This sketch has been written to test the Processing screenshot client. - - It has been created to work with the TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - It sends screenshots to a PC running a Processing client sketch. - - The Processing IDE that will run the client sketch can be downloaded - here: https://processing.org/ - - The Processing sketch needed is contained within a tab attached to this - Arduino sketch. Cut and copy that tab into the Processing IDE and run. - - This sketch uses the GLCD, 2, 4, 6 fonts only. - - Make sure all the display driver and pin comnenctions are correct by - editting the User_Setup.h file in the TFT_eSPI library folder. - - Maximum recommended SPI clock rate is 27MHz when reading pixels, 40MHz - seems to be OK with ILI9341 displays but this is above the manufacturers - specifed maximum clock rate. - - ######################################################################### - ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### - ######################################################################### -*/ - -// Created by: Bodmer 5/3/17 -// Updated by: Bodmer 10/3/17 -// Version: 0.06 - -// MIT licence applies, all text above must be included in derivative works - -#include // Hardware-specific library -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height - -unsigned long targetTime = 0; -byte red = 31; -byte green = 0; -byte blue = 0; -byte state = 0; -unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each - -void setup(void) { - Serial.begin(921600); - - tft.init(); - tft.setRotation(0); - tft.fillScreen(TFT_BLACK); - - randomSeed(analogRead(A0)); - - targetTime = millis() + 1000; -} - -void loop() { - - if (targetTime < millis()) { - targetTime = millis() + 1500; // Wait a minimum of 1.5s - - tft.setRotation(random(4)); - rainbow_fill(); // Fill the screen with rainbow colours - - tft.setTextColor(TFT_BLACK); // Text background is not defined so it is transparent - tft.setTextDatum(TC_DATUM); // Top Centre datum - int xpos = tft.width()/2; // Centre of screen - - tft.setTextFont(0); // Select font 0 which is the Adafruit font - tft.drawString("Original Adafruit font!", xpos, 5); - - // The new larger fonts do not need to use the .setCursor call, coords are embedded - tft.setTextColor(TFT_BLACK); // Do not plot the background colour - - // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) - tft.drawString("Font size 2", xpos, 14, 2); // Draw text centre at position xpos, 14 using font 2 - tft.drawString("Font size 4", xpos, 30, 4); // Draw text centre at position xpos, 30 using font 4 - tft.drawString("12.34", xpos, 54, 6); // Draw text centre at position xpos, 54 using font 6 - - tft.drawString("12.34 is in font size 6", xpos, 92, 2); // Draw text centre at position xpos, 92 using font 2 - // Note the x position is the top of the font! - - // draw a floating point number - float pi = 3.1415926; // Value to print - int precision = 3; // Number of digits after decimal point - - int ypos = 110; // y position - - tft.setTextDatum(TR_DATUM); // Top Right datum so text butts neatly to xpos (right justified) - - tft.drawFloat(pi, precision, xpos, ypos, 2); // Draw rounded number and return new xpos delta for next print position - - tft.setTextDatum(TL_DATUM); // Top Left datum so text butts neatly to xpos (left justified) - - tft.drawString(" is pi", xpos, ypos, 2); - - tft.setTextSize(1); // We are using a font size multiplier of 1 - tft.setTextDatum(TC_DATUM); // Top Centre datum - tft.setTextColor(TFT_BLACK); // Set text colour to black, no background (so transparent) - - tft.drawString("Transparent...", xpos, 125, 4); // Font 4 - - tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text colour to white and background to black - tft.drawString("White on black", xpos, 150, 4); // Font 4 - - tft.setTextColor(TFT_GREEN, TFT_BLACK); // This time we will use green text on a black background - - tft.setTextFont(2); // Select font 2, now we do not need to specify the font in drawString() - - // An easier way to position text and blank old text is to set the datum and use width padding - tft.setTextDatum(BC_DATUM); // Bottom centre for text datum - tft.setTextPadding(tft.width() + 1); // Pad text to full screen width + 1 spare for +/-1 position rounding - - tft.drawString("Ode to a Small Lump of Green Putty", xpos, 230 - 32); - tft.drawString("I Found in My Armpit One Midsummer", xpos, 230 - 16); - tft.drawString("Morning", xpos, 230); - - tft.setTextDatum(TL_DATUM); // Reset to top left for text datum - tft.setTextPadding(0); // Reset text padding to 0 pixels - - // Now call the screen server to send a copy of the TFT screen to the PC running the Processing client sketch - screenServer(); - } -} - -// Fill screen with a rainbow pattern -void rainbow_fill() -{ - // The colours and state are not initialised so the start colour changes each time the funtion is called - int rotation = tft.getRotation(); - tft.setRotation(random(4)); - for (int i = tft.height() - 1; i >= 0; i--) { - // This is a "state machine" that ramps up/down the colour brightnesses in sequence - switch (state) { - case 0: - green ++; - if (green == 64) { - green = 63; - state = 1; - } - break; - case 1: - red--; - if (red == 255) { - red = 0; - state = 2; - } - break; - case 2: - blue ++; - if (blue == 32) { - blue = 31; - state = 3; - } - break; - case 3: - green --; - if (green == 255) { - green = 0; - state = 4; - } - break; - case 4: - red ++; - if (red == 32) { - red = 31; - state = 5; - } - break; - case 5: - blue --; - if (blue == 255) { - blue = 0; - state = 0; - } - break; - } - colour = red << 11 | green << 5 | blue; - // Draw a line 1 pixel wide in the selected colour - tft.drawFastHLine(0, i, tft.width(), colour); // in this example tft.width() returns the pixel width of the display - } - tft.setRotation(rotation); -} - - - diff --git a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino index 7db002e..ee76936 100644 --- a/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino +++ b/examples/320 x 240/TFT_graphicstest_PDQ/TFT_graphicstest_PDQ.ino @@ -336,10 +336,10 @@ uint32_t testHaD() tft.fillScreen(TFT_BLACK); uint32_t start = micros_start(); - + for (int i = 0; i < 0x10; i++) { - tft.setWindow(0, 0, 240-1, 320-1); + tft.setAddrWindow(0, 0, 240, 320); uint16_t cnt = 0; uint16_t color = tft.color565((i << 4) | i, (i << 4) | i, (i << 4) | i); @@ -347,6 +347,7 @@ uint32_t testHaD() const uint8_t *cmp = &HaD_240x320[0]; + tft.startWrite(); while (cmp < &HaD_240x320[sizeof(HaD_240x320)]) { cnt = pgm_read_byte(cmp++); @@ -354,6 +355,7 @@ uint32_t testHaD() tft.pushColor(curcolor, cnt); // PDQ_GFX has count curcolor ^= color; } + tft.endWrite(); } uint32_t t = micros() - start; @@ -432,7 +434,7 @@ uint32_t testPixels() int32_t h = tft.height(); uint32_t start = micros_start(); - + tft.startWrite(); for (uint16_t y = 0; y < h; y++) { for (uint16_t x = 0; x < w; x++) @@ -440,7 +442,7 @@ uint32_t testPixels() tft.drawPixel(x, y, tft.color565(x<<3, y<<3, x*y)); } } - + tft.endWrite(); return micros() - start; } diff --git a/examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h b/examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h deleted file mode 100644 index 767147c..0000000 --- a/examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h +++ /dev/null @@ -1,226 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -// Created by http://oleddisplay.squix.ch/ Consider a donation -// In case of problems make sure that you are using the font file with the correct version! - -// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected -// this avoids screen corruption if ~ is printer - -// Bodmer change: '`' changed to tiny degree symbol (typically this character is on top left key of a QWERTY keyboard) - -const uint8_t ArialRoundedMTBold_36Bitmaps[] PROGMEM = { - - // Bitmap Data: - 0x00, // ' ' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x39,0xCE,0x73,0x00,0x00,0x3B,0xFF,0xFB,0x80, // '!' - 0xFC,0xFF,0xF3,0xFF,0xCF,0xFF,0x3F,0xFC,0xFF,0xF3,0xFF,0xCF,0xDE,0x1E,0x78,0x78, // '"' - 0x01,0x83,0x80,0x78,0x70,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x0F,0x0F,0x01,0xE1,0xE3,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x07,0x87,0x80,0xF0,0xE0,0x1E,0x3C,0x07,0x87,0x80,0xF0,0xF0,0x7F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xE3,0xC3,0xC0,0x78,0x78,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x07,0x06,0x00, // '#' - 0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x7F,0xE0,0x3F,0xFE,0x0F,0xFF,0xE1,0xF3,0x7E,0x7C,0x67,0xCF,0x0C,0x79,0xE1,0x8F,0x3C,0x30,0xC7,0xC6,0x00,0xFE,0xC0,0x0F,0xF8,0x00,0xFF,0xE0,0x0F,0xFF,0x00,0x7F,0xF0,0x01,0xFF,0x00,0x37,0xE0,0x06,0x3E,0xE0,0xC3,0xFC,0x18,0x7F,0xC3,0x0F,0xF8,0x61,0xEF,0x8C,0x79,0xFD,0x9F,0x1F,0xFF,0xC1,0xFF,0xF0,0x0F,0xFC,0x00,0x38,0x00,0x03,0x00,0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x06,0x00, // '$' - 0x1F,0x00,0x06,0x03,0xFC,0x00,0x70,0x1C,0x70,0x03,0x01,0xC1,0x80,0x38,0x0E,0x0E,0x03,0x80,0x70,0x70,0x1C,0x03,0x83,0x81,0xC0,0x1C,0x1C,0x0C,0x00,0xE0,0xE0,0xE0,0x07,0x07,0x0E,0x00,0x1C,0x70,0x70,0x00,0xFF,0x87,0x00,0x03,0xF8,0x30,0x00,0x00,0x03,0x87,0xF0,0x00,0x38,0x7F,0xC0,0x01,0xC3,0x8E,0x00,0x1C,0x38,0x38,0x00,0xC1,0xC1,0xC0,0x0E,0x0E,0x0E,0x00,0xE0,0x70,0x70,0x07,0x03,0x83,0x80,0x70,0x1C,0x1C,0x07,0x00,0xE0,0xE0,0x38,0x03,0x8E,0x03,0x80,0x0F,0xE0,0x1C,0x00,0x3E,0x00,0xC0,0x00,0x00, // '%' - 0x00,0xFC,0x00,0x01,0xFF,0x80,0x01,0xFF,0xE0,0x01,0xF0,0xF0,0x00,0xF0,0x3C,0x00,0x78,0x1E,0x00,0x3C,0x0F,0x00,0x1F,0x0F,0x80,0x0F,0xDF,0x80,0x03,0xFF,0x80,0x00,0xFF,0x80,0x00,0xFF,0x00,0x00,0xFF,0xC1,0x81,0xFF,0xF0,0xE1,0xF9,0xF8,0xF8,0xF8,0x7E,0x78,0xF8,0x1F,0xFC,0x7C,0x07,0xFC,0x3E,0x01,0xFE,0x1F,0x00,0x7F,0x0F,0xC0,0x3F,0xC3,0xF0,0x7F,0xF1,0xFF,0xFF,0xFC,0x7F,0xFF,0x3F,0x0F,0xFE,0x0F,0x01,0xFC,0x03,0x80, // '&' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x78, // ''' - 0x03,0x81,0xC1,0xC1,0xE0,0xF0,0xF0,0xF8,0x78,0x3C,0x3E,0x1F,0x0F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x83,0xC1,0xF0,0xF8,0x3C,0x1E,0x0F,0x83,0xC0,0xF0,0x78,0x1C,0x07,0x01,0x80, // '(' - 0xE0,0x70,0x1C,0x0F,0x03,0x81,0xE0,0xF8,0x3C,0x1E,0x0F,0x87,0xC1,0xE0,0xF8,0x7C,0x3E,0x1F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x78,0x7C,0x3E,0x1E,0x0F,0x0F,0x87,0x83,0x83,0xC1,0xC1,0xC0,0xE0,0x00, // ')' - 0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x0E,0x38,0xFF,0x77,0xDF,0xFF,0x07,0xF0,0x07,0xC0,0x1D,0xC0,0x3B,0xC0,0xE3,0x83,0xC7,0x83,0x06,0x00, // '*' - 0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00, // '+' - 0x7B,0xEF,0xFF,0x7C,0x71,0xCE,0x7B,0xCE,0x00, // ',' - 0x7F,0xDF,0xFF,0xFF,0xBF,0xE0, // '-' - 0x77,0xFF,0xF7,0x00, // '.' - 0x03,0x81,0xC1,0xE0,0xF0,0x70,0x78,0x3C,0x1E,0x0E,0x07,0x07,0x83,0xC1,0xC0,0xE0,0xF0,0x78,0x38,0x1C,0x1E,0x0F,0x07,0x03,0x83,0xC1,0xE0,0xE0,0x70,0x00, // '/' - 0x03,0xF0,0x03,0xFF,0x01,0xFF,0xE0,0xFF,0xFC,0x3E,0x1F,0x1F,0x03,0xE7,0xC0,0xF9,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x79,0xF0,0x3E,0x7C,0x0F,0x8F,0x87,0xC3,0xFF,0xF0,0x7F,0xF8,0x0F,0xFC,0x00,0xFC,0x00, // '0' - 0x00,0x30,0x03,0xC0,0x3E,0x03,0xF0,0x3F,0x83,0xFC,0x7F,0xEF,0xDF,0xFC,0xFF,0xC7,0xD8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x03,0x80, // '1' - 0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0x9F,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0xF0,0x07,0xD8,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x1F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xF0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xF0, // '2' - 0x03,0xF0,0x07,0xFF,0x03,0xFF,0xE1,0xF0,0xFC,0x78,0x1F,0x1E,0x03,0xE7,0x00,0xF8,0x80,0x3E,0x00,0x1F,0x00,0x0F,0xC0,0x7F,0xE0,0x1F,0xF0,0x07,0xFE,0x01,0xFF,0xC0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xD8,0x01,0xFF,0x00,0x7F,0xE0,0x1F,0xF8,0x0F,0x9F,0x07,0xE7,0xFF,0xF0,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '3' - 0x00,0x0F,0x00,0x00,0xFC,0x00,0x07,0xE0,0x00,0x7F,0x00,0x07,0xF8,0x00,0x7F,0xC0,0x03,0xFE,0x00,0x3D,0xF0,0x03,0xCF,0x80,0x3C,0x7C,0x03,0xE3,0xE0,0x1E,0x1F,0x01,0xE0,0xF8,0x1E,0x07,0xC1,0xF0,0x3E,0x0F,0x01,0xF0,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE0,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x38,0x00, // '4' - 0x1F,0xFF,0x8F,0xFF,0xE3,0xFF,0xF8,0xFF,0xFC,0x3C,0x00,0x0F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x78,0x00,0x1E,0x7E,0x07,0xFF,0xE1,0xFF,0xFC,0xFF,0xFF,0xBF,0x07,0xE7,0x80,0xFC,0x80,0x1F,0x00,0x07,0xC0,0x01,0xF6,0x00,0x7F,0xC0,0x1F,0xF0,0x0F,0xBE,0x03,0xE7,0xC1,0xF1,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '5' - 0x03,0xF8,0x01,0xFF,0x81,0xFF,0xF0,0x7C,0x7C,0x3C,0x0F,0x9F,0x03,0xE7,0x80,0x71,0xE0,0x00,0xF8,0x00,0x3E,0x3E,0x0F,0xBF,0xE3,0xFF,0xFC,0xFE,0x1F,0xBF,0x03,0xEF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x7D,0xF0,0x1F,0x7C,0x0F,0x8F,0x87,0xE3,0xFF,0xF0,0x7F,0xFC,0x0F,0xFC,0x00,0xFC,0x00, // '6' - 0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x00,0x0F,0x80,0x07,0xC0,0x01,0xE0,0x00,0xF8,0x00,0x7C,0x00,0x1E,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x3E,0x00,0x0F,0x80,0x07,0xC0,0x01,0xF0,0x00,0x7C,0x00,0x3F,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x01,0xC0,0x00, // '7' - 0x03,0xF8,0x01,0xFF,0xC0,0x7F,0xFC,0x1F,0x0F,0xC7,0xC0,0xFC,0xF8,0x0F,0x9F,0x01,0xF3,0xE0,0x3E,0x7C,0x07,0xCF,0x80,0xF0,0xF8,0x7E,0x0F,0xFF,0x80,0xFF,0xE0,0x7F,0xFE,0x1F,0x83,0xF3,0xE0,0x3E,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0x80,0x3E,0xF8,0x0F,0x9F,0x83,0xF1,0xFF,0xFC,0x1F,0xFF,0x00,0x7F,0x00, // '8' - 0x03,0xF0,0x03,0xFF,0x03,0xFF,0xE0,0xFF,0xFC,0x7E,0x1F,0x1F,0x03,0xEF,0x80,0xFB,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x0F,0xDF,0x87,0xF3,0xFF,0xFC,0x7F,0xDF,0x07,0xC7,0xC0,0x01,0xF0,0x00,0x78,0xE0,0x1E,0x78,0x0F,0x9F,0x03,0xC3,0xE3,0xE0,0xFF,0xF8,0x1F,0xF8,0x01,0xF8,0x00, // '9' - 0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDF,0xFF,0xDC, // ':' - 0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDE,0xFF,0xFE,0x73,0x9B,0xDC,0xC0, // ';' - 0x00,0x00,0x40,0x00,0x70,0x00,0xFC,0x00,0xFF,0x00,0xFF,0xC1,0xFF,0xE1,0xFF,0xC1,0xFF,0xC0,0xFF,0x80,0x3F,0x80,0x0F,0xE0,0x03,0xFE,0x00,0x7F,0xF0,0x07,0xFF,0x00,0x7F,0xF8,0x03,0xFF,0x00,0x3F,0xC0,0x03,0xF0,0x00,0x1C,0x00,0x01, // '<' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, // '=' - 0x80,0x00,0x38,0x00,0x0F,0xC0,0x03,0xFC,0x00,0xFF,0xC0,0x1F,0xFE,0x00,0xFF,0xE0,0x0F,0xFE,0x00,0x7F,0xC0,0x07,0xF0,0x01,0xFC,0x01,0xFF,0x03,0xFF,0x83,0xFF,0x87,0xFF,0x83,0xFF,0x00,0xFF,0x00,0x3F,0x00,0x0E,0x00,0x02,0x00,0x00, // '>' - 0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0xBF,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0x70,0x07,0xC8,0x03,0xE0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x1F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x38,0x00, // '?' - 0x00,0x07,0xFE,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x0F,0xFF,0xFE,0x00,0x07,0xE0,0x0F,0xE0,0x07,0xC0,0x00,0x7C,0x03,0xE0,0x00,0x0F,0x00,0xE0,0x00,0x01,0xE0,0x70,0x1F,0x9F,0x3C,0x3C,0x1F,0xF7,0xC7,0x0E,0x0F,0xFF,0xE1,0xC7,0x07,0xE3,0xF8,0x39,0xC3,0xE0,0x7E,0x0E,0x70,0xF8,0x0F,0x83,0xB8,0x7C,0x03,0xE0,0xEE,0x1F,0x00,0xF0,0x3B,0x8F,0x80,0x3C,0x0E,0xE3,0xE0,0x1F,0x07,0xB8,0xF8,0x07,0xC1,0xCE,0x3E,0x01,0xE0,0xF3,0x8F,0x80,0xF8,0x78,0xE3,0xE0,0x3E,0x1E,0x1C,0x7C,0x1F,0x9F,0x07,0x1F,0xFF,0xFF,0x81,0xC3,0xFF,0xFF,0xC0,0x38,0x7F,0xBF,0xE0,0x0F,0x07,0x87,0xE0,0x01,0xE0,0x00,0x00,0x3C,0x3C,0x00,0x00,0x3E,0x07,0xC0,0x00,0x1F,0x00,0xFE,0x00,0x3F,0x80,0x1F,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x80,0x00,0x07,0xFF,0x00,0x00, // '@' - 0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x01,0xFF,0x00,0x01,0xFF,0x80,0x01,0xEF,0x80,0x03,0xE7,0xC0,0x03,0xE7,0xC0,0x07,0xC7,0xC0,0x07,0xC3,0xE0,0x07,0xC3,0xE0,0x0F,0x81,0xF0,0x0F,0x81,0xF0,0x1F,0x81,0xF8,0x1F,0x00,0xF8,0x1F,0xFF,0xF8,0x3F,0xFF,0xFC,0x3F,0xFF,0xFC,0x7F,0xFF,0xFE,0x7C,0x00,0x7E,0x7C,0x00,0x3E,0xFC,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x1F,0x70,0x00,0x0E, // 'A' - 0x7F,0xFF,0x07,0xFF,0xFC,0x3F,0xFF,0xF1,0xFF,0xFF,0xCF,0x80,0x7F,0x7C,0x01,0xFB,0xE0,0x07,0xDF,0x00,0x3E,0xF8,0x01,0xF7,0xC0,0x1F,0x3E,0x01,0xF9,0xFF,0xFF,0x8F,0xFF,0xF0,0x7F,0xFF,0xE3,0xFF,0xFF,0x9F,0x00,0x7E,0xF8,0x01,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x01,0xFB,0xFF,0xFF,0xDF,0xFF,0xFC,0xFF,0xFF,0xC3,0xFF,0xF8,0x00, // 'B' - 0x00,0xFF,0x00,0x07,0xFF,0x80,0x3F,0xFF,0xC0,0xFF,0xFF,0xC3,0xF8,0x1F,0xC7,0xE0,0x1F,0x9F,0x80,0x1F,0x3E,0x00,0x1F,0x7C,0x00,0x3D,0xF0,0x00,0x33,0xE0,0x00,0x07,0xC0,0x00,0x0F,0x80,0x00,0x1F,0x00,0x00,0x3E,0x00,0x00,0x7C,0x00,0x04,0xF8,0x00,0x1C,0xF8,0x00,0x7D,0xF0,0x00,0xFB,0xF0,0x03,0xE3,0xF0,0x0F,0xC7,0xF0,0x3F,0x07,0xFF,0xFE,0x07,0xFF,0xF8,0x03,0xFF,0xC0,0x01,0xFE,0x00, // 'C' - 0x7F,0xFE,0x03,0xFF,0xFE,0x0F,0xFF,0xFC,0x3F,0xFF,0xF8,0xF8,0x07,0xF3,0xE0,0x07,0xEF,0x80,0x1F,0xBE,0x00,0x3E,0xF8,0x00,0xFF,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x03,0xFF,0x80,0x0F,0xBE,0x00,0x7E,0xF8,0x01,0xFB,0xE0,0x1F,0xCF,0xFF,0xFE,0x3F,0xFF,0xF0,0xFF,0xFF,0x81,0xFF,0xF8,0x00, // 'D' - 0x7F,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFE,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xCF,0xFF,0xFC,0xFF,0xFF,0xCF,0xFF,0xFC,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFE, // 'E' - 0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xFF,0xF8,0xFF,0xFF,0x3F,0xFF,0xCF,0xFF,0xE3,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x1C,0x00,0x00, // 'F' - 0x00,0x7F,0x80,0x03,0xFF,0xF0,0x07,0xFF,0xF8,0x1F,0xFF,0xFC,0x1F,0xC1,0xFE,0x3F,0x00,0x7E,0x7E,0x00,0x3E,0x7C,0x00,0x3E,0x7C,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x07,0xFE,0xF8,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x07,0xFF,0xF8,0x00,0x1F,0x7C,0x00,0x1F,0x7C,0x00,0x1F,0x7E,0x00,0x1F,0x3F,0x00,0x3F,0x1F,0xC0,0xFF,0x1F,0xFF,0xFE,0x07,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0x7F,0x80, // 'G' - 0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'H' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'I' - 0x00,0x07,0x00,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x70,0x0F,0xFC,0x07,0xFE,0x03,0xFF,0x01,0xFF,0xC1,0xFB,0xF1,0xF9,0xFF,0xFC,0x7F,0xFC,0x1F,0xFC,0x03,0xF8,0x00, // 'J' - 0x70,0x00,0xE3,0xE0,0x07,0xCF,0x80,0x3F,0x3E,0x01,0xFC,0xF8,0x0F,0xE3,0xE0,0x7F,0x0F,0x83,0xF8,0x3E,0x1F,0xC0,0xF8,0xFE,0x03,0xE7,0xF0,0x0F,0xBF,0x80,0x3F,0xFF,0x00,0xFF,0xFC,0x03,0xFF,0xF8,0x0F,0xFB,0xF0,0x3F,0xCF,0xE0,0xFE,0x1F,0x83,0xE0,0x3F,0x0F,0x80,0xFE,0x3E,0x01,0xF8,0xF8,0x03,0xF3,0xE0,0x0F,0xEF,0x80,0x1F,0xBE,0x00,0x3F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'K' - 0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xE0, // 'L' - 0x7E,0x00,0x3F,0x7F,0x80,0x3F,0xFF,0xE0,0x1F,0xFF,0xF0,0x1F,0xFF,0xF8,0x0F,0xFF,0xFC,0x07,0xFF,0xFF,0x07,0xFF,0xFF,0x83,0xFF,0xFB,0xC1,0xEF,0xFD,0xE0,0xF7,0xFE,0xF8,0xFB,0xFF,0x7C,0x7D,0xFF,0x9E,0x3C,0xFF,0xCF,0x1E,0x7F,0xE7,0xDF,0x3F,0xF3,0xEF,0x9F,0xF8,0xF7,0x8F,0xFC,0x7B,0xC7,0xFE,0x3F,0xE3,0xFF,0x1F,0xF1,0xFF,0x87,0xF0,0xFF,0xC3,0xF8,0x7F,0xE1,0xFC,0x3F,0xF0,0x7C,0x1F,0xF8,0x3E,0x0F,0xB8,0x0E,0x03,0x80, // 'M' - 0x78,0x00,0x3B,0xF0,0x01,0xFF,0xC0,0x07,0xFF,0x80,0x1F,0xFF,0x00,0x7F,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xF0,0x1F,0xFF,0xE0,0x7F,0xEF,0x81,0xFF,0x9F,0x07,0xFE,0x7E,0x1F,0xF8,0xF8,0x7F,0xE1,0xF1,0xFF,0x87,0xE7,0xFE,0x0F,0x9F,0xF8,0x1F,0x7F,0xE0,0x7F,0xFF,0x80,0xFF,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xE0,0x0F,0xFF,0x80,0x1F,0xFE,0x00,0x7F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'N' - 0x00,0xFF,0x00,0x01,0xFF,0xF0,0x03,0xFF,0xFE,0x03,0xFF,0xFF,0x83,0xFC,0x1F,0xE1,0xF8,0x03,0xF1,0xF8,0x00,0xFC,0xF8,0x00,0x3E,0x7C,0x00,0x1F,0x7C,0x00,0x07,0xFE,0x00,0x03,0xFF,0x00,0x01,0xFF,0x80,0x00,0xFF,0xC0,0x00,0x7F,0xE0,0x00,0x3F,0xF0,0x00,0x1F,0xFC,0x00,0x0F,0xBE,0x00,0x0F,0x9F,0x00,0x07,0xCF,0xC0,0x07,0xE3,0xF0,0x07,0xE0,0xFE,0x0F,0xF0,0x7F,0xFF,0xF0,0x1F,0xFF,0xF0,0x03,0xFF,0xE0,0x00,0x3F,0xC0,0x00, // 'O' - 0x7F,0xFC,0x1F,0xFF,0xE3,0xFF,0xFE,0x7F,0xFF,0xEF,0x80,0xFD,0xF0,0x0F,0xFE,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFC,0x07,0xEF,0xFF,0xFD,0xFF,0xFF,0x3F,0xFF,0xC7,0xFF,0xE0,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'P' - 0x00,0xFF,0x00,0x00,0xFF,0xF8,0x00,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x3F,0xC1,0xFE,0x0F,0xC0,0x1F,0x87,0xE0,0x03,0xF1,0xF0,0x00,0x7C,0x7C,0x00,0x1F,0x3E,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0xBE,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0x9F,0x07,0x07,0xC7,0xC1,0xF1,0xF1,0xF8,0x3F,0xFC,0x3F,0x03,0xFE,0x07,0xF0,0x7F,0x81,0xFF,0xFF,0xC0,0x1F,0xFF,0xF8,0x03,0xFF,0xFF,0x80,0x1F,0xE3,0xF0,0x00,0x00,0x7C,0x00,0x00,0x07, // 'Q' - 0x7F,0xFF,0x07,0xFF,0xFE,0x3F,0xFF,0xF9,0xFF,0xFF,0xEF,0x80,0x3F,0xFC,0x00,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x0F,0xFE,0x00,0xFD,0xFF,0xFF,0xEF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x1F,0x07,0xE0,0xF8,0x1F,0x87,0xC0,0x7E,0x3E,0x01,0xF9,0xF0,0x0F,0xCF,0x80,0x3F,0x7C,0x00,0xFF,0xE0,0x07,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0xC0, // 'R' - 0x03,0xF8,0x01,0xFF,0xF0,0x3F,0xFF,0x87,0xFF,0xFC,0x7E,0x0F,0xCF,0xC0,0x7E,0xF8,0x03,0xEF,0x80,0x1E,0xFC,0x00,0xCF,0xF0,0x00,0x7F,0xF0,0x03,0xFF,0xE0,0x1F,0xFF,0x80,0x7F,0xFC,0x00,0x7F,0xE0,0x00,0x7F,0x60,0x03,0xFF,0x00,0x1F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xFF,0xE0,0x7E,0x7F,0xFF,0xC3,0xFF,0xFC,0x0F,0xFF,0x00,0x3F,0xC0, // 'S' - 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'T' - 0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF8,0x03,0xF7,0xC0,0x1F,0x3F,0x83,0xF8,0xFF,0xFF,0x83,0xFF,0xF8,0x0F,0xFF,0x80,0x1F,0xF0,0x00, // 'U' - 0x70,0x00,0x1D,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xE0,0x03,0xF7,0xC0,0x07,0xCF,0x80,0x0F,0x9F,0x80,0x3F,0x1F,0x00,0x7C,0x3F,0x00,0xF8,0x7E,0x03,0xE0,0x7C,0x07,0xC0,0xFC,0x0F,0x80,0xF8,0x3E,0x01,0xF0,0x7C,0x03,0xF0,0xF8,0x03,0xE3,0xE0,0x07,0xC7,0xC0,0x07,0xDF,0x00,0x0F,0xBE,0x00,0x1F,0x7C,0x00,0x1F,0xF0,0x00,0x3F,0xE0,0x00,0x7F,0x80,0x00,0x7F,0x00,0x00,0xFE,0x00,0x00,0x70,0x00, // 'V' - 0x70,0x03,0xC0,0x0E,0xF8,0x07,0xE0,0x1F,0xF8,0x07,0xE0,0x1F,0xF8,0x0F,0xF0,0x1F,0xF8,0x0F,0xF0,0x1F,0x7C,0x0F,0xF0,0x3E,0x7C,0x0F,0xF0,0x3E,0x7C,0x1F,0xF8,0x3E,0x7C,0x1E,0x78,0x3E,0x3E,0x1E,0x78,0x7C,0x3E,0x1E,0x78,0x7C,0x3E,0x3E,0x7C,0x7C,0x3E,0x3C,0x3C,0x7C,0x1E,0x3C,0x3C,0x78,0x1F,0x7C,0x3E,0xF8,0x1F,0x78,0x1E,0xF8,0x1F,0x78,0x1E,0xF8,0x0F,0x78,0x1E,0xF0,0x0F,0xF8,0x1F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xC0,0x03,0xC0, // 'W' - 0x38,0x00,0x73,0xE0,0x07,0x9F,0x00,0x7E,0xFC,0x07,0xE3,0xF0,0x3F,0x1F,0x83,0xF0,0x7E,0x3F,0x01,0xF9,0xF8,0x0F,0xDF,0x80,0x3F,0xF8,0x00,0xFF,0xC0,0x07,0xFC,0x00,0x1F,0xC0,0x00,0xFE,0x00,0x0F,0xF8,0x00,0xFF,0xE0,0x07,0xFF,0x80,0x7E,0xFC,0x07,0xE3,0xF0,0x7F,0x1F,0xC3,0xF0,0x7E,0x3F,0x01,0xFB,0xF0,0x07,0xFF,0x80,0x3F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'X' - 0x70,0x00,0x77,0xC0,0x07,0xFF,0x00,0x3E,0xF8,0x03,0xF7,0xE0,0x3F,0x1F,0x01,0xF0,0xFC,0x1F,0x83,0xF0,0xF8,0x0F,0x8F,0x80,0x7E,0xFC,0x01,0xF7,0xC0,0x07,0xFC,0x00,0x3F,0xE0,0x00,0xFE,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'Y' - 0x3F,0xFF,0xF8,0x7F,0xFF,0xF9,0xFF,0xFF,0xF1,0xFF,0xFF,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0x00,0x00,0xFC,0x00,0x03,0xF0,0x00,0x0F,0xE0,0x00,0x3F,0x80,0x00,0x7E,0x00,0x01,0xF8,0x00,0x07,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF8, // 'Z' - 0x7F,0xFF,0xFF,0xFF,0xFF,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3F,0xFF,0xFF,0xFF,0x7F,0xC0, // '[' - 0x70,0x3C,0x07,0x01,0xE0,0x78,0x1E,0x03,0x80,0xF0,0x3C,0x0F,0x01,0xC0,0x78,0x1E,0x07,0x80,0xE0,0x3C,0x0F,0x03,0xC0,0x70,0x1E,0x07,0x81,0xE0,0x38,0x0F,0x03,0xC0,0x60, // '\' - 0xFF,0xBF,0xFF,0xFF,0xFF,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x80, // ']' - 0x03,0xE0,0x01,0xF0,0x01,0xFC,0x00,0xFE,0x00,0x7F,0x80,0x7B,0xC0,0x3D,0xF0,0x3E,0xF8,0x1E,0x3C,0x1F,0x1F,0x0F,0x07,0x8F,0x83,0xE7,0xC1,0xF7,0xC0,0x7C, // '^' - 0xFF,0xFF,0xFF,0xFF,0xF0, // '_' - 0x0E,0x1B,0x11,0x1B,0x0E, // '`' Changed into a degree symbol - 0x03,0xFC,0x03,0xFF,0xE0,0xFF,0xFE,0x3F,0x07,0xC7,0xC0,0x7C,0xF0,0x0F,0x9C,0x01,0xF0,0x00,0xFE,0x01,0xFF,0xC3,0xFF,0xF8,0xFF,0x9F,0x3F,0x03,0xEF,0x80,0x7D,0xF0,0x0F,0xBE,0x03,0xF7,0xE1,0xFE,0x7F,0xFF,0xE7,0xFE,0x7C,0x3E,0x07,0x00, // 'a' - 0x70,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC7,0xE0,0xF9,0xFF,0x1F,0x7F,0xF3,0xFF,0xFF,0x7F,0x87,0xEF,0xE0,0x7D,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFE,0x03,0xFF,0xC0,0x7D,0xFE,0x1F,0xBF,0xFF,0xE7,0xDF,0xFC,0xF9,0xFF,0x0E,0x1F,0x80, // 'b' - 0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xFF,0xFE,0x7F,0x0F,0xDF,0x01,0xFF,0xC0,0x3F,0xE0,0x04,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x07,0xFC,0x03,0xDF,0x01,0xF7,0xF0,0xFC,0xFF,0xFE,0x1F,0xFF,0x83,0xFF,0x80,0x3F,0x80, // 'c' - 0x00,0x01,0xC0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x3F,0x1F,0x1F,0xF3,0xE7,0xFF,0x7D,0xFF,0xFF,0xBF,0x0F,0xF7,0xC0,0xFF,0xF8,0x0F,0xFE,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFE,0x03,0xF7,0xC0,0x7E,0xFC,0x3F,0xCF,0xFF,0xF9,0xFF,0xDF,0x1F,0xF3,0xE0,0xF8,0x38, // 'd' - 0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xF8,0x7E,0x7C,0x07,0x9F,0x01,0xFF,0x80,0x7F,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x77,0xC0,0x3C,0xFC,0x3F,0x1F,0xFF,0x83,0xFF,0xC0,0x3F,0x80, // 'e' - 0x01,0xF8,0x0F,0xF8,0x1F,0xF8,0x7F,0xE0,0xF8,0x01,0xF0,0x03,0xE0,0x3F,0xF8,0x7F,0xF9,0xFF,0xF1,0xFF,0xC0,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x3E,0x00,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x0E,0x00, // 'f' - 0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0xBF,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x8F,0x80,0x01,0xF7,0x00,0x7E,0xF0,0x0F,0x9F,0x83,0xF3,0xFF,0xFC,0x1F,0xFF,0x00,0xFF,0x80, // 'g' - 0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE3,0xF0,0xF9,0xFF,0x3E,0xFF,0xEF,0xFF,0xFB,0xF8,0x3F,0xFC,0x0F,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xDC,0x00,0xE0, // 'h' - 0x77,0xFF,0xF7,0x00,0x0E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'i' - 0x03,0x81,0xF0,0x7C,0x1F,0x03,0x80,0x00,0x00,0x0E,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFB,0xFE,0x7E,0x00, // 'j' - 0x70,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x1C,0xF8,0x1E,0x7C,0x1F,0x3E,0x1F,0x9F,0x1F,0x8F,0x9F,0x07,0xDF,0x03,0xFF,0x81,0xFF,0xE0,0xFF,0xF0,0x7F,0x7C,0x3F,0x1F,0x1F,0x0F,0x8F,0x83,0xE7,0xC1,0xFB,0xE0,0x7D,0xF0,0x1F,0xF8,0x0F,0xB8,0x03,0x80, // 'k' - 0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'l' - 0x70,0xFC,0x0F,0x8F,0x3F,0xE3,0xFC,0xFF,0xFF,0x7F,0xEF,0xFF,0xFF,0xFE,0xFE,0x1F,0xE3,0xFF,0xC0,0xFC,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0x70,0x07,0x00,0xE0, // 'm' - 0x70,0xFC,0x3C,0x7F,0xCF,0xBF,0xFB,0xFF,0xFE,0xFE,0x0F,0xFF,0x03,0xFF,0xC0,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x00,0x38, // 'n' - 0x01,0xF8,0x00,0xFF,0xF0,0x1F,0xFF,0x83,0xFF,0xFC,0x7F,0x0F,0xE7,0xC0,0x3E,0xFC,0x03,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xF7,0xC0,0x3E,0x7F,0x0F,0xE3,0xFF,0xFC,0x1F,0xFF,0x80,0xFF,0xF0,0x01,0xF8,0x00, // 'o' - 0x70,0xFC,0x1F,0x3F,0xE3,0xEF,0xFE,0x7F,0xFF,0xCF,0xF0,0xFD,0xF8,0x0F,0xBF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7F,0xF8,0x0F,0xBF,0xC3,0xF7,0xFF,0xFC,0xFB,0xFF,0x9F,0x3F,0xE3,0xE3,0xF0,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'p' - 0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0x9F,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x38, // 'q' - 0x71,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xE1,0x7E,0x03,0xF0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x1C,0x00, // 'r' - 0x0F,0xF0,0x1F,0xFE,0x1F,0xFF,0x8F,0x87,0xEF,0x81,0xF7,0xC0,0x7B,0xF0,0x00,0xFF,0x80,0x3F,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x0F,0xF6,0x01,0xFF,0x80,0x7F,0xE0,0x3F,0xF8,0x3E,0x7F,0xFF,0x1F,0xFF,0x03,0xFC,0x00, // 's' - 0x0E,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x0F,0xFC,0xFF,0xF7,0xFF,0x9F,0xF8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7F,0xE3,0xFF,0x0F,0xF8,0x3F,0x80, // 't' - 0x70,0x03,0xBE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFF,0x03,0xFF,0xE3,0xFD,0xFF,0xFF,0x7F,0xF7,0xCF,0xF8,0xF0,0xF8,0x38, // 'u' - 0x70,0x03,0xBC,0x00,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x07,0x9F,0x03,0xE3,0xC0,0xF0,0xF8,0x7C,0x3E,0x1E,0x07,0x87,0x81,0xF3,0xE0,0x3C,0xF0,0x0F,0x3C,0x01,0xFE,0x00,0x7F,0x80,0x1F,0xE0,0x03,0xF0,0x00,0xFC,0x00,0x1E,0x00, // 'v' - 0x70,0x0F,0x00,0xEF,0x00,0xF0,0x0F,0xF8,0x1F,0x81,0xFF,0x81,0xF8,0x1F,0x78,0x1F,0x81,0xE7,0x83,0xFC,0x1E,0x7C,0x3F,0xC3,0xE3,0xC3,0xFC,0x3C,0x3C,0x79,0xE3,0xC3,0xE7,0x9E,0x7C,0x1E,0x79,0xE7,0x81,0xE7,0x0E,0x78,0x0E,0xF0,0xF7,0x00,0xFF,0x0F,0xF0,0x0F,0xE0,0x7F,0x00,0x7E,0x07,0xE0,0x07,0xE0,0x7E,0x00,0x7C,0x03,0xE0,0x03,0xC0,0x3C,0x00, // 'w' - 0x70,0x07,0x3C,0x07,0xBF,0x07,0xEF,0xC7,0xE3,0xE3,0xE0,0xFB,0xE0,0x7F,0xE0,0x1F,0xF0,0x07,0xF0,0x03,0xF8,0x03,0xFE,0x01,0xFF,0x01,0xF7,0xC1,0xF1,0xF1,0xF8,0xFC,0xF8,0x3E,0xF8,0x0F,0xFC,0x07,0xDC,0x01,0xC0, // 'x' - 0x38,0x01,0xCF,0x80,0x3D,0xF0,0x0F,0xBE,0x01,0xF3,0xE0,0x3C,0x7C,0x0F,0x87,0x81,0xE0,0xF8,0x7C,0x1F,0x0F,0x81,0xE1,0xE0,0x3E,0x7C,0x03,0xCF,0x00,0x7D,0xE0,0x07,0xFC,0x00,0xFF,0x00,0x1F,0xE0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x07,0xC0,0x1F,0xF8,0x07,0xFE,0x00,0x7F,0xC0,0x07,0xE0,0x00, // 'y' - 0x7F,0xFF,0x1F,0xFF,0xE7,0xFF,0xF9,0xFF,0xFE,0x00,0x3F,0x00,0x1F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF8, // 'z' - 0x01,0xF0,0x1F,0xC1,0xFE,0x1F,0xE0,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x0F,0x81,0xFC,0x1F,0xC0,0xF8,0x07,0xF0,0x1F,0xC0,0x3E,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x07,0xF8,0x1F,0xE0,0x7F,0x01,0xF0, // '{' - 0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60, // '|' - 0x7C,0x07,0xF0,0x3F,0xC0,0xFF,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x03,0xE0,0x1F,0xC0,0x7F,0x00,0xF8,0x1F,0xC1,0xFC,0x0F,0x80,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x3F,0xC3,0xFC,0x1F,0xC0,0x7C,0x00 // '}' -}; -const GFXglyph ArialRoundedMTBold_36Glyphs[] PROGMEM = { -// bitmapOffset, width, height, xAdvance, xOffset, yOffset - { 0, 1, 1, 10, 0, 0 }, // ' ' - { 1, 5, 26, 13, 4, -26 }, // '!' - { 18, 14, 9, 18, 2, -26 }, // '"' - { 34, 19, 26, 21, 0, -26 }, // '#' - { 96, 19, 37, 22, 1, -30 }, // '$' - { 184, 29, 27, 32, 1, -26 }, // '%' - { 282, 25, 26, 28, 2, -26 }, // '&' - { 364, 6, 9, 10, 1, -26 }, // ''' - { 371, 9, 33, 14, 2, -26 }, // '(' - { 409, 9, 33, 14, 2, -26 }, // ')' - { 447, 15, 14, 17, 0, -28 }, // '*' - { 474, 19, 18, 22, 1, -22 }, // '+' - { 517, 6, 11, 12, 3, -5 }, // ',' - { 526, 11, 4, 13, 1, -11 }, // '-' - { 532, 5, 5, 12, 3, -5 }, // '.' - { 536, 9, 26, 11, 1, -26 }, // '/' - { 566, 18, 26, 22, 2, -26 }, // '0' - { 625, 13, 26, 22, 2, -26 }, // '1' - { 668, 18, 26, 22, 2, -26 }, // '2' - { 727, 18, 26, 22, 2, -26 }, // '3' - { 786, 21, 26, 22, 0, -26 }, // '4' - { 855, 18, 26, 22, 2, -26 }, // '5' - { 914, 18, 26, 22, 2, -26 }, // '6' - { 973, 18, 26, 22, 3, -26 }, // '7' - { 1032, 19, 26, 22, 1, -26 }, // '8' - { 1094, 18, 26, 22, 1, -26 }, // '9' - { 1153, 5, 19, 12, 3, -19 }, // ':' - { 1165, 5, 25, 12, 3, -19 }, // ';' - { 1181, 18, 20, 22, 1, -23 }, // '<' - { 1226, 18, 13, 22, 2, -19 }, // '=' - { 1256, 18, 20, 22, 1, -23 }, // '>' - { 1301, 18, 26, 22, 1, -26 }, // '?' - { 1360, 34, 33, 36, 1, -26 }, // '@' - { 1501, 24, 26, 27, 1, -26 }, // 'A' - { 1579, 21, 26, 27, 3, -26 }, // 'B' - { 1648, 23, 26, 28, 2, -26 }, // 'C' - { 1723, 22, 26, 28, 3, -26 }, // 'D' - { 1795, 20, 26, 25, 3, -26 }, // 'E' - { 1860, 18, 26, 23, 3, -26 }, // 'F' - { 1919, 24, 26, 30, 2, -26 }, // 'G' - { 1997, 21, 26, 28, 3, -26 }, // 'H' - { 2066, 5, 26, 12, 3, -26 }, // 'I' - { 2083, 17, 26, 22, 1, -26 }, // 'J' - { 2139, 22, 26, 28, 3, -26 }, // 'K' - { 2211, 18, 26, 23, 3, -26 }, // 'L' - { 2270, 25, 26, 31, 3, -26 }, // 'M' - { 2352, 22, 26, 28, 3, -26 }, // 'N' - { 2424, 25, 26, 30, 2, -26 }, // 'O' - { 2506, 19, 26, 25, 3, -26 }, // 'P' - { 2568, 26, 28, 30, 2, -26 }, // 'Q' - { 2659, 21, 26, 27, 3, -26 }, // 'R' - { 2728, 20, 26, 25, 2, -26 }, // 'S' - { 2793, 21, 26, 24, 1, -26 }, // 'T' - { 2862, 21, 26, 28, 3, -26 }, // 'U' - { 2931, 23, 26, 26, 1, -26 }, // 'V' - { 3006, 32, 26, 35, 1, -26 }, // 'W' - { 3110, 21, 26, 23, 0, -26 }, // 'X' - { 3179, 21, 26, 24, 1, -26 }, // 'Y' - { 3248, 23, 26, 24, 0, -26 }, // 'Z' - { 3323, 10, 33, 14, 2, -26 }, // '[' - { 3365, 10, 26, 11, 0, -26 }, // '\' - { 3398, 10, 33, 14, 0, -26 }, // ']' - { 3440, 17, 14, 22, 2, -26 }, // '^' - { 3470, 18, 2, 19, 0, 3 }, // '_' - { 3475, 8, 5, 10, 0, -26 }, // '`' Changed to degree symbol - { 3480, 19, 19, 22, 1, -19 }, // 'a' - { 3526, 19, 26, 24, 2, -26 }, // 'b' - { 3588, 18, 19, 22, 1, -19 }, // 'c' - { 3631, 19, 26, 24, 1, -26 }, // 'd' - { 3693, 18, 19, 22, 2, -19 }, // 'e' - { 3736, 15, 26, 13, -1, -26 }, // 'f' - { 3785, 19, 26, 24, 1, -19 }, // 'g' - { 3847, 18, 26, 23, 2, -26 }, // 'h' - { 3906, 5, 26, 11, 2, -26 }, // 'i' - { 3923, 10, 33, 11, -3, -26 }, // 'j' - { 3965, 17, 26, 22, 3, -26 }, // 'k' - { 4021, 5, 26, 11, 2, -26 }, // 'l' - { 4038, 28, 19, 33, 2, -19 }, // 'm' - { 4105, 18, 19, 23, 2, -19 }, // 'n' - { 4148, 20, 19, 23, 1, -19 }, // 'o' - { 4196, 19, 26, 24, 2, -19 }, // 'p' - { 4258, 19, 26, 24, 1, -19 }, // 'q' - { 4320, 13, 19, 17, 2, -19 }, // 'r' - { 4351, 17, 19, 21, 1, -19 }, // 's' - { 4392, 13, 26, 14, 0, -26 }, // 't' - { 4435, 18, 19, 23, 2, -19 }, // 'u' - { 4478, 18, 19, 21, 1, -19 }, // 'v' - { 4521, 28, 19, 30, 1, -19 }, // 'w' - { 4588, 17, 19, 20, 1, -19 }, // 'x' - { 4629, 19, 26, 21, 0, -19 }, // 'y' - { 4691, 18, 19, 20, 1, -19 }, // 'z' - { 4734, 13, 33, 15, 1, -26 }, // '{' - { 4788, 4, 33, 11, 3, -26 }, // '|' - { 4805, 13, 33, 15, 0, -26 } // '}' character 0x7D -}; -const GFXfont ArialRoundedMTBold_36 PROGMEM = { // Last character bug fixed 0x7E to 0x7D -(uint8_t *)ArialRoundedMTBold_36Bitmaps,(GFXglyph *)ArialRoundedMTBold_36Glyphs,0x20, 0x7D, 43}; - diff --git a/examples/320 x 240/weather-station-v8/ArialRoundedMtBold_14.h b/examples/320 x 240/weather-station-v8/ArialRoundedMtBold_14.h deleted file mode 100644 index b08d84f..0000000 --- a/examples/320 x 240/weather-station-v8/ArialRoundedMtBold_14.h +++ /dev/null @@ -1,224 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -// Created by http://oleddisplay.squix.ch/ Consider a donation -// In case of problems make sure that you are using the font file with the correct version! - -// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected -// this avoids screen corruption if ~ is printer - -const uint8_t ArialRoundedMTBold_14Bitmaps[] PROGMEM = { - - // Bitmap Data: - 0x00, // ' ' - 0xFF,0xF8,0xF0, // '!' - 0xDE,0xF6, // '"' - 0x12,0x32,0x36,0xFF,0xFF,0x24,0xFF,0xFF,0x4C,0x48, // '#' - 0x10,0x61,0xF6,0xAD,0x7A,0x1E,0x0E,0xD7,0xAF,0x5B,0xE1,0x02,0x04,0x00, // '$' - 0x60,0x92,0x22,0x44,0x49,0x07,0x60,0x0B,0x82,0x48,0xC9,0x11,0x24,0x18, // '%' - 0x3C,0x19,0x82,0x60,0xF0,0x39,0x33,0x6C,0x73,0x1C,0xFF,0x8E,0x30, // '&' - 0xFC, // ''' - 0x32,0x64,0xCC,0xCC,0xC4,0x62,0x30, // '(' - 0xC4,0x62,0x33,0x33,0x32,0x64,0xC0, // ')' - 0x21,0x2A,0xE5,0x28, // '*' - 0x18,0x18,0x18,0xFF,0xFF,0x18,0x18, // '+' - 0xF6, // ',' - 0xFF, // '-' - 0xF0, // '.' - 0x33,0x32,0x66,0x4C,0xCC, // '/' - 0x38,0xFB,0x9E,0x3C,0x78,0xF1,0xF6,0x7C,0x70, // '0' - 0x19,0xDF,0xB1,0x8C,0x63,0x18,0xC0, // '1' - 0x38,0xFF,0x1E,0x30,0xC3,0x0C,0x30,0xFF,0xFC, // '2' - 0x79,0x9B,0x10,0x63,0xC7,0x81,0xC3,0xC6,0xF0, // '3' - 0x06,0x0E,0x1E,0x16,0x26,0x46,0xFF,0xFF,0x06,0x06, // '4' - 0x7E,0xFD,0x06,0x0F,0xD8,0xC1,0xC3,0xCC,0xF0, // '5' - 0x38,0xDB,0x1E,0x0F,0xD8,0xF1,0xE3,0x66,0x78, // '6' - 0xFF,0xFC,0x30,0x41,0x82,0x0C,0x18,0x30,0xC0, // '7' - 0x38,0xDB,0x1F,0x63,0x98,0xF1,0xE3,0xC6,0xF8, // '8' - 0x3C,0x66,0xC3,0xC3,0xE7,0x3F,0x03,0xC3,0x66,0x3C, // '9' - 0xF0,0x3C, // ':' - 0xF0,0x3D,0x80, // ';' - 0x02,0x1D,0xF7,0x0E,0x0F,0x83,0x81, // '<' - 0xFF,0xFC,0x07,0xFF,0xE0, // '=' - 0x81,0xC1,0xF0,0x70,0xEF,0xB8,0x40, // '>' - 0x3C,0xFF,0x1E,0x30,0xC7,0x0C,0x00,0x30,0x60, // '?' - 0x0F,0x83,0x06,0x60,0x24,0xED,0x99,0x9B,0x19,0xB1,0xBB,0x12,0xBF,0xE4,0xDC,0x40,0x13,0x06,0x0F,0xC0, // '@' - 0x1C,0x0E,0x05,0x06,0xC3,0x63,0x19,0xFC,0xFE,0xC1,0xE0,0xC0, // 'A' - 0xFC,0xFE,0xC7,0xC6,0xFE,0xFE,0xC3,0xC3,0xFF,0xFE, // 'B' - 0x3E,0x3F,0xB8,0xF8,0x3C,0x06,0x03,0x06,0xC7,0x7F,0x0F,0x00, // 'C' - 0xFE,0x7F,0xB0,0xF8,0x3C,0x1E,0x0F,0x07,0x87,0xFF,0x7F,0x00, // 'D' - 0xFE,0xFF,0xC0,0xC0,0xFE,0xFE,0xC0,0xC0,0xFF,0xFF, // 'E' - 0xFF,0xFF,0x06,0x0F,0xDF,0xB0,0x60,0xC1,0x80, // 'F' - 0x1E,0x3F,0x98,0xF8,0x2C,0x06,0x3F,0x1E,0xC3,0x7F,0x9F,0x00, // 'G' - 0xC1,0xE0,0xF0,0x78,0x3F,0xFF,0xFF,0x07,0x83,0xC1,0xE0,0xC0, // 'H' - 0xFF,0xFF,0xF0, // 'I' - 0x06,0x0C,0x18,0x30,0x60,0xF1,0xF3,0x7E,0x78, // 'J' - 0xC3,0x63,0xB3,0x9B,0x8F,0x87,0x63,0x19,0x8E,0xC3,0x60,0xC0, // 'K' - 0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xFF,0xFC, // 'L' - 0xE1,0xFC,0xFF,0x3F,0xCF,0xD2,0xF7,0xBD,0xEF,0x7B,0xCC,0xF3,0x30, // 'M' - 0xC1,0xF0,0xFC,0x7E,0x3D,0x9E,0x6F,0x3F,0x8F,0xC3,0xE0,0xC0, // 'N' - 0x1E,0x1F,0xE6,0x1B,0x03,0xC0,0xF0,0x3C,0x0D,0x86,0x7F,0x87,0x80, // 'O' - 0xFE,0xFF,0xC3,0xC3,0xFF,0xFE,0xC0,0xC0,0xC0,0xC0, // 'P' - 0x1E,0x0F,0xF1,0x87,0x60,0x6C,0x0D,0x81,0xB1,0x33,0x7C,0x7F,0x83,0xD8,0x01,0x80, // 'Q' - 0xFE,0xFF,0xC3,0xC3,0xFE,0xFC,0xCE,0xC6,0xC3,0xC3, // 'R' - 0x7C,0xFE,0xC7,0xC2,0x7C,0x0F,0xC3,0xC3,0x7E,0x3C, // 'S' - 0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 'T' - 0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x0F,0x07,0xC7,0x7F,0x1F,0x00, // 'U' - 0xC1,0xE0,0xD8,0xCC,0x66,0x31,0xB0,0xD8,0x6C,0x1C,0x0E,0x00, // 'V' - 0xC7,0x1E,0x38,0xF1,0x46,0xDB,0x66,0xDB,0x36,0xD9,0xA2,0xC7,0x1C,0x38,0xE1,0x83,0x00, // 'W' - 0xC3,0x66,0x7E,0x3C,0x18,0x3C,0x7E,0x66,0xC3,0xC3, // 'X' - 0xC3,0xC3,0x66,0x3E,0x3C,0x18,0x18,0x18,0x18,0x18, // 'Y' - 0x7F,0x3F,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0, // 'Z' - 0xFF,0xCC,0xCC,0xCC,0xCC,0xCF,0xF0, // '[' - 0xCC,0x44,0x66,0x22,0x33, // '\' - 0xFF,0x33,0x33,0x33,0x33,0x3F,0xF0, // ']' - 0x30,0xE7,0x9A,0xCF,0x30, // '^' - 0xFE, // '_' - 0xD0, // '`' - 0x7D,0x8C,0x7F,0x3C,0x79,0xDD,0x80, // 'a' - 0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xFF,0xB8, // 'b' - 0x3C,0xFF,0x1E,0x0C,0x6F,0xCF,0x00, // 'c' - 0x06,0x0C,0x1B,0xBF,0xF8,0xF1,0xE3,0xFE,0xEC, // 'd' - 0x3C,0xCF,0x1F,0xFC,0x0C,0xCF,0x00, // 'e' - 0x3B,0x19,0xF6,0x31,0x8C,0x63,0x00, // 'f' - 0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0xE3,0xC6,0xF8, // 'g' - 0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xC7,0x8C, // 'h' - 0xF3,0xFF,0xF0, // 'i' - 0x33,0x03,0x33,0x33,0x33,0x3F,0xE0, // 'j' - 0xC1,0x83,0x06,0x6D,0x9E,0x3E,0x66,0xCD,0x8C, // 'k' - 0xFF,0xFF,0xF0, // 'l' - 0xD9,0xDF,0xFF,0x31,0xE6,0x3C,0xC7,0x98,0xF3,0x18, // 'm' - 0xDD,0xFF,0x1E,0x3C,0x78,0xF1,0x80, // 'n' - 0x38,0xFB,0x1E,0x3C,0x6F,0x8E,0x00, // 'o' - 0xDD,0xFF,0x1E,0x3C,0x7F,0xF7,0x60,0xC1,0x80, // 'p' - 0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0x83,0x06,0x0C, // 'q' - 0xDF,0xF1,0x8C,0x63,0x00, // 'r' - 0x7B,0x3E,0x1E,0x0F,0x37,0x80, // 's' - 0x63,0x19,0xF6,0x31,0x8C,0x79,0xC0, // 't' - 0xC7,0x8F,0x1E,0x3C,0x7F,0xDD,0x80, // 'u' - 0xC7,0x8D,0x93,0x62,0x87,0x04,0x00, // 'v' - 0xC4,0x79,0xCD,0x29,0x35,0x67,0xBC,0x63,0x0C,0x60, // 'w' - 0xC6,0xD9,0xF1,0xC7,0xCD,0xB1,0x80, // 'x' - 0xC7,0x8D,0x93,0x62,0xC7,0x06,0x18,0xF1,0xC0, // 'y' - 0xFE,0x18,0x61,0x86,0x1F,0xFF,0x80, // 'z' - 0x19,0xCC,0x63,0x3B,0x8E,0x31,0x8C,0x71,0x80, // '{' - 0xFF,0xFF,0xFF,0xC0, // '|' - 0xC7,0x18,0xC6,0x38,0xEE,0x63,0x19,0xCC,0x00 // '}' -}; -const GFXglyph ArialRoundedMTBold_14Glyphs[] PROGMEM = { -// bitmapOffset, width, height, xAdvance, xOffset, yOffset - { 0, 1, 1, 5, 0, 0 }, // ' ' - { 1, 2, 10, 6, 1, -10 }, // '!' - { 4, 5, 3, 8, 1, -10 }, // '"' - { 6, 8, 10, 9, 0, -10 }, // '#' - { 16, 7, 15, 9, 1, -12 }, // '$' - { 30, 11, 10, 13, 0, -10 }, // '%' - { 44, 10, 10, 12, 1, -10 }, // '&' - { 57, 2, 3, 4, 1, -10 }, // ''' - { 58, 4, 13, 6, 1, -10 }, // '(' - { 65, 4, 13, 6, 0, -10 }, // ')' - { 72, 5, 6, 7, 1, -11 }, // '*' - { 76, 8, 7, 9, 0, -9 }, // '+' - { 83, 2, 4, 5, 1, -2 }, // ',' - { 84, 4, 2, 6, 0, -5 }, // '-' - { 85, 2, 2, 5, 1, -2 }, // '.' - { 86, 4, 10, 5, 0, -10 }, // '/' - { 91, 7, 10, 9, 1, -10 }, // '0' - { 100, 5, 10, 9, 1, -10 }, // '1' - { 107, 7, 10, 9, 1, -10 }, // '2' - { 116, 7, 10, 9, 1, -10 }, // '3' - { 125, 8, 10, 9, 0, -10 }, // '4' - { 135, 7, 10, 9, 1, -10 }, // '5' - { 144, 7, 10, 9, 1, -10 }, // '6' - { 153, 7, 10, 9, 1, -10 }, // '7' - { 162, 7, 10, 9, 1, -10 }, // '8' - { 171, 8, 10, 9, 0, -10 }, // '9' - { 181, 2, 7, 5, 1, -7 }, // ':' - { 183, 2, 9, 5, 1, -7 }, // ';' - { 186, 7, 8, 9, 1, -9 }, // '<' - { 193, 7, 5, 9, 1, -7 }, // '=' - { 198, 7, 8, 9, 1, -9 }, // '>' - { 205, 7, 10, 9, 1, -10 }, // '?' - { 214, 12, 13, 15, 1, -10 }, // '@' - { 234, 9, 10, 11, 1, -10 }, // 'A' - { 246, 8, 10, 11, 1, -10 }, // 'B' - { 256, 9, 10, 11, 1, -10 }, // 'C' - { 268, 9, 10, 11, 1, -10 }, // 'D' - { 280, 8, 10, 10, 1, -10 }, // 'E' - { 290, 7, 10, 9, 1, -10 }, // 'F' - { 299, 9, 10, 12, 1, -10 }, // 'G' - { 311, 9, 10, 12, 1, -10 }, // 'H' - { 323, 2, 10, 5, 1, -10 }, // 'I' - { 326, 7, 10, 9, 0, -10 }, // 'J' - { 335, 9, 10, 11, 1, -10 }, // 'K' - { 347, 7, 10, 9, 1, -10 }, // 'L' - { 356, 10, 10, 13, 1, -10 }, // 'M' - { 369, 9, 10, 12, 1, -10 }, // 'N' - { 381, 10, 10, 12, 1, -10 }, // 'O' - { 394, 8, 10, 10, 1, -10 }, // 'P' - { 404, 11, 11, 12, 1, -10 }, // 'Q' - { 420, 8, 10, 11, 1, -10 }, // 'R' - { 430, 8, 10, 10, 1, -10 }, // 'S' - { 440, 8, 10, 10, 0, -10 }, // 'T' - { 450, 9, 10, 12, 1, -10 }, // 'U' - { 462, 9, 10, 11, 0, -10 }, // 'V' - { 474, 13, 10, 14, 0, -10 }, // 'W' - { 491, 8, 10, 9, 0, -10 }, // 'X' - { 501, 8, 10, 10, 0, -10 }, // 'Y' - { 511, 9, 10, 10, 0, -10 }, // 'Z' - { 523, 4, 13, 6, 1, -10 }, // '[' - { 530, 4, 10, 5, 0, -10 }, // '\' - { 535, 4, 13, 6, 0, -10 }, // ']' - { 542, 6, 6, 9, 1, -10 }, // '^' - { 547, 7, 1, 8, 0, 1 }, // '_' - { 548, 2, 2, 6, 1, -10 }, // '`' - { 549, 7, 7, 9, 1, -7 }, // 'a' - { 556, 7, 10, 10, 1, -10 }, // 'b' - { 565, 7, 7, 9, 1, -7 }, // 'c' - { 572, 7, 10, 10, 1, -10 }, // 'd' - { 581, 7, 7, 9, 1, -7 }, // 'e' - { 588, 5, 10, 6, 0, -10 }, // 'f' - { 595, 7, 10, 10, 1, -7 }, // 'g' - { 604, 7, 10, 9, 1, -10 }, // 'h' - { 613, 2, 10, 5, 1, -10 }, // 'i' - { 616, 4, 13, 5, -1, -10 }, // 'j' - { 623, 7, 10, 9, 1, -10 }, // 'k' - { 632, 2, 10, 5, 1, -10 }, // 'l' - { 635, 11, 7, 13, 1, -7 }, // 'm' - { 645, 7, 7, 9, 1, -7 }, // 'n' - { 652, 7, 7, 9, 1, -7 }, // 'o' - { 659, 7, 10, 10, 1, -7 }, // 'p' - { 668, 7, 10, 10, 1, -7 }, // 'q' - { 677, 5, 7, 7, 1, -7 }, // 'r' - { 682, 6, 7, 9, 1, -7 }, // 's' - { 688, 5, 10, 6, 0, -10 }, // 't' - { 695, 7, 7, 9, 1, -7 }, // 'u' - { 702, 7, 7, 9, 0, -7 }, // 'v' - { 709, 11, 7, 12, 0, -7 }, // 'w' - { 719, 7, 7, 8, 0, -7 }, // 'x' - { 726, 7, 10, 9, 0, -7 }, // 'y' - { 735, 7, 7, 8, 0, -7 }, // 'z' - { 742, 5, 13, 6, 0, -10 }, // '{' - { 751, 2, 13, 5, 1, -10 }, // '|' - { 755, 5, 13, 6, 1, -10 } // '}' character 0x7D -}; -const GFXfont ArialRoundedMTBold_14 PROGMEM = { // Last character bug fixed 0x7E to 0x7D -(uint8_t *)ArialRoundedMTBold_14Bitmaps,(GFXglyph *)ArialRoundedMTBold_14Glyphs,0x20, 0x7D, 17}; - diff --git a/examples/320 x 240/weather-station-v8/GfxUi.cpp b/examples/320 x 240/weather-station-v8/GfxUi.cpp deleted file mode 100644 index 4716da0..0000000 --- a/examples/320 x 240/weather-station-v8/GfxUi.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_eSPI library: -https://github.com/Bodmer/TFT_eSPI - -Bodmer: Functions no longer needed weeded out, Jpeg decoder functions added -Bodmer: drawBMP() updated to buffer in and out pixels and use screen CGRAM rotation for faster bottom up drawing (now ~2x faster) -*/ - -#include "GfxUi.h" - -GfxUi::GfxUi(TFT_eSPI *tft) { - _tft = tft; -} - -void GfxUi::drawProgressBar(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor) { - if (percentage == 0) { - _tft->fillRoundRect(x0, y0, w, h, 3, TFT_BLACK); - } - uint8_t margin = 2; - uint16_t barHeight = h - 2 * margin; - uint16_t barWidth = w - 2 * margin; - _tft->drawRoundRect(x0, y0, w, h, 3, frameColor); - _tft->fillRect(x0 + margin, y0 + margin, barWidth * percentage / 100.0, barHeight, barColor); -} - -// This drawBMP function contains code from: -// https://github.com/adafruit/Adafruit_ILI9341/blob/master/examples/spitftbitmap/spitftbitmap.ino -// Here is Bodmer's version: this uses the ILI9341 CGRAM coordinate rotation features inside the display and -// buffers both file and TFT pixel blocks, it typically runs about 2x faster for bottom up encoded BMP images - -//void GfxUi::drawBMP(String filename, uint8_t x, uint16_t y, boolean flip) { // Alernative for caller control of flip -void GfxUi::drawBmp(String filename, uint8_t x, uint16_t y) { - // Flips the TFT internal SGRAM coords to draw bottom up BMP images faster, in this application it can be fixed - boolean flip = 1; - - if ((x >= _tft->width()) || (y >= _tft->height())) return; - - fs::File bmpFile; - int16_t bmpWidth, bmpHeight; // Image W+H in pixels - uint32_t bmpImageoffset; // Start address of image data in file - uint32_t rowSize; // Not always = bmpWidth; may have padding - uint8_t sdbuffer[3 * BUFFPIXEL]; // file read pixel buffer (8 bits each R+G+B per pixel) - uint16_t tftbuffer[BUFFPIXEL]; // TFT pixel out buffer (16-bit per pixel) - uint8_t rgb_ptr = sizeof(sdbuffer); // read 24 bit RGB pixel data buffer pointer (8 bit so BUFF_SIZE must be less than 86) - boolean goodBmp = false; // Flag set to true on valid header parse - int16_t w, h, row, col; // to store width, height, row and column - uint8_t rotation; // to restore rotation - uint8_t tft_ptr = 0; // TFT 16 bit 565 format pixel data buffer pointer - - // Check file exists and open it - Serial.println(filename); - if ( !(bmpFile = SPIFFS.open(filename, "r")) ) { - Serial.println(F(" File not found")); // Can comment out if not needed - return; - } - - // Parse BMP header to get the information we need - if (read16(bmpFile) == 0x4D42) { // BMP file start signature check - read32(bmpFile); // Dummy read to throw away and move on - read32(bmpFile); // Read & ignore creator bytes - bmpImageoffset = read32(bmpFile); // Start of image data - read32(bmpFile); // Dummy read to throw away and move on - bmpWidth = read32(bmpFile); // Image width - bmpHeight = read32(bmpFile); // Image height - - // Only proceed if we pass a bitmap file check - // Number of image planes -- must be '1', depth 24 and 0 (uncompressed format) - if ((read16(bmpFile) == 1) && (read16(bmpFile) == 24) && (read32(bmpFile) == 0)) { - goodBmp = true; // Supported BMP format - // BMP rows are padded (if needed) to 4-byte boundary - rowSize = (bmpWidth * 3 + 3) & ~3; - // Crop area to be loaded - w = bmpWidth; - h = bmpHeight; - - // We might need to alter rotation to avoid tedious file pointer manipulation - // Save the current value so we can restore it later - rotation = _tft->getRotation(); - // Use TFT SGRAM coord rotation if flip is set for 25% faster rendering (new rotations 4-7 supported by library) - if (flip) _tft->setRotation((rotation + (flip<<2)) % 8); // Value 0-3 mapped to 4-7 - - // Calculate new y plot coordinate if we are flipping - switch (rotation) { - case 0: - if (flip) y = _tft->height() - y - h; break; - case 1: - y = _tft->height() - y - h; break; - break; - case 2: - if (flip) y = _tft->height() - y - h; break; - break; - case 3: - y = _tft->height() - y - h; break; - break; - } - - // Set TFT address window to image bounds - // Currently, image will not draw or will be corrputed if it does not fit - // TODO -> efficient clipping, but I don't need it to be idiot proof ;-) - _tft->setAddrWindow(x, y, x + w - 1, y + h - 1); - - // Finally we are ready to send rows of pixels, writing like this avoids slow 32 bit multiply in 8 bit processors - for (uint32_t pos = bmpImageoffset; pos < bmpImageoffset + h * rowSize ; pos += rowSize) { - // Seek if we need to on boundaries and arrange to dump buffer and start again - if (bmpFile.position() != pos) { - bmpFile.seek(pos, fs::SeekSet); - rgb_ptr = sizeof(sdbuffer); - //Serial.println("Seeking in file >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); - } - - // Fill the pixel buffer and plot - for (col = 0; col < w; col++) { // For each column... - // Time to read more pixel data? - if (rgb_ptr >= sizeof(sdbuffer)) { - // Push tft buffer to the display - if (tft_ptr) { - // Here we are sending a uint16_t array to the function - _tft->pushColors(tftbuffer, tft_ptr); - tft_ptr = 0; // tft_ptr and rgb_ptr are not always in sync... - } - // Finally reading bytes from SD Card - bmpFile.read(sdbuffer, sizeof(sdbuffer)); - rgb_ptr = 0; // Set buffer index to start - } - // Convert pixel from BMP 8+8+8 format to TFT compatible 16 bit word - // Blue 5 bits, green 6 bits and red 5 bits (16 bits total) - // Is is a long line but it is faster than calling a library fn for this - tftbuffer[tft_ptr] = (sdbuffer[rgb_ptr++] >> 3) ; - tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xFC) << 3); - tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xF8) << 8); - tft_ptr++; - } // Next row - } // All rows done - - // Write any partially full buffer to TFT - if (tft_ptr) _tft->pushColors(tftbuffer, tft_ptr); - - } // End of bitmap access - } // End of bitmap file check - - bmpFile.close(); - if(!goodBmp) Serial.println(F("BMP format not recognised.")); - _tft->setRotation(rotation); // Put back original rotation -} - -// These read 16- and 32-bit types from the SD card file. -// BMP data is stored little-endian, Arduino is little-endian too. -// May need to reverse subscript order if porting elsewhere. - -uint16_t GfxUi::read16(fs::File &f) { - uint16_t result; - ((uint8_t *)&result)[0] = f.read(); // LSB - ((uint8_t *)&result)[1] = f.read(); // MSB - return result; -} - -uint32_t GfxUi::read32(fs::File &f) { - uint32_t result; - ((uint8_t *)&result)[0] = f.read(); // LSB - ((uint8_t *)&result)[1] = f.read(); - ((uint8_t *)&result)[2] = f.read(); - ((uint8_t *)&result)[3] = f.read(); // MSB - return result; -} - -/*==================================================================================== - This sketch support functions to render the Jpeg images. - - Created by Bodmer 15th Jan 2017 - ==================================================================================*/ - -// Return the minimum of two values a and b -#define minimum(a,b) (((a) < (b)) ? (a) : (b)) - -#define USE_SPI_BUFFER // Comment out to use slower 16 bit pushColor() - -//==================================================================================== -// Opens the image file and prime the Jpeg decoder -//==================================================================================== -void GfxUi::drawJpeg(const char *filename, int xpos, int ypos) { - - Serial.println("==========================="); - Serial.print("Drawing file: "); Serial.println(filename); - Serial.println("==========================="); - - // Open the named file (the Jpeg decoder library will close it after rendering image) - fs::File jpegFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS - // File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library - - if ( !jpegFile ) { - Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); - return; - } - - // Use one of the three following methods to initialise the decoder: - //boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder, - //boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder, - boolean decoded = JpegDec.decodeFsFile(filename); // or pass the filename (leading / distinguishes SPIFFS files) - // Note: the filename can be a String or character array type - if (decoded) { - // print information about the image to the serial port - jpegInfo(); - - // render the image onto the screen at given coordinates - jpegRender(xpos, ypos); - } - else { - Serial.println("Jpeg file format not supported!"); - } -} - -//==================================================================================== -// Decode and render the Jpeg image onto the TFT screen -//==================================================================================== -void GfxUi::jpegRender(int xpos, int ypos) { - - // retrieve infomration about the image - uint16_t *pImg; - uint16_t mcu_w = JpegDec.MCUWidth; - uint16_t mcu_h = JpegDec.MCUHeight; - uint32_t max_x = JpegDec.width; - uint32_t max_y = JpegDec.height; - - // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) - // Typically these MCUs are 16x16 pixel blocks - // Determine the width and height of the right and bottom edge image blocks - uint32_t min_w = minimum(mcu_w, max_x % mcu_w); - uint32_t min_h = minimum(mcu_h, max_y % mcu_h); - - // save the current image block size - uint32_t win_w = mcu_w; - uint32_t win_h = mcu_h; - - // record the current time so we can measure how long it takes to draw an image - uint32_t drawTime = millis(); - - // save the coordinate of the right and bottom edges to assist image cropping - // to the screen size - max_x += xpos; - max_y += ypos; - - // read each MCU block until there are no more -#ifdef USE_SPI_BUFFER - while( JpegDec.readSwappedBytes()){ // Swap byte order so the SPI buffer can be used -#else - while ( JpegDec.read()) { // Normal byte order read -#endif - // save a pointer to the image block - pImg = JpegDec.pImage; - - // calculate where the image block should be drawn on the screen - int mcu_x = JpegDec.MCUx * mcu_w + xpos; - int mcu_y = JpegDec.MCUy * mcu_h + ypos; - - // check if the image block size needs to be changed for the right and bottom edges - if (mcu_x + mcu_w <= max_x) win_w = mcu_w; - else win_w = min_w; - if (mcu_y + mcu_h <= max_y) win_h = mcu_h; - else win_h = min_h; - - // calculate how many pixels must be drawn - uint32_t mcu_pixels = win_w * win_h; - - // draw image MCU block only if it will fit on the screen - if ( ( mcu_x + win_w) <= _tft->width() && ( mcu_y + win_h) <= _tft->height()) - { -#ifdef USE_SPI_BUFFER - // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1) - _tft->setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); - // Write all MCU pixels to the TFT window - uint8_t *pImg8 = (uint8_t*)pImg; // Convert 16 bit pointer to an 8 bit pointer - _tft->pushColors(pImg8, mcu_pixels*2); // Send bytes via 64 byte SPI port buffer -#else - // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1) - _tft->setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); - // Write all MCU pixels to the TFT window - while (mcu_pixels--) _tft->pushColor(*pImg++); -#endif - } - - else if ( ( mcu_y + win_h) >= _tft->height()) JpegDec.abort(); - - } - - // calculate how long it took to draw the image - drawTime = millis() - drawTime; // Calculate the time it took - - // print the results to the serial port - Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms"); - Serial.println("====================================="); - -} - -//==================================================================================== -// Print information decoded from the Jpeg image -//==================================================================================== -void GfxUi::jpegInfo() { - - Serial.println("==============="); - Serial.println("JPEG image info"); - Serial.println("==============="); - Serial.print ("Width :"); Serial.println(JpegDec.width); - Serial.print ("Height :"); Serial.println(JpegDec.height); - Serial.print ("Components :"); Serial.println(JpegDec.comps); - Serial.print ("MCU / row :"); Serial.println(JpegDec.MCUSPerRow); - Serial.print ("MCU / col :"); Serial.println(JpegDec.MCUSPerCol); - Serial.print ("Scan type :"); Serial.println(JpegDec.scanType); - Serial.print ("MCU width :"); Serial.println(JpegDec.MCUWidth); - Serial.print ("MCU height :"); Serial.println(JpegDec.MCUHeight); - Serial.println("==============="); - Serial.println(""); - -} -//==================================================================================== diff --git a/examples/320 x 240/weather-station-v8/GfxUi.h b/examples/320 x 240/weather-station-v8/GfxUi.h deleted file mode 100644 index f381129..0000000 --- a/examples/320 x 240/weather-station-v8/GfxUi.h +++ /dev/null @@ -1,60 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_eSPI library: -https://github.com/Bodmer/TFT_eSPI - -*/ - - -#include // Hardware-specific library - -#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition -#include - -// JPEG decoder library -#include - -#ifndef _GFX_UI_H -#define _GFX_UI_H - -// Maximum of 85 for BUFFPIXEL as 3 x this value is stored in an 8 bit variable! -// 32 is an efficient size for SPIFFS due to SPI hardware pipeline buffer size -// A larger value of 80 is better for SD cards -#define BUFFPIXEL 32 - -class GfxUi { - public: - GfxUi(TFT_eSPI * tft); - void drawBmp(String filename, uint8_t x, uint16_t y); - void drawProgressBar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor); - void jpegInfo(); - void drawJpeg(const char *filename, int xpos, int ypos); - void jpegRender(int xpos, int ypos); - - private: - TFT_eSPI * _tft; - uint16_t read16(fs::File &f); - uint32_t read32(fs::File &f); - -}; - -#endif - diff --git a/examples/320 x 240/weather-station-v8/WebResource.cpp b/examples/320 x 240/weather-station-v8/WebResource.cpp deleted file mode 100644 index 2020fd1..0000000 --- a/examples/320 x 240/weather-station-v8/WebResource.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -#include "WebResource.h" - -WebResource::WebResource(){ - -} - -void WebResource::downloadFile(String url, String filename) { - downloadFile(url, filename, nullptr); -} - -void WebResource::downloadFile(String url, String filename, ProgressCallback progressCallback) { - - if (SPIFFS.exists(filename) == true) { - Serial.println("Found " + filename); - return; - } - else Serial.println("Downloading " + filename + " from " + url); - - // wait for WiFi connection - if((_wifiMulti.run() == WL_CONNECTED)) { - HTTPClient http; - - Serial.print("[HTTP] begin...\n"); - - // configure server and url - http.begin(url); - - Serial.print("[HTTP] GET...\n"); - // start connection and send HTTP header - int httpCode = http.GET(); - if(httpCode > 0) { - //SPIFFS.remove(filename); - fs::File f = SPIFFS.open(filename, "w+"); - if (!f) { - Serial.println("file open failed"); - return; - } - // HTTP header has been send and Server response header has been handled - Serial.printf("[HTTP] GET... code: %d\n", httpCode); - - // file found at server - if(httpCode == HTTP_CODE_OK) { - - // get length of document (is -1 when Server sends no Content-Length header) - int total = http.getSize(); - int len = total; - progressCallback(filename, 0,total); - // create buffer for read - uint8_t buff[128] = { 0 }; - - // get tcp stream - WiFiClient * stream = http.getStreamPtr(); - - // read all data from server - while(http.connected() && (len > 0 || len == -1)) { - // get available data size - size_t size = stream->available(); - - if(size) { - // read up to 128 byte - int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); - - // write it to Serial - f.write(buff, c); - - if(len > 0) { - len -= c; - } - progressCallback(filename, total - len,total); - } - delay(1); - } - - Serial.println(); - Serial.print("[HTTP] connection closed or file end.\n"); - - } - f.close(); - } else { - Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); - } - - http.end(); - } -} diff --git a/examples/320 x 240/weather-station-v8/WebResource.h b/examples/320 x 240/weather-station-v8/WebResource.h deleted file mode 100644 index acff084..0000000 --- a/examples/320 x 240/weather-station-v8/WebResource.h +++ /dev/null @@ -1,46 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch -*/ - -#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition -#include -#include -#include -#include -#include - -#ifndef _WEBRESOURCE_H -#define _WEBRESOURCE_H - -typedef void (*ProgressCallback)(String fileName, int16_t bytesDownloaded, int16_t bytesTotal); - -class WebResource { - public: - WebResource(); - void downloadFile(String url, String filename, ProgressCallback progressCallback); - void downloadFile(String url, String filename); - - - private: - ESP8266WiFiMulti _wifiMulti; - -}; - -#endif - diff --git a/examples/320 x 240/weather-station-v8/settings.h b/examples/320 x 240/weather-station-v8/settings.h deleted file mode 100644 index 4a4618c..0000000 --- a/examples/320 x 240/weather-station-v8/settings.h +++ /dev/null @@ -1,64 +0,0 @@ -/**The MIT License (MIT) -Copyright (c) 2015 by Daniel Eichhorn -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -See more at http://blog.squix.ch - -Adapted by Bodmer to use the faster TFT_ILI9341_ESP library: -https://github.com/Bodmer/TFT_ILI9341_ESP - -*/ - -// Setup -const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes - -// Pins for the TFT interface are defined in the User_Config.h file inside the TFT_ILI9341_ESP library - -// TimeClient settings -const float UTC_OFFSET = 1; - -// Wunderground Settings, EDIT TO SUIT YOUR LOCATION -const boolean IS_METRIC = true; // Temperature only? Wind speed units appear to stay in mph. To do: investigate <<<<<<<<<<<<<<<<<<<<<<<<< -const String WUNDERGRROUND_API_KEY = ""; -//const String WUNDERGRROUND_API_KEY = "1c265fajf48s0a82"; // Random key example showing how the above line should look - -// For language codes see https://www.wunderground.com/weather/api/d/docs?d=language-support&_ga=1.55148395.1951311424.1484425551 -const String WUNDERGRROUND_LANGUAGE = "EN"; // Language EN = English - -// For a list of countries, states and cities see https://www.wunderground.com/about/faq/international_cities.asp -const String WUNDERGROUND_COUNTRY = "Peru"; // UK, US etc -const String WUNDERGROUND_CITY = "Base_Naval"; // City, "London", "FL/Boca_Raton" for Boca Raton in Florida (State/City) etc. Use underscore_for spaces) - -// Windspeed conversion, use 1 pair of #defines. To do: investigate a more convenient method <<<<<<<<<<<<<<<<<<<<< -//#define WIND_SPEED_SCALING 1.0 // mph -//#define WIND_SPEED_UNITS " mph" - -//#define WIND_SPEED_SCALING 0.868976 // mph to knots -//#define WIND_SPEED_UNITS " kn" - -#define WIND_SPEED_SCALING 1.60934 // mph to kph -#define WIND_SPEED_UNITS " kph" - -//Thingspeak Settings - not used, no need to populate this at the moment -const String THINGSPEAK_CHANNEL_ID = ""; -const String THINGSPEAK_API_READ_KEY = ""; - -// List, so that the downloader knows what to fetch -String wundergroundIcons [] = {"chanceflurries","chancerain","chancesleet","chancesnow","clear","cloudy","flurries","fog","hazy","mostlycloudy","mostlysunny","partlycloudy","partlysunny","rain","sleet","snow","sunny","tstorms","unknown"}; - -/*************************** - * End Settings - **************************/ diff --git a/examples/320 x 240/weather-station-v8/weather-station-v8.ino b/examples/320 x 240/weather-station-v8/weather-station-v8.ino deleted file mode 100644 index 4a84d28..0000000 --- a/examples/320 x 240/weather-station-v8/weather-station-v8.ino +++ /dev/null @@ -1,594 +0,0 @@ -/**The MIT License (MIT) - Copyright (c) 2015 by Daniel Eichhorn - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYBR_DATUM HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - See more at http://blog.squix.ch - - Adapted by Bodmer to use the faster TFT_eSPI library: - https://github.com/Bodmer/TFT_eSPI - - Plus: - Minor changes to text placement and auto-blanking out old text with background colour padding - Moon phase text added - Forecast text lines are automatically split onto two lines at a central space (some are long!) - Time is printed with colons aligned to tidy display - Min and max forecast temperatures spaced out - The ` character has been changed to a degree symbol in the 36 point font - New smart WU splash startup screen and updated progress messages - Display does not need to be blanked between updates - Icons nudged about slightly to add wind direction + speed -*/ - -#define SERIAL_MESSAGES - -#include - -#include -#include // Hardware-specific library - -// Additional UI functions -#include "GfxUi.h" - -// Fonts created by http://oleddisplay.squix.ch/ -#include "ArialRoundedMTBold_14.h" -#include "ArialRoundedMTBold_36.h" - -// Download helper -#include "WebResource.h" - -#include -#include -#include -#include -#include - -// Helps with connecting to internet -#include - -// check settings.h for adapting to your needs -#include "settings.h" -#include -#include -#include "TimeClient.h" - -// HOSTNAME for OTA update -#define HOSTNAME "ESP8266-OTA-" - -/***************************** - Important: see settings.h to configure your settings!!! - * ***************************/ - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library - -boolean booted = true; - -GfxUi ui = GfxUi(&tft); - -WebResource webResource; -TimeClient timeClient(UTC_OFFSET); - -// Set to false, if you prefere imperial/inches, Fahrenheit -WundergroundClient wunderground(IS_METRIC); - -//declaring prototypes -void configModeCallback (WiFiManager *myWiFiManager); -void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal); -ProgressCallback _downloadCallback = downloadCallback; -void downloadResources(); -void updateData(); -void drawProgress(uint8_t percentage, String text); -void drawTime(); -void drawCurrentWeather(); -void drawForecast(); -void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex); -String getMeteoconIcon(String iconText); -void drawAstronomy(); -void drawSeparator(uint16_t y); - -long lastDownloadUpdate = millis(); - -void setup() { -#ifdef SERIAL_MESSAGES - Serial.begin(250000); -#endif - tft.begin(); - tft.fillScreen(TFT_BLACK); - - tft.setFreeFont(&ArialRoundedMTBold_14); - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_DARKGREY, TFT_BLACK); - tft.drawString("Original by: blog.squix.org", 120, 240); - tft.drawString("Adapted by: Bodmer", 120, 260); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - SPIFFS.begin(); - //listFiles(); - //Uncomment if you want to erase SPIFFS and update all internet resources, this takes some time! - //tft.drawString("Formatting SPIFFS, so wait!", 120, 200); SPIFFS.format(); - - if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10); - if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56); // Image is 56 pixels high - delay(1000); - tft.drawString("Connecting to WiFi", 120, 200); - tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text - - //WiFiManager - //Local intialization. Once its business is done, there is no need to keep it around - WiFiManager wifiManager; - // Uncomment for testing wifi manager - //wifiManager.resetSettings(); - wifiManager.setAPCallback(configModeCallback); - - //or use this for auto generated name ESP + ChipID - wifiManager.autoConnect(); - - //Manual Wifi - //WiFi.begin(WIFI_SSID, WIFI_PWD); - - // OTA Setup - String hostname(HOSTNAME); - hostname += String(ESP.getChipId(), HEX); - WiFi.hostname(hostname); - ArduinoOTA.setHostname((const char *)hostname.c_str()); - ArduinoOTA.begin(); - - // download images from the net. If images already exist don't download - tft.drawString("Downloading to SPIFFS...", 120, 200); - tft.drawString(" ", 120, 240); // Clear line - tft.drawString(" ", 120, 260); // Clear line - downloadResources(); - //listFiles(); - tft.setTextDatum(BC_DATUM); - tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text - tft.drawString(" ", 120, 200); // Clear line above using set padding width - tft.drawString("Fetching weather data...", 120, 200); - //delay(500); - - // load the weather information - updateData(); -} - -long lastDrew = 0; -void loop() { - // Handle OTA update requests - ArduinoOTA.handle(); - - // Check if we should update the clock - if (millis() - lastDrew > 30000 && wunderground.getSeconds() == "00") { - drawTime(); - lastDrew = millis(); - } - - // Check if we should update weather information - if (millis() - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) { - updateData(); - lastDownloadUpdate = millis(); - } -} - -// Called if WiFi has not been configured yet -void configModeCallback (WiFiManager *myWiFiManager) { - tft.setTextDatum(BC_DATUM); - tft.setFreeFont(&ArialRoundedMTBold_14); - tft.setTextColor(TFT_ORANGE); - tft.drawString("Wifi Manager", 120, 28); - tft.drawString("Please connect to AP", 120, 42); - tft.setTextColor(TFT_WHITE); - tft.drawString(myWiFiManager->getConfigPortalSSID(), 120, 56); - tft.setTextColor(TFT_ORANGE); - tft.drawString("To setup Wifi Configuration", 120, 70); -} - -// callback called during download of files. Updates progress bar -void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal) { - Serial.println(String(bytesDownloaded) + " / " + String(bytesTotal)); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(240); - - int percentage = 100 * bytesDownloaded / bytesTotal; - if (percentage == 0) { - tft.drawString(filename, 120, 220); - } - if (percentage % 5 == 0) { - tft.setTextDatum(TC_DATUM); - tft.setTextPadding(tft.textWidth(" 888% ")); - tft.drawString(String(percentage) + "%", 120, 245); - ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE); - } - -} - -// Download the bitmaps -void downloadResources() { - // tft.fillScreen(TFT_BLACK); - tft.setFreeFont(&ArialRoundedMTBold_14); - char id[5]; - - // Download WU graphic jpeg first and display it, then the Earth view - webResource.downloadFile((String)"http://i.imgur.com/njl1pMj.jpg", (String)"/WU.jpg", _downloadCallback); - if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10); - - webResource.downloadFile((String)"http://i.imgur.com/v4eTLCC.jpg", (String)"/Earth.jpg", _downloadCallback); - if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56); - - //webResource.downloadFile((String)"http://i.imgur.com/IY57GSv.jpg", (String)"/Horizon.jpg", _downloadCallback); - //if (SPIFFS.exists("/Horizon.jpg") == true) ui.drawJpeg("/Horizon.jpg", 0, 320-160); - - //webResource.downloadFile((String)"http://i.imgur.com/jZptbtY.jpg", (String)"/Rainbow.jpg", _downloadCallback); - //if (SPIFFS.exists("/Rainbow.jpg") == true) ui.drawJpeg("/Rainbow.jpg", 0, 0); - - for (int i = 0; i < 19; i++) { - sprintf(id, "%02d", i); - webResource.downloadFile("http://www.squix.org/blog/wunderground/" + wundergroundIcons[i] + ".bmp", wundergroundIcons[i] + ".bmp", _downloadCallback); - } - for (int i = 0; i < 19; i++) { - sprintf(id, "%02d", i); - webResource.downloadFile("http://www.squix.org/blog/wunderground/mini/" + wundergroundIcons[i] + ".bmp", "/mini/" + wundergroundIcons[i] + ".bmp", _downloadCallback); - } - for (int i = 0; i < 24; i++) { - webResource.downloadFile("http://www.squix.org/blog/moonphase_L" + String(i) + ".bmp", "/moon" + String(i) + ".bmp", _downloadCallback); - } -} - -// Update the internet based information and update screen -void updateData() { - // booted = true; // Test only - // booted = false; // Test only - - if (booted) ui.drawJpeg("/WU.jpg", 0, 10); // May have already drawn this but it does not take long - else tft.drawCircle(22, 22, 18, TFT_DARKGREY); // Outer ring - optional - - if (booted) drawProgress(20, "Updating time..."); - else fillSegment(22, 22, 0, (int) (20 * 3.6), 16, TFT_NAVY); - - timeClient.updateTime(); - if (booted) drawProgress(50, "Updating conditions..."); - else fillSegment(22, 22, 0, (int) (50 * 3.6), 16, TFT_NAVY); - - wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - if (booted) drawProgress(70, "Updating forecasts..."); - else fillSegment(22, 22, 0, (int) (70 * 3.6), 16, TFT_NAVY); - - wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - if (booted) drawProgress(90, "Updating astronomy..."); - else fillSegment(22, 22, 0, (int) (90 * 3.6), 16, TFT_NAVY); - - wunderground.updateAstronomy(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY); - // lastUpdate = timeClient.getFormattedTime(); - // readyForWeatherUpdate = false; - if (booted) drawProgress(100, "Done..."); - else fillSegment(22, 22, 0, 360, 16, TFT_NAVY); - - if (booted) delay(2000); - - if (booted) tft.fillScreen(TFT_BLACK); - else fillSegment(22, 22, 0, 360, 22, TFT_BLACK); - - //tft.fillScreen(TFT_CYAN); // For text padding and update graphics over-write checking only - drawTime(); - drawCurrentWeather(); - drawForecast(); - drawAstronomy(); - booted = false; -} - -// Progress bar helper -void drawProgress(uint8_t percentage, String text) { - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(240); - tft.drawString(text, 120, 220); - - ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE); - - tft.setTextPadding(0); -} - -// draws the clock -void drawTime() { - - tft.setFreeFont(&ArialRoundedMTBold_36); - - String timeNow = timeClient.getHours() + ":" + timeClient.getMinutes(); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_YELLOW, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 44:44 ")); // String width + margin - tft.drawString(timeNow, 120, 53); - - tft.setFreeFont(&ArialRoundedMTBold_14); - - String date = wunderground.getDate(); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" Ddd, 44 Mmm 4444 ")); // String width + margin - tft.drawString(date, 120, 16); - - drawSeparator(54); - - tft.setTextPadding(0); -} - -// draws current weather information -void drawCurrentWeather() { - // Weather Icon - String weatherIcon = getMeteoconIcon(wunderground.getTodayIcon()); - //uint32_t dt = millis(); - ui.drawBmp(weatherIcon + ".bmp", 0, 59); - //Serial.print("Icon draw time = "); Serial.println(millis()-dt); - - // Weather Text - - String weatherText = wunderground.getWeatherText(); - //weatherText = "Heavy Thunderstorms with Small Hail"; // Test line splitting with longest(?) string - - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - int splitPoint = 0; - int xpos = 230; - splitPoint = splitIndex(weatherText); - if (splitPoint > 16) xpos = 235; - - tft.setTextPadding(tft.textWidth("Heavy Thunderstorms")); // Max anticipated string width - if (splitPoint) tft.drawString(weatherText.substring(0, splitPoint), xpos, 72); - tft.setTextPadding(tft.textWidth(" with Small Hail")); // Max anticipated string width + margin - tft.drawString(weatherText.substring(splitPoint), xpos, 87); - - tft.setFreeFont(&ArialRoundedMTBold_36); - - tft.setTextDatum(TR_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - - // Font ASCII code 96 (0x60) modified to make "`" a degree symbol - tft.setTextPadding(tft.textWidth("-88`")); // Max width of vales - - weatherText = wunderground.getCurrentTemp(); - if (weatherText.indexOf(".")) weatherText = weatherText.substring(0, weatherText.indexOf(".")); // Make it integer temperature - if (weatherText == "") weatherText = "?"; // Handle null return - tft.drawString(weatherText + "`", 221, 100); - - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(TL_DATUM); - tft.setTextPadding(0); - if (IS_METRIC) tft.drawString("C ", 221, 100); - else tft.drawString("F ", 221, 100); - - //tft.drawString(wunderground.getPressure(), 180, 30); - - weatherText = ""; //wunderground.getWindDir() + " "; - weatherText += String((int)(wunderground.getWindSpeed().toInt() * WIND_SPEED_SCALING)) + WIND_SPEED_UNITS; - - tft.setTextDatum(TC_DATUM); - tft.setTextPadding(tft.textWidth(" 888 mph")); // Max string length? - tft.drawString(weatherText, 128, 136); - - weatherText = wunderground.getPressure(); - - tft.setTextDatum(TR_DATUM); - tft.setTextPadding(tft.textWidth(" 8888mb")); // Max string length? - tft.drawString(weatherText, 230, 136); - - weatherText = wunderground.getWindDir(); - - int windAngle = 0; - String compassCardinal = ""; - switch (weatherText.length()) { - case 1: - compassCardinal = "N E S W "; // Not used, see default below - windAngle = 90 * compassCardinal.indexOf(weatherText) / 2; - break; - case 2: - compassCardinal = "NE SE SW NW"; - windAngle = 45 + 90 * compassCardinal.indexOf(weatherText) / 3; - break; - case 3: - compassCardinal = "NNE ENE ESE SSE SSW WSW WNW NNW"; - windAngle = 22 + 45 * compassCardinal.indexOf(weatherText) / 4; // 22 should be 22.5 but accuracy is not needed! - break; - default: - if (weatherText == "Variable") windAngle = -1; - else { - // v23456v23456v23456v23456 character ruler - compassCardinal = "North East South West"; // Possible strings - windAngle = 90 * compassCardinal.indexOf(weatherText) / 6; - } - break; - } - - tft.fillCircle(128, 110, 23, TFT_BLACK); // Erase old plot, radius + 1 to delete stray pixels - tft.drawCircle(128, 110, 22, TFT_DARKGREY); // Outer ring - optional - if ( windAngle >= 0 ) fillSegment(128, 110, windAngle - 15, 30, 22, TFT_GREEN); // Might replace this with a bigger rotating arrow - tft.drawCircle(128, 110, 6, TFT_RED); - - drawSeparator(153); - - tft.setTextDatum(TL_DATUM); // Reset datum to normal - tft.setTextPadding(0); // Reset padding width to none -} - -// draws the three forecast columns -void drawForecast() { - drawForecastDetail(10, 171, 0); - drawForecastDetail(95, 171, 2); - drawForecastDetail(180, 171, 4); - drawSeparator(171 + 69); -} - -// helper for the forecast columns -void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex) { - tft.setFreeFont(&ArialRoundedMTBold_14); - - String day = wunderground.getForecastTitle(dayIndex).substring(0, 3); - day.toUpperCase(); - - tft.setTextDatum(BC_DATUM); - - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(tft.textWidth("WWW")); - tft.drawString(day, x + 25, y); - - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth("-88 -88")); - tft.drawString(wunderground.getForecastHighTemp(dayIndex) + " " + wunderground.getForecastLowTemp(dayIndex), x + 25, y + 14); - - String weatherIcon = getMeteoconIcon(wunderground.getForecastIcon(dayIndex)); - ui.drawBmp("/mini/" + weatherIcon + ".bmp", x, y + 15); - - tft.setTextPadding(0); // Reset padding width to none -} - -// draw moonphase and sunrise/set and moonrise/set -void drawAstronomy() { - tft.setFreeFont(&ArialRoundedMTBold_14); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" Waxing Crescent ")); - tft.drawString(wunderground.getMoonPhase(), 120, 260 - 2); - - int moonAgeImage = 24 * wunderground.getMoonAge().toInt() / 30.0; - ui.drawBmp("/moon" + String(moonAgeImage) + ".bmp", 120 - 30, 260); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(0); // Reset padding width to none - tft.drawString("Sun", 40, 280); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 88:88 ")); - int dt = rightOffset(wunderground.getSunriseTime(), ":"); // Draw relative to colon to them aligned - tft.drawString(wunderground.getSunriseTime(), 40 + dt, 300); - - dt = rightOffset(wunderground.getSunsetTime(), ":"); - tft.drawString(wunderground.getSunsetTime(), 40 + dt, 315); - - tft.setTextDatum(BC_DATUM); - tft.setTextColor(TFT_ORANGE, TFT_BLACK); - tft.setTextPadding(0); // Reset padding width to none - tft.drawString("Moon", 200, 280); - - tft.setTextDatum(BR_DATUM); - tft.setTextColor(TFT_WHITE, TFT_BLACK); - tft.setTextPadding(tft.textWidth(" 88:88 ")); - dt = rightOffset(wunderground.getMoonriseTime(), ":"); // Draw relative to colon to them aligned - tft.drawString(wunderground.getMoonriseTime(), 200 + dt, 300); - - dt = rightOffset(wunderground.getMoonsetTime(), ":"); - tft.drawString(wunderground.getMoonsetTime(), 200 + dt, 315); - - tft.setTextPadding(0); // Reset padding width to none -} - -// Helper function, should be part of the weather station library and should disappear soon -String getMeteoconIcon(String iconText) { - if (iconText == "F") return "chanceflurries"; - if (iconText == "Q") return "chancerain"; - if (iconText == "W") return "chancesleet"; - if (iconText == "V") return "chancesnow"; - if (iconText == "S") return "chancetstorms"; - if (iconText == "B") return "clear"; - if (iconText == "Y") return "cloudy"; - if (iconText == "F") return "flurries"; - if (iconText == "M") return "fog"; - if (iconText == "E") return "hazy"; - if (iconText == "Y") return "mostlycloudy"; - if (iconText == "H") return "mostlysunny"; - if (iconText == "H") return "partlycloudy"; - if (iconText == "J") return "partlysunny"; - if (iconText == "W") return "sleet"; - if (iconText == "R") return "rain"; - if (iconText == "W") return "snow"; - if (iconText == "B") return "sunny"; - if (iconText == "0") return "tstorms"; - - - return "unknown"; -} - -// if you want separators, uncomment the tft-line -void drawSeparator(uint16_t y) { - tft.drawFastHLine(10, y, 240 - 2 * 10, 0x4228); -} - -// determine the "space" split point in a long string -int splitIndex(String text) -{ - int index = 0; - while ( (text.indexOf(' ', index) >= 0) && ( index <= text.length() / 2 ) ) { - index = text.indexOf(' ', index) + 1; - } - if (index) index--; - return index; -} - -// Calculate coord delta from start of text String to start of sub String contained within that text -// Can be used to vertically right align text so for example a colon ":" in the time value is always -// plotted at same point on the screen irrespective of different proportional character widths, -// could also be used to align decimal points for neat formatting -int rightOffset(String text, String sub) -{ - int index = text.indexOf(sub); - return tft.textWidth(text.substring(index)); -} - -// Calculate coord delta from start of text String to start of sub String contained within that text -// Can be used to vertically left align text so for example a colon ":" in the time value is always -// plotted at same point on the screen irrespective of different proportional character widths, -// could also be used to align decimal points for neat formatting -int leftOffset(String text, String sub) -{ - int index = text.indexOf(sub); - return tft.textWidth(text.substring(0, index)); -} - -// Draw a segment of a circle, centred on x,y with defined start_angle and subtended sub_angle -// Angles are defined in a clockwise direction with 0 at top -// Segment has radius r and it is plotted in defined colour -// Can be used for pie charts etc, in this sketch it is used for wind direction -#define DEG2RAD 0.0174532925 // Degrees to Radians conversion factor -#define INC 2 // Minimum segment subtended angle and plotting angle increment (in degrees) -void fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned int colour) -{ - // Calculate first pair of coordinates for segment start - float sx = cos((start_angle - 90) * DEG2RAD); - float sy = sin((start_angle - 90) * DEG2RAD); - uint16_t x1 = sx * r + x; - uint16_t y1 = sy * r + y; - - // Draw colour blocks every INC degrees - for (int i = start_angle; i < start_angle + sub_angle; i += INC) { - - // Calculate pair of coordinates for segment end - int x2 = cos((i + 1 - 90) * DEG2RAD) * r + x; - int y2 = sin((i + 1 - 90) * DEG2RAD) * r + y; - - tft.fillTriangle(x1, y1, x2, y2, x, y, colour); - - // Copy segment end to sgement start for next segment - x1 = x2; - y1 = y2; - } -} diff --git a/examples/480 x 320/Flash_Bitmap/Alert.h b/examples/480 x 320/Flash_Bitmap/Alert.h deleted file mode 100644 index 54d013d..0000000 --- a/examples/480 x 320/Flash_Bitmap/Alert.h +++ /dev/null @@ -1,42 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t alertWidth = 32; -const uint16_t alertHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short alert[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1080,0xAC66,0xEDE8,0xFE69,0xC4C6,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xBCC6,0xFE68,0xFE68,0xFE6A,0xFE68,0xEDE8,0x18A1,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x8344,0xFE48,0xFE8C,0xFFDD,0xFFFF,0xFEF0,0xFE48,0xB466,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1880,0xEDC7,0xFE48,0xFF99,0xFFBC,0xFF9B,0xFFBD,0xFE6A,0xFE48,0x5A23,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BE5,0xFE28,0xFED0,0xFFBC,0xFF7A,0xFF9A,0xFF9B,0xFF35,0xFE28,0xBCA6,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3962,0xFE28,0xFE28,0xFF9A,0xFF79,0xFF9A,0xFF9B,0xFF9A,0xFFBD,0xFE6B,0xFE28,0x72E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xB465,0xFE28,0xFEF2,0xFF7A,0xFF79,0xFF7A,0xFF9A,0xFF7A,0xFF7A,0xFF78,0xFE28,0xDD67,0x0860,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5A22,0xFE07,0xFE29,0xFF9B,0xFF37,0xFF58,0xFF79,0xFF79,0xFF79,0xFF58,0xFF9B,0xFEAE,0xFE07,0x93A4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xC4A5,0xFE07,0xFF15,0xFF37,0xFF36,0xAD11,0x2965,0x2965,0xCDF4,0xFF37,0xFF37,0xFF79,0xFE07,0xFE07,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7B03,0xFDE7,0xFE4B,0xFF79,0xFEF4,0xFF15,0xB552,0x2945,0x2945,0xDE55,0xFF16,0xFF15,0xFF58,0xFED1,0xFDE7,0xAC25,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0xDD26,0xFDE7,0xFF57,0xFED3,0xFED2,0xFEF4,0xBD93,0x2124,0x2124,0xDE75,0xFF14,0xFED3,0xFED3,0xFF7A,0xFE08,0xFDE7,0x49A2,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 11, 384 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x9BA4,0xFDC6,0xFE6E,0xFF36,0xFE90,0xFEB1,0xFED3,0xC592,0x2124,0x2124,0xE675,0xFED3,0xFEB2,0xFEB1,0xFEF3,0xFEF3,0xFDC6,0xBC45,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 12, 416 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3141,0xF5C6,0xF5C7,0xFF58,0xFE90,0xFE6F,0xFE8F,0xFEB1,0xCDB2,0x2104,0x2104,0xF6B4,0xFEB1,0xFE90,0xFE8F,0xFE90,0xFF58,0xFE0A,0xF5C6,0x72A3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 13, 448 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xABE4,0xF5A6,0xFEB1,0xFED3,0xFE4E,0xFE6E,0xFE6F,0xFE90,0xD5F2,0x18E3,0x18E3,0xFED4,0xFE90,0xFE6F,0xFE6F,0xFE6E,0xFE91,0xFF36,0xF5A6,0xCCA5,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 14, 480 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x5202,0xF5A6,0xF5C7,0xFF58,0xFE4D,0xFE4D,0xFE4D,0xFE4E,0xFE6F,0xDE11,0x18C3,0x18C3,0xFED3,0xFE6F,0xFE6E,0xFE4E,0xFE4D,0xFE4D,0xFF16,0xFE2C,0xF5A6,0x9363,0x0000,0x0000,0x0000,0x0000,0x0000, // row 15, 512 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0xBC44,0xF585,0xFED3,0xFE6F,0xFE2C,0xFE2C,0xFE2D,0xFE4D,0xFE4E,0xE630,0x10A2,0x2104,0xFED1,0xFE4E,0xFE4D,0xFE4D,0xFE2D,0xFE2C,0xFE4D,0xFF37,0xF586,0xF585,0x28E1,0x0000,0x0000,0x0000,0x0000, // row 16, 544 pixels -0x0000,0x0000,0x0000,0x0000,0x7282,0xF565,0xF5EA,0xFF16,0xFE0B,0xFE0B,0xFE0B,0xFE2C,0xFE2C,0xFE4D,0xF670,0x1082,0x2924,0xFEB0,0xFE2D,0xFE2C,0xFE2C,0xFE2C,0xFE0B,0xFE0B,0xFEB2,0xFE6F,0xF565,0xA383,0x0000,0x0000,0x0000,0x0000, // row 17, 576 pixels -0x0000,0x0000,0x0000,0x0840,0xD4C4,0xF565,0xFEF5,0xFE0C,0xFDE9,0xFDEA,0xFE0A,0xFE0B,0xFE0B,0xFE2C,0xFE8F,0x0861,0x2964,0xFE8F,0xFE2C,0xFE0B,0xFE0B,0xFE0B,0xFE0A,0xFDEA,0xFE0B,0xFF37,0xF586,0xF565,0x4181,0x0000,0x0000,0x0000, // row 18, 608 pixels -0x0000,0x0000,0x0000,0x9343,0xF545,0xF60C,0xFED3,0xFDC8,0xFDC8,0xFDC9,0xFDE9,0xFDEA,0xFDEA,0xFE0B,0xFE8E,0x0861,0x3184,0xFE6D,0xFE0B,0xFE0A,0xFDEA,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFE4E,0xFEB2,0xF545,0xB3E3,0x0000,0x0000,0x0000, // row 19, 640 pixels -0x0000,0x0000,0x28E0,0xF544,0xF545,0xFF17,0xFDC8,0xFDA7,0xFDA7,0xFDC8,0xFDC8,0xFDC9,0xFDC9,0xFDE9,0xFE6C,0x10A2,0x39C4,0xFE4C,0xFDEA,0xFDE9,0xFDC9,0xFDC9,0xFDC8,0xFDC8,0xFDA7,0xFDA8,0xFF16,0xF588,0xF544,0x6222,0x0000,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xA383,0xF524,0xF64E,0xFE4E,0xFD86,0xFD86,0xFD87,0xFDA7,0xFDA7,0xFDA8,0xFDC8,0xFDC8,0xFE2A,0xA469,0xB4EA,0xFE2A,0xFDC9,0xFDC8,0xFDC8,0xFDA8,0xFDA7,0xFDA7,0xFD87,0xFD86,0xFDEA,0xFED3,0xF524,0xC443,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x51C1,0xF504,0xF546,0xFF16,0xF565,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDA7,0xFDA7,0xFDE8,0xFE6A,0xFE4A,0xFDE8,0xFDA7,0xFDA7,0xFDA7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFEB2,0xF5CA,0xF504,0x8AE2,0x0000, // row 22, 736 pixels -0x0000,0xB3A2,0xED03,0xFE92,0xFDC9,0xF543,0xF544,0xFD44,0xFD65,0xFD65,0xFD65,0xFD86,0xFD86,0xFD86,0xFDA7,0xFDC7,0xFDC7,0xFDA7,0xFD86,0xFD86,0xFD86,0xFD86,0xFD65,0xFD65,0xFD65,0xFD44,0xF544,0xFD86,0xFEF5,0xED03,0xE4C3,0x1880, // row 23, 768 pixels -0x7241,0xECE3,0xF567,0xFED3,0xF523,0xF523,0xF523,0xF543,0xF544,0xF544,0xFD65,0xFD65,0xFD65,0xFD65,0xD4E6,0x39C5,0x39A5,0xD4E6,0xFD86,0xFD65,0xFD65,0xFD65,0xFD65,0xF544,0xF544,0xF543,0xF523,0xF523,0xFE2E,0xF5EC,0xECE3,0x9B42, // row 24, 800 pixels -0xD443,0xECE3,0xFED4,0xF565,0xF502,0xF502,0xF522,0xF523,0xF523,0xF543,0xF544,0xF544,0xF544,0xFD65,0x8B64,0x18C3,0x18C3,0x8344,0xFD85,0xFD44,0xF544,0xF544,0xF544,0xF543,0xF523,0xF523,0xF522,0xF502,0xF523,0xFEF5,0xED04,0xECE3, // row 25, 832 pixels -0xECC3,0xF5AB,0xFE6F,0xF501,0xF4E1,0xF501,0xF502,0xF502,0xF522,0xF522,0xF523,0xF523,0xF523,0xFD84,0xC504,0x20E1,0x18E1,0xC4E4,0xFD84,0xF543,0xF523,0xF523,0xF523,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xFDC9,0xF62F,0xECC3, // row 26, 864 pixels -0xECC2,0xFE92,0xF523,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF502,0xF502,0xF522,0xF522,0xF543,0xFDE3,0xFEA5,0xF6A4,0xFE04,0xF543,0xF522,0xF522,0xF522,0xF502,0xF502,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E1,0xFED4,0xECC2, // row 27, 896 pixels -0xECA2,0xF5EC,0xF4E0,0xF4C0,0xF4E0,0xF4E0,0xF4E0,0xF4E1,0xF4E1,0xF501,0xF501,0xF501,0xF502,0xF502,0xF542,0xFDA2,0xFDA2,0xF542,0xF502,0xF502,0xF502,0xF501,0xF501,0xF501,0xF4E1,0xF4E1,0xF4E0,0xF4E0,0xF4E0,0xF4C0,0xF5A9,0xECA2, // row 28, 928 pixels -0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels -0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels -0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/480 x 320/Flash_Bitmap/Close.h b/examples/480 x 320/Flash_Bitmap/Close.h deleted file mode 100644 index c16d522..0000000 --- a/examples/480 x 320/Flash_Bitmap/Close.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t closeWidth = 32; -const uint16_t closeHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short close[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x58E3,0xC228,0xFC10,0xFD34,0xFE18,0xFE59,0xFE79,0xFE9A,0xFE9A,0xFE9A,0xFE9A,0xFE59,0xFD75,0xFC51,0xC28A,0x5904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2041,0x8945,0xF34D,0xFD34,0xFDB6,0xFD75,0xFD55,0xFD55,0xFD96,0xFDD7,0xFDF7,0xFDF7,0xFDB6,0xFDB6,0xFDD7,0xFDF7,0xFD75,0xF38E,0x8965,0x2041,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x4082,0xE208,0xF410,0xFD34,0xFC92,0xFBEF,0xFBAE,0xFBEF,0xFC71,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC92,0xFC51,0xFC71,0xFCF3,0xFD75,0xFC30,0xEA28,0x40A2,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x3861,0xE1E7,0xF451,0xFC92,0xFB4D,0xFA49,0xFA49,0xFAEB,0xFBAE,0xFC71,0xFD34,0xFDB6,0xFE18,0xFDB6,0xFD34,0xFC71,0xFBAE,0xFB0C,0xFAEB,0xFBAE,0xFCD3,0xFC71,0xE208,0x4082,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x1020,0xD986,0xF430,0xFC30,0xFA28,0xF924,0xF965,0xFA8A,0xFB0C,0xFBAE,0xFC51,0xFD14,0xFD75,0xFDB6,0xFD75,0xFD14,0xFC51,0xFC71,0xFBEF,0xFA28,0xF9C7,0xFA8A,0xFC51,0xF430,0xD9A6,0x1020,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x78A2,0xEB6D,0xFC30,0xF9C7,0xF861,0xF8A2,0xFA08,0xFEDB,0xFD55,0xFB4D,0xFC10,0xFC92,0xFD14,0xFD34,0xFD14,0xFC92,0xFCB2,0xFF7D,0xFF7D,0xFB2C,0xF945,0xF8E3,0xF9E7,0xFC30,0xEB8E,0x78C3,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x3841,0xD9E7,0xF492,0xF208,0xF041,0xF800,0xF945,0xFE9A,0xFFFF,0xFFFF,0xFD75,0xFB8E,0xFC10,0xFC51,0xFC71,0xFC51,0xFCB2,0xFF7D,0xFFFF,0xFFFF,0xFF3C,0xFA8A,0xF882,0xF841,0xFA08,0xFC92,0xDA08,0x3841,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x88A2,0xEBCF,0xF2EB,0xF061,0xF000,0xF8E3,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD75,0xFB4D,0xFBAE,0xFBAE,0xFC71,0xFF7D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFEFB,0xFA28,0xF800,0xF061,0xF2EB,0xEBEF,0x90C3,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x2820,0xD1C7,0xF410,0xE945,0xE800,0xF000,0xFE9A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD34,0xFAEB,0xFBCF,0xFF5D,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFF1C,0xF986,0xF000,0xF145,0xF410,0xD1E7,0x2820,0x0000, // row 10, 352 pixels -0x0000,0x6841,0xDB2C,0xEACB,0xE041,0xE800,0xF000,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFD14,0xFF1C,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFBCF,0xF082,0xF000,0xE841,0xEACB,0xE34D,0x7061,0x0000, // row 11, 384 pixels -0x0000,0x9861,0xE3CF,0xE186,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE986,0xEBCF,0xA082,0x0000, // row 12, 416 pixels -0x0800,0xB8A2,0xE3AE,0xD8A2,0xD800,0xE000,0xE800,0xE800,0xF145,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE0A2,0xEBAE,0xC0C3,0x0800, // row 13, 448 pixels -0x1800,0xC124,0xE30C,0xD020,0xD800,0xE000,0xE000,0xE800,0xE800,0xF145,0xFEDB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB8E,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD820,0xE30C,0xC124,0x1800, // row 14, 480 pixels -0x2800,0xC165,0xDAAA,0xC800,0xD000,0xD800,0xE000,0xE000,0xE800,0xE800,0xF124,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFB6D,0xF000,0xF000,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xDAAA,0xC165,0x2800, // row 15, 512 pixels -0x2000,0xB924,0xD269,0xC800,0xD000,0xD000,0xD800,0xE000,0xE000,0xE800,0xE924,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF36D,0xE800,0xE800,0xE800,0xE000,0xE000,0xD800,0xD000,0xD000,0xDA69,0xC145,0x2800, // row 16, 544 pixels -0x1000,0xB0A2,0xD28A,0xC000,0xC800,0xD000,0xD000,0xD800,0xD800,0xE165,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xF3AE,0xE000,0xE000,0xD800,0xD800,0xD000,0xD000,0xC800,0xD28A,0xB8C3,0x1000, // row 17, 576 pixels -0x0000,0xA800,0xD2AA,0xB800,0xC000,0xC800,0xC800,0xD000,0xD965,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBAE,0xD800,0xD800,0xD000,0xC800,0xC800,0xC000,0xD2AA,0xB020,0x0000, // row 18, 608 pixels -0x0000,0x8000,0xCA69,0xB841,0xB800,0xC000,0xC800,0xD186,0xFEFB,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBCF,0xD000,0xC800,0xC800,0xC000,0xC041,0xCA69,0x8000,0x0000, // row 19, 640 pixels -0x0000,0x4800,0xC1C7,0xB8E3,0xB800,0xB800,0xC000,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xEBEF,0xFE79,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE410,0xC841,0xC000,0xB800,0xC0E3,0xC1C7,0x4800,0x0000, // row 20, 672 pixels -0x0000,0x1000,0xB061,0xC1E7,0xB000,0xB000,0xB800,0xD269,0xFFBE,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xD000,0xD965,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xC020,0xB800,0xB000,0xC1E7,0xB061,0x1000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x6000,0xB9C7,0xB061,0xB000,0xB000,0xB800,0xCA49,0xFF9E,0xFFFF,0xFFFF,0xFFFF,0xE38E,0xC800,0xC800,0xC800,0xD186,0xF69A,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xDB0C,0xB800,0xB800,0xB000,0xB061,0xC1C7,0x6000,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x1800,0xB041,0xB986,0xA800,0xA800,0xB000,0xB000,0xCA49,0xFF7D,0xFFFF,0xDB8E,0xC000,0xC000,0xC000,0xC000,0xC000,0xC986,0xF6DB,0xFFFF,0xFFFF,0xD30C,0xB800,0xB000,0xB000,0xA800,0xB986,0xB041,0x1800,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x5800,0xB0E3,0xA8C3,0xA800,0xA800,0xA800,0xB000,0xCACB,0xD38E,0xB000,0xB800,0xB800,0xB800,0xB800,0xB800,0xB800,0xC145,0xF6DB,0xD34D,0xB000,0xB000,0xA800,0xA800,0xB0C3,0xB0E3,0x5800,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x6000,0xB124,0xA882,0xA000,0xA800,0xA800,0xA800,0xA800,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xB000,0xA800,0xA800,0xA800,0xA800,0xA882,0xB124,0x6000,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB104,0xA882,0xA000,0xA000,0xA000,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA800,0xA000,0xA000,0xA882,0xB104,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x6000,0xB0A2,0xA8C3,0xA020,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA000,0xA020,0xA8C3,0xB0A2,0x6000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4800,0xA800,0xB0C3,0xA0A2,0x9800,0x9800,0x9800,0x9800,0xA000,0xA000,0xA000,0x9800,0x9800,0x9800,0xA082,0xB0E3,0xA800,0x4800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x5800,0xA800,0xB0A2,0xA8E3,0xA0A2,0xA041,0x9800,0x9800,0xA041,0xA0A2,0xA8E3,0xB0A2,0xA800,0x5800,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3000,0x6000,0x8800,0xA000,0xA800,0xA800,0xA000,0x8800,0x6000,0x3000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino b/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino deleted file mode 100644 index 0329e5f..0000000 --- a/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino +++ /dev/null @@ -1,113 +0,0 @@ -// Code partly derived from ILI9341_due library example - -// Draws the 3 icons across the middle of the screen and pauses. -// Then draws 300 icons at random locations, clears screen and repeats -// -// This demonstrates drawing icons from FLASH - -// Icons are stored in tabs, e.g. Alert.h etc -// more than one icon can be in a header file. - -/* - This sketch demonstrates loading images from arrays stored in program (FLASH) memory. - - Works with TFT_eSPI library here: - https://github.com/Bodmer/TFT_eSPI - - This sketch does not use/need any fonts at all... - - Arrays containing FLASH images can be created with UTFT library tool: - (libraries\UTFT\Tools\ImageConverter565.exe) - Convert to .c format then copy into a new tab - - The number and size of icons is limited by available FLASH memory. The icon array will - use width x height x 2 bytes of FLASH, i.e. 32 x 32 icon uses ~2048 bytes - -*/ - -#include // Hardware-specific library -#include - -TFT_eSPI tft = TFT_eSPI(); // Invoke custom library with default width and height - -// Include the header files that contain the icons -#include "alert.h" -#include "Close.h" -#include "Info.h" - -long count = 0; // Loop count - -void setup() -{ - Serial.begin(115200); - tft.begin(); - tft.setRotation(1); // landscape - - tft.fillScreen(TFT_BLACK); - - // Draw the icons - drawIcon(info, (tft.width() - infoWidth)/2 - 50, (tft.height() - infoHeight)/2, infoWidth, infoHeight); - drawIcon(alert, (tft.width() - alertWidth)/2, (tft.height() - alertHeight)/2, alertWidth, alertHeight); - drawIcon(close, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); - - // Pause here to admire the icons! - delay(4000); - -} - -void loop() -{ - // Loop filling and clearing screen - drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight); - drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight); - drawIcon(close, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); - - // Clear screen after 100 x 3 = 300 icons drawn - if (100 == count++) { - count = 1; - tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! - tft.fillScreen(TFT_BLACK); - tft.setRotation(1); - Serial.println(millis()); - } -} - - -//==================================================================================== -// This is the function to draw the icon stored as an array in program memory (FLASH) -//==================================================================================== - -// To speed up rendering we use a 64 pixel buffer -#define BUFF_SIZE 64 - -// Draw array "icon" of defined width and height at coordinate x,y -// Maximum icon size is 255x255 pixels to avoid integer overflow - -void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, int8_t height) { - - uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) - - // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); - - // Work out the number whole buffers to send - uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; - - // Fill and send "nb" buffers to TFT - for (int i = 0; i < nb; i++) { - for (int j = 0; j < BUFF_SIZE; j++) { - pix_buffer[j] = pgm_read_word(&icon[i * BUFF_SIZE + j]); - } - tft.pushColors(pix_buffer, BUFF_SIZE); - } - - // Work out number of pixels not yet sent - uint16_t np = ((uint16_t)height * width) % BUFF_SIZE; - - // Send any partial buffer left over - if (np) { - for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); - tft.pushColors(pix_buffer, np); - } -} - diff --git a/examples/480 x 320/Flash_Bitmap/Info.h b/examples/480 x 320/Flash_Bitmap/Info.h deleted file mode 100644 index c4ee633..0000000 --- a/examples/480 x 320/Flash_Bitmap/Info.h +++ /dev/null @@ -1,41 +0,0 @@ -// We need this header file to use FLASH as storage with PROGMEM directive: -#include - -// Icon width and height -const uint16_t infoWidth = 32; -const uint16_t infoHeight = 32; - -// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here -const unsigned short info[1024] PROGMEM={ -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0861,0x4A69,0x8C71,0xA514,0xBDF7,0xBDF7,0xA514,0x8C71,0x4A69,0x0861,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x39E7,0x9CF3,0xEF7D,0xF79E,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xFFDF,0xF79E,0xEF7D,0x9CF3,0x39E7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x2965,0x9492,0xF79E,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xF79E,0x9492,0x2965,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 3, 128 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFDF,0xFFFF,0xFFFF,0xFFFF,0xD75F,0xB6BF,0x9E5F,0x963F,0x963F,0x9E5F,0xB6BF,0xD75F,0xFFFF,0xFFFF,0xFFFF,0xFFDF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 4, 160 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xEF7D,0xFFDF,0xFFFF,0xFFDF,0xBEDF,0x7DBF,0x7DBF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x7DBE,0xBEBF,0xFFDF,0xFFFF,0xFFDF,0xEF7D,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 5, 192 pixels -0x0000,0x0000,0x0000,0x0000,0x630C,0xEF7D,0xFFFF,0xFFFF,0xE77F,0x7DBE,0x759E,0x759F,0x7DBF,0x7DDF,0x7DDF,0x85FF,0x7DDF,0x7DDF,0x7DBF,0x759F,0x759E,0x6D7E,0x7DBE,0xDF7F,0xFFFF,0xFFFF,0xEF7D,0x630C,0x0000,0x0000,0x0000,0x0000, // row 6, 224 pixels -0x0000,0x0000,0x0000,0x31A6,0xEF5D,0xFFDF,0xFFFF,0xCF1E,0x6D7E,0x6D7E,0x759E,0x759F,0x7DBF,0x7DDF,0x8E1F,0xBEDF,0xC6FF,0x8DFF,0x75BF,0x759F,0x759E,0x6D7E,0x655E,0x655D,0xCF1E,0xFFFF,0xFFDF,0xEF5D,0x31A6,0x0000,0x0000,0x0000, // row 7, 256 pixels -0x0000,0x0000,0x0000,0x94B2,0xF7BE,0xFFFF,0xDF5E,0x655D,0x655D,0x6D7E,0x6D7E,0x759E,0x75BF,0x759F,0xEFBF,0xFFFF,0xFFFF,0xEFBF,0x759F,0x759E,0x6D7E,0x6D7E,0x655D,0x653D,0x653D,0xDF5E,0xFFFF,0xF7BE,0x94B2,0x0000,0x0000,0x0000, // row 8, 288 pixels -0x0000,0x0000,0x4228,0xEF7D,0xFFFF,0xF7BF,0x6D5D,0x653D,0x655D,0x6D5E,0x6D7E,0x759E,0x759E,0x85DF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8DFE,0x6D7E,0x6D7E,0x6D5E,0x655D,0x653D,0x5D1D,0x6D5D,0xF7BF,0xFFFF,0xEF7D,0x4228,0x0000,0x0000, // row 9, 320 pixels -0x0000,0x0000,0xA534,0xFFDF,0xFFDF,0xA65D,0x5D1D,0x5D1D,0x653D,0x655E,0x6D7E,0x6D7E,0x6D7E,0x651E,0xE77F,0xFFFF,0xFFFF,0xF7BF,0x5CFE,0x6D7E,0x6D7E,0x655E,0x653D,0x5D1D,0x5D1D,0x54FC,0xA65D,0xFFDF,0xFFDF,0xA534,0x0000,0x0000, // row 10, 352 pixels -0x0000,0x18E3,0xEF5D,0xFFFF,0xEF9E,0x5CFC,0x54FC,0x5D1D,0x5D3D,0x653D,0x655E,0x6D7E,0x6D7E,0x653E,0x6D3E,0xB67E,0xBEBE,0x755E,0x5D1E,0x6D5E,0x655E,0x653D,0x5D3D,0x5D1D,0x54FC,0x54DC,0x54FC,0xEF9E,0xFFFF,0xEF5D,0x18E3,0x0000, // row 11, 384 pixels -0x0000,0x630C,0xEF7D,0xFFDF,0xB69D,0x54DC,0x54FC,0x5CFC,0x5D1D,0x653D,0x653D,0x655E,0x6D5E,0x655E,0x5CFE,0x4C9D,0x4C7D,0x54DD,0x653E,0x655E,0x653D,0x653D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0xB69D,0xFFDF,0xEF7D,0x630C,0x0000, // row 12, 416 pixels -0x0000,0x94B2,0xF7BE,0xFFDF,0x85BC,0x4CBC,0x54DC,0x54FC,0x5CFD,0x5D1D,0x5D3D,0x653D,0x655D,0x653D,0x85DE,0xC6FE,0xC6FE,0x85BE,0x653D,0x653D,0x5D3D,0x5D1D,0x5CFD,0x54FC,0x54DC,0x4CBC,0x4CBB,0x85BC,0xFFDF,0xF7BE,0x94B2,0x0000, // row 13, 448 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x651C,0x4CBB,0x4CBC,0x54DC,0x54FC,0x5CFC,0x5D1D,0x5D1D,0x653D,0x5D1D,0xE77E,0xFFDF,0xFFDF,0xEF9E,0x5CFD,0x5D1D,0x5D1D,0x5CFC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x651B,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 14, 480 pixels -0x0000,0xC638,0xFFDF,0xF7BE,0x54DB,0x449B,0x4CBB,0x4CBC,0x54DC,0x54FC,0x54FC,0x5D1D,0x5D1D,0x7D7D,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x7D7D,0x5CFD,0x54FC,0x54FC,0x54DC,0x4CBC,0x4CBB,0x449B,0x447B,0x54BB,0xF7BE,0xFFDF,0xC638,0x0000, // row 15, 512 pixels -0x0000,0xC638,0xFFDF,0xF79E,0x4CBB,0x449B,0x449B,0x4CBB,0x4CBC,0x54DC,0x54DC,0x54FC,0x54DC,0x753C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x753C,0x54DC,0x54DC,0x54DC,0x4CBC,0x4CBB,0x449B,0x449B,0x3C7B,0x4C9B,0xF79E,0xFFDF,0xC638,0x0000, // row 16, 544 pixels -0x0000,0xB5B6,0xFFDF,0xF7BE,0x5CFB,0x3C7B,0x447B,0x449B,0x4CBB,0x4CBC,0x4CBC,0x4CDC,0x4CBC,0x6D1C,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0x6CFC,0x4CBC,0x4CBC,0x4CBC,0x4CBB,0x449B,0x447B,0x3C7B,0x3C5A,0x54DB,0xF7BE,0xFFDF,0xB5B6,0x0000, // row 17, 576 pixels -0x0000,0x94B2,0xF7BE,0xF7BE,0x755B,0x3C5A,0x3C7B,0x447B,0x449B,0x449B,0x4CBB,0x4CBB,0x4C9B,0x6CFB,0xF79E,0xF79E,0xF79E,0xF79E,0x64FB,0x449B,0x4CBB,0x449B,0x449B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x753B,0xF7BE,0xF7BE,0x9CD3,0x0000, // row 18, 608 pixels -0x0000,0x6B4D,0xEF7D,0xF7BE,0xA61C,0x3C5A,0x3C5A,0x3C7B,0x447B,0x447B,0x449B,0x449B,0x447B,0x64DB,0xF79E,0xF79E,0xF79E,0xF79E,0x64DB,0x447B,0x449B,0x447B,0x447B,0x3C7B,0x3C5A,0x3C5A,0x343A,0xA61C,0xF7BE,0xEF7D,0x6B4D,0x0000, // row 19, 640 pixels -0x0000,0x2124,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x3C5A,0x3C5A,0x3C7B,0x3C7B,0x447B,0x3C5B,0x64BA,0xF79E,0xF79E,0xF79E,0xF79E,0x64BA,0x3C5B,0x3C7B,0x3C7B,0x3C5A,0x3C5A,0x343A,0x343A,0x343A,0xDF3D,0xFFDF,0xE71C,0x2124,0x0000, // row 20, 672 pixels -0x0000,0x0000,0xAD75,0xF7BE,0xF79E,0x859B,0x343A,0x343A,0x345A,0x3C5A,0x3C5A,0x3C5A,0x3C5A,0x5C9A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x5C9A,0x3C3A,0x3C5A,0x3C5A,0x345A,0x343A,0x343A,0x341A,0x859B,0xF79E,0xF7BE,0xAD75,0x0000,0x0000, // row 21, 704 pixels -0x0000,0x0000,0x528A,0xE71C,0xFFDF,0xDF3D,0x3C5A,0x343A,0x343A,0x343A,0x343A,0x3C5A,0x343A,0x4C5A,0xEF7D,0xEF7D,0xEF7D,0xEF7D,0x4C59,0x343A,0x343A,0x343A,0x343A,0x343A,0x341A,0x3C5A,0xDF3D,0xFFDF,0xE71C,0x528A,0x0000,0x0000, // row 22, 736 pixels -0x0000,0x0000,0x0000,0x9CD3,0xF79E,0xF7BE,0xBE7C,0x3419,0x341A,0x341A,0x343A,0x343A,0x341A,0x2B99,0xC69C,0xEF7D,0xEF7D,0xD6DC,0x2398,0x341A,0x343A,0x341A,0x341A,0x2C19,0x2C19,0xBE7C,0xF7BE,0xF79E,0x9CD3,0x0000,0x0000,0x0000, // row 23, 768 pixels -0x0000,0x0000,0x0000,0x39E7,0xDEDB,0xFFDF,0xF79E,0x9DFB,0x2C19,0x2C19,0x2C1A,0x341A,0x341A,0x2BB9,0x2B57,0x6459,0x74B9,0x2337,0x2BB9,0x341A,0x2C1A,0x2C19,0x2C19,0x2C19,0x9DFB,0xF79E,0xFFDF,0xDEDB,0x39E7,0x0000,0x0000,0x0000, // row 24, 800 pixels -0x0000,0x0000,0x0000,0x0000,0x632C,0xDEFB,0xFFDF,0xEF7D,0xB65C,0x3C39,0x2BF9,0x2C19,0x2C19,0x2BF9,0x2398,0x1B58,0x1B37,0x2398,0x2BF9,0x2C19,0x2BF9,0x2BF9,0x3439,0xB65C,0xEF7D,0xFFDF,0xDEFB,0x632C,0x0000,0x0000,0x0000,0x0000, // row 25, 832 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x73AE,0xDEFB,0xF7BE,0xF79E,0xDF1C,0x7D5A,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x23D9,0x23D9,0x2BF9,0x2BF9,0x2BF9,0x2BF9,0x7D5A,0xDF1C,0xF79E,0xF7BE,0xDEFB,0x73AE,0x0000,0x0000,0x0000,0x0000,0x0000, // row 26, 864 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x632C,0xDEDB,0xF79E,0xFFDF,0xEF7D,0xD6FC,0x9DFB,0x5CDA,0x4C9A,0x3419,0x3419,0x4C9A,0x5CDA,0x9DFB,0xD6FC,0xEF7D,0xFFDF,0xF79E,0xDEDB,0x632C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 27, 896 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x4208,0x94B2,0xDEFB,0xF7BE,0xFFDF,0xF7BE,0xF79E,0xEF7D,0xEF5D,0xEF5D,0xEF7D,0xF79E,0xF7BE,0xFFDF,0xF7BE,0xDEFB,0x94B2,0x4208,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 28, 928 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x528A,0xA534,0xDEDB,0xE73C,0xF79E,0xF7BE,0xF7BE,0xF7BE,0xF7BE,0xF79E,0xE73C,0xDEDB,0xA534,0x528A,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 29, 960 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x18C3,0x5AEB,0x8C71,0xAD55,0xBDD7,0xBDD7,0xAD55,0x8C71,0x5AEB,0x18C3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 30, 992 pixels -0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000}; // row 31, 1024 pixels diff --git a/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino b/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino new file mode 100644 index 0000000..427cb6a --- /dev/null +++ b/examples/480 x 320/Keypad_480x320/Keypad_480x320.ino @@ -0,0 +1,287 @@ +/* + The TFT_eSPI library incorporates an Adafruit_GFX compatible + button handling class, this sketch is based on the Arduin-o-phone + example. + + This example diplays a keypad where numbers can be entered and + send to the Serial Monitor window. + + The sketch has been tested on the ESP8266 (which supports SPIFFS) + + The minimum screen size is 320 x 240 as that is the keypad size. + + TOUCH_CS and SPI_TOUCH_FREQUENCY must be defined in the User_Setup.h file + for the touch functions to do anything. +*/ + +// The SPIFFS (FLASH filing system) is used to hold touch screen +// calibration data + +#include "FS.h" + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +// This is the file name used to store the calibration data +// You can change this to create new calibration files. +// The SPIFFS file name must start with "/". +#define CALIBRATION_FILE "/TouchCalData2" + +// Set REPEAT_CAL to true instead of false to run calibration +// again, otherwise it will only be done once. +// Repeat calibration if you change the screen rotation. +#define REPEAT_CAL false + +// Keypad start position, key sizes and spacing +#define KEY_X 40 // Centre of key +#define KEY_Y 96 +#define KEY_W 62 // Width and height +#define KEY_H 30 +#define KEY_SPACING_X 18 // X and Y gap +#define KEY_SPACING_Y 20 +#define KEY_TEXTSIZE 1 // Font size multiplier + +// Using two fonts since numbers are nice when bold +#define LABEL1_FONT &FreeSansOblique12pt7b // Key label font 1 +#define LABEL2_FONT &FreeSansBold12pt7b // Key label font 2 + +// Numeric display box size and location +#define DISP_X 1 +#define DISP_Y 10 +#define DISP_W 238 +#define DISP_H 50 +#define DISP_TSIZE 3 +#define DISP_TCOLOR TFT_CYAN + +// Number length, buffer for storing it and character index +#define NUM_LEN 12 +char numberBuffer[NUM_LEN + 1] = ""; +uint8_t numberIndex = 0; + +// We have a status line for messages +#define STATUS_X 120 // Centred on this +#define STATUS_Y 65 + +// Create 15 keys for the keypad +char keyLabel[15][5] = {"New", "Del", "Send", "1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "#" }; +uint16_t keyColor[15] = {TFT_RED, TFT_DARKGREY, TFT_DARKGREEN, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE, + TFT_BLUE, TFT_BLUE, TFT_BLUE + }; + +// Invoke the TFT_eSPI button class and create all the button objects +TFT_eSPI_Button key[15]; + +//------------------------------------------------------------------------------------------ + +void setup() { + // Use serial port + Serial.begin(9600); + + // Initialise the TFT screen + tft.init(); + + // Set the rotation before we calibrate + tft.setRotation(1); + + // Calibrate the touch screen and retrieve the scaling factors + touch_calibrate(); + + // Clear the screen + tft.fillScreen(TFT_BLACK); + + // Draw keypad background + tft.fillRect(0, 0, 240, 320, TFT_DARKGREY); + + // Draw number display area and frame + tft.fillRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_BLACK); + tft.drawRect(DISP_X, DISP_Y, DISP_W, DISP_H, TFT_WHITE); + + // Draw keypad + drawKeypad(); +} + +//------------------------------------------------------------------------------------------ + +void loop(void) { + uint16_t t_x = 0, t_y = 0; // To store the touch coordinates + + // Pressed will be set true is there is a valid touch on the screen + boolean pressed = tft.getTouch(&t_x, &t_y); + + // / Check if any key coordinate boxes contain the touch coordinates + for (uint8_t b = 0; b < 15; b++) { + if (pressed && key[b].contains(t_x, t_y)) { + key[b].press(true); // tell the button it is pressed + } else { + key[b].press(false); // tell the button it is NOT pressed + } + } + + // Check if any key has changed state + for (uint8_t b = 0; b < 15; b++) { + + if (b < 3) tft.setFreeFont(LABEL1_FONT); + else tft.setFreeFont(LABEL2_FONT); + + if (key[b].justReleased()) key[b].drawButton(); // draw normal + + if (key[b].justPressed()) { + key[b].drawButton(true); // draw invert + + // if a numberpad button, append the relevant # to the numberBuffer + if (b >= 3) { + if (numberIndex < NUM_LEN) { + numberBuffer[numberIndex] = keyLabel[b][0]; + numberIndex++; + numberBuffer[numberIndex] = 0; // zero terminate + } + status(""); // Clear the old status + } + + // Del button, so delete last char + if (b == 1) { + numberBuffer[numberIndex] = 0; + if (numberIndex > 0) { + numberIndex--; + numberBuffer[numberIndex] = 0;//' '; + } + status(""); // Clear the old status + } + + if (b == 2) { + status("Sent value to serial port"); + Serial.println(numberBuffer); + } + // we dont really check that the text field makes sense + // just try to call + if (b == 0) { + status("Value cleared"); + numberIndex = 0; // Reset index to 0 + numberBuffer[numberIndex] = 0; // Place null in buffer + } + + // Update the number display field + tft.setTextDatum(TL_DATUM); // Use top left corner as text coord datum + tft.setFreeFont(&FreeSans18pt7b); // Choose a nicefont that fits box + tft.setTextColor(DISP_TCOLOR); // Set the font colour + + // Draw the string, the value returned is the width in pixels + int xwidth = tft.drawString(numberBuffer, DISP_X + 4, DISP_Y + 12); + + // Now cover up the rest of the line up by drawing a black rectangle. No flicker this way + // but it will not work with italic or oblique fonts due to character overlap. + tft.fillRect(DISP_X + 4 + xwidth, DISP_Y + 1, DISP_W - xwidth - 5, DISP_H - 2, TFT_BLACK); + + delay(10); // UI debouncing + } + } +} + +//------------------------------------------------------------------------------------------ + +void drawKeypad() +{ + // Draw the keys + for (uint8_t row = 0; row < 5; row++) { + for (uint8_t col = 0; col < 3; col++) { + uint8_t b = col + row * 3; + + if (b < 3) tft.setFreeFont(LABEL1_FONT); + else tft.setFreeFont(LABEL2_FONT); + + key[b].initButton(&tft, KEY_X + col * (KEY_W + KEY_SPACING_X), + KEY_Y + row * (KEY_H + KEY_SPACING_Y), // x, y, w, h, outline, fill, text + KEY_W, KEY_H, TFT_WHITE, keyColor[b], TFT_WHITE, + keyLabel[b], KEY_TEXTSIZE); + key[b].drawButton(); + } + } +} + +//------------------------------------------------------------------------------------------ + +void touch_calibrate() +{ + uint16_t calData[5]; + uint8_t calDataOK = 0; + + // check file system exists + if (!SPIFFS.begin()) { + Serial.println("Formating file system"); + SPIFFS.format(); + SPIFFS.begin(); + } + + // check if calibration file exists and size is correct + if (SPIFFS.exists(CALIBRATION_FILE)) { + if (REPEAT_CAL) + { + // Delete if we want to re-calibrate + SPIFFS.remove(CALIBRATION_FILE); + } + else + { + File f = SPIFFS.open(CALIBRATION_FILE, "r"); + if (f) { + if (f.readBytes((char *)calData, 14) == 14) + calDataOK = 1; + f.close(); + } + } + } + + if (calDataOK && !REPEAT_CAL) { + // calibration data valid + tft.setTouch(calData); + } else { + // data not valid so recalibrate + tft.fillScreen(TFT_BLACK); + tft.setCursor(20, 0); + tft.setTextFont(2); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + tft.println("Touch corners as indicated"); + + tft.setTextFont(1); + tft.println(); + + if (REPEAT_CAL) { + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Set REPEAT_CAL to false to stop this running again!"); + } + + tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Calibration complete!"); + + // store data + File f = SPIFFS.open(CALIBRATION_FILE, "w"); + if (f) { + f.write((const unsigned char *)calData, 14); + f.close(); + } + } +} + +//------------------------------------------------------------------------------------------ + +// Print something in the mini status bar +void status(const char *msg) { + tft.setTextPadding(240); + //tft.setCursor(STATUS_X, STATUS_Y); + tft.setTextColor(TFT_WHITE, TFT_DARKGREY); + tft.setTextFont(0); + tft.setTextDatum(TC_DATUM); + tft.setTextSize(1); + tft.drawString(msg, STATUS_X, STATUS_Y); +} + +//------------------------------------------------------------------------------------------ + diff --git a/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino b/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino index 39232a0..f8ebcb1 100644 --- a/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino +++ b/examples/480 x 320/TFT_flash_jpg/TFT_flash_jpg.ino @@ -23,9 +23,6 @@ TFT_eSPI tft = TFT_eSPI(); // JPEG decoder library #include -// Chip Select Pin for SD card -#define SD_CS 53 - // Return the minimum of two values a and b #define minimum(a,b) (((a) < (b)) ? (a) : (b)) @@ -146,20 +143,42 @@ void renderJPEG(int xpos, int ypos) { int mcu_x = JpegDec.MCUx * mcu_w + xpos; // Calculate coordinates of top left corner of current MCU int mcu_y = JpegDec.MCUy * mcu_h + ypos; - // check if the image block size needs to be changed for the right and bottom edges + // check if the image block size needs to be changed for the right edge if (mcu_x + mcu_w <= max_x) win_w = mcu_w; else win_w = min_w; + + // check if the image block size needs to be changed for the bottom edge if (mcu_y + mcu_h <= max_y) win_h = mcu_h; else win_h = min_h; + // copy pixels into a contiguous block + if (win_w != mcu_w) + { + uint16_t *cImg; + int p = 0; + cImg = pImg + win_w; + for (int h = 1; h < win_h; h++) + { + p += mcu_w; + for (int w = 0; w < win_w; w++) + { + *cImg = *(pImg + w + p); + cImg++; + } + } + } + // calculate how many pixels must be drawn uint32_t mcu_pixels = win_w * win_h; + tft.startWrite(); + // draw image MCU block only if it will fit on the screen if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height()) { + // Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1) - tft.setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1); + tft.setAddrWindow(mcu_x, mcu_y, win_w, win_h); // Write all MCU pixels to the TFT window while (mcu_pixels--) { @@ -169,6 +188,8 @@ void renderJPEG(int xpos, int ypos) { } else if ( (mcu_y + win_h) >= tft.height()) JpegDec.abort(); // Image has run off bottom of screen so abort decoding + + tft.endWrite(); } // calculate how long it took to draw the image diff --git a/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino b/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino index ebed42b..d4d8c2f 100644 --- a/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino +++ b/examples/480 x 320/TFT_ring_meter/TFT_ring_meter.ino @@ -251,8 +251,10 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) + tft.startWrite(); + // Set up a window the right size to stream pixels into - tft.setWindow(x, y, x + width - 1, y + height - 1); + tft.setAddrWindow(x, y, width, height); // Work out the number whole buffers to send uint16_t nb = ((uint16_t)height * width) / BUFF_SIZE; @@ -273,5 +275,7 @@ void drawIcon(const unsigned short* icon, int16_t x, int16_t y, int8_t width, in for (int i = 0; i < np; i++) pix_buffer[i] = pgm_read_word(&icon[nb * BUFF_SIZE + i]); tft.pushColors(pix_buffer, np); } + + tft.endWrite(); } diff --git a/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino new file mode 100644 index 0000000..f0b14d8 --- /dev/null +++ b/examples/480 x 320/Touch_Controller_Demo/Touch_Controller_Demo.ino @@ -0,0 +1,76 @@ +#include "FS.h" +#include +#include +TFT_eSPI tft = TFT_eSPI(); + +#define CALIBRATION_FILE "/calibrationData" + +void setup(void) { + uint16_t calibrationData[5]; + uint8_t calDataOK = 0; + + Serial.begin(115200); + Serial.println("starting"); + + tft.init(); + + tft.setRotation(3); + tft.fillScreen((0xFFFF)); + + tft.setCursor(20, 0, 2); + tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextSize(1); + tft.println("calibration run"); + + // check file system + if (!SPIFFS.begin()) { + Serial.println("formating file system"); + + SPIFFS.format(); + SPIFFS.begin(); + } + + // check if calibration file exists + if (SPIFFS.exists(CALIBRATION_FILE)) { + File f = SPIFFS.open(CALIBRATION_FILE, "r"); + if (f) { + if (f.readBytes((char *)calibrationData, 14) == 14) + calDataOK = 1; + f.close(); + } + } + if (calDataOK) { + // calibration data valid + tft.setTouch(calibrationData); + } else { + // data not valid. recalibrate + tft.calibrateTouch(calibrationData, TFT_WHITE, TFT_RED, 15); + // store data + File f = SPIFFS.open(CALIBRATION_FILE, "w"); + if (f) { + f.write((const unsigned char *)calibrationData, 14); + f.close(); + } + } + + tft.fillScreen((0xFFFF)); + +} + +void loop() { + uint16_t x, y; + static uint16_t color; + + if (tft.getTouch(&x, &y)) { + + tft.setCursor(5, 5, 2); + tft.printf("x: %i ", x); + tft.setCursor(5, 20, 2); + tft.printf("y: %i ", y); + + tft.drawPixel(x, y, color); + color += 155; + } +} + + + diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg new file mode 100644 index 0000000..a53afef Binary files /dev/null and b/examples/Generic/ESP32_SDcard_jpeg/Data/Baboon40.jpg differ diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/EagleEye.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/EagleEye.jpg new file mode 100644 index 0000000..240b7ef Binary files /dev/null and b/examples/Generic/ESP32_SDcard_jpeg/Data/EagleEye.jpg differ diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/Mouse480.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/Mouse480.jpg new file mode 100644 index 0000000..9cab6a7 Binary files /dev/null and b/examples/Generic/ESP32_SDcard_jpeg/Data/Mouse480.jpg differ diff --git a/examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg b/examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg new file mode 100644 index 0000000..183b98f Binary files /dev/null and b/examples/Generic/ESP32_SDcard_jpeg/Data/lena20k.jpg differ diff --git a/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino b/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino new file mode 100644 index 0000000..9cc8b02 --- /dev/null +++ b/examples/Generic/ESP32_SDcard_jpeg/ESP32_SDcard_jpeg.ino @@ -0,0 +1,268 @@ +// This sketch if for an ESP32, it draws Jpeg images pulled from an SD Card +// onto the TFT. + +// As well as the TFT_eSPI library you will need the JPEG Decoder library. +// A copy can be downloaded here, it is based on the library by Makoto Kurauchi. +// https://github.com/Bodmer/JPEGDecoder + +// Images on SD Card must be put in the root folder (top level) to be found +// Use the SD library examples to verify your SD Card interface works! + +// The example images used to test this sketch can be found in the library +// JPEGDecoder/extras folder +//---------------------------------------------------------------------------------------------------- + +#include + +#include +#include + +#include +TFT_eSPI tft = TFT_eSPI(); + +// JPEG decoder library +#include + +//#################################################################################################### +// Setup +//#################################################################################################### +void setup() { + Serial.begin(115200); + + // Set all chip selects high to avoid bus contention during initialisation of each peripheral + digitalWrite(22, HIGH); // Touch controller chip select (if used) + digitalWrite(15, HIGH); // TFT screen chip select + digitalWrite( 5, HIGH); // SD card chips select, must use GPIO 5 (ESP32 SS) + + tft.begin(); + + if (!SD.begin()) { + Serial.println("Card Mount Failed"); + return; + } + uint8_t cardType = SD.cardType(); + + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.print("SD Card Type: "); + if (cardType == CARD_MMC) { + Serial.println("MMC"); + } else if (cardType == CARD_SD) { + Serial.println("SDSC"); + } else if (cardType == CARD_SDHC) { + Serial.println("SDHC"); + } else { + Serial.println("UNKNOWN"); + } + + uint64_t cardSize = SD.cardSize() / (1024 * 1024); + Serial.printf("SD Card Size: %lluMB\n", cardSize); + + Serial.println("initialisation done."); +} + +//#################################################################################################### +// Main loop +//#################################################################################################### +void loop() { + + tft.setRotation(2); // portrait + tft.fillScreen(random(0xFFFF)); + + // The image is 300 x 300 pixels so we do some sums to position image in the middle of the screen! + // Doing this by reading the image width and height from the jpeg info is left as an exercise! + int x = (tft.width() - 300) / 2 - 1; + int y = (tft.height() - 300) / 2 - 1; + + drawSdJpeg("/EagleEye.jpg", x, y); // This draws a jpeg pulled off the SD Card + delay(2000); + + tft.setRotation(2); // portrait + tft.fillScreen(random(0xFFFF)); + drawSdJpeg("/Baboon40.jpg", 0, 0); // This draws a jpeg pulled off the SD Card + delay(2000); + + tft.setRotation(2); // portrait + tft.fillScreen(random(0xFFFF)); + drawSdJpeg("/lena20k.jpg", 0, 0); // This draws a jpeg pulled off the SD Card + delay(2000); + + tft.setRotation(1); // landscape + tft.fillScreen(random(0xFFFF)); + drawSdJpeg("/Mouse480.jpg", 0, 0); // This draws a jpeg pulled off the SD Card + + delay(2000); + + while(1); // Wait here +} + +//#################################################################################################### +// Draw a JPEG on the TFT pulled from SD Card +//#################################################################################################### +// xpos, ypos is top left corner of plotted image +void drawSdJpeg(const char *filename, int xpos, int ypos) { + + // Open the named file (the Jpeg decoder library will close it) + File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library + + if ( !jpegFile ) { + Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!"); + return; + } + + Serial.println("==========================="); + Serial.print("Drawing file: "); Serial.println(filename); + Serial.println("==========================="); + + // Use one of the following methods to initialise the decoder: + boolean decoded = JpegDec.decodeSdFile(jpegFile); // Pass the SD file handle to the decoder, + //boolean decoded = JpegDec.decodeSdFile(filename); // or pass the filename (String or character array) + + if (decoded) { + // print information about the image to the serial port + jpegInfo(); + // render the image onto the screen at given coordinates + jpegRender(xpos, ypos); + } + else { + Serial.println("Jpeg file format not supported!"); + } +} + +//#################################################################################################### +// Draw a JPEG on the TFT, images will be cropped on the right/bottom sides if they do not fit +//#################################################################################################### +// This function assumes xpos,ypos is a valid screen coordinate. For convenience images that do not +// fit totally on the screen are cropped to the nearest MCU size and may leave right/bottom borders. +void jpegRender(int xpos, int ypos) { + + //jpegInfo(); // Print information from the JPEG file (could comment this line out) + + uint16_t *pImg; + uint16_t mcu_w = JpegDec.MCUWidth; + uint16_t mcu_h = JpegDec.MCUHeight; + uint32_t max_x = JpegDec.width; + uint32_t max_y = JpegDec.height; + + bool swapBytes = tft.getSwapBytes(); + tft.setSwapBytes(true); + + // Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs) + // Typically these MCUs are 16x16 pixel blocks + // Determine the width and height of the right and bottom edge image blocks + uint32_t min_w = min(mcu_w, max_x % mcu_w); + uint32_t min_h = min(mcu_h, max_y % mcu_h); + + // save the current image block size + uint32_t win_w = mcu_w; + uint32_t win_h = mcu_h; + + // record the current time so we can measure how long it takes to draw an image + uint32_t drawTime = millis(); + + // save the coordinate of the right and bottom edges to assist image cropping + // to the screen size + max_x += xpos; + max_y += ypos; + + // Fetch data from the file, decode and display + while (JpegDec.read()) { // While there is more data in the file + pImg = JpegDec.pImage ; // Decode a MCU (Minimum Coding Unit, typically a 8x8 or 16x16 pixel block) + + // Calculate coordinates of top left corner of current MCU + int mcu_x = JpegDec.MCUx * mcu_w + xpos; + int mcu_y = JpegDec.MCUy * mcu_h + ypos; + + // check if the image block size needs to be changed for the right edge + if (mcu_x + mcu_w <= max_x) win_w = mcu_w; + else win_w = min_w; + + // check if the image block size needs to be changed for the bottom edge + if (mcu_y + mcu_h <= max_y) win_h = mcu_h; + else win_h = min_h; + + // copy pixels into a contiguous block + if (win_w != mcu_w) + { + uint16_t *cImg; + int p = 0; + cImg = pImg + win_w; + for (int h = 1; h < win_h; h++) + { + p += mcu_w; + for (int w = 0; w < win_w; w++) + { + *cImg = *(pImg + w + p); + cImg++; + } + } + } + + // calculate how many pixels must be drawn + uint32_t mcu_pixels = win_w * win_h; + + // draw image MCU block only if it will fit on the screen + if (( mcu_x + win_w ) <= tft.width() && ( mcu_y + win_h ) <= tft.height()) + tft.pushImage(mcu_x, mcu_y, win_w, win_h, pImg); + else if ( (mcu_y + win_h) >= tft.height()) + JpegDec.abort(); // Image has run off bottom of screen so abort decoding + } + + tft.setSwapBytes(swapBytes); + + showTime(millis() - drawTime); // These lines are for sketch testing only +} + +//#################################################################################################### +// Print image information to the serial port (optional) +//#################################################################################################### +// JpegDec.decodeFile(...) or JpegDec.decodeArray(...) must be called before this info is available! +void jpegInfo() { + + // Print information extracted from the JPEG file + Serial.println("JPEG image info"); + Serial.println("==============="); + Serial.print("Width :"); + Serial.println(JpegDec.width); + Serial.print("Height :"); + Serial.println(JpegDec.height); + Serial.print("Components :"); + Serial.println(JpegDec.comps); + Serial.print("MCU / row :"); + Serial.println(JpegDec.MCUSPerRow); + Serial.print("MCU / col :"); + Serial.println(JpegDec.MCUSPerCol); + Serial.print("Scan type :"); + Serial.println(JpegDec.scanType); + Serial.print("MCU width :"); + Serial.println(JpegDec.MCUWidth); + Serial.print("MCU height :"); + Serial.println(JpegDec.MCUHeight); + Serial.println("==============="); + Serial.println(""); +} + +//#################################################################################################### +// Show the execution time (optional) +//#################################################################################################### +// WARNING: for UNO/AVR legacy reasons printing text to the screen with the Mega might not work for +// sketch sizes greater than ~70KBytes because 16 bit address pointers are used in some libraries. + +// The Due will work fine with the HX8357_Due library. + +void showTime(uint32_t msTime) { + //tft.setCursor(0, 0); + //tft.setTextFont(1); + //tft.setTextSize(2); + //tft.setTextColor(TFT_WHITE, TFT_BLACK); + //tft.print(F(" JPEG drawn in ")); + //tft.print(msTime); + //tft.println(F(" ms ")); + Serial.print(F(" JPEG drawn in ")); + Serial.print(msTime); + Serial.println(F(" ms ")); +} + diff --git a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino index 0e3654e..4d5d4e7 100644 --- a/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino +++ b/examples/Generic/ESP8266_uncannyEyes/ESP8266_uncannyEyes.ino @@ -141,7 +141,7 @@ void drawEye( // Renders one eye. Inputs must be pre-clipped & valid. // reset on each frame here in case of an SPI glitch. //eye[e].tft.setAddrWindow(319-127, 0, 319, 127); - eye[e].tft.setAddrWindow(0, 0, 127, 127); + eye[e].tft.setAddrWindow(0, 0, 128, 128); //digitalWrite(eye[e].cs, LOW); // Chip select diff --git a/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino new file mode 100644 index 0000000..67deb9a --- /dev/null +++ b/examples/Generic/Local_Custom_Fonts/Local_Custom_Fonts.ino @@ -0,0 +1,121 @@ +/* + Example for TFT_eSPI library + + This example shows the use of a Adafruit_GFX custom font with a + character code range of 32 - 255, this means accented characters + (amongst others) are available. + + The custom font file is attached to this sketch as a header file. The + font data has been created following the instructions here: + https://www.youtube.com/watch?v=L8MmTISmwZ8 + + Note that online converters for Adafruit_GFX compatible fonts are + available but these typically only use characters in the range 32-127, + and thus do not include the accented characters. These online converters + can however still be used with this sketch but the example characters + used must be changed. + + The Arduino IDE uses UTF8 encoding for these characters. The TFT_eSPI + library also expects characters in the range 128 to 255 to be UTF-8 + encoded. See link here for details: + + https://playground.arduino.cc/Code/UTF-8 + + To sumarise, UTF-8 characters are encoded as mor than 1 byte so care must + be taken: + + char c = 'µ'; // Wrong + char bad[4] = "5µA"; // Wrong + char good[] = "5µA"; // Good + String okay = "5µA"; // Good + + Created by Bodmer 08/02/19 + + Make sure LOAD_GFXFF is defined in the used User_Setup file + within the library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ###### TO SELECT YOUR DISPLAY TYPE, PINS USED AND ENABLE FONTS ###### + ######################################################################### +*/ + +#define TEST_TEXT "ßäöü ñâàå" // Text that will be printed on screen in the font +//#define TEST_TEXT "Hello" // Text that will be printed on screen in the font + +#include "SPI.h" +#include "TFT_eSPI.h" + +// The custom font file attached to this sketch must be included +#include "MyFont.h" + +// Stock font and GFXFF reference handle +#define GFXFF 1 + +// Easily remembered name for the font +#define MYFONT32 &myFont32pt8b + +// Use hardware SPI +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + +} + +void loop() { + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Show custom fonts + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + // Where font sizes increase the screen is not cleared as the larger fonts overwrite + // the smaller one with the background colour. + + // We can set the text datum to be Top, Middle, Bottom vertically and Left, Centre + // and Right horizontally. These are the text datums that can be used: + // TL_DATUM = Top left (default) + // TC_DATUM = Top centre + // TR_DATUM = Top right + // ML_DATUM = Middle left + // MC_DATUM = Middle centre <<< This is used below + // MR_DATUM = Middle right + // BL_DATUM = Bottom left + // BC_DATUM = Bottom centre + // BR_DATUM = Bottom right + // L_BASELINE = Left character baseline (Line the 'A' character would sit on) + // C_BASELINE = Centre character baseline + // R_BASELINE = Right character baseline + + //Serial.println(); + + // Set text datum to middle centre (MC_DATUM) + tft.setTextDatum(MC_DATUM); + + // Set text colour to white with black background + // Unlike the stock Adafruit_GFX library, the TFT_eSPI library DOES optionally draw + // the background colour for the custom and Free Fonts when using drawString() + tft.setTextColor(TFT_WHITE, TFT_BLACK); // White characters on black background + //tft.setTextColor(TFT_WHITE); // or white characters, no background + + tft.fillScreen(TFT_BLUE); // Clear screen + tft.setFreeFont(MYFONT32); // Select the font + tft.drawString("MyFont 32", 160, 60, GFXFF); // Print the name of the font + tft.setFreeFont(MYFONT32); // Select the font + tft.drawString(TEST_TEXT, 160, 140, GFXFF); // Print the test text in the custom font + delay(2000); + + // Setting textDatum does nothing when using tft.print + tft.fillScreen(TFT_BLUE); // Clear screen + tft.setCursor(0,60); // To be compatible with Adafruit_GFX the cursor datum is always bottom left + tft.print("âäàå"); // Using tft.print means text background is NEVER rendered + delay(2000); + + // Reset text padding to zero (default) + tft.setTextPadding(0); +} diff --git a/examples/Generic/Local_Custom_Fonts/MyFont.h b/examples/Generic/Local_Custom_Fonts/MyFont.h new file mode 100644 index 0000000..da5ee55 --- /dev/null +++ b/examples/Generic/Local_Custom_Fonts/MyFont.h @@ -0,0 +1,3366 @@ +// If you follow the tutorial here: +// https://www.youtube.com/watch?v=L8MmTISmwZ8 +// do not forget the names must be edited to remove the Windows file path. + +// I had to edit lines 8, 3135, 3361-3363 in this file + + +const uint8_t myFont32pt8bBitmaps[] PROGMEM = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xBF, 0xCF, 0xE7, 0xF3, + 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0x8F, 0xC7, 0xE1, 0xF0, 0xF8, 0x7C, + 0x3E, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF8, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, + 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, + 0xFF, 0xC3, 0xFF, 0x7F, 0xC3, 0xFF, 0x7F, 0xC1, 0xFE, 0x7F, 0x81, 0xFE, + 0x7F, 0x81, 0xFE, 0x7F, 0x81, 0xFE, 0x3F, 0x81, 0xFE, 0x3F, 0x80, 0xFE, + 0x3F, 0x80, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, + 0x0F, 0xE0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x1F, 0xE0, + 0x01, 0xFC, 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x00, 0xFE, 0x03, 0xF8, + 0x00, 0x7F, 0x01, 0xFC, 0x00, 0x3F, 0x81, 0xFE, 0x00, 0x1F, 0x80, 0xFE, + 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7F, 0x01, 0xFC, 0x00, 0x3F, 0x81, + 0xFC, 0x00, 0x3F, 0x80, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0xE0, + 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x1F, 0xC0, 0x03, 0xF8, + 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, + 0xF0, 0x1F, 0xC0, 0x03, 0xF8, 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xF0, 0x00, + 0xFE, 0x03, 0xF8, 0x00, 0x7F, 0x03, 0xF8, 0x00, 0x7F, 0x01, 0xFC, 0x00, + 0x3F, 0x80, 0xFE, 0x00, 0x1F, 0xC0, 0x7F, 0x00, 0x0F, 0xE0, 0x3F, 0x80, + 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x07, 0xC0, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0xFC, 0x00, + 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF8, 0x03, + 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, + 0x7F, 0xFF, 0x0F, 0xF9, 0xF3, 0xFC, 0x3F, 0xC7, 0xCF, 0xF9, 0xFE, 0x1F, + 0x1F, 0xE7, 0xF8, 0x7C, 0x78, 0x1F, 0xE1, 0xF0, 0x00, 0x7F, 0x87, 0xC0, + 0x00, 0xFF, 0x1F, 0x00, 0x03, 0xFC, 0x7C, 0x00, 0x0F, 0xFD, 0xF0, 0x00, + 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xE0, 0x00, 0x7D, 0xFF, 0xC0, 0x01, 0xF1, 0xFF, 0x00, 0x07, 0xC3, + 0xFC, 0x00, 0x1F, 0x0F, 0xF0, 0xF0, 0x7C, 0x1F, 0xFF, 0xE1, 0xF0, 0x7F, + 0xFF, 0x87, 0xC1, 0xFD, 0xFE, 0x1F, 0x0F, 0xF7, 0xFC, 0x7C, 0x3F, 0xDF, + 0xF9, 0xF1, 0xFF, 0x3F, 0xF7, 0xCF, 0xF8, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, + 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, + 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x03, 0xF8, 0x00, 0x00, 0x3F, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0x80, + 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xF0, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFC, 0x00, 0x1F, 0xC7, 0xF8, 0x00, 0x7E, + 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x1F, 0x80, 0x03, 0xF8, 0x3F, 0x80, 0x0F, + 0xC0, 0x00, 0xFE, 0x07, 0xE0, 0x03, 0xF0, 0x00, 0x3F, 0x81, 0xFC, 0x01, + 0xF8, 0x00, 0x0F, 0xE0, 0x7F, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x1F, 0xC0, + 0x3F, 0x00, 0x00, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x00, 0x3F, 0x01, 0xFC, + 0x07, 0xE0, 0x00, 0x0F, 0xE0, 0x7F, 0x01, 0xF8, 0x00, 0x03, 0xF8, 0x1F, + 0x80, 0xFC, 0x00, 0x00, 0xFE, 0x0F, 0xE0, 0x3F, 0x00, 0x00, 0x3F, 0x83, + 0xF8, 0x1F, 0x80, 0x00, 0x07, 0xF1, 0xFE, 0x07, 0xE0, 0x00, 0x01, 0xFF, + 0xFF, 0x03, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xE0, 0x7E, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x1F, 0x80, 0x00, 0x00, + 0x0F, 0xE0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF0, 0x07, 0xF0, + 0x00, 0x00, 0x01, 0xF8, 0x07, 0xFF, 0x00, 0x00, 0x00, 0x7E, 0x07, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0x03, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xC0, 0xFF, + 0xFF, 0x00, 0x00, 0x07, 0xE0, 0x7F, 0x8F, 0xE0, 0x00, 0x01, 0xF8, 0x1F, + 0xC3, 0xF8, 0x00, 0x00, 0xFC, 0x07, 0xE0, 0x7F, 0x00, 0x00, 0x3F, 0x03, + 0xF8, 0x1F, 0xC0, 0x00, 0x1F, 0x80, 0xFE, 0x07, 0xF0, 0x00, 0x07, 0xE0, + 0x3F, 0x81, 0xFC, 0x00, 0x03, 0xF0, 0x0F, 0xE0, 0x7F, 0x00, 0x00, 0xFC, + 0x03, 0xF8, 0x1F, 0xC0, 0x00, 0x7E, 0x00, 0xFE, 0x07, 0xF0, 0x00, 0x1F, + 0x80, 0x3F, 0x81, 0xFC, 0x00, 0x0F, 0xC0, 0x0F, 0xE0, 0x7F, 0x00, 0x03, + 0xF0, 0x01, 0xF8, 0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x7F, 0x0F, 0xE0, 0x00, + 0x7E, 0x00, 0x1F, 0xC3, 0xF8, 0x00, 0x3F, 0x00, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x07, 0xE0, 0x00, 0x1F, 0xFF, 0x80, + 0x01, 0xF8, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0xFC, 0x00, 0x00, 0x1F, 0xC0, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0xF0, 0x00, + 0x07, 0xFE, 0x0F, 0xF8, 0x00, 0x07, 0xFE, 0x03, 0xFC, 0x00, 0x03, 0xFE, + 0x00, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x80, 0x3F, + 0x80, 0x00, 0x3F, 0xE0, 0x3F, 0xC0, 0x00, 0x1F, 0xF0, 0x1F, 0xE0, 0x00, + 0x0F, 0xFC, 0x3F, 0xE0, 0x00, 0x03, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, + 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, + 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x82, 0x00, 0x0F, 0xFE, 0xFF, 0xE1, + 0xF8, 0x0F, 0xFE, 0x3F, 0xF0, 0xFF, 0x0F, 0xFC, 0x1F, 0xFC, 0xFF, 0x87, + 0xFC, 0x07, 0xFF, 0x7F, 0x87, 0xFE, 0x01, 0xFF, 0xFF, 0xC3, 0xFE, 0x00, + 0x7F, 0xFF, 0xE1, 0xFF, 0x00, 0x1F, 0xFF, 0xE0, 0xFF, 0x80, 0x07, 0xFF, + 0xF0, 0x7F, 0xC0, 0x03, 0xFF, 0xF0, 0x3F, 0xE0, 0x00, 0xFF, 0xF8, 0x1F, + 0xF0, 0x00, 0x3F, 0xFC, 0x0F, 0xFC, 0x00, 0x3F, 0xFF, 0x07, 0xFF, 0x00, + 0x3F, 0xFF, 0xE1, 0xFF, 0xC0, 0x7F, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFF, 0xFC, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x3F, 0xC0, 0x3F, 0xFF, + 0xF8, 0x0F, 0xC0, 0x0F, 0xFF, 0xF0, 0x01, 0xC0, 0x00, 0x7F, 0xC0, 0x00, + 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xEF, 0xF7, 0xF3, 0xF9, 0xFC, 0xFE, 0x00, 0x3F, 0x00, 0x7E, 0x00, + 0xFE, 0x00, 0xFC, 0x01, 0xFC, 0x01, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x07, + 0xF0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xE0, 0x1F, 0xE0, 0x1F, 0xE0, 0x1F, + 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x7F, 0xC0, 0x7F, 0x80, 0x7F, + 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, 0x80, 0x7F, + 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x1F, 0xC0, 0x1F, + 0xE0, 0x1F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0xF0, 0x07, 0xF0, 0x03, + 0xF8, 0x03, 0xF8, 0x01, 0xF8, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0xFE, 0x00, + 0x7E, 0x00, 0x3F, 0xFC, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x3F, 0x00, 0x3F, + 0x80, 0x3F, 0x80, 0x1F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, + 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x07, 0xF8, 0x03, 0xF8, 0x03, 0xFC, 0x03, + 0xFC, 0x03, 0xFC, 0x03, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0xFE, 0x01, 0xFE, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFE, 0x01, + 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x03, 0xFC, 0x03, + 0xFC, 0x03, 0xFC, 0x03, 0xFC, 0x03, 0xF8, 0x07, 0xF8, 0x07, 0xF8, 0x07, + 0xF0, 0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0, 0x1F, 0xC0, 0x1F, + 0x80, 0x3F, 0x80, 0x3F, 0x00, 0x7F, 0x00, 0x7E, 0x00, 0xFC, 0x00, 0x00, + 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0xF8, + 0x01, 0x81, 0xE0, 0x67, 0xC7, 0x87, 0x9F, 0xDE, 0x7E, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0x00, 0x3F, 0x00, 0x01, 0xFE, 0x00, 0x0F, + 0xFC, 0x00, 0x7F, 0xF8, 0x03, 0xF3, 0xF0, 0x1F, 0x8F, 0xE0, 0xFE, 0x1F, + 0xC1, 0xF0, 0x3C, 0x01, 0xC0, 0xE0, 0x02, 0x01, 0x00, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, + 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, + 0xC3, 0xE1, 0xF0, 0xF0, 0xF9, 0xF9, 0xFC, 0xFC, 0x38, 0x18, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, + 0x00, 0x0F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7E, 0x00, 0x1F, 0x80, + 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0x07, + 0xF0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03, 0xF0, + 0x00, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xE0, 0x01, 0xF8, 0x00, + 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xFC, 0x00, 0x7F, + 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x00, + 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xFC, 0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, + 0xE0, 0x03, 0xF8, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, + 0xF0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8, + 0x3F, 0xF0, 0xFF, 0xE3, 0xFF, 0x01, 0xFF, 0x1F, 0xF0, 0x0F, 0xF8, 0xFF, + 0x80, 0x3F, 0xE7, 0xFC, 0x01, 0xFF, 0x7F, 0xC0, 0x0F, 0xFB, 0xFE, 0x00, + 0x7F, 0xDF, 0xF0, 0x01, 0xFE, 0xFF, 0x80, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, + 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, + 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0x80, + 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xDF, + 0xF0, 0x03, 0xFE, 0xFF, 0x80, 0x1F, 0xF3, 0xFE, 0x00, 0xFF, 0x9F, 0xF0, + 0x07, 0xFC, 0xFF, 0x80, 0x7F, 0xC7, 0xFE, 0x03, 0xFE, 0x1F, 0xF8, 0x7F, + 0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x80, + 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xF8, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0xFF, 0x00, + 0x0F, 0xF0, 0x01, 0xFF, 0x00, 0x3F, 0xF0, 0x07, 0xFF, 0x00, 0xFF, 0xF0, + 0x1F, 0xFF, 0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0x9F, 0xFF, 0xF1, 0xFF, 0xFE, 0x1F, + 0xFF, 0x81, 0xFF, 0xE0, 0x1F, 0xF8, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, + 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, + 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, + 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, + 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, + 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x00, + 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, + 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, + 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x3F, 0xF8, 0x3F, 0xF9, 0xFF, 0x80, 0x3F, + 0xF7, 0xFC, 0x00, 0xFF, 0xDF, 0xF0, 0x01, 0xFF, 0x7F, 0xC0, 0x07, 0xFD, + 0xFE, 0x00, 0x1F, 0xF0, 0xF8, 0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x0F, + 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x1F, 0xF8, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x01, 0xFF, 0x80, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x03, + 0xFF, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x07, 0xFE, + 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, + 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x1F, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, + 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x01, 0xFF, + 0xFF, 0xFE, 0x07, 0xFF, 0xFF, 0xF8, 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0x80, + 0xFF, 0xC7, 0xFC, 0x01, 0xFF, 0x1F, 0xF0, 0x03, 0xFC, 0x7F, 0x80, 0x0F, + 0xF0, 0x0E, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x40, + 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xC1, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFD, 0xFE, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x7F, 0xDF, + 0xF0, 0x03, 0xFF, 0x7F, 0xE0, 0x1F, 0xFC, 0xFF, 0xE0, 0xFF, 0xE3, 0xFF, + 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, + 0xFF, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xFC, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, + 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, + 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x03, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x01, + 0xFE, 0xFF, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x00, 0xFF, 0x3F, 0xC0, 0x00, + 0xFF, 0x1F, 0xE0, 0x00, 0xFF, 0x0F, 0xF0, 0x00, 0xFF, 0x07, 0xF8, 0x00, + 0x7F, 0x83, 0xFC, 0x00, 0x7F, 0x81, 0xFE, 0x00, 0x7F, 0x80, 0xFF, 0x00, + 0x7F, 0xC0, 0x7F, 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x3F, 0xC0, 0x1F, 0xE0, + 0x3F, 0xC0, 0x0F, 0xF0, 0x1F, 0xE0, 0x07, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x1F, + 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, + 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, + 0xFC, 0x0F, 0xFF, 0xFF, 0xF0, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x07, 0xF9, 0xFC, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0xFF, + 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, + 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x9F, 0xFC, 0x1F, + 0xFE, 0x7F, 0xC0, 0x1F, 0xF8, 0x3C, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF0, + 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, + 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0xFF, 0x9F, 0xF8, 0x07, 0xFE, 0x7F, 0xF0, + 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFE, 0x07, 0xFF, 0xFF, + 0xF8, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x01, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xE0, 0x07, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFE, 0x07, 0xFF, + 0xFF, 0xFC, 0x3F, 0xF8, 0x3F, 0xF0, 0xFF, 0xC0, 0x7F, 0xC7, 0xFE, 0x00, + 0xFF, 0x9F, 0xF0, 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0x81, 0xFF, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x1F, 0xC0, 0x0F, 0xF9, 0xFF, 0xE0, 0x3F, 0xEF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xE0, 0xFF, 0xEF, 0xFE, 0x01, + 0xFF, 0xBF, 0xF0, 0x03, 0xFE, 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0x7F, 0x80, 0x07, 0xFD, + 0xFF, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x7F, 0xDF, 0xF8, 0x01, 0xFE, 0x3F, + 0xF0, 0x0F, 0xF8, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, + 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xF8, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, + 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0x80, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFE, 0x00, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xFF, 0xC0, + 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x8F, 0xFE, 0x0F, 0xFC, 0x7F, 0xC0, + 0x3F, 0xE3, 0xFE, 0x00, 0xFF, 0x9F, 0xE0, 0x07, 0xFC, 0xFF, 0x00, 0x1F, + 0xE7, 0xF8, 0x00, 0xFF, 0x3F, 0xC0, 0x07, 0xF9, 0xFE, 0x00, 0x7F, 0x8F, + 0xF8, 0x03, 0xFC, 0x3F, 0xC0, 0x3F, 0xE1, 0xFF, 0x83, 0xFE, 0x07, 0xFF, + 0xFF, 0xE0, 0x1F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, + 0x00, 0x1F, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC1, + 0xFF, 0x83, 0xFF, 0x1F, 0xF0, 0x0F, 0xFC, 0xFF, 0x00, 0x3F, 0xEF, 0xF8, + 0x00, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xE0, 0x00, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xE0, 0x0F, 0xF9, 0xFF, + 0xC1, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, + 0xFE, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xC0, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x80, 0x7F, + 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xF8, 0x7F, 0xF0, + 0x7F, 0xF1, 0xFF, 0x00, 0xFF, 0xCF, 0xF8, 0x01, 0xFF, 0x3F, 0xE0, 0x03, + 0xFE, 0xFF, 0x80, 0x0F, 0xFB, 0xFE, 0x00, 0x3F, 0xEF, 0xF0, 0x00, 0xFF, + 0xBF, 0xE0, 0x03, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xF8, 0x01, 0xFF, 0xDF, 0xF0, 0x07, 0xFF, 0x7F, 0xF0, 0x7F, 0xFD, 0xFF, + 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, + 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0x7F, 0xC0, 0x7F, 0xF9, + 0xFF, 0x00, 0x7F, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x1E, 0x00, 0x3F, 0xE7, + 0xFC, 0x01, 0xFF, 0x9F, 0xF0, 0x07, 0xFC, 0x7F, 0xE0, 0x3F, 0xF0, 0xFF, + 0xC3, 0xFF, 0x83, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, + 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x7F, + 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xDF, 0xF7, 0xFD, 0xFF, 0x7F, 0xDF, + 0xF7, 0xFD, 0xFF, 0x7F, 0xC1, 0xE0, 0x78, 0x1E, 0x0F, 0x87, 0xC3, 0xF3, + 0xF8, 0x7C, 0x1E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFE, 0x00, + 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x3F, + 0xFF, 0x80, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x01, + 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x1E, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x80, 0x00, 0x00, 0x01, 0xC0, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, + 0xC0, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x0F, + 0xFE, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, + 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, + 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xE0, 0x03, + 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, + 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xE0, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFE, 0x00, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xF8, + 0x7F, 0xF8, 0x1F, 0xFC, 0x7F, 0xF0, 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, + 0x9F, 0xF0, 0x00, 0x3F, 0xDF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, + 0xF8, 0x78, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFC, + 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x7F, 0xF0, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, + 0x1F, 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x3F, 0xC0, + 0x0F, 0xE0, 0x00, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xFF, 0x0F, 0xF1, 0xFC, + 0x03, 0xFC, 0x03, 0xFF, 0xF1, 0xFE, 0x1F, 0xC0, 0x7F, 0x00, 0xFF, 0xFF, + 0x3F, 0xC1, 0xF8, 0x1F, 0xC0, 0x3F, 0xFF, 0xEF, 0xF0, 0x3F, 0x03, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x03, 0xF0, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x1F, 0xC0, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xC3, 0xF0, 0x1F, 0xFC, + 0x1F, 0xFF, 0x00, 0xF8, 0xFE, 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0x1F, + 0x80, 0xFF, 0x80, 0x0F, 0xF8, 0x03, 0xF3, 0xF0, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x7E, 0x7E, 0x07, 0xF8, 0x00, 0x3F, 0xE0, 0x0F, 0xDF, 0x80, 0xFF, + 0x00, 0x07, 0xF8, 0x01, 0xFB, 0xF0, 0x3F, 0xE0, 0x00, 0xFF, 0x00, 0x3E, + 0x7E, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x07, 0xCF, 0xC0, 0xFF, 0x00, 0x03, + 0xFC, 0x01, 0xF9, 0xF8, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x3F, 0x3F, 0x03, + 0xF8, 0x00, 0x0F, 0xE0, 0x07, 0xE7, 0xC0, 0xFF, 0x00, 0x03, 0xFC, 0x01, + 0xF8, 0xF8, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x7F, 0x1F, 0x03, 0xFE, 0x00, + 0x1F, 0xF0, 0x0F, 0xC3, 0xF0, 0x7F, 0xC0, 0x03, 0xFE, 0x03, 0xF8, 0x7E, + 0x07, 0xF8, 0x00, 0xFF, 0x80, 0xFE, 0x0F, 0xC0, 0xFF, 0x80, 0x3F, 0xF0, + 0x3F, 0xC1, 0xF8, 0x1F, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x3F, 0x03, 0xFF, + 0xFF, 0xFF, 0xC7, 0xFC, 0x03, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x7E, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, 0xC0, 0x7F, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFC, 0x07, 0xFF, 0xFB, 0xFF, 0xFC, 0x00, 0x1F, 0x80, + 0x7F, 0xFE, 0x7F, 0xFF, 0x00, 0x03, 0xF8, 0x07, 0xFF, 0x07, 0xFF, 0x80, + 0x00, 0x3F, 0x80, 0x1F, 0x80, 0x7F, 0x80, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xF8, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x0F, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0xFF, 0x80, 0x00, 0x00, 0x00, + 0x0F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0xE0, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x1F, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xE0, + 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0xFE, + 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0xDF, 0xF0, 0x00, + 0x00, 0x07, 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE3, 0xFE, 0x00, 0x00, + 0x03, 0xFF, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xC0, 0x00, 0x00, + 0xFF, 0x83, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x1F, 0xF8, 0x00, 0x00, 0x7F, + 0xC0, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0x00, 0x3F, 0xE0, + 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0x00, 0x7F, 0xC0, 0x00, 0x1F, 0xF8, 0x03, + 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0x07, 0xFC, 0x00, 0x7F, + 0xC0, 0x00, 0x7F, 0xC0, 0x03, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x80, + 0x00, 0x0F, 0xFC, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, + 0x01, 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x3F, 0xE0, 0x00, 0x00, + 0x3F, 0xE3, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x9F, 0xF8, 0x00, 0x00, 0x0F, + 0xFC, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0x80, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, + 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x7F, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0x80, 0x01, 0xFF, 0xE7, 0xFC, 0x00, 0x03, 0xFF, 0x3F, + 0xE0, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x03, + 0xFE, 0x7F, 0xC0, 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x00, 0xFF, 0x9F, 0xF0, + 0x00, 0x07, 0xF8, 0xFF, 0x80, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0x0F, 0xFC, + 0x3F, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, + 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, + 0xFF, 0x3F, 0xE0, 0x00, 0x3F, 0xFD, 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xF8, + 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, + 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, + 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x01, + 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, + 0xFF, 0xF8, 0x3F, 0xFC, 0x00, 0x7F, 0xF0, 0x7F, 0xF0, 0x00, 0x7F, 0xF1, + 0xFF, 0x80, 0x00, 0x7F, 0xE3, 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xFC, 0x00, + 0x00, 0xFF, 0xDF, 0xF8, 0x00, 0x00, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0x80, + 0x7F, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x00, + 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x30, 0x0F, 0xF8, 0x00, 0x00, 0x7C, 0x1F, 0xF0, 0x00, 0x00, + 0xFF, 0x3F, 0xF0, 0x00, 0x03, 0xFF, 0x7F, 0xE0, 0x00, 0x07, 0xFE, 0x7F, + 0xE0, 0x00, 0x1F, 0xF8, 0xFF, 0xC0, 0x00, 0x3F, 0xF0, 0xFF, 0xC0, 0x00, + 0xFF, 0xE1, 0xFF, 0xE0, 0x03, 0xFF, 0x81, 0xFF, 0xF0, 0x3F, 0xFF, 0x03, + 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, + 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFE, 0x00, + 0x3F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, + 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x80, 0x07, 0xFF, 0xC7, 0xFC, 0x00, 0x0F, + 0xFF, 0x3F, 0xE0, 0x00, 0x3F, 0xF9, 0xFF, 0x00, 0x00, 0xFF, 0xEF, 0xF8, + 0x00, 0x03, 0xFF, 0x7F, 0xC0, 0x00, 0x0F, 0xFB, 0xFE, 0x00, 0x00, 0x7F, + 0xDF, 0xF0, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xFC, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x3F, 0xF7, + 0xFC, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x01, + 0xFF, 0xCF, 0xF8, 0x00, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, + 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFE, + 0x07, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, + 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, + 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xC1, 0xFF, 0xC0, 0x00, 0x7F, + 0xF8, 0x7F, 0xE0, 0x00, 0x0F, 0xFE, 0x3F, 0xF0, 0x00, 0x01, 0xFF, 0x8F, + 0xFC, 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xE1, 0xFF, 0x80, + 0x00, 0x03, 0x80, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x1F, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xDF, + 0xF0, 0x00, 0x7F, 0xFF, 0xF7, 0xFC, 0x00, 0x00, 0x07, 0xFD, 0xFF, 0x80, + 0x00, 0x01, 0xFF, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, + 0x1F, 0xF3, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x7F, 0xE0, 0x00, 0x01, 0xFF, + 0x1F, 0xFE, 0x00, 0x01, 0xFF, 0xC3, 0xFF, 0xC0, 0x01, 0xFF, 0xF0, 0xFF, + 0xFE, 0x03, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, + 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFF, 0xE0, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, + 0xFC, 0x3E, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x80, 0x3F, 0xE7, 0xFC, + 0x03, 0xFF, 0x3F, 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, + 0xFC, 0x3F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xE0, + 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x1F, 0xF0, 0x00, 0xFF, + 0x80, 0x00, 0x1F, 0xFE, 0xFF, 0x80, 0x00, 0x3F, 0xFC, 0xFF, 0x80, 0x00, + 0x7F, 0xF8, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x01, 0xFF, 0xE0, + 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0xFF, 0x80, + 0x0F, 0xFF, 0x00, 0xFF, 0x80, 0x1F, 0xFE, 0x00, 0xFF, 0x80, 0x3F, 0xFC, + 0x00, 0xFF, 0x80, 0x7F, 0xF8, 0x00, 0xFF, 0x80, 0xFF, 0xF0, 0x00, 0xFF, + 0x81, 0xFF, 0xE0, 0x00, 0xFF, 0x83, 0xFF, 0xC0, 0x00, 0xFF, 0x87, 0xFF, + 0x80, 0x00, 0xFF, 0x8F, 0xFF, 0x00, 0x00, 0xFF, 0x9F, 0xFE, 0x00, 0x00, + 0xFF, 0xBF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, + 0xFF, 0x7F, 0xE0, 0x00, 0xFF, 0xFE, 0x7F, 0xF0, 0x00, 0xFF, 0xFC, 0x3F, + 0xF0, 0x00, 0xFF, 0xF8, 0x3F, 0xF8, 0x00, 0xFF, 0xF0, 0x1F, 0xFC, 0x00, + 0xFF, 0xE0, 0x1F, 0xFC, 0x00, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0xFF, 0x80, + 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x03, 0xFF, + 0x80, 0xFF, 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x01, 0xFF, 0xC0, 0xFF, + 0x80, 0x00, 0xFF, 0xE0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, + 0x7F, 0xF0, 0xFF, 0x80, 0x00, 0x7F, 0xF8, 0xFF, 0x80, 0x00, 0x3F, 0xF8, + 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0xFF, 0x80, 0x00, 0x1F, 0xFE, 0xFF, 0x80, + 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x03, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFF, + 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xEF, 0xFF, 0xFF, 0xF8, 0x01, + 0xFE, 0xFF, 0xFF, 0xBF, 0x80, 0x1F, 0xEF, 0xFF, 0xFB, 0xFC, 0x01, 0xFE, + 0xFF, 0xFF, 0xBF, 0xC0, 0x1F, 0xCF, 0xFF, 0xFB, 0xFC, 0x03, 0xFC, 0xFF, + 0xFF, 0x9F, 0xC0, 0x3F, 0xCF, 0xFF, 0xF9, 0xFE, 0x03, 0xFC, 0xFF, 0xFF, + 0x9F, 0xE0, 0x7F, 0x8F, 0xFF, 0xF9, 0xFE, 0x07, 0xF8, 0xFF, 0xFF, 0x8F, + 0xF0, 0x7F, 0x8F, 0xFF, 0xF8, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x8F, 0xF0, + 0xFF, 0x0F, 0xFF, 0xF8, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0x87, 0xF8, 0xFF, + 0x0F, 0xFF, 0xF8, 0x7F, 0x8F, 0xF0, 0xFF, 0xFF, 0x87, 0xF9, 0xFE, 0x0F, + 0xFF, 0xF8, 0x7F, 0x9F, 0xE0, 0xFF, 0xFF, 0x83, 0xFD, 0xFE, 0x0F, 0xFF, + 0xF8, 0x3F, 0xDF, 0xE0, 0xFF, 0xFF, 0x83, 0xFF, 0xFC, 0x0F, 0xFF, 0xF8, + 0x3F, 0xFF, 0xC0, 0xFF, 0xFF, 0x81, 0xFF, 0xFC, 0x0F, 0xFF, 0xF8, 0x1F, + 0xFF, 0xC0, 0xFF, 0xFF, 0x81, 0xFF, 0xF8, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF, + 0x80, 0xFF, 0xFF, 0x80, 0xFF, 0xF8, 0x0F, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, + 0xFF, 0xFF, 0x80, 0xFF, 0xF0, 0x0F, 0xFF, 0xF8, 0x0F, 0xFF, 0x00, 0xFF, + 0xFF, 0x80, 0x7F, 0xF0, 0x0F, 0xFF, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xFF, + 0x80, 0x7F, 0xE0, 0x0F, 0xFF, 0xF8, 0x07, 0xFE, 0x00, 0xFF, 0xFF, 0x80, + 0x3F, 0xE0, 0x0F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xF0, 0x01, + 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFE, + 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xEF, 0xFE, 0x03, 0xFF, 0xFC, + 0xFF, 0xC0, 0x7F, 0xFF, 0x9F, 0xFC, 0x0F, 0xFF, 0xF1, 0xFF, 0x81, 0xFF, + 0xFE, 0x1F, 0xF8, 0x3F, 0xFF, 0xC3, 0xFF, 0x87, 0xFF, 0xF8, 0x3F, 0xF0, + 0xFF, 0xFF, 0x07, 0xFF, 0x1F, 0xFF, 0xE0, 0x7F, 0xF3, 0xFF, 0xFC, 0x07, + 0xFE, 0x7F, 0xFF, 0x80, 0xFF, 0xEF, 0xFF, 0xF0, 0x0F, 0xFD, 0xFF, 0xFE, + 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, + 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x3F, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFE, 0x00, + 0x07, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xFE, + 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, + 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xC0, 0x7F, 0xFE, 0x03, 0xFF, 0xE0, + 0x01, 0xFF, 0xE0, 0x7F, 0xF0, 0x00, 0x1F, 0xFE, 0x1F, 0xFC, 0x00, 0x01, + 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x1F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, + 0x9F, 0xF8, 0x00, 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, + 0x00, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFB, 0xFE, 0x00, 0x00, 0x03, + 0xFF, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF8, + 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xC1, 0xFF, + 0xC0, 0x00, 0x7F, 0xF8, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x03, 0xFF, 0xF0, + 0x1F, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xCF, + 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x07, 0xFF, + 0xBF, 0xE0, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xE0, + 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xF3, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFC, + 0x0F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xC0, 0x7F, 0xFE, + 0x00, 0xFF, 0xF8, 0x00, 0x7F, 0xF8, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xE0, + 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0x03, 0xFF, 0x00, 0x00, 0x1F, 0xFC, 0x3F, + 0xF0, 0x00, 0x00, 0x7F, 0xE1, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x0F, 0xF8, + 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, + 0x00, 0x03, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xC0, 0x00, 0x00, + 0x1F, 0xF3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x9F, 0xF0, 0x00, 0x00, 0x07, + 0xFC, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xCF, + 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xF3, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x40, 0x0F, 0xF8, 0x7F, 0xE0, + 0x07, 0xC0, 0xFF, 0xC3, 0xFF, 0x00, 0x3F, 0x87, 0xFE, 0x0F, 0xFC, 0x03, + 0xFE, 0x7F, 0xE0, 0x7F, 0xF0, 0x1F, 0xFF, 0xFF, 0x03, 0xFF, 0xC0, 0x7F, + 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0x01, 0xFF, + 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x7F, 0xF8, 0x00, 0x03, 0xFF, 0x80, 0xFF, 0xC0, 0x00, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, + 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0x80, 0x00, + 0x1F, 0xF8, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0xFF, 0x80, 0x00, 0x1F, 0xF0, + 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, 0x00, 0x3F, 0xF0, 0xFF, 0x80, + 0x00, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, + 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, + 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0x81, 0xFF, 0xE0, 0x00, + 0xFF, 0x80, 0x7F, 0xF0, 0x00, 0xFF, 0x80, 0x3F, 0xF8, 0x00, 0xFF, 0x80, + 0x1F, 0xFC, 0x00, 0xFF, 0x80, 0x0F, 0xFE, 0x00, 0xFF, 0x80, 0x0F, 0xFF, + 0x00, 0xFF, 0x80, 0x07, 0xFF, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0x80, 0xFF, + 0x80, 0x03, 0xFF, 0xC0, 0xFF, 0x80, 0x01, 0xFF, 0xC0, 0xFF, 0x80, 0x00, + 0xFF, 0xE0, 0xFF, 0x80, 0x00, 0xFF, 0xF0, 0xFF, 0x80, 0x00, 0x7F, 0xF0, + 0xFF, 0x80, 0x00, 0x3F, 0xF8, 0xFF, 0x80, 0x00, 0x3F, 0xF8, 0xFF, 0x80, + 0x00, 0x1F, 0xFC, 0xFF, 0x80, 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x00, 0x0F, + 0xFE, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x01, + 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, 0xFE, 0x03, 0xFF, 0xC1, + 0xFF, 0x80, 0x07, 0xFF, 0x0F, 0xF8, 0x00, 0x1F, 0xF8, 0x7F, 0xC0, 0x00, + 0xFF, 0xC3, 0xFE, 0x00, 0x03, 0xFE, 0x1F, 0xF0, 0x00, 0x1F, 0xF8, 0xFF, + 0x80, 0x00, 0xFF, 0xC7, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x00, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x3F, + 0xF8, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0xF0, 0x00, 0x03, 0xFF, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xDF, 0xF0, 0x00, 0x03, 0xFE, + 0xFF, 0xC0, 0x00, 0x3F, 0xF7, 0xFF, 0x00, 0x03, 0xFF, 0x9F, 0xFC, 0x00, + 0x3F, 0xF8, 0xFF, 0xF8, 0x07, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, + 0xE0, 0x07, 0xFF, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, + 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xF7, 0xFF, 0x00, 0x1F, + 0xFC, 0xFF, 0xF8, 0x0F, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, + 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, + 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xDF, 0xF0, + 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x07, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x0F, 0xFC, 0x00, 0x00, 0xFF, + 0xC3, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x7F, 0xC0, 0x00, 0x0F, 0xF8, 0x1F, + 0xF8, 0x00, 0x07, 0xFE, 0x07, 0xFE, 0x00, 0x01, 0xFF, 0x80, 0xFF, 0x80, + 0x00, 0x7F, 0xC0, 0x3F, 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFC, 0x00, 0x0F, + 0xF8, 0x01, 0xFF, 0x80, 0x03, 0xFE, 0x00, 0x7F, 0xE0, 0x01, 0xFF, 0x80, + 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFF, 0x00, 0x1F, 0xF0, 0x00, 0xFF, + 0xC0, 0x0F, 0xFC, 0x00, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x07, 0xFE, 0x00, + 0xFF, 0x80, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x00, 0x3F, 0xE0, 0x1F, 0xF0, + 0x00, 0x0F, 0xFC, 0x07, 0xFC, 0x00, 0x03, 0xFF, 0x03, 0xFF, 0x00, 0x00, + 0x7F, 0xC0, 0xFF, 0x80, 0x00, 0x1F, 0xF8, 0x3F, 0xE0, 0x00, 0x07, 0xFE, + 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x87, 0xFC, 0x00, 0x00, 0x3F, 0xF1, 0xFF, + 0x00, 0x00, 0x07, 0xFC, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x3F, 0xE0, 0x00, + 0x00, 0x7F, 0xEF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, + 0xE0, 0x00, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x1F, + 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xF0, 0x00, 0x3F, 0xEF, 0xF8, 0x00, + 0x1F, 0xFE, 0x00, 0x07, 0xFD, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0xFF, + 0xBF, 0xE0, 0x00, 0x7F, 0xF8, 0x00, 0x3F, 0xF7, 0xFE, 0x00, 0x1F, 0xFF, + 0x80, 0x07, 0xFC, 0x7F, 0xC0, 0x03, 0xFF, 0xF0, 0x00, 0xFF, 0x8F, 0xF8, + 0x00, 0x7F, 0xFE, 0x00, 0x1F, 0xF1, 0xFF, 0x00, 0x0F, 0xFF, 0xC0, 0x03, + 0xFE, 0x3F, 0xE0, 0x03, 0xFF, 0xFC, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0x7F, + 0xFF, 0x80, 0x1F, 0xF0, 0x7F, 0xC0, 0x0F, 0xFF, 0xF0, 0x03, 0xFE, 0x0F, + 0xF8, 0x03, 0xFF, 0xFE, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, + 0x1F, 0xF0, 0x3F, 0xE0, 0x0F, 0xF7, 0xFC, 0x03, 0xFE, 0x03, 0xFE, 0x01, + 0xFE, 0x7F, 0x80, 0x7F, 0xC0, 0x7F, 0xC0, 0x7F, 0xCF, 0xF0, 0x0F, 0xF8, + 0x0F, 0xF8, 0x0F, 0xF1, 0xFF, 0x01, 0xFE, 0x01, 0xFF, 0x01, 0xFE, 0x3F, + 0xE0, 0x7F, 0xC0, 0x1F, 0xF0, 0x3F, 0xC3, 0xFC, 0x0F, 0xF8, 0x03, 0xFE, + 0x0F, 0xF8, 0x7F, 0x81, 0xFF, 0x00, 0x7F, 0xC1, 0xFE, 0x0F, 0xF8, 0x3F, + 0xC0, 0x0F, 0xF8, 0x3F, 0xC0, 0xFF, 0x0F, 0xF8, 0x00, 0xFF, 0x07, 0xF8, + 0x1F, 0xE1, 0xFF, 0x00, 0x1F, 0xF1, 0xFF, 0x03, 0xFC, 0x3F, 0xE0, 0x03, + 0xFE, 0x3F, 0xC0, 0x7F, 0xC7, 0xF8, 0x00, 0x7F, 0xC7, 0xF8, 0x07, 0xF8, + 0xFF, 0x00, 0x07, 0xF9, 0xFF, 0x00, 0xFF, 0x3F, 0xE0, 0x00, 0xFF, 0xBF, + 0xE0, 0x1F, 0xE7, 0xFC, 0x00, 0x1F, 0xF7, 0xF8, 0x03, 0xFE, 0xFF, 0x00, + 0x03, 0xFE, 0xFF, 0x00, 0x3F, 0xDF, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x07, + 0xFB, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x01, 0xFF, 0xFC, + 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x00, + 0x07, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x7F, 0xFE, 0x00, 0x00, + 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x80, 0x01, 0xFF, + 0xF0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x3F, 0xFC, + 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x7F, 0xF0, 0x00, + 0x00, 0xFF, 0xF0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x01, + 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF8, 0x00, 0x3F, 0xF0, + 0x00, 0x03, 0xFF, 0x0F, 0xFE, 0x00, 0x01, 0xFF, 0xC1, 0xFF, 0xC0, 0x00, + 0xFF, 0xE0, 0x3F, 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFE, 0x00, 0x1F, 0xFC, + 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x3F, 0xF0, 0x03, 0xFF, 0x00, 0x0F, + 0xFE, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x3F, 0xF0, + 0x3F, 0xF0, 0x00, 0x0F, 0xFE, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xCF, 0xFE, + 0x00, 0x00, 0x3F, 0xF3, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF, + 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x01, 0xFF, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, + 0x03, 0xFF, 0x7F, 0xF0, 0x00, 0x01, 0xFF, 0xCF, 0xFE, 0x00, 0x00, 0xFF, + 0xE1, 0xFF, 0xC0, 0x00, 0x3F, 0xF0, 0x7F, 0xF0, 0x00, 0x1F, 0xFC, 0x0F, + 0xFE, 0x00, 0x0F, 0xFE, 0x01, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x7F, 0xF0, + 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0xFF, 0xE0, 0x01, 0xFF, 0xC0, 0x3F, + 0xF8, 0x00, 0x7F, 0xF0, 0x1F, 0xFC, 0x00, 0x0F, 0xFE, 0x0F, 0xFE, 0x00, + 0x01, 0xFF, 0xC3, 0xFF, 0x80, 0x00, 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x0F, + 0xFE, 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x01, 0xFF, + 0xDF, 0xF8, 0x00, 0x00, 0x7F, 0xE7, 0xFF, 0x00, 0x00, 0x3F, 0xF8, 0xFF, + 0xE0, 0x00, 0x0F, 0xFC, 0x1F, 0xF8, 0x00, 0x07, 0xFE, 0x07, 0xFF, 0x00, + 0x03, 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x7F, + 0xE0, 0x07, 0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x0F, 0xFC, 0x00, + 0x1F, 0xF8, 0x07, 0xFE, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0x80, 0x00, 0xFF, + 0xC0, 0xFF, 0xC0, 0x00, 0x3F, 0xF8, 0x3F, 0xF0, 0x00, 0x07, 0xFE, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xC7, 0xFC, 0x00, 0x00, 0x3F, 0xF3, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, + 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x80, + 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, + 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, + 0xFC, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, + 0x0F, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x07, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, + 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xE0, + 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, + 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x3F, 0x80, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0xC0, + 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xF8, 0x00, + 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, + 0xC0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x01, 0xFC, + 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFE, 0x00, 0x3F, 0x80, + 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x03, 0xF0, 0x00, + 0xFC, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, + 0xC0, 0x07, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x03, 0xF8, + 0x00, 0x7E, 0x00, 0x1F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFE, 0x03, 0xFC, + 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, + 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, + 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, + 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, + 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, + 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, + 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x7F, 0xFC, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x00, 0x01, + 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0xFF, 0x7F, 0x80, 0x07, 0xFB, + 0xFC, 0x00, 0x7F, 0x8F, 0xF0, 0x03, 0xFC, 0x7F, 0x80, 0x3F, 0xC1, 0xFE, + 0x01, 0xFE, 0x0F, 0xF0, 0x1F, 0xE0, 0x7F, 0xC0, 0xFF, 0x01, 0xFE, 0x0F, + 0xF8, 0x0F, 0xF8, 0x7F, 0x80, 0x3F, 0xC7, 0xFC, 0x01, 0xFF, 0x3F, 0xC0, + 0x0F, 0xFB, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, + 0x07, 0xF0, 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x3F, 0xF8, + 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFC, + 0x1F, 0xF8, 0x1F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0xFF, 0x80, 0x1F, 0xF0, + 0x1E, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x01, 0xFF, 0x80, + 0x00, 0x1F, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFC, 0x07, + 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xE1, 0xFF, + 0xFF, 0x3F, 0xC7, 0xFF, 0xC0, 0x7F, 0x8F, 0xFC, 0x00, 0xFF, 0x3F, 0xE0, + 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0xFC, 0xFF, 0x80, 0x0F, 0xF9, 0xFF, 0x00, + 0x3F, 0xF3, 0xFF, 0x00, 0xFF, 0xE3, 0xFF, 0x07, 0xFF, 0xC7, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xF9, + 0xFE, 0x1F, 0xFF, 0xE3, 0xFC, 0x0F, 0xFF, 0x07, 0xFC, 0x07, 0xF8, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x81, 0xFC, + 0x00, 0xFF, 0x8F, 0xFF, 0x00, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0xBF, 0xFF, + 0xE0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFC, 0xFF, 0xF8, 0x3F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xE0, 0x07, + 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, + 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFC, 0xFF, 0xFC, 0x1F, + 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x7F, 0xFF, + 0xF0, 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x1F, 0xFF, 0xC0, 0xFF, 0x07, 0xFF, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, + 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, 0x7F, + 0xE0, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x7F, 0xFF, 0xE0, + 0x01, 0xF0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x3C, 0x3F, 0xE0, 0x00, 0xFF, 0x7F, + 0xC0, 0x07, 0xFD, 0xFF, 0x00, 0x1F, 0xF7, 0xFE, 0x00, 0xFF, 0x8F, 0xFE, + 0x0F, 0xFE, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, + 0xFE, 0x01, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xF8, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, + 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, + 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, + 0x01, 0xFC, 0x0F, 0xF0, 0x1F, 0xFE, 0x1F, 0xE0, 0x7F, 0xFF, 0x3F, 0xC3, + 0xFF, 0xFF, 0x7F, 0x8F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x7F, + 0xFF, 0xFF, 0xFD, 0xFF, 0xE0, 0xFF, 0xFB, 0xFF, 0x00, 0x7F, 0xF7, 0xFC, + 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xC0, + 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, + 0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x3F, + 0xF7, 0xFC, 0x00, 0x7F, 0xEF, 0xFC, 0x01, 0xFF, 0xCF, 0xFE, 0x0F, 0xFF, + 0x9F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFB, 0xFC, + 0x1F, 0xFF, 0xE7, 0xF8, 0x1F, 0xFF, 0x8F, 0xF0, 0x1F, 0xFE, 0x1F, 0xE0, + 0x07, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x01, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x01, + 0xFF, 0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0xFC, 0x1F, 0xFC, 0x1F, 0xF8, 0x3F, + 0xE0, 0x1F, 0xF8, 0xFF, 0xC0, 0x1F, 0xF1, 0xFF, 0x00, 0x1F, 0xE3, 0xFE, + 0x00, 0x3F, 0xEF, 0xF8, 0x00, 0x3F, 0xDF, 0xF0, 0x00, 0x7F, 0xBF, 0xE0, + 0x00, 0xFF, 0x7F, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x03, + 0xE0, 0x7F, 0xC0, 0x07, 0xFC, 0xFF, 0xC0, 0x1F, 0xF8, 0xFF, 0xC0, 0x3F, + 0xE1, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFC, + 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x00, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x03, + 0xFF, 0xF0, 0x1F, 0xFF, 0xC0, 0xFF, 0xFE, 0x07, 0xFF, 0xF8, 0x1F, 0xFF, + 0xE0, 0x7F, 0xFF, 0x81, 0xFF, 0x00, 0x07, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, 0x03, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0x3F, 0xFF, 0xFC, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, + 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, + 0x00, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, + 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, + 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, + 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01, 0xFE, 0x00, 0x07, 0xF8, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x03, 0xFF, 0xC3, 0xFC, 0x0F, + 0xFF, 0xC7, 0xF8, 0x7F, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0xDF, 0xE3, 0xFF, + 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFC, 0x1F, 0xFF, 0x7F, 0xE0, + 0x0F, 0xFE, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, + 0x7F, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, + 0x7F, 0xC0, 0x07, 0xFE, 0xFF, 0xC0, 0x1F, 0xFD, 0xFF, 0xE0, 0xFF, 0xF9, + 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xBF, 0xC3, + 0xFF, 0xFE, 0x7F, 0x83, 0xFF, 0xF8, 0xFF, 0x01, 0xFF, 0xE1, 0xFE, 0x00, + 0xFE, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF7, 0xC0, + 0x00, 0x1F, 0xEF, 0xFC, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0xFF, 0xBF, 0xF0, + 0x03, 0xFF, 0x7F, 0xF8, 0x1F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFE, 0x00, 0xFF, 0x80, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0x80, 0xFF, 0x87, 0xFF, 0x83, 0xFE, 0x3F, + 0xFF, 0x8F, 0xF9, 0xFF, 0xFF, 0x3F, 0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFB, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, + 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, + 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x03, + 0xFF, 0x7F, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFC, 0xFF, + 0xF8, 0xFF, 0xF0, 0x3F, 0xC0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0xFF, 0x80, 0x1F, 0xFB, 0xFE, 0x00, 0xFF, 0xCF, 0xF8, 0x07, + 0xFE, 0x3F, 0xE0, 0x3F, 0xF0, 0xFF, 0x81, 0xFF, 0x83, 0xFE, 0x0F, 0xFE, + 0x0F, 0xF8, 0x7F, 0xF0, 0x3F, 0xE3, 0xFF, 0x80, 0xFF, 0x8F, 0xFC, 0x03, + 0xFE, 0x7F, 0xE0, 0x0F, 0xFB, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0xFF, + 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, + 0xFC, 0x00, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x3F, 0xFC, 0xFF, 0x80, 0xFF, 0xE3, 0xFE, 0x03, 0xFF, 0x07, 0xFC, + 0x0F, 0xF8, 0x1F, 0xF0, 0x3F, 0xE0, 0x3F, 0xE0, 0xFF, 0x80, 0xFF, 0xC3, + 0xFE, 0x01, 0xFF, 0x0F, 0xF8, 0x03, 0xFE, 0x3F, 0xE0, 0x0F, 0xF8, 0xFF, + 0x80, 0x1F, 0xF3, 0xFE, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0xBF, 0xE0, + 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xF8, 0x00, 0x3F, 0x80, 0xFF, 0x0F, 0xFF, + 0x00, 0xFF, 0xE0, 0xFF, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0x3F, 0xFF, + 0xC7, 0xFF, 0xFC, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF8, 0x7F, + 0xFF, 0x07, 0xFE, 0xFF, 0xE0, 0x1F, 0xFE, 0x03, 0xFF, 0xFF, 0xC0, 0x1F, + 0xFC, 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x1F, + 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF8, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xF0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, + 0xF0, 0x01, 0xFF, 0x00, 0x00, 0xFE, 0x03, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, + 0xFF, 0xFE, 0x3F, 0xC7, 0xFF, 0xFC, 0xFF, 0x3F, 0xFF, 0xFB, 0xFD, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x07, 0xFF, 0xFF, 0xF0, 0x0F, + 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF0, 0x01, 0xFF, + 0xFF, 0xC0, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, + 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, + 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xF0, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x7F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xC0, + 0x7F, 0xFF, 0xFF, 0xF0, 0x7F, 0xF8, 0x3F, 0xFC, 0x3F, 0xF0, 0x07, 0xFE, + 0x3F, 0xF0, 0x01, 0xFF, 0x9F, 0xF0, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0x3F, + 0xEF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, + 0x7F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x03, 0xFE, 0x7F, 0xC0, 0x01, 0xFF, 0x3F, 0xF0, 0x01, 0xFF, 0x9F, 0xFC, + 0x01, 0xFF, 0x87, 0xFF, 0x83, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0xFF, 0x07, 0xFF, 0x00, 0xFF, 0x1F, 0xFF, 0xC0, + 0xFF, 0x3F, 0xFF, 0xE0, 0xFF, 0x7F, 0xFF, 0xF0, 0xFF, 0x7F, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, + 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, + 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFE, + 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xBF, 0xFF, 0xE0, 0xFF, 0x9F, 0xFF, 0xC0, + 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x81, 0xFC, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, + 0x00, 0xFF, 0xE0, 0xFF, 0x03, 0xFF, 0xF8, 0xFF, 0x07, 0xFF, 0xFC, 0xFF, + 0x0F, 0xFF, 0xFE, 0xFF, 0x1F, 0xFF, 0xFE, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, + 0x3F, 0xFC, 0x3F, 0xFF, 0x7F, 0xF0, 0x0F, 0xFF, 0x7F, 0xE0, 0x07, 0xFF, + 0x7F, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0x7F, 0xC0, 0x07, 0xFF, + 0x7F, 0xE0, 0x07, 0xFF, 0x7F, 0xF0, 0x0F, 0xFF, 0x3F, 0xF8, 0x3F, 0xFF, + 0x3F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, + 0x07, 0xFF, 0xFD, 0xFF, 0x03, 0xFF, 0xF9, 0xFF, 0x01, 0xFF, 0xE1, 0xFF, + 0x00, 0x3F, 0x81, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x07, 0xE7, 0xF8, 0xFF, 0xFF, 0xCF, 0xFF, + 0xFE, 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xE7, 0xFF, 0x83, 0x3F, 0xF8, 0x01, 0xFF, 0x80, 0x0F, + 0xFC, 0x00, 0x7F, 0xE0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, + 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, + 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x3F, + 0xF0, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, + 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, + 0xFE, 0x1F, 0xF8, 0x0F, 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x7F, 0x80, 0x0F, + 0xF8, 0xFF, 0x00, 0x0F, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xC0, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, + 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xC0, + 0x00, 0x01, 0xFF, 0x83, 0xC0, 0x01, 0xFF, 0x7F, 0xC0, 0x03, 0xFE, 0xFF, + 0x80, 0x07, 0xFD, 0xFF, 0x80, 0x0F, 0xF9, 0xFF, 0xC0, 0x7F, 0xE3, 0xFF, + 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, + 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, + 0xE0, 0x00, 0x00, 0x08, 0x00, 0x07, 0x00, 0x03, 0xE0, 0x00, 0xFC, 0x00, + 0x7F, 0x80, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, 0xF8, 0x01, + 0xFF, 0x00, 0x3F, 0xE0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xE0, 0x07, + 0xFC, 0x00, 0xFF, 0x80, 0x1F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, + 0xF8, 0x01, 0xFF, 0x00, 0x3F, 0xE0, 0x07, 0xFC, 0x00, 0xFF, 0x80, 0x1F, + 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x0F, 0xF8, 0x01, 0xFF, 0x00, 0x3F, + 0xE0, 0x07, 0xFC, 0x00, 0xFF, 0x80, 0x1F, 0xF0, 0x83, 0xFF, 0xF8, 0x7F, + 0xFF, 0x07, 0xFF, 0xE0, 0xFF, 0xFC, 0x0F, 0xFF, 0x80, 0xFF, 0xF0, 0x07, + 0xF8, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, + 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0x7F, 0xC0, 0x0F, 0xFD, 0xFF, + 0x80, 0x7F, 0xF7, 0xFF, 0x07, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0x3F, 0xC3, 0xFF, 0xF8, + 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x03, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xF7, 0xFC, 0x00, 0x0F, 0xF8, 0xFF, 0x80, + 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x87, 0xF8, 0x00, 0x7F, 0xC1, 0xFF, + 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, 0x0F, 0xF8, 0x03, 0xFE, 0x03, + 0xFE, 0x00, 0xFF, 0x80, 0x7F, 0x80, 0x7F, 0xC0, 0x1F, 0xF0, 0x1F, 0xF0, + 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0xFF, + 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, 0x1F, 0xF0, 0x00, 0x7F, 0xC7, + 0xF8, 0x00, 0x0F, 0xF1, 0xFE, 0x00, 0x03, 0xFC, 0xFF, 0x80, 0x00, 0x7F, + 0xBF, 0xC0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, + 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0xFF, + 0xBF, 0xC0, 0x07, 0xFC, 0x00, 0x7F, 0xDF, 0xE0, 0x03, 0xFE, 0x00, 0x3F, + 0xCF, 0xF8, 0x03, 0xFF, 0x80, 0x3F, 0xE3, 0xFC, 0x01, 0xFF, 0xC0, 0x1F, + 0xF1, 0xFE, 0x00, 0xFF, 0xE0, 0x0F, 0xF0, 0xFF, 0x80, 0x7F, 0xF0, 0x07, + 0xF8, 0x3F, 0xC0, 0x7F, 0xFC, 0x07, 0xFC, 0x1F, 0xE0, 0x3F, 0xFE, 0x03, + 0xFC, 0x0F, 0xF0, 0x1F, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x0F, 0xFF, 0x81, + 0xFF, 0x01, 0xFE, 0x0F, 0xFF, 0xE0, 0xFF, 0x00, 0xFF, 0x07, 0xF7, 0xF0, + 0x7F, 0x80, 0x3F, 0x83, 0xFB, 0xF8, 0x3F, 0xC0, 0x1F, 0xE1, 0xFD, 0xFC, + 0x3F, 0xC0, 0x0F, 0xF1, 0xFE, 0x7F, 0x1F, 0xE0, 0x07, 0xF8, 0xFE, 0x3F, + 0x8F, 0xF0, 0x01, 0xFE, 0x7F, 0x1F, 0xCF, 0xF0, 0x00, 0xFF, 0x3F, 0x8F, + 0xE7, 0xF8, 0x00, 0x7F, 0xBF, 0xC3, 0xFB, 0xFC, 0x00, 0x1F, 0xDF, 0xC1, + 0xFD, 0xFC, 0x00, 0x0F, 0xFF, 0xE0, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xF0, + 0x7F, 0xFF, 0x00, 0x01, 0xFF, 0xF8, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xF8, + 0x0F, 0xFF, 0x80, 0x00, 0x7F, 0xFC, 0x07, 0xFF, 0xC0, 0x00, 0x1F, 0xFE, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFF, + 0x00, 0x7F, 0xF0, 0x00, 0x01, 0xFF, 0x80, 0x3F, 0xF8, 0x00, 0x00, 0xFF, + 0xC0, 0x0F, 0xF8, 0x00, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x00, 0x3F, + 0xE0, 0x03, 0xFE, 0x00, 0x00, 0x7F, 0xF0, 0x01, 0xFF, 0x8F, 0xFC, 0x00, + 0xFF, 0xC1, 0xFF, 0x80, 0x3F, 0xF0, 0x7F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, + 0x0F, 0xFC, 0x01, 0xFF, 0x83, 0xFF, 0x00, 0x7F, 0xF1, 0xFF, 0x80, 0x0F, + 0xFC, 0xFF, 0xC0, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x3F, 0xFF, 0xF8, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xF0, + 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x03, 0xFF, + 0xF0, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x07, 0xFE, 0xFF, 0xC0, 0x03, + 0xFF, 0x3F, 0xF8, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0x7F, 0xE0, 0xFF, 0xC0, + 0x3F, 0xF0, 0x3F, 0xF8, 0x1F, 0xF8, 0x07, 0xFE, 0x07, 0xFE, 0x00, 0xFF, + 0xC3, 0xFF, 0x00, 0x3F, 0xF9, 0xFF, 0x80, 0x07, 0xFE, 0x7F, 0xE0, 0x00, + 0xFF, 0xC0, 0x7F, 0xC0, 0x00, 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xE7, 0xFC, + 0x00, 0x0F, 0xF8, 0xFF, 0x80, 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, + 0x0F, 0xF0, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, + 0xC0, 0x1F, 0xE0, 0x1F, 0xF0, 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x01, + 0xFE, 0x00, 0x3F, 0xC0, 0xFF, 0x80, 0x0F, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, + 0x0F, 0xF0, 0x00, 0x7F, 0x87, 0xFC, 0x00, 0x1F, 0xF1, 0xFE, 0x00, 0x03, + 0xFC, 0x7F, 0x80, 0x00, 0xFF, 0x3F, 0xE0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, + 0x07, 0xFB, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, + 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, + 0x01, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, + 0xE7, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0xFF, 0xE0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x7F, 0xF0, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x7F, + 0xF0, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x03, 0xFF, 0x80, + 0x00, 0x3F, 0xF8, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x03, + 0xF8, 0x00, 0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0xFF, 0xF0, 0x0F, 0xFF, 0x80, + 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0x00, 0x0F, 0xF0, + 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0xFF, 0x00, + 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0xFF, + 0x80, 0x0F, 0xF8, 0x00, 0xFF, 0xC0, 0x3F, 0xFE, 0x01, 0xFF, 0xE0, 0x0F, + 0xFE, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0xFF, 0xF0, + 0x07, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0x7F, 0xC0, 0x01, + 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, + 0x00, 0xFF, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xC0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, + 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x1F, + 0xFF, 0x00, 0x7F, 0xF8, 0x01, 0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x07, 0xF0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0x00, 0x07, 0xFE, 0x00, 0x3F, 0xFC, 0x01, + 0xFF, 0xF0, 0x0F, 0xFF, 0x80, 0x7F, 0xFE, 0x03, 0xFF, 0xF0, 0x1F, 0xFF, + 0x80, 0x07, 0xFC, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0xFF, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x00, 0xFF, 0x80, 0x07, 0xFF, + 0x00, 0x1F, 0xFE, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x07, 0xFF, 0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xC0, 0x3F, 0xF8, + 0x01, 0xFF, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xF8, 0x00, 0x3F, + 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x0F, 0xFF, 0xC0, 0x7F, + 0xFE, 0x03, 0xFF, 0xF0, 0x1F, 0xFF, 0x00, 0xFF, 0xF8, 0x07, 0xFF, 0x80, + 0x3F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x8F, 0xFF, + 0x80, 0x00, 0xCF, 0xFF, 0xF8, 0x01, 0xEF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0x70, 0x00, 0xFF, 0xFF, 0x30, + 0x00, 0x1F, 0xFE, 0x10, 0x00, 0x01, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, + 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, + 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, + 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xE1, 0xF0, + 0xF8, 0x7C, 0x3F, 0x1F, 0x8F, 0xC7, 0xE7, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, + 0x3F, 0x9F, 0xCF, 0xF7, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x78, 0x00, + 0x00, 0x01, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xFF, 0x00, 0x00, 0xFF, 0xFC, + 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8, + 0x1F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0x8F, 0xFF, 0x9F, + 0xF8, 0x3F, 0xFE, 0x7F, 0xC0, 0xFF, 0xFB, 0xFF, 0x07, 0x9F, 0xFF, 0xF8, + 0x1E, 0x7C, 0x3F, 0xE0, 0x78, 0x00, 0xFF, 0x83, 0xE0, 0x03, 0xFE, 0x0F, + 0x00, 0x0F, 0xF0, 0x3C, 0x00, 0x3F, 0xC1, 0xF0, 0x00, 0xFF, 0x07, 0x80, + 0x03, 0xFC, 0x1E, 0x00, 0x0F, 0xF8, 0x78, 0x00, 0x3F, 0xE3, 0xC0, 0x00, + 0xFF, 0x8F, 0x00, 0x03, 0xFE, 0x3C, 0x0F, 0x0F, 0xF9, 0xF0, 0x3F, 0xDF, + 0xF7, 0x81, 0xFF, 0x7F, 0xFE, 0x07, 0xFD, 0xFF, 0xF8, 0x3F, 0xE3, 0xFF, + 0xC3, 0xFF, 0x8F, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0x80, 0x7F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, + 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x01, 0xE0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, + 0xF8, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x3C, + 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xF8, 0x00, + 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFC, 0x3F, 0xF8, + 0x07, 0xFC, 0x03, 0xFF, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0xFF, 0x80, 0x1F, + 0xF0, 0x3F, 0xC0, 0x03, 0xFC, 0x0F, 0xF0, 0x00, 0xE0, 0x03, 0xFC, 0x00, + 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x0F, + 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFE, 0x00, + 0x3F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x07, 0xFB, 0xF0, 0x00, 0x83, 0xFF, 0xFF, 0x00, 0x63, + 0xFF, 0xFF, 0xF0, 0x7C, 0x7F, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0x01, 0xFF, + 0xFF, 0xC7, 0x00, 0x0F, 0xFF, 0xE1, 0x00, 0x00, 0x3F, 0xC0, 0x04, 0x00, + 0x00, 0x10, 0x0E, 0x00, 0x00, 0x38, 0x1F, 0x00, 0x00, 0x78, 0x3F, 0x07, + 0xF0, 0xFC, 0x3F, 0x9F, 0xFC, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, + 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x1F, 0xF0, + 0x07, 0xF8, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xC0, + 0x01, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xE0, + 0x03, 0xFC, 0x1F, 0xE0, 0x03, 0xFC, 0x1F, 0xF0, 0x07, 0xF8, 0x0F, 0xFC, + 0x1F, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, + 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0x3F, 0x9F, 0xFC, 0xFE, 0x1F, 0x87, 0xF0, 0xFC, 0x0F, 0x00, + 0x00, 0x78, 0x0E, 0x00, 0x00, 0x38, 0x04, 0x00, 0x00, 0x10, 0xFF, 0xC0, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x0F, 0xF9, 0xFF, 0x80, 0x03, 0xFF, 0x1F, + 0xF0, 0x00, 0x7F, 0xC3, 0xFF, 0x00, 0x1F, 0xF8, 0x3F, 0xE0, 0x03, 0xFE, + 0x07, 0xFE, 0x00, 0xFF, 0xC0, 0x7F, 0xC0, 0x1F, 0xF0, 0x0F, 0xF8, 0x07, + 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x1F, 0xF0, 0x3F, 0xF0, 0x01, 0xFF, + 0x07, 0xFC, 0x00, 0x3F, 0xE1, 0xFF, 0x80, 0x07, 0xFE, 0x3F, 0xE0, 0x00, + 0x7F, 0xCF, 0xFC, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0xFF, 0xBF, 0xE0, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, + 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xFF, 0xFF, + 0xFF, 0xE1, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, + 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xC3, + 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0x7F, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xE0, 0x00, 0x01, + 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0xFF, + 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x0F, 0xFC, + 0x3F, 0xF0, 0x3F, 0xE0, 0x1F, 0xF0, 0x7F, 0xC0, 0x3F, 0xE0, 0xFF, 0x80, + 0x3F, 0xC0, 0xFF, 0x80, 0x78, 0x01, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x80, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xE0, + 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xF0, + 0x07, 0xFF, 0xFF, 0xF0, 0x0F, 0xF3, 0xFF, 0xF8, 0x1F, 0xC1, 0xFF, 0xF8, + 0x7F, 0x81, 0xFF, 0xF8, 0xFF, 0x00, 0xFF, 0xF9, 0xFE, 0x00, 0xFF, 0xF3, + 0xFC, 0x00, 0xFF, 0xF7, 0xF8, 0x00, 0x7F, 0xEF, 0xF8, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x7F, 0xDF, 0xF8, 0x00, 0x7F, 0xBF, 0xFC, 0x00, 0xFF, 0x7F, + 0xFC, 0x01, 0xFE, 0x7F, 0xFE, 0x03, 0xFC, 0x7F, 0xFE, 0x07, 0xF0, 0x7F, + 0xFF, 0x1F, 0xE0, 0x7F, 0xFF, 0x7F, 0x80, 0x3F, 0xFF, 0xFF, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x1F, + 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x07, + 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x01, 0xE0, 0x07, + 0xFC, 0x3F, 0xC0, 0x0F, 0xF8, 0x7F, 0xC0, 0x1F, 0xF0, 0xFF, 0xC0, 0x3F, + 0xE1, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFE, + 0x03, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0xFF, 0x07, 0xFF, 0xF8, + 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0x83, 0xFF, + 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, + 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x01, 0xFE, + 0x00, 0x00, 0x3F, 0xC0, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x1F, 0xC0, + 0x00, 0x00, 0x1F, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x1F, 0x80, 0xFC, 0x00, + 0x7F, 0x00, 0x1F, 0x83, 0xF0, 0x07, 0xFF, 0xC0, 0x3F, 0x07, 0xC0, 0x1F, + 0xFF, 0xC0, 0x3F, 0x0F, 0x80, 0x7F, 0xFF, 0xC0, 0x3E, 0x3E, 0x01, 0xFC, + 0x1F, 0xC0, 0x7C, 0x7C, 0x07, 0xE0, 0x1F, 0x80, 0x7D, 0xF0, 0x0F, 0xC0, + 0x1F, 0x80, 0xFB, 0xE0, 0x3F, 0x00, 0x18, 0x01, 0xF7, 0xC0, 0x7E, 0x00, + 0x00, 0x01, 0xEF, 0x80, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x01, 0xF0, 0x00, + 0x00, 0x07, 0xFC, 0x03, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x07, 0xC0, 0x00, + 0x00, 0x1F, 0xF0, 0x0F, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x1F, 0x00, 0x00, + 0x00, 0x7F, 0xE0, 0x3E, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x7E, 0x00, 0x00, + 0x01, 0xFF, 0x80, 0xFC, 0x00, 0x70, 0x07, 0xDF, 0x00, 0xFC, 0x01, 0xF8, + 0x0F, 0x9F, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x3E, 0x01, 0xFC, 0x1F, 0xC0, + 0x7C, 0x3E, 0x01, 0xFF, 0xFF, 0x00, 0xF8, 0x7C, 0x01, 0xFF, 0xFC, 0x03, + 0xF0, 0xFC, 0x01, 0xFF, 0xF0, 0x07, 0xC0, 0xFC, 0x00, 0x7F, 0x00, 0x1F, + 0x80, 0xFC, 0x00, 0x00, 0x00, 0x7E, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, + 0x01, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, + 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, + 0x01, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, + 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, + 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x7F, 0xFE, 0x07, + 0xFF, 0xF8, 0x7F, 0xFF, 0xC3, 0xFF, 0xFF, 0x3F, 0x83, 0xF9, 0xF8, 0x1F, + 0xC1, 0xC0, 0x7E, 0x00, 0x0F, 0xF0, 0x07, 0xFF, 0x83, 0xFF, 0xFC, 0x7F, + 0xFF, 0xE7, 0xFF, 0xBF, 0x3F, 0xC1, 0xFB, 0xF8, 0x1F, 0xDF, 0xC0, 0xFE, + 0xFE, 0x07, 0xF7, 0xF8, 0xFF, 0xBF, 0xFF, 0xFC, 0xFF, 0xFF, 0xE7, 0xFF, + 0xFF, 0x0F, 0xFD, 0xF8, 0x3F, 0x87, 0xE0, 0x00, 0x7F, 0x07, 0xF0, 0x03, + 0xF8, 0x3F, 0x80, 0x3F, 0x83, 0xF8, 0x03, 0xFC, 0x3F, 0xC0, 0x1F, 0xC1, + 0xFC, 0x01, 0xFC, 0x1F, 0xC0, 0x1F, 0xE1, 0xFE, 0x00, 0xFE, 0x0F, 0xE0, + 0x0F, 0xF0, 0xFF, 0x00, 0xFF, 0x0F, 0xF0, 0x07, 0xF8, 0x7F, 0x80, 0x7F, + 0x87, 0xF8, 0x07, 0xFC, 0x7F, 0xC0, 0x3F, 0xC3, 0xFC, 0x03, 0xFE, 0x3F, + 0xE0, 0x0F, 0xF0, 0xFF, 0x00, 0x7F, 0xC7, 0xFC, 0x01, 0xFE, 0x1F, 0xE0, + 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0xC3, 0xFC, 0x00, 0xFF, 0x0F, 0xF0, 0x03, + 0xF8, 0x3F, 0x80, 0x1F, 0xE1, 0xFE, 0x00, 0x7F, 0x07, 0xF8, 0x01, 0xFC, + 0x1F, 0xC0, 0x0F, 0xF0, 0xFF, 0x00, 0x3F, 0x83, 0xF8, 0x00, 0xFE, 0x0F, + 0xE0, 0x07, 0xF0, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, + 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x00, + 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, + 0x07, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x1F, 0xFC, 0x01, 0xFF, 0xC0, 0x00, + 0x7F, 0xC0, 0x00, 0x7F, 0xC0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x07, + 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0x80, 0x3F, + 0x00, 0x00, 0x00, 0x1F, 0x80, 0xFC, 0x3F, 0xFF, 0x80, 0x1F, 0x83, 0xF0, + 0x7F, 0xFF, 0xC0, 0x1F, 0x07, 0xC0, 0xFF, 0xFF, 0xC0, 0x3F, 0x0F, 0x81, + 0xFF, 0xFF, 0xC0, 0x3E, 0x3E, 0x03, 0xE0, 0x3F, 0x80, 0x7C, 0x7C, 0x07, + 0xC0, 0x1F, 0x80, 0x7D, 0xF0, 0x0F, 0x80, 0x3F, 0x00, 0xFB, 0xE0, 0x1F, + 0x00, 0x3E, 0x00, 0xF7, 0xC0, 0x3E, 0x00, 0xFC, 0x01, 0xEF, 0x80, 0x7C, + 0x01, 0xF8, 0x03, 0xFF, 0x00, 0xF8, 0x07, 0xE0, 0x07, 0xFC, 0x01, 0xFF, + 0xFF, 0x80, 0x0F, 0xF8, 0x03, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x07, 0xFF, + 0xF0, 0x00, 0x3F, 0xF0, 0x0F, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x1F, 0x0F, + 0xC0, 0x00, 0xFF, 0xC0, 0x3E, 0x0F, 0xC0, 0x01, 0xFF, 0x80, 0x7C, 0x0F, + 0xC0, 0x03, 0xDF, 0x00, 0xF8, 0x0F, 0xC0, 0x0F, 0x9F, 0x01, 0xF0, 0x1F, + 0x80, 0x1F, 0x3E, 0x03, 0xE0, 0x1F, 0x80, 0x7C, 0x3E, 0x07, 0xC0, 0x3F, + 0x00, 0xF8, 0x7C, 0x0F, 0x80, 0x3F, 0x03, 0xF0, 0xFC, 0x1F, 0x00, 0x7F, + 0x07, 0xC0, 0xFC, 0x3E, 0x00, 0x7E, 0x1F, 0x80, 0xFC, 0x00, 0x00, 0x00, + 0x7E, 0x01, 0xFC, 0x00, 0x00, 0x01, 0xF8, 0x01, 0xFC, 0x00, 0x00, 0x0F, + 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x01, 0xFF, 0x00, 0x01, 0xFF, + 0x00, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0xFF, 0xFC, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xF8, 0x01, + 0xFF, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0xC7, 0xFF, 0xFC, 0xFC, 0x1F, 0xBF, + 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, + 0x01, 0xFF, 0xC0, 0x7E, 0xFC, 0x1F, 0x9F, 0xFF, 0xF1, 0xFF, 0xFC, 0x1F, + 0xFF, 0x01, 0xFF, 0xC0, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, + 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, + 0x80, 0x00, 0x00, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xF8, 0x03, 0xFF, 0xC3, 0xFF, + 0xF8, 0xFF, 0xFF, 0x7F, 0xFF, 0xDF, 0x83, 0xF7, 0xE0, 0xFF, 0xF0, 0x1F, + 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0xFF, 0x00, + 0x7F, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xE0, 0x07, 0xFF, + 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xF8, + 0x01, 0xFF, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0xC7, 0xFF, 0xF8, 0xFC, 0x3F, + 0x1F, 0x03, 0xF0, 0xE0, 0xFC, 0x00, 0x3F, 0x80, 0x3F, 0xE0, 0x07, 0xF8, + 0x00, 0xFF, 0x80, 0x1F, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF3, 0xE0, 0x3F, + 0xFC, 0x0F, 0xEF, 0xC3, 0xFD, 0xFF, 0xFF, 0x1F, 0xFF, 0xC1, 0xFF, 0xF8, + 0x1F, 0xFC, 0x00, 0xFE, 0x00, 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, + 0x3F, 0x81, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0xFC, 0x00, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xF0, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, + 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFB, 0xFF, 0xBF, 0xFF, 0xEF, 0xFE, 0xFF, 0xFF, 0x9F, 0xF3, + 0xFF, 0xFE, 0x1F, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xFC, 0x1F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFE, + 0x7F, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0x87, + 0xF0, 0xFF, 0xFF, 0xF0, 0xFE, 0x1F, 0xFF, 0xFE, 0x1F, 0xC3, 0xFF, 0xFF, + 0xC3, 0xF8, 0x7F, 0xFF, 0xF8, 0x7F, 0x0F, 0xFF, 0xFF, 0x0F, 0xE1, 0xFF, + 0xFF, 0xE1, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0x87, 0xFF, 0xFF, 0x87, 0xF0, + 0xFF, 0xFF, 0xF0, 0xFE, 0x0F, 0xFF, 0xFE, 0x1F, 0xC1, 0xFF, 0xFF, 0xC3, + 0xF8, 0x1F, 0xFF, 0xF8, 0x7F, 0x03, 0xFF, 0xFF, 0x0F, 0xE0, 0x3F, 0xFF, + 0xE1, 0xFC, 0x03, 0xFF, 0xFC, 0x3F, 0x80, 0x1F, 0xFF, 0x87, 0xF0, 0x00, + 0x7F, 0xF0, 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, + 0x00, 0x07, 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, + 0xFC, 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, + 0xF0, 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, + 0x07, 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, + 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, + 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, 0x07, + 0xF8, 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, 0x00, + 0x03, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, 0xFE, + 0x00, 0x01, 0xFE, 0x1F, 0xC0, 0x00, 0x3F, 0xC3, 0xF8, 0x00, 0x07, 0xF8, + 0x7F, 0x00, 0x00, 0xFF, 0x0F, 0xE0, 0x00, 0x1F, 0xE1, 0xFC, 0x00, 0x03, + 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF0, 0xFE, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, + 0xF8, 0x07, 0xFF, 0x07, 0xFF, 0xC2, 0x07, 0xF0, 0x01, 0xF8, 0x00, 0xFC, + 0x00, 0x7E, 0x00, 0xFE, 0xFF, 0xFE, 0x7F, 0xFE, 0x0F, 0xF8, 0x00, 0x01, + 0xF0, 0x3F, 0x07, 0xF0, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xF3, + 0xF8, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, + 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x01, 0xFC, + 0x00, 0x3F, 0xF8, 0x07, 0xFF, 0xF0, 0x7F, 0xFF, 0xC3, 0xFF, 0xFE, 0x3F, + 0xC7, 0xF9, 0xF8, 0x1F, 0xDF, 0xC0, 0x7F, 0xFE, 0x03, 0xFF, 0xE0, 0x1F, + 0xFF, 0x00, 0xFF, 0xF8, 0x07, 0xFF, 0xC0, 0x3F, 0xFE, 0x01, 0xFF, 0xF8, + 0x0F, 0xFF, 0xC0, 0x7F, 0x7E, 0x07, 0xF3, 0xFC, 0x7F, 0x8F, 0xFF, 0xF8, + 0x7F, 0xFF, 0xC1, 0xFF, 0xFC, 0x03, 0xFF, 0x80, 0x07, 0xF0, 0x00, 0x7E, + 0x07, 0xE0, 0x03, 0xF8, 0x3F, 0x80, 0x0F, 0xE0, 0xFE, 0x00, 0x7F, 0x07, + 0xF0, 0x01, 0xFC, 0x1F, 0xC0, 0x0F, 0xF0, 0xFF, 0x00, 0x3F, 0x83, 0xF8, + 0x01, 0xFE, 0x1F, 0xE0, 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0xC1, 0xFC, 0x00, + 0xFF, 0x0F, 0xF0, 0x03, 0xFC, 0x3F, 0xC0, 0x1F, 0xE1, 0xFE, 0x00, 0x7F, + 0x87, 0xF8, 0x03, 0xFE, 0x3F, 0xE0, 0x1F, 0xE1, 0xFE, 0x01, 0xFF, 0x1F, + 0xF0, 0x0F, 0xF0, 0xFF, 0x00, 0xFF, 0x0F, 0xF0, 0x07, 0xF8, 0x7F, 0x80, + 0x7F, 0x87, 0xF8, 0x07, 0xF8, 0x7F, 0x80, 0x3F, 0x83, 0xFC, 0x03, 0xFC, + 0x3F, 0xC0, 0x1F, 0xC1, 0xFC, 0x01, 0xFC, 0x1F, 0xE0, 0x0F, 0xE0, 0xFE, + 0x00, 0xFE, 0x0F, 0xE0, 0x07, 0xE0, 0x7E, 0x00, 0x00, 0x01, 0xF0, 0x00, + 0x00, 0x3E, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x1F, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x0F, 0x00, 0x07, 0xFF, 0x80, 0x00, 0x0F, 0x80, 0x03, 0xFF, 0xC0, + 0x00, 0x0F, 0x80, 0x01, 0xF7, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0xF3, 0xF0, + 0x00, 0x07, 0xC0, 0x00, 0x41, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xFC, + 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7E, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x3F, + 0x00, 0x01, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x0F, + 0xC0, 0x00, 0xF8, 0x00, 0x00, 0x07, 0xE0, 0x00, 0xF8, 0x00, 0x00, 0x03, + 0xF0, 0x00, 0x78, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x1F, 0x00, 0x00, 0x00, + 0x0F, 0xC0, 0x1F, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x0F, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFC, 0x00, 0x00, 0x0F, 0x80, 0x01, 0xFE, + 0x00, 0x00, 0x07, 0xC0, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xC0, 0x01, 0xFF, + 0x80, 0x00, 0x03, 0xE0, 0x01, 0xFF, 0xC0, 0x00, 0x03, 0xE0, 0x01, 0xF7, + 0xE0, 0x00, 0x03, 0xE0, 0x01, 0xFB, 0xF0, 0x00, 0x01, 0xF0, 0x01, 0xF9, + 0xF8, 0x00, 0x01, 0xF0, 0x01, 0xF8, 0xFC, 0x00, 0x00, 0xF8, 0x00, 0xF8, + 0x7E, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0x78, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x7C, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x7C, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x3E, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x3E, 0x00, 0x0F, + 0xFF, 0xFF, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x1F, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x0F, 0x80, 0x00, + 0x00, 0x1F, 0x80, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0xC0, 0x07, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x03, 0xF0, 0x00, + 0x00, 0x7C, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0xF8, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0xFF, 0xF0, 0x00, + 0x01, 0xF0, 0x00, 0xFF, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0xFB, 0xF0, 0x00, + 0x03, 0xE0, 0x00, 0xF3, 0xF0, 0x00, 0x07, 0xC0, 0x00, 0x83, 0xF0, 0x00, + 0x07, 0xC0, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xF0, 0x00, + 0x0F, 0x80, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0x7C, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x7C, 0x00, 0x00, 0x03, 0xF0, 0x00, + 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x01, + 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x03, + 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xC0, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x7F, 0xF8, 0x00, 0x00, 0x0F, + 0x80, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x1E, + 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x3E, 0x03, 0xF8, 0x7F, 0x00, 0x00, 0x7C, + 0x03, 0xF0, 0x3F, 0x00, 0x00, 0x7C, 0x03, 0xF0, 0x3F, 0x00, 0x00, 0xF8, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xF0, + 0x00, 0x00, 0xFE, 0x00, 0x01, 0xE0, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xE0, + 0x00, 0x03, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xC0, + 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0x80, + 0x00, 0x7F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x1E, 0x00, + 0x01, 0xFF, 0xFF, 0x00, 0x3E, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x7C, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0xF8, 0x00, + 0x07, 0xFF, 0xFF, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x7F, 0xFC, + 0x00, 0x00, 0x3E, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x0F, 0x80, 0x07, 0xFF, + 0xF8, 0x00, 0x01, 0xF0, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x7C, 0x00, 0x1F, + 0x03, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0xE0, 0xFC, 0x00, 0x03, 0xE0, 0x00, + 0x00, 0x3F, 0x80, 0x00, 0x78, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x1F, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xF8, + 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x07, + 0xC0, 0x00, 0x00, 0x01, 0xF0, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x3F, 0x00, + 0x7C, 0x00, 0x00, 0xFC, 0x0F, 0xE0, 0x0F, 0x80, 0x00, 0x0F, 0xC3, 0xFC, + 0x03, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0xFF, + 0xC0, 0x1F, 0x00, 0x00, 0x01, 0xFF, 0xF8, 0x03, 0xC0, 0x00, 0x00, 0x1F, + 0xFC, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xC0, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x0F, 0x80, 0x03, + 0xFC, 0x00, 0x00, 0x01, 0xE0, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7C, 0x00, + 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x03, 0xE0, + 0x03, 0xEF, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0xFD, 0xF8, 0x00, 0x00, 0x1F, + 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x07, 0xC0, 0x0F, 0xC7, 0xE0, 0x00, 0x01, + 0xF0, 0x01, 0xF0, 0xFC, 0x00, 0x00, 0x3E, 0x00, 0x7C, 0x1F, 0x80, 0x00, + 0x0F, 0x80, 0x1F, 0xFF, 0xFE, 0x00, 0x01, 0xF0, 0x03, 0xFF, 0xFF, 0xC0, + 0x00, 0x7C, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x03, 0xE0, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0xF8, 0x00, 0x00, 0x07, + 0xE0, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x07, 0xC0, 0x00, 0x00, + 0x1F, 0x80, 0x00, 0xF8, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, + 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, + 0x07, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x3E, 0x1F, 0xF0, 0x00, + 0x1F, 0xEF, 0xF8, 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x0F, 0xF9, 0xFF, 0x80, + 0x0F, 0xFC, 0x7F, 0xF0, 0x3F, 0xFC, 0x3F, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, + 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, + 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x03, + 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xEF, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x00, + 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x7F, 0xE0, 0x00, + 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x0F, 0xFC, 0x00, 0x00, + 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0x00, 0x00, 0x1F, + 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, 0x80, 0x3F, 0xE0, 0x00, 0x0F, 0xFC, + 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x03, 0xFE, 0x00, + 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, + 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, + 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF8, 0x00, 0x00, 0xFF, 0x80, 0xFF, + 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xF0, 0x3F, 0xE0, + 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x07, 0xFE, 0x1F, 0xF0, 0x00, + 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, + 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, + 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x7F, 0xFE, 0x00, + 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x3F, 0xEF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0x1F, + 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x0F, 0xF8, + 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x0F, + 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x01, 0xFF, + 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, 0x80, 0x3F, 0xE0, + 0x00, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, + 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x80, 0x01, + 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, + 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, + 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF8, 0x00, 0x00, + 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x3F, + 0xF0, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, 0x00, 0x07, 0xFE, + 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, + 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, + 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x01, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xDF, 0xC0, 0x00, 0x00, 0x00, 0xFC, + 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xE3, 0xF8, 0x00, 0x00, 0x00, 0xFE, 0x0F, + 0xE0, 0x00, 0x00, 0x0F, 0xE0, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x1F, + 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x3F, 0xEF, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x7F, 0xE0, + 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x8F, 0xF8, 0x00, + 0x00, 0x0F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, + 0x07, 0xFC, 0x0F, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x01, + 0xFF, 0x01, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x0F, 0xFC, 0x00, 0x00, 0xFF, + 0x80, 0x3F, 0xE0, 0x00, 0x0F, 0xFC, 0x01, 0xFF, 0x80, 0x00, 0x7F, 0xC0, + 0x07, 0xFC, 0x00, 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0x00, 0x3F, 0xE0, 0x01, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, + 0xF8, 0x00, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0x00, 0x07, 0xFE, 0x07, 0xFC, + 0x00, 0x00, 0x3F, 0xF0, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFF, 0x00, + 0x00, 0x07, 0xFE, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF1, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x7F, 0xC0, 0x00, 0x00, + 0x1F, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x01, 0xF0, 0x07, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x3C, 0x00, 0x00, 0x01, 0xFF, 0xC3, 0xE0, + 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0x07, 0x87, 0xFF, 0x80, 0x00, 0x00, 0x3C, 0x0F, 0xF8, 0x00, 0x00, + 0x01, 0xE0, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, + 0xF8, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, + 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x07, 0xFD, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, 0x03, + 0xFE, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x81, + 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, + 0xE0, 0x00, 0x03, 0xFE, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x07, 0xFC, + 0x00, 0x01, 0xFF, 0x80, 0x3F, 0xF0, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0x80, + 0x00, 0x7F, 0xC0, 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xF0, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0x00, 0x00, + 0x1F, 0xF0, 0x1F, 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0xFF, 0x80, 0x00, 0x07, + 0xFE, 0x07, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0xFF, + 0xC3, 0xFE, 0x00, 0x00, 0x03, 0xFE, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF9, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xC0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x00, + 0x7F, 0x83, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x1F, + 0xE0, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF8, + 0x3F, 0xC0, 0x00, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x0F, + 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x07, 0xFD, 0xFF, + 0x00, 0x00, 0x00, 0x7F, 0xCF, 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x3F, 0xE0, + 0x00, 0x00, 0x3F, 0xF1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x0F, 0xFC, 0x00, + 0x00, 0x0F, 0xF8, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x81, 0xFF, 0x80, 0x00, + 0x07, 0xFC, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x03, + 0xFE, 0x01, 0xFF, 0x80, 0x00, 0x1F, 0xF0, 0x07, 0xFC, 0x00, 0x01, 0xFF, + 0x80, 0x3F, 0xF0, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0xC0, + 0x07, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x3F, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, + 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFE, + 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x1F, + 0xF8, 0x00, 0x00, 0xFF, 0xC0, 0xFF, 0x80, 0x00, 0x07, 0xFE, 0x07, 0xFC, + 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xC3, 0xFE, 0x00, + 0x00, 0x03, 0xFE, 0x3F, 0xF0, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xCF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xC0, 0x00, 0x00, + 0x1F, 0xF8, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x00, + 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x78, 0x38, 0x00, 0x00, + 0x00, 0x03, 0xC1, 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x78, 0xF0, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0x80, 0x00, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFF, + 0xE0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF0, 0x00, + 0x00, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x00, + 0x01, 0xFF, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF8, 0xFF, 0x80, 0x00, 0x00, + 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x1F, 0xF0, 0x00, 0x00, 0x7F, + 0xC0, 0xFF, 0xC0, 0x00, 0x03, 0xFE, 0x03, 0xFE, 0x00, 0x00, 0x1F, 0xF0, + 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x00, 0xFF, 0xC0, 0x00, 0x0F, 0xF8, 0x03, + 0xFE, 0x00, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x00, 0x07, 0xFC, 0x00, 0x7F, + 0xC0, 0x00, 0x3F, 0xE0, 0x03, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xF8, + 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x80, + 0x00, 0x0F, 0xF8, 0x0F, 0xFC, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, + 0x03, 0xFF, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x3F, 0xF0, 0x00, 0x00, + 0x7F, 0xE1, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x1F, 0xF8, 0x00, 0x00, 0x0F, + 0xFC, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xE7, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xE0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x03, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x7F, + 0xE1, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x83, 0xFE, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xFF, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFC, + 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x1F, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0xE0, 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, + 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0xFF, 0x80, 0x00, 0x00, + 0x00, 0x03, 0xFE, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x03, + 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0x00, 0x7F, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x1F, + 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xFE, 0x00, + 0x07, 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xF8, 0x00, 0xFF, + 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, + 0xFF, 0xC0, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0xF8, + 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x01, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xC7, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x8F, 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xF0, 0x00, + 0x01, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFF, + 0xFC, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0xFF, 0xF7, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE0, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, + 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, + 0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, + 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, 0xFF, 0xF8, 0x3F, 0xFC, 0x00, + 0x7F, 0xF0, 0x7F, 0xF0, 0x00, 0x7F, 0xF1, 0xFF, 0x80, 0x00, 0x7F, 0xE3, + 0xFF, 0x00, 0x00, 0x7F, 0xEF, 0xFC, 0x00, 0x00, 0xFF, 0xDF, 0xF8, 0x00, + 0x00, 0xFE, 0x3F, 0xE0, 0x00, 0x01, 0x80, 0x7F, 0xC0, 0x00, 0x00, 0x01, + 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x07, 0xFE, 0x00, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x07, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x30, 0x0F, 0xF8, + 0x00, 0x00, 0x7C, 0x1F, 0xF0, 0x00, 0x00, 0xFF, 0x3F, 0xF0, 0x00, 0x03, + 0xFF, 0x7F, 0xE0, 0x00, 0x07, 0xFE, 0x7F, 0xE0, 0x00, 0x1F, 0xF8, 0xFF, + 0xC0, 0x00, 0x3F, 0xF0, 0xFF, 0xC0, 0x00, 0xFF, 0xE1, 0xFF, 0xE0, 0x03, + 0xFF, 0x81, 0xFF, 0xF0, 0x3F, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, + 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, + 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x03, 0xFF, 0xE0, 0x00, + 0x00, 0x04, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, + 0x1F, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, + 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x03, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x0F, 0xE0, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x0F, 0xE0, + 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, + 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, + 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xFE, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x00, 0xFE, + 0xFE, 0x00, 0x00, 0x3F, 0x3F, 0x80, 0x00, 0x1F, 0xC7, 0xF0, 0x00, 0x0F, + 0xE0, 0xFE, 0x00, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3F, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, + 0xFF, 0xFF, 0xE3, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, + 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x3F, 0xC1, 0xFE, + 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, + 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, + 0xFE, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, + 0x8F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x8F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, 0x07, 0xF0, + 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, + 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, + 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, + 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, + 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, + 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, + 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x0F, 0xF8, 0x7F, + 0xC1, 0xFE, 0x0F, 0xF0, 0x3F, 0x81, 0xFE, 0x07, 0xF0, 0x3F, 0x80, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x0F, 0xF8, 0x3F, + 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, + 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, + 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, + 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, + 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, + 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, + 0x83, 0xFE, 0x00, 0x03, 0xFE, 0x00, 0x3F, 0xF8, 0x01, 0xFF, 0xC0, 0x1F, + 0xFF, 0x01, 0xFD, 0xFC, 0x0F, 0xCF, 0xE0, 0xFE, 0x3F, 0x8F, 0xE0, 0xFE, + 0xFE, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, + 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, + 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, + 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, + 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, + 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, + 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, + 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x00, + 0xFF, 0x07, 0xFF, 0xF8, 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, + 0x7F, 0xFF, 0x83, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, + 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, + 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, + 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, + 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, + 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, + 0x1F, 0xF0, 0x00, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, + 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x1F, 0xF0, 0x00, + 0xFF, 0x80, 0x07, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xFF, 0x00, 0x0F, 0xF8, + 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x01, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, + 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xF8, + 0x07, 0xFC, 0x00, 0x3F, 0xFE, 0x01, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x7F, + 0xC0, 0x00, 0x7F, 0xF0, 0x1F, 0xF0, 0x00, 0x0F, 0xFE, 0x07, 0xFC, 0x00, + 0x01, 0xFF, 0x81, 0xFF, 0x00, 0x00, 0x3F, 0xE0, 0x7F, 0xC0, 0x00, 0x0F, + 0xFC, 0x1F, 0xF0, 0x00, 0x03, 0xFF, 0x07, 0xFC, 0x00, 0x00, 0xFF, 0xC1, + 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, + 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x80, + 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, + 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x7F, + 0xC0, 0x00, 0x07, 0xFC, 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0x07, 0xFC, 0x00, + 0x00, 0x7F, 0xC1, 0xFF, 0x00, 0x00, 0x3F, 0xF0, 0x7F, 0xC0, 0x00, 0x0F, + 0xFC, 0x1F, 0xF0, 0x00, 0x03, 0xFE, 0x07, 0xFC, 0x00, 0x01, 0xFF, 0x81, + 0xFF, 0x00, 0x00, 0x7F, 0xE0, 0x7F, 0xC0, 0x00, 0x3F, 0xF0, 0x1F, 0xF0, + 0x00, 0x1F, 0xFC, 0x07, 0xFC, 0x00, 0x3F, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, + 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, + 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFF, + 0xF0, 0x00, 0x00, 0x00, 0x3E, 0x00, 0xF0, 0x00, 0x1F, 0xF0, 0x1E, 0x00, + 0x03, 0xFF, 0x87, 0xC0, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFE, + 0x00, 0x03, 0xC3, 0xFF, 0xC0, 0x00, 0x78, 0x1F, 0xF0, 0x00, 0x0F, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x01, 0xFF, + 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xE0, + 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, + 0xFC, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xF8, 0x00, 0xFF, + 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0x00, + 0x7F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFE, 0xFF, + 0xE0, 0x3F, 0xFF, 0xCF, 0xFC, 0x07, 0xFF, 0xF9, 0xFF, 0xC0, 0xFF, 0xFF, + 0x1F, 0xF8, 0x1F, 0xFF, 0xE1, 0xFF, 0x83, 0xFF, 0xFC, 0x3F, 0xF8, 0x7F, + 0xFF, 0x83, 0xFF, 0x0F, 0xFF, 0xF0, 0x7F, 0xF1, 0xFF, 0xFE, 0x07, 0xFF, + 0x3F, 0xFF, 0xC0, 0x7F, 0xE7, 0xFF, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF, 0x00, + 0xFF, 0xDF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, + 0x80, 0x1F, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x07, + 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, + 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, + 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, + 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, + 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, + 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, + 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, + 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, + 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x07, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, + 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, + 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, + 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, + 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, + 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, + 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, + 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, + 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, + 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x00, + 0x3F, 0xBF, 0x80, 0x00, 0x00, 0x07, 0xE7, 0xF0, 0x00, 0x00, 0x01, 0xFC, + 0x7F, 0x00, 0x00, 0x00, 0x7F, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0xC0, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x03, 0xFF, + 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x3F, 0xFE, 0x00, 0x1F, 0xFE, 0x07, + 0xFF, 0x00, 0x01, 0xFF, 0xE1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x3F, 0xF0, + 0x00, 0x01, 0xFF, 0xCF, 0xFC, 0x00, 0x00, 0x1F, 0xF9, 0xFF, 0x80, 0x00, + 0x03, 0xFF, 0x3F, 0xE0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, + 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x00, 0x0F, 0xFF, 0xFF, + 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x3F, 0xF7, 0xFE, 0x00, + 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0x8F, 0xFC, 0x00, 0x00, + 0x7F, 0xF1, 0xFF, 0xC0, 0x00, 0x1F, 0xFC, 0x1F, 0xFC, 0x00, 0x07, 0xFF, + 0x83, 0xFF, 0xE0, 0x01, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF8, 0x07, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, + 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, + 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xFF, 0x80, + 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x0F, 0x00, + 0x00, 0x01, 0xFF, 0x01, 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x7C, 0x00, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x3C, + 0x3F, 0xFC, 0x00, 0x00, 0x07, 0x81, 0xFF, 0x00, 0x00, 0x00, 0xF0, 0x07, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, + 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE1, 0xFF, + 0x80, 0x00, 0x0F, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xF0, + 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x7F, 0xE0, 0x00, + 0x03, 0xFF, 0x8F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0xFF, 0xE0, 0x00, 0x3F, + 0xFC, 0x1F, 0xFF, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0xFF, 0x00, + 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x00, + 0x0F, 0xF0, 0x7F, 0x80, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x00, 0x3F, + 0xC1, 0xFE, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0xFF, 0x07, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x00, 0x1F, + 0xFF, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0x01, 0xFF, 0xF0, 0x00, 0xFF, 0xF0, + 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xE1, 0xFF, + 0x80, 0x00, 0x0F, 0xFE, 0x7F, 0xE0, 0x00, 0x00, 0xFF, 0xCF, 0xFC, 0x00, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, + 0x3F, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x00, 0x0F, + 0xFF, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFF, + 0xF8, 0x00, 0x00, 0x0F, 0xFD, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xBF, 0xF0, + 0x00, 0x00, 0x7F, 0xE7, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x7F, 0xE0, 0x00, + 0x03, 0xFF, 0x8F, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0xFF, 0xE0, 0x00, 0x3F, + 0xFC, 0x1F, 0xFF, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xF8, 0x0F, 0xFF, 0xC0, + 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xFF, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFC, + 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, + 0x00, 0x07, 0x00, 0xF0, 0x00, 0x3E, 0x0F, 0xE0, 0x01, 0xFC, 0x7F, 0xC0, + 0x0F, 0xFB, 0xFF, 0x80, 0x7F, 0xF7, 0xFF, 0x03, 0xFF, 0x8F, 0xFE, 0x1F, + 0xFC, 0x1F, 0xFC, 0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xF8, + 0x00, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0x80, 0x00, 0x1F, 0xFE, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x07, + 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, + 0xFF, 0xC0, 0x7F, 0xF3, 0xFF, 0x83, 0xFF, 0x87, 0xFF, 0x0F, 0xFC, 0x0F, + 0xFE, 0x7F, 0xE0, 0x1F, 0xFD, 0xFF, 0x00, 0x3F, 0xF3, 0xF8, 0x00, 0x7F, + 0x07, 0xC0, 0x00, 0xF8, 0x0E, 0x00, 0x01, 0xC0, 0x10, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x1F, 0xFC, 0x00, 0x78, 0x00, 0x07, 0xFF, 0xFC, 0x07, 0xE0, 0x01, + 0xFF, 0xFF, 0xFC, 0x7F, 0x80, 0x1F, 0xFF, 0xFF, 0xF3, 0xF8, 0x03, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x0F, + 0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x00, 0x3F, + 0xF8, 0x0F, 0xFE, 0x00, 0x01, 0xFF, 0xE0, 0x7F, 0xE0, 0x00, 0x1F, 0xFF, + 0x07, 0xFE, 0x00, 0x01, 0xFF, 0xFC, 0x3F, 0xF0, 0x00, 0x1F, 0xFF, 0xE1, + 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x1F, 0xF8, 0x00, 0x1F, 0xEF, 0xFC, 0xFF, + 0xC0, 0x01, 0xFE, 0x7F, 0xE7, 0xFC, 0x00, 0x1F, 0xE1, 0xFF, 0x3F, 0xE0, + 0x01, 0xFE, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE0, 0x7F, 0xCF, 0xF8, 0x00, + 0xFE, 0x03, 0xFE, 0x7F, 0xC0, 0x0F, 0xE0, 0x1F, 0xF3, 0xFE, 0x00, 0xFF, + 0x00, 0xFF, 0x9F, 0xF0, 0x0F, 0xF0, 0x07, 0xFC, 0xFF, 0x80, 0xFF, 0x00, + 0x3F, 0xE7, 0xFC, 0x0F, 0xF0, 0x01, 0xFF, 0x3F, 0xE0, 0xFF, 0x00, 0x0F, + 0xF9, 0xFF, 0x8F, 0xF0, 0x00, 0x7F, 0xCF, 0xFC, 0xFF, 0x00, 0x07, 0xFE, + 0x7F, 0xEF, 0xF0, 0x00, 0x3F, 0xF1, 0xFF, 0x7F, 0x00, 0x01, 0xFF, 0x8F, + 0xFF, 0xF0, 0x00, 0x1F, 0xF8, 0x7F, 0xFF, 0x80, 0x00, 0xFF, 0xC1, 0xFF, + 0xF8, 0x00, 0x0F, 0xFE, 0x0F, 0xFF, 0x80, 0x00, 0xFF, 0xE0, 0x3F, 0xF8, + 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0xE0, + 0x3F, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, + 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x3F, 0xDF, 0xFF, 0xFF, 0xF0, 0x03, 0xFC, 0x3F, 0xFF, 0xFF, 0x00, + 0x0F, 0xC0, 0x7F, 0xFF, 0xE0, 0x00, 0x3C, 0x00, 0x7F, 0xF0, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x07, + 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, + 0x00, 0x7F, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0xFE, 0x00, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, + 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, + 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, + 0xFF, 0xE0, 0x00, 0x7F, 0xEF, 0xFE, 0x00, 0x3F, 0xF9, 0xFF, 0xF0, 0x1F, + 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, + 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, + 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x07, + 0xF8, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, + 0x0F, 0xF0, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, + 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, + 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, + 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, + 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, + 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xEF, + 0xFE, 0x00, 0x3F, 0xF9, 0xFF, 0xF0, 0x1F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, + 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, + 0xFF, 0xFC, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xFF, + 0x80, 0x00, 0x03, 0xFB, 0xF8, 0x00, 0x00, 0x7E, 0x7F, 0x00, 0x00, 0x1F, + 0xC7, 0xF0, 0x00, 0x07, 0xF0, 0x7F, 0x00, 0x01, 0xFC, 0x07, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, + 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, + 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, + 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, + 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, + 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, + 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xEF, 0xFE, 0x00, 0x3F, 0xF9, 0xFF, + 0xF0, 0x1F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xF8, + 0x3F, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, + 0xE0, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x00, 0x3F, + 0xFC, 0x00, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x3F, 0xC1, 0xFE, 0x00, + 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x1F, 0xE0, 0xFF, + 0x00, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x0F, 0xF0, + 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x03, 0xFF, + 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, + 0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, + 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, + 0x80, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, + 0x7F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, + 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x7F, 0xF0, 0x01, + 0xFF, 0xCF, 0xFF, 0x80, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, + 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFE, 0x01, + 0xFF, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xE0, + 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, + 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x7F, 0xF7, 0xFE, 0x00, 0x00, 0x1F, 0xF9, + 0xFF, 0xC0, 0x00, 0x0F, 0xFE, 0x3F, 0xF8, 0x00, 0x03, 0xFF, 0x07, 0xFE, + 0x00, 0x01, 0xFF, 0x81, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x3F, 0xF0, 0x00, + 0x3F, 0xF0, 0x07, 0xFE, 0x00, 0x1F, 0xF8, 0x01, 0xFF, 0xC0, 0x07, 0xFE, + 0x00, 0x3F, 0xF0, 0x03, 0xFF, 0x00, 0x07, 0xFE, 0x01, 0xFF, 0x80, 0x01, + 0xFF, 0x80, 0x7F, 0xE0, 0x00, 0x3F, 0xF0, 0x3F, 0xF0, 0x00, 0x0F, 0xFE, + 0x0F, 0xFC, 0x00, 0x01, 0xFF, 0x87, 0xFE, 0x00, 0x00, 0x3F, 0xF1, 0xFF, + 0x00, 0x00, 0x0F, 0xFC, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x00, 0x01, + 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, + 0xC0, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x7F, 0xF8, 0x00, + 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, + 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, + 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, + 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, + 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, + 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, + 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, + 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x80, 0x07, 0xFF, 0xBF, 0xE0, + 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, + 0x80, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFE, 0x00, 0x0F, 0xFE, 0xFF, 0x80, 0x07, + 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, + 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFE, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, + 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, + 0xFF, 0xC0, 0x7F, 0xF0, 0xFF, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, + 0x7F, 0xC0, 0x7F, 0x80, 0x7F, 0xC0, 0x7F, 0x80, 0x7F, 0xC0, 0xFF, 0x80, + 0x7F, 0xC0, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0x80, + 0xFF, 0x00, 0xFF, 0x81, 0xFF, 0x00, 0xFF, 0x81, 0xFE, 0x00, 0xFF, 0x83, + 0xFE, 0x00, 0xFF, 0x83, 0xFC, 0x00, 0xFF, 0x87, 0xFC, 0x00, 0xFF, 0x87, + 0xFE, 0x00, 0xFF, 0x87, 0xFE, 0x00, 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x83, + 0xFF, 0x80, 0xFF, 0x81, 0xFF, 0xC0, 0xFF, 0x81, 0xFF, 0xE0, 0xFF, 0x80, + 0xFF, 0xF0, 0xFF, 0x80, 0x7F, 0xF8, 0xFF, 0x80, 0x3F, 0xFC, 0xFF, 0x80, + 0x1F, 0xFC, 0xFF, 0x80, 0x0F, 0xFE, 0xFF, 0x80, 0x07, 0xFE, 0xFF, 0x80, + 0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x80, 0xC1, 0xFF, 0xFF, 0x83, + 0xE3, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFE, 0xFF, 0x8F, + 0xFF, 0xFC, 0xFF, 0x87, 0xFF, 0xFC, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0x80, + 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x01, 0xFC, + 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xE0, + 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, + 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, 0x81, 0xFF, 0xC3, + 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, 0xFF, 0x01, 0xE0, 0x03, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x01, 0xFF, 0xF0, 0x00, + 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x83, 0xFF, + 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xF3, 0xFC, 0x7F, 0xFC, + 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, + 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, 0xF0, 0x03, 0xFF, 0x3F, 0xF0, 0x0F, + 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x9F, 0xE1, 0xFF, 0xFE, 0x3F, + 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, + 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x00, + 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xF0, 0x0F, + 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF, + 0x81, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, 0xFF, 0x01, 0xE0, + 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x01, + 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, + 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xF3, + 0xFC, 0x7F, 0xFC, 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, 0xFE, 0x00, 0x3F, + 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, 0xF0, 0x03, 0xFF, + 0x3F, 0xF0, 0x0F, 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, + 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0x9F, 0xE1, + 0xFF, 0xFE, 0x3F, 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, 0x80, 0x00, 0x00, + 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xFF, 0xE0, 0x00, + 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x1F, 0x9F, 0xC0, 0x00, + 0x7F, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xFF, 0x80, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, + 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, + 0xFF, 0xC1, 0xFF, 0x81, 0xFF, 0xC3, 0xFC, 0x00, 0xFF, 0x8F, 0xF8, 0x01, + 0xFF, 0x01, 0xE0, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F, + 0xF8, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x7F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFE, + 0x1F, 0xFF, 0xF3, 0xFC, 0x7F, 0xFC, 0x07, 0xF8, 0xFF, 0xC0, 0x0F, 0xF3, + 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0xFF, 0x9F, + 0xF0, 0x03, 0xFF, 0x3F, 0xF0, 0x0F, 0xFE, 0x3F, 0xF0, 0x7F, 0xFC, 0x7F, + 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, + 0xFF, 0x9F, 0xE1, 0xFF, 0xFE, 0x3F, 0xC0, 0xFF, 0xF0, 0x7F, 0xC0, 0x7F, + 0x80, 0x00, 0x00, 0x00, 0xF8, 0x03, 0xC0, 0x07, 0xFC, 0x07, 0x80, 0x0F, + 0xFE, 0x1F, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xF8, 0x00, 0xF0, + 0xFF, 0xF0, 0x01, 0xE0, 0x7F, 0xC0, 0x03, 0xC0, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0xC0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, + 0xE0, 0xFF, 0xC0, 0xFF, 0xE1, 0xFE, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0xFF, + 0x80, 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xFC, + 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xE0, + 0x3F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x0F, + 0xFF, 0xF9, 0xFE, 0x3F, 0xFE, 0x03, 0xFC, 0x7F, 0xE0, 0x07, 0xF9, 0xFF, + 0x00, 0x1F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, + 0x01, 0xFF, 0x9F, 0xF8, 0x07, 0xFF, 0x1F, 0xF8, 0x3F, 0xFE, 0x3F, 0xFF, + 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, + 0xCF, 0xF0, 0xFF, 0xFF, 0x1F, 0xE0, 0x7F, 0xF8, 0x3F, 0xE0, 0x3F, 0xC0, + 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x7F, 0x80, 0x1F, 0xE0, + 0xFF, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0xFF, 0x07, + 0xF8, 0x01, 0xFE, 0x0F, 0xF0, 0x03, 0xFC, 0x1F, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xC0, + 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, + 0x07, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xE0, + 0xFF, 0xC0, 0xFF, 0xE1, 0xFE, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0xFF, 0x80, + 0xF0, 0x01, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xFC, 0x00, + 0x00, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xE0, 0x3F, + 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, + 0xF9, 0xFE, 0x3F, 0xFE, 0x03, 0xFC, 0x7F, 0xE0, 0x07, 0xF9, 0xFF, 0x00, + 0x1F, 0xF3, 0xFE, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x7F, 0xCF, 0xF8, 0x01, + 0xFF, 0x9F, 0xF8, 0x07, 0xFF, 0x1F, 0xF8, 0x3F, 0xFE, 0x3F, 0xFF, 0xFF, + 0xFC, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xCF, + 0xF0, 0xFF, 0xFF, 0x1F, 0xE0, 0x7F, 0xF8, 0x3F, 0xE0, 0x3F, 0xC0, 0x00, + 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x01, 0xE3, 0xC0, 0x00, 0x03, 0x83, 0x80, 0x00, 0x0F, 0x07, 0x00, + 0x00, 0x1E, 0x0F, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x3C, 0x78, 0x00, + 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0xFC, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x80, 0x1F, + 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, + 0xFF, 0xFE, 0x0F, 0xFC, 0x0F, 0xFE, 0x1F, 0xE0, 0x07, 0xFC, 0x7F, 0xC0, + 0x0F, 0xF8, 0x0F, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, + 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, + 0xFE, 0x03, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, + 0xF0, 0xFF, 0xFF, 0x9F, 0xE3, 0xFF, 0xE0, 0x3F, 0xC7, 0xFE, 0x00, 0x7F, + 0x9F, 0xF0, 0x01, 0xFF, 0x3F, 0xE0, 0x03, 0xFE, 0x7F, 0xC0, 0x07, 0xFC, + 0xFF, 0x80, 0x1F, 0xF9, 0xFF, 0x80, 0x7F, 0xF1, 0xFF, 0x83, 0xFF, 0xE3, + 0xFF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xFF, 0x87, + 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xF1, 0xFE, 0x07, 0xFF, 0x83, 0xFE, 0x03, + 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xF0, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0xFF, + 0x83, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xFB, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xFF, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x07, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, + 0xC1, 0xFF, 0xFC, 0x1F, 0xFC, 0x7F, 0xC0, 0x1F, 0xFE, 0x01, 0xFF, 0x1F, + 0xE0, 0x03, 0xFF, 0x00, 0x3F, 0xE0, 0x78, 0x00, 0xFF, 0x80, 0x07, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x7F, + 0x80, 0x00, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x03, 0xFF, 0xFF, 0x00, 0x07, + 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0xF0, + 0x00, 0x00, 0x3F, 0xF0, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFC, 0x00, 0x3F, 0xE0, 0x01, 0xE0, 0xFF, 0x00, 0x1F, + 0xFC, 0x00, 0x7F, 0xBF, 0xE0, 0x07, 0xFF, 0x00, 0x3F, 0xEF, 0xF8, 0x03, + 0xFF, 0xE0, 0x1F, 0xFB, 0xFF, 0x83, 0xFF, 0xFE, 0x0F, 0xFC, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xE0, 0x1F, + 0xFF, 0xF0, 0x3F, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x00, + 0x1F, 0xE0, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x03, 0xFF, + 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, + 0xE0, 0x7F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, + 0x7F, 0xE0, 0x0F, 0xF9, 0xFF, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xF0, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, + 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x3C, 0x3F, 0xE0, 0x00, 0xFF, + 0x7F, 0xC0, 0x07, 0xFD, 0xFF, 0x00, 0x1F, 0xF7, 0xFE, 0x00, 0xFF, 0x8F, + 0xFE, 0x0F, 0xFE, 0x3F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, + 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0x03, 0xFF, + 0xF8, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x3F, 0xFE, + 0x00, 0x00, 0x81, 0xFC, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x0F, 0xC0, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x03, + 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x07, + 0xF0, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x1F, 0xFF, + 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, + 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, + 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, 0x01, 0xFF, 0x1F, 0xF0, 0x01, 0xFE, + 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, + 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, + 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, + 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, + 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, 0xCF, 0xFC, 0x01, 0xFF, 0x8F, 0xFC, + 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, + 0xC0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x00, + 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xC0, + 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xC1, + 0xFF, 0xC1, 0xFF, 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, 0x01, 0xFF, 0x1F, + 0xF0, 0x01, 0xFE, 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, + 0x00, 0x07, 0xFB, 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, + 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, + 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x00, 0x03, 0xFC, 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, 0xCF, 0xFC, 0x01, + 0xFF, 0x8F, 0xFC, 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, 0x1F, 0xFF, 0xFF, + 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFE, + 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x07, 0xFC, 0x00, + 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0xFF, 0xE0, + 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x1F, 0x9F, 0xC0, + 0x00, 0x7F, 0x1F, 0xC0, 0x01, 0xFC, 0x1F, 0xC0, 0x07, 0xF0, 0x1F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0xC0, 0x03, + 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, + 0xFF, 0xFF, 0xC1, 0xFF, 0xC1, 0xFF, 0x83, 0xFE, 0x01, 0xFF, 0x8F, 0xFC, + 0x01, 0xFF, 0x1F, 0xF0, 0x01, 0xFE, 0x3F, 0xE0, 0x03, 0xFE, 0xFF, 0x80, + 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, 0xFE, 0x00, 0x0F, 0xF7, 0xFF, 0xFF, + 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, + 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x3E, 0x07, 0xFC, 0x00, 0x7F, + 0xCF, 0xFC, 0x01, 0xFF, 0x8F, 0xFC, 0x03, 0xFE, 0x1F, 0xFC, 0x1F, 0xFC, + 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x80, + 0x3F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, + 0x07, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x0F, 0xF0, 0x7F, 0x80, + 0x1F, 0xE0, 0xFF, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x7F, 0x83, 0xFC, 0x00, + 0xFF, 0x07, 0xF8, 0x01, 0xFE, 0x0F, 0xF0, 0x03, 0xFC, 0x1F, 0xE0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, + 0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC1, 0xFF, 0x00, 0xFF, 0xC7, 0xFE, 0x00, + 0xFF, 0x8F, 0xF8, 0x00, 0xFF, 0x1F, 0xF0, 0x01, 0xFF, 0x7F, 0xC0, 0x01, + 0xFE, 0xFF, 0x80, 0x03, 0xFD, 0xFF, 0x00, 0x07, 0xFB, 0xFF, 0xFF, 0xFF, + 0xF7, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x1F, 0x03, 0xFE, 0x00, 0x3F, 0xE7, + 0xFE, 0x00, 0xFF, 0xC7, 0xFE, 0x01, 0xFF, 0x0F, 0xFE, 0x0F, 0xFE, 0x0F, + 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, + 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, + 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0xFF, 0x81, 0xFE, 0x03, 0xFC, 0x07, 0xF0, + 0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, + 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, + 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, + 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, + 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, + 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x3F, 0x81, 0xFE, 0x07, 0xF0, + 0x3F, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, + 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, + 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, + 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, + 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, + 0xFE, 0x07, 0xF8, 0x1F, 0xE0, 0x7F, 0x81, 0xFE, 0x00, 0x03, 0xFE, 0x00, + 0x3F, 0xF8, 0x01, 0xFF, 0xC0, 0x1F, 0xFF, 0x01, 0xFD, 0xFC, 0x0F, 0xCF, + 0xE0, 0xFE, 0x3F, 0x8F, 0xE0, 0xFE, 0xFE, 0x03, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x07, 0xF8, + 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, + 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, + 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, + 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, + 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, + 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, + 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0xFF, 0x07, + 0xFF, 0xF8, 0x3F, 0xFF, 0xC1, 0xFF, 0xFE, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, + 0x83, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, + 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, + 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, + 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, + 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, + 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, + 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, + 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0xFF, 0x80, + 0x80, 0x00, 0x3F, 0xE1, 0xE0, 0x00, 0x07, 0xFB, 0xF0, 0x00, 0x01, 0xFF, + 0xF0, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x7F, + 0xFC, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x01, 0xFC, 0x7F, 0x80, 0x00, 0x78, + 0x1F, 0xE0, 0x00, 0x30, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x03, + 0xF8, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, + 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, + 0xFF, 0xFF, 0xFF, 0x87, 0xFF, 0x83, 0xFF, 0xE7, 0xFF, 0x00, 0xFF, 0xF3, + 0xFF, 0x00, 0x1F, 0xFB, 0xFF, 0x00, 0x0F, 0xFD, 0xFF, 0x80, 0x03, 0xFF, + 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, + 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, + 0xFF, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x7F, 0xCF, 0xF8, 0x00, + 0x7F, 0xE7, 0xFE, 0x00, 0x3F, 0xF1, 0xFF, 0x80, 0x3F, 0xF0, 0xFF, 0xF0, + 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, + 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0x07, + 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xF8, 0x03, 0xC0, 0x0F, + 0xF8, 0x0F, 0x00, 0x3F, 0xF8, 0x7C, 0x01, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, + 0xFF, 0x80, 0x1E, 0x1F, 0xFE, 0x00, 0x78, 0x1F, 0xF0, 0x01, 0xE0, 0x0F, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x80, 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x3F, 0xFF, 0x8F, + 0xF1, 0xFF, 0xFF, 0x3F, 0xCF, 0xFF, 0xFE, 0xFF, 0x7F, 0xFF, 0xFB, 0xFF, + 0xFF, 0xFF, 0xEF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xE0, + 0x07, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF0, 0x01, + 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, + 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, + 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x00, + 0xFF, 0xFF, 0x80, 0x03, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x3F, + 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x03, 0xFC, 0x01, 0xFF, 0x00, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x00, + 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0x80, + 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x07, 0xFF, + 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFC, 0x07, 0xFF, + 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, 0x00, 0x7F, 0xE3, 0xFF, + 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, 0x80, 0x03, 0xFE, 0xFF, + 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, + 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x3F, + 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0xC0, 0x1F, + 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, + 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, + 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x00, + 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, + 0x7F, 0x80, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0x1F, 0xC0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFE, 0x00, + 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFC, + 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, 0x00, 0x7F, + 0xE3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, 0x80, 0x03, + 0xFE, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, + 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xF8, 0x00, + 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x80, + 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xF0, + 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, + 0xC0, 0x1F, 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFC, 0x0F, + 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xFC, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xE0, 0x00, + 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x00, + 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x07, 0xF7, 0xF0, 0x00, 0x03, 0xF3, 0xF8, + 0x00, 0x03, 0xF8, 0xFE, 0x00, 0x03, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x0F, + 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, + 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, + 0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, + 0x00, 0x7F, 0xE3, 0xFF, 0x00, 0x1F, 0xF9, 0xFF, 0x00, 0x07, 0xFD, 0xFF, + 0x80, 0x03, 0xFE, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, + 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFE, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x3F, + 0xFF, 0xF0, 0x00, 0x3F, 0xE7, 0xFC, 0x00, 0x1F, 0xF3, 0xFF, 0x00, 0x1F, + 0xF9, 0xFF, 0xC0, 0x1F, 0xF8, 0x7F, 0xF8, 0x3F, 0xF8, 0x1F, 0xFF, 0xFF, + 0xFC, 0x0F, 0xFF, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, + 0xFC, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F, + 0xE0, 0x00, 0x00, 0x7C, 0x01, 0xE0, 0x00, 0xFF, 0x80, 0xF0, 0x00, 0x7F, + 0xF0, 0xF8, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x1E, + 0x1F, 0xFE, 0x00, 0x0F, 0x03, 0xFE, 0x00, 0x07, 0x80, 0x3E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, + 0x0F, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF8, + 0x0F, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0x07, 0xFF, 0x87, 0xFE, 0x00, 0xFF, + 0xC7, 0xFE, 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x0F, 0xFB, 0xFF, 0x00, 0x07, + 0xFD, 0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, + 0x7F, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, + 0x0F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0x00, + 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, + 0x00, 0x7F, 0xCF, 0xF8, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x3F, 0xF3, 0xFF, + 0x80, 0x3F, 0xF0, 0xFF, 0xF0, 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x00, + 0x3F, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x03, 0xFC, 0x1F, 0xE0, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0xFF, 0x07, 0xF8, + 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x1F, 0xE0, 0xFF, + 0x00, 0x0F, 0xF0, 0x7F, 0x80, 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, + 0x00, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, + 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, + 0xFF, 0xFE, 0x0F, 0xFF, 0x07, 0xFF, 0x87, 0xFE, 0x00, 0xFF, 0xC7, 0xFE, + 0x00, 0x3F, 0xF3, 0xFE, 0x00, 0x0F, 0xFB, 0xFF, 0x00, 0x07, 0xFD, 0xFF, + 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, + 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x0F, 0xFF, + 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x01, 0xFF, + 0xFF, 0x80, 0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xE0, 0x00, 0x7F, + 0xCF, 0xF8, 0x00, 0x3F, 0xE7, 0xFE, 0x00, 0x3F, 0xF3, 0xFF, 0x80, 0x3F, + 0xF0, 0xFF, 0xF0, 0x7F, 0xF0, 0x3F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, + 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, + 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x1F, + 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, + 0x80, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, + 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, + 0x3F, 0xE0, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, + 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0xFE, 0x03, 0xC0, 0x0F, 0xFF, 0xE3, 0xF0, 0x1F, 0xFF, 0xFB, 0xF0, 0x1F, + 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, + 0xFF, 0xFF, 0xFC, 0x1F, 0xFE, 0x0F, 0xFF, 0x0F, 0xFC, 0x01, 0xFF, 0x8F, + 0xFC, 0x01, 0xFF, 0xE7, 0xFC, 0x01, 0xFF, 0xF7, 0xFC, 0x00, 0xFF, 0xFB, + 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFD, 0xFF, 0xFF, 0x00, 0xFC, 0xFF, + 0xFF, 0x80, 0xFC, 0x3F, 0xFF, 0xC0, 0xFC, 0x1F, 0xFF, 0xE0, 0x7C, 0x0F, + 0xFF, 0xF0, 0x7E, 0x07, 0xFF, 0xF8, 0x7E, 0x03, 0xFF, 0xFE, 0x7E, 0x01, + 0xFF, 0xFF, 0x7E, 0x01, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xBF, 0xFE, 0x00, + 0x7F, 0xDF, 0xFF, 0x00, 0x7F, 0xCF, 0xFF, 0x00, 0x7F, 0xE3, 0xFF, 0x00, + 0x7F, 0xE1, 0xFF, 0xE0, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, + 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, + 0xFF, 0xF0, 0x1F, 0x8F, 0xFF, 0xE0, 0x07, 0x80, 0xFF, 0x80, 0x01, 0x80, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x0F, + 0xF0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xFF, + 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, + 0x3F, 0xF7, 0xFE, 0x01, 0xFF, 0xDF, 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, + 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, + 0x0F, 0xFF, 0xE3, 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, + 0x00, 0x01, 0xFF, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xC0, 0x00, + 0x01, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, 0x3F, 0xF7, 0xFE, + 0x01, 0xFF, 0xDF, 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, + 0xFF, 0xF3, 0xFF, 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xE3, + 0xFC, 0x1F, 0xFE, 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x00, 0x1F, 0xF0, + 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0xFE, 0xFE, 0x00, 0x03, 0xF3, 0xF8, 0x00, 0x1F, 0xC7, 0xF0, 0x00, + 0xFE, 0x0F, 0xE0, 0x07, 0xF0, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x0F, 0xFD, 0xFF, 0x00, 0x3F, 0xF7, 0xFE, 0x01, 0xFF, 0xDF, + 0xFC, 0x1F, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, + 0xFF, 0xBF, 0xC7, 0xFF, 0xFC, 0xFF, 0x0F, 0xFF, 0xE3, 0xFC, 0x1F, 0xFE, + 0x0F, 0xF0, 0x0F, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x1F, 0xE0, + 0xFF, 0x00, 0x7F, 0x83, 0xFC, 0x01, 0xFE, 0x0F, 0xF0, 0x07, 0xF8, 0x3F, + 0xC0, 0x1F, 0xE0, 0xFF, 0x00, 0x7F, 0x83, 0xFC, 0x01, 0xFE, 0x0F, 0xF0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, + 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, + 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, + 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xF8, + 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, + 0x1F, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0x7F, 0xC0, 0x0F, + 0xFD, 0xFF, 0x80, 0x7F, 0xF7, 0xFF, 0x07, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, + 0x3F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xEF, 0xF1, 0xFF, 0xFF, 0x3F, 0xC3, + 0xFF, 0xF8, 0xFF, 0x07, 0xFF, 0x83, 0xFC, 0x03, 0xF8, 0x00, 0x00, 0x00, + 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, + 0x00, 0x07, 0xF8, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x07, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xF7, 0xFC, + 0x00, 0x07, 0xF9, 0xFF, 0x00, 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x8F, + 0xF8, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xFC, + 0x1F, 0xF0, 0x01, 0xFE, 0x03, 0xFC, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, + 0xE0, 0x3F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x07, 0xFC, 0x01, 0xFF, 0x01, + 0xFE, 0x00, 0x3F, 0xC0, 0x7F, 0x80, 0x0F, 0xF0, 0x3F, 0xE0, 0x03, 0xFE, + 0x0F, 0xF0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x1F, 0xE1, 0xFF, 0x00, 0x07, + 0xFC, 0x7F, 0x80, 0x00, 0xFF, 0x1F, 0xE0, 0x00, 0x3F, 0xCF, 0xF8, 0x00, + 0x07, 0xFB, 0xFC, 0x00, 0x01, 0xFE, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xC0, + 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFC, + 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0xFF, + 0xE0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x01, + 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xF0, 0x00, 0x00, + 0x0F, 0xF8, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, + 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, + 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x80, + 0x00, 0x07, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0xC0, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x81, + 0xFC, 0x00, 0xFF, 0x87, 0xFF, 0x00, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0xBF, + 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xFC, 0xFF, 0xFC, 0x1F, 0xFC, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xE0, + 0x07, 0xFE, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x80, + 0x01, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFE, 0xFF, 0xC0, + 0x03, 0xFE, 0xFF, 0xE0, 0x07, 0xFE, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0xFC, + 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, + 0xFF, 0xF0, 0xFF, 0xBF, 0xFF, 0xE0, 0xFF, 0x9F, 0xFF, 0xC0, 0xFF, 0x87, + 0xFF, 0x00, 0xFF, 0x81, 0xFC, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0x80, + 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x7F, + 0x83, 0xFC, 0x00, 0x1F, 0xE0, 0xFF, 0x00, 0x07, 0xF8, 0x3F, 0xC0, 0x01, + 0xFE, 0x0F, 0xF0, 0x00, 0x7F, 0x83, 0xFC, 0x00, 0x1F, 0xE0, 0xFF, 0x00, + 0x07, 0xF8, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, + 0x7F, 0xDF, 0xF0, 0x00, 0x1F, 0xE7, 0xFC, 0x00, 0x0F, 0xF8, 0xFF, 0x80, + 0x03, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x07, 0xF8, 0x00, 0x7F, 0xC1, 0xFF, + 0x00, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF8, 0x0F, 0xF0, 0x03, 0xFE, 0x03, + 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x1F, 0xF0, + 0x07, 0xFC, 0x07, 0xF8, 0x00, 0xFF, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0xFF, + 0x80, 0x0F, 0xF8, 0x3F, 0xC0, 0x01, 0xFE, 0x0F, 0xF0, 0x00, 0x7F, 0x87, + 0xFC, 0x00, 0x1F, 0xF1, 0xFE, 0x00, 0x03, 0xFC, 0x7F, 0x80, 0x00, 0xFF, + 0x3F, 0xE0, 0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x07, 0xFB, 0xFC, 0x00, 0x01, + 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xE0, 0x00, + 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0x00, + 0x00, 0x03, 0xFF, 0x80, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x3F, 0xF8, + 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, + 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, + 0xFE, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x1F, + 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, + 0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x80, 0x00, + 0x01, 0xFF, 0x00, 0x00, 0x00 }; + +const GFXglyph myFont32pt8bGlyphs[] PROGMEM = { + { 0, 0, 0, 18, 0, 1 }, // 0x20 ' ' + { 0, 9, 45, 21, 6, -44 }, // 0x21 '!' + { 51, 24, 16, 30, 3, -44 }, // 0x22 '"' + { 99, 33, 45, 35, 1, -44 }, // 0x23 '#' + { 285, 30, 55, 35, 2, -47 }, // 0x24 '$' + { 492, 50, 48, 56, 3, -45 }, // 0x25 '%' + { 792, 41, 47, 46, 3, -45 }, // 0x26 '&' + { 1033, 9, 16, 15, 3, -44 }, // 0x27 ''' + { 1051, 16, 58, 21, 3, -44 }, // 0x28 '(' + { 1167, 16, 58, 21, 2, -44 }, // 0x29 ')' + { 1283, 22, 21, 25, 1, -44 }, // 0x2A '*' + { 1341, 31, 32, 37, 3, -37 }, // 0x2B '+' + { 1465, 9, 19, 18, 4, -8 }, // 0x2C ',' + { 1487, 17, 8, 21, 4, -19 }, // 0x2D '-' + { 1504, 8, 9, 18, 5, -8 }, // 0x2E '.' + { 1513, 18, 45, 18, 0, -44 }, // 0x2F '/' + { 1615, 29, 46, 35, 3, -44 }, // 0x30 '0' + { 1782, 20, 45, 35, 5, -44 }, // 0x31 '1' + { 1895, 30, 45, 35, 2, -44 }, // 0x32 '2' + { 2064, 30, 46, 35, 2, -44 }, // 0x33 '3' + { 2237, 33, 44, 35, 1, -43 }, // 0x34 '4' + { 2419, 30, 45, 35, 3, -43 }, // 0x35 '5' + { 2588, 30, 46, 35, 3, -44 }, // 0x36 '6' + { 2761, 29, 44, 35, 3, -43 }, // 0x37 '7' + { 2921, 29, 46, 35, 3, -44 }, // 0x38 '8' + { 3088, 30, 46, 35, 2, -44 }, // 0x39 '9' + { 3261, 9, 33, 21, 6, -32 }, // 0x3A ':' + { 3299, 10, 43, 21, 5, -32 }, // 0x3B ';' + { 3353, 31, 34, 37, 3, -38 }, // 0x3C '<' + { 3485, 31, 22, 37, 3, -32 }, // 0x3D '=' + { 3571, 31, 34, 37, 3, -38 }, // 0x3E '>' + { 3703, 33, 46, 38, 3, -45 }, // 0x3F '?' + { 3893, 59, 61, 61, 2, -45 }, // 0x40 '@' + { 4343, 45, 45, 46, 0, -44 }, // 0x41 'A' + { 4597, 37, 45, 46, 5, -44 }, // 0x42 'B' + { 4806, 39, 46, 46, 3, -45 }, // 0x43 'C' + { 5031, 37, 45, 46, 5, -44 }, // 0x44 'D' + { 5240, 34, 45, 42, 5, -44 }, // 0x45 'E' + { 5432, 31, 45, 38, 5, -44 }, // 0x46 'F' + { 5607, 42, 47, 49, 3, -45 }, // 0x47 'G' + { 5854, 36, 45, 46, 5, -44 }, // 0x48 'H' + { 6057, 9, 45, 18, 4, -44 }, // 0x49 'I' + { 6108, 29, 46, 35, 1, -44 }, // 0x4A 'J' + { 6275, 40, 45, 46, 5, -44 }, // 0x4B 'K' + { 6500, 32, 45, 38, 5, -44 }, // 0x4C 'L' + { 6680, 44, 45, 52, 4, -44 }, // 0x4D 'M' + { 6928, 35, 45, 46, 5, -44 }, // 0x4E 'N' + { 7125, 43, 47, 49, 3, -45 }, // 0x4F 'O' + { 7378, 34, 45, 42, 5, -44 }, // 0x50 'P' + { 7570, 45, 51, 49, 3, -45 }, // 0x51 'Q' + { 7857, 40, 45, 46, 5, -44 }, // 0x52 'R' + { 8082, 37, 47, 42, 2, -45 }, // 0x53 'S' + { 8300, 36, 45, 38, 1, -44 }, // 0x54 'T' + { 8503, 35, 46, 46, 5, -44 }, // 0x55 'U' + { 8705, 42, 45, 42, 0, -44 }, // 0x56 'V' + { 8942, 59, 45, 59, 0, -44 }, // 0x57 'W' + { 9274, 42, 45, 42, 0, -44 }, // 0x58 'X' + { 9511, 42, 45, 42, 0, -44 }, // 0x59 'Y' + { 9748, 36, 45, 38, 1, -44 }, // 0x5A 'Z' + { 9951, 16, 58, 21, 4, -44 }, // 0x5B '[' + { 10067, 18, 45, 18, 0, -44 }, // 0x5C '\' + { 10169, 15, 58, 21, 1, -44 }, // 0x5D ']' + { 10278, 29, 24, 37, 4, -45 }, // 0x5E '^' + { 10365, 36, 7, 35, -1, 6 }, // 0x5F '_' + { 10397, 14, 9, 21, 1, -44 }, // 0x60 '`' + { 10413, 31, 35, 35, 2, -33 }, // 0x61 'a' + { 10549, 32, 46, 38, 4, -44 }, // 0x62 'b' + { 10733, 30, 35, 35, 3, -33 }, // 0x63 'c' + { 10865, 31, 46, 38, 3, -44 }, // 0x64 'd' + { 11044, 31, 35, 35, 2, -33 }, // 0x65 'e' + { 11180, 22, 46, 21, 1, -45 }, // 0x66 'f' + { 11307, 31, 48, 38, 3, -33 }, // 0x67 'g' + { 11493, 30, 45, 38, 4, -44 }, // 0x68 'h' + { 11662, 8, 45, 18, 5, -44 }, // 0x69 'i' + { 11707, 16, 59, 18, -3, -44 }, // 0x6A 'j' + { 11825, 30, 45, 35, 4, -44 }, // 0x6B 'k' + { 11994, 8, 45, 18, 5, -44 }, // 0x6C 'l' + { 12039, 48, 34, 56, 4, -33 }, // 0x6D 'm' + { 12243, 30, 34, 38, 4, -33 }, // 0x6E 'n' + { 12371, 33, 35, 38, 3, -33 }, // 0x6F 'o' + { 12516, 32, 47, 38, 4, -33 }, // 0x70 'p' + { 12704, 32, 47, 38, 3, -33 }, // 0x71 'q' + { 12892, 21, 34, 25, 4, -33 }, // 0x72 'r' + { 12982, 31, 35, 35, 1, -33 }, // 0x73 's' + { 13118, 19, 45, 21, 1, -43 }, // 0x74 't' + { 13225, 30, 34, 38, 4, -32 }, // 0x75 'u' + { 13353, 34, 33, 35, 0, -32 }, // 0x76 'v' + { 13494, 49, 33, 49, 0, -32 }, // 0x77 'w' + { 13697, 34, 33, 35, 0, -32 }, // 0x78 'x' + { 13838, 34, 47, 35, 0, -32 }, // 0x79 'y' + { 14038, 29, 33, 32, 1, -32 }, // 0x7A 'z' + { 14158, 21, 60, 25, 2, -45 }, // 0x7B '{' + { 14316, 7, 59, 18, 5, -44 }, // 0x7C '|' + { 14368, 21, 60, 25, 1, -45 }, // 0x7D '}' + { 14526, 33, 12, 37, 2, -27 }, // 0x7E '~' + { 14576, 31, 39, 47, 8, -38 }, // 0x7F + { 14728, 31, 39, 47, 8, -38 }, // 0x80 + { 14880, 31, 39, 47, 8, -38 }, // 0x81 + { 15032, 31, 39, 47, 8, -38 }, // 0x82 + { 15184, 31, 39, 47, 8, -38 }, // 0x83 + { 15336, 31, 39, 47, 8, -38 }, // 0x84 + { 15488, 31, 39, 47, 8, -38 }, // 0x85 + { 15640, 31, 39, 47, 8, -38 }, // 0x86 + { 15792, 31, 39, 47, 8, -38 }, // 0x87 + { 15944, 31, 39, 47, 8, -38 }, // 0x88 + { 16096, 31, 39, 47, 8, -38 }, // 0x89 + { 16248, 31, 39, 47, 8, -38 }, // 0x8A + { 16400, 31, 39, 47, 8, -38 }, // 0x8B + { 16552, 31, 39, 47, 8, -38 }, // 0x8C + { 16704, 31, 39, 47, 8, -38 }, // 0x8D + { 16856, 31, 39, 47, 8, -38 }, // 0x8E + { 17008, 31, 39, 47, 8, -38 }, // 0x8F + { 17160, 31, 39, 47, 8, -38 }, // 0x90 + { 17312, 31, 39, 47, 8, -38 }, // 0x91 + { 17464, 31, 39, 47, 8, -38 }, // 0x92 + { 17616, 31, 39, 47, 8, -38 }, // 0x93 + { 17768, 31, 39, 47, 8, -38 }, // 0x94 + { 17920, 31, 39, 47, 8, -38 }, // 0x95 + { 18072, 31, 39, 47, 8, -38 }, // 0x96 + { 18224, 31, 39, 47, 8, -38 }, // 0x97 + { 18376, 31, 39, 47, 8, -38 }, // 0x98 + { 18528, 31, 39, 47, 8, -38 }, // 0x99 + { 18680, 31, 39, 47, 8, -38 }, // 0x9A + { 18832, 31, 39, 47, 8, -38 }, // 0x9B + { 18984, 31, 39, 47, 8, -38 }, // 0x9C + { 19136, 31, 39, 47, 8, -38 }, // 0x9D + { 19288, 31, 39, 47, 8, -38 }, // 0x9E + { 19440, 31, 39, 47, 8, -38 }, // 0x9F + { 19592, 0, 0, 18, 0, 1 }, // 0xA0 + { 19592, 9, 46, 21, 6, -32 }, // 0xA1 + { 19644, 30, 58, 35, 3, -44 }, // 0xA2 + { 19862, 34, 47, 35, 0, -45 }, // 0xA3 + { 20062, 32, 33, 35, 1, -38 }, // 0xA4 + { 20194, 35, 45, 35, 0, -44 }, // 0xA5 + { 20391, 7, 59, 18, 5, -44 }, // 0xA6 + { 20443, 31, 59, 35, 2, -45 }, // 0xA7 + { 20672, 21, 8, 21, 0, -44 }, // 0xA8 + { 20693, 47, 47, 46, 0, -45 }, // 0xA9 + { 20970, 21, 23, 23, 1, -45 }, // 0xAA + { 21031, 29, 29, 35, 3, -30 }, // 0xAB + { 21137, 31, 22, 37, 3, -32 }, // 0xAC + { 21223, 17, 8, 21, 4, -19 }, // 0xAD + { 21240, 47, 47, 46, 0, -45 }, // 0xAE + { 21517, 36, 7, 35, -1, -54 }, // 0xAF + { 21549, 19, 19, 25, 3, -45 }, // 0xB0 + { 21595, 31, 43, 35, 2, -42 }, // 0xB1 + { 21762, 18, 23, 21, 1, -45 }, // 0xB2 + { 21814, 19, 23, 21, 1, -45 }, // 0xB3 + { 21869, 14, 9, 21, 6, -44 }, // 0xB4 + { 21885, 30, 46, 36, 3, -32 }, // 0xB5 + { 22058, 35, 57, 35, 0, -44 }, // 0xB6 + { 22308, 9, 9, 21, 6, -26 }, // 0xB7 + { 22319, 17, 11, 21, 1, 1 }, // 0xB8 + { 22343, 12, 23, 21, 3, -45 }, // 0xB9 + { 22378, 21, 23, 23, 1, -45 }, // 0xBA + { 22439, 29, 29, 35, 3, -30 }, // 0xBB + { 22545, 49, 46, 53, 3, -44 }, // 0xBC + { 22827, 48, 47, 53, 3, -45 }, // 0xBD + { 23109, 51, 47, 53, 1, -45 }, // 0xBE + { 23409, 33, 47, 38, 3, -32 }, // 0xBF + { 23603, 45, 58, 46, 0, -57 }, // 0xC0 + { 23930, 45, 58, 46, 0, -57 }, // 0xC1 + { 24257, 45, 58, 46, 0, -57 }, // 0xC2 + { 24584, 45, 57, 46, 0, -56 }, // 0xC3 + { 24905, 45, 57, 46, 0, -56 }, // 0xC4 + { 25226, 45, 54, 46, 0, -53 }, // 0xC5 + { 25530, 63, 45, 63, -3, -44 }, // 0xC6 + { 25885, 39, 57, 46, 3, -45 }, // 0xC7 + { 26163, 34, 58, 42, 5, -57 }, // 0xC8 + { 26410, 34, 58, 42, 5, -57 }, // 0xC9 + { 26657, 34, 58, 42, 5, -57 }, // 0xCA + { 26904, 34, 57, 42, 5, -56 }, // 0xCB + { 27147, 14, 58, 18, -1, -57 }, // 0xCC + { 27249, 14, 58, 18, 4, -57 }, // 0xCD + { 27351, 21, 58, 18, -1, -57 }, // 0xCE + { 27504, 21, 57, 18, -2, -56 }, // 0xCF + { 27654, 42, 45, 46, 0, -44 }, // 0xD0 + { 27891, 35, 57, 46, 5, -56 }, // 0xD1 + { 28141, 43, 59, 49, 3, -57 }, // 0xD2 + { 28459, 43, 59, 49, 3, -57 }, // 0xD3 + { 28777, 43, 59, 49, 3, -57 }, // 0xD4 + { 29095, 43, 58, 49, 3, -56 }, // 0xD5 + { 29407, 43, 58, 49, 3, -56 }, // 0xD6 + { 29719, 30, 30, 37, 3, -36 }, // 0xD7 + { 29832, 45, 50, 49, 2, -47 }, // 0xD8 + { 30114, 35, 59, 46, 5, -57 }, // 0xD9 + { 30373, 35, 59, 46, 5, -57 }, // 0xDA + { 30632, 35, 59, 46, 5, -57 }, // 0xDB + { 30891, 35, 58, 46, 5, -56 }, // 0xDC + { 31145, 42, 58, 42, 0, -57 }, // 0xDD + { 31450, 34, 45, 42, 5, -44 }, // 0xDE + { 31642, 32, 47, 38, 4, -45 }, // 0xDF + { 31830, 31, 47, 35, 2, -45 }, // 0xE0 + { 32013, 31, 47, 35, 2, -45 }, // 0xE1 + { 32196, 31, 47, 35, 2, -45 }, // 0xE2 + { 32379, 31, 46, 35, 2, -44 }, // 0xE3 + { 32558, 31, 46, 35, 2, -44 }, // 0xE4 + { 32737, 31, 50, 35, 2, -48 }, // 0xE5 + { 32931, 50, 35, 56, 3, -33 }, // 0xE6 + { 33150, 30, 45, 35, 3, -33 }, // 0xE7 + { 33319, 31, 47, 35, 2, -45 }, // 0xE8 + { 33502, 31, 47, 35, 2, -45 }, // 0xE9 + { 33685, 31, 47, 35, 2, -45 }, // 0xEA + { 33868, 31, 46, 35, 2, -44 }, // 0xEB + { 34047, 14, 46, 18, -1, -45 }, // 0xEC + { 34128, 14, 46, 18, 4, -45 }, // 0xED + { 34209, 21, 46, 18, -2, -45 }, // 0xEE + { 34330, 21, 45, 18, -2, -44 }, // 0xEF + { 34449, 33, 46, 38, 3, -44 }, // 0xF0 + { 34639, 30, 45, 38, 4, -44 }, // 0xF1 + { 34808, 33, 47, 38, 3, -45 }, // 0xF2 + { 35002, 33, 47, 38, 3, -45 }, // 0xF3 + { 35196, 33, 47, 38, 3, -45 }, // 0xF4 + { 35390, 33, 46, 38, 3, -44 }, // 0xF5 + { 35580, 33, 46, 38, 3, -44 }, // 0xF6 + { 35770, 31, 32, 35, 2, -37 }, // 0xF7 + { 35894, 33, 38, 38, 3, -35 }, // 0xF8 + { 36051, 30, 47, 38, 4, -45 }, // 0xF9 + { 36228, 30, 47, 38, 4, -45 }, // 0xFA + { 36405, 30, 47, 38, 4, -45 }, // 0xFB + { 36582, 30, 46, 38, 4, -44 }, // 0xFC + { 36755, 34, 60, 35, 0, -45 }, // 0xFD + { 37010, 32, 58, 38, 4, -44 }, // 0xFE + { 37242, 34, 59, 35, 0, -44 } }; // 0xFF + +const GFXfont myFont32pt8b PROGMEM = { + (uint8_t *)myFont32pt8bBitmaps, + (GFXglyph *)myFont32pt8bGlyphs, + 0x20, 0xFF, 72 }; + +// Approx. 39068 bytes diff --git a/examples/Generic/On_Off_Button/On_Off_Button.ino b/examples/Generic/On_Off_Button/On_Off_Button.ino new file mode 100644 index 0000000..035cf6e --- /dev/null +++ b/examples/Generic/On_Off_Button/On_Off_Button.ino @@ -0,0 +1,206 @@ +// Example of drawing a graphical "switch" and using +// the touch screen to change it's state. + +// This sketch does not use the libraries button drawing +// and handling functions. + +// Based on Adafruit_GFX library onoffbutton example. + +// Touch handling for XPT2046 based screens is handled by +// the TFT_eSPI library. + +// Calibration data is stored in SPIFFS so we need to include it +#include "FS.h" + +#include + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +// This is the file name used to store the touch coordinate +// calibration data. Cahnge the name to start a new calibration. +#define CALIBRATION_FILE "/TouchCalData3" + +// Set REPEAT_CAL to true instead of false to run calibration +// again, otherwise it will only be done once. +// Repeat calibration if you change the screen rotation. +#define REPEAT_CAL false + +boolean SwitchOn = false; + +// Comment out to stop drawing black spots +#define BLACK_SPOT + +// Switch position and size +#define FRAME_X 100 +#define FRAME_Y 64 +#define FRAME_W 120 +#define FRAME_H 50 + +// Red zone size +#define REDBUTTON_X FRAME_X +#define REDBUTTON_Y FRAME_Y +#define REDBUTTON_W (FRAME_W/2) +#define REDBUTTON_H FRAME_H + +// Green zone size +#define GREENBUTTON_X (REDBUTTON_X + REDBUTTON_W) +#define GREENBUTTON_Y FRAME_Y +#define GREENBUTTON_W (FRAME_W/2) +#define GREENBUTTON_H FRAME_H + +//------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------ +void setup(void) +{ + Serial.begin(9600); + tft.init(); + + // Set the rotation before we calibrate + tft.setRotation(1); + + // call screen calibration + touch_calibrate(); + + // clear screen + tft.fillScreen(TFT_BLUE); + + // Draw button (this example does not use library Button class) + redBtn(); +} +//------------------------------------------------------------------------------------------ +//------------------------------------------------------------------------------------------ +void loop() +{ + uint16_t x, y; + + // See if there's any touch data for us + if (tft.getTouch(&x, &y)) + { + // Draw a block spot to show where touch was calculated to be + #ifdef BLACK_SPOT + tft.fillCircle(x, y, 2, TFT_BLACK); + #endif + + if (SwitchOn) + { + if ((x > REDBUTTON_X) && (x < (REDBUTTON_X + REDBUTTON_W))) { + if ((y > REDBUTTON_Y) && (y <= (REDBUTTON_Y + REDBUTTON_H))) { + Serial.println("Red btn hit"); + redBtn(); + } + } + } + else //Record is off (SwitchOn == false) + { + if ((x > GREENBUTTON_X) && (x < (GREENBUTTON_X + GREENBUTTON_W))) { + if ((y > GREENBUTTON_Y) && (y <= (GREENBUTTON_Y + GREENBUTTON_H))) { + Serial.println("Green btn hit"); + greenBtn(); + } + } + } + + Serial.println(SwitchOn); + + } +} +//------------------------------------------------------------------------------------------ + +void touch_calibrate() +{ + uint16_t calData[5]; + uint8_t calDataOK = 0; + + // check file system exists + if (!SPIFFS.begin()) { + Serial.println("Formating file system"); + SPIFFS.format(); + SPIFFS.begin(); + } + + // check if calibration file exists and size is correct + if (SPIFFS.exists(CALIBRATION_FILE)) { + if (REPEAT_CAL) + { + // Delete if we want to re-calibrate + SPIFFS.remove(CALIBRATION_FILE); + } + else + { + File f = SPIFFS.open(CALIBRATION_FILE, "r"); + if (f) { + if (f.readBytes((char *)calData, 14) == 14) + calDataOK = 1; + f.close(); + } + } + } + + if (calDataOK && !REPEAT_CAL) { + // calibration data valid + tft.setTouch(calData); + } else { + // data not valid so recalibrate + tft.fillScreen(TFT_BLACK); + tft.setCursor(20, 0); + tft.setTextFont(2); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + tft.println("Touch corners as indicated"); + + tft.setTextFont(1); + tft.println(); + + if (REPEAT_CAL) { + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Set REPEAT_CAL to false to stop this running again!"); + } + + tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Calibration complete!"); + + // store data + File f = SPIFFS.open(CALIBRATION_FILE, "w"); + if (f) { + f.write((const unsigned char *)calData, 14); + f.close(); + } + } +} + +void drawFrame() +{ + tft.drawRect(FRAME_X, FRAME_Y, FRAME_W, FRAME_H, TFT_BLACK); +} + +// Draw a red button +void redBtn() +{ + tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_RED); + tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_DARKGREY); + drawFrame(); + tft.setTextColor(TFT_WHITE); + tft.setTextSize(2); + tft.setTextDatum(MC_DATUM); + tft.drawString("ON", GREENBUTTON_X + (GREENBUTTON_W / 2), GREENBUTTON_Y + (GREENBUTTON_H / 2)); + SwitchOn = false; +} + +// Draw a green button +void greenBtn() +{ + tft.fillRect(GREENBUTTON_X, GREENBUTTON_Y, GREENBUTTON_W, GREENBUTTON_H, TFT_GREEN); + tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, TFT_DARKGREY); + drawFrame(); + tft.setTextColor(TFT_WHITE); + tft.setTextSize(2); + tft.setTextDatum(MC_DATUM); + tft.drawString("OFF", REDBUTTON_X + (REDBUTTON_W / 2) + 1, REDBUTTON_Y + (REDBUTTON_H / 2)); + SwitchOn = true; +} + diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Alert.h b/examples/Generic/TFT_Flash_Bitmap/Alert.h similarity index 99% rename from examples/320 x 240/TFT_Flash_Bitmap/Alert.h rename to examples/Generic/TFT_Flash_Bitmap/Alert.h index 44196a9..0e5a895 100644 --- a/examples/320 x 240/TFT_Flash_Bitmap/Alert.h +++ b/examples/Generic/TFT_Flash_Bitmap/Alert.h @@ -38,4 +38,3 @@ const unsigned short alert[1024] PROGMEM={ 0xECA2,0xECA2,0xECC2,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4E1,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E2,0xF4E1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xF4C1,0xECC2,0xECC3,0xECA2, // row 29, 960 pixels 0x8AC1,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0xEC82,0x9B01, // row 30, 992 pixels 0x0000,0x1880,0x51A0,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x8AA1,0x61E0,0x28E0,0x0000}; // row 31, 1024 pixels - diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Close.h b/examples/Generic/TFT_Flash_Bitmap/Close.h similarity index 99% rename from examples/320 x 240/TFT_Flash_Bitmap/Close.h rename to examples/Generic/TFT_Flash_Bitmap/Close.h index b58ec12..dc2a4fd 100644 --- a/examples/320 x 240/TFT_Flash_Bitmap/Close.h +++ b/examples/Generic/TFT_Flash_Bitmap/Close.h @@ -5,7 +5,7 @@ const uint16_t closeWidth = 32; const uint16_t closeHeight = 32; -const unsigned short close[1024] PROGMEM={ +const unsigned short closeX[1024] PROGMEM={ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x58E3,0xC228,0xFC10,0xFD34,0xFE18,0xFE59,0xFE79,0xFE9A,0xFE9A,0xFE9A,0xFE9A,0xFE59,0xFD75,0xFC51,0xC28A,0x5904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 2, 96 pixels diff --git a/examples/320 x 240/TFT_Flash_Bitmap/Info.h b/examples/Generic/TFT_Flash_Bitmap/Info.h similarity index 100% rename from examples/320 x 240/TFT_Flash_Bitmap/Info.h rename to examples/Generic/TFT_Flash_Bitmap/Info.h diff --git a/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino b/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino new file mode 100644 index 0000000..54ac4e7 --- /dev/null +++ b/examples/Generic/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino @@ -0,0 +1,72 @@ +// Icon images are stored in tabs ^ e.g. Alert.h etc above this line +// more than one icon can be in a header file + +// Arrays containing FLASH images can be created with UTFT library tool: +// (libraries\UTFT\Tools\ImageConverter565.exe) +// Convert to .c format then copy into a new tab + +/* + This sketch demonstrates loading images from arrays stored in program (FLASH) memory. + + Works with TFT_eSPI library here: + https://github.com/Bodmer/TFT_eSPI + + This sketch does not use/need any fonts at all... + + Code derived from ILI9341_due library example + + Make sure all the display driver and pin comnenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +// Include the header files that contain the icons +#include "Alert.h" +#include "Close.h" +#include "Info.h" + +long count = 0; // Loop count + +void setup() +{ + Serial.begin(115200); + tft.begin(); + tft.setRotation(1); // landscape + + tft.fillScreen(TFT_BLACK); + + // Swap the colour byte order when rendering + tft.setSwapBytes(true); + + // Draw the icons + tft.pushImage(100, 100, infoWidth, infoHeight, info); + tft.pushImage(140, 100, alertWidth, alertHeight, alert); + tft.pushImage(180, 100, closeWidth, closeHeight, closeX); + + // Pause here to admire the icons! + delay(2000); + +} + +void loop() +{ + // Loop filling and clearing screen + tft.pushImage(random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight, info); + tft.pushImage(random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight, alert); + tft.pushImage(random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight, closeX); + + // Clear screen after 100 x 3 = 300 icons drawn + if (1000 == count++) { + count = 1; + tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony! + tft.fillScreen(TFT_BLACK); + tft.setRotation(1); + } +} diff --git a/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino b/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino new file mode 100644 index 0000000..515f13a --- /dev/null +++ b/examples/Generic/TFT_SPIFFS_BMP/BMP_functions.ino @@ -0,0 +1,88 @@ +// Bodmers BMP image rendering function + +void drawBmp(const char *filename, int16_t x, int16_t y) { + + if ((x >= tft.width()) || (y >= tft.height())) return; + + fs::File bmpFS; + + // Open requested file on SD card + bmpFS = SPIFFS.open(filename, "r"); + + if (!bmpFS) + { + Serial.print("File not found"); + return; + } + + uint32_t seekOffset; + uint16_t w, h, row, col; + uint8_t r, g, b; + + uint32_t startTime = millis(); + + if (read16(bmpFS) == 0x4D42) + { + read32(bmpFS); + read32(bmpFS); + seekOffset = read32(bmpFS); + read32(bmpFS); + w = read32(bmpFS); + h = read32(bmpFS); + + if ((read16(bmpFS) == 1) && (read16(bmpFS) == 24) && (read32(bmpFS) == 0)) + { + y += h - 1; + + tft.setSwapBytes(true); + bmpFS.seek(seekOffset); + + uint16_t padding = (4 - ((w * 3) & 3)) & 3; + uint8_t lineBuffer[w * 3 + padding]; + + for (row = 0; row < h; row++) { + + bmpFS.read(lineBuffer, sizeof(lineBuffer)); + uint8_t* bptr = lineBuffer; + uint16_t* tptr = (uint16_t*)lineBuffer; + // Convert 24 to 16 bit colours + for (uint16_t col = 0; col < w; col++) + { + b = *bptr++; + g = *bptr++; + r = *bptr++; + *tptr++ = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + } + + // Push the pixel row to screen, pushImage will crop the line if needed + // y is decremented as the BMP image is drawn bottom up + tft.pushImage(x, y--, w, 1, (uint16_t*)lineBuffer); + } + Serial.print("Loaded in "); Serial.print(millis() - startTime); + Serial.println(" ms"); + } + else Serial.println("BMP format not recognized."); + } + bmpFS.close(); +} + +// These read 16- and 32-bit types from the SD card file. +// BMP data is stored little-endian, Arduino is little-endian too. +// May need to reverse subscript order if porting elsewhere. + +uint16_t read16(fs::File &f) { + uint16_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); // MSB + return result; +} + +uint32_t read32(fs::File &f) { + uint32_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); + ((uint8_t *)&result)[2] = f.read(); + ((uint8_t *)&result)[3] = f.read(); // MSB + return result; +} + diff --git a/examples/Generic/TFT_SPIFFS_BMP/TFT_SPIFFS_BMP.ino b/examples/Generic/TFT_SPIFFS_BMP/TFT_SPIFFS_BMP.ino new file mode 100644 index 0000000..df43a4d --- /dev/null +++ b/examples/Generic/TFT_SPIFFS_BMP/TFT_SPIFFS_BMP.ino @@ -0,0 +1,64 @@ +// This sketch draws BMP images pulled from SPIFFS onto the TFT. It is an +// an example from this library: https://github.com/Bodmer/TFT_eSPI + +// Images in SPIFFS must be put in the root folder (top level) to be found +// Use the SPIFFS library example to verify SPIFFS works! + +// The example image used to test this sketch can be found in the sketch +// Data folder, press Ctrl+K to see this folder. Use the IDE "Tools" menu +// option to upload the sketches data folder to the SPIFFS + +// This sketch has been tested on the ESP32 and ESP8266 + +//---------------------------------------------------------------------------------------------------- + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the SPIFFS FLASH filing system this is part of the ESP Core +#define FS_NO_GLOBALS +#include + +#ifdef ESP32 + #include "SPIFFS.h" // For ESP32 only +#endif + +// Call up the TFT library +#include // Hardware-specific library for ESP8266 + +// Invoke TFT library +TFT_eSPI tft = TFT_eSPI(); + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(115200); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS initialised."); + + // Now initialise the TFT + tft.begin(); + tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape + tft.fillScreen(TFT_BLACK); +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + int x = random(tft.width() - 128); + int y = random(tft.height() - 160); + + drawBmp("/parrot.bmp", x, y); + + delay(1000); +} +//==================================================================================== + diff --git a/examples/Generic/TFT_SPIFFS_BMP/data/parrot.bmp b/examples/Generic/TFT_SPIFFS_BMP/data/parrot.bmp new file mode 100644 index 0000000..a98c4eb Binary files /dev/null and b/examples/Generic/TFT_SPIFFS_BMP/data/parrot.bmp differ diff --git a/examples/Generic/TFT_Screen_Capture/TFT_Screen_Capture.ino b/examples/Generic/TFT_Screen_Capture/TFT_Screen_Capture.ino new file mode 100644 index 0000000..50cfc16 --- /dev/null +++ b/examples/Generic/TFT_Screen_Capture/TFT_Screen_Capture.ino @@ -0,0 +1,207 @@ +/* + This sketch has been written to test the Processing screenshot client. + + It has been created to work with the TFT_eSPI library here: + https://github.com/Bodmer/TFT_eSPI + + It sends screenshots to a PC running a Processing client sketch. + + The Processing IDE that will run the client sketch can be downloaded + here: https://processing.org/ + + The Processing sketch needed is contained within a tab attached to this + Arduino sketch. Cut and paste that tab into the Processing IDE and run. + Read the Procesing sketch header for instructions. + + This sketch uses the GLCD, 2, 4, 6 fonts only. + + Make sure all the display driver and pin comnenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + Maximum recommended SPI clock rate is 27MHz when reading pixels, 40MHz + seems to be OK with ILI9341 displays but this is above the manufacturers + specifed maximum clock rate. + + In the setup file you can define different write and read SPI clock rates + + In the setup file you can define TFT_SDA_READ for a TFT with bi-directional + SDA pin (otherwise the normal MISO pin will be used to read from the TFT) + + >>>> NOTE: NOT ALL TFTs SUPPORT READING THE CGRAM (pixel) MEMORY <<<< + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Created by: Bodmer 5/3/17 +// Updated by: Bodmer 10/3/17 +// Updated by: Bodmer 23/11/18 to support SDA reads and the ESP32 +// Version: 0.07 + +// MIT licence applies, all text above must be included in derivative works + +#include // Hardware-specific library +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +unsigned long targetTime = 0; +byte red = 0x1F; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; // Colour order is RGB 5+6+5 bits each + +void setup(void) { + Serial.begin(921600); // Set to a high rate for fast image transfer to a PC + + tft.init(); + tft.setRotation(0); + tft.fillScreen(TFT_BLACK); + + randomSeed(analogRead(A0)); + + targetTime = millis() + 1000; +} + +#define RGB_TEST false // true produces a simple RGB color test screen + +void loop() { + + if (targetTime < millis()) { + if (!RGB_TEST) + { + targetTime = millis() + 1500; // Wait a minimum of 1.5s + + tft.setRotation(random(4)); + rainbow_fill(); // Fill the screen with rainbow colours + + tft.setTextColor(TFT_BLACK); // Text background is not defined so it is transparent + tft.setTextDatum(TC_DATUM); // Top Centre datum + int xpos = tft.width() / 2; // Centre of screen + + tft.setTextFont(0); // Select font 0 which is the Adafruit font + tft.drawString("Original Adafruit font!", xpos, 5); + + // The new larger fonts do not need to use the .setCursor call, coords are embedded + tft.setTextColor(TFT_BLACK); // Do not plot the background colour + + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + tft.drawString("Font size 2", xpos, 14, 2); // Draw text centre at position xpos, 14 using font 2 + tft.drawString("Font size 4", xpos, 30, 4); // Draw text centre at position xpos, 30 using font 4 + tft.drawString("12.34", xpos, 54, 6); // Draw text centre at position xpos, 54 using font 6 + + tft.drawString("12.34 is in font size 6", xpos, 92, 2); // Draw text centre at position xpos, 92 using font 2 + // Note the x position is the top of the font! + + // draw a floating point number + float pi = 3.1415926; // Value to print + int precision = 3; // Number of digits after decimal point + + int ypos = 110; // y position + + tft.setTextDatum(TR_DATUM); // Top Right datum so text butts neatly to xpos (right justified) + + tft.drawFloat(pi, precision, xpos, ypos, 2); // Draw rounded number and return new xpos delta for next print position + + tft.setTextDatum(TL_DATUM); // Top Left datum so text butts neatly to xpos (left justified) + + tft.drawString(" is pi", xpos, ypos, 2); + + tft.setTextSize(1); // We are using a font size multiplier of 1 + tft.setTextDatum(TC_DATUM); // Top Centre datum + tft.setTextColor(TFT_BLACK); // Set text colour to black, no background (so transparent) + + tft.drawString("Transparent...", xpos, 125, 4); // Font 4 + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set text colour to white and background to black + tft.drawString("White on black", xpos, 150, 4); // Font 4 + + tft.setTextColor(TFT_GREEN, TFT_BLACK); // This time we will use green text on a black background + + tft.setTextFont(2); // Select font 2, now we do not need to specify the font in drawString() + + // An easier way to position text and blank old text is to set the datum and use width padding + tft.setTextDatum(BC_DATUM); // Bottom centre for text datum + tft.setTextPadding(tft.width() + 1); // Pad text to full screen width + 1 spare for +/-1 position rounding + + tft.drawString("Ode to a Small Lump of Green Putty", xpos, 230 - 32); + tft.drawString("I Found in My Armpit One Midsummer", xpos, 230 - 16); + tft.drawString("Morning", xpos, 230); + + tft.setTextDatum(TL_DATUM); // Reset to top left for text datum + tft.setTextPadding(0); // Reset text padding to 0 pixels + + // Now call the screen server to send a copy of the TFT screen to the PC running the Processing client sketch + screenServer(); + } + else + { + tft.fillScreen(TFT_BLACK); + tft.fillRect( 0, 0, 16, 16, TFT_RED); + tft.fillRect(16, 0, 16, 16, TFT_GREEN); + tft.fillRect(32, 0, 16, 16, TFT_BLUE); + screenServer(); + } + } +} + +// Fill screen with a rainbow pattern +void rainbow_fill() +{ + // The colours and state are not initialised so the start colour changes each time the funtion is called + int rotation = tft.getRotation(); + tft.setRotation(random(4)); + for (int i = tft.height() - 1; i >= 0; i--) { + // This is a "state machine" that ramps up/down the colour brightnesses in sequence + switch (state) { + case 0: + green ++; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green --; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + // Draw a line 1 pixel wide in the selected colour + tft.drawFastHLine(0, i, tft.width(), colour); // tft.width() returns the pixel width of the display + } + tft.setRotation(rotation); +} diff --git a/examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino b/examples/Generic/TFT_Screen_Capture/processing_sketch.ino similarity index 100% rename from examples/320 x 240/TFT_Screen_Capture/processing_sketch.ino rename to examples/Generic/TFT_Screen_Capture/processing_sketch.ino diff --git a/examples/320 x 240/TFT_Screen_Capture/screenServer.ino b/examples/Generic/TFT_Screen_Capture/screenServer.ino similarity index 89% rename from examples/320 x 240/TFT_Screen_Capture/screenServer.ino rename to examples/Generic/TFT_Screen_Capture/screenServer.ino index 962d561..2924947 100644 --- a/examples/320 x 240/TFT_Screen_Capture/screenServer.ino +++ b/examples/Generic/TFT_Screen_Capture/screenServer.ino @@ -11,16 +11,14 @@ // Created by: Bodmer 27/1/17 // Updated by: Bodmer 10/3/17 -// Version: 0.07 +// Updated by: Bodmer 23/11/18 to support SDA reads and the ESP32 +// Version: 0.08 // MIT licence applies, all text above must be included in derivative works //==================================================================================== // Definitions //==================================================================================== -#define BAUD_RATE 250000 // Maximum Serial Monitor rate for other messages -#define DUMP_BAUD_RATE 921600 // Rate used for screen dumps - #define PIXEL_TIMEOUT 100 // 100ms Time-out between pixel requests #define START_TIMEOUT 10000 // 10s Maximum time to wait at start transfer @@ -33,14 +31,17 @@ #define FILE_TYPE "png" // jpg, bmp, png, tif are valid // Filename extension -// '#' = add 0-9, '@' = add timestamp, '%' add millis() timestamp, '*' = add nothing +// '#' = add incrementing number, '@' = add timestamp, '%' add millis() timestamp, +// '*' = add nothing // '@' and '%' will generate new unique filenames, so beware of cluttering up your // hard drive with lots of images! The PC client sketch is set to limit the number of // saved images to 1000 and will then prompt for a restart. -#define FILE_EXT '%' +#define FILE_EXT '@' // Number of pixels to send in a burst (minimum of 1), no benefit above 8 -// NPIXELS values and render times: 1 = 5.0s, 2 = 1.75s, 4 = 1.68s, 8 = 1.67s +// NPIXELS values and render times: +// NPIXELS 1 = use readPixel() = >5s and 16 bit pixels only +// NPIXELS >1 using rectRead() 2 = 1.75s, 4 = 1.68s, 8 = 1.67s #define NPIXELS 8 // Must be integer division of both TFT width and TFT height //==================================================================================== @@ -60,16 +61,12 @@ boolean screenServer(void) // Start a screen dump server (serial or network) - filename specified boolean screenServer(String filename) { - Serial.end(); // Stop the serial port (clears buffers too) - Serial.begin(DUMP_BAUD_RATE); // Force baud rate to be high delay(0); // Equivalent to yield() for ESP8266; boolean result = serialScreenServer(filename); // Screenshot serial port server //boolean result = wifiScreenServer(filename); // Screenshot WiFi UDP port server (WIP) - Serial.end(); // Stop the serial port (clears buffers too) - Serial.begin(BAUD_RATE); // Return baud rate to normal - delay(0); // Equivalent to yield() for ESP8266; + delay(0); // Equivalent to yield() //Serial.println(); //if (result) Serial.println(F("Screen dump passed :-)")); @@ -146,14 +143,20 @@ boolean serialScreenServer(String filename) // Save arrival time of the read command (for later time-out check) lastCmdTime = millis(); -#if defined BITS_PER_PIXEL && BITS_PER_PIXEL >= 24 +#if defined BITS_PER_PIXEL && BITS_PER_PIXEL >= 24 && NPIXELS > 1 // Fetch N RGB pixels from x,y and put in buffer tft.readRectRGB(x, y, NPIXELS, 1, color); // Send buffer to client Serial.write(color, 3 * NPIXELS); // Write all pixels in the buffer #else // Fetch N 565 format pixels from x,y and put in buffer - tft.readRect(x, y, NPIXELS, 1, (uint16_t *)color); + if (NPIXELS > 1) tft.readRect(x, y, NPIXELS, 1, (uint16_t *)color); + else + { + uint16_t c = tft.readPixel(x, y); + color[0] = c>>8; + color[1] = c & 0xFF; // Swap bytes + } // Send buffer to client Serial.write(color, 2 * NPIXELS); // Write all pixels in the buffer #endif @@ -179,7 +182,8 @@ void sendParameters(String filename) Serial.write(tft.height() & 0xFF); Serial.write('Y'); // Bits per pixel (16 or 24) - Serial.write(BITS_PER_PIXEL); + if (NPIXELS > 1) Serial.write(BITS_PER_PIXEL); + else Serial.write(16); // readPixel() only provides 16 bit values Serial.write('?'); // Filename next Serial.print(filename); @@ -190,5 +194,3 @@ void sendParameters(String filename) Serial.write(*FILE_TYPE); // First character defines file type j,b,p,t } - - diff --git a/examples/Generic/Touch_calibrate/Touch_calibrate.ino b/examples/Generic/Touch_calibrate/Touch_calibrate.ino new file mode 100644 index 0000000..4f10110 --- /dev/null +++ b/examples/Generic/Touch_calibrate/Touch_calibrate.ino @@ -0,0 +1,103 @@ +/* + Sketch to generate the setup() calibration values, these are reported + to the Serial Monitor. + + The sketch has been tested on the ESP8266 and screen with XPT2046 driver. +*/ + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +//------------------------------------------------------------------------------------------ + +void setup() { + // Use serial port + Serial.begin(115200); + + // Initialise the TFT screen + tft.init(); + + // Set the rotation before we calibrate + tft.setRotation(1); + + // Calibrate the touch screen and retrieve the scaling factors + touch_calibrate(); + +/* + // Replace above line with the code sent to Serial Monitor + // once calibration is complete, e.g.: + uint16_t calData[5] = { 286, 3534, 283, 3600, 6 }; + tft.setTouch(calData); +*/ + + // Clear the screen + tft.fillScreen(TFT_BLACK); + tft.drawCentreString("Touch screen to test!",tft.width()/2, tft.height()/2, 2); +} + +//------------------------------------------------------------------------------------------ + +void loop(void) { + uint16_t x = 0, y = 0; // To store the touch coordinates + + // Pressed will be set true is there is a valid touch on the screen + boolean pressed = tft.getTouch(&x, &y); + + // Draw a white spot at the detected coordinates + if (pressed) { + tft.fillCircle(x, y, 2, TFT_WHITE); + //Serial.print("x,y = "); + //Serial.print(x); + //Serial.print(","); + //Serial.println(y); + } +} + +//------------------------------------------------------------------------------------------ + +// Code to run a screen calibration, not needed when calibration values set in setup() +void touch_calibrate() +{ + uint16_t calData[5]; + uint8_t calDataOK = 0; + + // Calibrate + tft.fillScreen(TFT_BLACK); + tft.setCursor(20, 0); + tft.setTextFont(2); + tft.setTextSize(1); + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + tft.println("Touch corners as indicated"); + + tft.setTextFont(1); + tft.println(); + + tft.calibrateTouch(calData, TFT_MAGENTA, TFT_BLACK, 15); + + Serial.println(); Serial.println(); + Serial.println("// Use this calibration code in setup():"); + Serial.print(" uint16_t calData[5] = "); + Serial.print("{ "); + + for (uint8_t i = 0; i < 5; i++) + { + Serial.print(calData[i]); + if (i < 4) Serial.print(", "); + } + + Serial.println(" };"); + Serial.print(" tft.setTouch(calData);"); + Serial.println(); Serial.println(); + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Calibration complete!"); + tft.println("Calibration code sent to Serial port."); + + delay(4000); +} + diff --git a/examples/Generic/drawXBitmap/drawXBitmap.ino b/examples/Generic/drawXBitmap/drawXBitmap.ino new file mode 100644 index 0000000..d43138e --- /dev/null +++ b/examples/Generic/drawXBitmap/drawXBitmap.ino @@ -0,0 +1,61 @@ +// Example sketch to demonstrate the drawing of X BitMap (XBM) +// format image onto the display. + +// Information on the X BitMap (XBM) format can be found here: +// https://en.wikipedia.org/wiki/X_BitMap + +// This example is part of the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +// Created by Bodmer 23/04/18 + +#include "xbm.h" // Sketch tab header for xbm images + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + + +void setup() +{ + tft.begin(); // Initialise the display + tft.fillScreen(TFT_BLACK); // Black screen fill +} + +void loop() +{ + + // Example 1 + // ========= + // Random x and y coordinates + int x = random(tft.width() - logoWidth); + int y = random(tft.height() - logoHeight); + + // Draw bitmap with top left corner at x,y with foreground only color + // Bits set to 1 plot as the defined color, bits set to 0 are not plotted + // x y xbm xbm width xbm height color + tft.drawXBitmap(x, y, logo, logoWidth, logoHeight, TFT_WHITE); + + delay(500); + + // Erase old one by drawing over with background colour + tft.drawXBitmap(x, y, logo, logoWidth, logoHeight, TFT_BLACK); + + + // Example 2 + // ========= + // New random x and y coordinates + x = random(tft.width() - logoWidth); + y = random(tft.height() - logoHeight); + + // Draw bitmap with top left corner at x,y with foreground and background colors + // Bits set to 1 plot as the defined fg color, bits set to 0 are plotted as bg color + // x y xbm xbm width xbm height fg color bg color + tft.drawXBitmap(x, y, logo, logoWidth, logoHeight, TFT_WHITE, TFT_RED); + + delay(500); + + // Erase old one by drawing over with background colour + tft.drawXBitmap(x, y, logo, logoWidth, logoHeight, TFT_BLACK, TFT_BLACK); + +} diff --git a/examples/Generic/drawXBitmap/xbm.h b/examples/Generic/drawXBitmap/xbm.h new file mode 100644 index 0000000..675dc1f --- /dev/null +++ b/examples/Generic/drawXBitmap/xbm.h @@ -0,0 +1,52 @@ +// Images can be converted to XBM format by using the online converter here: +// https://www.online-utility.org/image/convert/to/XBM + +// The output must be pasted in a header file, renamed and adjusted to appear +// as as a const unsigned char array in PROGMEM (FLASH program memory). + +// The xbm format adds padding to pixel rows so they are a whole number of bytes +// In this example 50 pixel width means 56 bits = 7 bytes +// the 50 height then means array uses 50 x 7 = 350 bytes of FLASH +// The library ignores the padding bits when drawing the image on the display. + +// Example of the correct format is shown below + +#include // PROGMEM support header + +// Espressif logo 50 x 50 pixel array in XBM format +#define logoWidth 50 // logo width +#define logoHeight 50 // logo height + +// Image is stored in this array +PROGMEM const unsigned char logo[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xFC, 0x07, 0x00, 0x00, 0x00, 0x82, 0x7F, 0xF0, + 0x1F, 0x00, 0x00, 0x00, 0xC6, 0xFF, 0xC3, 0x3F, 0x00, 0x00, 0x00, 0xE7, + 0xFF, 0x8F, 0x7F, 0x00, 0x00, 0x80, 0xE3, 0xFF, 0x1F, 0xFE, 0x00, 0x00, + 0x80, 0xE1, 0xFF, 0x7F, 0xFC, 0x01, 0x00, 0xC0, 0x00, 0xFF, 0xFF, 0xF8, + 0x03, 0x00, 0xE0, 0x00, 0xE0, 0xFF, 0xF1, 0x03, 0x00, 0x60, 0xF0, 0x81, + 0xFF, 0xE3, 0x07, 0x00, 0x60, 0xFC, 0x1F, 0xFE, 0xC7, 0x07, 0x00, 0x30, + 0xFE, 0x7F, 0xF8, 0x8F, 0x0F, 0x00, 0x30, 0xFF, 0xFF, 0xF1, 0x9F, 0x0F, + 0x00, 0xB0, 0xFF, 0xFF, 0xE3, 0x3F, 0x0F, 0x00, 0xB0, 0xFF, 0xFF, 0xC7, + 0x3F, 0x1E, 0x00, 0xB8, 0xFF, 0xFF, 0x8F, 0x7F, 0x1E, 0x00, 0x98, 0x1F, + 0xFC, 0x3F, 0xFF, 0x1C, 0x00, 0xB8, 0x3F, 0xE0, 0x3F, 0xFE, 0x1C, 0x00, + 0x98, 0xFF, 0xC3, 0x7F, 0xFE, 0x19, 0x00, 0x98, 0xFF, 0x0F, 0xFF, 0xFC, + 0x19, 0x00, 0x38, 0xFF, 0x3F, 0xFF, 0xFC, 0x01, 0x00, 0x30, 0xFE, 0x7F, + 0xFE, 0xF9, 0x03, 0x00, 0x30, 0xFC, 0xFF, 0xFC, 0xF9, 0x03, 0x00, 0x30, + 0xF8, 0xFF, 0xF8, 0xF3, 0x03, 0x00, 0x30, 0x00, 0xFF, 0xF9, 0xF3, 0x03, + 0x00, 0x70, 0x00, 0xFC, 0xF9, 0xF3, 0x07, 0x00, 0x60, 0x00, 0xF8, 0xF3, + 0xF3, 0x07, 0x00, 0xE0, 0xF8, 0xF8, 0xF3, 0xF7, 0x03, 0x00, 0xC0, 0xF8, + 0xF1, 0xF3, 0xE3, 0x03, 0x00, 0xC0, 0xFD, 0xF1, 0xF3, 0xF7, 0x01, 0x00, + 0x80, 0xFD, 0xF1, 0xF3, 0xE7, 0x00, 0x00, 0x00, 0xFF, 0xF1, 0xF3, 0x07, + 0x00, 0x00, 0x00, 0xFF, 0xF8, 0xF3, 0x07, 0x00, 0x00, 0x00, 0x7E, 0xF8, + 0xF3, 0x83, 0x03, 0x00, 0x00, 0x3C, 0xF8, 0xF3, 0xC3, 0x01, 0x00, 0x00, + 0x70, 0xF8, 0xF9, 0xE3, 0x00, 0x00, 0x00, 0xE0, 0xE1, 0x41, 0x78, 0x00, + 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFD, + 0x07, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, }; + diff --git a/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino new file mode 100644 index 0000000..c6dbb19 --- /dev/null +++ b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/ESP32_Smooth_Font_SD.ino @@ -0,0 +1,174 @@ +/* + Sketch to demonstrate using the print class with smooth fonts + that are saved onto an SD Card accessed by the SD library. + + For ESP32 only, GPIO 5 must be used for SD chip select. + This method of storing the fonts is NOT compatible with the ESP8266. + + Sketch is written for a 240 x 320 display + + Load the font file onto the root directory of the SD Card. The font files + used by this sketch can be found in the Data folder, press Ctrl+K to see it. + + The library supports 16 bit unicode characters: + https://en.wikipedia.org/wiki/Unicode_font + + The characters supported are in the in the Basic Multilingal Plane: + https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + + Make sure all the display driver and pin connenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Font file is stored on SD card +#include + +// Graphics and font library +#include +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + Serial.begin(115200); // Used for messages + + // Initialise the SD library before the TFT so the chip select is defined + if (!SD.begin()) { + Serial.println("Card Mount Failed"); + return; + } + uint8_t cardType = SD.cardType(); + + if (cardType == CARD_NONE) { + Serial.println("No SD card attached"); + return; + } + + Serial.print("SD Card Type: "); + if (cardType == CARD_MMC) { + Serial.println("MMC"); + } else if (cardType == CARD_SD) { + Serial.println("SDSC"); + } else if (cardType == CARD_SDHC) { + Serial.println("SDHC"); + } else { + Serial.println("UNKNOWN"); + } + + uint64_t cardSize = SD.cardSize() / (1024 * 1024); + Serial.printf("SD Card Size: %lluMB\n", cardSize); + + // Initialise the TFT after the SD card! + tft.init(); + tft.setRotation(1); + tft.fillScreen(TFT_BLACK); + + listDir(SD, "/", 0); + + Serial.println("SD and TFT initialisation done."); +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + // Wrap test at right and bottom of screen + tft.setTextWrap(true, true); + + // Name of font file (library adds leading / and .vlw) + String fileName = "Final-Frontier-28"; + + // Font and background colour, background colour is used for anti-alias blending + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // Load the font + tft.loadFont(fileName, SD); // Use font stored on SD + + // Display all characters of the font + tft.showFont(2000); + + uint32_t dt = millis(); + + int count = 100; + + while (count--) + { + // Set "cursor" at top left corner of display (0,0) + // (cursor will move to next line automatically during printing with 'tft.println' + // or stay on the line is there is room for the text with tft.print) + tft.setCursor(0, 0); + + // Set the font colour to be white with a black background, set text size multiplier to 1 + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Hello World!"); + + // Set the font colour to be yellow + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.println(1234.56); + + // Set the font colour to be red + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println((uint32_t)3735928559, HEX); // Should print DEADBEEF + + // Set the font colour to be green with black background + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Anti-aliased font!"); + tft.println(""); + + // Test some print formatting functions + float fnumber = 123.45; + + // Set the font colour to be blue + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.print("Float = "); tft.println(fnumber); // Print floating point number + tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary + tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal + } + + Serial.println(millis()-dt); + + // Unload the font to recover used RAM + tft.unloadFont(); + + delay(10000); +} + +void listDir(fs::FS &fs, const char * dirname, uint8_t levels){ + Serial.printf("Listing directory: %s\n", dirname); + + File root = fs.open(dirname); + if(!root){ + Serial.println("Failed to open directory"); + return; + } + if(!root.isDirectory()){ + Serial.println("Not a directory"); + return; + } + + File file = root.openNextFile(); + while(file){ + if(file.isDirectory()){ + Serial.print(" DIR : "); + Serial.println(file.name()); + if(levels){ + listDir(fs, file.name(), levels -1); + } + } else { + Serial.print(" FILE: "); + Serial.print(file.name()); + Serial.print(" SIZE: "); + Serial.println(file.size()); + } + file = root.openNextFile(); + } +} diff --git a/examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw new file mode 100644 index 0000000..2872fd5 Binary files /dev/null and b/examples/Smooth Fonts/ESP32_Smooth_Font_SD/data/Final-Frontier-28.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino new file mode 100644 index 0000000..e38a5ee --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Font_Demo_1.ino @@ -0,0 +1,182 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 1, using tft.print() and tft.println() calls. + + In some cases the sketch shows what can go wrong too, so read the comments! + + The font is rendered WITHOUT a background, but a background colour needs to be + set so the anti-aliasing of the character is performed correctly. This is because + characters are drawn one by one. + + This method is good for static text that does not change often because changing + values may flicker. The text appears at the tft cursor coordinates. + + It is also possible to "print" text directly into a created sprite, for example using + spr.println("Hello"); and then push the sprite to the screen. That method is not + demonstrated in this sketch. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(0); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); +} + + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour AND the background colour + // so the anti-aliasing works + + tft.setCursor(0, 0); // Set cursor at top left of screen + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL); // Must load the font first + + tft.println("Small 15pt font"); // println moves cursor down for a new line + + tft.println(); // New line + + tft.print("ABC"); // print leaves cursor at end of line + + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("1234"); // Added to line after ABC + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + // print stream formatting can be used,see: + // https://www.arduino.cc/en/Serial/Print + int ivalue = 1234; + tft.println(ivalue); // print as an ASCII-encoded decimal + tft.println(ivalue, DEC); // print as an ASCII-encoded decimal + tft.println(ivalue, HEX); // print as an ASCII-encoded hexadecimal + tft.println(ivalue, OCT); // print as an ASCII-encoded octal + tft.println(ivalue, BIN); // print as an ASCII-encoded binary + + tft.println(); // New line + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + float fvalue = 1.23456; + tft.println(fvalue, 0); // no decimal places + tft.println(fvalue, 1); // 1 decimal place + tft.println(fvalue, 2); // 2 decimal places + tft.println(fvalue, 5); // 5 decimal places + + delay(5000); + + // Get ready for the next demo while we have this font loaded + tft.fillScreen(TFT_BLACK); + tft.setCursor(0, 0); // Set cursor at top left of screen + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Wrong and right ways to"); + tft.println("print changing values..."); + + tft.unloadFont(); // Remove the font to recover memory used + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE); // Load another different font + + //tft.fillScreen(TFT_BLACK); + + // Draw changing numbers - does not work unless a filled rectangle is drawn over the old text + for (int i = 0; i <= 20; i++) + { + tft.setCursor(50, 50); + tft.print(" "); // Overprinting old number with spaces DOES NOT WORK! + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 50); + tft.print(i / 10.0, 1); + + tft.fillRect (50, 90, 60, 40, TFT_BLACK); // Overprint with a filled rectangle + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.setCursor(50, 90); + tft.print(i / 10.0, 1); + + delay (200); + } + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font text wrapping + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_YELLOW, TFT_BLACK); // Change the font colour and the background colour + + tft.setCursor(0, 0); // Set cursor at top left of screen + + tft.println("Large font!"); + + tft.setTextWrap(true); // Wrap on width + tft.setTextColor(TFT_CYAN, TFT_BLACK); + tft.println("Long lines wrap to the next line"); + + tft.setTextWrap(false, false); // Wrap on width and height switched off + tft.setTextColor(TFT_MAGENTA, TFT_BLACK); + tft.println("Unless text wrap is switched off"); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/Font_Demo_1/Notes.ino b/examples/Smooth Fonts/Font_Demo_1/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_1/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw new file mode 100644 index 0000000..803a1bd Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold15.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw new file mode 100644 index 0000000..66003f6 Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_1/data/NotoSansBold36.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino new file mode 100644 index 0000000..6dbf769 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Font_Demo_2.ino @@ -0,0 +1,231 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 2, using graphics calls plotting direct to the TFT: + tft.drawString(string, x, y); + tft.drawNumber(integer, x, y); + tft.drawFloat(float, dp, x, y); // dp = number of decimal places + + setTextDatum() and setTextPadding() functions work with those draw functions. + + This method is good for static text that does not change often because changing + values may flicker. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 10; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_SMALL); // Must load the font first + + tft.drawString("Small 15pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + + // If the string does not fit the screen width, then the next character will wrap to a new line + tft.drawString("Ode To A Small Lump Of Green Putty I Found In My Armpit One Midsummer Morning", xpos, ypos); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Background colour does not match the screen background! + tft.drawString("Anti-aliasing causes odd looking shadow effects if the text and screen background colours are not the same!", xpos, ypos + 60); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.loadFont(AA_FONT_LARGE); // Load another different font + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_GREEN, TFT_BLUE); // Change the font colour and the background colour + + tft.drawString("36pt font", xpos, ypos); + + ypos += tft.fontHeight(); // Get the font height and move ypos down + + // Set text padding to 100 pixels wide area to over-write old values on screen + tft.setTextPadding(100); + + // Draw changing numbers - likely to flicker using this plot method! + for (int i = 0; i <= 20; i++) { + tft.drawFloat(i / 10.0, 1, xpos, ypos); + delay (200); + } + + tft.unloadFont(); // Remove the font to recover memory used + + delay(5000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Setting the 12 datum positions works with free fonts + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + // Integer numbers, floats and strings can be drawn relative to a x,y datum, e.g.: + // tft.drawNumber( 123, x, y); + // tft.drawFloat( 1.23, dp, x, y); // Where dp is number of decimal places to show + // tft.drawString( "Abc", x, y); + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_DARKGREY, TFT_BLACK); + + // Use middle of screen as datum + xpos = tft.width() /2; + ypos = tft.height()/2; + + tft.loadFont(AA_FONT_SMALL); + tft.setTextDatum(TL_DATUM); + tft.drawString("[Top left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TC_DATUM); + tft.drawString("[Top centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(TR_DATUM); + tft.drawString("[Top right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(ML_DATUM); + tft.drawString("[Middle left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MC_DATUM); + tft.drawString("[Middle centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(MR_DATUM); + tft.drawString("[Middle right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BL_DATUM); + tft.drawString("[Bottom left]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BC_DATUM); + tft.drawString("[Bottom centre]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(BR_DATUM); + tft.drawString("[Bottom right]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(L_BASELINE); + tft.drawString("[Left baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(C_BASELINE); + tft.drawString("[Centre baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.fillScreen(TFT_BLACK); + tft.setTextDatum(R_BASELINE); + tft.drawString("[Right baseline]", xpos, ypos); + drawDatumMarker(xpos, ypos); + delay(1000); + + tft.unloadFont(); // Remove the font to recover memory used + + delay(4000); + +} + +// Draw a + mark centred on x,y +void drawDatumMarker(int x, int y) +{ + tft.drawLine(x - 5, y, x + 5, y, TFT_GREEN); + tft.drawLine(x, y - 5, x, y + 5, TFT_GREEN); +} diff --git a/examples/Smooth Fonts/Font_Demo_2/Notes.ino b/examples/Smooth Fonts/Font_Demo_2/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_2/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw new file mode 100644 index 0000000..803a1bd Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold15.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw new file mode 100644 index 0000000..66003f6 Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_2/data/NotoSansBold36.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino new file mode 100644 index 0000000..ebc2055 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Font_Demo_3.ino @@ -0,0 +1,231 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 3, the font characters are first plotted in a Sprite, then the + Sprite is pushed to the screen. This method is very flexible and the Sprite can be + created, deleted, resized as needed. To render anit-aliased fonts well the Sprite + needs to be 16 bit. The fonts will render in 1 bit per pixel sprites but there + will then be no anti-aliasing. Using 1 bit per pixel Sprites is however useful + to use the extended Unicode range in fonts on mono displays like ePaper. + + A single Sprite can be re-used for plotting different values and graphics to + different positions on the screen. This makes this method a very powerful display tool, + for example round buttons can be created, making use of transparent colour plotting. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" +#define AA_FONT_MONO "NotoSansMonoSCB20" // NotoSansMono-SemiCondensedBold 20pt +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansMonoSCB20.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_DARKGREY); + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class + + spr.createSprite(100, 50); // Create a sprite 100 pixels wide and 50 high + + spr.fillSprite(TFT_BLUE); + + spr.drawRect(0, 0, 100, 50, TFT_WHITE); // Draw sprite border outline (so we see extent) + + spr.setTextColor(TFT_YELLOW, TFT_DARKGREY); // Set the sprite font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("15pt font", 50, 25 ); // Coords of middle of 100 x 50 Sprite + + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.pushSprite(10, 70, TFT_BLUE); // Push to TFT screen, TFT_BLUE is transparent + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + // Beware: Sprites are a differerent "class" to TFT, so different fonts can be loaded + // in the tft and sprite instances, so load the font in the class instance you use! + // In this example this means the spr. instance. + + spr.loadFont(AA_FONT_LARGE); // Load another different font into the sprite instance + + // 100 x 50 sprite was created above and still exists... + + spr.fillSprite(TFT_GREEN); + + spr.setTextColor(TFT_BLACK, TFT_GREEN); // Set the font colour and the background colour + + spr.setTextDatum(MC_DATUM); // Middle Centre datum + + spr.drawString("Fits", 50, 25); // Make sure text fits in the Sprite! + spr.pushSprite(10, 10); // Push to TFT screen coord 10, 10 + + spr.fillSprite(TFT_RED); + spr.setTextColor(TFT_WHITE, TFT_RED); // Set the font colour and the background colour + + spr.drawString("Too big", 50, 25); // Text is too big to all fit in the Sprite! + spr.pushSprite(10, 70); // Push to TFT screen coord 10, 70 + + // Draw changing numbers - no flicker using this plot method! + + // >>>> Note: it is best to use drawNumber() and drawFloat() for numeric values <<<< + // >>>> this reduces digit position movement when the value changes <<<< + // >>>> drawNumber() and drawFloat() functions behave like drawString() and are <<<< + // >>>> supported by setTextDatum() and setTextPadding() <<<< + + spr.setTextDatum(TC_DATUM); // Top Centre datum + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + for (int i = 0; i <= 200; i++) { + spr.fillSprite(TFT_BLUE); + spr.drawFloat(i / 100.0, 2, 50, 10); // draw with 2 decimal places at 50,10 in sprite + spr.pushSprite(10, 130); // Push to TFT screen coord 10, 130 + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + spr.deleteSprite(); // Recover memory + + delay(1000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Mono spaced font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_MONO); // Mono spaced fonts have fixed intercharacter gaps to + // aid formatting + int bnum = 1; + + // Example of drawing buttons + for (int j = 0; j < 4; j++) + { + for (int k = 0; k < 4; k++) + { + int x = 120 + k * 45; + int y = 40 + j * 30; + button(x, y, bnum++); + } + } + + for (int i = 0; i < 100; i++) + { + button(120, 160, i); + delay(50); + } + + spr.unloadFont(); + + delay(8000); +} + +// ######################################################################### +// Draw a number in a rounded rectangle with some transparent pixels +// Load the font before calling +// ######################################################################### +void button(int x, int y, int num ) +{ + + // Size of sprite + #define IWIDTH 40 + #define IHEIGHT 25 + + // Create a 16 bit sprite 40 pixels wide, 25 high (2000 bytes of RAM needed) + spr.setColorDepth(16); + spr.createSprite(IWIDTH, IHEIGHT); + + // Fill it with black (this will be the transparent colour this time) + spr.fillSprite(TFT_BLACK); + + // Draw a background for the numbers + spr.fillRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_RED); + spr.drawRoundRect( 0, 0, IWIDTH, IHEIGHT, 8, TFT_WHITE); + + // Set the font parameters + + // Set text coordinate datum to middle centre + spr.setTextDatum(MC_DATUM); + + // Set the font colour and the background colour + spr.setTextColor(TFT_WHITE, TFT_RED); + + // Draw the number + spr.drawNumber(num, IWIDTH/2, 1 + IHEIGHT/2); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // All black pixels will not be drawn hence will show as "transparent" + spr.pushSprite(x, y, TFT_BLACK); + + // Delete sprite to free up the RAM + spr.deleteSprite(); +} diff --git a/examples/Smooth Fonts/Font_Demo_3/Notes.ino b/examples/Smooth Fonts/Font_Demo_3/Notes.ino new file mode 100644 index 0000000..bdab3d0 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_3/Notes.ino @@ -0,0 +1,61 @@ +/* + +Information notes only: +====================== + +Note: it is best to use drawNumber() and drawFloat() for numeric values + this reduces digit position movement when the value changes + drawNumber() and drawFloat() functions behave like drawString() and are + supported by setTextDatum() and setTextPadding() + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw new file mode 100644 index 0000000..803a1bd Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold15.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw new file mode 100644 index 0000000..66003f6 Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansBold36.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw new file mode 100644 index 0000000..4045c62 Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_3/data/NotoSansMonoSCB20.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino new file mode 100644 index 0000000..edad83c --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_4/Font_Demo_4.ino @@ -0,0 +1,140 @@ +/* + There are four different methods of plotting anti-aliased fonts to the screen. + + This sketch uses method 4, printing "String" or character array types only to screen, + via a Sprite. The Sprite must NOT have been created already. The printToSprite() + function automatically creates a sprite of a minimal size to contain the String, + then plots to screen at the "tft" cursor position. Printing via a sprite draws the + text faster on the screen. This method minimises flicker but uses RAM for the Sprite, + the Sprite is automatically deleted after plotting to the TFT. + + Number and float types must be converted to strings to use printToSprite() e.g.: + spr.printToSprite( (String) number ); + spr.printToSprite( (String) (number * 55 / 1.23) ); // Put calculations within brackets + + The key advantage of this method is that you do not need to calculate the size of sprite + needed to contain the text, the library does that for you. The library also fills the + the sprite with text background colour for you. + + printToSprite() has a second purpose, if the sprite has been created already the String + will be printed into the Sprite at the "sprite" cursor position, which is + different to the "tft" cursor position. In this case the Sprite is not deleted and + you must use pushSprite() to plot on the screen. This method is not used in this sketch. + because in general it is better to use drawString() in an already created sprite. + printToSprite() will NOT move the tft cursor. + +*/ +// The fonts used are in the sketch data folder, press Ctrl+K to view. + +// Upload the fonts and icons to SPIFFS (must set at least 1M for SPIFFS) using the +// "Tools" "ESP8266 (or ESP32) Sketch Data Upload" menu option in the IDE. +// To add this option follow instructions here for the ESP8266: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// or for the ESP32: +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// Close the IDE and open again to see the new menu option. + +// A processing sketch to create new fonts can be found in the Tools folder of TFT_eSPI +// https://github.com/Bodmer/TFT_eSPI/tree/master/Tools/Create_Smooth_Font/Create_font + +// This sketch uses font files created from the Noto family of fonts: +// https://www.google.com/get/noto/ + +#define AA_FONT_SMALL "NotoSansBold15" +#define AA_FONT_LARGE "NotoSansBold36" + +// Font files are stored in SPIFFS, so load the linbrary +#include + +#include +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite class needs to be invoked + +void setup(void) { + + Serial.begin(250000); + + tft.begin(); + + tft.setRotation(1); + + spr.setColorDepth(16); // 16 bit colour needed to show antialiased fonts + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nSPIFFS available!"); + + // ESP32 will crash if any of the fonts are missing + bool font_missing = false; + if (SPIFFS.exists("/NotoSansBold15.vlw") == false) font_missing = true; + if (SPIFFS.exists("/NotoSansBold36.vlw") == false) font_missing = true; + + if (font_missing) + { + Serial.println("\r\nFont missing in SPIFFS, did you upload it?"); + while(1) yield(); + } + else Serial.println("\r\nFonts found OK."); +} + +void loop() { + + tft.fillScreen(TFT_BLACK); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); // Set the font colour and the background colour + + tft.setTextDatum(TC_DATUM); // Top Centre datum + + int xpos = tft.width() / 2; // Half the screen width + int ypos = 50; + + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Small font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + spr.loadFont(AA_FONT_SMALL); // Must load the font first into the sprite class + + spr.setTextColor(TFT_YELLOW, TFT_BLACK); // Set the sprite font colour and the background colour + + tft.setCursor(xpos - 50, ypos); // Set the tft cursor position, yes tft position! + spr.printToSprite("Small 15pt font"); // Prints to tft cursor position, tft cursor NOT moved + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + spr.unloadFont(); // Remove the font from sprite class to recover memory used + + delay(4000); + + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + // Large font + // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> + + tft.fillScreen(TFT_BLACK); + + spr.loadFont(AA_FONT_LARGE); // Load another different font + + spr.setTextColor(TFT_WHITE, TFT_BLUE); // Set the font colour and the background colour + + tft.setCursor(xpos - 90, ypos); // Set the tft cursor position + spr.printToSprite("36pt font"); // Text is rendered via a minimally sized sprite + + ypos += spr.fontHeight(); // Get the font height and move ypos down + + // Draw changing numbers - no flicker using this plot method! + for (int i = 0; i <= 200; i++) { + tft.setCursor(10, 10); + // Number is converted to String type by (String) (number) + spr.printToSprite(" " + (String) (i / 100.0) + " "); // Space padding helps over-write old numbers + delay (20); + } + + spr.unloadFont(); // Remove the font to recover memory used + + delay(8000); +} diff --git a/examples/Smooth Fonts/Font_Demo_4/Notes.ino b/examples/Smooth Fonts/Font_Demo_4/Notes.ino new file mode 100644 index 0000000..f04f2b7 --- /dev/null +++ b/examples/Smooth Fonts/Font_Demo_4/Notes.ino @@ -0,0 +1,56 @@ +/* + +Information notes only: +====================== + +//These are the text plotting alignment (reference datum point) + +TL_DATUM = Top left (default) +TC_DATUM = Top centre +TR_DATUM = Top right + +ML_DATUM = Middle left +MC_DATUM = Middle centre +MR_DATUM = Middle right + +BL_DATUM = Bottom left +BC_DATUM = Bottom centre +BR_DATUM = Bottom right + +L_BASELINE = Left character baseline (Line the 'A' character would sit on) +C_BASELINE = Centre character baseline +R_BASELINE = Right character baseline + +// Basic colours already defined: + +TFT_BLACK 0x0000 +TFT_NAVY 0x000F +TFT_DARKGREEN 0x03E0 +TFT_DARKCYAN 0x03EF +TFT_MAROON 0x7800 +TFT_PURPLE 0x780F +TFT_OLIVE 0x7BE0 +TFT_LIGHTGREY 0xC618 +TFT_DARKGREY 0x7BEF +TFT_BLUE 0x001F +TFT_GREEN 0x07E0 +TFT_CYAN 0x07FF +TFT_RED 0xF800 +TFT_MAGENTA 0xF81F +TFT_YELLOW 0xFFE0 +TFT_WHITE 0xFFFF +TFT_ORANGE 0xFDA0 +TFT_GREENYELLOW 0xB7E0 +TFT_PINK 0xFC9F + + + + + + + + + + + + */ diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw new file mode 100644 index 0000000..803a1bd Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold15.vlw differ diff --git a/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw new file mode 100644 index 0000000..66003f6 Binary files /dev/null and b/examples/Smooth Fonts/Font_Demo_4/data/NotoSansBold36.vlw differ diff --git a/examples/Smooth Fonts/Print_Smooth_Font/Print_Smooth_Font.ino b/examples/Smooth Fonts/Print_Smooth_Font/Print_Smooth_Font.ino new file mode 100644 index 0000000..10f9197 --- /dev/null +++ b/examples/Smooth Fonts/Print_Smooth_Font/Print_Smooth_Font.ino @@ -0,0 +1,195 @@ +/* + Sketch to demonstrate using the print class with smooth fonts + + Sketch is writtent for a 240 x 320 display + + Load the font file into SPIFFS first by using the Arduino IDE + Sketch Data Upload menu option. Font files must be stored in the + sketch data folder (Ctrl+k to view). + https://github.com/esp8266/arduino-esp8266fs-plugin + https://github.com/me-no-dev/arduino-esp32fs-plugin + + New font files in the .vlw format can be created using the Processing + sketch in the library Tools folder. The Processing sketch can convert + TrueType fonts in *.ttf or *.otf files. + + Note: SPIFFS does not accept an underscore _ in filenames! + + The library supports 16 bit unicode characters: + https://en.wikipedia.org/wiki/Unicode_font + + The characters supported are in the in the Basic Multilingal Plane: + https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_Multilingual_Plane + + Make sure all the display driver and pin connenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Font file is stored in SPIFFS +#define FS_NO_GLOBALS +#include + +// Graphics and font library +#include +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + Serial.begin(115200); // Used for messages + + tft.init(); + tft.setRotation(1); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nInitialisation done."); + + listFiles(); // Lists the files so you can see what is in the SPIFFS + +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + // Wrap test at right and bottom of screen + tft.setTextWrap(true, true); + + // Name of font file (library adds leading / and .vlw) + String fileName = "Final-Frontier-28"; + + // Font and background colour, background colour is used for anti-alias blending + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // Load the font + tft.loadFont(fileName); + + // Display all characters of the font + tft.showFont(2000); + + // Set "cursor" at top left corner of display (0,0) + // (cursor will move to next line automatically during printing with 'tft.println' + // or stay on the line is there is room for the text with tft.print) + tft.setCursor(0, 0); + + // Set the font colour to be white with a black background, set text size multiplier to 1 + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Hello World!"); + + // Set the font colour to be yellow + tft.setTextColor(TFT_YELLOW, TFT_BLACK); + tft.println(1234.56); + + // Set the font colour to be red + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println((uint32_t)3735928559, HEX); // Should print DEADBEEF + + // Set the font colour to be green with black background + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Anti-aliased font!"); + tft.println(""); + + // Test some print formatting functions + float fnumber = 123.45; + + // Set the font colour to be blue + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.print("Float = "); tft.println(fnumber); // Print floating point number + tft.print("Binary = "); tft.println((int)fnumber, BIN); // Print as integer value in binary + tft.print("Hexadecimal = "); tft.println((int)fnumber, HEX); // Print as integer number in Hexadecimal + + // Unload the font to recover used RAM + tft.unloadFont(); + + delay(10000); +} + + +// ------------------------------------------------------------------------- +// List files in ESP8266 or ESP32 SPIFFS memory +// ------------------------------------------------------------------------- +void listFiles(void) { + Serial.println(); + Serial.println("SPIFFS files found:"); + +#ifdef ESP32 + listDir(SPIFFS, "/", true); +#else + fs::Dir dir = SPIFFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); +#endif + Serial.println(); + delay(1000); +} + +#ifdef ESP32 +void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { + Serial.printf("Listing directory: %s\n", dirname); + + fs::File root = fs.open(dirname); + if (!root) { + Serial.println("Failed to open directory"); + return; + } + if (!root.isDirectory()) { + Serial.println("Not a directory"); + return; + } + + fs::File file = root.openNextFile(); + while (file) { + + if (file.isDirectory()) { + Serial.print("DIR : "); + String fileName = file.name(); + Serial.print(fileName); + if (levels) { + listDir(fs, file.name(), levels - 1); + } + } else { + String fileName = file.name(); + Serial.print(" " + fileName); + int spaces = 32 - fileName.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + String fileSize = (String) file.size(); + spaces = 8 - fileSize.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + Serial.println(fileSize + " bytes"); + } + + file = root.openNextFile(); + } +} +#endif +// ------------------------------------------------------------------------- diff --git a/examples/Smooth Fonts/Print_Smooth_Font/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/Print_Smooth_Font/data/Final-Frontier-28.vlw new file mode 100644 index 0000000..2872fd5 Binary files /dev/null and b/examples/Smooth Fonts/Print_Smooth_Font/data/Final-Frontier-28.vlw differ diff --git a/examples/Smooth Fonts/Unicode_test/SPIFFS_functions.ino b/examples/Smooth Fonts/Unicode_test/SPIFFS_functions.ino new file mode 100644 index 0000000..1415556 --- /dev/null +++ b/examples/Smooth Fonts/Unicode_test/SPIFFS_functions.ino @@ -0,0 +1,83 @@ +/*==================================================================================== + This sketch supports for the ESP6266 and ESP32 SPIFFS filing system + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +//==================================================================================== +// Print a SPIFFS directory list (root directory) +//==================================================================================== + +void listFiles(void) { + Serial.println(); + Serial.println("SPIFFS files found:"); + +#ifdef ESP32 + listDir(SPIFFS, "/", true); +#else + fs::Dir dir = SPIFFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); +#endif + Serial.println(); + delay(1000); +} +//==================================================================================== + +#ifdef ESP32 +void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { + Serial.printf("Listing directory: %s\n", dirname); + + fs::File root = fs.open(dirname); + if (!root) { + Serial.println("Failed to open directory"); + return; + } + if (!root.isDirectory()) { + Serial.println("Not a directory"); + return; + } + + fs::File file = root.openNextFile(); + while (file) { + + if (file.isDirectory()) { + Serial.print("DIR : "); + String fileName = file.name(); + Serial.print(fileName); + if (levels) { + listDir(fs, file.name(), levels - 1); + } + } else { + String fileName = file.name(); + Serial.print(" " + fileName); + int spaces = 32 - fileName.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + String fileSize = (String) file.size(); + spaces = 8 - fileSize.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + Serial.println(fileSize + " bytes"); + } + + file = root.openNextFile(); + } +} +#endif diff --git a/examples/Smooth Fonts/Unicode_test/Unicode_test.ino b/examples/Smooth Fonts/Unicode_test/Unicode_test.ino new file mode 100644 index 0000000..aac4926 --- /dev/null +++ b/examples/Smooth Fonts/Unicode_test/Unicode_test.ino @@ -0,0 +1,148 @@ +// Created by Bodmer 24th Jan 2017 - Tested in Arduino IDE 1.8.5 esp8266 Core 2.4.0 + +// The latest Arduino IDE versions support UTF-8 encoding of Unicode characters +// within sketches: +// https://playground.arduino.cc/Code/UTF-8 + +/* + The library expects strings to be in UTF-8 encoded format: + https://www.fileformat.info/info/unicode/utf8.htm + + Creating varaibles needs to be done with care when using character arrays: + char c = 'µ'; // Wrong + char bad[4] = "5µA"; // Wrong + char good[] = "5µA"; // Good + String okay = "5µA"; // Good + + This is because UTF-8 characters outside the basic Latin set occupy more than + 1 byte per character! A 16 bit unicode character occupies 3 bytes! + +*/ + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the SPIFFS FLASH filing system this is part of the ESP Core + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +uint16_t bg = TFT_BLACK; +uint16_t fg = TFT_WHITE; + + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(115200); // Used for messages and the C array generator + + Serial.println("NodeMCU vlw font test!"); + + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nInitialisation done."); + + listFiles(); // Lists the files so you can see what is in the SPIFFS + + tft.begin(); + tft.setRotation(0); // portrait + + fg = TFT_WHITE; + bg = TFT_BLACK; +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + tft.setTextColor(fg, bg); + + //---------------------------------------------------------------------------- + // Anti-aliased font test + + String test1 = "Hello World"; + + // Load a smooth font from SPIFFS + tft.loadFont("Final-Frontier-28"); + + tft.setRotation(0); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); + + tft.println(test1); + + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // We can have any random mix of characters in the font + + String test2 = "仝倀"; // Unicodes 0x4EDD, 0x5000 + + tft.loadFont("Unicode-Test-72"); + + tft.setRotation(1); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setCursor(0,0); + + tft.setTextColor(TFT_CYAN, bg); + tft.println(test2); + + tft.setTextColor(TFT_YELLOW, bg); + tft.println("12:00pm"); + + tft.setTextColor(TFT_MAGENTA, bg); + tft.println("1000Ω"); + + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + + //---------------------------------------------------------------------------- + // Latin and Hiragana font mix + + String test3 = "こんにちは"; + + tft.loadFont("Latin-Hiragana-24"); + + tft.setRotation(0); + + // Show all characters on screen with 2 second (2000ms) delay between screens + tft.showFont(2000); // Note: This function moves the cursor position! + + tft.fillScreen(bg); + tft.setTextColor(TFT_GREEN, bg); + tft.setCursor(0,0); + + tft.println("Konnichiwa"); + tft.println(test3); + tft.println(); + tft.println("Sayonara"); + tft.println("さようなら"); // Sayonara + + // Remove font parameters from memory to recover RAM + tft.unloadFont(); + + delay(2000); + // + //---------------------------------------------------------------------------- +} +//==================================================================================== + diff --git a/examples/Smooth Fonts/Unicode_test/data/Final-Frontier-28.vlw b/examples/Smooth Fonts/Unicode_test/data/Final-Frontier-28.vlw new file mode 100644 index 0000000..2872fd5 Binary files /dev/null and b/examples/Smooth Fonts/Unicode_test/data/Final-Frontier-28.vlw differ diff --git a/examples/Smooth Fonts/Unicode_test/data/Latin-Hiragana-24.vlw b/examples/Smooth Fonts/Unicode_test/data/Latin-Hiragana-24.vlw new file mode 100644 index 0000000..b2f128b Binary files /dev/null and b/examples/Smooth Fonts/Unicode_test/data/Latin-Hiragana-24.vlw differ diff --git a/examples/Smooth Fonts/Unicode_test/data/Unicode-Test-72.vlw b/examples/Smooth Fonts/Unicode_test/data/Unicode-Test-72.vlw new file mode 100644 index 0000000..c475756 Binary files /dev/null and b/examples/Smooth Fonts/Unicode_test/data/Unicode-Test-72.vlw differ diff --git a/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino b/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino new file mode 100644 index 0000000..f3f4cdf --- /dev/null +++ b/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino @@ -0,0 +1,194 @@ +/* + This tests the alpha blending function that is used with the antialiased + fonts: + + Alpha = 0 = 100% background, alpha = 255 = 100% foreground colour + + blendedColor = tft.alphaBlend(alpha, fg_color, bg_color); + + The alphaBlend() function operates on 16 bit colours only + A test is included where the colours are mapped to 8 bits after blending + + Information on alpha blending is here + https://en.wikipedia.org/wiki/Alpha_compositing + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + The sketch has been tested on a 320x240 ILI9341 based TFT, it + could be adapted for other screen sizes. + + Created by Bodmer 10/2/18 + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +#include // Include the graphics library + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + tft.init(); + tft.setRotation(0); + tft.fillScreen(TFT_DARKGREY); +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() +{ + // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) + // Blend from white to full spectrum + for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_WHITE)); + } + + // Blend from full spectrum to black + for (int a = 255; a > 2; a-=2) + { + for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_BLACK)); + } + + // Blend from white to black (32 grey levels) + for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)); + tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_RED)); + tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_GREEN)); + tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLUE)); + } + + delay(4000); + + // Blend from white to colour (32 grey levels) + for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + //tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)); + tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_RED, TFT_WHITE)); + tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_GREEN, TFT_WHITE)); + tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLUE, TFT_WHITE)); + } + + delay(4000); + + //* + // Decrease to 8 bit colour (3 bits red, 3 bits green, 2 bits blue) + // Blend from white to full spectrum + for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying + for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0xFFFF)))); + } + + // Blend from full spectrum to black + for (int a = 255; a > 2; a-=2) + { + // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying + for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0)))); + } + + // Blend from white to black (4 grey levels - it will draw 4 more with a blue tinge due to lower blue bit count) + // Blend from black to a primary colour + for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + tft.drawFastHLine(192, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)))); + tft.drawFastHLine(204, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_RED)))); + tft.drawFastHLine(216, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_GREEN)))); + tft.drawFastHLine(228, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_BLUE)))); + } + + delay(4000); + //*/ + + /* + // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) + for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_CYAN)); + } + + // Blend from full spectrum to cyan + for (int a = 255; a > 2; a-=2) + { + for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_YELLOW)); + } + //*/ + + /* + // Blend other colour transitions for test purposes + for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground + { + tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_WHITE, TFT_WHITE)); // Should show as solid white + tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLACK)); // Should show as solid black + tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_YELLOW, TFT_CYAN)); // Brightness should be fairly even + tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_CYAN, TFT_MAGENTA));// Brightness should be fairly even + } + + delay(4000); + //*/ +} + + +// ######################################################################### +// Return a 16 bit rainbow colour +// ######################################################################### +unsigned int rainbow(byte value) +{ + // If 'value' is in the range 0-159 it is converted to a spectrum colour + // from 0 = red through to 127 = blue to 159 = violet + // Extending the range to 0-191 adds a further violet to red band + + value = value%192; + + byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte green = 0; // Green is the middle 6 bits, but only top 5 bits used here + byte blue = 0; // Blue is the bottom 5 bits + + byte sector = value >> 5; + byte amplit = value & 0x1F; + + switch (sector) + { + case 0: + red = 0x1F; + green = amplit; // Green ramps up + blue = 0; + break; + case 1: + red = 0x1F - amplit; // Red ramps down + green = 0x1F; + blue = 0; + break; + case 2: + red = 0; + green = 0x1F; + blue = amplit; // Blue ramps up + break; + case 3: + red = 0; + green = 0x1F - amplit; // Green ramps down + blue = 0x1F; + break; + case 4: + red = amplit; // Red ramps up + green = 0; + blue = 0x1F; + break; + case 5: + red = 0x1F; + green = 0; + blue = 0x1F - amplit; // Blue ramps down + break; + } + + return red << 11 | green << 6 | blue; +} + + diff --git a/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino b/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino new file mode 100644 index 0000000..dacf64f --- /dev/null +++ b/examples/Sprite/One_bit_Sprite_Demo/One_bit_Sprite_Demo.ino @@ -0,0 +1,106 @@ +/* + Sketch to show creation of a 1bpp sprite with a transparent + background, then plot it on the TFT. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 1 bit Sprite occupies (width * height)/8 bytes in RAM. So, + for example, a 320 x 240 pixel Sprite occupies 9600 bytes. +*/ +// A new setBitmapColor(fg_color, bg_color) function allows +// any 2 colours to be used for the 1 bit sprite. +// One colour can also be defined as transparent when +// rendering to the screen. + + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object + // the pointer is used by pushSprite() to push it onto the TFT + +#define BITS_PER_PIXEL 1 // How many bits per pixel in Sprite + +// ========================================================================= +void setup(void) { + Serial.begin(250000); + + tft.init(); + + tft.setRotation(0); +} +// ========================================================================= +void loop() { + + tft.fillScreen(TFT_NAVY); + + // Draw 10 sprites containing a "transparent" colour + for (int i = 0; i < 10; i++) + { + int x = random(240 - 70); + int y = random(320 - 80); + int c = random(0x10000); // Random colour 0 - 0xFFFF + drawStar(x, y, c); + } + + delay(2000); + + // Now go bananas and draw 500 more + for (int i = 0; i < 500; i++) + { + int x = random(240 - 70); + int y = random(320 - 80); + int c = random(0x10000); // Random colour + drawStar(x, y, c); + yield(); // Stop watchdog reset + } + + delay(2000); +} +// ========================================================================= +// Create sprite, plot graphics in it, plot to screen, then delete sprite +// ========================================================================= +void drawStar(int x, int y, int star_color) +{ + // 1 bpp colour values can only be 1 or 0 (one or zero) + uint16_t transparent = 0; // The transparent colour, can only be 1 or 0 + + // Create an 1 bit (2 colour) sprite 70x80 pixels (uses 70*80/8 = 700 bytes of RAM) + // Colour depths of 8 bits per pixel and 16 bits are also supported. + img.setColorDepth(BITS_PER_PIXEL); // Set colour depth first + img.createSprite(70, 80); // then create the sprite + + // Fill Sprite with the colour that will be defined later as "transparent" + // We could also fill with any colour as transparent, and later specify that + // same colour when we push the Sprite onto the display screen. + img.fillSprite(transparent); + + // Draw 2 triangles to create a filled in star + img.fillTriangle(35, 0, 0, 59, 69, 59, star_color); + img.fillTriangle(35, 79, 0, 20, 69, 20, star_color); + + // Punch a star shaped hole in the middle with a smaller "transparent" star + img.fillTriangle(35, 7, 6, 56, 63, 56, transparent); + img.fillTriangle(35, 73, 6, 24, 63, 24, transparent); + + // Set the 2 pixel colours that 1 and 0 represent on the display screen + img.setBitmapColor(star_color, transparent); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // Specify what colour is to be treated as transparent (black in this example) + img.pushSprite(x, y, transparent); + + // Delete Sprite to free memory, creating and deleting takes very little time. + img.deleteSprite(); +} +// ========================================================================= + diff --git a/examples/Sprite/One_bit_Yin_Yang/One_bit_Yin_Yang.ino b/examples/Sprite/One_bit_Yin_Yang/One_bit_Yin_Yang.ino new file mode 100644 index 0000000..7067f7a --- /dev/null +++ b/examples/Sprite/One_bit_Yin_Yang/One_bit_Yin_Yang.ino @@ -0,0 +1,97 @@ +// This sketch draws a rotating Yin and Yang symbol. It illustrates +// the drawimg and rendering of simple animated graphics using +// a 1 bit per pixel (1 bpp) Sprite. + +// Note: TFT_BLACK sets the pixel value to 0 +// Any other colour sets the pixel value to 1 + +// A square sprite of side = 2 x RADIUS will be created +// (80 * 80)/8 = 800 bytes needed for 1 bpp sprite +// 6400 bytes for 8 bpp +// 12800 bytes for 16 bpp +#define RADIUS 40 // Radius of completed symbol = 40 + +#define WAIT 0 // Loop delay + +// 1bpp Sprites are economical on memory but slower to render +#define COLOR_DEPTH 1 // Colour depth (1, 8 or 16 bits per pixel) + +// Rotation angle increment and start angle +#define ANGLE_INC 3 +int angle = 0; + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +TFT_eSprite img = TFT_eSprite(&tft); // Sprite class + + +// ------------------------------------------------------------------------- +void setup(void) +{ + tft.begin(); + tft.setRotation(0); + tft.fillScreen(TFT_BLUE); + + img.setColorDepth(COLOR_DEPTH); + img.createSprite(RADIUS*2+1, RADIUS*2+1); + img.fillSprite(TFT_BLACK); +} +// ------------------------------------------------------------------------- +// ------------------------------------------------------------------------- +void loop() { + // Draw Yin and Yang symbol circles into Sprite + yinyang(RADIUS, RADIUS, angle, RADIUS); + + // Set the 2 pixel palette colours that 1 and 0 represent on the display screen + img.setBitmapColor(TFT_WHITE, TFT_BLACK); + + // Push Sprite image to the TFT screen at x, y + img.pushSprite(tft.width()/2 - RADIUS, 0); // Plot sprite + + angle+=3; //Increment angle to rotate circle positions + if (angle > 359) angle = 0; // Limit angle range + + // Slow things down + delay(WAIT); +} +// ------------------------------------------------------------------------- + + +// ========================================================================= +// Draw circles for Yin and Yang - rotate positions to create symbol +// ========================================================================= +// x,y == coordinate center within Sprite +// start_angle = 0 - 359 +// r = radius + +void yinyang(int x, int y, int start_angle, int r) +{ + int x1 = 0; // getCoord() will update these + int y1 = 0; + + getCoord(x, y, &x1, &y1, r/2, start_angle); // Get x1 ,y1 + img.fillCircle( x1, y1, r/2, TFT_WHITE); + img.fillCircle( x1, y1, r/8, TFT_BLACK); + + getCoord(x, y, &x1, &y1, r/2, start_angle + 180); + img.fillCircle( x1, y1, r/2, TFT_BLACK); + img.fillCircle( x1, y1, r/8, TFT_WHITE); + + img.drawCircle(x, y, r, TFT_WHITE); +} + +// ========================================================================= +// Get coordinates of end of a vector, pivot at x,y, length r, angle a +// ========================================================================= +// Coordinates are returned to caller via the xp and yp pointers +#define RAD2DEG 0.0174532925 +void getCoord(int x, int y, int *xp, int *yp, int r, int a) +{ + float sx1 = cos( (a-90) * RAD2DEG ); + float sy1 = sin( (a-90) * RAD2DEG ); + *xp = sx1 * r + x; + *yp = sy1 * r + y; +} + diff --git a/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino b/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino new file mode 100644 index 0000000..b789b50 --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_1/Rotated_Sprite_1.ino @@ -0,0 +1,182 @@ +// This example plots a rotated Sprite to the screen using the pushRotated() +// function. It is written for a 240 x 320 TFT screen. + +// Two rotation pivot points must be set, one for the Sprite and one for the TFT +// using setPivot(). These pivot points do not need to be within the visible screen +// or Sprite boundary. + +// When the Sprite is rotated and pushed to the TFT with pushRotated(angle) it will be +// drawn so that the two pivot points coincide. This makes rotation about a point on the +// screen very simple. The rotation is clockwise with increasing angle. The angle is in +// degrees, an angle of 0 means no Sprite rotation. + +// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. + +// The original Sprite is unchanged so can be plotted again at a different angle. + +// Optionally a transparent colour can be defined, pixels of this colour will +// not be plotted to the TFT. + +// For 1 bpp Sprites the foreground and background colours are defined with the +// function spr.setBitmapColor(foregroundColor, backgroundColor). + +// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +#include + +TFT_eSPI tft = TFT_eSPI(); // TFT object + +TFT_eSprite spr = TFT_eSprite(&tft); // Sprite object + +// ======================================================================================= +// Setup +// ======================================================================================= + +void setup() { + Serial.begin(250000); // Debug only + + tft.begin(); // initialize + tft.setRotation(0); +} + +// ======================================================================================= +// Loop +// ======================================================================================= + +void loop() { + + int xw = tft.width()/2; // xw, yh is midle of screen + int yh = tft.height()/2; + + + showMessage("90 degree angles"); + tft.setPivot(xw, yh); // Set pivot to middle of TFT screen + drawX(xw, yh); // Show where screen pivot is + + // Create the Sprite + spr.setColorDepth(8); // Create an 8bpp Sprite of 60x30 pixels + spr.createSprite(64, 30); // 8bpp requires 64 * 30 = 1920 bytes + spr.setPivot(32, 55); // Set pivot relative to top left corner of Sprite + spr.fillSprite(TFT_BLACK); // Fill the Sprite with black + + spr.setTextColor(TFT_GREEN); // Green text + spr.setTextDatum(MC_DATUM); // Middle centre datum + spr.drawString("Hello", 32, 15, 4); // Plot text, font 4, in Sprite at 30, 15 + + spr.pushRotated(0); + spr.pushRotated(90); + spr.pushRotated(180); + spr.pushRotated(270); + + delay(2000); + + + showMessage("45 degree angles"); + drawX(xw, yh); // Show where screen pivot is + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Moved Sprite pivot point"); + drawX(xw, yh); // Show where screen pivot is + + spr.setPivot(-20, 15); // Change just the Sprite pivot point + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Moved TFT pivot point"); + tft.setPivot(100, 100); // Change just the TFT pivot point + drawX(100, 100); // Show where pivot is + + spr.pushRotated(45); + spr.pushRotated(135); + spr.pushRotated(225); + spr.pushRotated(315); + + delay(2000); // Pause so we see it + + + showMessage("Transparent rotations"); + tft.fillCircle(xw, yh, 70, TFT_DARKGREY); // Draw a filled circle + + tft.setPivot(xw, yh); // Set pivot to middle of screen + drawX(xw, yh); // Show where pivot is + + spr.deleteSprite(); + + spr.setColorDepth(8); // Create a 8bpp Sprite + spr.createSprite(40, 30); // Create a new Sprite 40x30 + spr.setPivot(20, 70); // Set Sprite pivot at 20,80 + + spr.setTextColor(TFT_RED); // Red text in Sprite + spr.setTextDatum(MC_DATUM); // Middle centre datum + + int num = 1; + + for (int16_t angle = 30; angle <= 360; angle += 30) + { + spr.fillSprite(TFT_BLACK); // Clear the Sprite + spr.drawNumber(num, 20, 15, 4); // Plot number, in Sprite at 15,15 and with font 4 + spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent + num++; + } + + spr.setTextColor(TFT_WHITE); // White text in Sprite + spr.setPivot(-75, 15); // Set Sprite pivot at -75,15 + + for (int16_t angle = -90; angle < 270; angle += 30) + { + spr.fillSprite(TFT_BLACK); // Clear the Sprite + spr.drawNumber(angle+90, 15, 15, 4); // Plot number, in Sprite at 15,15 and with font 4 + spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent + num++; + } + + delay(8000); // Pause so we see it + + spr.deleteSprite(); + +} + +// ======================================================================================= +// Draw an X centered on x,y +// ======================================================================================= + +void drawX(int x, int y) +{ + tft.drawLine(x-5, y-5, x+5, y+5, TFT_WHITE); + tft.drawLine(x-5, y+5, x+5, y-5, TFT_WHITE); +} + +// ======================================================================================= +// Show a message at the top of the screen +// ======================================================================================= + +void showMessage(String msg) +{ + // Clear the screen areas + tft.fillRect(0, 0, tft.width(), 20, TFT_BLACK); + tft.fillRect(0, 20, tft.width(), tft.height()-20, TFT_BLUE); + + uint8_t td = tft.getTextDatum(); // Get current datum + + tft.setTextDatum(TC_DATUM); // Set new datum + + tft.drawString(msg, tft.width()/2, 2, 2); // Message in font 2 + + tft.setTextDatum(td); // Restore old datum +} + +// ======================================================================================= diff --git a/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino b/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino new file mode 100644 index 0000000..1dc5da7 --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_2/Rotated_Sprite_2.ino @@ -0,0 +1,181 @@ +// This example plots a rotated Sprite into another Sprite and then the resultant composited +// Sprite is pushed to the TFT screen. This example is for a 240 x 320 screen. + +// The motivation for developing this capability is that animated dials can be drawn easily +// and the complex calculations involved are handled by the TFT_eSPI library. To create a dial +// with a moving needle a graphic of a meter needle is plotted at a specified angle into another +// Sprite that contains the dial face. When the needle Sprite is pushed to the dial Sprite the +// plotting ensures two pivot points for each Sprite coincide with pixel level accuracy. + +// Two rotation pivot points must be set, one for the first Sprite and one for the second +// Sprite using setPivot(). These pivot points do not need to be within the Sprite boundaries. + +// In this example a needle graphic is also be plotted direct to a defined TFT pivot point. + +// The rotation angle is in degrees, an angle of 0 means no Sprite rotation. + +// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. + +// For 1 bpp Sprites the foreground and background colours are defined with the +// member function setBitmapColor(foregroundColor, backgroundColor). + +// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite dial = TFT_eSprite(&tft); // Sprite object for dial +TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle + +uint32_t startMillis; + +int16_t angle = 0; + +// ======================================================================================= +// Setup +// ======================================================================================= + +void setup() { + Serial.begin(250000); // Debug only + + tft.begin(); + tft.setRotation(1); + + // Clear TFT screen + tft.fillScreen(TFT_NAVY); + + // Create the dial Sprite and dial (this temporarily hijacks the use of the needle Sprite) + createDialScale(-120, 120, 30); // create scale (start angle, end angle, increment angle) + drawEmptyDial("Label", 12345); // draw the centre of dial in the Sprite + + dial.pushSprite(110, 0); // push a copy of the dial to the screen so we can see it + + // Create the needle Sprite + createNeedle(); // draw the needle graphic + needle.pushSprite(95, 7); // push a copy of the needle to the screen so we can see it +} + +// ======================================================================================= +// Loop +// ======================================================================================= + +void loop() { + + // Push the needle sprite to the dial Sprite at different angles and then push the dial to the screen + // Use angle increments in range 1 to 6 for smoother or faster movement + for (int16_t angle = -120; angle <= 120; angle += 2) { + plotDial(0, 0, angle, "RPM", angle + 120); + delay(25); + yield(); // Avoid a watchdog time-out + } + + delay(1000); // Pause + + // Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay + for (int16_t angle = 120; angle >= -120; angle -= 2) { + plotDial(0, 0, angle, "RPM", angle + 120); + yield(); // Avoid a watchdog time-out + } + + // Now show plotting of the rotated needle direct to the TFT + tft.setPivot(45, 150); // Set the TFT pivot point that the needle will rotate around + + // The needle graphic has a black border so if the angle increment is small + // (6 degrees or less in this case) it wipes the last needle position when + // it is rotated and hence it clears the swept area to black + for (int16_t angle = 0; angle <= 360; angle += 5) + { + needle.pushRotated(angle); // Plot direct to TFT at specifed angle + yield(); // Avoid a watchdog time-out + } +} + +// ======================================================================================= +// Create the dial sprite, the dial outer and place scale markers +// ======================================================================================= + +void createDialScale(int16_t start_angle, int16_t end_angle, int16_t increment) +{ + // Create the dial Sprite + dial.setColorDepth(8); // Size is odd (i.e. 91) so there is a centre pixel at 45,45 + dial.createSprite(91, 91); // 8bpp requires 91 * 91 = 8281 bytes + dial.setPivot(45, 45); // set pivot in middle of dial Sprite + + // Draw dial outline + dial.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour + dial.fillCircle(45, 45, 43, TFT_DARKGREY); // Draw dial outer + + // Hijack the use of the needle Sprite since that has not been used yet! + needle.createSprite(3, 3); // 3 pixels wide, 3 high + needle.fillSprite(TFT_WHITE); // Fill with white + needle.setPivot(1, 43); // Set pivot point x to the Sprite centre and y to marker radius + + for (int16_t angle = start_angle; angle <= end_angle; angle += increment) { + needle.pushRotated(&dial, angle); // Sprite is used to make scale markers + yield(); // Avoid a watchdog time-out + } + + needle.deleteSprite(); // Delete the hijacked Sprite +} + + +// ======================================================================================= +// Add the empty dial face with label and value +// ======================================================================================= + +void drawEmptyDial(String label, int16_t val) +{ + // Draw black face + dial.fillCircle(45, 45, 40, TFT_BLACK); + dial.drawPixel(45, 45, TFT_WHITE); // For demo only, mark pivot point with a while pixel + + dial.setTextDatum(TC_DATUM); // Draw dial text + dial.drawString(label, 45, 15, 2); + dial.drawNumber(val, 45, 60, 2); +} + +// ======================================================================================= +// Update the dial and plot to screen with needle at defined angle +// ======================================================================================= + +void plotDial(int16_t x, int16_t y, int16_t angle, String label, uint16_t val) +{ + // Draw the blank dial in the Sprite, add label and number + drawEmptyDial(label, val); + + // Push a rotated needle Sprite to the dial Sprite, with black as transparent colour + needle.pushRotated(&dial, angle, TFT_BLACK); // dial is the destination Sprite + + // Push the resultant dial Sprite to the screen, with transparent colour + dial.pushSprite(x, y, TFT_TRANSPARENT); +} + +// ======================================================================================= +// Create the needle Sprite and the image of the needle +// ======================================================================================= + +void createNeedle(void) +{ + needle.setColorDepth(8); + needle.createSprite(11, 49); // create the needle Sprite 11 pixels wide by 49 high + + needle.fillSprite(TFT_BLACK); // Fill with black + + // Define needle pivot point + uint16_t piv_x = needle.width() / 2; // x pivot of Sprite (middle) + uint16_t piv_y = needle.height() - 10; // y pivot of Sprite (10 pixels from bottom) + needle.setPivot(piv_x, piv_y); // Set pivot point in this Sprite + + // Draw the red needle with a yellow tip + // Keep needle tip 1 pixel inside dial circle to avoid leaving stray pixels + needle.fillRect(piv_x - 1, 2, 3, piv_y + 8, TFT_RED); + needle.fillRect(piv_x - 1, 2, 3, 5, TFT_YELLOW); + + // Draw needle centre boss + needle.fillCircle(piv_x, piv_y, 5, TFT_MAROON); + needle.drawPixel( piv_x, piv_y, TFT_WHITE); // Mark needle pivot point with a white pixel +} + +// ======================================================================================= diff --git a/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino new file mode 100644 index 0000000..8e8e72b --- /dev/null +++ b/examples/Sprite/Rotated_Sprite_3/Rotated_Sprite_3.ino @@ -0,0 +1,140 @@ +/*==================================================================================== + + This example draws a jpeg image in a Sprite then plot a rotated copy of the Sprite + to the TFT. + + The jpeg used in in the sketch Data folder (presss Ctrl+K to see folder) + + The jpeg must be uploaded to the ESP8266 or ESP32 SPIFFS by using the Tools menu + sketch data upload option of the Arduino IDE. If you do not have that option it can + be added. Close the Serial Monitor window before uploading to avoid an error message! + + To add the upload option for the ESP8266 see: + http://www.esp8266.com/viewtopic.php?f=32&t=10081 + https://github.com/esp8266/arduino-esp8266fs-plugin/releases + + To add the upload option for the ESP32 see: + https://github.com/me-no-dev/arduino-esp32fs-plugin + + Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: + https://github.com/Bodmer/TFT_eSPI + + Extension funtions in the TFT_eFEX library are used to list SPIFFS files and render + the jpeg to the TFT and to the Sprite: + https://github.com/Bodmer/TFT_eFEX + + To render the Jpeg image the JPEGDecoder library is needed, this can be obtained + with the IDE library manager, or downloaded from here: + https://github.com/Bodmer/JPEGDecoder + + ==================================================================================*/ + +//==================================================================================== +// Libraries +//==================================================================================== +// Call up the SPIFFS FLASH filing system, this is part of the ESP Core +#define FS_NO_GLOBALS +#include + +#ifdef ESP32 +#include "SPIFFS.h" // Needed for ESP32 only +#endif + +// https://github.com/Bodmer/TFT_eSPI +#include // Hardware-specific library +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library +TFT_eSprite spr = TFT_eSprite(&tft); // Create Sprite object "spr" with pointer to "tft" object + +// https://github.com/Bodmer/TFT_eFEX +#include // Include the function extension library +TFT_eFEX fex = TFT_eFEX(&tft); // Create TFT_eFX object "fex" with pointer to "tft" object + + +//==================================================================================== +// Setup +//==================================================================================== +void setup() +{ + Serial.begin(250000); // Used for messages + + tft.begin(); + tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape + tft.fillScreen(TFT_BLACK); + + // Create a sprite to hold the jpeg (or part of it) + spr.createSprite(80, 64); + + // Initialise SPIFFS + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs waiting + } + Serial.println("\r\nInitialisation done.\r\n"); + + // Lists the files so you can see what is in the SPIFFS + fex.listSPIFFS(); + + // Note the / before the SPIFFS file name must be present, this means the file is in + // the root directory of the SPIFFS, e.g. "/tiger.jpg" for a file called "tiger.jpg" + + // Send jpeg info to serial port + fex.jpegInfo("/Eye_80x64.jpg"); + + // Draw jpeg iamge in Sprite spr at 0,0 + fex.drawJpeg("/Eye_80x64.jpg", 0 , 0, &spr); +} + +//==================================================================================== +// Loop +//==================================================================================== +void loop() +{ + + tft.fillScreen(random(0xFFFF)); + + + // Set the TFT pivot point to the centre of the screen + tft.setPivot(tft.width() / 2, tft.height() / 2); + + // Set Sprite pivot point to centre of Sprite + spr.setPivot(spr.width() / 2, spr.height() / 2); + + // Push Sprite to the TFT at 0,0 (not rotated) + spr.pushSprite(0, 0); + + delay(1000); + + // Push copies of Sprite rotated through increasing angles 0-360 degrees + // with 45 fegree increments + for (int16_t angle = 0; angle <= 360; angle += 45) { + spr.pushRotated(angle); + delay(500); + } + + delay(2000); + + // Move Sprite pivot to a point above the image at 40,-60 + // (Note: Top left corner is Sprite coordinate 0,0) + // The TFT pivot point has already been set to middle of screen. + /* .Pivot point at 40,-60 + ^ + | + -60 + < 40 >| + ______V______ + | | + | Sprite | + |_____________| + */ + spr.setPivot(40, -60); + + // Push Sprite to screen rotated about the new pivot points + // negative angle rotates Sprite anticlockwise + for (int16_t angle = 330; angle >= 0; angle -= 30) { + spr.pushRotated(angle); + yield(); // Stop watchdog triggering + } + + delay(5000); +} +//==================================================================================== diff --git a/examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg b/examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg new file mode 100644 index 0000000..240b7ef Binary files /dev/null and b/examples/Sprite/Rotated_Sprite_3/data/EagleEye.jpg differ diff --git a/examples/Sprite/Rotated_Sprite_3/data/Eye_80x64.jpg b/examples/Sprite/Rotated_Sprite_3/data/Eye_80x64.jpg new file mode 100644 index 0000000..10013b7 Binary files /dev/null and b/examples/Sprite/Rotated_Sprite_3/data/Eye_80x64.jpg differ diff --git a/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino b/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino new file mode 100644 index 0000000..407c53f --- /dev/null +++ b/examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino @@ -0,0 +1,197 @@ +/* + Display all the fast rendering fonts in a sprite + + Make sure all the display driver and pin comnections are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Specify sprite 160 x 128 pixels (needs 40Kbytes of RAM for 16 bit colour) +#define IWIDTH 160 +#define IHEIGHT 128 + +// Pause in milliseconds between screens, change to 0 to time font rendering +#define WAIT 500 + +#include // Graphics and font library for ST7735 driver chip +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h + +TFT_eSprite img = TFT_eSprite(&tft); + +unsigned long targetTime = 0; // Used for testing draw times + +void setup(void) { + tft.init(); + tft.setRotation(0); + + tft.fillScreen(TFT_BLUE); + + //img.setColorDepth(8); // Optionally set depth to 8 to halve RAM use + img.createSprite(IWIDTH, IHEIGHT); + img.fillSprite(TFT_BLACK); +} + +void loop() { + targetTime = millis(); + + // First we test them with a background colour set + img.setTextSize(1); + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_GREEN, TFT_BLACK); + + img.drawString(" !\"#$%&'()*+,-./0123456", 0, 0, 2); + img.drawString("789:;<=>?@ABCDEFGHIJKL", 0, 16, 2); + img.drawString("MNOPQRSTUVWXYZ[\\]^_`", 0, 32, 2); + img.drawString("abcdefghijklmnopqrstuvw", 0, 48, 2); + + int xpos = 0; + xpos += img.drawString("xyz{|}~", 0, 64, 2); + img.drawChar(127, xpos, 64, 2); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_GREEN, TFT_BLACK); + + img.drawString(" !\"#$%&'()*+,-.", 0, 0, 4); + img.drawString("/0123456789:;", 0, 26, 4); + img.drawString("<=>?@ABCDE", 0, 52, 4); + img.drawString("FGHIJKLMNO", 0, 78, 4); + img.drawString("PQRSTUVWX", 0, 104, 4); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.drawString("YZ[\\]^_`abc", 0, 0, 4); + img.drawString("defghijklmno", 0, 26, 4); + img.drawString("pqrstuvwxyz", 0, 52, 4); + xpos = 0; + xpos += img.drawString("{|}~", 0, 78, 4); + img.drawChar(127, xpos, 78, 4); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_BLUE, TFT_BLACK); + + img.drawString("012345", 0, 0, 6); + img.drawString("6789", 0, 40, 6); + img.drawString("apm-:.", 0, 80, 6); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_RED, TFT_BLACK); + + img.drawString("0123", 0, 0, 7); + img.drawString("4567", 0, 60, 7); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.drawString("890:.", 0, 0, 7); + img.drawString("", 0, 60, 7); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_YELLOW, TFT_BLACK); + + img.drawString("01", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.drawString("23", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.drawString("45", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.drawString("67", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.drawString("89", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.drawString("0:.", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.setTextColor(TFT_WHITE); + img.drawNumber(millis() - targetTime, 0, 100, 4); + img.pushSprite(0, 0); delay(WAIT); + delay(4000); + + // Now test them with transparent background + targetTime = millis(); + + img.setTextSize(1); + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_GREEN); + + img.drawString(" !\"#$%&'()*+,-./0123456", 0, 0, 2); + img.drawString("789:;<=>?@ABCDEFGHIJKL", 0, 16, 2); + img.drawString("MNOPQRSTUVWXYZ[\\]^_`", 0, 32, 2); + img.drawString("abcdefghijklmnopqrstuvw", 0, 48, 2); + xpos = 0; + xpos += img.drawString("xyz{|}~", 0, 64, 2); + img.drawChar(127, xpos, 64, 2); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_GREEN); + + img.drawString(" !\"#$%&'()*+,-.", 0, 0, 4); + img.drawString("/0123456789:;", 0, 26, 4); + img.drawString("<=>?@ABCDE", 0, 52, 4); + img.drawString("FGHIJKLMNO", 0, 78, 4); + img.drawString("PQRSTUVWX", 0, 104, 4); + + img.pushSprite(0, 0); delay(WAIT); + img.fillSprite(TFT_BLACK); + img.drawString("YZ[\\]^_`abc", 0, 0, 4); + img.drawString("defghijklmno", 0, 26, 4); + img.drawString("pqrstuvwxyz", 0, 52, 4); + xpos = 0; + xpos += img.drawString("{|}~", 0, 78, 4); + img.drawChar(127, xpos, 78, 4); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_BLUE); + + img.drawString("012345", 0, 0, 6); + img.drawString("6789", 0, 40, 6); + img.drawString("apm-:.", 0, 80, 6); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_RED); + + img.drawString("0123", 0, 0, 7); + img.drawString("4567", 0, 60, 7); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.drawString("890:.", 0, 0, 7); + img.drawString("", 0, 60, 7); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.setTextColor(TFT_YELLOW); + + img.drawString("0123", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.drawString("4567", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.fillSprite(TFT_BLACK); + img.drawString("890:.", 0, 0, 8); + img.pushSprite(0, 0); delay(WAIT); + + img.setTextColor(TFT_WHITE); + + img.drawNumber(millis() - targetTime, 0, 100, 4); + img.pushSprite(0, 0); delay(WAIT); + delay(4000);; +} + diff --git a/examples/Sprite/Sprite_TFT_Rainbow/Sprite_TFT_Rainbow.ino b/examples/Sprite/Sprite_TFT_Rainbow/Sprite_TFT_Rainbow.ino new file mode 100644 index 0000000..e384ea2 --- /dev/null +++ b/examples/Sprite/Sprite_TFT_Rainbow/Sprite_TFT_Rainbow.ino @@ -0,0 +1,140 @@ +/* + An example showing rainbow colours on a 160x128 TFT LCD screen + and to show a basic example of font use. + + This example plots the text in a sprite then pushes the sprite to the + TFT screen. + + Make sure all the display driver and pin comnenctions are correct by + editting the User_Setup.h file in the TFT_eSPI library folder. + + Note that yield() or delay(0) must be called in long duration for/while + loops to stop the ESP8266 watchdog triggering. + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +#define IWIDTH 160 +#define IHEIGHT 128 + +#include // Graphics and font library +#include + +TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h + +TFT_eSprite img = TFT_eSprite(&tft); + +unsigned long targetTime = 0; +byte red = 31; +byte green = 0; +byte blue = 0; +byte state = 0; +unsigned int colour = red << 11; + +void setup(void) { + tft.init(); + tft.setRotation(1); + tft.fillScreen(TFT_BLACK); + + img.createSprite(IWIDTH, IHEIGHT); + img.fillSprite(TFT_BLACK); + + targetTime = millis() + 1000; +} + +void loop() { + + if (targetTime < millis()) { + targetTime = millis() + 100;//10000; + + // Colour changing state machine + for (int i = 0; i < 160; i++) { + img.drawFastVLine(i, 0, img.height(), colour); + switch (state) { + case 0: + green += 2; + if (green == 64) { + green = 63; + state = 1; + } + break; + case 1: + red--; + if (red == 255) { + red = 0; + state = 2; + } + break; + case 2: + blue ++; + if (blue == 32) { + blue = 31; + state = 3; + } + break; + case 3: + green -= 2; + if (green == 255) { + green = 0; + state = 4; + } + break; + case 4: + red ++; + if (red == 32) { + red = 31; + state = 5; + } + break; + case 5: + blue --; + if (blue == 255) { + blue = 0; + state = 0; + } + break; + } + colour = red << 11 | green << 5 | blue; + } + + // The standard ADAFruit font still works as before + img.setTextColor(TFT_BLACK); + img.setCursor (12, 5); + img.print("Original ADAfruit font!"); + + // The new larger fonts do not use the .setCursor call, coords are embedded + img.setTextColor(TFT_BLACK, TFT_BLACK); // Do not plot the background colour + + // Overlay the black text on top of the rainbow plot (the advantage of not drawing the backgorund colour!) + img.drawCentreString("Font size 2", 80, 14, 2); // Draw text centre at position 80, 12 using font 2 + + //img.drawCentreString("Font size 2",81,12,2); // Draw text centre at position 80, 12 using font 2 + + img.drawCentreString("Font size 4", 80, 30, 4); // Draw text centre at position 80, 24 using font 4 + + img.drawCentreString("12.34", 80, 54, 6); // Draw text centre at position 80, 24 using font 6 + + img.drawCentreString("12.34 is in font size 6", 80, 92, 2); // Draw text centre at position 80, 90 using font 2 + + // Note the x position is the top left of the font! + + // draw a floating point number + float pi = 3.14159; // Value to print + int precision = 3; // Number of digits after decimal point + int xpos = 50; // x position + int ypos = 110; // y position + int font = 2; // font number only 2,4,6,7 valid. Font 6 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : a p m + xpos += img.drawFloat(pi, precision, xpos, ypos, font); // Draw rounded number and return new xpos delta for next print position + img.drawString(" is pi", xpos, ypos, font); // Continue printing from new x position + + img.pushSprite(0, 0); + } +} + + + + + + diff --git a/examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino b/examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino new file mode 100644 index 0000000..78e02f2 --- /dev/null +++ b/examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino @@ -0,0 +1,141 @@ +/* + + Sketch to show how a Sprite is created, how to draw pixels + and text within the Sprite and then push the Sprite onto + the display screen. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + + On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, + this size requires 40kBytes of RAM for a 16 bit colour depth. + + When 8 bit colour depth sprites are created they occupy + (width * height) bytes in RAM, so larger sprites can be + created, or the RAM required is halved. + +*/ + +// Set delay after plotting the sprite +#define DELAY 1000 + +// Width and height of sprite +#define WIDTH 128 +#define HEIGHT 128 + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Declare object "tft" + +TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object + +void setup() +{ + Serial.begin(250000); + Serial.println(); + + // Initialise the TFT registers + tft.init(); + + // Optionally set colour depth to 8 or 16 bits, default is 16 if not spedified + // spr.setColorDepth(8); + + // Create a sprite of defined size + spr.createSprite(WIDTH, HEIGHT); + + // Clear the TFT screen to blue + tft.fillScreen(TFT_BLUE); +} + +void loop(void) +{ + // Fill the whole sprite with black (Sprite is in memory so not visible yet) + spr.fillSprite(TFT_BLACK); + + // Number of pixels to draw + uint16_t n = 100; + + // Draw 100 random colour pixels at random positions in sprite + while (n--) + { + uint16_t colour = random(0x10000); // Returns colour 0 - 0xFFFF + int16_t x = random(WIDTH); // Random x coordinate + int16_t y = random(HEIGHT); // Random y coordinate + spr.drawPixel( x, y, colour); // Draw pixel in sprite + } + + // Draw some lines + spr.drawLine(1, 0, WIDTH, HEIGHT-1, TFT_GREEN); + spr.drawLine(0, 0, WIDTH, HEIGHT, TFT_GREEN); + spr.drawLine(0, 1, WIDTH-1, HEIGHT, TFT_GREEN); + spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, TFT_RED); + spr.drawLine(0, HEIGHT, WIDTH, 0, TFT_RED); + spr.drawLine(1, HEIGHT, WIDTH, 1, TFT_RED); + + // Draw some text with Middle Centre datum + spr.setTextDatum(MC_DATUM); + spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4); + + // Now push the sprite to the TFT at position 0,0 on screen + spr.pushSprite(-40, -40); + spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2); + spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40); + + delay(DELAY); + + // Fill TFT screen with blue + tft.fillScreen(TFT_BLUE); + + // Draw a blue rectangle in sprite so when we move it 1 pixel it does not leave a trail + // on the blue screen background + spr.drawRect(0, 0, WIDTH, HEIGHT, TFT_BLUE); + + int x = tft.width() / 2 - WIDTH / 2; + int y = tft.height() / 2 - HEIGHT / 2; + + uint32_t updateTime = 0; // time for next update + + while (true) + { + // Random movement direction + int dx = 1; if (random(2)) dx = -1; + int dy = 1; if (random(2)) dy = -1; + + // Pull it back onto screen if it wanders off + if (x < -WIDTH/2) dx = 1; + if (x >= tft.width()-WIDTH/2) dx = -1; + if (y < -HEIGHT/2) dy = 1; + if (y >= tft.height()-HEIGHT/2) dy = -1; + + // Draw it 50 time, moving in random direct or staying still + n = 50; + int wait = random (50); + while (n) + { + if (updateTime <= millis()) + { + // Use time delay so sprtie does not move fast when not all on screen + updateTime = millis() + wait; + + // Push the sprite to the TFT screen + spr.pushSprite(x, y); + + // Change coord for next loop + x += dx; + y += dy; + n--; + yield(); // Stop watchdog reset + } + } + } // Infinite while, will not exit! +} + diff --git a/examples/Sprite/Sprite_scroll/Sprite_scroll.ino b/examples/Sprite/Sprite_scroll/Sprite_scroll.ino new file mode 100644 index 0000000..dfe8ad9 --- /dev/null +++ b/examples/Sprite/Sprite_scroll/Sprite_scroll.ino @@ -0,0 +1,118 @@ +/* + Sketch to show scrolling of the graphics in sprites. + Scrolling in this way moves the pixels in a defined rectangle + within the Sprite. By defalt the whole sprite is scrolled. + The gap left by scrolling is filled with a defined colour. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + + An 8 bit Sprite occupies (width * height) bytes in RAM. + +*/ + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1 + +TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1 + +TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2 + +int graphVal = 1; +int delta = 1; +int grid = 0; +int tcount = 0; + +//========================================================================================== +void setup() { + tft.init(); + tft.fillScreen(TFT_BLACK); + + // Create a sprite for the graph + graph1.setColorDepth(8); + graph1.createSprite(128, 61); + graph1.fillSprite(TFT_BLUE); // Note: Sprite is filled with black when created + + // The scroll area is set to the full sprite size upon creation of the sprite + // but we can change that by defining a smaller area using "setScrollRect()"if needed + // parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling + //graph1.setScrollRect(64, 0, 64, 61, TFT_DARKGREY); // Try this line to change the graph scroll area + + // Create a sprite for the scrolling numbers + stext1.setColorDepth(8); + stext1.createSprite(32, 64); + stext1.fillSprite(TFT_BLUE); // Fill sprite with blue + stext1.setScrollRect(0, 0, 32, 64, TFT_BLUE); // here we set scroll gap fill color to blue + stext1.setTextColor(TFT_WHITE); // White text, no background + stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum + + // Create a sprite for Hello World + stext2.setColorDepth(8); + stext2.createSprite(80, 16); + stext2.fillSprite(TFT_DARKGREY); + stext2.setScrollRect(0, 0, 40, 16, TFT_DARKGREY); // Scroll the "Hello" in the first 40 pixels + stext2.setTextColor(TFT_WHITE); // White text, no background +} + +//========================================================================================== +void loop() { + // Draw point in graph1 sprite at far right edge (this will scroll left later) + graph1.drawFastVLine(127,60-graphVal,2,TFT_YELLOW); // draw 2 pixel point on graph + + // Draw number in stext1 sprite at 31,63 (bottom right datum set) + stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2 + + // Push the sprites onto the TFT at specied coordinates + graph1.pushSprite(0, 0); + stext1.pushSprite(0, 64); + stext2.pushSprite(40, 70); + + // Change the value to plot + graphVal+=delta; + + // If the value reaches a limit, then change delta of value + if (graphVal >= 60) delta = -1; // ramp down value + else if (graphVal <= 1) delta = +1; // ramp up value + + delay(50); // wait so things do not scroll too fast + + // Now scroll the sprites scroll(dt, dy) where: + // dx is pixels to scroll, left = negative value, right = positive value + // dy is pixels to scroll, up = negative value, down = positive value + graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down + stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up + stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0 + + // Draw the grid on far right edge of sprite as graph has now moved 1 pixel left + grid++; + if (grid >= 10) + { // Draw a vertical line if we have scrolled 10 times (10 pixels) + grid = 0; + graph1.drawFastVLine(127, 0, 61, TFT_NAVY); // draw line on graph + } + else + { // Otherwise draw points spaced 10 pixels for the horizontal grid lines + for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, TFT_NAVY); + } + + tcount--; + if (tcount <=0) + { // If we have scrolled 40 pixels the redraw text + tcount = 40; + stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2 + } + +} // Loop back and do it all again +//========================================================================================== diff --git a/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino b/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino new file mode 100644 index 0000000..9d2c81b --- /dev/null +++ b/examples/Sprite/Sprite_scroll_16bit/Sprite_scroll_16bit.ino @@ -0,0 +1,194 @@ +/* + Display "flicker free" scrolling text and updating number + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + The sketch has been tested on a 320x240 ILI9341 based TFT, it + coule be adapted for other screen sizes. + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + The Sprite occupies (2 * width * height) bytes. + + On a ESP8266 Sprite sizes up to 128 x 160 can be accomodated, + this size requires 128*160*2 bytes (40kBytes) of RAM, this must be + available or the processor will crash. You need to make the sprite + small enough to fit, with RAM spare for any "local variables" that + may be needed by your sketch and libraries. + + Created by Bodmer 15/11/17 + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Size of sprite image for the scrolling text, this requires ~14 Kbytes of RAM +#define IWIDTH 240 +#define IHEIGHT 30 + +// Pause in milliseconds to set scroll speed +#define WAIT 0 + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object +// // the pointer is used by pushSprite() to push it onto the TFT + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + tft.init(); + tft.setRotation(0); + + tft.fillScreen(TFT_BLUE); +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + + while (1) + { + // Create the sprite and clear background to black + img.createSprite(IWIDTH, IHEIGHT); + //img.fillSprite(TFT_BLACK); // Optional here as we fill the sprite later anyway + + for (int pos = IWIDTH; pos > 0; pos--) + { + build_banner("Hello World", pos); + img.pushSprite(0, 0); + + build_banner("TFT_eSPI sprite" , pos); + img.pushSprite(0, 50); + + delay(WAIT); + } + + // Delete sprite to free up the memory + img.deleteSprite(); + + // Create a sprite of a different size + numberBox(random(100), 60, 100); + + } +} + +// ######################################################################### +// Build the scrolling sprite image from scratch, draw text at x = xpos +// ######################################################################### + +void build_banner(String msg, int xpos) +{ + int h = IHEIGHT; + + // We could just use fillSprite(color) but lets be a bit more creative... + + // Fill with rainbow stripes + while (h--) img.drawFastHLine(0, h, IWIDTH, rainbow(h * 4)); + + // Draw some graphics, the text will apear to scroll over these + img.fillRect (IWIDTH / 2 - 20, IHEIGHT / 2 - 10, 40, 20, TFT_YELLOW); + img.fillCircle(IWIDTH / 2, IHEIGHT / 2, 10, TFT_ORANGE); + + // Now print text on top of the graphics + img.setTextSize(1); // Font size scaling is x1 + img.setTextFont(4); // Font 4 selected + img.setTextColor(TFT_BLACK); // Black text, no background colour + img.setTextWrap(false); // Turn of wrap so we can print past end of sprite + + // Need to print twice so text appears to wrap around at left and right edges + img.setCursor(xpos, 2); // Print text at xpos + img.print(msg); + + img.setCursor(xpos - IWIDTH, 2); // Print text at xpos - sprite width + img.print(msg); +} + +// ######################################################################### +// Create sprite, plot graphics in it, plot to screen, then delete sprite +// ######################################################################### +void numberBox(int num, int x, int y) +{ + // Create a sprite 80 pixels wide, 50 high (8kbytes of RAM needed) + img.createSprite(80, 50); + + // Fill it with black + img.fillSprite(TFT_BLACK); + + // Draw a backgorund of 2 filled triangles + img.fillTriangle( 0, 0, 0, 49, 40, 25, TFT_RED); + img.fillTriangle( 79, 0, 79, 49, 40, 25, TFT_DARKGREEN); + + // Set the font parameters + img.setTextSize(1); // Font size scaling is x1 + img.setFreeFont(&FreeSerifBoldItalic24pt7b); // Select free font + img.setTextColor(TFT_WHITE); // White text, no background colour + + // Set text coordinate datum to middle centre + img.setTextDatum(MC_DATUM); + + // Draw the number in middle of 80 x 50 sprite + img.drawNumber(num, 40, 25); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + img.pushSprite(x, y); + + // Delete sprite to free up the RAM + img.deleteSprite(); +} + + +// ######################################################################### +// Return a 16 bit rainbow colour +// ######################################################################### +unsigned int rainbow(byte value) +{ + // Value is expected to be in range 0-127 + // The value is converted to a spectrum colour from 0 = red through to 127 = blue + + byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte green = 0;// Green is the middle 6 bits + byte blue = 0; // Blue is the bottom 5 bits + + byte sector = value >> 5; + byte amplit = value & 0x1F; + + switch (sector) + { + case 0: + red = 0x1F; + green = amplit; + blue = 0; + break; + case 1: + red = 0x1F - amplit; + green = 0x1F; + blue = 0; + break; + case 2: + red = 0; + green = 0x1F; + blue = amplit; + break; + case 3: + red = 0; + green = 0x1F - amplit; + blue = 0x1F; + break; + } + + return red << 11 | green << 6 | blue; +} + + diff --git a/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino new file mode 100644 index 0000000..ab4a53e --- /dev/null +++ b/examples/Sprite/Sprite_scroll_1bit/Sprite_scroll_1bit.ino @@ -0,0 +1,147 @@ +/* + Sketch to show scrolling of the graphics in sprites. + + This sketch scrolls a 1 bit per pixel (1 bpp) Sprite. + + In a 1 bit Sprite any colour except TFT_BLACK turns a pixel "ON" + TFT_BLACK turns a pixel "OFF". + + The 1 bpp Sprite has a unique property that other bit depth Sprites + do not have, you can set the rotation of the coordinate frame e.g.: + spr.setRotation(1); + + This is similar to screen rotations, so for example text can + be drawn rotated: + Rotation 0: Normal orientation + Rotation 1: Coordinate frame rotated clockwise 90 degrees + Rotation 2: Coordinate frame rotated clockwise 180 degrees (upside down) + Rotation 3: Coordinate frame rotated clockwise 270 degrees + + When pushSprite is used the sprite is drawn with the width and height + staying as created, so the created Sprite itself is not rotated during + rendering. See stext2 sprite example below at line 83. + + ON and OFF pixels can be set to any two colours before + rendering to the screen with pushSprite, for example: + tft.setBitmapColor(ON_COLOR, OFF_COLOR); + + Scrolling moves the pixels in a defined rectangle within + the Sprite. By defalt the whole sprite is scrolled. + The gap left by scrolling is filled with a defined colour. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 1 bit Sprite occupies (width * height)/8 bytes in RAM. + +*/ + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1 + +TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1 + +TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2 + +int graphVal = 1; +int delta = 1; +int grid = 0; +int tcount = 0; + +//========================================================================================== +void setup() { + tft.init(); + tft.fillScreen(TFT_BLACK); + + // Create a sprite for the graph + graph1.setColorDepth(1); + graph1.createSprite(128, 61); + graph1.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // The scroll area is set to the full sprite size upon creation of the sprite + // but we can change that by defining a smaller area using "setScrollRect()"if needed + // parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling + //graph1.setScrollRect(64, 0, 64, 61, TFT_BLACK); // Try this line to change the graph scroll area + + // Create a sprite for the scrolling numbers + stext1.setColorDepth(1); + stext1.createSprite(32, 64); + stext1.fillSprite(TFT_BLACK); // Fill sprite with blue + stext1.setScrollRect(0, 0, 32, 64, TFT_BLACK); // here we set scroll gap fill color to blue + stext1.setTextColor(TFT_WHITE); // White text, no background + stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum + + // Create a sprite for Hello World + stext2.setColorDepth(1); + stext2.createSprite(16, 80); // Narrow and tall + stext2.setRotation(1); // Plot with 90 deg. clockwise rotation + stext2.fillSprite(TFT_BLACK); + stext2.setScrollRect(0, 0, 40, 16, TFT_BLACK); // Scroll the "Hello" in the first 40 pixels + stext2.setTextColor(TFT_WHITE); // White text, no background +} + +//========================================================================================== +void loop() { + // Draw point in graph1 sprite at far right edge (this will scroll left later) + graph1.drawFastVLine(127,60-graphVal,2,TFT_WHITE); // draw 2 pixel point on graph + + // Draw number in stext1 sprite at 31,63 (bottom right datum set) + stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2 + + // Push the sprites onto the TFT at specied coordinates + tft.setBitmapColor(TFT_WHITE, TFT_BLUE); // Specify the colours of the ON and OFF pixels + graph1.pushSprite(0, 0); + + tft.setBitmapColor(TFT_GREEN, TFT_BLACK); + stext1.pushSprite(0, 64); + + tft.setBitmapColor(TFT_BLACK, TFT_YELLOW); + stext2.pushSprite(60, 70); + + // Change the value to plot + graphVal+=delta; + + // If the value reaches a limit, then change delta of value + if (graphVal >= 60) delta = -1; // ramp down value + else if (graphVal <= 1) delta = +1; // ramp up value + + delay(50); // wait so things do not scroll too fast + + // Now scroll the sprites scroll(dt, dy) where: + // dx is pixels to scroll, left = negative value, right = positive value + // dy is pixels to scroll, up = negative value, down = positive value + graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down + stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up + stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0 + + // Draw the grid on far right edge of sprite as graph has now moved 1 pixel left + grid++; + if (grid >= 10) + { // Draw a vertical line if we have scrolled 10 times (10 pixels) + grid = 0; + graph1.drawFastVLine(127, 0, 61, TFT_WHITE); // draw line on graph + } + else + { // Otherwise draw points spaced 10 pixels for the horizontal grid lines + for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, TFT_WHITE); + } + + tcount--; + if (tcount <=0) + { // If we have scrolled 40 pixels the redraw text + tcount = 40; + stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2 + } + +} // Loop back and do it all again +//========================================================================================== diff --git a/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino b/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino new file mode 100644 index 0000000..beca732 --- /dev/null +++ b/examples/Sprite/Sprite_scroll_8bit/Sprite_scroll_8bit.ino @@ -0,0 +1,205 @@ +/* + Display "flicker free" scrolling text and updating number + + This sketch uses 8 bit colour sprites to save RAM. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + The sketch has been tested on a 320x240 ILI9341 based TFT, it + coule be adapted for other screen sizes. + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 16 bit colour Sprite occupies (2 * width * height) bytes. + + An 8 bit colour Sprite occupies (width * height) bytes. + + On a ESP8266, 16 bit Sprite sizes up to 128 x 160 can be accomodated, + this size requires 128*160*2 bytes (40kBytes) of RAM. + + This sketch sets the colour depth to 8 bits so larger sprites can be + created. 8 bit colour sprites use half amount of RAM. If the colour + depth is not specified then 16 bits is assumed. + + You need to make the sprite small enough to fit, with RAM spare for + any "local variables" that may be needed by your sketch and libraries. + + Created by Bodmer 21/11/17 + + ######################################################################### + ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### + ######################################################################### +*/ + +// Size of sprite image for the scrolling text, this requires ~14 Kbytes of RAM +#define IWIDTH 240 +#define IHEIGHT 30 + +// Pause in milliseconds to set scroll speed +#define WAIT 0 + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object +// // the pointer is used by pushSprite() to push it onto the TFT + +// ------------------------------------------------------------------------- +// Setup +// ------------------------------------------------------------------------- +void setup(void) { + tft.init(); + tft.setRotation(0); + + tft.fillScreen(TFT_BLUE); +} + +// ------------------------------------------------------------------------- +// Main loop +// ------------------------------------------------------------------------- +void loop() { + + while (1) + { + // Set colour depth of Sprite to 8 (or 16) bits + img.setColorDepth(8); + + // Create the sprite and clear background to black + img.createSprite(IWIDTH, IHEIGHT); + //img.fillSprite(TFT_BLACK); // Optional here as we fill the sprite later anyway + + for (int pos = IWIDTH; pos > 0; pos--) + { + build_banner("Hello World", pos); + img.pushSprite(0, 0); + + build_banner("TFT_eSPI sprite" , pos); + img.pushSprite(0, 50); + + delay(WAIT); + } + + // Delete sprite to free up the memory + img.deleteSprite(); + + // Create a sprite of a different size + numberBox(random(100), 60, 100); + + } +} + +// ######################################################################### +// Build the scrolling sprite image from scratch, draw text at x = xpos +// ######################################################################### + +void build_banner(String msg, int xpos) +{ + int h = IHEIGHT; + + // We could just use fillSprite(color) but lets be a bit more creative... + + // Fill with rainbow stripes + while (h--) img.drawFastHLine(0, h, IWIDTH, rainbow(h * 4)); + + // Draw some graphics, the text will apear to scroll over these + img.fillRect (IWIDTH / 2 - 20, IHEIGHT / 2 - 10, 40, 20, TFT_YELLOW); + img.fillCircle(IWIDTH / 2, IHEIGHT / 2, 10, TFT_ORANGE); + + // Now print text on top of the graphics + img.setTextSize(1); // Font size scaling is x1 + img.setTextFont(4); // Font 4 selected + img.setTextColor(TFT_BLACK); // Black text, no background colour + img.setTextWrap(false); // Turn of wrap so we can print past end of sprite + + // Need to print twice so text appears to wrap around at left and right edges + img.setCursor(xpos, 2); // Print text at xpos + img.print(msg); + + img.setCursor(xpos - IWIDTH, 2); // Print text at xpos - sprite width + img.print(msg); +} + +// ######################################################################### +// Create sprite, plot graphics in it, plot to screen, then delete sprite +// ######################################################################### +void numberBox(int num, int x, int y) +{ + // Create a sprite 80 pixels wide, 50 high (8kbytes of RAM needed) + img.createSprite(80, 50); + + // Fill it with black + img.fillSprite(TFT_BLACK); + + // Draw a backgorund of 2 filled triangles + img.fillTriangle( 0, 0, 0, 49, 40, 25, TFT_RED); + img.fillTriangle( 79, 0, 79, 49, 40, 25, TFT_DARKGREEN); + + // Set the font parameters + img.setTextSize(1); // Font size scaling is x1 + img.setFreeFont(&FreeSerifBoldItalic24pt7b); // Select free font + img.setTextColor(TFT_WHITE); // White text, no background colour + + // Set text coordinate datum to middle centre + img.setTextDatum(MC_DATUM); + + // Draw the number in middle of 80 x 50 sprite + img.drawNumber(num, 40, 25); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + img.pushSprite(x, y); + + // Delete sprite to free up the RAM + img.deleteSprite(); +} + + +// ######################################################################### +// Return a 16 bit rainbow colour +// ######################################################################### +unsigned int rainbow(byte value) +{ + // Value is expected to be in range 0-127 + // The value is converted to a spectrum colour from 0 = red through to 127 = blue + + byte red = 0; // Red is the top 5 bits of a 16 bit colour value + byte green = 0;// Green is the middle 6 bits + byte blue = 0; // Blue is the bottom 5 bits + + byte sector = value >> 5; + byte amplit = value & 0x1F; + + switch (sector) + { + case 0: + red = 0x1F; + green = amplit; + blue = 0; + break; + case 1: + red = 0x1F - amplit; + green = 0x1F; + blue = 0; + break; + case 2: + red = 0; + green = 0x1F; + blue = amplit; + break; + case 3: + red = 0; + green = 0x1F - amplit; + blue = 0x1F; + break; + } + + return red << 11 | green << 6 | blue; +} + + diff --git a/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino new file mode 100644 index 0000000..76fcfc6 --- /dev/null +++ b/examples/Sprite/Sprite_scroll_wrap_1bit/Sprite_scroll_wrap_1bit.ino @@ -0,0 +1,139 @@ +// This **ONLY** works for 1 bpp Sprites due to lack of bounds checking in the +// Sprite pushImage() function for 8 and 16 bit Sprites (it is on the TO DO list) + +// Wrapping scroll example by Bodmer for the TFT_eSPI library + +//========================================================================================== + +#include + +TFT_eSPI tft = TFT_eSPI(); + +TFT_eSprite gfx = TFT_eSprite(&tft); // Sprite object for graphics write + +TFT_eSprite fb = TFT_eSprite(&tft); // Sprite object for frame buffer + +// Width and height of the Sprite +#define WIDTH 60 +#define HEIGHT 60 + +// Define scroll increment in x and y directions +// positive numbers = right, down +// negative numbers = left, up +#define XDELTA 1 +#define YDELTA 1 + +int16_t scroll_x = 0; // Keep track of the scrolled position, this is where the origin +int16_t scroll_y = 0; // (top left) of the gfx Sprite will be + +int16_t radius = 5; // radius of circle + +bool grow = true; // grow or shrink circle + +uint16_t *gfxPtr; // Pointer to start of graphics sprite memory area + +//========================================================================================== +//========================================================================================== + +void setup() { + Serial.begin(115200); + tft.init(); + tft.fillScreen(TFT_BLACK); + + tft.setRotation(1); + + //tft.invertDisplay(true); + + // Create a sprite for the graphics + gfx.setColorDepth(1); + gfxPtr = (uint16_t*) gfx.createSprite(WIDTH, HEIGHT); // 450 bytes needed + gfx.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // Create a sprite for the frame buffer + fb.setColorDepth(1); + fb.createSprite(WIDTH, HEIGHT); // 450 bytes needed + fb.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created + + // Text colour and alignment in graphics Sprite + gfx.setTextColor(TFT_WHITE, TFT_BLACK); + gfx.setTextDatum(MC_DATUM); + + // Text colour and alignment in frame buffer + fb.setTextColor(TFT_WHITE, TFT_BLACK); + fb.setTextDatum(MC_DATUM); + + // Next 3 lines are for test only to see what we have drawn + drawGraphics(); // draw the graphics in the gfx sprite and copy to buffer + gfx.pushSprite(0, 0); // Plot to screen so we see what it looks like + delay(2000); +} + +//========================================================================================== +//========================================================================================== + +void loop() { +uint32_t tnow = millis(); + drawGraphics(); // Not needed if scrolling graphics are static + + wrappingScroll(XDELTA, YDELTA); + + // Plot two copies without "Hello", then one in the middle with "Hello" + //fb.setBitmapColor(TFT_WHITE, TFT_RED ); + fb.pushSprite(0, 0); // Plot frame buffer onto the TFT screen + //fb.setBitmapColor(TFT_WHITE, TFT_BLUE ); + fb.pushSprite(120, 0); // Plot frame buffer onto the TFT screen + + fb.drawString("Hello", 30, 20, 2); // Plot hello in frame buffer + //fb.setBitmapColor(TFT_BLACK, TFT_GREEN); + fb.pushSprite(60, 0); // Plot frame buffer in middle of other two + + //Serial.println(millis() - tnow); + delay(20); +} + +//========================================================================================== +// Draw graphics in the master Sprite +//========================================================================================== + +void drawGraphics(void) +{ + gfx.fillSprite(TFT_BLACK); // Clear sprite each time and completely redraw + + //gfx.drawRect(0,0,60,60,TFT_WHITE); // Test to check alignment + + gfx.drawCircle( 30 , 30, radius, TFT_WHITE); + if (grow) radius++; + else radius--; + + if ( radius > 25 ) grow = false; + if ( radius < 1 ) grow = true; + + gfx.drawString("World", 30, 40, 2); // Plot hello in frame buffer +} + +//========================================================================================== +// This function scrolls and wraps the graphic in a 1 bit per pixel Sprite, dy and dy +// control the scroll direction. Pixels that scroll off one side appear on the other. +// Scrolling is achieved by plotting one Sprite inside another with an offset. This has +// to be done by plotting 4 times into a second frame buffer Sprite. +//========================================================================================== +void wrappingScroll(int16_t dx, int16_t dy) +{ + // Position the quadrants so they overlap all areas of the buffer + scroll_x += dx; + if (scroll_x < -WIDTH) scroll_x += WIDTH; + if (scroll_x > 0) scroll_x -= WIDTH; + + scroll_y += dy; + if (scroll_y < -HEIGHT) scroll_y += HEIGHT; + if (scroll_y > 0) scroll_y -= HEIGHT; + + // push the 4 quadrants of gfx. sprite into the fb. sprite + // pushImage will do the cropping + fb.pushImage(scroll_x, scroll_y, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x + WIDTH, scroll_y, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr); + fb.pushImage(scroll_x + WIDTH, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr); +} + +//========================================================================================== diff --git a/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino b/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino new file mode 100644 index 0000000..c8039e7 --- /dev/null +++ b/examples/Sprite/Transparent_Sprite_Demo/Transparent_Sprite_Demo.ino @@ -0,0 +1,144 @@ +/* + Sketch to show creation of a sprite with a transparent + background, then plot it on the TFT. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 16 bit Sprite occupies (2 * width * height) bytes in RAM. + + On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, + this size requires 40kBytes of RAM for a 16 bit colour depth. + + When 8 bit colour depth sprites are created they occupy + (width * height) bytes in RAM, so larger sprites can be + created, or the RAM required is halved. +*/ + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object + // the pointer is used by pushSprite() to push it onto the TFT + +void setup(void) { + Serial.begin(250000); + + tft.init(); + + tft.setRotation(0); +} + +void loop() { + + tft.fillScreen(TFT_NAVY); + + // Draw 10 sprites containing a "transparent" colour + for (int i = 0; i < 10; i++) + { + int x = random(240-70); + int y = random(320-80); + int c = random(0x10000); // Random colour + drawStar(x, y, c); + } + + delay(2000); + + uint32_t dt = millis(); + + // Now go bananas and draw 500 nore + for (int i = 0; i < 500; i++) + { + int x = random(240-70); + int y = random(320-80); + int c = random(0x10000); // Random colour + drawStar(x, y, c); + yield(); // Stop watchdog reset + } + + // Show time in milliseconds to draw and then push 1 sprite to TFT screen + numberBox( 10, 10, (millis()-dt)/500.0 ); + + delay(2000); + +} + +// ######################################################################### +// Create sprite, plot graphics in it, plot to screen, then delete sprite +// ######################################################################### +void drawStar(int x, int y, int star_color) +{ + // Create an 8 bit sprite 70x 80 pixels (uses 5600 bytes of RAM) + img.setColorDepth(8); + img.createSprite(70, 80); + + // Fill Sprite with a "transparent" colour + // TFT_TRANSPARENT is already defined for convenience + // We could also fill with any colour as "transparent" and later specify that + // same colour when we push the Sprite onto the screen. + img.fillSprite(TFT_TRANSPARENT); + + // Draw 2 triangles to create a filled in star + img.fillTriangle(35, 0, 0,59, 69,59, star_color); + img.fillTriangle(35,79, 0,20, 69,20, star_color); + + // Punch a star shaped hole in the middle with a smaller transparent star + img.fillTriangle(35, 7, 6,56, 63,56, TFT_TRANSPARENT); + img.fillTriangle(35,73, 6,24, 63,24, TFT_TRANSPARENT); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // Specify what colour is to be treated as transparent. + img.pushSprite(x, y, TFT_TRANSPARENT); + + // Delete it to free memory + img.deleteSprite(); + +} + +// ######################################################################### +// Draw a number in a rounded rectangle with some transparent pixels +// ######################################################################### +void numberBox(int x, int y, float num ) +{ + + // Size of sprite + #define IWIDTH 80 + #define IHEIGHT 35 + + // Create a 8 bit sprite 80 pixels wide, 35 high (2800 bytes of RAM needed) + img.setColorDepth(8); + img.createSprite(IWIDTH, IHEIGHT); + + // Fill it with black (this will be the transparent colour this time) + img.fillSprite(TFT_BLACK); + + // Draw a background for the numbers + img.fillRoundRect( 0, 0, 80, 35, 15, TFT_RED); + img.drawRoundRect( 0, 0, 80, 35, 15, TFT_WHITE); + + // Set the font parameters + img.setTextSize(1); // Font size scaling is x1 + img.setTextColor(TFT_WHITE); // White text, no background colour + + // Set text coordinate datum to middle right + img.setTextDatum(MR_DATUM); + + // Draw the number to 3 decimal places at 70,20 in font 4 + img.drawFloat(num, 3, 70, 20, 4); + + // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) + // All black pixels will not be drawn hence will show as "transparent" + img.pushSprite(x, y, TFT_BLACK); + + // Delete sprite to free up the RAM + img.deleteSprite(); +} + diff --git a/examples/Test and diagnostics/Colour_Test/Colour_Test.ino b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino new file mode 100644 index 0000000..ed7a061 --- /dev/null +++ b/examples/Test and diagnostics/Colour_Test/Colour_Test.ino @@ -0,0 +1,132 @@ + +// Diagnostic test for the displayed colour order +// +// Writen by Bodmer 17/2/19 for the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +/* + Different hardware manufacturers use different colour order + configurations at the hardware level. This may result in + incorrect colours being displayed. + + Incorrectly displayed colours could also be the result of + using the wrong display driver in the library setup file. + + Typically displays have a control register (MADCTL) that can + be used to set the Red Green Blue (RGB) colour order to RGB + or BRG so that red and blue are swapped on the display. + + This control register is also used to manage the display + rotation and coordinate mirroring. The control register + typically has 8 bits, for the ILI9341 these are: + + Bit Function + 7 Mirror Y coordinate (row address order) + 6 Mirror X coordinate (column address order) + 5 Row/column exchange (for rotation) + 4 Refresh direction (top to bottom or bottom to top in portrait orientation) + 3 RGB order (swaps red and blue) + 2 Refresh direction (top to bottom or bottom to top in landscape orientation) + 1 Not used + 0 Not used + + The control register bits can be written with this example command sequence: + + tft.writecommand(TFT_MADCTL); + tft.writedata(0x48); // Bits 6 and 3 set + + 0x48 is the default value for ILI9341 (0xA8 for ESP32 M5STACK) + in rotation 0 orientation. + + Another control register can be used to "invert" colours, + this swaps black and white as well as other colours (e.g. + green to magenta, red to cyan, blue to yellow). + + To invert colours insert this line after tft.init() or tft.begin(): + + tft.invertDisplay( invert ); // Where invert is true or false + +*/ + +#include + +#include // Hardware-specific library + +TFT_eSPI tft = TFT_eSPI(); // Invoke custom library + +void setup(void) { + tft.init(); + + tft.fillScreen(TFT_BLACK); + + // Set "cursor" at top left corner of display (0,0) and select font 4 + tft.setCursor(0, 0, 4); + + // Set the font colour to be white with a black background + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + // We can now plot text on screen using the "print" class + tft.println("Intialised default\n"); + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(5000); + +} + +void loop() { + + tft.invertDisplay( false ); // Where i is true or false + + tft.fillScreen(TFT_BLACK); + + tft.setCursor(0, 0, 4); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Invert OFF\n"); + + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(5000); + + + // Binary inversion of colours + tft.invertDisplay( true ); // Where i is true or false + + tft.fillScreen(TFT_BLACK); + + tft.setCursor(0, 0, 4); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.println("Invert ON\n"); + + tft.println("White text"); + + tft.setTextColor(TFT_RED, TFT_BLACK); + tft.println("Red text"); + + tft.setTextColor(TFT_GREEN, TFT_BLACK); + tft.println("Green text"); + + tft.setTextColor(TFT_BLUE, TFT_BLACK); + tft.println("Blue text"); + + delay(5000); +} diff --git a/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino new file mode 100644 index 0000000..6485568 --- /dev/null +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -0,0 +1,155 @@ +/* + This sketch reads the user setup information from the processor via the Serial Port + + It is a support and diagnostic sketch for the TFT_eSPI library: + https://github.com/Bodmer/TFT_eSPI + + The output is essentially a copy of the User_Setep configuration so can be used to + verify the correct settings are being picked up by the compiler. + + If support is needed the output can be cut and pasted into an Arduino Forum post and + already includes the formatting [code]...[/code] markups. + + Written by Bodmer 9/4/18 +*/ + +#include +#include // Graphics library + +TFT_eSPI tft = TFT_eSPI(); // Invoke library + +#ifdef ESP8266 + ADC_MODE(ADC_VCC); // Read the supply voltage +#endif + +setup_t user; // The library defines the type "setup_t" as a struct + // Calling tft.getSetup(user) populates it with the settings +//------------------------------------------------------------------------------------------ + +void setup() { + // Use serial port + Serial.begin(115200); + + // Initialise the TFT screen + tft.init(); +} + +//------------------------------------------------------------------------------------------ + +void loop(void) { + +tft.getSetup(user); // + +Serial.printf("\n[code]\n"); + +Serial.print ("TFT_eSPI ver = " + user.version + "\n"); +Serial.printf("Processor = ESP%i\n", user.esp, HEX); +Serial.printf("Frequency = %i MHz\n", ESP.getCpuFreqMHz()); +#ifdef ESP8266 +Serial.printf("Voltage = %2.2f V\n", ESP.getVcc() / 918.0); // 918 empirically determined +#endif +Serial.printf("Transactions = %s \n", (user.trans == 1) ? "Yes" : "No"); +Serial.printf("Interface = %s \n", (user.serial == 1) ? "SPI" : "Parallel"); +#ifdef ESP8266 +if (user.serial == 1) +Serial.printf("SPI overlap = %s \n\n", (user.overlap == 1) ? "Yes" : "No"); +#endif +if (user.tft_driver != 0xE9D) // For ePaper displays the size is defined in the sketch +{ + Serial.printf("Display driver = "); Serial.println(user.tft_driver, HEX); // Hexadecimal code + Serial.printf("Display width = %i \n", user.tft_width); // Rotation 0 width and height + Serial.printf("Display height = %i \n\n", user.tft_height); +} +else if (user.tft_driver == 0xE9D) Serial.printf("Display driver = ePaper\n\n"); + +if (user.r0_x_offset != 0) Serial.printf("R0 x offset = %i \n", user.r0_x_offset); // Offsets, not all used yet +if (user.r0_y_offset != 0) Serial.printf("R0 y offset = %i \n", user.r0_y_offset); +if (user.r1_x_offset != 0) Serial.printf("R1 x offset = %i \n", user.r1_x_offset); +if (user.r1_y_offset != 0) Serial.printf("R1 y offset = %i \n", user.r1_y_offset); +if (user.r2_x_offset != 0) Serial.printf("R2 x offset = %i \n", user.r2_x_offset); +if (user.r2_y_offset != 0) Serial.printf("R2 y offset = %i \n", user.r2_y_offset); +if (user.r3_x_offset != 0) Serial.printf("R3 x offset = %i \n", user.r3_x_offset); +if (user.r3_y_offset != 0) Serial.printf("R3 y offset = %i \n\n", user.r3_y_offset); + +if (user.pin_tft_mosi != -1) Serial.printf("MOSI = D%i (GPIO %i)\n", getPinName(user.pin_tft_mosi), user.pin_tft_mosi); +if (user.pin_tft_miso != -1) Serial.printf("MISO = D%i (GPIO %i)\n", getPinName(user.pin_tft_miso), user.pin_tft_miso); +if (user.pin_tft_clk != -1) Serial.printf("SCK = D%i (GPIO %i)\n", getPinName(user.pin_tft_clk), user.pin_tft_clk); + +#ifdef ESP8266 +if (user.overlap == true) +{ + Serial.printf("Overlap selected, following pins MUST be used:\n"); + + Serial.printf("MOSI = SD1 (GPIO 8)\n"); + Serial.printf("MISO = SD0 (GPIO 7)\n"); + Serial.printf("SCK = CLK (GPIO 6)\n"); + Serial.printf("TFT_CS = D3 (GPIO 0)\n\n"); + + Serial.printf("TFT_DC and TFT_RST pins can be user defined\n"); +} +#endif +if (user.pin_tft_cs != -1) Serial.printf("TFT_CS = D%i (GPIO %i)\n", getPinName(user.pin_tft_cs), user.pin_tft_cs); +if (user.pin_tft_dc != -1) Serial.printf("TFT_DC = D%i (GPIO %i)\n", getPinName(user.pin_tft_dc), user.pin_tft_dc); +if (user.pin_tft_rst != -1) Serial.printf("TFT_RST = D%i (GPIO %i)\n\n", getPinName(user.pin_tft_rst), user.pin_tft_rst); + +if (user.pin_tch_cs != -1) Serial.printf("TOUCH_CS = D%i (GPIO %i)\n\n", getPinName(user.pin_tch_cs), user.pin_tch_cs); + +if (user.pin_tft_wr != -1) Serial.printf("TFT_WR = D%i (GPIO %i)\n", getPinName(user.pin_tft_wr), user.pin_tft_wr); +if (user.pin_tft_rd != -1) Serial.printf("TFT_RD = D%i (GPIO %i)\n\n", getPinName(user.pin_tft_rd), user.pin_tft_rd); + +if (user.pin_tft_d0 != -1) Serial.printf("TFT_D0 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d0), user.pin_tft_d0); +if (user.pin_tft_d1 != -1) Serial.printf("TFT_D1 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d1), user.pin_tft_d1); +if (user.pin_tft_d2 != -1) Serial.printf("TFT_D2 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d2), user.pin_tft_d2); +if (user.pin_tft_d3 != -1) Serial.printf("TFT_D3 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d3), user.pin_tft_d3); +if (user.pin_tft_d4 != -1) Serial.printf("TFT_D4 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d4), user.pin_tft_d4); +if (user.pin_tft_d5 != -1) Serial.printf("TFT_D5 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d5), user.pin_tft_d5); +if (user.pin_tft_d6 != -1) Serial.printf("TFT_D6 = D%i (GPIO %i)\n", getPinName(user.pin_tft_d6), user.pin_tft_d6); +if (user.pin_tft_d7 != -1) Serial.printf("TFT_D7 = D%i (GPIO %i)\n\n", getPinName(user.pin_tft_d7), user.pin_tft_d7); + +uint16_t fonts = tft.fontsLoaded(); +if (fonts & (1 << 1)) Serial.printf("Font GLCD loaded\n"); +if (fonts & (1 << 2)) Serial.printf("Font 2 loaded\n"); +if (fonts & (1 << 4)) Serial.printf("Font 4 loaded\n"); +if (fonts & (1 << 6)) Serial.printf("Font 6 loaded\n"); +if (fonts & (1 << 7)) Serial.printf("Font 7 loaded\n"); +if (fonts & (1 << 9)) Serial.printf("Font 8N loaded\n"); +else +if (fonts & (1 << 8)) Serial.printf("Font 8 loaded\n"); +if (fonts & (1 << 15)) Serial.printf("Smooth font enabled\n"); +Serial.printf("\n"); + +if (user.serial==1) Serial.printf("Display SPI frequency = %2.1f MHz \n", user.tft_spi_freq/10.0); +if (user.pin_tch_cs != -1) Serial.printf("Touch SPI frequency = %2.1f MHz \n", user.tch_spi_freq/10.0); + +Serial.printf("[/code]\n"); + +while(1) yield(); + +} + +// Get pin name for ESP8266 +int8_t getPinName(int8_t pin) +{ + // For ESP32 pin labels on boards use the GPIO number + if (user.esp == 32) return pin; + + // For ESP8266 the pin labels are not the same as the GPIO number + // These are for the NodeMCU pin definitions: + // GPIO Dxx + if (pin == 16) return 0; + if (pin == 5) return 1; + if (pin == 4) return 2; + if (pin == 0) return 3; + if (pin == 2) return 4; + if (pin == 14) return 5; + if (pin == 12) return 6; + if (pin == 13) return 7; + if (pin == 15) return 8; + if (pin == 3) return 9; + if (pin == 1) return 10; + if (pin == 9) return 11; + if (pin == 10) return 12; + + return -1; // Invalid pin +} + diff --git a/examples/Test and diagnostics/Test_Touch_Controller/Test_Touch_Controller.ino b/examples/Test and diagnostics/Test_Touch_Controller/Test_Touch_Controller.ino new file mode 100644 index 0000000..6c1e887 --- /dev/null +++ b/examples/Test and diagnostics/Test_Touch_Controller/Test_Touch_Controller.ino @@ -0,0 +1,49 @@ +// This sketch is to test the touch controller, nothing is displayed +// on the TFT. The TFT_eSPI library must be configured to suit your +// pins used. Make sure both the touch chip select and the TFT chip +// select are correctly defined to avoid SPI bus contention. + +// Make sure you have defined a pin for the touch controller chip +// select line in the user setup file or you will see "no member" +// compile errors for the touch functions! + +// It is a support and diagnostic sketch for the TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI + +// The "raw" (unprocessed) touch sensor outputs are sent to the +// serial port. Touching the screen should show changes to the x, y +// and z values. x and y are raw ADC readings, not pixel coordinates. + +#include +#include +TFT_eSPI tft = TFT_eSPI(); + +//==================================================================== + +void setup(void) { + Serial.begin(115200); + Serial.println("\n\nStarting..."); + + tft.init(); +} + +//==================================================================== + +void loop() { + + uint16_t x, y; + + tft.getTouchRaw(&x, &y); + + Serial.printf("x: %i ", x); + + Serial.printf("y: %i ", y); + + Serial.printf("z: %i \n", tft.getTouchRawZ()); + + delay(250); + +} + +//==================================================================== + diff --git a/examples/ePaper/Floyd_Steinberg/EPD_Support.h b/examples/ePaper/Floyd_Steinberg/EPD_Support.h new file mode 100644 index 0000000..ce3ce1d --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/EPD_Support.h @@ -0,0 +1,105 @@ +/* Support definitions and functions for ePaper examples + * These tailor the library and screen settings + * Must be a header file to ensure #defines are established first + * + * Created by Bodmer 30/3/18 for TFT_eSPI library: + * https://github.com/Bodmer/TFT_eSPI + */ + +/* + EPD_WIDTH and EPD_HEIGHT are automatically defined here based on the library selected + + For 2 colour ePaper displays create one frame pointer in sketch: + uint8_t* framePtr; + + For 3 colour ePaper displays create two frame pointers in sketch: + uint8_t* blackFramePtr; + uint8_t* redFramePtr; + + Call this function to update whole display: + updateDisplay(); +*/ +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + + +//------------------------------------------------------------------------------------ +// Define which colour values are paper and ink +//------------------------------------------------------------------------------------ +#if defined (EPD2IN7B_H) + #define COLORED 1 // EPD2IN7B is opposite to all others! + #define UNCOLORED 0 +#else + #define COLORED 0 + #define UNCOLORED 1 +#endif + + +//------------------------------------------------------------------------------------ +// Define the width and height of the different displays +//------------------------------------------------------------------------------------ +#if defined (EPD1IN54_H) || defined (EPD1IN54B_H) + #define EPD_WIDTH 200 // Frame buffer is 5000 bytes + #define EPD_HEIGHT 200 + +#elif defined (EPD1IN54C_H) + #define EPD_WIDTH 152 // 2 frame buffers of 2888 bytes each + #define EPD_HEIGHT 152 + +#elif defined (EPD2IN7_H) || defined (EPD2IN7B_H) + #define EPD_WIDTH 176 // Frame buffer is 5808 bytes + #define EPD_HEIGHT 264 + +#elif defined (EPD2IN9_H) || defined (EPD2IN9B_H) + #define EPD_WIDTH 128 // Frame buffer is 4736 bytes + #define EPD_HEIGHT 296 + +#elif defined (EPD2IN13_H) + #define EPD_WIDTH 122 // Frame buffer is 4000 bytes + #define EPD_HEIGHT 250 + +#elif defined (EPD2IN13B_H) + #define EPD_WIDTH 104 // 2 frame buffers of 2756 bytes each + #define EPD_HEIGHT 212 + +#elif defined (EPD4IN2_H) + #define EPD_WIDTH 400 // Frame buffer is 15000 bytes + #define EPD_HEIGHT 300 + +// ESP8266 has just enough RAM for a 2 color 7.5" display full screen buffer +// ESP32 has just enough RAM for 2 or 3 color 7.5" display +// (Without using partial screen updates) +#elif defined (EPD7IN5_H) || defined (EPD7IN5B_H) + #define EPD_WIDTH 640 // 2 colour frame buffer is 30720 bytes + #define EPD_HEIGHT 384 // 2 colour frame buffer is 61440 bytes + +#else + # error "Selected ePaper library is not supported" + +#endif + + +//------------------------------------------------------------------------------------ +// Update display - different displays have different function names in the default +// Waveshare libraries :-( +//------------------------------------------------------------------------------------ +#if defined (EPD1IN54B_H) || defined(EPD1IN54C_H) || defined(EPD2IN13B_H) || defined(EPD2IN7B_H) || defined(EPD2IN9B_H) || defined(EPD4IN2_H) + void updateDisplay(uint8_t* blackFrame = blackFramePtr, uint8_t* redFrame = redFramePtr) + { + ePaper.DisplayFrame(blackFrame, redFrame); // Update 3 colour display +#else + void updateDisplay(uint8_t* blackFrame = framePtr) + { + #if defined (EPD2IN7_H) || defined(EPD4IN2_H) + ePaper.DisplayFrame(blackFrame); // Update 2 color display + + #elif defined (EPD1IN54_H) || defined(EPD2IN13_H) || defined(EPD2IN9_H) + ePaper.SetFrameMemory(blackFrame); // Update 2 colour display + + #else + # error "Selected ePaper library is not supported" + #endif +#endif +} + diff --git a/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino new file mode 100644 index 0000000..1245a8d --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg.ino @@ -0,0 +1,187 @@ +// Display grey-scale images on a Monchrome ePaper display using +// Floyd-Steinberg dithering +// https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering + +// Example created by Bodmer 31/3/18 for TFT_eSPI library: +// https://github.com/Bodmer/TFT_eSPI +// Select the ePaper setup in library's "User_Setup_Select.h" file + +// This sketch supports Waveshare 2 colour ePaper displays +// https://www.waveshare.com/product/modules/oleds-lcds/e-paper.htm + +// Test images are in the Data folder with sketch (press Ctrl+k) +// Upload using the Tools menu "ESP8266 Sketch Data Upload" option + +/////////////////////////////////////////////////////////////////// +// For ESP8266 connect as follows: // +// Display 3.3V to NodeMCU 3V3 // +// Display GND to NodeMCU GND // +// // +// Display GPIO NodeMCU pin // +// BUSY 5 D1 // +// RESET 4 D2 // +// DC 0 D3 // +// CS 2 D4 // +// CLK 14 D5 // +// D6 (MISO not connected to display) // +// DIN 13 D7 // +// // +// Note: Pin allocations for the ePaper signals are defined in // +// ePaper library's epdif.h file, above are the default pins // +/////////////////////////////////////////////////////////////////// + +// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS +// Install the ePaper library for your own display size and type +// from here: +// https://github.com/Bodmer/EPD_Libraries + +// The following is for the Waveshare 2.7" colour ePaper display +// include where ?.?? is screen size in inches + +#include // Screen specific library +Epd ePaper; // Create an instance ePaper + +#include // Graphics library and Sprite class + +TFT_eSPI glc = TFT_eSPI(); // Invoke the graphics library class +TFT_eSprite frame = TFT_eSprite(&glc); // Invoke the Sprite class for the image frame buffer + +#define INK COLORED // Black ink +#define PAPER UNCOLORED // 'paper' background colour + +uint16_t epd_width = EPD_WIDTH; // Set the initial values, these are swapped +uint16_t epd_height = EPD_HEIGHT; // in different landscape/portrait rotations + // so call frame.width() or frame.height() to get new values + +#define EPD_BUFFER 1 // Label for the black frame buffer 1 + +uint8_t* framePtr = NULL; // Pointer for the black frame buffer + +#include "EPD_Support.h" // Include sketch EPD support functions last! + +int8_t limit = 5; // Limit the number of loops before halting +//------------------------------------------------------------------------------------ +// Setup +//------------------------------------------------------------------------------------ +void setup() { + + Serial.begin(250000); // Used for messages + + // Initialise the ePaper library + if (ePaper.Init() != 0) { + Serial.print("ePaper init failed"); + while (1) yield(); // Wait here until re-boot + } + + Serial.println("\r\n ePaper initialisation OK"); + + // Initialise the SPIFFS filing system + if (!SPIFFS.begin()) { + Serial.println("SPIFFS initialisation failed!"); + while (1) yield(); // Stay here twiddling thumbs + } + + Serial.println(" SPIFFS initialisation OK"); + + frame.setColorDepth(1); // Must set the bits per pixel to 1 for ePaper displays + // Set bit depth BEFORE creating Sprite, default is 16! + + // Create a frame buffer in RAM of defined size and save the pointer to it + // RAM needed is about (EPD_WIDTH * EPD_HEIGHT)/8 , ~5000 bytes for 200 x 200 pixels + // Note: always create the Sprite before setting the Sprite rotation + framePtr = (uint8_t*) frame.createSprite(EPD_WIDTH, EPD_HEIGHT); + + Serial.println("\r\nInitialisation done."); + + listFiles(); // List all the files in the SPIFFS +} + +//------------------------------------------------------------------------------------ +// Loop +//------------------------------------------------------------------------------------ +void loop() { + + frame.setRotation(random(4)); // Set the rotation to 0, 1, 2 or 3 ( 1 & 3 = landscape) + + frame.fillSprite(PAPER); + + // Draw 8 bit grey-scale bitmap using Floyd-Steinberg dithering at x,y + // /File name x y + //drawFSBmp("/TestCard.bmp", 0, 0); // 176 x 264 pixels + + drawFSBmp("/Tiger.bmp", (frame.width()-176)/2, (frame.height()-234)/2); // 176 x 234 pixels + + updateDisplay(); // Send image to display and refresh + + delay(5000); + + frame.fillSprite(PAPER); // Fill frame with white + + // Draw circle in frame buffer (x, y, r, color) in center of screen + frame.drawCircle(frame.width()/2, frame.height()/2, frame.width()/6, INK); + + // Draw diagonal lines + frame.drawLine(0 , 0, frame.width()-1, frame.height()-1, INK); + frame.drawLine(0 , frame.height()-1, frame.width()-1, 0, INK); + + updateDisplay(); // Send image to display and refresh + + delay(3000); + + // Run a rotation test + rotateTest(); + + // Put screen to sleep to save power (if wanted) + ePaper.Sleep(); + + if (--limit <= 0) while(1) yield(); // Wait here + + delay(20000); // Wait here for 20s + + // Wake up ePaper display so we can talk to it + Serial.println("Waking up!"); + ePaper.Init(); + +} // end of loop() + + +//------------------------------------------------------------------------------------ +// setRotation() actually rotates the drawing coordinates, not the whole display frame +// buffer so we can use this to draw text at right angles or upside down +//------------------------------------------------------------------------------------ +void rotateTest(void) +{ + //frame.fillSprite(PAPER); // Fill buffer with white to clear old graphics + + // Draw some text in frame buffer + frame.setTextFont(4); // Select font 4 + frame.setTextColor(INK); // Set colour to ink + frame.setTextDatum(TC_DATUM); // Middle centre text datum + + frame.setRotation(0); // Set the display rotation to 0, 1, 2 or 3 ( 1 & 3 = landscape) + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 0", epd_width / 2, 10); + + frame.setRotation(1); // Set the display rotation to 1 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 1", epd_width / 2, 10); + + frame.setRotation(2); // Set the display rotation to 2 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 2", epd_width / 2, 10); + + frame.setRotation(3); // Set the display rotation to 3 + epd_width = frame.width(); // Get the values for the current rotation + epd_height = frame.height(); // epd_height is not used in this sketch + + frame.drawString("Rotation 3", epd_width / 2, 10); + + Serial.println("Updating display"); + updateDisplay(); // Update display +} diff --git a/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino new file mode 100644 index 0000000..e52dbe0 --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/Floyd_Steinberg_BMP.ino @@ -0,0 +1,200 @@ +/* + Support function for Floyd-Steinberg dithering of an 8bit grey-scale BMP image + on a Monochrome display: + https://en.wikipedia.org/wiki/Floyd%E2%80%93Steinberg_dithering + + Bitmap format: + https://en.wikipedia.org/wiki/BMP_file_format + + Example for https://github.com/Bodmer/TFT_eSPI + + The MIT License (MIT) + Copyright (c) 2015 by Bodmer + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYBR_DATUM HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + + Note: drawFSBmp() is a simplified function and does not handle all possible + BMP file header variants. It works OK with 8 bit per pixel grey-scale images + generated by MS Paint and IrfanView. +*/ + +// https://github.com/Bodmer/TFT_eSPI + +//==================================================================================== +// Draw an 8 bit grey-scale bitmap (*.BMP) on a Monochrome display using dithering +//==================================================================================== +// Uses RAM for buffers (3 * width + 4) ( 532 bytes for 176 pixels) + +// Image must be stored in ESP8266 or ESP32 SPIFFS + +// Quantisation error distribution for pixel X +// (This is for bottum up drawing of the BMP) +// |-------|-------|-------| +// | +3/16 | +5/16 | +1/16 | +// |-------|-------|-------| +// | | X | +7/16 | +// |-------|-------|-------| +// + +void drawFSBmp(const char *filename, int16_t x, int16_t y) { + + if ((x >= frame.width()) || (y >= frame.height())) return; + + fs::File bmpFS; + + // Open requested file + bmpFS = SPIFFS.open( filename, "r"); + + if (!bmpFS) + { + Serial.print("File not found"); + return; + } + + uint32_t seekOffset, dib_size; + uint16_t w, h, row, col, num_colors; + uint8_t r, g, b; + + if (read16(bmpFS) == 0x4D42) // Check it is a valid bitmap header + { + read32(bmpFS); + read32(bmpFS); + seekOffset = read32(bmpFS); // Pointer to image start + dib_size = read32(bmpFS); // DIB header size, typically 40 bytes + + w = read32(bmpFS); // Get width and height of image + h = read32(bmpFS); + + // Check it is 1 plane and 8 bits per pixel and no compression + if ((read16(bmpFS) == 1) && (read16(bmpFS) == 8) && (read32(bmpFS) == 0)) + { + read32(bmpFS); // Throw away image size + read32(bmpFS); // Throw away x pixels per meter + read32(bmpFS); // Throw away y pixels per meter + + num_colors = read32(bmpFS); // Number of colours in colour table (usually 256) + + uint8_t pixel_color[num_colors]; // Lookup table for grey-scale + + bmpFS.seek(14 + dib_size); // Seek to start of colour table + + // Capture the colour lookup table + for (uint16_t i = 0; i < num_colors; i++) + { + uint32_t abgr = read32(bmpFS); // Assume 4 byte, RGB colours in LS 3 bytes + pixel_color[i] = (uint8_t) abgr; // For grey-scale R, G, B are same value + } + + bmpFS.seek(seekOffset); // Seek to start of image + + uint16_t padding = (4 - (w & 3)) & 3; // Calculate the BMP line padding + + // Create an zero an 8 bit pixel line buffer + uint8_t* lineBuffer = ( uint8_t*) calloc(w , sizeof(uint8_t)); + + // Create a 16 bit signed line buffer for the quantisation error + // Diffusion spreads to x-1 and x+1 so w + 2 avoids a bounds check + int16_t* qerrBuffer = ( int16_t*) calloc((w + 2)<<1, sizeof(uint8_t)); + + y += h - 1; // Start from bottom (assumes bottum up!) + + // Draw row by row from bottom up + for (row = 0; row < h; row++) { + + // Read a row of pixels + bmpFS.read(lineBuffer, w); + + // Prep variables + uint16_t dx = 0; + uint8_t* bptr = lineBuffer; + int16_t* qptr = qerrBuffer + 1; // + 1 because diffusion spreads to x-1 + + // Lookup color, add quantisation error, clip and clear error buffer + while(dx < w) + { + int16_t depixel = pixel_color[(uint8_t)*bptr] + *qptr; + if (depixel >255) depixel = 255; // Clip pixel to 0-255 + else if (depixel < 0) depixel = 0; + *bptr++ = (uint8_t) depixel; // Save new value, inc pointer + *qptr++ = 0; // Zero error, inc pointer + dx++; // Next pixel + } + + dx = 0; // Reset varaibles to start of line + bptr = lineBuffer; + qptr = qerrBuffer + 1; + int32_t qerr = 0; + int32_t qerr16 = 0; + + // Push the pixel row to screen + while(dx < w) + { + // Add 7/16 of error (error = 0 on first entry) + int16_t pixel = *bptr + (qerr>>1) - qerr16; + + // Do not clip here so quantisation error accumulates correctly? + // Draw pixel (black or white) and determine new error + if (pixel < 128) { frame.drawPixel(x + dx, y, INK); qerr = pixel; } + else qerr = pixel - 255; + + // Diffuse into error buffer for next pixel line + qerr16 = qerr>>4; // 1/16 of error + *(qptr - 1) += (qerr>>2) - qerr16; // Add 3/16 of error + *(qptr ) += (qerr>>2) + qerr16; // Add 5/16 of error + *(qptr + 1) += qerr16; // Add 1/16 of error + + bptr++; // Move along pixel and error buffers + qptr++; + dx++; // Move coordinate along + } + y--; + + // Read any line padding (saves a slow seek) + if (padding) bmpFS.read(lineBuffer, padding); + } + free(lineBuffer); + free(qerrBuffer); + } + else Serial.println("BMP format not recognized."); + } + bmpFS.close(); +} + +//==================================================================================== +// Read a 16 bit value from the filing system +//==================================================================================== +uint16_t read16(fs::File &f) { + uint16_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); // MSB + return result; +} + +//==================================================================================== +// Read a 32 bit value from the filing system +//==================================================================================== +uint32_t read32(fs::File &f) { + uint32_t result; + ((uint8_t *)&result)[0] = f.read(); // LSB + ((uint8_t *)&result)[1] = f.read(); + ((uint8_t *)&result)[2] = f.read(); + ((uint8_t *)&result)[3] = f.read(); // MSB + return result; +} + +// TODO: Add support for colour images by converting RGB to grey-scale +// grey = (R+G+B)/3 + diff --git a/examples/ePaper/Floyd_Steinberg/SPIFFS.ino b/examples/ePaper/Floyd_Steinberg/SPIFFS.ino new file mode 100644 index 0000000..ff35f61 --- /dev/null +++ b/examples/ePaper/Floyd_Steinberg/SPIFFS.ino @@ -0,0 +1,92 @@ + + // Call up the SPIFFS FLASH filing system + #define FS_NO_GLOBALS + #include + + #ifdef ESP32 + #include "SPIFFS.h" + #endif + + /*==================================================================================== + This sketch supports the ESP6266 and ESP32 SPIFFS filing system + + Created by Bodmer 15th Jan 2017 + ==================================================================================*/ + +//==================================================================================== +// Print a SPIFFS directory list (root directory) +//==================================================================================== + +void listFiles(void) { + Serial.println(); + Serial.println("SPIFFS files found:"); + +#ifdef ESP32 + listDir(SPIFFS, "/", true); +#else + fs::Dir dir = SPIFFS.openDir("/"); // Root directory + String line = "====================================="; + + Serial.println(line); + Serial.println(" File name Size"); + Serial.println(line); + + while (dir.next()) { + String fileName = dir.fileName(); + Serial.print(fileName); + int spaces = 25 - fileName.length(); // Tabulate nicely + if (spaces < 0) spaces = 1; + while (spaces--) Serial.print(" "); + fs::File f = dir.openFile("r"); + Serial.print(f.size()); Serial.println(" bytes"); + yield(); + } + + Serial.println(line); +#endif + Serial.println(); + delay(1000); +} +//==================================================================================== + +#ifdef ESP32 +void listDir(fs::FS &fs, const char * dirname, uint8_t levels) { + Serial.printf("Listing directory: %s\n", dirname); + + fs::File root = fs.open(dirname); + if (!root) { + Serial.println("Failed to open directory"); + return; + } + if (!root.isDirectory()) { + Serial.println("Not a directory"); + return; + } + + fs::File file = root.openNextFile(); + while (file) { + + if (file.isDirectory()) { + Serial.print("DIR : "); + String fileName = file.name(); + Serial.print(fileName); + if (levels) { + listDir(fs, file.name(), levels - 1); + } + } else { + String fileName = file.name(); + Serial.print(" " + fileName); + int spaces = 32 - fileName.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + String fileSize = (String) file.size(); + spaces = 8 - fileSize.length(); // Tabulate nicely + if (spaces < 1) spaces = 1; + while (spaces--) Serial.print(" "); + Serial.println(fileSize + " bytes"); + } + + file = root.openNextFile(); + } +} +#endif diff --git a/examples/ePaper/Floyd_Steinberg/data/TestCard.bmp b/examples/ePaper/Floyd_Steinberg/data/TestCard.bmp new file mode 100644 index 0000000..3a18f0c Binary files /dev/null and b/examples/ePaper/Floyd_Steinberg/data/TestCard.bmp differ diff --git a/examples/ePaper/Floyd_Steinberg/data/Tiger.bmp b/examples/ePaper/Floyd_Steinberg/data/Tiger.bmp new file mode 100644 index 0000000..ef26eb1 Binary files /dev/null and b/examples/ePaper/Floyd_Steinberg/data/Tiger.bmp differ diff --git a/Keywords.txt b/keywords.txt similarity index 50% rename from Keywords.txt rename to keywords.txt index 784ec75..f89d981 100644 --- a/Keywords.txt +++ b/keywords.txt @@ -5,9 +5,11 @@ drawPixel KEYWORD2 drawChar KEYWORD2 setAddrWindow KEYWORD2 setWindow KEYWORD2 +readAddrWindow KEYWORD2 +startWrite KEYWORD2 +writeColor KEYWORD2 +endWrite KEYWORD2 pushColor KEYWORD2 -pushColor KEYWORD2 -pushColors KEYWORD2 pushColors KEYWORD2 fillScreen KEYWORD2 writeBegin KEYWORD2 @@ -30,12 +32,14 @@ fillEllipse KEYWORD2 drawTriangle KEYWORD2 fillTriangle KEYWORD2 drawBitmap KEYWORD2 +drawXBitmap KEYWORD2 setCursor KEYWORD2 -setCursor KEYWORD2 -setTextColor KEYWORD2 +getCursorX KEYWORD2 +getCursorY KEYWORD2 setTextColor KEYWORD2 setTextSize KEYWORD2 setTextFont KEYWORD2 +setFreeFont KEYWORD2 setTextWrap KEYWORD2 setTextDatum KEYWORD2 setTextPadding KEYWORD2 @@ -48,11 +52,17 @@ readcommand16 KEYWORD2 readcommand32 KEYWORD2 readPixel KEYWORD2 readRect KEYWORD2 +pushRect KEYWORD2 +pushImage KEYWORD2 +setSwapBytes KEYWORD2 +getSwapBytes KEYWORD2 readRectRGB KEYWORD2 getRotation KEYWORD2 +getTextDatum KEYWORD2 fontsLoaded KEYWORD2 color565 KEYWORD2 -drawChar KEYWORD2 +color16to8 KEYWORD2 +color8to16 KEYWORD2 drawNumber KEYWORD2 drawFloat KEYWORD2 drawString KEYWORD2 @@ -63,3 +73,50 @@ width KEYWORD2 textWidth KEYWORD2 fontHeight KEYWORD2 +getTouchRaw KEYWORD2 +convertRawXY KEYWORD2 +getTouchRawZ KEYWORD2 +getTouch KEYWORD2 +calibrateTouch KEYWORD2 +setTouch KEYWORD2 + +TFT_eSPI_Button KEYWORD1 + +initButton KEYWORD2 +textcolor KEYWORD2 +initButtonUL KEYWORD2 +drawButton KEYWORD2 +contains KEYWORD2 +press KEYWORD2 +isPressed KEYWORD2 +justPressed KEYWORD2 +justReleased KEYWORD2 + + +TFT_eSprite KEYWORD1 + +createSprite KEYWORD2 +setColorDepth KEYWORD2 +getColorDepth KEYWORD2 +deleteSprite KEYWORD2 +pushRotated KEYWORD2 +rotatedBounds KEYWORD2 +setPivot KEYWORD2 +getPivotX KEYWORD2 +getPivotY KEYWORD2 +fillSprite KEYWORD2 +pushBitmap KEYWORD2 +pushSprite KEYWORD2 +setScrollRect KEYWORD2 +scroll KEYWORD2 +printToSprite KEYWORD2 +frameBuffer KEYWORD2 +setBitmapColor KEYWORD2 + +alphaBlend KEYWORD2 +showFont KEYWORD2 +loadFont KEYWORD2 +unloadFont KEYWORD2 +getUnicodeIndex KEYWORD2 +decodeUTF8 KEYWORD2 +drawGlyph KEYWORD2 diff --git a/library.json b/library.json index 6696ff4..ac9e8b9 100644 --- a/library.json +++ b/library.json @@ -1,8 +1,8 @@ { "name": "TFT_eSPI", - "version": "0.16.14", - "keywords": "TFT, ESP8266, NodeMCU, ESP32, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486", - "description": "A TFT SPI graphics library for ESP8266", + "version": "1.4.20", + "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140", + "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": { "type": "git", @@ -14,12 +14,8 @@ "name": "Bodmer", "email": "bodmer@anola.net", "maintainer": true - }, - { - "name": "Adafruit", - "url": "https://www.adafruit.com/" } ], "frameworks": "arduino", - "platforms": "espressif8266" + "platforms": "espressif8266, espressif32" } diff --git a/library.properties b/library.properties index 6150dea..aea4881 100644 --- a/library.properties +++ b/library.properties @@ -1,10 +1,11 @@ name=TFT_eSPI -version=0.16.14 +version=1.4.20 author=Bodmer maintainer=Bodmer -sentence=A fast TFT library for ESP8266 processors and the Arduino IDE -paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI. +sentence=A fast TFT graphics library for ESP8266 and ESP32 processors for the Arduino IDE +paragraph=Supports TFT displays using drivers (ILI9341 etc) that operate with hardware SPI or 8 bit parallel. category=Display -url=http://www.instructables.com/id/Arduino-TFT-display-and-font-library/ +url=https://github.com/Bodmer/TFT_eSPI architectures=esp8266,esp32 includes=TFT_eSPI.h + diff --git a/license.txt b/license.txt new file mode 100644 index 0000000..a58b151 --- /dev/null +++ b/license.txt @@ -0,0 +1,131 @@ +The original starting point for this library was the Adafruit_ILI9341 +library in January 2015. + +The licence for that library is MIT. + +The first evolution of the library that led to TFT_eSPI is recorded here: + +https://www.instructables.com/id/Arduino-TFT-display-and-font-library/ + +Adafruit_ILI9341 ORIGINAL LIBRARY HEADER: + +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + This is our library for the Adafruit ILI9341 Breakout and Shield + ----> http://www.adafruit.com/products/1651 + + Check out the links above for our tutorials and wiring diagrams + These displays use SPI to communicate, 4 or 5 pins are required to + interface (RST is optional) + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + MIT license, all text above must be included in any redistribution + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^End^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + +Selected functions from the Adafruit_GFX library (as it was in 2015) have +been imported into the TFT_eSPI.cpp file and modified to improve +performance, add features and make them compatible with the ESP8266 and +ESP32. + +The fonts from the Adafruit_GFX and Button functions were added later. +The fonts can be found with the license.txt file in the "Fonts\GFXFF" +folder. + +The Adafruit_GFX functions are covered by the BSD licence. + +Adafruit_GFX ORIGINAL LIBRARY LICENSE: + +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + +Software License Agreement (BSD License) + +Copyright (c) 2012 Adafruit Industries. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^End^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Due to the evolution of the TFT_eSPI library the original code may no longer +be recognisable, however in most cases the function names can be used as a +reference point since the aim is to retain a level of compatibility with +the popular Adafruit_GFX graphics functions. + +Contributions from other authors are recorded on GitHub: +https://github.com/Bodmer/TFT_eSPI + +The major addition to the original library was the addition of fast +rendering proportional fonts of different sizes as documented here: + +https://www.instructables.com/id/Arduino-TFT-display-and-font-library/ + +The larger fonts are "Run Length Encoded (RLE)", this was done to +reduce the font memory footprint for AVR processors that have limited +FLASH, with the added benefit of a significant improvement in rendering +speed. + +In 2016 the library evolved significantly to support the ESP8266 and then +the ESP32. In 2017 new Touch Screen functions were added and a new Sprite +class called TFT_eSprite to permit "flicker free" screen updates of complex +graphics. + +In 2018 anti-aliased fonts were added along with a Processing font conversion +sketch. + +Many of the example sketches are original work, that contain code created +for my own projects. For all the original code the FreeBSD licence applies +and is compatible with the GNU GPL. + +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +Software License Agreement (FreeBSD License) + +Copyright (c) 2017 Bodmer (https://github.com/Bodmer) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^End^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^