| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /*
- * Display.cpp
- *
- * Created on: 05.01.2026
- * Author: FSmilari
- */
-
- #include "Display.h"
- #include "Adafruit_ST7735.h"
- #include "images/SFToolsLogo.h"
- #include "fonts/titillium_web_regular16pt7b.h" // Add a custom font
- #include "fonts/titillium_web_regular10pt7b.h" // Add a custom font
- #include "fonts/titillium_web_semibold10pt7b.h" // Add a custom font
- #include "fonts/titillium_web_regular8pt7b.h" // Add a custom font
- #include "fonts/titillium_web_semibold8pt7b.h" // Add a custom font
- #include <Fonts/FreeSans9pt7b.h> // Add a custom font
- #include "images/stm32duino_logo.h"
- #include "images/thermometer_32.h"
- #include "images/gear.h"
- #include "images/zzz.h"
- #include "images/ruler.h"
- #include "images/air.h"
- #include "images/water.h"
- #include "images/water_s.h"
-
- //#define LED -1 // to +5v
- //#define SCK PA5
- //#define SDA PA7
- //#define MISO -1
- //#define MOSI SDA
- #define CS PA2
- #define DC PA1
- #define RST PA0
-
- #define ST7735_ARDUINOGREEN 0x04b3
- #define ST7735_STM32BLUE 0x03d6
- #define ST7735_DODGERBLUE 0x249f
-
- /*****************
- ** Constructors.
- ****************/
- Display::Display() : tft(Adafruit_ST7735(CS, DC, RST)) { // @suppress("Abstract class cannot be instantiated")
- starttime = 0;
- configUnit = "m/s";
- distance = 0;
- environment = 1;
- waterTemp = 20.0;
- airTemp = 20.0;
- refreshScreen = true;
- doMeasureAnimation = false;
- }
-
- void Display::init(void) {
- tft.initR(INITR_BLACKTAB);
- tft.fillScreen(ST7735_BLACK);
- tft.setRotation(1);
- tft.setTextWrap(false);
- tft.setTextColor(ST7735_WHITE);
- refreshScreen = true;
- }
-
- void Display::setRefreshScreen() {
- refreshScreen = true;
- }
-
- void Display::drawXCenteredText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t y) {
- int16_t x1, y1; // Top-left corner of text
- uint16_t w, h; // Width and height
-
- tft.setFont(font);
- tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
- tft.setTextColor(col);
-
- // Get bounds starting from (0, 0)
- tft.getTextBounds(txt, 0, 0, &x1, &y1, &w, &h);
-
- // Calculate centered position
- int16_t centered_x = (SCREEN_WIDTH - w) / 2 - 3;
-
- // Set cursor and print
- tft.setCursor(centered_x, y);
- tft.print(txt);
- }
-
- void Display::drawRightAlignedText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t xOffset, int16_t y) {
- int16_t x1, y1; // Top-left corner of text
- uint16_t w, h; // Width and height
-
- tft.setFont(font);
- tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
- tft.setTextColor(col);
-
- // Get bounds starting from (0, 0)
- tft.getTextBounds(txt, 0, 0, &x1, &y1, &w, &h);
-
- // Calculate position
- int16_t rightAligned_x = (SCREEN_WIDTH - xOffset) - w;
-
- // Set cursor and print
- tft.setCursor(rightAligned_x, y);
- tft.print(txt);
- }
-
- void Display::drawText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t x, int16_t y) {
- tft.setFont(font);
- tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
- tft.setTextColor(col);
-
- tft.setCursor(x, y);
- tft.print(txt);
- }
-
- void Display::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
- tft.drawCircle(x0, y0, r, color);
- }
-
- void Display::clearDisplay(void) {
- tft.fillScreen(ST7735_BLACK);
- }
-
- void Display::showBrand(int16_t x, int16_t y) {
- drawBitmap(x, y, 128, 34, SFTools_Logo, ST7735_ORANGE);
- }
-
- void Display::showInitialization(String version) {
- redrawFrame();
- drawXCenteredText("EchoLoT", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 36);
- drawXCenteredText("designed by", &FreeSans9pt7b, 1, ST7735_WHITE, 64);
- showBrand(16, 84);
- delay(2000);
-
- redrawFrame();
- drawText("powered by", &FreeSans9pt7b, 1, ST7735_CYAN, 35, 20);
- tft.fillRoundRect(46, 32, 68, 68, 7, ST7735_STM32BLUE);
- drawBitmap(48, 34, 64, 64, epd_bitmap_stm32duino_logo_icon, ST7735_WHITE);
- drawXCenteredText("Ver: " + version, &titillium_web_regular8pt7b, 1, ST7735_CYAN, 118);
- delay(5000);
- }
-
- void Display::display(void) {
- if (!refreshScreen) {
- return;
- }
-
- refreshScreen = false;
- }
-
- void Display::showFrame(Status status) {
- switch (status) {
- case Status::INITIALIZATION:
- redrawFrame();
- break;
- case Status::IDLE:
- if (refreshScreen) {
- redrawIdleStatus();
- refreshScreen = false;
- }
- break;
- case Status::CONFIGURATION:
- if (refreshScreen) {
- redrawConfigStatus();
- refreshScreen = false;
- }
- break;
- default:
- break;
- }
- }
-
- void Display::setStatusValues(float airTemp, float waterTemp, float sonicSpeedAir, uint8_t saltPromilleWater) {
- this->airTemp = airTemp;
- this->waterTemp = waterTemp;
- this->sonicSpeedAir = sonicSpeedAir;
- this->saltPromilleWater = saltPromilleWater;
- }
-
- void Display::setEnvironment(int environment) {
- if (this->environment != environment) {
- this->environment = environment;
- redrawEnvIcon();
- redrawTempIcon();
- }
- }
-
- void Display::setDistance(uint32_t distance) {
- if (this->distance != distance) {
- this->distance = distance;
- redrawDistance();
- }
- }
-
- void Display::setConfigOption(String configOption) {
- if (!this->configOption.equals(configOption)) {
- this->configOption = configOption;
- redrawConfigOption();
- }
- }
-
- void Display::setConfigText(String configText) {
- if (!this->configValue.equals(configText)) {
- this->configValue = configText;
- redrawConfigValue();
- }
- }
-
- void Display::setConfigUnit(String configUnit) {
- if (!this->configUnit.equals(configUnit)) {
- this->configUnit = configUnit;
- redrawConfigUnit();
- }
-
- }
-
- /* ===== Private methods ===== */
- void Display::drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col) {
- tft.drawBitmap(x, y, bitmap, w, h, col);
- }
-
- void Display::drawRGBBitmap(int x, int y, int w, int h, const uint16_t bitmap[]) {
- tft.drawRGBBitmap(x, y, bitmap, w, h);
- }
-
- void Display::redrawFrame() {
- clearDisplay();
- tft.drawRoundRect(0, 0, 160, 128, 9, ST7735_CYAN);
- tft.drawRoundRect(1, 1, 158, 126, 8, ST7735_CYAN);
- }
-
- void Display::redrawGrid(bool cfg) {
- redrawFrame();
- tft.drawLine(0, 31, 160, 31, ST7735_CYAN);
- tft.drawLine(0, 32, 160, 32, ST7735_CYAN);
- tft.drawLine(0, 89, 160, 89, ST7735_CYAN);
- tft.drawLine(0, 90, 160, 90, ST7735_CYAN);
- tft.drawLine(cfg ? 120 : 80, 90, cfg ? 120 : 80, 128, ST7735_CYAN);
- tft.drawLine(cfg ? 121 : 81, 90, cfg ? 121 : 81, 128, ST7735_CYAN);
- }
-
- void Display::redrawIdleStatus() {
- redrawGrid();
- tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
- drawText("OPERATIV", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 55, 21);
-
- // float temp = environment == 1 ? airTemp : waterTemp;
- // uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
- // uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
- // tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
- // tft.drawRect(15, 107 - thH, 2, thH, col);
- // drawRightAlignedText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 96, 114);
- // drawCircle(72, 104, 2, col);
- redrawTempIcon();
- redrawEnvIcon();
- redrawDistance();
- }
-
- void Display::redrawConfigStatus() {
- redrawGrid(true);
- tft.drawBitmap(35, 4, epd_bitmap_gear, 24, 24, ST7735_YELLOW);
- drawText("KONFIG.", &titillium_web_semibold8pt7b, 1, ST7735_YELLOW, 65, 21);
-
- redrawConfigValue();
- redrawConfigOption();
- redrawConfigUnit();
- }
-
- void Display::redrawEnvIcon() {
- const uint8_t *environmentIcon = environment == 1 ? epd_bitmap_air : environment == 2 ? epd_bitmap_water : epd_bitmap_water_s;
- uint16_t col = environment == 1 ? ST7735_WHITE : ST7735_DODGERBLUE;
- tft.fillRect(83, 92, 72, 33, ST7735_BLACK);
- tft.drawBitmap(108, 97, environmentIcon, 24, 24, col);
- }
-
- void Display::redrawTempIcon() {
- float temp = environment == 1 ? airTemp : waterTemp;
- uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
- uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
- tft.fillRect(4, 92, 75, 30, ST7735_BLACK);
- tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
- tft.drawRect(15, 107 - thH, 2, thH, col);
- drawRightAlignedText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 96, 114);
- drawCircle(72, 104, 2, col);
- }
-
- void Display::runMeasureAnimation(bool run) {
- if (!this->doMeasureAnimation && run) {
- this->starttime = millis();
- this->doMeasureAnimation = run;
- } else if (this->doMeasureAnimation && !run) {
- this->starttime = 0;
- this->doMeasureAnimation = run;
- }
- tft.fillRect(24, 3, 28, 28, ST7735_BLACK);
- if (this->doMeasureAnimation && starttime != 0) {
- uint8_t lvl = ((millis() - starttime) / 1000) % 4;
- tft.drawBitmap(25, 4, epd_bitmap_Measure_25, 25, 25, ST7735_RED);
- switch (lvl) {
- case 0:
- tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_RED);
- tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
- tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
- tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
- break;
- case 1:
- tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
- tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_RED);
- tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
- tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
- break;
- case 2:
- tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
- tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
- tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_RED);
- tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
- break;
- case 3:
- tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
- tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
- tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
- tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_RED);
- break;
- default:
- break;
- }
- } else {
- tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
- }
- }
-
- void Display::redrawDistance() {
- tft.fillRect(4, 34, 152, 54, ST7735_BLACK);
- if (distance == 0) {
- drawXCenteredText("- - -", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
- } else {
- if (environment == 1) {
- uint16_t dist_CM = distance / 10;
- drawXCenteredText(String(dist_CM) + " cm", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
- } else {
- float dist_M = float(distance) / 1000;
- drawXCenteredText(String(dist_M, 1) + " m", &titillium_web_regular16pt7b, 1, ST7735_WHITE, 69);
- }
- }
- }
-
- void Display::redrawConfigValue() {
- tft.fillRect(4, 34, 152, 54, ST7735_BLACK);
- drawXCenteredText(configValue, &titillium_web_regular16pt7b, 1, ST7735_ORANGE, 69);
- }
-
- void Display::redrawConfigOption() {
- tft.fillRect(4, 92, 116, 30, ST7735_BLACK);
- drawText(configOption, &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 6, 113);
- }
-
- void Display::redrawConfigUnit() {
- int16_t x1, y1; // Top-left corner of text
- uint16_t w, h; // Width and height
- tft.getTextBounds(configUnit, 0, 0, &x1, &y1, &w, &h);
-
- tft.fillRect(123, 92, 35, 30, ST7735_BLACK);
- drawRightAlignedText(configUnit, &titillium_web_semibold8pt7b, 1, ST7735_WHITE, (37 - w) / 2 + 2, 113);
- if (configUnit.equals(" C")) {
- drawCircle(121 + ((37 - w) / 2), 105, 2, ST7735_WHITE);
- } else if (configUnit.equals(" / ")) {
- drawCircle(124 + ((37 - w) / 2), 105, 2, ST7735_WHITE);
- drawCircle(124 + ((37 - w) / 2) + 10, 110, 2, ST7735_WHITE);
- drawCircle(124 + ((37 - w) / 2) + 15, 110, 2, ST7735_WHITE);
- }
-
- }
|