AMOLED Market Ticker
LilyGO T-Display-S3 AMOLED·Arduino C++·Updated Jul 27, 2026·by FluxBench TeamIncludes Lab + Schematic
A stock ticker for the LilyGo T-Display S3 AMOLED (536×240): big color-coded price, change line and a live sparkline, all drawn with the flicker-free full-screen sprite pattern and pushed in one shot with pushColors(). Cycles QQQ → SPY → BTC-USD every 6 seconds — or on the GPIO 21 button: the bench has a push button wired to GPIO 21, so click it in the Lab to skip ahead (it works the same as the side button on the real board). Prices are a simulated random walk so the whole screen runs live in the Lab simulator — the comments show exactly how to swap in a real Yahoo Finance fetch on hardware.
sketch.ino
// AMOLED Market Ticker — LilyGo T-Display S3 AMOLED (536x240)
//
// Three symbols (QQQ / SPY / BTC-USD) rendered with the flicker-free
// full-screen sprite pattern: draw everything into a 536x240 sprite,
// then push it to the panel in one shot with amoled.pushColors().
//
// The onboard side button (GPIO 21) cycles symbols, and the page also
// auto-advances every 6 seconds. Prices here are a simulated random walk
// so the demo runs anywhere — including the FluxBench Lab simulator.
// On real hardware, swap simulateTick() for a Yahoo Finance fetch:
// https://query1.finance.yahoo.com/v8/finance/chart/QQQ?interval=1d&range=1d
// (send one header: http.addHeader("User-Agent", "Mozilla/5.0"))
#include <LilyGo_AMOLED.h>
#include <TFT_eSPI.h>
#define BTN_PIN 21 // onboard button
#define W 536
#define H 240
LilyGo_Class amoled;
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft);
const int NHIST = 60; // sparkline points
float hist[60];
int histLen = 0;
int sym = 0; // 0=QQQ 1=SPY 2=BTC-USD
String symName = "QQQ";
float price = 529.14;
float prevClose = 527.90;
unsigned long lastTick = 0;
unsigned long lastPage = 0;
int lastBtn = HIGH;
void selectSymbol(int s) {
sym = s;
if (sym == 0) { symName = "QQQ"; price = 529.14; prevClose = 527.90; }
if (sym == 1) { symName = "SPY"; price = 623.50; prevClose = 625.10; }
if (sym == 2) { symName = "BTC-USD"; price = 118250.0; prevClose = 116900.0; }
histLen = 0;
}
void simulateTick() {
// random walk: +/-0.15% per tick — replace with the Yahoo fetch on hardware
float step = (random(-100, 101) / 100.0) * price * 0.0015;
price = price + step;
if (histLen < NHIST) {
hist[histLen] = price;
histLen = histLen + 1;
} else {
for (int i = 0; i < NHIST - 1; i++) hist[i] = hist[i + 1];
hist[NHIST - 1] = price;
}
}
void drawScreen() {
spr.fillSprite(TFT_BLACK);
// header
spr.setTextDatum(TL_DATUM);
spr.setTextFont(4);
spr.setTextColor(TFT_CYAN, TFT_BLACK);
spr.drawString(symName, 16, 12);
spr.setTextDatum(TR_DATUM);
spr.setTextColor(TFT_DARKGREY, TFT_BLACK);
spr.drawString("FluxBench Ticker", W - 16, 12);
// big price, centered
float change = price - prevClose;
uint16_t upDown = TFT_GREEN;
if (change < 0) upDown = TFT_RED;
spr.setTextDatum(MC_DATUM);
spr.setTextFont(8);
spr.setTextColor(upDown, TFT_BLACK);
spr.drawString(String("$") + String(price, 2), W / 2, 92);
// change line
float pct = 100.0 * change / prevClose;
String sign = "+";
if (change < 0) sign = "";
spr.setTextFont(4);
spr.drawString(sign + String(change, 2) + " (" + sign + String(pct, 2) + "%)", W / 2, 150);
// sparkline of the recent walk
if (histLen >= 2) {
float lo = hist[0];
float hi = hist[0];
for (int i = 1; i < histLen; i++) {
if (hist[i] < lo) lo = hist[i];
if (hist[i] > hi) hi = hist[i];
}
if (hi - lo < 0.01) hi = lo + 0.01;
int x0 = 20, x1 = W - 20, y0 = 176, y1 = 228;
spr.drawRect(x0 - 4, y0 - 4, (x1 - x0) + 8, (y1 - y0) + 8, TFT_DARKGREY);
for (int i = 1; i < histLen; i++) {
int xa = x0 + (i - 1) * (x1 - x0) / (NHIST - 1);
int xb = x0 + i * (x1 - x0) / (NHIST - 1);
int ya = y1 - (int)((hist[i - 1] - lo) / (hi - lo) * (y1 - y0));
int yb = y1 - (int)((hist[i] - lo) / (hi - lo) * (y1 - y0));
spr.drawLine(xa, ya, xb, yb, upDown);
}
}
amoled.pushColors(0, 0, W, H, (uint16_t *)spr.getPointer());
}
void setup() {
Serial.begin(115200);
pinMode(BTN_PIN, INPUT_PULLUP);
if (!amoled.beginAMOLED_191()) {
Serial.println("Panel init failed");
}
spr.createSprite(W, H);
spr.setSwapBytes(true);
selectSymbol(0);
Serial.println("AMOLED Market Ticker ready");
}
void loop() {
// button cycles symbols (falling edge)
int b = digitalRead(BTN_PIN);
if (b == LOW && lastBtn == HIGH) {
selectSymbol((sym + 1) % 3);
lastPage = millis();
}
lastBtn = b;
// auto-advance pages every 6 s
if (millis() - lastPage >= 6000) {
lastPage = millis();
selectSymbol((sym + 1) % 3);
}
// new "quote" twice a second
if (millis() - lastTick >= 500) {
lastTick = millis();
simulateTick();
drawScreen();
Serial.print(symName);
Serial.print(" $");
Serial.println(price, 2);
}
delay(20);
}
Built with FluxBench.AI — the AI workbench for embedded projects.