Files
Arduino/WeatherPredictor/display_ui.cpp
T

103 lines
3.0 KiB
C++

#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
#include <SPI.h>
#include "config.h"
#include "display_ui.h"
// Non-static so displayRender() can reference it via extern.
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
void displayBegin() {
pinMode(TFT_BLK, OUTPUT);
digitalWrite(TFT_BLK, HIGH); // backlight on
tft.initR(INITR_MINI160x80); // 0.96" ST7735S
tft.invertDisplay(false); // this panel: no inversion
tft.setRotation(3); // landscape, 160 wide x 80 tall
tft.fillScreen(ST77XX_BLACK);
}
void displaySplash(const char* line1, const char* line2) {
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
tft.setTextSize(2);
tft.setCursor(4, 20);
tft.print(line1);
tft.setTextSize(1);
tft.setCursor(4, 50);
tft.print(line2);
}
// Simple 34x34 weather icon at (x, y).
static void drawIcon(WxCategory c, int x, int y) {
uint16_t sun = ST77XX_YELLOW;
uint16_t cloud = ST77XX_WHITE;
uint16_t rain = ST77XX_CYAN;
switch (c) {
case WX_FINE:
tft.fillCircle(x + 17, y + 17, 11, sun);
break;
case WX_FAIR:
tft.fillCircle(x + 12, y + 12, 8, sun);
tft.fillRoundRect(x + 8, y + 18, 24, 12, 6, cloud);
break;
case WX_CHANGEABLE:
tft.fillRoundRect(x + 4, y + 12, 26, 14, 7, cloud);
break;
case WX_RAIN:
tft.fillRoundRect(x + 4, y + 8, 26, 14, 7, cloud);
for (int i = 0; i < 3; i++)
tft.drawFastVLine(x + 9 + i * 8, y + 24, 8, rain);
break;
case WX_STORM:
tft.fillRoundRect(x + 4, y + 8, 26, 14, 7, cloud);
tft.fillTriangle(x + 16, y + 22, x + 12, y + 32, x + 20, y + 30, ST77XX_YELLOW);
break;
default:
tft.drawRect(x + 4, y + 10, 26, 18, cloud); // unknown / collecting
break;
}
}
// Layout for landscape 160 x 80.
void displayRender(const AppState& s) {
tft.fillScreen(ST77XX_BLACK);
tft.setTextColor(ST77XX_WHITE);
char buf[24];
// Time (large), top-left
snprintf(buf, sizeof(buf), "%02u:%02u", s.now.hour, s.now.minute);
tft.setTextSize(2);
tft.setCursor(4, 4);
tft.print(buf);
// Icon, top-right
drawIcon(s.haveTrend ? s.forecast.category : WX_UNKNOWN, 120, 4);
// Date
snprintf(buf, sizeof(buf), "%04u-%02u-%02u", s.now.year, s.now.month, s.now.day);
tft.setTextSize(1);
tft.setCursor(4, 26);
tft.print(buf);
// Pressure + trend arrow
snprintf(buf, sizeof(buf), "%.0f hPa", s.mslHpa);
tft.setCursor(4, 40);
tft.print(buf);
const char* arrow = (s.trend == TREND_RISING) ? "^" : (s.trend == TREND_FALLING ? "v" : "=");
tft.setCursor(96, 40);
tft.setTextColor(ST77XX_CYAN);
tft.print(arrow);
tft.setTextColor(ST77XX_WHITE);
// Temperature
snprintf(buf, sizeof(buf), "%.1f C", s.tempC);
tft.setCursor(4, 52);
tft.print(buf);
// Forecast short label (full width, bottom row)
tft.setTextColor(ST77XX_YELLOW);
tft.setCursor(4, 66);
tft.print(s.haveTrend ? categoryShort(s.forecast.category) : "Collecting...");
tft.setTextColor(ST77XX_WHITE);
}