Add viewport feature

2 new example sketches added for viewport demonstration
This commit is contained in:
Bodmer committed 2020-10-06 00:51:41 +01:00
1 parent 22ca8193c5
commit 13d217dc89
11 files changed
+813 -72

No files matched your search

@@ -20,7 +20,7 @@ uint8_t __attribute__((always_inline)) rng()
zx++;
za = (za^zc^zx);
zb = (zb+za);
zc = (zc+(zb>>1)^za);
zc = ((zc+(zb>>1))^za);
return zc;
}
+142
View File
@@ -0,0 +1,142 @@
// Viewport Demo
// See viewport_commands tab
// This example uses the viewport commands to create a "virtual TFT" within the
// normal TFT display area. This allows a sketch written for a smaller screen to
// be run in a viewport window. By default, the graphics 0,0 datum is set to the
// top left corner of the viewport, but optionally the datum can be kept at the
// corner of the TFT.
// Viewports have a number of potential uses:
// - create a "virtual" TFT screen smaller than the actual TFT screen
// - render GUI items (menus etc) in a viewport, erase GUI item by redrawing whole screen,
// this will be fast because only the viewport will be refreshed (e.g. clearing menu)
// - limit screen refresh to a particular area, e.g. changing numbers, icons or graph plotting
// - showing a small portion of a larger image or sprite, this allows panning and scrolling
// A viewport can have the coordinate datum (position 0,0) either at the top left corner of
// the viewport or at the normal top left corner of the TFT.
// Putting the coordinate datum at the viewport corner means that functions that draw graphics
// in a fixed position can be relocated anywhere on the screen. (see plotShapes() below). This
// makes it easier to reposition groupd of graphical ojects (for example GUI buttons) that have
// fixed relative positions.
// The viewport position x, and y coordinates and viewport bounds must be constrained by the
// user sketch to be within the screen boundaries.
#include <SPI.h>
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
Serial.begin(115200);
tft.init();
tft.setRotation(1);
tft.fillScreen(TFT_BLACK);
/*
tft.setViewport(VP_X, VP_Y, VP_W, VP_H); // By default the 0,0 coordinate datum is
// moved to top left corner of viewport
// Note: tft.width() and tft.height() now return viewport size
// Other command options:
//tft.setViewport(VP_X, VP_Y, VP_W, VP_H, true); // Explicitly set datum to viewport corner
//tft.setViewport(VP_X, VP_Y, VP_W, VP_H, false); // Create viewport but datum stays at TFT corner
// Note: tft.width() and tft.height() now return TFT size
w = tft.getViewportWidth(); // Always returns width of viewport
h = tft.getViewportHeight(); // Always returns height of viewport
tft.frameViewport(TFT_GREEN, -2); // Draw a rectangle of width 2 outside (negative width) viewport
tft.frameViewport(TFT_RED, 10); // Draw a rectangle of width 10 inside (positive width) viewport
// tft.resetViewport(); // Command to reset viewport to "normal" full TFT screen
// Graphics will not be drawn to the TFT outside a viewport until
// this command is used!
// tft.setRotation(2); // Using setRotation rotates the whole TFT screen it does not just
// rotate the viewport (this is a possible future enhancement).
// Redraw all graphics after a rotation since some TFT's do not
// re-map the TFT graphics RAM to the screen pixels as expected.
delay(1000);
*/
}
void loop()
{
// Normal Screen
drawX();
delay(2000);
// Viewport screen
tft.setViewport(10, 10, 140, 100);
tft.frameViewport(TFT_NAVY, -2);
tft.fillScreen(TFT_BLACK);
drawX();
tft.resetViewport();
delay(2000);
//Normal screen
tft.fillScreen(TFT_BLACK);
drawX();
delay(2000);
tft.fillScreen(TFT_BLACK);
// Viewport as a clipping window (false parameter means coordinate datum stays at TFT top left)
tft.setViewport(10, 10, tft.width()/2 - 10, tft.height() - 20, false);
//tft.frameViewport(TFT_NAVY, 2); // Add 2 pixel border inside viewport
//tft.frameViewport(TFT_NAVY, -2); // Add 2 pixel border outside viewport
drawX();
delay(2000);
while(1)
{
tft.resetViewport(); // Reset viewport so width() and height() return TFT size
uint16_t w = 40;
uint16_t h = 40;
uint16_t x = random(tft.width() - w);
uint16_t y = random(tft.height() - h);
tft.setViewport(x, y, w, h);
plotBox();
}
}
void drawX(void)
{
tft.fillScreen(tft.color565(25,25,25)); // Grey
// Draw circle
tft.drawCircle(tft.width()/2, tft.height()/2, tft.width()/4, TFT_RED);
// Draw diagonal lines
tft.drawLine(0 , 0, tft.width()-1, tft.height()-1, TFT_GREEN);
tft.drawLine(0 , tft.height()-1, tft.width()-1, 0, TFT_BLUE);
tft.setTextDatum(MC_DATUM);
tft.setTextColor(TFT_WHITE, tft.color565(25,25,25));
tft.drawString("Hello World!", tft.width()/2, tft.height()/2, 4); // Font 4
}
void plotBox(void)
{
// These are always plotted at a fixed position but they can
// be plotted into a viewport anywhere on the screen because
// a viewport can move the screen datum
tft.fillScreen(TFT_BLACK); // When a viewport is set, this just fills the viewport
tft.drawRect(0,0, 40,40, TFT_BLUE);
tft.setTextDatum(MC_DATUM);
tft.setTextColor(TFT_WHITE);
tft.drawNumber( random(100), 20, 23, 4);
}
@@ -0,0 +1,33 @@
/*
// Create a viewport at TFT screen coordinated X,y of width W and height H
tft.setViewport(X, Y, W, H); // By default the 0,0 coordinate datum is moved to top left
// corner of viewport
// Note: tft.width() and tft.height() now return viewport size!
// The above command is identical to:
tft.setViewport(VP_X, VP_Y, VP_W, VP_H, true); // true parameter is optional
// To create a viewport that keeps the coordinate datum at top left of TFT, use false parameter
tft.setViewport(VP_X, VP_Y, VP_W, VP_H, false); // Note: tft.width() and tft.height() return TFT size!
// To get width of viewport
uint16_t w = tft.getViewportWidth(); // Always returns width of viewport
// To get height of viewport
uint16_t h = tft.getViewportHeight(); // Always returns height of viewport
// To draw a rectangular frame outside viewport of width W (when W is negative)
tft.frameViewport(TFT_RED, -W); // Note setting the width to a large negative value will clear the screen
// outside the viewport
// To draw a rectangular frame inside viewport of width W (when W is positive)
tft.frameViewport(TFT_RED, W); // Note setting the width to a large positive value will clear the screen
// inside the viewport
// To reset the viewport to the normal TFT full screen
tft.resetViewport(); // Note: Graphics will NOT be drawn to the TFT outside a viewport until
// this command is used! ( The exception is using the frameViewport command
// detailed above with a negative width.)
*/
@@ -0,0 +1,381 @@
/*
This sketch demonstrates the Adafruit graphicstest sketch running in a
viewport (aka window) within the TFT screen area. To do this line 37 has
been added. Line 38 outlines the viewport.
This sketch uses the GLCD font (font 1) only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include "SPI.h"
#include "TFT_eSPI.h"
TFT_eSPI tft = TFT_eSPI();
unsigned long total = 0;
unsigned long tn = 0;
void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println(""); Serial.println("");
Serial.println("TFT_eSPI library test!");
tft.init();
tn = micros();
tft.fillScreen(TFT_BLACK);
// Create a viewport 220 x 300 pixels
tft.setViewport(10,10,220,300);
tft.frameViewport(TFT_RED, -1); // 1 pixel wide frame around viewport
yield(); Serial.println(F("Benchmark Time (microseconds)"));
yield(); Serial.print(F("Screen fill "));
yield(); Serial.println(testFillScreen());
//total+=testFillScreen();
//delay(500);
yield(); Serial.print(F("Text "));
yield(); Serial.println(testText());
//total+=testText();
//delay(3000);
yield(); Serial.print(F("Lines "));
yield(); Serial.println(testLines(TFT_CYAN));
//total+=testLines(TFT_CYAN);
//delay(500);
yield(); Serial.print(F("Horiz/Vert Lines "));
yield(); Serial.println(testFastLines(TFT_RED, TFT_BLUE));
//total+=testFastLines(TFT_RED, TFT_BLUE);
//delay(500);
yield(); Serial.print(F("Rectangles (outline) "));
yield(); Serial.println(testRects(TFT_GREEN));
//total+=testRects(TFT_GREEN);
//delay(500);
yield(); Serial.print(F("Rectangles (filled) "));
yield(); Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
//total+=testFilledRects(TFT_YELLOW, TFT_MAGENTA);
//delay(500);
yield(); Serial.print(F("Circles (filled) "));
yield(); Serial.println(testFilledCircles(10, TFT_MAGENTA));
//total+= testFilledCircles(10, TFT_MAGENTA);
yield(); Serial.print(F("Circles (outline) "));
yield(); Serial.println(testCircles(10, TFT_WHITE));
//total+=testCircles(10, TFT_WHITE);
//delay(500);
yield(); Serial.print(F("Triangles (outline) "));
yield(); Serial.println(testTriangles());
//total+=testTriangles();
//delay(500);
yield(); Serial.print(F("Triangles (filled) "));
yield(); Serial.println(testFilledTriangles());
//total += testFilledTriangles();
//delay(500);
yield(); Serial.print(F("Rounded rects (outline) "));
yield(); Serial.println(testRoundRects());
//total+=testRoundRects();
//delay(500);
yield(); Serial.print(F("Rounded rects (filled) "));
yield(); Serial.println(testFilledRoundRects());
//total+=testFilledRoundRects();
//delay(500);
yield(); Serial.println(F("Done!")); yield();
//Serial.print(F("Total = ")); Serial.println(total);
//yield();Serial.println(millis()-tn);
}
void loop(void) {
for (uint8_t rotation = 0; rotation < 4; rotation++) {
tft.setRotation(rotation);
tft.resetViewport(); // reset viewport to whole screen
tft.fillScreen(TFT_BLACK); // so it can be cleared
// Create a viewport 220 x 300 pixels
tft.setViewport(10,10,220,300);
tft.frameViewport(TFT_RED, -1); // 1 pixel wide frame around viewport
testText();
delay(2000);
}
}
unsigned long testFillScreen() {
unsigned long start = micros();
tft.fillScreen(TFT_BLACK);
tft.fillScreen(TFT_RED);
tft.fillScreen(TFT_GREEN);
tft.fillScreen(TFT_BLUE);
tft.fillScreen(TFT_BLACK);
return micros() - start;
}
unsigned long testText() {
tft.fillScreen(TFT_BLACK);
unsigned long start = micros();
tft.setCursor(0, 0);
tft.setTextColor(TFT_WHITE); tft.setTextSize(1);
tft.println("Hello World!");
tft.setTextColor(TFT_YELLOW); tft.setTextSize(2);
tft.println(1234.56);
tft.setTextColor(TFT_RED); tft.setTextSize(3);
tft.println(0xDEADBEEF, HEX);
tft.println();
tft.setTextColor(TFT_GREEN);
tft.setTextSize(5);
tft.println("Groop");
tft.setTextSize(2);
tft.println("I implore thee,");
//tft.setTextColor(TFT_GREEN,TFT_BLACK);
tft.setTextSize(1);
tft.println("my foonting turlingdromes.");
tft.println("And hooptiously drangle me");
tft.println("with crinkly bindlewurdles,");
tft.println("Or I will rend thee");
tft.println("in the gobberwarts");
tft.println("with my blurglecruncheon,");
tft.println("see if I don't!");
return micros() - start;
}
unsigned long testLines(uint16_t color) {
unsigned long start, t;
int x1, y1, x2, y2,
w = tft.width(),
h = tft.height();
tft.fillScreen(TFT_BLACK);
x1 = y1 = 0;
y2 = h - 1;
start = micros();
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t = micros() - start; // fillScreen doesn't count against timing
tft.fillScreen(TFT_BLACK);
x1 = w - 1;
y1 = 0;
y2 = h - 1;
start = micros();
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen(TFT_BLACK);
x1 = 0;
y1 = h - 1;
y2 = 0;
start = micros();
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen(TFT_BLACK);
x1 = w - 1;
y1 = h - 1;
y2 = 0;
start = micros();
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
return micros() - start;
}
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
unsigned long start;
int x, y, w = tft.width(), h = tft.height();
tft.fillScreen(TFT_BLACK);
start = micros();
for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);
return micros() - start;
}
unsigned long testRects(uint16_t color) {
unsigned long start;
int n, i, i2,
cx = tft.width() / 2,
cy = tft.height() / 2;
tft.fillScreen(TFT_BLACK);
n = min(tft.width(), tft.height());
start = micros();
for (i = 2; i < n; i += 6) {
i2 = i / 2;
tft.drawRect(cx - i2, cy - i2, i, i, color);
}
return micros() - start;
}
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
unsigned long start, t = 0;
int n, i, i2,
cx = tft.width() / 2 - 1,
cy = tft.height() / 2 - 1;
tft.fillScreen(TFT_BLACK);
n = min(tft.width(), tft.height());
for (i = n - 1; i > 0; i -= 6) {
i2 = i / 2;
start = micros();
tft.fillRect(cx - i2, cy - i2, i, i, color1);
t += micros() - start;
// Outlines are not included in timing results
tft.drawRect(cx - i2, cy - i2, i, i, color2);
}
return t;
}
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
unsigned long start;
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
tft.fillScreen(TFT_BLACK);
start = micros();
for (x = radius; x < w; x += r2) {
for (y = radius; y < h; y += r2) {
tft.fillCircle(x, y, radius, color);
}
}
return micros() - start;
}
unsigned long testCircles(uint8_t radius, uint16_t color) {
unsigned long start;
int x, y, r2 = radius * 2,
w = tft.width() + radius,
h = tft.height() + radius;
// Screen is not cleared for this one -- this is
// intentional and does not affect the reported time.
start = micros();
for (x = 0; x < w; x += r2) {
for (y = 0; y < h; y += r2) {
tft.drawCircle(x, y, radius, color);
}
}
return micros() - start;
}
unsigned long testTriangles() {
unsigned long start;
int n, i, cx = tft.width() / 2 - 1,
cy = tft.height() / 2 - 1;
tft.fillScreen(TFT_BLACK);
n = min(cx, cy);
start = micros();
for (i = 0; i < n; i += 5) {
tft.drawTriangle(
cx , cy - i, // peak
cx - i, cy + i, // bottom left
cx + i, cy + i, // bottom right
tft.color565(0, 0, i));
}
return micros() - start;
}
unsigned long testFilledTriangles() {
unsigned long start, t = 0;
int i, cx = tft.width() / 2 - 1,
cy = tft.height() / 2 - 1;
tft.fillScreen(TFT_BLACK);
start = micros();
for (i = min(cx, cy); i > 10; i -= 5) {
start = micros();
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
tft.color565(0, i, i));
t += micros() - start;
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
tft.color565(i, i, 0));
}
return t;
}
unsigned long testRoundRects() {
unsigned long start;
int w, i, i2,
cx = tft.width() / 2 - 1,
cy = tft.height() / 2 - 1;
tft.fillScreen(TFT_BLACK);
w = min(tft.width(), tft.height());
start = micros();
for (i = 0; i < w; i += 6) {
i2 = i / 2;
tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(i, 0, 0));
}
return micros() - start;
}
unsigned long testFilledRoundRects() {
unsigned long start;
int i, i2,
cx = tft.width() / 2 - 1,
cy = tft.height() / 2 - 1;
tft.fillScreen(TFT_BLACK);
start = micros();
for (i = min(tft.width(), tft.height()); i > 20; i -= 6) {
i2 = i / 2;
tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(0, i, 0));
}
return micros() - start;
}
/***************************************************
Original Adafruit text:
This is an example sketch for the Adafruit 2.2" SPI display.
This library works with the Adafruit 2.2" TFT Breakout w/SD card
----> http://www.adafruit.com/products/1480
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
****************************************************/