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..14ed796 --- /dev/null +++ b/Extensions/Smooth_font.cpp @@ -0,0 +1,520 @@ + // 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 stored in SPIFFS +*************************************************************************************x*/ +void TFT_eSPI::loadFont(String fontName) +{ + /* + 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 + + */ + + unloadFont(); + + _gFontFilename = "/" + fontName + ".vlw"; + + fontFile = SPIFFS.open( _gFontFilename, "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 will 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; + + 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 = (int8_t*)malloc( gCount ); // offset from bitmap top edge from lowest point in any character + gdX = (int8_t*)malloc( gCount ); // offset for bitmap left edge relative to cursor X + gBitmap = (uint32_t*)malloc( gCount * 4); // seek pointer to glyph bitmap in SPIFFS file + +#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] = (int8_t)readInt32(); // y delta from baseline + gdX[gNum] = (int8_t)readInt32(); // x delta from cursor + readInt32(); // ignored + + // Different glyph sets have different ascent values not always based on "d", so get maximum glyph ascent + if (gdY[gNum] > gFont.maxAscent) + { + // Avoid UTF coding values and characters that tend to give duff values + if (((gUnicode[gNum] > 0x20) && (gUnicode[gNum] < 0xA0) && (gUnicode[gNum] != 0x7F)) || (gUnicode[gNum] > 0xFF)) + { + 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*/ +#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)) + return ((c & 0x0F)<<12) | ((buf[(*index)++]&0x3F)<<6) | ((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*/ +uint16_t TFT_eSPI::decodeUTF8(uint8_t c) +{ + +#ifdef DECODE_UTF8 + if (decoderState == 0) + { + // 7 bit Unicode + if ((c & 0x80) == 0x00) return (uint16_t)c; + + // 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 + + 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]]; + + uint16_t xs = 0; + uint32_t dl = 0; + + int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum]; + int16_t cx = cursor_x + gdX[gNum]; + + for (int y = 0; y < gHeight[gNum]; y++) + { + fontFile.read(pbuffer, gWidth[gNum]); //= 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..6ab09fc --- /dev/null +++ b/Extensions/Smooth_font.h @@ -0,0 +1,54 @@ + // 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); + void unloadFont( void ); + bool getUnicodeIndex(uint16_t unicode, uint16_t *index); + + uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining); + uint16_t decodeUTF8(uint8_t c); + + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + + void drawGlyph(uint16_t code); + void showFont(uint32_t td); + + fs::File fontFile; + + // 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 + int8_t* gdY = NULL; //topExtent + int8_t* gdX = NULL; //leftExtent + uint32_t* gBitmap = NULL; //file pointer to greyscale bitmap + + String _gFontFilename; + + uint8_t decoderState = 0; // UTF8 decoder state + uint16_t decoderBuffer; // Unicode code-point buffer + + bool fontLoaded = false; // Flags when a anti-aliased font is loaded + + private: + + void loadMetrics(uint16_t gCount); + uint32_t readInt32(void); diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp new file mode 100644 index 0000000..a7443e9 --- /dev/null +++ b/Extensions/Sprite.cpp @@ -0,0 +1,1662 @@ +/************************************************************************************** +// 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; + + 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; + + // 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. + if (_bpp == 16) + { + _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint16_t)); + _img8_2 = _img8_1; + _img = (uint16_t*) _img8_1; + + if (_img) + { + _created = true; + return _img; + } + } + + else if (_bpp == 8) + { + _img8_1 = ( uint8_t*) calloc(w * h + 1, sizeof(uint8_t)); + + if (_img8_1) + { + _img8 = _img8_1; + _img8_2 = _img8_1; + _created = true; + return _img8; + } + } + + 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; + _img8 = ( uint8_t*) calloc(frames * (w>>3) * h + frames, sizeof(uint8_t)); // extra pixel added + + if (_img8) + { + _created = true; + _img8_1 = _img8; + _img8_2 = _img8 + ( (w>>3) * h + 1 ); + return _img8_1; + } + } + + return NULL; +} + +/*************************************************************************************** +** 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: setDepth +** Description: Set bits per pixel for colour (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: 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: 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) _tft->pushImage(x, y, _iwidth, _iheight, _img ); + + 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) _tft->pushImage(x, y, _iwidth, _iheight, _img, transp ); + 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*/ +// TODO Need to add more area boundary checks +void TFT_eSprite::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) +{ + if ((x >= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + + if (_bpp == 16) + { + for (uint32_t yp = y; yp < y + h; yp++) + { + for (uint32_t xp = x; xp < x + w; xp++) + { + uint16_t color = *data++; + if(!_iswapBytes) color = color<<8 | color>>8; + _img[xp + yp * _iwidth] = color; + } + } + } + else if (_bpp == 8) + { + for (uint32_t yp = y; yp < y + h; yp++) + { + for (uint32_t xp = x; xp < x + w; xp++) + { + uint16_t color = *data++; + if(_iswapBytes) color = color<<8 | color>>8; + _img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + } + } + } + + 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; + } + + uint8_t* pdata = (uint8_t*) data; + uint32_t ww = (w+7) & 0xFFF8; + for (int32_t yp = 0; yp= _iwidth) || (y >= _iheight) || (w == 0) || (h == 0) || !_created) return; + + if (_bpp == 16) + { + for (uint32_t yp = y; yp < y + h; yp++) + { + for (uint32_t xp = x; xp < x + w; xp++) + { + uint16_t color = pgm_read_word(data++); + if(!_iswapBytes) color = color<<8 | color>>8; + _img[xp + yp * _iwidth] = color; + } + } + } + + else if (_bpp == 8) + { + for (uint32_t yp = y; yp < y + h; yp++) + { + for (uint32_t xp = x; xp < x + w; xp++) + { + uint16_t color = pgm_read_word(data++); + if(_iswapBytes) color = color<<8 | color>>8; + _img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + } + } + } + + 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; + } + + 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 < 0) x0 = 0; + if (x0 >= _iwidth) duff_coord = true; + if (x1 < 0) x1 = 0; + if (x1 >= _iwidth) x1 = _iwidth - 1; + + if (y0 < 0) y0 = 0; + if (y0 >= _iheight) duff_coord = true; + if (y1 < 0) y1 = 0; + if (y1 >= _iheight) y1 = _iheight - 1; + + if (duff_coord) + { // Point to that extra "off screen" pixel + _xs = 0; + _ys = _iheight; + _xe = 0; + _ye = _iheight; + } + else + { + _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 Nothing to do 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, uint32_t w, uint32_t h, uint16_t color) +{ + if ((x >= _iwidth) || (y >= _iheight) || !_created ) return; + + if (x < 0) x = 0; + if (y < 0) 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 return; // TODO add scroll for 1 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 _bitwidth; +} + + +/*************************************************************************************** +** 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) +{ + _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(uint32_t x, uint32_t y, uint32_t color) +{ + // x and y are unsigned so that -ve coordinates turn into large positive ones + // this make bounds checking a bit faster + if ((x >= _iwidth) || (y >= _iheight) || !_created) return; + + 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 < 0) { w += x; x = 0; } + + if ((x < 0) || (y < 0) || (x >= _iwidth) || (y >= _iheight)) return; + if ((x + w) > _iwidth) w = _iwidth - x; + if ((y + h) > _iheight) h = _iheight - y; + if ((w < 1) || (h < 1)) return; + + int32_t yp = _iwidth * y + x; + + 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) +{ + if (utf8 == '\r') return 1; + +#ifdef SMOOTH_FONT + if(this->fontLoaded) + { + uint16_t unicode = decodeUTF8(utf8); + if (unicode < 32 && utf8 != '\n') return 0; + + //fontFile = SPIFFS.open( _gFontFilename, "r" ); + //fontFile = SPIFFS.open( this->_gFontFilename, "r" ); + + //if(!fontFile) + //{ + // fontLoaded = false; + // return 0; + //} + //Serial.print("Decoded Unicode = 0x");Serial.println(unicode,HEX); + + drawGlyph(unicode); + //fontFile.close(); + return 0; + } +#endif + + if (!_created ) return 0; + + + uint8_t uniCode = utf8; // Work with a copy + if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (utf8 < 32) return 0; + + 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 0; + // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) + width = pgm_read_byte(widtbl_f16 + uniCode-32); + height = chr_hgt_f16; + // Font 2 is rendered in whole byte widths so we must allow for this + 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 0; + // 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 ); + } + } +#endif + +#ifdef LOAD_GLCD + if (textfont==1) + { + width = 6; + height = 8; + } +#else + if (textfont==1) return 0; +#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 > (uint8_t)pgm_read_byte(&gfxFont->last )) return 0; + if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 0; + + 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(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, unsigned char 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; + +#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 >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + { +//>>>>>>>>>>>>>>>>>>>>>>>>>>> + + 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 = 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*/ +int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y) +{ + return drawChar(uniCode, x, y, textfont); +} + +int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font) +{ + if (!_created ) 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_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) + { + uint8_t c2 = uniCode - pgm_read_byte(&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; + + int width = 0; + int 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( 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; + 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 (int i = 0; i < height; i++) + { + if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize, textbgcolor); + + for (int 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); + int px = 0, py = pY; // To hold character block start and end column and row values + int 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]]; + + uint16_t xs = 0; + uint16_t dl = 0; + + for (int y = 0; y < this->gHeight[gNum]; y++) + { + this->fontFile.read(pbuffer, this->gWidth[gNum]); + for (int 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 (pixel>127) drawPixel(x + this->cursor_x + this->gdX[gNum], y + this->cursor_y + this->gFont.maxAscent - this->gdY[gNum], alphaBlend(pixel, fg, bg)); + } + 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; + int16_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, int 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); + uint16_t transparent = TFT_BLACK; + + 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); + uint16_t transparent = TFT_BLACK; + 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..1ea7645 --- /dev/null +++ b/Extensions/Sprite.h @@ -0,0 +1,125 @@ +/*************************************************************************************** +// 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 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); + + void setBitmapColor(uint16_t c, uint16_t b); + + void drawPixel(uint32_t x, uint32_t y, uint32_t color); + + void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), + + fillSprite(uint32_t color), + + // Define a window to push 16 bit colour pixels into is 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, uint32_t w, uint32_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); + + void setRotation(uint8_t rotation); + uint8_t getRotation(void); + + // 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, uint32_t w, uint32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data); + + // 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(unsigned int uniCode, int x, int y, int font), + drawChar(unsigned int uniCode, int x, int 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, int len); + int16_t printToSprite(int16_t x, int16_t y, uint16_t index); + + private: + + TFT_eSPI *_tft; + + protected: + + uint8_t _bpp; + uint16_t *_img; // pointer to 16 bit sprite + uint8_t *_img8; // pointer to 8 bit sprite + uint8_t *_img8_1; // pointer to frame 1 + uint8_t *_img8_2; // pointer to frame 2 + + bool _created; // created and bits per pixel depth flags + 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..8a3efa8 --- /dev/null +++ b/Extensions/Touch.cpp @@ -0,0 +1,289 @@ +// 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. Return false if not pressed. +***************************************************************************************/ +uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ + uint16_t tmp; + CS_H; + + spi_begin_touch(); + + T_CS_L; + + // Start bit + YP sample request for x position + tmp = SPI.transfer(0xd0); + tmp = SPI.transfer(0); + tmp = tmp <<5; + tmp |= 0x1f & (SPI.transfer(0)>>3); + + *x = tmp; + + // Start bit + XP sample request for y position + SPI.transfer(0x90); + tmp = SPI.transfer(0); + tmp = tmp <<5; + tmp |= 0x1f & (SPI.transfer(0)>>3); + + *y = tmp; + + T_CS_H; + + spi_end_touch(); + + return true; +} + +/*************************************************************************************** +** Function name: getTouchRawZ +** Description: read raw pressure on touchpad and return Z value. +***************************************************************************************/ +uint16_t TFT_eSPI::getTouchRawZ(void){ + CS_H; + + spi_begin_touch(); + + T_CS_L; + + // Z sample request + int16_t tz = 0xFFF; + SPI.transfer(0xb1); + tz += SPI.transfer16(0xc1) >> 3; + tz -= SPI.transfer16(0x91) >> 3; + + T_CS_H; + + spi_end_touch(); + + return (uint16_t)tz; +} + +/*************************************************************************************** +** Function name: validTouch +** Description: read validated position. Return false if not pressed. +***************************************************************************************/ +#define _RAWERR 10 // Deadband in 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 + 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, xx, yy; + + 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; + + 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; + } + + if (xx >= _width || yy >= _height) return valid; + + _pressX = xx; + _pressY = yy; + *x = _pressX; + *y = _pressY; + return valid; +} + +/*************************************************************************************** +** 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..7f3b22a --- /dev/null +++ b/Extensions/Touch.h @@ -0,0 +1,24 @@ + // 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: + + uint8_t getTouchRaw(uint16_t *x, uint16_t *y); + uint16_t getTouchRawZ(void); + uint8_t getTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + + void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size); + void setTouch(uint16_t *data); + + private: + + inline void spi_begin_touch() __attribute__((always_inline)); + inline void spi_end_touch() __attribute__((always_inline)); + + // These are associated with the Touch Screen handlers + uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); + // Initialise with example calibration values so processor does not crash if setTouch() not called in setup() + uint16_t touchCalibration_x0 = 300, touchCalibration_x1 = 3600, touchCalibration_y0 = 300, touchCalibration_y1 = 3600; + uint8_t touchCalibration_rotate = 1, touchCalibration_invert_x = 2, touchCalibration_invert_y = 0; + uint32_t _pressTime; + uint16_t _pressX, _pressY; 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/README.md b/README.md index d059391..00e3023 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,78 @@ # TFT_eSPI -In addition to the original library, this library supports the XPT2046 touch screen controller, which is part of many RPi displays. The SPI is shared with the TFT and only an additional chip select line is needed. +An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with a driver for ILI9341, ILI9163, ST7735, S6D02A1, ILI9481, ILI9486, HX8357D and ST7789 based TFT displays that support SPI. + +8 bit parallel interface TFTs (e.g. UNO format mcufriend shields) can used with an ESP32. The ILI9488 is supported in 8 bit parallel mode. + +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). + +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. + +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 and in the case any 16 bit Unicode character can be included and rendered, this means many language specific characters can be rendered to the screen. + +The library is based on the Adafruit GFX and Adafruit driver libraries and the aim is to retain compatibility. Significant additions have been made to the library to boost the speed for ESP8266/ESP32 processors (it is typically 3 to 10 times faster) and to add new features. The new graphics functions include different size proportional fonts and formatting features. There are lots of example sketches to demonstrate the different features and included functions. + +Configuration of the library font selections, pins used to interface with the TFT and other features is made by editting the User_Setup.h file in the library folder, or by selecting a configuration in the library "User_Setup_Selet,h" file. Fonts and features can easily be disabled by commenting out lines. -An Arduino IDE compatible graphics and fonts library for ESP8266 and ESP32 processors with a driver for ILI9341, ILI9163, ST7735 and S6D02A1 based TFT displays that support SPI. +# Anti-aliased Fonts -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). +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. -The library supports SPI overlap so the TFT screen can share MOSI, MISO and SCLK pins with the program FLASH. +Here is the Adafruit_GFX "FreeSans12pt" bitmap font compared to the same font drawn as anti-aliased: -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) and an ESP32 demo board. +![Smooth_font](https://i.imgur.com/gAeDPFY.png) -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 a significant number of example sketches to demonstrate the different features. +The smooth font example displays the following screen: -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. +![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) + + +# 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 db56bbe..03ec449 100644 --- a/README.txt +++ b/README.txt @@ -10,5 +10,9 @@ 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_Init.h b/TFT_Drivers/ILI9341_Init.h index c867e4e..124c849 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(0xA8); // Rotation 0 (portrait mode) +#else + writedata(0x48); // Rotation 0 (portrait mode) +#endif writecommand(ILI9341_PIXFMT); writedata(0x55); @@ -116,4 +120,11 @@ spi_begin(); writecommand(ILI9341_DISPON); //Display on + +#ifdef M5STACK + // Turn on the back-light LED + digitalWrite(TFT_BL, HIGH); + pinMode(TFT_BL, OUTPUT); +#endif + } \ No newline at end of file diff --git a/TFT_Drivers/ILI9341_Rotation.h b/TFT_Drivers/ILI9341_Rotation.h index c856dea..f5e9b38 100644 --- a/TFT_Drivers/ILI9341_Rotation.h +++ b/TFT_Drivers/ILI9341_Rotation.h @@ -6,45 +6,77 @@ writecommand(TFT_MADCTL); switch (rotation) { case 0: +#ifdef M5STACK + writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); +#else writedata(TFT_MAD_MX | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#endif + _width = _init_width; + _height = _init_height; break; case 1: +#ifdef M5STACK + writedata(TFT_MAD_BGR); +#else writedata(TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#endif + _width = _init_height; + _height = _init_width; break; case 2: +#ifdef M5STACK + writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_BGR); +#else writedata(TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#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; - break; - // These next rotations are for bottum up BMP drawing - case 4: +#ifdef M5STACK writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#else + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); +#endif + _width = _init_height; + _height = _init_width; + break; + // These next rotations are for bottom up BMP drawing + case 4: +#ifdef M5STACK + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); +#else + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_BGR); +#endif + _width = _init_width; + _height = _init_height; break; case 5: +#ifdef M5STACK + writedata(TFT_MAD_MY | TFT_MAD_BGR); +#else writedata(TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#endif + _width = _init_height; + _height = _init_width; break; case 6: +#ifdef M5STACK + writedata(TFT_MAD_MV | TFT_MAD_BGR); +#else writedata(TFT_MAD_BGR); - _width = TFT_WIDTH; - _height = TFT_HEIGHT; +#endif + _width = _init_width; + _height = _init_height; break; case 7: +#ifdef M5STACK + writedata(TFT_MAD_MX | TFT_MAD_BGR); +#else writedata(TFT_MAD_MY | TFT_MAD_MV | TFT_MAD_BGR); - _width = TFT_HEIGHT; - _height = TFT_WIDTH; +#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/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..feaffdd --- /dev/null +++ b/TFT_Drivers/ILI9488_Init.h @@ -0,0 +1,97 @@ + +// 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(0x3A); // Pixel Interface Format (16 bit colour) + writedata(0x55); + + writecommand(0xB0); // Interface Mode Control + writedata(0x00); + + writecommand(0xB1); // Frame Rate Control + writedata(0xB0); + writedata(0x11); + + 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(0XC0); // Power Control 1 + writedata(0x10); + writedata(0x10); + + writecommand(0xC1); // Power Control 2 + writedata(0x41); + + writecommand(0xC5); // VCOM Control + writedata(0x00); + writedata(0x22); + writedata(0x80); + writedata(0x40); + + 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(0xF7); // Adjust Control 3 + writedata(0xA9); + writedata(0x51); + writedata(0x2C); + writedata(0x02); + + writecommand(TFT_MADCTL); // Memory Access Control + writedata(0x48); // MX, BGR + + 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/RPI_ILI9486_Rotation.h b/TFT_Drivers/RPI_ILI9486_Rotation.h index cd6b0f7..495d675 100644 --- a/TFT_Drivers/RPI_ILI9486_Rotation.h +++ b/TFT_Drivers/RPI_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/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_Init.h b/TFT_Drivers/ST7735_Init.h index 27b3253..0df152c 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); diff --git a/TFT_Drivers/ST7735_Rotation.h b/TFT_Drivers/ST7735_Rotation.h index 6b38560..b9476a1 100644 --- a/TFT_Drivers/ST7735_Rotation.h +++ b/TFT_Drivers/ST7735_Rotation.h @@ -20,11 +20,13 @@ writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_MH | TFT_MAD_BGR); colstart = 0; rowstart = 32; - } else { + } 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 +43,13 @@ writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_BGR); colstart = 32; rowstart = 0; - } else { + } 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 +66,13 @@ writedata(TFT_MAD_BGR); colstart = 0; rowstart = 0; - } else { + } 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 +89,35 @@ writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_BGR); colstart = 0; rowstart = 0; - } else { + } 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_Defines.h b/TFT_Drivers/ST7789_Defines.h new file mode 100644 index 0000000..b900b79 --- /dev/null +++ b/TFT_Drivers/ST7789_Defines.h @@ -0,0 +1,48 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 240 +#define TFT_HEIGHT 240 + + +// 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 + +#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/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h new file mode 100644 index 0000000..57b526b --- /dev/null +++ b/TFT_Drivers/ST7789_Init.h @@ -0,0 +1,25 @@ + +// This is the command sequence that initialises the ST7789 driver + +// Configure ST7789 display +{ +static const uint8_t PROGMEM + st7789[] = { + 9, + TFT_SWRST, TFT_INIT_DELAY, 150, + TFT_SLPOUT, TFT_INIT_DELAY, 255, + TFT_COLMOD, 1+TFT_INIT_DELAY, 0x55, 10, + TFT_MADCTL, 1, 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 + + + diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h new file mode 100644 index 0000000..3a75ec6 --- /dev/null +++ b/TFT_Drivers/ST7789_Rotation.h @@ -0,0 +1,26 @@ + // This is the command sequence that rotates the ST7789 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_eSPI.cpp b/TFT_eSPI.cpp index a335193..b63a1bc 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 @@ -21,42 +17,66 @@ #include -//#include -//#include "pins_arduino.h" -//#include "wiring_private.h" -#include +#ifndef ESP32_PARALLEL + #include +#endif + + // 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 #else #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); + +// Byte read prototype +uint8_t readByte(void); + +// GPIO parallel input/output control +void busDir(uint32_t mask, uint8_t mode); // If the SPI library has transaction support, these functions // establish settings and protect from interference from other // libraries. Otherwise, they simply do nothing. inline void TFT_eSPI::spi_begin(void){ -#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, SPI_MODE0));} #endif } inline void TFT_eSPI::spi_end(void){ -#ifdef SPI_HAS_TRANSACTION - #ifdef SUPPORT_TRANSACTIONS +#if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(ESP32_PARALLEL) if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} - #endif #endif } +#if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(ESP32_PARALLEL) + + inline void TFT_eSPI::spi_begin_touch(void){ + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + #else + SPI.setFrequency(SPI_TOUCH_FREQUENCY); + #endif + } + + inline void TFT_eSPI::spi_end_touch(void){ + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if(!inTransaction) {if (!locked) {locked = true; SPI.endTransaction();}} + #else + SPI.setFrequency(SPI_FREQUENCY); + #endif + } + +#endif /*************************************************************************************** ** Function name: TFT_eSPI @@ -96,19 +116,55 @@ 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 data bus and Write line GPIO bit clear mask + //clr_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) | (1 << TFT_WR); + + // Create a data bus GPIO bit direction mask + //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); + + + // Create a bit set lookup table for data bus - wastes 1kbyte of RAM but speeds things up dramatically + for (int c = 0; c<256; c++) + { + 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 + 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; @@ -139,6 +195,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 } @@ -146,9 +209,9 @@ 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); } @@ -156,7 +219,7 @@ void TFT_eSPI::begin(void) ** Function name: init ** Description: Reset, then initialise the TFT display registers ***************************************************************************************/ -void TFT_eSPI::init(void) +void TFT_eSPI::init(uint8_t tc) { #if !defined (ESP32) #ifdef TFT_CS @@ -180,39 +243,39 @@ void TFT_eSPI::init(void) SPI.begin(); // This will set HMISO to input #else - #if defined (TFT_MOSI) && !defined (TFT_SPI_OVERLAP) - SPI.begin(TFT_SCLK, TFT_MISO, TFT_MOSI, -1); - #else - SPI.begin(); + #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 inTransaction = false; locked = true; -#ifndef SUPPORT_TRANSACTIONS - + // 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(SPI_MODE0); SPI.setFrequency(SPI_FREQUENCY); - - #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 - #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); +#if defined(ESP32_PARALLEL) + digitalWrite(TFT_CS, LOW); // Chip select low permanently + pinMode(TFT_CS, OUTPUT); #else - SPI.setHwCs(1); // Use hardware SS toggling + #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 @@ -244,6 +307,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) @@ -255,6 +319,21 @@ void TFT_eSPI::init(void) #elif defined (RPI_ILI9486_DRIVER) #include "TFT_Drivers/RPI_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" + #endif spi_end(); @@ -287,6 +366,21 @@ void TFT_eSPI::setRotation(uint8_t m) #elif defined (RPI_ILI9486_DRIVER) #include "TFT_Drivers/RPI_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" + #endif delayMicroseconds(10); @@ -340,7 +434,7 @@ void TFT_eSPI::commandList (const uint8_t *addr) ***************************************************************************************/ void TFT_eSPI::spiwrite(uint8_t c) { - SPI.transfer(c); + tft_Write_8(c); } @@ -352,10 +446,9 @@ void TFT_eSPI::writecommand(uint8_t c) { DC_C; CS_L; - #ifdef SEND_16_BITS - SPI.transfer(0); - #endif - SPI.transfer(c); + + tft_Write_8(c); + CS_H; DC_D; } @@ -365,52 +458,71 @@ 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); + + tft_Write_8(d); + 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) { + 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(); index = 0x10 + (index & 0x0F); DC_C; CS_L; - SPI.transfer(0xD9); + tft_Write_8(0xD9); DC_D; - SPI.transfer(index); + tft_Write_8(index); CS_H; DC_C; CS_L; - SPI.transfer(cmd_function); + tft_Write_8(cmd_function); DC_D; - uint8_t reg = SPI.transfer(0); + reg = tft_Write_8(0); CS_H; spi_end(); +#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; + uint32_t reg; + reg |= (readcommand8(cmd_function, index + 0) << 8); reg |= (readcommand8(cmd_function, index + 1) << 0); @@ -419,10 +531,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; @@ -441,61 +553,198 @@ void TFT_eSPI::writedata(uint8_t c) ***************************************************************************************/ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) { +#if defined(ESP32_PARALLEL) + + readAddrWindow(x0, y0, x0, y0); // Sets CS low + + // Set masked pins D0- D7 to input + busDir(dir_mask, INPUT); + + // Dummy read to throw away don't care value + 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; + + // 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(); readAddrWindow(x0, y0, x0, y0); // Sets CS low // Dummy read to throw away don't care value - SPI.transfer(0); + tft_Write_8(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); + uint8_t r = tft_Write_8(0); + uint8_t g = tft_Write_8(0); + uint8_t b = tft_Write_8(0); CS_H; spi_end(); 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(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) { if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return; - + +#if defined(ESP32_PARALLEL) + + readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low + + // Set masked pins D0- D7 to input + busDir(dir_mask, INPUT); + + // Dummy read to throw away don't care value + 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(); readAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low // Dummy read to throw away don't care value - SPI.transfer(0); + tft_Write_8(0); // Read window pixel 24 bit RGB values uint32_t len = w * h; while (len--) { // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits - uint8_t r = SPI.transfer(0); - uint8_t g = SPI.transfer(0); - uint8_t b = SPI.transfer(0); + uint8_t r = tft_Write_8(0); + uint8_t g = tft_Write_8(0); + uint8_t b = tft_Write_8(0); + // 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(); +#endif } @@ -503,51 +752,570 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) ** 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(uint32_t x, uint32_t y, uint32_t w, uint32_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, uint32_t w, uint32_t h, uint16_t *data) +{ + + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _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 + setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR - 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; + + while (dh--) + { + pushColors(data, dw, _swapBytes); + data += w; + } CS_H; + 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, uint32_t w, uint32_t h, uint16_t *data, uint16_t transp) +{ + + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _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; setAddrWindow(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; + } + + CS_H; + + 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, uint32_t w, uint32_t h, const uint16_t *data) +{ + + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _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; + + setAddrWindow(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 (int i = 0; i < nb; i++) { + for (int 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 (int i = 0; i < np; i++) + { + pix_buffer[i] = pgm_read_word(&data[nb * 64 + i]); + } + pushColors(pix_buffer, np, !_swapBytes); + } + + CS_H; + + inTransaction = false; + spi_end(); +} + + +/*************************************************************************************** +** Function name: pushImage - for FLASH (PROGMEM) stored images +** Description: plot 16 bit image with 1 colour being transparent +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transp) +{ + + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _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; setAddrWindow(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; + } + + CS_H; + + inTransaction = false; + spi_end(); +} + + +/*************************************************************************************** +** Function name: pushImage +** Description: plot 8 bit image or sprite using a line buffer +***************************************************************************************/ +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data, bool bpp8) +{ + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _height) dh = _height - y; + + if (dw < 1 || dh < 1) return; + + spi_begin(); + inTransaction = true; + + setAddrWindow(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++; + } + } + + CS_H; + + 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, uint32_t w, uint32_t h, uint8_t *data, uint8_t transp, bool bpp8) +{ + if ((x >= (int32_t)_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 + w) > _width ) dw = _width - x; + if ((y + h) > _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; setAddrWindow(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; + setAddrWindow(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++; + } + } + + CS_H; + + 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) { +#if !defined(ESP32_PARALLEL) spi_begin(); readAddrWindow(x0, y0, x0 + w - 1, y0 + h - 1); // Sets CS low // Dummy read to throw away don't care value - SPI.transfer(0); + tft_Write_8(0); // Read window pixel 24 bit RGB values, buffer must be set in sketch to 3 * w * h uint32_t len = w * h; while (len--) { // Read the 3 RGB bytes, colour is actually only in the top 6 bits of each byte // as the TFT stores colours as 18 bits - *data++ = SPI.transfer(0); - *data++ = SPI.transfer(0); - *data++ = SPI.transfer(0); + *data++ = tft_Write_8(0); + *data++ = tft_Write_8(0); + *data++ = tft_Write_8(0); } CS_H; spi_end(); +#endif } @@ -555,41 +1323,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) { @@ -683,17 +1416,8 @@ 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; @@ -703,7 +1427,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) 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); } } } @@ -945,19 +1655,19 @@ 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(); 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(); } @@ -991,9 +1701,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); @@ -1015,6 +1722,9 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in return; } + spi_begin(); + inTransaction = true; + int32_t dx01 = x1 - x0, dy01 = y1 - y0, @@ -1067,8 +1777,8 @@ 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) { - +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(); inTransaction = true; @@ -1087,6 +1797,54 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w } +/*************************************************************************************** +** 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(); + 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(); +} + + +/*************************************************************************************** +** 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(); + 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(); +} + + /*************************************************************************************** ** Function name: setCursor ** Description: Set the text cursor x,y position @@ -1110,6 +1868,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 @@ -1144,13 +1921,26 @@ void TFT_eSPI::setTextColor(uint16_t c, uint16_t b) } +/*************************************************************************************** +** 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; } @@ -1183,6 +1973,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 @@ -1232,8 +2031,36 @@ int16_t TFT_eSPI::textWidth(const char *string) int16_t TFT_eSPI::textWidth(const char *string, int font) { - unsigned int str_width = 0; - char uniCode; + int str_width = 0; + +#ifdef SMOOTH_FONT + if(fontLoaded) + { + while (*string) + { + uint16_t 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) str_width += gxAdvance[gNum]; + else str_width += (gdX[gNum] + gWidth[gNum]); + } + else str_width += gFont.spaceWidth + 1; + } + } + } + return str_width; + } +#endif + + unsigned char uniCode; char *widthtable; if (font>1 && font<9) @@ -1243,8 +2070,9 @@ int16_t TFT_eSPI::textWidth(const char *string, int font) while (*string) { uniCode = *(string++); - + if (uniCode > 31 && uniCode < 128) str_width += pgm_read_byte( widthtable + uniCode); // Normally we need to subract 32 from uniCode + else str_width += pgm_read_byte( widthtable + 32); // Set illegal character = space width } } else @@ -1256,13 +2084,15 @@ 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)); + if ((uniCode >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (uniCode <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + { + 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)); + } } } else @@ -1295,6 +2125,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) { @@ -1320,6 +2154,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u ((y + 8 * size - 1) < 0)) // Clip top return; + if (c < 32) return; #ifdef LOAD_GLCD //>>>>>>>>>>>>>>>>>> #ifdef LOAD_GFXFF @@ -1331,9 +2166,10 @@ 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(); + //inTransaction = true; setAddrWindow(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; @@ -1362,22 +2198,19 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, u while(SPI1CMD & SPIBUSY) {} } #else // for ESP32 + 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; + //inTransaction = false; spi_end(); } else @@ -1418,30 +2251,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 >= (uint8_t)pgm_read_byte(&gfxFont->first)) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last ))) + { + 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_byte(&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; - } + 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 = 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 @@ -1462,90 +2295,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), 0, (uint8_t) (x0>>0), 0, (uint8_t) (x1>>8), 0, (uint8_t) (x1>>0), }; SPI.writePattern(&xBin[0], 8, 1); #else - SPI.write32(xaw); + tft_Write_32(xaw); #endif // 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); #else - SPI.write32(yaw); + tft_Write_32(yaw); #endif // write to RAM DC_C; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_RAMWR); -#else - SPI.write(TFT_RAMWR); -#endif + tft_Write_8(TFT_RAMWR); DC_D; @@ -1947,23 +2766,25 @@ void TFT_eSPI::readAddrWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_C; CS_L; - SPI.write(TFT_CASET); + tft_Write_8(TFT_CASET); + DC_D; - SPI.write32(xaw); + tft_Write_32(xaw); // Row addr set DC_C; - SPI.write(TFT_PASET); + tft_Write_8(TFT_PASET); DC_D; - SPI.write32(yaw); + tft_Write_32(yaw); DC_C; - SPI.transfer(TFT_RAMRD); // Read CGRAM command + tft_Write_8(TFT_RAMRD); // Read CGRAM command + DC_D; //spi_end(); @@ -2180,11 +3001,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_CASET); -#else - SPI.write(TFT_CASET); -#endif + tft_Write_8(TFT_CASET); DC_D; @@ -2192,7 +3009,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) 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); #else - SPI.write32(xaw); + tft_Write_32(xaw); #endif addr_col = x; @@ -2203,11 +3020,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) DC_C; -#if defined (RPI_ILI9486_DRIVER) - SPI.write16(TFT_PASET); -#else - SPI.write(TFT_PASET); -#endif + tft_Write_8(TFT_PASET); DC_D; @@ -2215,7 +3028,7 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) 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); #else - SPI.write32(yaw); + tft_Write_32(yaw); #endif addr_row = y; @@ -2223,15 +3036,11 @@ void TFT_eSPI::drawPixel(uint32_t x, uint32_t y, uint32_t color) 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); + tft_Write_16(color); CS_H; @@ -2251,7 +3060,7 @@ void TFT_eSPI::pushColor(uint16_t color) CS_L; - SPI.write16(color); + tft_Write_16(color); CS_H; @@ -2274,7 +3083,11 @@ void TFT_eSPI::pushColor(uint16_t color, uint16_t len) if(len) SPI.writePattern(&colorBin[0], 2, 1); len--; while(len--) {WR_L; WR_H;} #else - spiWriteBlock(color, len); + #ifdef ESP32_PARALLEL + while (len--) {tft_Write_16(color);} + #else + writeBlock(color, len); + #endif #endif CS_H; @@ -2282,73 +3095,9 @@ void TFT_eSPI::pushColor(uint16_t color, uint16_t len) spi_end(); } - /*************************************************************************************** ** Function name: pushColors -** Description: push an aray of pixels for BMP image drawing -***************************************************************************************/ -// 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) -{ - spi_begin(); - - 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; - - spi_end(); -} - - -/*************************************************************************************** -** 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 @@ -2359,15 +3108,18 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) 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); #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++;} #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 @@ -2377,14 +3129,115 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) } +/*************************************************************************************** +** 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(); + + CS_L; + +#if defined (ESP32) + #ifdef ESP32_PARALLEL + 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]; + + uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); + + SPI1U1 = (SPI1U1 & mask) | (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 = (SPI1U1 & mask) | (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 + + CS_H; + + spi_end(); +} + + /*************************************************************************************** ** Function name: drawLine ** 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) void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { @@ -2444,7 +3297,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); @@ -2467,6 +3319,8 @@ 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); + spi_begin(); + uint32_t mask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO)); mask = (SPI1U1 & mask) | (15 << SPILMOSI) | (15 << SPILMISO); SPI1U = SPIUMOSI | SPIUSSE; @@ -2485,7 +3339,7 @@ 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; @@ -2519,7 +3373,7 @@ 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; @@ -2536,7 +3390,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t while(SPI1CMD & SPIBUSY) {} setAddrWindow(x0+1, y0, _width, y0); SPI1U1 = mask; - SPI1W0 = swapped_color; + SPI1W0 = swapped_color; } } } @@ -2546,6 +3400,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t CS_H; spi_end(); } + #endif @@ -2564,7 +3419,7 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) setAddrWindow(x, y, x, y + h - 1); - spiWriteBlock(color, h); + writeBlock(color, h); CS_H; @@ -2585,17 +3440,21 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) #ifdef RPI_WRITE_STROBE #if defined (ESP8266) + // SPI1U1 will already be set to transfer 16 bits by setAddrWindow() SPI1W0 = (color >> 8) | (color << 8); 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; @@ -2619,7 +3478,7 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) setAddrWindow(x, y, x + w - 1, y); - spiWriteBlock(color, w); + writeBlock(color, w); CS_H; @@ -2639,17 +3498,21 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) #ifdef RPI_WRITE_STROBE #if defined (ESP8266) + // SPI1U1 will already be set to transfer 16 bits by setAddrWindow() SPI1W0 = (color >> 8) | (color << 8); 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; @@ -2673,7 +3536,7 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col spi_begin(); setAddrWindow(x, y, x + w - 1, y + h - 1); - spiWriteBlock(color, w * h); + writeBlock(color, w * h); CS_H; @@ -2695,11 +3558,23 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col 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; @@ -2718,6 +3593,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 @@ -2740,8 +3643,30 @@ size_t TFT_eSPI::write(uint8_t utf8) { if (utf8 == '\r') return 1; +#ifdef SMOOTH_FONT + if(fontLoaded) + { + uint16_t unicode = decodeUTF8(utf8); + if (!unicode) return 0; + + //fontFile = SPIFFS.open( _gFontFilename, "r" ); + + if(!fontFile) + { + fontLoaded = false; + return 0; + } + + drawGlyph(unicode); + + //fontFile.close(); + return 1; + } +#endif + uint8_t uniCode = utf8; // Work with a copy if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors + else if (utf8 < 32) return 0; uint16_t width = 0; uint16_t height = 0; @@ -2761,12 +3686,13 @@ size_t TFT_eSPI::write(uint8_t utf8) #ifdef LOAD_FONT2 if (textfont == 2) { + if (utf8 > 127) return 0; // This is 20us faster than using the fontdata structure (0.443ms per character instead of 0.465ms) width = pgm_read_byte(widtbl_f16 + uniCode-32); height = chr_hgt_f16; // Font 2 is rendered in whole byte widths so we must allow for this 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 @@ -2777,6 +3703,7 @@ size_t TFT_eSPI::write(uint8_t utf8) { if ((textfont>2) && (textfont<9)) { + if (utf8 > 127) return 0; // 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 ); @@ -2803,11 +3730,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 >= _height)) cursor_y = 0; cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont); } @@ -2821,28 +3749,27 @@ size_t TFT_eSPI::write(uint8_t utf8) 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 > (uint8_t)pgm_read_byte(&gfxFont->last )) return 0; + if (uniCode < (uint8_t)pgm_read_byte(&gfxFont->first)) return 0; - 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); + 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(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 >= _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 //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @@ -2853,7 +3780,7 @@ size_t TFT_eSPI::write(uint8_t utf8) /*************************************************************************************** ** Function name: drawChar -** Description: draw a unicode onto the screen +** Description: draw a Unicode onto the screen ***************************************************************************************/ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y) { @@ -2887,9 +3814,7 @@ 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_byte(&gfxFont->first)) && (uniCode <= pgm_read_byte(&gfxFont->last) )) { uint8_t c2 = uniCode - pgm_read_byte(&gfxFont->first); GFXglyph *glyph = &(((GFXglyph *)pgm_read_dword(&gfxFont->glyph))[c2]); @@ -2903,6 +3828,8 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) #endif } + if ((font>1) && (font<9) && ((uniCode < 32) || (uniCode > 127))) return 0; + int width = 0; int height = 0; uint32_t flash_address = 0; @@ -2936,7 +3863,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) int w = width; int pX = 0; int pY = y; - byte line = 0; + uint8_t line = 0; #ifdef LOAD_FONT2 // chop out code if we do not need it if (font == 2) { @@ -2945,6 +3872,8 @@ 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(); + inTransaction = true; for (int i = 0; i < height; i++) { @@ -2980,6 +3909,9 @@ 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 @@ -2987,7 +3919,7 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) spi_begin(); setAddrWindow(x, y, (x + w * 8) - 1, y + height - 1); - byte mask; + uint8_t mask; for (int i = 0; i < height; i++) { for (int k = 0; k < w; k++) @@ -2996,12 +3928,8 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) pX = x + k * 8; mask = 0x80; while (mask) { - if (line & mask) { - SPI.write16(textcolor); - } - else { - SPI.write16(textbgcolor); - } + if (line & mask) {tft_Write_16(textcolor);} + else {tft_Write_16(textbgcolor);} mask = mask >> 1; } } @@ -3028,16 +3956,16 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) 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 + 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++; @@ -3055,13 +3983,9 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) 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)) @@ -3100,7 +4024,11 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) 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 { @@ -3109,7 +4037,11 @@ int16_t TFT_eSPI::drawChar(unsigned int uniCode, int x, int y, int font) 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 } } @@ -3155,7 +4087,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int 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) { @@ -3165,7 +4097,7 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) baseline = cheight; padding =101; // Different padding method used for Free Fonts - // We need to make an adjustment for the botom of the string (eg 'y' character) + // 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; } @@ -3176,7 +4108,15 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) if (textdatum || padX) { - // If it is not font 1 (GLCD or free font) get the basline and pixel height of the font + // If it is not font 1 (GLCD or free font) get the baseline and pixel height of the font +#ifdef SMOOTH_FONT + if(fontLoaded) { + baseline = gFont.maxAscent; + cheight = fontHeight(0); + } + + else +#endif if (font!=1) { baseline = pgm_read_byte( &fontdata[font].baseline ) * textsize; cheight = fontHeight(font); @@ -3236,9 +4176,9 @@ 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; } @@ -3248,21 +4188,46 @@ int16_t TFT_eSPI::drawString(const char *string, int poX, int poY, int font) { 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); + uint8_t c2 = *string; + if((c2 >= pgm_read_byte(&gfxFont->first)) && (c2 <= pgm_read_byte(&gfxFont->last) )) + { + c2 -= 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 + 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); +#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; + uint16_t len = strlen(string); + uint16_t n = 0; + setCursor(poX, poY); + while (n < len) + { + uint16_t unicode = decodeUTF8((uint8_t*)string, &n, len - n); + drawGlyph(unicode); + } + sumX += cwidth; + //fontFile.close(); + } + else +#endif + while (*string) sumX += drawChar(*(string++), poX+sumX, poY, font); //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv DEBUG vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv // Switch on debugging for the padding areas @@ -3349,7 +4314,7 @@ int16_t TFT_eSPI::drawCentreString(const String& string, int dX, int poY, int fo int16_t TFT_eSPI::drawCentreString(const char *string, int dX, int poY, int font) { - static byte tempdatum = textdatum; + uint8_t tempdatum = textdatum; int sumX = 0; textdatum = TC_DATUM; sumX = drawString(string, dX, poY, font); @@ -3372,7 +4337,7 @@ int16_t TFT_eSPI::drawRightString(const String& string, int dX, int poY, int fon int16_t TFT_eSPI::drawRightString(const char *string, int dX, int poY, int font) { - static byte tempdatum = textdatum; + uint8_t tempdatum = textdatum; int16_t sumX = 0; textdatum = TR_DATUM; sumX = drawString(string, dX, poY, font); @@ -3544,8 +4509,14 @@ void TFT_eSPI::setTextFont(uint8_t f) ** Function name: spiBlockWrite ** 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) +void writeBlock(uint16_t color, uint32_t repeat) { uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; @@ -3583,6 +4554,9 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) SPI1U1 = mask | (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; @@ -3600,23 +4574,13 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) 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 #include "soc/spi_reg.h" #define SPI_NUM 0x3 -void spiWriteBlock(uint16_t color, uint32_t repeat) +void writeBlock(uint16_t color, uint32_t repeat) { uint16_t color16 = (color >> 8) | (color << 8); uint32_t color32 = color16 | color16 << 16; @@ -3649,333 +4613,152 @@ void spiWriteBlock(uint16_t color, uint32_t repeat) /*************************************************************************************** -** Function name: getTouchRaw -** Description: read raw position of touchpad if pressed. Return false if not pressed. +** Function name: getSetup +** Description: Get the setup details for diagnostic and sketch access ***************************************************************************************/ +void TFT_eSPI::getSetup(setup_t &tft_settings) +{ + +#if defined (ESP8266) + tft_settings.esp = 8266; +#elif defined (ESP32) + tft_settings.esp = 32; +#else + tft_settings.esp = -1; +#endif + +#if defined (SUPPORT_TRANSACTIONS) + tft_settings.trans = true; +#else + tft_settings.trans = false; +#endif + +#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; +#endif + +#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 + +#if defined (TFT_MISO) + tft_settings.pin_tft_miso = TFT_MISO; +#else + tft_settings.pin_tft_miso = -1; +#endif + +#if defined (TFT_SCLK) + tft_settings.pin_tft_clk = TFT_SCLK; +#else + tft_settings.pin_tft_clk = -1; +#endif + +#if defined (TFT_CS) + tft_settings.pin_tft_cs = TFT_CS; +#else + tft_settings.pin_tft_cs = -1; +#endif + +#if defined (TFT_DC) + tft_settings.pin_tft_dc = TFT_DC; +#else + tft_settings.pin_tft_dc = -1; +#endif + +#if defined (TFT_RD) + tft_settings.pin_tft_rd = TFT_RD; +#else + tft_settings.pin_tft_rd = -1; +#endif + +#if defined (TFT_WR) + tft_settings.pin_tft_wr = TFT_WR; +#else + tft_settings.pin_tft_wr = -1; +#endif + +#if defined (TFT_RST) + tft_settings.pin_tft_rst = TFT_RST; +#else + tft_settings.pin_tft_rst = -1; +#endif + +#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 - -uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ - uint16_t tmp; - CS_H; - T_CS_L; - -#ifdef SPI_HAS_TRANSACTION - #ifdef SUPPORT_TRANSACTIONS - if (locked) {locked = false; SPI.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} - #endif + #include "Extensions/Touch.cpp" + #include "Extensions/Button.cpp" #endif - SPI.setFrequency(SPI_TOUCH_FREQUENCY); - - // Start bit + YP sample request for x position - tmp = SPI.transfer(0xd0); - tmp = SPI.transfer(0); - tmp = tmp <<5; - tmp |= 0x1f & (SPI.transfer(0)>>3); - - if(tmp == 0 || tmp == 0x3ff){ - T_CS_H; - SPI.setFrequency(SPI_FREQUENCY); - spi_end(); - return false; - } - - *x = tmp; - - // Start bit + XP sample request for y position - SPI.transfer(0x90); - tmp = SPI.transfer(0); - tmp = tmp <<5; - tmp |= 0x1f & (SPI.transfer(0)>>3); - - *y = tmp; - - T_CS_H; - SPI.setFrequency(SPI_FREQUENCY); - spi_end(); - - if(tmp == 0 || tmp == 0x3ff){ - return false; - } - return true; -} - -/*************************************************************************************** -** Function name: getTouch -** Description: read callibrated position of touchpad if pressed. Return false if not pressed. -***************************************************************************************/ -uint8_t TFT_eSPI::getTouch(uint16_t *x, uint16_t *y){ - uint8_t retVal; - uint16_t x_tmp, y_tmp; - - retVal = getTouchRaw(&x_tmp,&y_tmp); - if(!retVal) - return retVal; - - if(!touchCalibration_rotate){ - *x=(x_tmp-touchCalibration_x0)*_width/touchCalibration_x1; - *y=(y_tmp-touchCalibration_y0)*_height/touchCalibration_y1; - if(touchCalibration_invert_x) - *x = _width - *x; - if(touchCalibration_invert_y) - *y = _height - *y; - } else { - *y=(x_tmp-touchCalibration_x0)*_height/touchCalibration_x1; - *x=(y_tmp-touchCalibration_y0)*_width/touchCalibration_y1; - if(touchCalibration_invert_x) - *x = _width - *x; - if(touchCalibration_invert_y) - *y = _height - *y; - } - - return retVal; -} - -/*************************************************************************************** -** Function name: calibrateTouch -** Description: generates calibration data for touchscreen. -***************************************************************************************/ -uint8_t TFT_eSPI::calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t color_fg, 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++){ - while(!getTouchRaw(&x_tmp, &y_tmp)) delay(100); - values[i*2 ] += x_tmp; - values[i*2+1] += y_tmp; - } - values[i*2 ] /= 8; - values[i*2+1] /= 8; - } - - - - // check orientation - // from case 0 to case 1, the y value changed. - // If the meassured 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_x1 = (values[0] + values[4])/2; // calc min x - touchCalibration_x0 = (values[2] + values[6])/2; // calc max x - touchCalibration_y1 = (values[1] + values[3])/2; // calc min y - touchCalibration_y0 = (values[5] + values[7])/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 opposit 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; - - // export data, if pointer valid - if(data != NULL){ - data[0] = touchCalibration_x0; - data[1] = touchCalibration_x1; - data[2] = touchCalibration_y0; - data[3] = touchCalibration_y1; - data[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2); - } -} - - -/*************************************************************************************** -** Function name: setTouch -** Description: imports calibration data for touchscreen. -***************************************************************************************/ -void TFT_eSPI::setTouch(uint16_t *data){ - touchCalibration_x0 = data[0]; - touchCalibration_x1 = data[1]; - touchCalibration_y0 = data[2]; - touchCalibration_y1 = data[3]; - - touchCalibration_rotate = data[4] & 0x01; - touchCalibration_invert_x = data[4] & 0x02; - touchCalibration_invert_y = data[4] & 0x04; -} +#include "Extensions/Sprite.cpp" +#ifdef SMOOTH_FONT + #include "Extensions/Smooth_font.cpp" #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 +//////////////////////////////////////////////////////////////////////////////////////// - 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. - - The library would not have been created without the initial inspiration from - Adafruit_ILI9341 and Adafruit_GFX libraries. - - - If any other conditions of use have been missed then please raise this as an - issue on GitHub: - - -/*************************************************** - The Adafruit_ILI9341 library has been used as a starting point - for this library. - - ORIGINAL LIBRARY HEADER - - 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 - - ****************************************************/ - - -/**************************************************** - - Some member funtions have been imported from the Adafruit_GFX - library. The license associated with these is reproduced below. - - ORIGINAL LIBRARY HEADER from Adafruit_GFX.cpp - - 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). - - Adafruit invests time and resources providing this open source code, please - support Adafruit & open-source hardware by purchasing products from Adafruit! - - Copyright (c) 2013 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. - - ****************************************************/ - - -/**************************************************** - - In compliance with the licence.txt file for the Adafruit_GFX library the - following is included. - - 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 d3a37da..75362a9 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 @@ -25,11 +21,28 @@ // 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_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 +77,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,17 +92,50 @@ #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 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) && defined (D0_USED_FOR_DC) + #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 + #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 + #if TFT_DC >= 0 + #define DC_C GPIO.out_w1ts = (1 << TFT_DC); \ + GPIO.out_w1tc = (1 << TFT_DC) + #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ + GPIO.out_w1ts = (1 << TFT_DC) + #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) @@ -98,10 +150,25 @@ #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 + #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 + #if TFT_CS >= 0 + #define CS_L GPIO.out_w1ts = (1 << TFT_CS);GPIO.out_w1tc = (1 << TFT_CS) + #define CS_H GPIO.out_w1tc = (1 << TFT_CS);GPIO.out_w1ts = (1 << TFT_CS) + #else + #define CS_L + #define CS_H + #endif + #endif + #endif #else #define CS_L GPOC=cspinmask #define CS_H GPOS=cspinmask @@ -113,23 +180,76 @@ #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) + #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 + +#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 (RPI_ILI9486_DRIVER) + #define tft_Write_8(C) SPI.transfer(0); SPI.transfer(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_32(C) SPI.write32(C) + +#else + #define tft_Write_8(C) SPI.transfer(C) + #define tft_Write_16(C) SPI.write16(C) + #define tft_Write_32(C) SPI.write32(C) + +#endif + #ifdef LOAD_GFXFF // We can include all the free fonts and they will only be built into // the sketch if they are used @@ -241,18 +361,78 @@ #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 + #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 +{ +int16_t esp; +uint8_t trans; +uint8_t serial; +uint8_t overlap; + +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 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; @@ -262,50 +442,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 { @@ -313,27 +495,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(uint32_t x, uint32_t y, uint32_t color), + drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size), + drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), + drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), + drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), + fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); - 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(unsigned int uniCode, int x, int y, int font), + drawChar(unsigned int uniCode, int x, int y), + height(void), + width(void); + // The TFT_eSprite class inherits the following functions + void setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1), pushColor(uint16_t color), pushColor(uint16_t color, uint16_t len), - - pushColors(uint16_t *data, uint8_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), @@ -352,6 +538,9 @@ class TFT_eSPI : public Print { 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 c, uint16_t b), // For 1bpp sprites setCursor(int16_t x, int16_t y), setCursor(int16_t x, int16_t y, uint8_t font), @@ -359,7 +548,7 @@ class TFT_eSPI : public Print { 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), @@ -373,6 +562,7 @@ 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); @@ -388,23 +578,43 @@ class TFT_eSPI : public Print { // 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); + // These are used to render images or sprites stored in RAM arrays + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data, uint16_t transparent); + + // These are used to render images stored in FLASH (PROGMEM) + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transparent); + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data); + + // These are used by pushSprite for 1 and 8 bit colours + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, bool bpp8 = true); + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true); + + // 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); uint16_t fontsLoaded(void), - color565(uint8_t r, uint8_t g, uint8_t b); + color565(uint8_t r, uint8_t g, uint8_t b), + color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits - 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), + int16_t drawNumber(long long_num,int poX, int poY, int font), drawNumber(long long_num,int poX, int poY), drawFloat(float floatNumber,int decimal,int poX, int poY, int font), drawFloat(float floatNumber,int decimal,int poX, int poY), - + // Handle char arrays drawString(const char *string, int poX, int poY, int font), drawString(const char *string, int poX, int poY), @@ -416,90 +626,90 @@ class TFT_eSPI : public Print { 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), + + int16_t textWidth(const char *string, int font), textWidth(const char *string), textWidth(const String& string, int font), textWidth(const String& string), fontHeight(int16_t font); - void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); + void setAddrWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); -#ifdef TOUCH_CS - uint8_t getTouch(uint16_t *x, uint16_t *y); - uint8_t getTouchRaw(uint16_t *x, uint16_t *y); - uint8_t calibrateTouch(uint16_t *data, uint32_t color_bg, uint32_t color_fg, uint8_t size); - void setTouch(uint16_t *data); -#endif - virtual size_t write(uint8_t); + size_t write(uint8_t); - private: + void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate -inline void spi_begin() __attribute__((always_inline)); -inline void spi_end() __attribute__((always_inline)); + int32_t cursor_x, cursor_y, padX; + uint32_t textcolor, textbgcolor; - 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 + uint32_t bitmap_fg, bitmap_bg; - volatile uint32_t *dcport, *csport;//, *mosiport, *clkport, *rsport; - - uint32_t cspinmask, dcpinmask, wrpinmask;//, mosipinmask, clkpinmask; - - uint32_t lastColor = 0xFFFF; - -#ifdef TOUCH_CS - uint16_t touchCalibration_x0, touchCalibration_x1, touchCalibration_y0, touchCalibration_y1; - uint8_t touchCalibration_rotate, touchCalibration_invert_x, touchCalibration_invert_y; -#endif - - protected: - - 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 + private: - boolean locked, inTransaction; // Transaction and mutex lock flags for ESP32 + inline void spi_begin() __attribute__((always_inline)); + inline void spi_end() __attribute__((always_inline)); + + 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 + + volatile uint32_t *dcport, *csport; + + uint32_t cspinmask, dcpinmask, wrpinmask; + +#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; + + uint32_t _init_width, _init_height; // Display w/h as input, used by setRotation() + uint32_t _width, _height; // Display w/h as modified by current rotation + uint32_t addr_row, addr_col; + + uint32_t fontsloaded; + + uint8_t glyph_ab, // glyph height above baseline + glyph_bb; // glyph height below baseline + + 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 + + int32_t _lastColor; #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..1363b6b --- /dev/null +++ b/Tools/Create_Smooth_Font/Create_font/Create_font.pde @@ -0,0 +1,489 @@ +// This is a Processing sketch, see https://processing.org/ to download the IDE + +// Select the character range in the user configure section starting at line 100 + +/* +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 + +// See comments below in code for specifying the font parameters +// (point size, unicode blocks to include etc). Ranges of characers or +// specific individual unicodes can be included in the created font file/ + +// Created fonts are saved in the sketches "FontFiles" folder. Press Ctrl+K to +// see that folder. + +// 16 bit unicodes in the range 0x0000 - 0xFFFF are supported. + +// 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 only include the characters you will use. +// Characters at the start of the file will render faster than those at the end. + +// Once created the files must be loaded into the ESP32 or ESP8266 SPIFFS memory +// using the Arduino IDE plugin detailed here: +// https://github.com/esp8266/arduino-esp8266fs-plugin +// https://github.com/me-no-dev/arduino-esp32fs-plugin + +// The sketch list all the available PC fonts to the console, you may need to increase +// console line count (in preferences.txt) to stop some fonts scrolling out of view. +// See link in File>Preferences to locate "preferences.txt" file. You must close +// Processing then edit the file lines. If Processing is not closed first then the +// edits will be overwritten by defaults! Edit "preferences.txt" as follows for +// 1000 lines, then save, then run Processing again: + + /* + console.length=1000 // Line 4 in file + console.scrollback.lines=1000 // 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 + + */ +//////////////////////////////////////////////////////////////////////////////////////////////// + +import java.awt.Desktop; + +// >>>>>>>>>> USER CONFIGURED PARAMETERS START HERE <<<<<<<<<< + + +// Use font name for ttf files placed in the "Data" folder or the font number seen in IDE Console for system fonts +// the font numbers are listed when the sketch is run. +// | 1 2 | Maximum filename size for SPIFFS is 32 including leading / +// 1234567890123456789012345 and added point size and .vlw extension, so max is 25 +String fontName = "Final-Frontier"; //Manually crop the filename length later after creation if needed + +String fontType = ".ttf"; //SPIFFS does not accept underscore in filename! +//String fontType = ".otf"; + +// Use font number instead of name, -1 means use name above, or a value >=0 means use system font number from list. +int fontNumber = -1; // << Use [Number] in brackets from the fonts listed in console window + +// Define the font size in points for the created font file +int fontSize = 28; + +// 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 specific individual Unicodes to be included (appended at end of selected range) +static final int[] specificUnicodes = { + + // Commonly used codes, add or remove // in next line + // 0x00A3, 0x00B0, 0x00B5, 0x03A9, 0x20AC, // £ ° µ Ω € + + // Numbers and characters for showing time, change next line to //* to use + /* + 0x002B, 0x002D, 0x002E, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, // - + . 0 1 2 3 4 + 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x0061, 0x006D, // 5 6 7 8 9 : a m + 0x0070, // p + //*/ + + // More characters, change next line to //* to use + /* + 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; + +void setup() { + + size(1000, 800); + + // Print the available fonts to the console as a list: + String[] fontList = PFont.list(); + printArray(fontList); + + // 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 range specified + for (int i = 0; i < specificUnicodes.length; i++) { + charset[index] = Character.toChars(specificUnicodes[i])[0]; + index++; + } + + // Make font smooth + boolean smooth = true; + + // Create the font in memory + myFont = createFont(fontName+fontType, displayFontSize, smooth, charset); + + // Print a few 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 letter 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 + 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"); + } +} \ No newline at end of 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 70f798a..782b71d 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -4,8 +4,9 @@ // 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 // ################################################################################## // @@ -14,11 +15,23 @@ // ################################################################################## // Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER +#define ILI9341_DRIVER //#define ST7735_DRIVER //#define ILI9163_DRIVER //#define S6D02A1_DRIVER -#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9488_DRIVER +//#define ST7789_DRIVER + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -31,14 +44,10 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display //#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 @@ -46,13 +55,13 @@ // ################################################################################## // 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) @@ -60,8 +69,10 @@ // // 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. // @@ -73,26 +84,93 @@ // 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 TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin //#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -#define TOUCH_CS D4 // Chip select pin (T_CS) of touch screen +//#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 +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP -// 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 +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -112,18 +190,23 @@ // ################################################################################## // 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 +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -137,26 +220,33 @@ // // ################################################################################## -// 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 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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 -// #define SUPPORT_TRANSACTIONS +// 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 3d8c600..fe14441 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 @@ -27,8 +30,20 @@ //#include // Setup file configured for my ST7735 128x128 display //#include // Setup file configured for my ILI9163 128x128 display //#include // Setup file configured for my ST7735 +//#include // Setup file configured for ESP8266 and RPi TFT with touch +//#include // Setup file configured for ESP32 and RPi TFT with touch +//#include // Setup file for the ESP32 based M5Stack +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file configured for HX8357D (untested) +//#include // Setup file for the ESP32 with parallel bus TFT +//#include // Setup file for any Waveshare ePaper display +//#include // Setup file configured for HX8357D (untested) -//#include // Setup file template for copying/editting +//#include + + +#endif // USER_SETUP_LOADED @@ -43,33 +58,59 @@ // 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 + #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 (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 +// Name GPIO Function +#define PIN_D0 16 // WAKE +#define PIN_D1 5 // User purpose +#define PIN_D2 4 // User purpose +#define PIN_D3 0 // FLASH mode at boot time +#define PIN_D4 2 // TXD1 (Note: low on boot means go to FLASH mode) +#define PIN_D5 14 // HSCLK +#define PIN_D6 12 // HMISO +#define PIN_D7 13 // HMOSI RXD2 +#define PIN_D8 15 // HCS TXD0 +#define PIN_D9 3 // RXD0 +#define PIN_D10 1 // TXD0 -#define PIN_MOSI 8 -#define PIN_MISO 7 -#define PIN_SCLK 6 -#define PIN_HWCS 0 +#define PIN_MOSI 8 // SD1 +#define PIN_MISO 7 // SD0 +#define PIN_SCLK 6 // CLK +#define PIN_HWCS 0 // D3 -#define PIN_D11 9 -#define PIN_D12 10 \ No newline at end of file +#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 index b572e0f..bbfe895 100644 --- a/User_Setups/Setup10_RPi_touch_ILI9486.h +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -4,7 +4,7 @@ // 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! // ################################################################################## @@ -19,7 +19,14 @@ //#define ILI9163_DRIVER //#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// to enable XPT2046 touch controller, define TOUCH_CS + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try @@ -32,14 +39,10 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display //#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 @@ -47,13 +50,13 @@ // ################################################################################## // 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) @@ -61,8 +64,10 @@ // // 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. // @@ -74,26 +79,64 @@ // 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin //#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -#define TOUCH_CS D4 // Chip select pin (T_CS) of touch screen controller XPT2046 +//#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 +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP -// 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 +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -113,9 +156,9 @@ // ################################################################################## // 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 @@ -123,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -138,26 +186,33 @@ // // ################################################################################## -// 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 10000000 +#define SPI_FREQUENCY 20000000 // #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: #define SPI_TOUCH_FREQUENCY 2500000 // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup11_RPi_touch_ILI9486.h b/User_Setups/Setup11_RPi_touch_ILI9486.h new file mode 100644 index 0000000..cbb489b --- /dev/null +++ b/User_Setups/Setup11_RPi_touch_ILI9486.h @@ -0,0 +1,219 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER +//#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +//#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 15 // Chip select control pin +#define TFT_DC 2 // Data Command control pin +#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 +#define SPI_FREQUENCY 20000000 +// #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup12_M5Stack.h b/User_Setups/Setup12_M5Stack.h new file mode 100644 index 0000000..3439512 --- /dev/null +++ b/User_Setups/Setup12_M5Stack.h @@ -0,0 +1,218 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +#define ILI9341_DRIVER +//#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +//#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +#define TFT_MISO 19 +#define TFT_MOSI 23 +#define TFT_SCLK 18 +#define TFT_CS 14 // Chip select control pin +#define TFT_DC 27 // Data Command control pin +#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +#define TFT_BL 32 // LED back-light + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup13_ILI9481_Parallel.h b/User_Setups/Setup13_ILI9481_Parallel.h new file mode 100644 index 0000000..0de1ebd --- /dev/null +++ b/User_Setups/Setup13_ILI9481_Parallel.h @@ -0,0 +1,91 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Parallel bus is only supported on ESP32 +// Use ESP32 Parallel interface instead of SPI +#define ESP32_PARALLEL + +// Only define one driver, the other ones must be commented out +#define ILI9481_DRIVER + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// ESP32 pins used +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - 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 + + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + + diff --git a/User_Setups/Setup14_ILI9341_Parallel.h b/User_Setups/Setup14_ILI9341_Parallel.h new file mode 100644 index 0000000..d777264 --- /dev/null +++ b/User_Setups/Setup14_ILI9341_Parallel.h @@ -0,0 +1,91 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Parallel bus is only supported on ESP32 +// Use ESP32 Parallel interface instead of SPI +#define ESP32_PARALLEL + +// Only define one driver, the other ones must be commented out +#define ILI9341_DRIVER + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// ESP32 pins used for the parallel interface TFT +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - 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 + + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + + diff --git a/User_Setups/Setup15_HX8357D.h b/User_Setups/Setup15_HX8357D.h new file mode 100644 index 0000000..99ae1d6 --- /dev/null +++ b/User_Setups/Setup15_HX8357D.h @@ -0,0 +1,219 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER +//#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +#define HX8357D_DRIVER + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +// #define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup16_ILI9488_Parallel.h b/User_Setups/Setup16_ILI9488_Parallel.h new file mode 100644 index 0000000..bcaca48 --- /dev/null +++ b/User_Setups/Setup16_ILI9488_Parallel.h @@ -0,0 +1,91 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Parallel bus is only supported on ESP32 +// Use ESP32 Parallel interface instead of SPI +#define ESP32_PARALLEL + +// Only define one driver, the other ones must be commented out +#define ILI9488_DRIVER + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// ESP32 pins used +#define TFT_CS 33 // Chip select control pin +#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +#define TFT_RST 32 // Reset pin + +#define TFT_WR 4 // Write strobe control pin - 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 + + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + + diff --git a/User_Setups/Setup17_ePaper.h b/User_Setups/Setup17_ePaper.h new file mode 100644 index 0000000..3704cc5 --- /dev/null +++ b/User_Setups/Setup17_ePaper.h @@ -0,0 +1,94 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +#define EPD_DRIVER // ePaper driver + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + + +// READ THIS READ THIS READ THIS READ THIS READ THIS READ THIS +// Install the ePaper library for your own display size and type +// 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 // +// // +/////////////////////////////////////////////////////////////////// + + +// ################################################################################## +// +// Section 2. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 below, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Not used +// +// ################################################################################## + diff --git a/User_Setups/Setup18_ST7789.h b/User_Setups/Setup18_ST7789.h new file mode 100644 index 0000000..d532d0a --- /dev/null +++ b/User_Setups/Setup18_ST7789.h @@ -0,0 +1,252 @@ +// USER DEFINED SETTINGS +// Set driver type, fonts to be loaded, pins used and SPI control method etc +// +// See the User_Setup_Select.h file if you wish to be able to define multiple +// setups and then easily select which setup file is used by the compiler. +// +// If this file is edited correctly then all the library example sketches should +// run without the need to make any more changes for a particular hardware setup! +// Note that some sketches are designed for a particular TFT pixel width/height + +// ################################################################################## +// +// Section 0. Call up the right driver file and any options for it +// +// ################################################################################## + +// Only define one driver, the other ones must be commented out +//#define ILI9341_DRIVER +//#define ST7735_DRIVER +//#define ILI9163_DRIVER +//#define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI +//#define HX8357D_DRIVER +//#define ILI9481_DRIVER +//#define ILI9488_DRIVER +#define ST7789_DRIVER + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + +// ################################################################################## +// +// Section 1. Define the pins that are used to interface with the display here +// +// ################################################################################## + +// We must use hardware SPI, a minimum of 3 GPIO pins is needed. +// Typical setup for ESP8266 NodeMCU ESP-12 is : +// +// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) +// Display LED to NodeMCU pin VIN (or 5V, see below) +// Display SCK to NodeMCU pin D5 +// Display SDI/MOSI to NodeMCU pin D7 +// Display DC (RS/AO)to NodeMCU pin D3 +// Display RESET to NodeMCU pin D4 (or RST, see below) +// Display CS to NodeMCU pin D8 (or GND, see below) +// Display GND to NodeMCU pin GND (0V) +// Display VCC to NodeMCU 5V or 3.3V +// +// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin +// +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// +// The NodeMCU D0 pin can be used for RST +// +// See Section 2. below if DC or CS is connected to D0 +// +// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin +// If 5V is not available at a pin you can use 3.3V but backlight brightness +// will be lower. + + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_DC PIN_D3 // Data Command control pin +#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) +//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### + +// The library supports 8 bit parallel TFTs with the ESP32, the pin +// selection below is compatible with ESP32 boards in UNO format. +// Wemos D32 boards need to be modified, see diagram in Tools folder. +// Only ILI9481 and ILI9341 based displays have been tested! + +// Parallel bus is only supported on ESP32 +// Uncomment line below to use ESP32 Parallel interface instead of SPI + +//#define ESP32_PARALLEL + +// The ESP32 and TFT the pins used for testing are: +//#define TFT_CS 33 // Chip select control pin (library pulls permanently low +//#define TFT_DC 15 // Data Command control pin - use a pin in the range 0-31 +//#define TFT_RST 32 // Reset pin, toggles on startup + +//#define TFT_WR 4 // Write strobe control pin - use a pin in the range 0-31 +//#define TFT_RD 2 // Read strobe control pin - use a pin in the range 0-31 + +//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus +//#define TFT_D1 13 // so a single register write sets/clears all bits. +//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect +//#define TFT_D3 25 // TFT screen update performance. +//#define TFT_D4 17 +//#define TFT_D5 16 +//#define TFT_D6 27 +//#define TFT_D7 14 + +// ################################################################################## +// +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) +// +// ################################################################################## + +// Normally the library uses direct register access for the DC and CS lines for speed +// If D0 (GPIO16) is used for CS or DC then a different slower method must be used +// Uncomment one line if D0 is used for DC or CS +// DC on D0 = 6% performance penalty at 40MHz SPI running graphics test +// CS on D0 = 2% performance penalty at 40MHz SPI running graphics test + +// #define D0_USED_FOR_DC +// #define D0_USED_FOR_CS + +// ################################################################################## +// +// Section 3. Define the fonts that are to be used here +// +// ################################################################################## + +// Comment out the #defines below with // to stop that font being loaded +// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not +// normally necessary. If all fonts are loaded the extra FLASH space required is +// about 17Kbytes. To save FLASH space only enable the fonts you need! + +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + +// ################################################################################## +// +// Section 4. Not used +// +// ################################################################################## + + +// ################################################################################## +// +// Section 5. Other options +// +// ################################################################################## + +// Define the SPI clock frequency, this affects the graphics rendering speed. Too +// fast and the TFT driver will not keep up and display corruption appears. +// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails +// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) +// With an ILI9163 display 27 MHz works OK. +// The RPi typically only works at 20MHz maximum. + +// #define SPI_FREQUENCY 1000000 +// #define SPI_FREQUENCY 5000000 +// #define SPI_FREQUENCY 10000000 +// #define SPI_FREQUENCY 20000000 +#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 +// #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS +// #define SPI_FREQUENCY 80000000 + +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + + +// Comment out the following #define if "SPI Transactions" do not need to be +// supported. When commented out the code size will be smaller and sketches will +// run slightly faster, so leave it commented out unless you need it! + +// Transaction support is needed to work with SD library but not needed with TFT_SdFat +// Transaction support is required if other SPI devices are connected. + +// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) +// so changing it here has no effect + +//#define SUPPORT_TRANSACTIONS diff --git a/User_Setups/Setup1_ILI9341.h b/User_Setups/Setup1_ILI9341.h index 82b0469..7eb6fba 100644 --- a/User_Setups/Setup1_ILI9341.h +++ b/User_Setups/Setup1_ILI9341.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -16,8 +16,14 @@ // 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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation //#define TFT_WIDTH 128 //#define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -32,6 +38,8 @@ //#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 @@ -42,13 +50,13 @@ // ################################################################################## // 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) @@ -56,8 +64,10 @@ // // 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. // @@ -69,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -105,9 +156,9 @@ // ################################################################################## // 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 @@ -115,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -130,23 +186,33 @@ // // ################################################################################## -// 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup2_ST7735.h b/User_Setups/Setup2_ST7735.h index 8f1c1c2..7f79ca8 100644 --- a/User_Setups/Setup2_ST7735.h +++ b/User_Setups/Setup2_ST7735.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -16,8 +16,14 @@ // 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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -33,6 +39,7 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display #define ST7735_REDTAB //#define ST7735_BLACKTAB @@ -43,13 +50,13 @@ // ################################################################################## // 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) @@ -57,8 +64,10 @@ // // 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. // @@ -70,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -106,9 +156,9 @@ // ################################################################################## // 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 @@ -116,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -131,23 +186,33 @@ // // ################################################################################## -// 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 // Maximum for my ST7735. It is actually 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup3_ILI9163.h b/User_Setups/Setup3_ILI9163.h index 56cfccd..e8bd1b2 100644 --- a/User_Setups/Setup3_ILI9163.h +++ b/User_Setups/Setup3_ILI9163.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -17,12 +17,32 @@ //#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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + // ################################################################################## // // Section 1. Define the pins that are used to interface with the display here @@ -30,13 +50,13 @@ // ################################################################################## // 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) @@ -44,8 +64,10 @@ // // 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. // @@ -57,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -93,9 +156,9 @@ // ################################################################################## // 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 @@ -103,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -118,24 +186,33 @@ // // ################################################################################## -// 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup4_S6D02A1.h b/User_Setups/Setup4_S6D02A1.h index 72a6fe4..0a1530b 100644 --- a/User_Setups/Setup4_S6D02A1.h +++ b/User_Setups/Setup4_S6D02A1.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -18,6 +18,30 @@ //#define ST7735_DRIVER //#define ILI9163_DRIVER #define S6D02A1_DRIVER +//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI + +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB // ################################################################################## // @@ -26,13 +50,13 @@ // ################################################################################## // 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) @@ -40,8 +64,10 @@ // // 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. // @@ -53,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -89,9 +156,9 @@ // ################################################################################## // 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 @@ -99,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -114,24 +186,33 @@ // // ################################################################################## -// 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup5_RPi_ILI9486.h b/User_Setups/Setup5_RPi_ILI9486.h index 5517041..c21e181 100644 --- a/User_Setups/Setup5_RPi_ILI9486.h +++ b/User_Setups/Setup5_RPi_ILI9486.h @@ -4,7 +4,7 @@ // 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! // ################################################################################## @@ -20,6 +20,14 @@ //#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +//#define TFT_WIDTH 128 +//#define TFT_HEIGHT 160 +//#define TFT_HEIGHT 128 + // For ST7735 ONLY, define the type of display, originally this was based on the // colour of the tab on the screen protector film but this is not always true, so try // out the different options below if the screen does not display graphics correctly, @@ -31,14 +39,10 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display //#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 @@ -46,13 +50,13 @@ // ################################################################################## // 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) @@ -60,8 +64,10 @@ // // 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. // @@ -73,25 +79,64 @@ // 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_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen -// 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_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -111,9 +156,9 @@ // ################################################################################## // 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 @@ -121,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -136,24 +186,33 @@ // // ################################################################################## -// 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 20000000 // #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup6_RPi_Wr_ILI9486.h b/User_Setups/Setup6_RPi_Wr_ILI9486.h index 2f1552a..e5c9303 100644 --- a/User_Setups/Setup6_RPi_Wr_ILI9486.h +++ b/User_Setups/Setup6_RPi_Wr_ILI9486.h @@ -4,7 +4,7 @@ // 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! // ################################################################################## @@ -20,7 +20,10 @@ //#define S6D02A1_DRIVER #define RPI_ILI9486_DRIVER // 20MHz maximum SPI -// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation //#define TFT_WIDTH 128 //#define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -36,6 +39,7 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display //#define ST7735_REDTAB //#define ST7735_BLACKTAB @@ -46,13 +50,13 @@ // ################################################################################## // 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) @@ -60,8 +64,10 @@ // // 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. // @@ -73,25 +79,64 @@ // 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_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen -// 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_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -111,9 +156,9 @@ // ################################################################################## // 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 @@ -121,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -136,24 +186,33 @@ // // ################################################################################## -// 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 20000000 // #define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3 // #define SPI_FREQUENCY 40000000 // Maximum to use SPIFFS // #define SPI_FREQUENCY 80000000 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup7_ST7735_128x128.h b/User_Setups/Setup7_ST7735_128x128.h index 6d9140e..3bb32cf 100644 --- a/User_Setups/Setup7_ST7735_128x128.h +++ b/User_Setups/Setup7_ST7735_128x128.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -16,8 +16,14 @@ // 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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 //#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 @@ -29,12 +35,12 @@ // 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_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 #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_REDTAB //#define ST7735_BLACKTAB // ################################################################################## @@ -44,7 +50,7 @@ // ################################################################################## // 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) @@ -58,10 +64,10 @@ // // 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) +// 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. // @@ -73,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -109,9 +156,9 @@ // ################################################################################## // 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 @@ -119,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -128,31 +180,39 @@ // ################################################################################## - - // ################################################################################## // // Section 5. 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 // Maximum for my ST7735. It is actually 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup8_ILI9163_128x128.h b/User_Setups/Setup8_ILI9163_128x128.h index f5d6607..05b7cb6 100644 --- a/User_Setups/Setup8_ILI9163_128x128.h +++ b/User_Setups/Setup8_ILI9163_128x128.h @@ -1,10 +1,10 @@ // 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 +// +// 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! // ################################################################################## @@ -17,12 +17,32 @@ //#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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 //#define TFT_HEIGHT 160 #define TFT_HEIGHT 128 +// For ST7735 ONLY, define the type of display, originally this was based on the +// colour of the tab on the screen protector film but this is not always true, so try +// out the different options below if the screen does not display graphics correctly, +// e.g. colours wrong, mirror images, or tray pixels at the edges. +// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this +// this User_Setup file, then rebuild and upload the sketch to the board again: + +//#define ST7735_INITB +//#define ST7735_GREENTAB +//#define ST7735_GREENTAB2 +//#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display +//#define ST7735_REDTAB +//#define ST7735_BLACKTAB + // ################################################################################## // // Section 1. Define the pins that are used to interface with the display here @@ -30,13 +50,13 @@ // ################################################################################## // 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) @@ -44,8 +64,10 @@ // // 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. // @@ -57,23 +79,64 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -93,9 +156,9 @@ // ################################################################################## // 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 @@ -103,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -118,24 +186,33 @@ // // ################################################################################## -// 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 40 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/Setup9_ST7735_Overlap.h b/User_Setups/Setup9_ST7735_Overlap.h index c1fb0c0..57f9019 100644 --- a/User_Setups/Setup9_ST7735_Overlap.h +++ b/User_Setups/Setup9_ST7735_Overlap.h @@ -1,16 +1,12 @@ // 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 +// +// 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! -// IMPORTANT -// This particular setup uses the SPI overlap capabiltiy of the ESP8266, this allows -// the FLASH SPI pins to be re-used with the TFT, saving pins for other functions. - // ################################################################################## // // Section 0. Call up the right driver file and any options for it @@ -20,8 +16,14 @@ // 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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation #define TFT_WIDTH 128 #define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -37,6 +39,7 @@ //#define ST7735_GREENTAB //#define ST7735_GREENTAB2 //#define ST7735_GREENTAB3 +//#define ST7735_GREENTAB128 // For 128 x 128 display #define ST7735_REDTAB //#define ST7735_BLACKTAB @@ -47,46 +50,93 @@ // ################################################################################## // We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for NodeMCU ESP-12 with SPI overlap is : +// Typical setup for ESP8266 NodeMCU ESP-12 is : // -// Display SDO/MISO to NodeMCU SD0 (or leave disconnected if not reading TFT) +// 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 CLK -// Display SDI/MOSI to NodeMCU pin SD1 -// Display DC (or AO)to NodeMCU pin D5 +// 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 D3 +// Display CS to NodeMCU pin D8 (or GND, see below) // Display GND to NodeMCU pin GND (0V) // Display VCC to NodeMCU 5V or 3.3V // // The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin // +// The DC (Data Command) pin may be labeled AO or RS (Register Select) +// +// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more +// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS +// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin +// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. +// // The NodeMCU D0 pin can be used for RST // -// See Section 2. below if DC is connected to D0 +// 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 -// Do not define TFT_CS in overlap mode, TFT chip select must connect to pin D3 +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### + +// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation +//#define TFT_CS PIN_D8 // Chip select control pin D8 +//#define TFT_DC PIN_D3 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +//#define TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 #define TFT_CS PIN_D3 #define TFT_DC PIN_D5 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V -// ESP32 Dev board -//#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) +// In ESP8266 overlap mode the following must be defined +#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -106,9 +156,9 @@ // ################################################################################## // 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 @@ -116,8 +166,13 @@ #define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm #define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -131,33 +186,33 @@ // // ################################################################################## -// 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 // Maximum for my ST7735. It is actually 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 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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 - -// If this next #define is not commented out then the SPI pins used by the program FLASH -// can be shared with the TFT, this frees up the HSPI SCK, MOSI and MISO pins. -// The TFT must be connected as follows for this to work: -// TFT Chip Select to GPIO0 (pin D3 on a NodeMCU) -// TFT MOSI/SDA to GPIO8/SDD1 (pin SD1 on a NodeMCU) -// TFT MISO to GPIO7/SDD0 (pin SD0 on a NodeMCU) - does not need to be connected -// TFT SCK to GPIO6/SDCLK (pin CLK on a NodeMCU) - -#define TFT_SPI_OVERLAP diff --git a/User_Setups/SetupX_Template.h b/User_Setups/SetupX_Template.h index cc28faa..8b22cbc 100644 --- a/User_Setups/SetupX_Template.h +++ b/User_Setups/SetupX_Template.h @@ -1,12 +1,10 @@ // 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! // ################################################################################## @@ -18,8 +16,14 @@ // 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 +// For M5Stack ESP32 module with integrated display ONLY, remove // in line below +//#define M5STACK + +// For ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation //#define TFT_WIDTH 128 //#define TFT_HEIGHT 160 //#define TFT_HEIGHT 128 @@ -34,6 +38,8 @@ //#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 @@ -44,13 +50,13 @@ // ################################################################################## // 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,8 +64,10 @@ // // 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. // @@ -71,23 +79,65 @@ // 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 -// 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 TOUCH_CS PIN_D1 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only + + +// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### + +// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact +// but saves pins for other functions. +// Use NodeMCU SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode + +// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 +//#define TFT_CS PIN_D3 +//#define TFT_DC PIN_D5 // Data Command control pin +//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V + +// In ESP8266 overlap mode the following must be defined +//#define TFT_SPI_OVERLAP + +// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### + +// For ESP32 Dev board (only tested with ILI9341 display) +// The hardware SPI can be mapped to any pins + +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 15 // Chip select control pin +//#define TFT_DC 2 // Data Command control pin +//#define TFT_RST 4 // Reset pin (could connect to RST pin) //#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST +//#define TOUCH_CS 22 // Chip select pin (T_CS) of touch screen + +//#define TFT_WR 21 // Write strobe for modified Raspberry Pi TFT only + +// For the M5Stack module use these #define lines +//#define TFT_MISO 19 +//#define TFT_MOSI 23 +//#define TFT_SCLK 18 +//#define TFT_CS 14 // Chip select control pin +//#define TFT_DC 27 // Data Command control pin +//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) +//#define TFT_BL 32 // LED back-light + + // ################################################################################## // -// Section 2. Define the way the DC and/or CS lines are driven +// Section 2. Define the way the DC and/or CS lines are driven (ESP8266 only) // // ################################################################################## @@ -107,18 +157,23 @@ // ################################################################################## // 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_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT #define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. #define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded +// this will save ~20kbytes of FLASH +#define SMOOTH_FONT + // ################################################################################## // // Section 4. Not used @@ -132,23 +187,34 @@ // // ################################################################################## -// 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 53400000 // #define SPI_FREQUENCY 80000000 +// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: +#define SPI_TOUCH_FREQUENCY 2500000 + // Comment out the following #define if "SPI Transactions" do not need to be -// supported. 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/examples/160 x 128/Flash_Bitmap2/Close.h b/examples/160 x 128/Flash_Bitmap2/Close.h index c16d522..ce676c9 100644 --- a/examples/160 x 128/Flash_Bitmap2/Close.h +++ b/examples/160 x 128/Flash_Bitmap2/Close.h @@ -6,7 +6,7 @@ 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={ +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/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino b/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino index 3cf517a..42099e9 100644 --- a/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino +++ b/examples/160 x 128/Flash_Bitmap2/Flash_Bitmap2.ino @@ -28,7 +28,7 @@ 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 "Alert.h" #include "Close.h" #include "Info.h" @@ -45,7 +45,7 @@ void setup() // 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); + drawIcon(closeX, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); // Pause here to admire the icons! delay(4000); @@ -57,7 +57,7 @@ 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); + drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); // Clear screen after 100 x 3 = 300 icons drawn if (100 == count++) { @@ -80,7 +80,7 @@ void loop() // 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) { +void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) diff --git a/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino b/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino index ce4dd80..313a2f6 100644 --- a/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino +++ b/examples/160 x 128/TFT_SPIFFS_Jpeg/JPEG_functions.ino @@ -79,15 +79,34 @@ void jpegRender(int xpos, int ypos) { pImg = JpegDec.pImage; // calculate where the image block should be drawn on the screen - int mcu_x = JpegDec.MCUx * mcu_w + xpos; + 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++; + } + } + } + // 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()) { diff --git a/examples/160 x 128/TFT_FLASH_Jpeg/TFT_FLASH_Jpeg.ino b/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino similarity index 94% rename from examples/160 x 128/TFT_FLASH_Jpeg/TFT_FLASH_Jpeg.ino rename to examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino index 7d0f662..7179945 100644 --- a/examples/160 x 128/TFT_FLASH_Jpeg/TFT_FLASH_Jpeg.ino +++ b/examples/160 x 128/TFT_flash_jpg/TFT_flash_jpg.ino @@ -130,12 +130,31 @@ 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++; + } + } + } + // 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()) { diff --git a/examples/160 x 128/TFT_FLASH_Jpeg/jpeg1.h b/examples/160 x 128/TFT_flash_jpg/jpeg1.h similarity index 100% rename from examples/160 x 128/TFT_FLASH_Jpeg/jpeg1.h rename to examples/160 x 128/TFT_flash_jpg/jpeg1.h diff --git a/examples/160 x 128/TFT_FLASH_Jpeg/jpeg2.h b/examples/160 x 128/TFT_flash_jpg/jpeg2.h similarity index 100% rename from examples/160 x 128/TFT_FLASH_Jpeg/jpeg2.h rename to examples/160 x 128/TFT_flash_jpg/jpeg2.h diff --git a/examples/160 x 128/TFT_FLASH_Jpeg/jpeg3.h b/examples/160 x 128/TFT_flash_jpg/jpeg3.h similarity index 100% rename from examples/160 x 128/TFT_FLASH_Jpeg/jpeg3.h rename to examples/160 x 128/TFT_flash_jpg/jpeg3.h diff --git a/examples/160 x 128/TFT_FLASH_Jpeg/jpeg4.h b/examples/160 x 128/TFT_flash_jpg/jpeg4.h similarity index 100% rename from examples/160 x 128/TFT_FLASH_Jpeg/jpeg4.h rename to examples/160 x 128/TFT_flash_jpg/jpeg4.h 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/Close.h b/examples/320 x 240/TFT_Flash_Bitmap/Close.h index b58ec12..dc2a4fd 100644 --- a/examples/320 x 240/TFT_Flash_Bitmap/Close.h +++ b/examples/320 x 240/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/TFT_Flash_Bitmap.ino b/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino index 081087c..82e09eb 100644 --- a/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino +++ b/examples/320 x 240/TFT_Flash_Bitmap/TFT_Flash_Bitmap.ino @@ -24,7 +24,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library // Include the header files that contain the icons -#include "alert.h" +#include "Alert.h" #include "Close.h" #include "Info.h" @@ -41,7 +41,7 @@ void setup() // Draw the icons drawIcon(info, 100, 100, infoWidth, infoHeight); drawIcon(alert, 140, 100, alertWidth, alertHeight); - drawIcon(close, 180, 100, closeWidth, closeHeight); + drawIcon(closeX, 180, 100, closeWidth, closeHeight); // Pause here to admire the icons! delay(2000); @@ -53,7 +53,7 @@ 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); + drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); // Clear screen after 100 x 3 = 300 icons drawn if (100 == count++) { @@ -76,7 +76,7 @@ void loop() // 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) { +void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) diff --git a/examples/320 x 240/weather-station-v8/ArialRoundedMtBold_14.h b/examples/320 x 240/weather-station/ArialRoundedMTBold_14.h similarity index 100% rename from examples/320 x 240/weather-station-v8/ArialRoundedMtBold_14.h rename to examples/320 x 240/weather-station/ArialRoundedMTBold_14.h diff --git a/examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h b/examples/320 x 240/weather-station/ArialRoundedMTBold_36.h similarity index 99% rename from examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h rename to examples/320 x 240/weather-station/ArialRoundedMTBold_36.h index 767147c..a171dbe 100644 --- a/examples/320 x 240/weather-station-v8/ArialRoundedMTBold_36.h +++ b/examples/320 x 240/weather-station/ArialRoundedMTBold_36.h @@ -22,7 +22,7 @@ See more at http://blog.squix.ch // 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 +// this avoids screen corruption if ~ is printed // Bodmer change: '`' changed to tiny degree symbol (typically this character is on top left key of a QWERTY keyboard) diff --git a/examples/320 x 240/weather-station-v8/GfxUi.cpp b/examples/320 x 240/weather-station/GfxUi.cpp similarity index 93% rename from examples/320 x 240/weather-station-v8/GfxUi.cpp rename to examples/320 x 240/weather-station/GfxUi.cpp index 4716da0..c425abb 100644 --- a/examples/320 x 240/weather-station-v8/GfxUi.cpp +++ b/examples/320 x 240/weather-station/GfxUi.cpp @@ -157,8 +157,13 @@ void GfxUi::drawBmp(String filename, uint8_t x, uint16_t y) { } // End of bitmap file check bmpFile.close(); - if(!goodBmp) Serial.println(F("BMP format not recognised.")); - _tft->setRotation(rotation); // Put back original rotation + + if(!goodBmp) { + Serial.print(F("BMP format not recognised. File:")); + Serial.println(filename); + } + else + _tft->setRotation(rotation); // Put back original rotation } // These read 16- and 32-bit types from the SD card file. @@ -270,30 +275,35 @@ void GfxUi::jpegRender(int xpos, int ypos) { 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 + // 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; - // calculate how many pixels must be drawn - uint32_t mcu_pixels = win_w * win_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()) - { -#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 + { + _tft->pushImage(mcu_x, mcu_y, win_w, win_h, pImg); } else if ( ( mcu_y + win_h) >= _tft->height()) JpegDec.abort(); diff --git a/examples/320 x 240/weather-station-v8/GfxUi.h b/examples/320 x 240/weather-station/GfxUi.h similarity index 100% rename from examples/320 x 240/weather-station-v8/GfxUi.h rename to examples/320 x 240/weather-station/GfxUi.h diff --git a/examples/320 x 240/weather-station-v8/SPIFFS_Support.ino b/examples/320 x 240/weather-station/SPIFFS_Support.ino similarity index 100% rename from examples/320 x 240/weather-station-v8/SPIFFS_Support.ino rename to examples/320 x 240/weather-station/SPIFFS_Support.ino diff --git a/examples/320 x 240/weather-station-v8/WebResource.cpp b/examples/320 x 240/weather-station/WebResource.cpp similarity index 100% rename from examples/320 x 240/weather-station-v8/WebResource.cpp rename to examples/320 x 240/weather-station/WebResource.cpp diff --git a/examples/320 x 240/weather-station-v8/WebResource.h b/examples/320 x 240/weather-station/WebResource.h similarity index 100% rename from examples/320 x 240/weather-station-v8/WebResource.h rename to examples/320 x 240/weather-station/WebResource.h diff --git a/examples/320 x 240/weather-station-v8/settings.h b/examples/320 x 240/weather-station/settings.h similarity index 78% rename from examples/320 x 240/weather-station-v8/settings.h rename to examples/320 x 240/weather-station/settings.h index 4a4618c..d4d97c2 100644 --- a/examples/320 x 240/weather-station-v8/settings.h +++ b/examples/320 x 240/weather-station/settings.h @@ -18,22 +18,30 @@ 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 +https://github.com/Bodmer/TFT_eSPI +Version 9 */ +// *************************************************************************************** +// WARNING - READ THIS +// +// 3M Flash Size MUST be allocated to SPIFFS using the IDE Tools menu option or else the +// ESP8266 may crash or do strange things (due to lack of error checks in SPIFFS library?) +// *************************************************************************************** +// // Setup const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes -// Pins for the TFT interface are defined in the User_Config.h file inside the TFT_ILI9341_ESP library +// Pins for the TFT interface are defined in the User_Config.h file inside the TFT_eSPI library // TimeClient settings const float UTC_OFFSET = 1; -// Wunderground Settings, EDIT TO SUIT YOUR LOCATION +// Wunderground Settings, EDIT to suit your Wunderground key and location const boolean IS_METRIC = true; // Temperature only? Wind speed units appear to stay in mph. To do: investigate <<<<<<<<<<<<<<<<<<<<<<<<< -const String WUNDERGRROUND_API_KEY = ""; -//const String WUNDERGRROUND_API_KEY = "1c265fajf48s0a82"; // Random key example showing how the above line should look +//const String WUNDERGRROUND_API_KEY = "WUNDERGROUND KEY HERE"; + const String WUNDERGRROUND_API_KEY = "1c265fajf48s0a82"; // Random key example showing how the above line should look // For language codes see https://www.wunderground.com/weather/api/d/docs?d=language-support&_ga=1.55148395.1951311424.1484425551 const String WUNDERGRROUND_LANGUAGE = "EN"; // Language EN = English @@ -53,8 +61,8 @@ const String WUNDERGROUND_CITY = "Base_Naval"; // City, "London", "FL/Boca_Raton #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 = ""; +const String THINGSPEAK_CHANNEL_ID = "CHANNEL_ID_HERE"; +const String THINGSPEAK_API_READ_KEY = "API_READ_KEY_HERE"; // List, so that the downloader knows what to fetch String wundergroundIcons [] = {"chanceflurries","chancerain","chancesleet","chancesnow","clear","cloudy","flurries","fog","hazy","mostlycloudy","mostlysunny","partlycloudy","partlysunny","rain","sleet","snow","sunny","tstorms","unknown"}; diff --git a/examples/320 x 240/weather-station-v8/weather-station-v8.ino b/examples/320 x 240/weather-station/weather-station.ino similarity index 99% rename from examples/320 x 240/weather-station-v8/weather-station-v8.ino rename to examples/320 x 240/weather-station/weather-station.ino index 4a84d28..ab3cfad 100644 --- a/examples/320 x 240/weather-station-v8/weather-station-v8.ino +++ b/examples/320 x 240/weather-station/weather-station.ino @@ -30,6 +30,7 @@ New smart WU splash startup screen and updated progress messages Display does not need to be blanked between updates Icons nudged about slightly to add wind direction + speed + Barometric pressure added */ #define SERIAL_MESSAGES diff --git a/examples/480 x 320/Flash_Bitmap/Close.h b/examples/480 x 320/Flash_Bitmap/Close.h index c16d522..ce676c9 100644 --- a/examples/480 x 320/Flash_Bitmap/Close.h +++ b/examples/480 x 320/Flash_Bitmap/Close.h @@ -6,7 +6,7 @@ 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={ +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/480 x 320/Flash_Bitmap/Flash_Bitmap.ino b/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino index 0329e5f..d3ca697 100644 --- a/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino +++ b/examples/480 x 320/Flash_Bitmap/Flash_Bitmap.ino @@ -31,7 +31,7 @@ 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 "Alert.h" #include "Close.h" #include "Info.h" @@ -48,7 +48,7 @@ void setup() // 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); + drawIcon(closeX, (tft.width() - closeWidth)/2 + 50, (tft.height() - closeHeight)/2, closeWidth, closeHeight); // Pause here to admire the icons! delay(4000); @@ -60,7 +60,7 @@ 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); + drawIcon(closeX, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight); // Clear screen after 100 x 3 = 300 icons drawn if (100 == count++) { @@ -83,7 +83,7 @@ void loop() // 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) { +void drawIcon(const unsigned short* icon, int16_t x, int16_t y, uint16_t width, uint16_t height) { uint16_t pix_buffer[BUFF_SIZE]; // Pixel buffer (16 bits per pixel) 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..5af0f13 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,12 +143,31 @@ 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; 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/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/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/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/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/1_bit_Sprite_Demo/1_bit_Sprite_Demo.ino b/examples/Sprite/1_bit_Sprite_Demo/1_bit_Sprite_Demo.ino new file mode 100644 index 0000000..dacf64f --- /dev/null +++ b/examples/Sprite/1_bit_Sprite_Demo/1_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/1_bit_Yin_Yang/1_bit_Yin_Yang.ino b/examples/Sprite/1_bit_Yin_Yang/1_bit_Yin_Yang.ino new file mode 100644 index 0000000..40fccb4 --- /dev/null +++ b/examples/Sprite/1_bit_Yin_Yang/1_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 + +int 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/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_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/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/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..45d48bf --- /dev/null +++ b/examples/Test and diagnostics/Read_User_Setup/Read_User_Setup.ino @@ -0,0 +1,151 @@ +/* + 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.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; +} + 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..a5cc6cb --- /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 56% rename from Keywords.txt rename to keywords.txt index 47a42a8..53b0825 100644 --- a/Keywords.txt +++ b/keywords.txt @@ -5,9 +5,8 @@ drawPixel KEYWORD2 drawChar KEYWORD2 setAddrWindow KEYWORD2 setWindow KEYWORD2 +readAddrWindow KEYWORD2 pushColor KEYWORD2 -pushColor KEYWORD2 -pushColors KEYWORD2 pushColors KEYWORD2 fillScreen KEYWORD2 writeBegin KEYWORD2 @@ -30,9 +29,10 @@ 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 @@ -49,11 +49,16 @@ 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 @@ -64,3 +69,44 @@ width KEYWORD2 textWidth KEYWORD2 fontHeight KEYWORD2 +getTouchRaw KEYWORD2 +getTouchRawZ KEYWORD2 +getTouch KEYWORD2 +calibrateTouch KEYWORD2 +setTouch KEYWORD2 +validTouch 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 +deleteSprite 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 4cfc6a5..a8f6f7f 100644 --- a/library.json +++ b/library.json @@ -1,8 +1,8 @@ { "name": "TFT_eSPI", - "version": "0.16.15", - "keywords": "TFT, ESP8266, NodeMCU, ESP32, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486", - "description": "A TFT SPI graphics library for ESP8266", + "version": "0.20.15", + "keywords": "tft, ePaper, display, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789", + "description": "A TFT and ePaper SPI graphics library for ESP8266 and ESP32", "repository": { "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 b35285f..a2a4eb1 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=0.16.15 +version=0.20.15 author=Bodmer maintainer=Bodmer sentence=A fast TFT library for ESP8266 processors and the Arduino IDE 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^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^