Here’s a minimal example that prints 80 lines including the line number and the amount of millis to draw it
#include <Terminal.h>
#include <Adafruit_GFX.h>
#include <Adafruit_HX8357.h>
Terminal term;
Adafruit_HX8357 tft = Adafruit_HX8357(10,6,5);
void setup() {
// put your setup code here, to run once:
tft.begin();
tft.fillScreen(HX8357_BLACK);
tft.setCursor(0,0);
tft.setTextColor(HX8357_WHITE, HX8357_BLACK);
tft.setTextWrap(false);
unsigned long startTime = millis();
for (byte i = 0; i < 80; i++) {
term.print("Line ");
term.print(String(i));
term.print("! ");
//print time it took to draw line
term.println(String(millis() - startTime));
term.drawTerm(tft);
}
}
void loop() {
// put your main code here, to run repeatedly:
}
Terminal.h is a class I wrote that writes to the TFT but also scrolls horizontally and vertically automatically. It works by writing to a buffer and then drawing the screen when drawTerm() is called.
Terminal.h
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_HX8357.h>
#ifndef terminal_h
#define terminal_h
#define TERM_WIDTH 53
#define TERM_HEIGHT 60
class Terminal : public Print {
public:
Terminal() {
memset(buffer, 0, sizeof(buffer)); //clear buffer
}
size_t write(uint8_t a) {
if (a == '\b') { //Backspace character
if (buffer[cursorY].length() == 0 && cursorY > 0) {
for (unsigned int i = cursorY; i < bufsize; i++) {
buffer[i] = buffer[i+1];
}
cursorY--;
bufsize--;
cursorX = buffer[cursorY].length();
if (cursorY < screenY + 3) {
screenY--;
}
} else {
buffer[cursorY] = buffer[cursorY].substring(0, cursorX-1) + buffer[cursorY].substring(cursorX, buffer[cursorY].length());
cursorX--;
}
} else if (a == '\n') { //newline character
cursorY++;
bufsize++;
cursorX = 0;
for (unsigned int i = bufsize + 1; i > cursorY; i--) {
buffer[i] = buffer[i-1];
}
} else {
buffer[cursorY] = buffer[cursorY].substring(0, cursorX) + (char)a + buffer[cursorY].substring(cursorX, buffer[cursorY].length());
cursorX++;
}
screenX = (cursorX > TERM_WIDTH) ? cursorX - TERM_WIDTH : 0;
if (cursorY > screenY + (TERM_HEIGHT - 1)) {
screenY = cursorY - (TERM_HEIGHT - 1);
} else if (cursorY < screenY) {
screenY = cursorY;
}
return 1;
}
size_t write(const uint8_t *buffer, size_t size) {
size_t n = 0;
while (size--) {
if (write(*buffer++)) n++;
else break;
}
//drawTerm();
return n;
}
size_t write(const char *buffer, size_t size) {
return write((const uint8_t *)buffer, size);
}
size_t write(const char *str) {
if (str == NULL) return 0;
return write((const uint8_t *)str, strlen(str));
}
size_t print(const __FlashStringHelper *ifsh)
{
PGM_P p = reinterpret_cast<PGM_P>(ifsh);
size_t n = 0;
while (1) {
unsigned char c = pgm_read_byte(p++);
if (c == 0) break;
if (write(c)) n++;
else break;
}
return n;
}
size_t print(const String &s)
{
write(s.c_str(), s.length());
return 0;
}
size_t print(const char str[])
{
write(str);
return 0;
}
size_t print(char c)
{
write(c);
return 0;
}
size_t println(void)
{
write("\n");
return 0;
}
size_t println(const String &s)
{
print(s);
println();
return 0;
}
size_t println(const char c[])
{
print(c);
println();
return 0;
}
size_t println(char c)
{
print(c);
println();
return 0;
}
void drawTerm(Adafruit_HX8357 tft_out, boolean full=false) {
tft_out.setCursor(0,0);
for (unsigned int i = screenY; i < screenY + TERM_HEIGHT; i++) { //go from current screen y position
//if the screen buffer line is not equal to the buffer
// (or we want to update the full screen) update that line
if (!screenBuffer[i-screenY].equals(buffer[i]) || full) {
// if that line has text
if (buffer[i].length() != 0) {
screenBuffer[i-screenY] = buffer[i];
tft_out.print(buffer[i].substring(screenX, (screenX + TERM_WIDTH < buffer[i].length() ? screenX + TERM_WIDTH : buffer[i].length())));
for (int j = buffer[i].length(); j < TERM_WIDTH; j++) {
tft_out.print(" ");
}
tft_out.println();
} else {
for (int j = 0; j < TERM_WIDTH; j++) {
tft_out.print(" ");
}
tft_out.println();
}
screenBuffer[i-screenY] = buffer[i];
// otherwise skip that line
} else {
tft_out.println();
}
}
}
void showTerm(Adafruit_HX8357 tft_out) {
tft_out.fillScreen(HX8357_BLACK);
drawTerm(tft_out, true);
}
void hideTerm(Adafruit_HX8357 tft_out) {
tft_out.fillScreen(HX8357_BLACK);
}
void clearTerm(Adafruit_HX8357 tft_out) {
memset(buffer, 0, sizeof(buffer)); //clear buffer
cursorX = 0;
cursorY = 0;
screenX = 0;
screenY = 0;
tft_out.fillScreen(HX8357_BLACK);
drawTerm(tft_out,true);
}
private:
String buffer[2048];
String screenBuffer[TERM_HEIGHT];
unsigned int cursorX = 0;
unsigned int cursorY = 0;
unsigned int bufsize;
unsigned int screenX = 0;
unsigned int screenY = 0;
};
#endif
At the beginning when the screen is filling up it’s fine; takes about 30 ms per line:
Line 38! 1004
Line 39! 1030
Line 40! 1057
Line 41! 1083
Line 42! 1110
Line 43! 1136
Line 44! 1163
But after it gets to the bottom of the screen and starts vertical scrolling, it starts to take much longer:
Line 60! 3097
Line 61! 4635
Line 62! 6173
Line 63! 7711