From 93ba6e3716fab6c2dd80fd55e4702352da4c29a1 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Sun, 10 Dec 2017 23:04:31 +0000 Subject: [PATCH] Add scrolling inside a sprite Added example "Sprite_scroll" Tidy up virtual function list Add PROGMEM bitmap image functions --- Keywords.txt | 4 +- TFT_eSPI.cpp | 274 +++++++++++++++--- TFT_eSPI.h | 86 ++++-- .../Sprite/Sprite_scroll/Sprite_scroll.ino | 118 ++++++++ library.json | 2 +- library.properties | 2 +- 6 files changed, 420 insertions(+), 66 deletions(-) create mode 100644 examples/Sprite/Sprite_scroll/Sprite_scroll.ino diff --git a/Keywords.txt b/Keywords.txt index 97f9b28..86f33fb 100644 --- a/Keywords.txt +++ b/Keywords.txt @@ -50,7 +50,7 @@ readcommand32 KEYWORD2 readPixel KEYWORD2 readRect KEYWORD2 pushRect KEYWORD2 -pushSprite KEYWORD2 +pushImage KEYWORD2 readRectRGB KEYWORD2 getRotation KEYWORD2 getTextDatum KEYWORD2 @@ -97,3 +97,5 @@ fillSprite KEYWORD2 setWindow KEYWORD2 pushBitmap KEYWORD2 pushSprite KEYWORD2 +setScrollRect KEYWORD2 +scroll KEYWORD2 diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 70939c2..641874a 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -535,10 +535,10 @@ void TFT_eSPI::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t /*************************************************************************************** -** Function name: push sprite -** Description: plot 16 bit sprite in a defined area with clipping +** Function name: pushImage +** Description: plot 16 bit colour sprite or image onto TFT ***************************************************************************************/ -void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data) { if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; @@ -587,10 +587,10 @@ void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t } /*************************************************************************************** -** Function name: push sprite -** Description: plot 16 bit sprite with 1 colour being transparent +** Function name: pushImage +** Description: plot 16 bit sprite or image with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data, uint16_t transp) +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t *data, uint16_t transp) { if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; @@ -643,12 +643,75 @@ void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t spi_end(); } +//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< TEMPORARY TEST +/*************************************************************************************** +** Function name: pushImage - for FLASH (PROGMEM) stored images +** 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, const uint16_t *data, uint16_t transp, bool swap) +{ + // Swap=true swaps the two bytes in the color to cater for big+little endian formats + // default is false if parameter is missing + + 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(); + + data += dx + dy * w; + + int32_t xe = x + dw - 1, ye = y + dh - 1; + + if (swap) transp = transp >> 8 | transp << 8; + + while (dh--) + { + int32_t len = dw; + uint16_t* ptr = (uint16_t*)data; + int32_t px = x; + boolean move = true; + + while (len--) + { + uint16_t color = pgm_read_word(ptr); + if (transp != color) + { + if (move) { move = false; setAddrWindow(px, y, xe, ye); } + if (swap) color = color>>8 | color<<8; + SPI.write16(color); + } + else move = true; + px++; + ptr++; + } + + y++; + data += w; + } + + CS_H; + + spi_end(); +} + /*************************************************************************************** -** Function name: push sprite -** Description: plot 8 bit sprite with clipping using a line buffer +** Function name: pushImage +** Description: plot 8 bit image or sprite using a line buffer ***************************************************************************************/ -void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data) +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data) { if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; @@ -716,10 +779,10 @@ void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t /*************************************************************************************** -** Function name: push sprite -** Description: plot 8 bit sprite with 1 colour being transparent +** Function name: pushImage +** Description: plot 8 bit image or sprite with 1 colour being transparent ***************************************************************************************/ -void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data, uint8_t transp) +void TFT_eSPI::pushImage(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data, uint8_t transp) { if ((x >= (int32_t)_width) || (y >= (int32_t)_height)) return; @@ -2945,7 +3008,7 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) ** Description: draw a filled rectangle ***************************************************************************************/ #if defined (ESP8266) && !defined (RPI_WRITE_STROBE) -void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) +void TFT_eSPI::fillRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color) { // rudimentary clipping (drawChar w/big text requires this) if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; @@ -2964,7 +3027,7 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col #else -void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) +void TFT_eSPI::fillRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color) { // rudimentary clipping (drawChar w/big text requires this) if ((x > _width) || (y > _height) || (w < 1) || (h < 1)) return; @@ -4368,23 +4431,42 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft) ** Function name: createSprite ** Description: Create a sprite (bitmap) of defined width and height *************************************************************************************x*/ -void TFT_eSprite::createSprite(int16_t w, int16_t h) +// returns a uint8_t* pointer, cast returned value to (uint16_t*) for 16 bit colours +uint8_t* TFT_eSprite::createSprite(int16_t w, int16_t h) { - if ( w < 1 || h < 1 || _created) return; + if ( w < 1 || h < 1 || _created) return NULL; _iwidth = w; _iheight = h; + _sx = 0; + _sy = 0; + _sw = w; + _sh = h; + _scolor = TFT_BLACK; + if(_bpp16) { _img = (uint16_t*) malloc(w * h * 2); - if (_img) _created = true; + if (_img) + { + _created = true; + fillSprite(TFT_BLACK); + return (uint8_t*)_img; + } } else { _img8 = ( uint8_t*) malloc(w * h); - if (_img8) _created = true; + if (_img8) + { + _created = true; + fillSprite(TFT_BLACK); + return _img8; + } } + + return NULL; } @@ -4437,8 +4519,8 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y) { if (!_created ) return; - if (_bpp16) _tft->pushSprite(x, y, _iwidth, _iheight, _img ); - else _tft->pushSprite(x, y, _iwidth, _iheight, _img8); + if (_bpp16) _tft->pushImage(x, y, _iwidth, _iheight, _img ); + else _tft->pushImage(x, y, _iwidth, _iheight, _img8); } @@ -4450,11 +4532,11 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) { if (!_created ) return; - if (_bpp16) _tft->pushSprite(x, y, _iwidth, _iheight, _img, transp ); + if (_bpp16) _tft->pushImage(x, y, _iwidth, _iheight, _img, transp ); else { transp = (uint8_t)((transp & 0xE000)>>8 | (transp & 0x0700)>>6 | (transp & 0x0018)>>3); - _tft->pushSprite(x, y, _iwidth, _iheight, _img8, (uint8_t) transp); + _tft->pushImage(x, y, _iwidth, _iheight, _img8, (uint8_t) transp); } } @@ -4486,10 +4568,10 @@ uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y) /*************************************************************************************** -** Function name: pushRect (same as pushBitmap) -** Description: push 565 colour bitmap into a defined area +** Function name: pushImage +** Description: push 565 colour bitmap image into a defined area *************************************************************************************x*/ -void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +void TFT_eSprite::pushImage(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) { if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0) || !_created) return; @@ -4518,12 +4600,37 @@ void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint /*************************************************************************************** -** Function name: pushBitmap (same as pushRect) -** Description: push 565 colour bitmap into a defined area -***************************************************************************************/ -void TFT_eSprite::pushBitmap(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data) +** Function name: pushImage +** Description: push 565 colour FLASH (PROGMEM) image into a defined area +*************************************************************************************x*/ +void TFT_eSprite::pushImage(uint32_t x, uint32_t y, uint32_t w, uint32_t h, const uint16_t *data, bool swap) { - pushRect(x, y, w, h, data); + if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0) || !_created) return; + + if (_bpp16) + { + 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(!swap) color = color<<8 | color>>8; + _img[xp + yp * _iwidth] = color; + } + } + } + else + { + 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(swap) color = color<<8 | color>>8; + _img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3); + } + } + } } @@ -4629,6 +4736,99 @@ void TFT_eSprite::writeColor(uint16_t color) } +/*************************************************************************************** +** Function name: setScrollRect +** Description: Set scroll area within the sprite and the gap fill colour +*************************************************************************************x*/ +void TFT_eSprite::setScrollRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint16_t color) +{ + 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 wodth 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 (_bpp16) + { + while (h--) + { // move pixel lines (to, from, byte count) + memmove( _img + typ, _img + fyp, w<<1); + typ += iw; + fyp += iw; + } + } + else + { + while (h--) + { // move pixel lines (to, from, byte count) + memmove( _img8 + typ, _img8 + fyp, w); + typ += iw; + fyp += iw; + } + } + + // 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 @@ -4964,7 +5164,7 @@ void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) ** 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) +void TFT_eSprite::fillRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color) { if (!_created ) return; @@ -4975,17 +5175,19 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t if ((y + h) > _iheight) h = _iheight - y; if ((w < 1) || (h < 1)) return; - int32_t yp = _iwidth * y; + int32_t yp = _iwidth * y + x; if (_bpp16) { 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--) { - uint32_t ix = x, iw = w; - while (iw--) _img[yp + ix++] = (uint16_t) color; yp += _iwidth; + memcpy( _img+yp, _img+ys, w<<1); } } else @@ -4993,7 +5195,7 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3; while (h--) { - memset(_img8 + yp + x, (uint8_t)color, w); + memset(_img8 + yp, (uint8_t)color, w); yp += _iwidth; } } diff --git a/TFT_eSPI.h b/TFT_eSPI.h index ef4ecf8..ae7f3c0 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -334,22 +334,20 @@ class TFT_eSPI : public Print { // 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 font), - setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1), - pushColor(uint16_t color), - pushColor(uint16_t color, uint16_t len), + 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); + fillRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color); virtual int16_t drawChar(unsigned int uniCode, int x, int y, int font), - drawChar(unsigned int uniCode, int x, int y), - height(void), - width(void); + drawChar(unsigned int uniCode, int x, int y); // The TFT_eSprite class inherits the following functions - void pushColors(uint16_t *data, uint8_t len), + 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(uint8_t *data, uint32_t len), fillScreen(uint32_t color); @@ -408,10 +406,16 @@ class TFT_eSPI : public Print { void readRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); // Write a block of pixels to the screen void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); - void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data); - void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data); - void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data, uint16_t transparent); - void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, uint8_t transparent); + + // These are used by pushSprite and can also be used to push bitmap images to the screen + // "565" 16 bit and "332" 8 bit colour encodings are supported + 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, uint8_t *data); + // The next two support a "transparent" colour so those image areas are not rendered + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data, uint16_t transparent); + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data, uint8_t transparent); + // This one has an optional flag to swap byte order in colours + void pushImage(int32_t x0, int32_t y0, uint32_t w, uint32_t h, const uint16_t *data, uint16_t transparent, bool swap = false); // 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 @@ -441,7 +445,9 @@ class TFT_eSPI : public Print { 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 textWidth(const char *string, int font), + int16_t height(void), + width(void), + textWidth(const char *string, int font), textWidth(const char *string), textWidth(const String& string, int font), textWidth(const String& string), @@ -564,10 +570,16 @@ class TFT_eSprite : public TFT_eSPI { TFT_eSprite(TFT_eSPI *tft); - void createSprite(int16_t w, int16_t y); // 2 bytes per pixel + // 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 + uint8_t* createSprite(int16_t width, int16_t height); + // Delete the sprite to free up the RAM void deleteSprite(void); + // Set the colour depth to 8 or 16 bits + // Can be used to change depth an existing sprite, but clears it to black void setColorDepth(int8_t b); void drawPixel(uint32_t x, uint32_t y, uint32_t color); @@ -576,35 +588,51 @@ class TFT_eSprite : public TFT_eSPI { 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), + fillRect(int32_t x, int32_t y, uint32_t w, uint32_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); // 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 a block of pixels to the sprite - void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); - void pushBitmap(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + // Write an image (bitmap) to the sprite + void pushImage(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data); + void pushImage(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, const uint16_t *data, bool swap = false); + // 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); - - int16_t height(void), - width(void); + // 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); private: @@ -613,13 +641,17 @@ class TFT_eSprite : public TFT_eSPI { protected: - uint16_t *_img; - uint8_t *_img8; - bool _created, _bpp16; + uint16_t *_img; // pointer to 16 bit sprite + uint8_t *_img8; // pointer to 8 bit sprite + bool _created, _bpp16; // created and bits per pixel depth flags - int32_t _icursor_x, _icursor_y, _xs, _ys, _xe, _ye, _xptr, _yptr; + int32_t _icursor_x, _icursor_y; + 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 - int32_t _iwidth, _iheight; + int32_t _iwidth, _iheight; // Sprite image width and height }; 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/library.json b/library.json index f7d7113..1de946d 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "0.17.17", + "version": "0.17.19", "keywords": "TFT, ESP8266, NodeMCU, ESP32, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486", "description": "A TFT SPI graphics library for ESP8266", "repository": diff --git a/library.properties b/library.properties index 787cc6f..59804c6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=0.17.17 +version=0.17.19 author=Bodmer maintainer=Bodmer sentence=A fast TFT library for ESP8266 processors and the Arduino IDE