The library has been cleaned up as it has got a bit untidy due to the large number of small incremental changes. 4bit Sprite examples renaed to be consistent with others. alphaBlend example moved to generic folder (alphaBlend fn was moved to TFT_eSPI class). Added sections + explanatory comments to functions prototypes. Temporary comments added for potential gotchas for noobs when using DMA. spi_begin/end functions renamed to reflect functionality. Old fns retained for backwards compatibility with user setup.h files.
199 lines
5.6 KiB
Arduino
199 lines
5.6 KiB
Arduino
/*
|
|
Sketch to show how a 4 bit Sprite is created, how to draw pixels
|
|
and text within the Sprite and then push the Sprite onto
|
|
the display screen.
|
|
|
|
The advantage of 4 bit sprites is:
|
|
1. Small memory footprint
|
|
2. Any set of 16 colours can be specified
|
|
3. Colours can be changed without redrawing in Sprite
|
|
4. Simple animations like flashing text can be achieved
|
|
by colour palette cycling and pushing sprite to TFT:
|
|
https://en.wikipedia.org/wiki/Color_cycling
|
|
|
|
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 4 bit Sprite occupies (width * height)/2 bytes in 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(115200);
|
|
Serial.println();
|
|
|
|
delay(500);
|
|
|
|
// Initialise the TFT registers
|
|
tft.init();
|
|
|
|
// Set the sprite colour depth to 4
|
|
spr.setColorDepth(4);
|
|
|
|
// 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 color 0 (Sprite is in memory so not visible yet)
|
|
spr.fillSprite(0);
|
|
|
|
// create a color map with known colors (16 maximum for 4 bit Sprite
|
|
uint16_t cmap[16];
|
|
|
|
|
|
cmap[0] = TFT_BLACK; // We will keep this as black
|
|
cmap[1] = TFT_NAVY;
|
|
cmap[2] = TFT_DARKGREEN;
|
|
cmap[3] = TFT_DARKCYAN;
|
|
cmap[4] = TFT_MAROON;
|
|
cmap[5] = TFT_PURPLE;
|
|
cmap[6] = TFT_PINK;
|
|
cmap[7] = TFT_LIGHTGREY;
|
|
cmap[8] = TFT_YELLOW;
|
|
cmap[9] = TFT_BLUE;
|
|
cmap[10] = TFT_GREEN;
|
|
cmap[11] = TFT_CYAN;
|
|
cmap[12] = TFT_RED;
|
|
cmap[13] = TFT_MAGENTA;
|
|
cmap[14] = TFT_WHITE; // Keep as white for text
|
|
cmap[15] = TFT_BLUE; // Keep as blue for sprite border
|
|
|
|
// Pass the palette to the Sprite class
|
|
spr.createPalette(cmap);
|
|
|
|
// Push Sprite parially off-screen to test cropping
|
|
spr.pushSprite(-40, -40);
|
|
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
|
|
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
|
|
|
|
// Number of pixels to draw
|
|
uint16_t n = 100;
|
|
|
|
// Draw 100 random color pixels at random positions in sprite
|
|
while (n--)
|
|
{
|
|
uint16_t color = random(0x10); // Returns color 0 - 0x0F (i.e. 0-15)
|
|
int16_t x = random(WIDTH); // Random x coordinate
|
|
int16_t y = random(HEIGHT); // Random y coordinate
|
|
spr.drawPixel(x, y, color); // Draw pixel in sprite
|
|
}
|
|
|
|
// Draw some lines
|
|
spr.drawLine(1, 0, WIDTH, HEIGHT-1, 10);
|
|
spr.drawLine(0, 0, WIDTH, HEIGHT, 10);
|
|
spr.drawLine(0, 1, WIDTH-1, HEIGHT, 10);
|
|
spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, 12);
|
|
spr.drawLine(0, HEIGHT, WIDTH, 0, 12);
|
|
spr.drawLine(1, HEIGHT, WIDTH, 1, 12);
|
|
|
|
// Draw some text with Middle Centre datum
|
|
spr.setTextDatum(MC_DATUM);
|
|
spr.setTextColor(14); // White text
|
|
spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4);
|
|
|
|
// Now push the sprite to the TFT at 3 positions 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 * 4);
|
|
|
|
// create a new color map for colours 1-13 and use it instead
|
|
for (auto i = 1; i <= 13; i++)
|
|
{
|
|
cmap[i] = random(0x10000);
|
|
}
|
|
|
|
spr.createPalette(cmap, 16);
|
|
// 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.createPalette(cmap);
|
|
|
|
spr.drawRect(0, 0, WIDTH, HEIGHT, 15); // Blue rectangle
|
|
|
|
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;
|
|
|
|
// Randomise the palette to change colours without redrawing
|
|
// the sprite
|
|
for (auto i = 1; i <= 13; i++)
|
|
{
|
|
cmap[i] = random(0x10000);
|
|
}
|
|
spr.createPalette(cmap); // Update sprite class palette
|
|
|
|
// Draw it 50 times, moving in random direct or staying still
|
|
n = 50;
|
|
int wait = random (50);
|
|
while (n)
|
|
{
|
|
if (updateTime <= millis())
|
|
{
|
|
// Use time delay so sprite 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!
|
|
}
|