mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-03 20:54:42 +02:00
Add sprite class
Sprites (images) can now be created in RAM, written to with text and graphics and rendered to screen quickly, this makes it easier to get flicker frre screen updates. ESP8266 can typically create up to a 160x128 sprite, and ESP32 about 200x200 pixels. 16 bit colour only at the moment, may soon implement 8 bit colour to reduce RAM.
This commit is contained in:
32
Keywords.txt
32
Keywords.txt
@@ -5,6 +5,7 @@ drawPixel KEYWORD2
|
|||||||
drawChar KEYWORD2
|
drawChar KEYWORD2
|
||||||
setAddrWindow KEYWORD2
|
setAddrWindow KEYWORD2
|
||||||
setWindow KEYWORD2
|
setWindow KEYWORD2
|
||||||
|
readAddrWindow KEYWORD2
|
||||||
pushColor KEYWORD2
|
pushColor KEYWORD2
|
||||||
pushColor KEYWORD2
|
pushColor KEYWORD2
|
||||||
pushColors KEYWORD2
|
pushColors KEYWORD2
|
||||||
@@ -49,8 +50,10 @@ readcommand32 KEYWORD2
|
|||||||
readPixel KEYWORD2
|
readPixel KEYWORD2
|
||||||
readRect KEYWORD2
|
readRect KEYWORD2
|
||||||
pushRect KEYWORD2
|
pushRect KEYWORD2
|
||||||
|
pushSprite KEYWORD2
|
||||||
readRectRGB KEYWORD2
|
readRectRGB KEYWORD2
|
||||||
getRotation KEYWORD2
|
getRotation KEYWORD2
|
||||||
|
getTextDatum KEYWORD2
|
||||||
fontsLoaded KEYWORD2
|
fontsLoaded KEYWORD2
|
||||||
color565 KEYWORD2
|
color565 KEYWORD2
|
||||||
drawChar KEYWORD2
|
drawChar KEYWORD2
|
||||||
@@ -64,3 +67,32 @@ width KEYWORD2
|
|||||||
textWidth KEYWORD2
|
textWidth KEYWORD2
|
||||||
fontHeight 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
|
||||||
|
deleteSprite KEYWORD2
|
||||||
|
fillSprite KEYWORD2
|
||||||
|
setWindow KEYWORD2
|
||||||
|
pushBitmap KEYWORD2
|
||||||
|
pushSprite KEYWORD2
|
||||||
|
942
TFT_eSPI.cpp
942
TFT_eSPI.cpp
@@ -512,13 +512,14 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
|||||||
***************************************************************************************/
|
***************************************************************************************/
|
||||||
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;
|
if ((x >= _width) || (y >= _height) || (w == 0) || (h == 0)) return;
|
||||||
|
|
||||||
spi_begin();
|
spi_begin();
|
||||||
|
|
||||||
setAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low and sent RAMWR
|
setAddrWindow(x, y, x + w - 1, y + h - 1); // Sets CS low and sent RAMWR
|
||||||
|
|
||||||
uint32_t len = w * h * 2;
|
uint32_t len = w * h * 2;
|
||||||
|
|
||||||
// Push pixels into window rectangle, data is a 16 bit pointer thus increment is halved
|
// 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; }
|
while ( len >=32 ) {SPI.writeBytes((uint8_t*)data, 32); data += 16; len -= 32; }
|
||||||
if (len) SPI.writeBytes((uint8_t*)data, len);
|
if (len) SPI.writeBytes((uint8_t*)data, len);
|
||||||
@@ -529,6 +530,62 @@ 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::pushSprite(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 < 0 || dh < 0) return;
|
||||||
|
|
||||||
|
//Serial.print("dx="); Serial.println(dx);
|
||||||
|
//Serial.print("dy="); Serial.println(dy);
|
||||||
|
//Serial.print("dw="); Serial.println(dw);
|
||||||
|
//Serial.print("dh="); Serial.println(dh);
|
||||||
|
|
||||||
|
spi_begin();
|
||||||
|
|
||||||
|
setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
|
||||||
|
|
||||||
|
data += dx + dy * w;
|
||||||
|
|
||||||
|
while (dh--)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
uint32_t len = dw;
|
||||||
|
uint16_t* ptr = data;
|
||||||
|
// Push pixels into window rectangle, data is a 16 bit pointer thus increment is halved
|
||||||
|
while ( len--) SPI.write16(*ptr++, 0);
|
||||||
|
data += w;
|
||||||
|
*/
|
||||||
|
uint32_t len = dw * 2;
|
||||||
|
uint8_t* ptr = (uint8_t*)data;
|
||||||
|
// Push pixels into window rectangle, data is a 16 bit pointer thus increment is halved
|
||||||
|
while ( len>32) { SPI.writePattern(ptr, 32, 1); len -= 32; ptr += 32; }
|
||||||
|
if (len) SPI.writePattern((uint8_t*)ptr, len, 1);
|
||||||
|
data += w;
|
||||||
|
}
|
||||||
|
|
||||||
|
CS_H;
|
||||||
|
|
||||||
|
spi_end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************************
|
/***************************************************************************************
|
||||||
** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
|
** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
|
||||||
** Description: Read RGB pixel colours from a defined area
|
** Description: Read RGB pixel colours from a defined area
|
||||||
@@ -3906,7 +3963,7 @@ void TFT_eSPI::calibrateTouch(uint16_t *parameters, uint32_t color_fg, uint32_t
|
|||||||
parameters[2] = touchCalibration_y0;
|
parameters[2] = touchCalibration_y0;
|
||||||
parameters[3] = touchCalibration_y1;
|
parameters[3] = touchCalibration_y1;
|
||||||
parameters[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2);
|
parameters[4] = touchCalibration_rotate | (touchCalibration_invert_x <<1) | (touchCalibration_invert_y <<2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -4057,134 +4114,787 @@ boolean TFT_eSPI_Button::justReleased() { return (!currstate && laststate); }
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
// 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
|
||||||
|
***************************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** 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;
|
||||||
|
|
||||||
|
_xs = 0; // window bounds for pushColor
|
||||||
|
_ys = 0;
|
||||||
|
_xe = 0;
|
||||||
|
_ye = 0;
|
||||||
|
|
||||||
|
_xptr = 0; // pushColor coordinate
|
||||||
|
_yptr = 0;
|
||||||
|
|
||||||
|
_icursor_y = _icursor_x = 0; // Text cursor position
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
/***************************************************
|
** Function name: createSprite
|
||||||
The majority of code in this file is "FunWare", the only condition of use of
|
** Description: Create a sprite (bitmap) of defined width and height
|
||||||
those portions is that users have fun! Most of the effort has been spent on
|
*************************************************************************************x*/
|
||||||
the creation and incorporation of the proportional Run Length Encoded fonts
|
uint16_t* TFT_eSprite::createSprite(int16_t w, int16_t h)
|
||||||
that can be rendered over an SPI bus at high speeds.
|
{
|
||||||
|
if ( w < 1 || h < 1) return 0;
|
||||||
A significant number of new features have been added to the original source
|
_iwidth = w;
|
||||||
libraries. Functions names have been retained where practical to allow old
|
_iheight = h;
|
||||||
Adafruit_GFX TFT screen compatible sketches to be easily adapted.
|
_img = (uint16_t*) malloc(w * h * sizeof(uint16_t));
|
||||||
|
return _img;
|
||||||
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:
|
** Function name: deleteSprite
|
||||||
|
** Description: Delete the sprite to free up memory (RAM)
|
||||||
|
*************************************************************************************x*/
|
||||||
|
void TFT_eSprite::deleteSprite(void)
|
||||||
|
{
|
||||||
|
free(_img);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************************************************
|
/***************************************************************************************
|
||||||
The Adafruit_ILI9341 library has been used as a starting point
|
** Function name: pushSprite
|
||||||
for this library.
|
** Description: Delete the sprite to free up memory (RAM)
|
||||||
|
*************************************************************************************x*/
|
||||||
ORIGINAL LIBRARY HEADER
|
void TFT_eSprite::pushSprite(int32_t x, int32_t y)
|
||||||
|
{
|
||||||
This is our library for the Adafruit ILI9341 Breakout and Shield
|
_tft->pushSprite(x, y, _iwidth, _iheight, _img);
|
||||||
----> 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
|
|
||||||
|
|
||||||
****************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************
|
/***************************************************************************************
|
||||||
|
** Function name: readPixel
|
||||||
Some member funtions have been imported from the Adafruit_GFX
|
** Description: Read 565 colour of a pixel at deined coordinates
|
||||||
library. The license associated with these is reproduced below.
|
*************************************************************************************x*/
|
||||||
|
uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y)
|
||||||
ORIGINAL LIBRARY HEADER from Adafruit_GFX.cpp
|
{
|
||||||
|
uint16_t color = _img[x + y * _iwidth];
|
||||||
This is the core graphics library for all our displays, providing a common
|
return (color >> 8) | (color << 8);
|
||||||
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.
|
|
||||||
|
|
||||||
****************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************
|
/***************************************************************************************
|
||||||
|
** Function name: pushRect (same as pushBitmap)
|
||||||
|
** Description: push 565 colour bitmap into a defined area
|
||||||
|
*************************************************************************************x*/
|
||||||
|
void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data)
|
||||||
|
{
|
||||||
|
if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0)) return;
|
||||||
|
|
||||||
In compliance with the licence.txt file for the Adafruit_GFX library the
|
for (uint32_t yp = y; yp < y + h; yp++)
|
||||||
following is included.
|
{
|
||||||
|
for (uint32_t xp = x; xp < x + w; xp++)
|
||||||
|
{
|
||||||
|
_img[xp + yp * _iwidth] = *data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Software License Agreement (BSD License)
|
|
||||||
|
|
||||||
Copyright (c) 2012 Adafruit Industries. All rights reserved.
|
/***************************************************************************************
|
||||||
|
** 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)
|
||||||
|
{
|
||||||
|
if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0)) return;
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
for (uint32_t yp = y; yp < y + h; yp++)
|
||||||
modification, are permitted provided that the following conditions are met:
|
{
|
||||||
|
for (uint32_t xp = x; xp < x + w; xp++)
|
||||||
|
{
|
||||||
|
_img[xp + yp * _iwidth] = *data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- 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
|
** Function name: spriteWindow
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
** Description: Set the bounds of a window for pushColor
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
*************************************************************************************x*/
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
{
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
// Bounds will be checked by drawPixel
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
if (x0 > x1) swap_coord(x0, x1);
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
if (y0 > y1) swap_coord(y0, y1);
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
_xs = x0;
|
||||||
|
_ys = y0;
|
||||||
|
_xe = x1;
|
||||||
|
_ye = y1;
|
||||||
|
|
||||||
|
_xptr = _xs;
|
||||||
|
_yptr = _ys;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: pushColor
|
||||||
|
** Description: Send a new pixel to the sprite window
|
||||||
|
*************************************************************************************x*/
|
||||||
|
void TFT_eSprite::pushColor(uint32_t color)
|
||||||
|
{
|
||||||
|
drawPixel(_xptr++, _yptr, color);
|
||||||
|
if (_xptr > _xe) { _xptr = _xs; _yptr++; }
|
||||||
|
if (_yptr > _ye) { _yptr = _ys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void TFT_eSprite::pushColor(uint32_t color, uint16_t len)
|
||||||
|
{
|
||||||
|
drawPixel(_xptr++, _yptr, color);
|
||||||
|
if (_xptr > _xe) { _xptr = _xs; _yptr++; }
|
||||||
|
if (_yptr > _ye) { _yptr = _ys; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: fillSprite
|
||||||
|
** Description: Fill the whole sprite with defined colour
|
||||||
|
*************************************************************************************x*/
|
||||||
|
void TFT_eSprite::fillSprite(uint32_t color)
|
||||||
|
{
|
||||||
|
// Use memset if possible as it is super fast
|
||||||
|
if((uint8_t)color == (color>>8)) memset(_img, (uint8_t)color, _iwidth * _iheight * 2);
|
||||||
|
else fillRect(0, 0, _iwidth, _iheight, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: setCursor
|
||||||
|
** Description: Set the sprite text cursor x,y position
|
||||||
|
*************************************************************************************x*/
|
||||||
|
void TFT_eSprite::setCursor(int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
_icursor_x = x;
|
||||||
|
_icursor_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: width or spriteWidth
|
||||||
|
** Description: Return the width of sprite
|
||||||
|
*************************************************************************************x*/
|
||||||
|
// Return the size of the display
|
||||||
|
int16_t TFT_eSprite::width(void)
|
||||||
|
{
|
||||||
|
return _iwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Return the size of the display
|
||||||
|
int16_t TFT_eSprite::spriteWidth(void)
|
||||||
|
{
|
||||||
|
return _iwidth;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** Function name: height or spriteHeight
|
||||||
|
** Description: Return the height of sprite
|
||||||
|
*************************************************************************************x*/
|
||||||
|
int16_t TFT_eSprite::height(void)
|
||||||
|
{
|
||||||
|
return _iheight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int16_t TFT_eSprite::spriteHeight(void)
|
||||||
|
{
|
||||||
|
return _iheight;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** 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 ((x >= (int16_t)_iwidth) || // Clip right
|
||||||
|
(y >= (int16_t)_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)
|
||||||
|
{
|
||||||
|
byte column[6];
|
||||||
|
byte 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
|
||||||
|
|
||||||
|
//>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
if(size > 1) {
|
||||||
|
xo16 = xo;
|
||||||
|
yo16 = yo;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t hpc = 0; // Horizontal foreground pixel count
|
||||||
|
for(yy=0; yy<h; yy++) {
|
||||||
|
for(xx=0; xx<w; xx++) {
|
||||||
|
if(bit == 0) {
|
||||||
|
bits = pgm_read_byte(&bitmap[bo++]);
|
||||||
|
bit = 0x80;
|
||||||
|
}
|
||||||
|
if(bits & bit) hpc++;
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bit >>= 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: 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)) return;
|
||||||
|
color = (color >> 8) | (color << 8);
|
||||||
|
_img[x+y*_iwidth] = (uint16_t) color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** 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)
|
||||||
|
{
|
||||||
|
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)) return;
|
||||||
|
if (y < 0) { h += y; y = 0; }
|
||||||
|
if ((y + h) > _iheight) h = _iheight - y;
|
||||||
|
|
||||||
|
if (h < 1) return;
|
||||||
|
color = (color >> 8) | (color << 8);
|
||||||
|
while (h--) _img[x + _iwidth * y++] = (uint16_t) color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** 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)) return;
|
||||||
|
if (x < 0) { w += x; x = 0; }
|
||||||
|
if ((x + w) > _iwidth) w = _iwidth - x;
|
||||||
|
|
||||||
|
if (w < 1) return;
|
||||||
|
color = (color >> 8) | (color << 8);
|
||||||
|
while (w--) _img[_iwidth * y + x++] = (uint16_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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
color = (color >> 8) | (color << 8);
|
||||||
|
|
||||||
|
while (h--) {
|
||||||
|
int32_t ix = x, iw = w;
|
||||||
|
while (iw--) _img[_iwidth * y + ix++] = (uint16_t) 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;
|
||||||
|
|
||||||
|
uint8_t uniCode = utf8; // Work with a copy
|
||||||
|
if (utf8 == '\n') uniCode+=22; // Make it a valid space character to stop errors
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
// 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')
|
||||||
|
{
|
||||||
|
_icursor_y += height;
|
||||||
|
_icursor_x = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (textwrap && (_icursor_x + width * textsize > _iwidth))
|
||||||
|
{
|
||||||
|
_icursor_y += height;
|
||||||
|
_icursor_x = 0;
|
||||||
|
}
|
||||||
|
_icursor_x += drawChar(uniCode, _icursor_x, _icursor_y, textfont);
|
||||||
|
}
|
||||||
|
|
||||||
|
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
#ifdef LOAD_GFXFF
|
||||||
|
} // Custom GFX font
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
if(utf8 == '\n') {
|
||||||
|
_icursor_x = 0;
|
||||||
|
_icursor_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);
|
||||||
|
|
||||||
|
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 && ((_icursor_x + textsize * (xo + w)) > _iwidth)) {
|
||||||
|
// Drawing character would go off right edge; wrap to new line
|
||||||
|
_icursor_x = 0;
|
||||||
|
_icursor_y += (int16_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance);
|
||||||
|
}
|
||||||
|
drawChar(_icursor_x, _icursor_y, uniCode, textcolor, textbgcolor, textsize);
|
||||||
|
}
|
||||||
|
_icursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif // LOAD_GFXFF
|
||||||
|
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
** 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 (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->last)) uniCode = pgm_read_byte(&gfxFont->first);
|
||||||
|
|
||||||
|
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]);
|
||||||
|
return pgm_read_byte(&glyph->xAdvance) * textsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
byte 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 >= (int16_t)_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);
|
||||||
|
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
|
||||||
|
|
||||||
|
byte tnp = 0; // Temporary copy of np for while loop
|
||||||
|
byte 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--) {
|
||||||
|
pushColor(textcolor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pushColor(textcolor);
|
||||||
|
}
|
||||||
|
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 +
|
||||||
|
}
|
||||||
|
|
||||||
*****************************************************/
|
|
||||||
|
121
TFT_eSPI.h
121
TFT_eSPI.h
@@ -30,6 +30,11 @@
|
|||||||
#define SPI_FREQUENCY 20000000
|
#define SPI_FREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// If the frequency is not defined, set a default
|
||||||
|
#ifndef SPI_TOUCH_FREQUENCY
|
||||||
|
#define SPI_TOUCH_FREQUENCY 2500000
|
||||||
|
#endif
|
||||||
|
|
||||||
// Only load the fonts defined in User_Setup.h (to save space)
|
// Only load the fonts defined in User_Setup.h (to save space)
|
||||||
// Set flag so RLE rendering code is optionally compiled
|
// Set flag so RLE rendering code is optionally compiled
|
||||||
#ifdef LOAD_GLCD
|
#ifdef LOAD_GLCD
|
||||||
@@ -267,8 +272,11 @@ typedef struct {
|
|||||||
|
|
||||||
// Now fill the structure
|
// Now fill the structure
|
||||||
const PROGMEM fontinfo fontdata [] = {
|
const PROGMEM fontinfo fontdata [] = {
|
||||||
|
#ifdef LOAD_GLCD
|
||||||
|
{ (const uint8_t *)font, widtbl_null, 0, 0 },
|
||||||
|
#else
|
||||||
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
|
{ (const uint8_t *)chrtbl_null, widtbl_null, 0, 0 },
|
||||||
|
#endif
|
||||||
// GLCD font (Font 1) does not have all parameters
|
// GLCD font (Font 1) does not have all parameters
|
||||||
{ (const uint8_t *)chrtbl_null, widtbl_null, 8, 7 },
|
{ (const uint8_t *)chrtbl_null, widtbl_null, 8, 7 },
|
||||||
|
|
||||||
@@ -320,25 +328,32 @@ class TFT_eSPI : public Print {
|
|||||||
|
|
||||||
void init(void), begin(void); // Same - begin included for backwards compatibility
|
void init(void), begin(void); // 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 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),
|
||||||
|
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),
|
virtual int16_t drawChar(unsigned int uniCode, int x, int y, int font),
|
||||||
setWindow(int16_t x0, int16_t y0, int16_t x1, int16_t y1),
|
drawChar(unsigned int uniCode, int x, int y),
|
||||||
|
height(void),
|
||||||
|
width(void);
|
||||||
|
|
||||||
pushColor(uint16_t color),
|
virtual size_t write(uint8_t);
|
||||||
pushColor(uint16_t color, uint16_t len),
|
|
||||||
|
|
||||||
pushColors(uint16_t *data, uint8_t len),
|
|
||||||
|
// The TFT_eSprite class inherits the following functions
|
||||||
|
void pushColors(uint16_t *data, uint8_t len),
|
||||||
pushColors(uint8_t *data, uint32_t len),
|
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),
|
void drawRect(int32_t x, int32_t y, int32_t w, int32_t h, 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),
|
|
||||||
drawRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, 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),
|
fillRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, uint32_t color),
|
||||||
|
|
||||||
@@ -392,6 +407,7 @@ class TFT_eSPI : public Print {
|
|||||||
void readRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data);
|
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
|
// Write a block of pixels to the screen
|
||||||
void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data);
|
void pushRect(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);
|
||||||
|
|
||||||
// This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
|
// 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
|
// It reads a screen area and returns the RGB 8 bit colour values of each pixel
|
||||||
@@ -404,9 +420,7 @@ class TFT_eSPI : public Print {
|
|||||||
uint16_t fontsLoaded(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);
|
||||||
|
|
||||||
int16_t drawChar(unsigned int uniCode, int x, int y, int font),
|
int16_t drawNumber(long long_num,int poX, int poY, int font),
|
||||||
drawChar(unsigned int uniCode, int x, int y),
|
|
||||||
drawNumber(long long_num,int poX, int poY, int font),
|
|
||||||
drawNumber(long long_num,int poX, int poY),
|
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, int font),
|
||||||
drawFloat(float floatNumber,int decimal,int poX, int poY),
|
drawFloat(float floatNumber,int decimal,int poX, int poY),
|
||||||
@@ -423,9 +437,7 @@ class TFT_eSPI : public Print {
|
|||||||
drawCentreString(const String& string, int dX, int poY, int font), // Deprecated, use setTextDatum() and drawString()
|
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()
|
drawRightString(const String& string, int dX, int poY, int font); // Deprecated, use setTextDatum() and drawString()
|
||||||
|
|
||||||
int16_t height(void),
|
int16_t textWidth(const char *string, int font),
|
||||||
width(void),
|
|
||||||
textWidth(const char *string, int font),
|
|
||||||
textWidth(const char *string),
|
textWidth(const char *string),
|
||||||
textWidth(const String& string, int font),
|
textWidth(const String& string, int font),
|
||||||
textWidth(const String& string),
|
textWidth(const String& string),
|
||||||
@@ -441,7 +453,6 @@ class TFT_eSPI : public Print {
|
|||||||
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size);
|
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size);
|
||||||
void setTouch(uint16_t *data);
|
void setTouch(uint16_t *data);
|
||||||
|
|
||||||
virtual size_t write(uint8_t);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -531,6 +542,74 @@ class TFT_eSPI_Button {
|
|||||||
boolean currstate, laststate;
|
boolean currstate, laststate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************************************************************
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
uint16_t* createSprite(int16_t w, int16_t y); // 16 bpp
|
||||||
|
void deleteSprite(void);
|
||||||
|
|
||||||
|
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),
|
||||||
|
|
||||||
|
setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1),
|
||||||
|
pushColor(uint32_t color),
|
||||||
|
pushColor(uint32_t color, uint16_t len),
|
||||||
|
|
||||||
|
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),
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void pushSprite(int32_t x, int32_t y);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
size_t write(uint8_t);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
TFT_eSPI *_tft;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
uint16_t *_img;
|
||||||
|
|
||||||
|
int32_t _icursor_x, _icursor_y, _xs, _ys, _xe, _ye, _xptr, _yptr;
|
||||||
|
|
||||||
|
int32_t _iwidth, _iheight; // Display w/h as modified by current rotation
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***************************************************
|
/***************************************************
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
//#include <User_Setups/Setup8_ILI9163_128x128.h> // Setup file configured for my ILI9163 128x128 display
|
//#include <User_Setups/Setup8_ILI9163_128x128.h> // Setup file configured for my ILI9163 128x128 display
|
||||||
//#include <User_Setups/Setup9_ST7735_Overlap.h> // Setup file configured for my ST7735
|
//#include <User_Setups/Setup9_ST7735_Overlap.h> // Setup file configured for my ST7735
|
||||||
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
|
//#include <User_Setups/Setup10_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
|
||||||
|
//#include <User_Setups/Setup11_RPi_touch_ILI9486.h> // Setup file configured for my stock RPi TFT with touch
|
||||||
|
|
||||||
//#include <User_Setups/SetupX_Template.h> // Setup file template for copying/editting
|
//#include <User_Setups/SetupX_Template.h> // Setup file template for copying/editting
|
||||||
|
|
||||||
|
199
examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino
Normal file
199
examples/Sprite/Sprite_RLE_Font_test/Sprite_RLE_Font_test.ino
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
Display all the fast rendering fonts.
|
||||||
|
|
||||||
|
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 ######
|
||||||
|
#########################################################################
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Create a sprite 160 x 128 pixels (needs 40Kbytes of RAM!)
|
||||||
|
#define IWIDTH 160
|
||||||
|
#define IHEIGHT 128
|
||||||
|
|
||||||
|
// New background colour
|
||||||
|
#define TFT_BROWN 0x38E0
|
||||||
|
|
||||||
|
// Pause in milliseconds between screens, change to 0 to time font rendering
|
||||||
|
#define WAIT 500
|
||||||
|
|
||||||
|
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
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.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_BROWN);
|
||||||
|
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_BROWN);
|
||||||
|
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_BROWN);
|
||||||
|
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_BROWN);
|
||||||
|
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_BROWN);
|
||||||
|
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_BROWN);
|
||||||
|
img.drawString("890:.", 0, 0, 7);
|
||||||
|
img.drawString("", 0, 60, 7);
|
||||||
|
img.pushSprite(0, 0); delay(WAIT);
|
||||||
|
|
||||||
|
img.fillSprite(TFT_BROWN);
|
||||||
|
img.setTextColor(TFT_YELLOW);
|
||||||
|
|
||||||
|
img.drawString("0123", 0, 0, 8);
|
||||||
|
img.pushSprite(0, 0); delay(WAIT);
|
||||||
|
|
||||||
|
img.fillSprite(TFT_BROWN);
|
||||||
|
img.drawString("4567", 0, 0, 8);
|
||||||
|
img.pushSprite(0, 0); delay(WAIT);
|
||||||
|
|
||||||
|
img.fillSprite(TFT_BROWN);
|
||||||
|
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);;
|
||||||
|
}
|
||||||
|
|
140
examples/Sprite/Sprite_TFT_Rainbow/Sprite_TFT_Rainbow.ino
Normal file
140
examples/Sprite/Sprite_TFT_Rainbow/Sprite_TFT_Rainbow.ino
Normal file
@@ -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 <TFT_eSPI.h> // Graphics and font library
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
imgPtr = 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
|
||||||
|
|
||||||
|
tft.pushSprite(0, 0, IWIDTH, IHEIGHT, imgPtr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
134
examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino
Normal file
134
examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
Sketch to show how a Sprite is created, how to draw pixels
|
||||||
|
and text within the Sprite and then split the Sprite onto
|
||||||
|
the display screen.
|
||||||
|
|
||||||
|
Example for library:
|
||||||
|
https://github.com/Bodmer/TFT_eSPI
|
||||||
|
|
||||||
|
A Sprite is notionally an invisibly 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 in RAM.
|
||||||
|
|
||||||
|
On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated,
|
||||||
|
this size requires 40kBytes of RAM.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Set delay after plotting the sprite
|
||||||
|
#define DELAY 1000
|
||||||
|
|
||||||
|
// Width and height of sprite
|
||||||
|
#define WIDTH 128
|
||||||
|
#define HEIGHT 128
|
||||||
|
|
||||||
|
#include <TFT_eSPI.h> // 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();
|
||||||
|
|
||||||
|
// 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!
|
||||||
|
}
|
||||||
|
|
194
examples/Sprite/Sprite_scroll_text/Sprite_scroll_text.ino
Normal file
194
examples/Sprite/Sprite_scroll_text/Sprite_scroll_text.ino
Normal file
@@ -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 invisibly 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 <TFT_eSPI.h> // 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue
Block a user