From a4291ec4e114c6a814df56c6dbd32830dc2c6a99 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 5 May 2024 09:15:57 +1000 Subject: [PATCH 001/146] Try to fix fonts with TFT_eSPI --- EX-Display.ino | 5 ----- FontOptions.h | 8 ++++++-- TFT_eSPIScreen.cpp | 11 ++++++++++- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index b7270ab..2fa3abb 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -34,10 +34,6 @@ void setup() { // and how to call back when found. AtFinder::setup(100, updateEXDisplayRow); - // SCREEN::TFT_Startup(); - // tft.invertDisplay(1); - // tft.invertDisplay(0); - // HARDWARE SETUP TODO..... Create an EXDisplay instance for each screen this ino wants to display. // The updateEXDisplayRow will ignore messages destined for screens we dont have. // For testing lets create some @@ -48,7 +44,6 @@ void setup() { #ifdef SCREEN_2_TYPE SCREEN_2 #endif - // new EXDisplay(0, new MCUFriendScreen(8, 20), 30); for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_COLOUR, BACKGROUND_COLOUR); diff --git a/FontOptions.h b/FontOptions.h index cf8f06d..ac21441 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,9 +1,11 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#include "Adafruit_GFX.h" #include "Arial9pt7b.h" #include "FreeSans12pt7b.h" +#include +#include +#include /// @brief Macros for available colours #define BLACK 0x0000 @@ -14,8 +16,10 @@ #define YELLOW 0xFFE0 #define WHITE 0xFFFF -/// @brief Macros for avaialble fonts +/// @brief Macros for available fonts #define ARIAL9PT7B &Arial9pt7b +#define FREESANS &FreeSans9pt7b +#define FREEMONO &FreeMono9pt7b #define FREESANS12PT7B &FreeSans12pt7b #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 9f5ad20..09b983d 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -14,7 +14,16 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint16_t textColour, uint16_t void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, uint8_t textSize, char *message) { - _tft.setCursor(column, row); + _tft.setTextSize(textSize); + _tft.setFreeFont(fontName); + uint8_t textRow = row * 8; + _tft.setCursor(column, textRow); + uint8_t blankLength = strlen(message); + _tft.setTextColor(BACKGROUND_COLOUR); + for (uint8_t i = 0; i < blankLength; i++) { + _tft.print(' '); + } + _tft.setCursor(column, textRow); _tft.setTextColor(fontColour); _tft.print(message); } From 8c2e6abdba605cf8f13054a01cf690c094544cc7 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 5 May 2024 10:55:47 +1000 Subject: [PATCH 002/146] Better without Adafruit_GFX --- EXScreen.h | 3 ++- FontOptions.h | 10 +++++----- OLDEXScreen.cpp | 20 ++++++++++---------- TFT_eSPIScreen.cpp | 10 ++++++---- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/EXScreen.h b/EXScreen.h index 0ee2109..ce98689 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -1,8 +1,9 @@ #ifndef EXSCREEN_H #define EXSCREEN_H -#include +// #include #include +#include /// @brief This EXScreen class is designed to be extended by other screen classes that define the methods to perform the /// requesite activities according to the library in use to drive the physical display. diff --git a/FontOptions.h b/FontOptions.h index ac21441..1128e76 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,11 +1,11 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#include "Arial9pt7b.h" -#include "FreeSans12pt7b.h" -#include -#include -#include +// #include "Arial9pt7b.h" +// #include "FreeSans12pt7b.h" +// #include +// #include +// #include /// @brief Macros for available colours #define BLACK 0x0000 diff --git a/OLDEXScreen.cpp b/OLDEXScreen.cpp index d569f36..691273b 100644 --- a/OLDEXScreen.cpp +++ b/OLDEXScreen.cpp @@ -17,20 +17,20 @@ * along with CommandStation. If not, see . */ -#include "Defines.h" -#include "DisplayFunctions.h" -#include "EXDisplayClass.h" -#include "EXDisplayRow.h" -#include "OLDEXScreen.h" -#include "config.h" -#include -#include -#include +// #include "Defines.h" +// #include "DisplayFunctions.h" +// #include "EXDisplayClass.h" +// #include "EXDisplayRow.h" +// #include "OLDEXScreen.h" +// #include "config.h" +// #include +// #include +// #include // MCUFRIEND_kbv tft; -#include "Arial9pt7b.h" +// #include "Arial9pt7b.h" //#include "FreeSans12pt7b.h" // int ScreenLines; diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 09b983d..9663d96 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -16,14 +16,16 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontNa uint8_t textSize, char *message) { _tft.setTextSize(textSize); _tft.setFreeFont(fontName); - uint8_t textRow = row * 8; + uint8_t fontHeight = fontName->yAdvance; + uint8_t textRow = (row * fontHeight) + fontHeight; _tft.setCursor(column, textRow); uint8_t blankLength = strlen(message); - _tft.setTextColor(BACKGROUND_COLOUR); + CONSOLE.print(F("Blanking: ")); + CONSOLE.println(blankLength); + _tft.setTextColor(fontColour); for (uint8_t i = 0; i < blankLength; i++) { - _tft.print(' '); + _tft.print(" "); } _tft.setCursor(column, textRow); - _tft.setTextColor(fontColour); _tft.print(message); } From 0c334a2299b644eb3bfd1d080aa6bb0ac76f6431 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 5 May 2024 19:05:29 +1000 Subject: [PATCH 003/146] Overwrite text not working --- EX-Display.ino | 2 ++ TFT_eSPIScreen.cpp | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 2fa3abb..f141602 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -47,6 +47,8 @@ void setup() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_COLOUR, BACKGROUND_COLOUR); + display->getEXScreen()->writeRow(0, 0, TEXT_FONT, TEXT_COLOUR, TEXT_SIZE, "EX-Display"); + display->getEXScreen()->writeRow(1, 0, TEXT_FONT, TEXT_COLOUR, TEXT_SIZE, VERSION); CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 9663d96..4c16d75 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -8,8 +8,6 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint16_t textColour, uint16_t _tft.init(); _tft.setRotation(rotation); _tft.fillScreen(backgroundColour); - _tft.setCursor(0, 0); - _tft.print(F("EX-Display")); } void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, @@ -18,14 +16,17 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontNa _tft.setFreeFont(fontName); uint8_t fontHeight = fontName->yAdvance; uint8_t textRow = (row * fontHeight) + fontHeight; + _tft.setTextPadding(_tft.textWidth(" ")); _tft.setCursor(column, textRow); - uint8_t blankLength = strlen(message); - CONSOLE.print(F("Blanking: ")); - CONSOLE.println(blankLength); - _tft.setTextColor(fontColour); - for (uint8_t i = 0; i < blankLength; i++) { - _tft.print(" "); - } + // uint8_t blankLength = strlen(message); + // CONSOLE.print(F("Blanking: ")); + // CONSOLE.println(blankLength); + _tft.setTextColor(BACKGROUND_COLOUR, BACKGROUND_COLOUR, true); + _tft.print(message); + _tft.setTextColor(fontColour, BACKGROUND_COLOUR, true); + // for (uint8_t i = 0; i < blankLength; i++) { + // _tft.print(" "); + // } _tft.setCursor(column, textRow); _tft.print(message); } From 2b7c02dfe1401dbde17ea211ad28e2308129e937 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 07:57:48 +1000 Subject: [PATCH 004/146] Ready for calcs, eSPI clearing --- DisplayFunctions.cpp | 2 +- EX-Display.ino | 12 +++++++++--- EXDisplayRow.cpp | 2 ++ EXDisplayRow.h | 4 ++++ EXScreen.h | 11 +++++++++-- MCUFriendScreen.cpp | 17 ++++++++++------- MCUFriendScreen.h | 9 ++++++--- TFT_eSPIScreen.cpp | 32 +++++++++++++------------------- TFT_eSPIScreen.h | 9 ++++++--- 9 files changed, 60 insertions(+), 38 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 1304b98..3be5322 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -49,7 +49,7 @@ void updateScreens() { #endif for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { if (row->needsRender() && row->isChanged()) { - screen->writeRow(row->getDisplayRow(), 0, TEXT_FONT, TEXT_COLOUR, TEXT_SIZE, row->getRowText()); + screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), row->getRowText()); } } } diff --git a/EX-Display.ino b/EX-Display.ino index f141602..b180639 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -46,9 +46,9 @@ void setup() { #endif for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_COLOUR, BACKGROUND_COLOUR); - display->getEXScreen()->writeRow(0, 0, TEXT_FONT, TEXT_COLOUR, TEXT_SIZE, "EX-Display"); - display->getEXScreen()->writeRow(1, 0, TEXT_FONT, TEXT_COLOUR, TEXT_SIZE, VERSION); + display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); + display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display"); + display->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION); CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); @@ -57,6 +57,12 @@ void setup() { CONSOLE.println(display->getScreenMaxColumns()); } + delay(2000); + + for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { + display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); + } + // Setup the start screen. // if (MAX_SCREENS > 1) { // currentScreenID = INITIAL_SCREEN; diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index bbf1455..5b8dedb 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -12,6 +12,8 @@ EXDisplayRow::EXDisplayRow(uint8_t rowNumber) { uint8_t EXDisplayRow::getRowNumber() { return _rowNumber; } +uint8_t EXDisplayRow::getMaxRowLength() { return _maxMalloc; } + void EXDisplayRow::setRowText(char *rowText) { // Note size limit is 254 chars but that is beyond // the capability of the caller anyway. diff --git a/EXDisplayRow.h b/EXDisplayRow.h index ee170ac..c0766eb 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -18,6 +18,10 @@ class EXDisplayRow { /// @return 0 - 255 uint8_t getRowNumber(); + /// @brief Get the maximum length this row has been set to + /// @return 0 - 255 + uint8_t getMaxRowLength(); + /// @brief Update the text for the specified row /// @param rowText Char array containing the text void setRowText(char *rowText); diff --git a/EXScreen.h b/EXScreen.h index ce98689..7fc2971 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -17,10 +17,14 @@ class EXScreen { EXScreen(uint8_t maxRows, uint8_t maxColumns) : _maxRows(maxRows), _maxColumns(maxColumns) {} /// @brief Virtual function to implement to setup the required parameters for the physical screen - virtual void setupScreen(uint8_t rotation, uint16_t textColour, uint16_t backgroundColour); + virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour); + + /// @brief Virtual function to implement + /// @param backgroundColour + virtual void clearScreen(uint16_t backgroundColour); /// @brief Virtual function to implement to write a row of text to the physical screen - virtual void writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, uint8_t textSize, + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); /// @brief Get the maximum number of rows this screen can physically display @@ -31,6 +35,9 @@ class EXScreen { /// @return 0 - 255 uint8_t getMaxColumns() { return _maxColumns; } + /// @brief Height of the font in use to determine row height + uint8_t fontHeight; + private: uint8_t _maxRows; // Maximum number of rows this screen can display uint8_t _maxColumns; // Maximum number of columns this screen can display diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 428c678..d95e8b9 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -4,7 +4,8 @@ MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft, uint8_t maxRows, uint8_t maxColumns) : EXScreen(maxRows, maxColumns), _tft(tft) {} -void MCUFriendScreen::setupScreen(uint8_t rotation, uint16_t textColour, uint16_t backgroundColour) { +void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, + uint16_t backgroundColour) { uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); CONSOLE.println(screenId, HEX); @@ -13,22 +14,24 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint16_t textColour, uint16_ } _tft.begin(screenId); _tft.setRotation(rotation); - _tft.setTextColor(textColour); _tft.fillScreen(backgroundColour); + _tft.setFont(gfxFont); + _tft.setTextSize(textSize); + fontHeight = gfxFont->yAdvance; } -void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, - uint8_t textSize, char *message) { +void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } + +void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, + uint8_t maxLength, char *message) { CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); CONSOLE.print(row); CONSOLE.print(F("|")); CONSOLE.print(column); CONSOLE.print(F("|")); CONSOLE.println(message); - _tft.setFont(fontName); - _tft.setTextColor(fontColour); + _tft.setTextColor(fontColour, backgroundColour); _tft.setCursor(column, row); - _tft.setTextSize(textSize); _tft.print(message); } diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 5feb9ad..3b52c86 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -9,13 +9,16 @@ class MCUFriendScreen : public EXScreen { public: MCUFriendScreen(MCUFRIEND_kbv &tft, uint8_t maxRows, uint8_t maxColumns); - virtual void setupScreen(uint8_t rotation, uint16_t textColour, uint16_t backgroundColour) override; + virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, + uint16_t backgroundColour) override; - virtual void writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, uint8_t textSize, + virtual void clearScreen(uint16_t backgroundColour) override; + + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; private: - MCUFRIEND_kbv _tft; + MCUFRIEND_kbv &_tft; }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 4c16d75..1adf07e 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -4,29 +4,23 @@ TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft, uint8_t maxRows, uint8_t maxColumns) : EXScreen(maxRows, maxColumns), _tft(tft) {} -void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint16_t textColour, uint16_t backgroundColour) { +void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, + uint16_t backgroundColour) { _tft.init(); _tft.setRotation(rotation); _tft.fillScreen(backgroundColour); + _tft.setFreeFont(gfxFont); + _tft.setTextSize(textSize); + fontHeight = gfxFont->yAdvance; } -void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, - uint8_t textSize, char *message) { - _tft.setTextSize(textSize); - _tft.setFreeFont(fontName); - uint8_t fontHeight = fontName->yAdvance; +void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } + +void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, + uint8_t maxLength, char *message) { uint8_t textRow = (row * fontHeight) + fontHeight; - _tft.setTextPadding(_tft.textWidth(" ")); - _tft.setCursor(column, textRow); - // uint8_t blankLength = strlen(message); - // CONSOLE.print(F("Blanking: ")); - // CONSOLE.println(blankLength); - _tft.setTextColor(BACKGROUND_COLOUR, BACKGROUND_COLOUR, true); - _tft.print(message); - _tft.setTextColor(fontColour, BACKGROUND_COLOUR, true); - // for (uint8_t i = 0; i < blankLength; i++) { - // _tft.print(" "); - // } - _tft.setCursor(column, textRow); - _tft.print(message); + uint8_t width = _tft.textWidth("A") * maxLength; + _tft.setTextPadding(width); + _tft.setTextColor(fontColour, backgroundColour); + _tft.drawString(message, column, textRow); } diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 9eaea03..5e06087 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -10,13 +10,16 @@ class TFT_eSPIScreen : public EXScreen { public: TFT_eSPIScreen(TFT_eSPI &tft, uint8_t maxRows, uint8_t maxColumns); - virtual void setupScreen(uint8_t rotation, uint16_t textColour, uint16_t backgroundColour) override; + virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, + uint16_t backgroundColour) override; - virtual void writeRow(uint8_t row, uint8_t column, const GFXfont *fontName, uint16_t fontColour, uint8_t textSize, + virtual void clearScreen(uint16_t backgroundColour) override; + + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; private: - TFT_eSPI _tft; + TFT_eSPI &_tft; }; #endif From c4c4a6a966e3e3abcf09837a036fde06eaa3877d Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 08:10:29 +1000 Subject: [PATCH 005/146] Fix STM PIO --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 23ec134..7f12476 100644 --- a/platformio.ini +++ b/platformio.ini @@ -101,7 +101,7 @@ lib_deps = upload_protocol = stlink build_flags = ${env.build_flags} - -std=-Os -g2 + -std=c++17 -Os -g2 monitor_speed = 115200 monitor_echo = yes @@ -114,7 +114,7 @@ lib_deps = upload_protocol = stlink build_flags = ${env.build_flags} - -std=-Os -g2 + -std=c++17 -Os -g2 monitor_speed = 115200 monitor_echo = yes From 8ba6494f0d6dd0482e348aa64a29e5b1eb13497f Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 08:13:50 +1000 Subject: [PATCH 006/146] Include fonts --- FontOptions.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/FontOptions.h b/FontOptions.h index 1128e76..3559455 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,11 +1,8 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -// #include "Arial9pt7b.h" -// #include "FreeSans12pt7b.h" -// #include -// #include -// #include +#include "Arial9pt7b.h" +#include "FreeSans12pt7b.h" /// @brief Macros for available colours #define BLACK 0x0000 From f3352be5e1ec0b31491e3d021113b1830718ea77 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 10:11:37 +1000 Subject: [PATCH 007/146] Font fixes --- FontOptions.h | 11 ++++------- TFT_eSPIScreen.cpp | 2 +- config.example.h | 2 +- version.h | 6 +++++- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/FontOptions.h b/FontOptions.h index 3559455..be407a8 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,9 +1,6 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#include "Arial9pt7b.h" -#include "FreeSans12pt7b.h" - /// @brief Macros for available colours #define BLACK 0x0000 #define RED 0xF800 @@ -14,9 +11,9 @@ #define WHITE 0xFFFF /// @brief Macros for available fonts -#define ARIAL9PT7B &Arial9pt7b -#define FREESANS &FreeSans9pt7b -#define FREEMONO &FreeMono9pt7b -#define FREESANS12PT7B &FreeSans12pt7b +#define SMALL &FreeSans9pt7b +#define MEDIUM &FreeSans12pt7b +#define LARGE &FreeSans18pt7b +#define XLARGE &FreeSans24pt7b #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 1adf07e..30f8a34 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -18,7 +18,7 @@ void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(ba void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint8_t textRow = (row * fontHeight) + fontHeight; + uint8_t textRow = (row * fontHeight) + row; uint8_t width = _tft.textWidth("A") * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); diff --git a/config.example.h b/config.example.h index 21d35a6..136f918 100644 --- a/config.example.h +++ b/config.example.h @@ -16,7 +16,7 @@ // #define SCREEN_2_TYPE MCU // Font options -#define TEXT_FONT ARIAL9PT7B +#define TEXT_FONT MEDIUM #define TEXT_COLOUR WHITE #define TEXT_SIZE 1 #define BACKGROUND_COLOUR BLACK diff --git a/version.h b/version.h index ae04c9d..491ccba 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,12 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.2" +#define VERSION "0.0.3" +// 0.0.3 includes: +// - Fixed TFT_eSPI row height calculations and overwrite of previous text +// - Moved to using TFT_eSPI fonts only +// - Refactored EXScreen and associated classes // 0.0.2 includes: // - Adding TFT_eSPI library // - Implement vertical scrolling From eb075ca710efa210af1e39351a39ed79e3863ed4 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 11:02:30 +1000 Subject: [PATCH 008/146] TFT_eSPI rows/cols calculated --- Defines.h | 4 ++-- EXDisplayClass.cpp | 8 ++++---- EXDisplayClass.h | 4 ++++ EXDisplayRow.cpp | 4 ++++ EXScreen.h | 22 ++++++++++------------ MCUFriendScreen.cpp | 4 ++-- MCUFriendScreen.h | 2 +- TFT_eSPIScreen.cpp | 32 ++++++++++++++++++++++++++++---- TFT_eSPIScreen.h | 2 +- version.h | 1 + 10 files changed, 57 insertions(+), 26 deletions(-) diff --git a/Defines.h b/Defines.h index 511c7fc..33b9fb2 100644 --- a/Defines.h +++ b/Defines.h @@ -29,9 +29,9 @@ #endif #if SCREEN_0_TYPE == MCU -#define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft, 8, 20), 30); +#define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); #elif SCREEN_0_TYPE == TFT -#define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft, 8, 20), 30); +#define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 321bbbb..eaaba0c 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -58,11 +58,11 @@ void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { } } row->setRowText(rowText); - row->setDisplayRow(rowNumber, _exScreen->getMaxRows()); + row->setDisplayRow(rowNumber, _exScreen->maxRows); } void EXDisplay::scroll() { - uint8_t screenRows = _exScreen->getMaxRows(); + uint8_t screenRows = _exScreen->maxRows; uint8_t newPosition = 0; if (_numberOfRows <= screenRows) { _scrollPosition = newPosition; @@ -85,9 +85,9 @@ void EXDisplay::autoScroll(unsigned long scrollDelay) { EXScreen *EXDisplay::getEXScreen() { return _exScreen; } -uint8_t EXDisplay::getScreenMaxRows() { return _exScreen->getMaxRows(); } +uint8_t EXDisplay::getScreenMaxRows() { return _exScreen->maxRows; } -uint8_t EXDisplay::getScreenMaxColumns() { return _exScreen->getMaxColumns(); } +uint8_t EXDisplay::getScreenMaxColumns() { return _exScreen->maxColumns; } /*** probably not needed void EXDisplay::deleteRowNumber(uint8_t rowNumber) { diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 6dca047..fc7e89c 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -14,6 +14,10 @@ */ class EXDisplay { public: + /// @brief Constructor for the EXDisplay class + /// @param displayNumber The ID of this display, 0 - 254 + /// @param exScreen Pointer to an associated EXScreen object to use for the physical display + /// @param maxScreenWidth Maximum number of characters that will fit on the physical screen, 0 - 255 EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScreenWidth); /// @brief Get the first EXDisplay object in the linked list diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 5b8dedb..037fe87 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -1,4 +1,6 @@ +#include "Defines.h" #include "EXDisplayRow.h" + /* * EXDisplayRow class implementation */ @@ -29,6 +31,8 @@ void EXDisplayRow::setRowText(char *rowText) { // the tail which we will probabaly need later anyway. _rowText = (char *)realloc(_rowText, bytesNeeded); _maxMalloc = bytesNeeded; + CONSOLE.print(F("maxMalloc: ")); + CONSOLE.println(_maxMalloc); } strcpy(_rowText, rowText); _changed = true; diff --git a/EXScreen.h b/EXScreen.h index 7fc2971..b0b64af 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -14,7 +14,11 @@ class EXScreen { public: /// @brief Constructor for a new EXScreen object - EXScreen(uint8_t maxRows, uint8_t maxColumns) : _maxRows(maxRows), _maxColumns(maxColumns) {} + EXScreen() { + fontHeight = 0; + maxRows = 0; + maxColumns = 0; + } /// @brief Virtual function to implement to setup the required parameters for the physical screen virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour); @@ -27,20 +31,14 @@ class EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); - /// @brief Get the maximum number of rows this screen can physically display - /// @return 0 - 255 - uint8_t getMaxRows() { return _maxRows; } - - /// @brief Get the maximum number of columns this screen can physically display - /// @return 0 - 255 - uint8_t getMaxColumns() { return _maxColumns; } - /// @brief Height of the font in use to determine row height uint8_t fontHeight; -private: - uint8_t _maxRows; // Maximum number of rows this screen can display - uint8_t _maxColumns; // Maximum number of columns this screen can display + /// @brief Maximum number of rows this screen can physically display + uint8_t maxRows; + + /// @brief Maximum number of columns this screen can physically display + uint8_t maxColumns; }; #endif diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index d95e8b9..790ca75 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,8 +1,8 @@ #include "Defines.h" #include "MCUFriendScreen.h" -MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft, uint8_t maxRows, uint8_t maxColumns) - : EXScreen(maxRows, maxColumns), _tft(tft) {} +MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) + : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) { diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 3b52c86..b38c2cd 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -7,7 +7,7 @@ class MCUFriendScreen : public EXScreen { public: - MCUFriendScreen(MCUFRIEND_kbv &tft, uint8_t maxRows, uint8_t maxColumns); + MCUFriendScreen(MCUFRIEND_kbv &tft); virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) override; diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 30f8a34..c6c0e53 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,8 +1,8 @@ #include "Defines.h" #include "TFT_eSPIScreen.h" -TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft, uint8_t maxRows, uint8_t maxColumns) - : EXScreen(maxRows, maxColumns), _tft(tft) {} +TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) + : EXScreen(), _tft(tft) {} void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) { @@ -12,14 +12,38 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8 _tft.setFreeFont(gfxFont); _tft.setTextSize(textSize); fontHeight = gfxFont->yAdvance; + uint8_t fontWidth = _tft.textWidth("A"); + maxRows = _tft.height() / fontHeight; + maxColumns = _tft.width() / fontWidth; + CONSOLE.print(F("Height|Width|maxRows|maxColumns: ")); + CONSOLE.print(_tft.height()); + CONSOLE.print(F("|")); + CONSOLE.print(_tft.width()); + CONSOLE.print(F("|")); + CONSOLE.print(maxRows); + CONSOLE.print(F("|")); + CONSOLE.println(maxColumns); } void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint8_t textRow = (row * fontHeight) + row; - uint8_t width = _tft.textWidth("A") * maxLength; + uint16_t textRow = (row * fontHeight) + row; + uint16_t width = _tft.textWidth("A") * maxLength; + CONSOLE.print(F("row|fontHeight|textRow|maxLength|textWidth|width ")); + CONSOLE.print(F("|")); + CONSOLE.print(row); + CONSOLE.print(F("|")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + CONSOLE.print(textRow); + CONSOLE.print(F("|")); + CONSOLE.print(maxLength); + CONSOLE.print(F("|")); + CONSOLE.print(_tft.textWidth("A")); + CONSOLE.print(F("|")); + CONSOLE.println(width); _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 5e06087..4fcd7a3 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -8,7 +8,7 @@ class TFT_eSPIScreen : public EXScreen { public: - TFT_eSPIScreen(TFT_eSPI &tft, uint8_t maxRows, uint8_t maxColumns); + TFT_eSPIScreen(TFT_eSPI &tft); virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) override; diff --git a/version.h b/version.h index 491ccba..9319988 100644 --- a/version.h +++ b/version.h @@ -8,6 +8,7 @@ // - Fixed TFT_eSPI row height calculations and overwrite of previous text // - Moved to using TFT_eSPI fonts only // - Refactored EXScreen and associated classes +// - Calculate max rows and columns based on resolution and specified font size // 0.0.2 includes: // - Adding TFT_eSPI library // - Implement vertical scrolling From 9420036c894346bd5f400a9d41519e0c17e34284 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 6 May 2024 18:59:40 +1000 Subject: [PATCH 009/146] TFT_eSPIScreen clean up --- TFT_eSPIScreen.cpp | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index c6c0e53..6b8b198 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,5 +1,5 @@ #include "Defines.h" -#include "TFT_eSPIScreen.h" +#include TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} @@ -15,14 +15,6 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8 uint8_t fontWidth = _tft.textWidth("A"); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; - CONSOLE.print(F("Height|Width|maxRows|maxColumns: ")); - CONSOLE.print(_tft.height()); - CONSOLE.print(F("|")); - CONSOLE.print(_tft.width()); - CONSOLE.print(F("|")); - CONSOLE.print(maxRows); - CONSOLE.print(F("|")); - CONSOLE.println(maxColumns); } void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } @@ -30,20 +22,8 @@ void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(ba void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { uint16_t textRow = (row * fontHeight) + row; - uint16_t width = _tft.textWidth("A") * maxLength; - CONSOLE.print(F("row|fontHeight|textRow|maxLength|textWidth|width ")); - CONSOLE.print(F("|")); - CONSOLE.print(row); - CONSOLE.print(F("|")); - CONSOLE.print(fontHeight); - CONSOLE.print(F("|")); - CONSOLE.print(textRow); - CONSOLE.print(F("|")); - CONSOLE.print(maxLength); - CONSOLE.print(F("|")); - CONSOLE.print(_tft.textWidth("A")); - CONSOLE.print(F("|")); - CONSOLE.println(width); + uint8_t fontWidth = _tft.textWidth("A"); + uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); From 00825b59d7e1592800114f68e6cebc526739a191 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Mon, 6 May 2024 17:59:46 +0100 Subject: [PATCH 010/146] Matt build flags ESP32 ST7796 SPI --- platformio.ini | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/platformio.ini b/platformio.ini index 7f12476..24aaa4e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -58,6 +58,28 @@ lib_deps = ${env.lib_deps} build_flags = ${env.build_flags} + -DUSER_SETUP_LOADED=1 + #-DRPI_DISPLAY_TYPE=0 + -DST7796_DRIVER=1 + -DTFT_SDA_READ=1 + -DTFT_BL=5 + -DTFT_MISO=19 + -DTFT_MOSI=23 + -DTFT_SCLK=18 + -DTFT_CS=15 + -DTFT_DC=2 + -DTFT_RST=4 + -DTOUCH_CS=22 + -DLOAD_GLCD=1 + -DLOAD_FONT2=1 + -DLOAD_FONT4=1 + -DLOAD_FONT6=1 + -DLOAD_FONT7=1 + -DLOAD_FONT8=1 + -DLOAD_GFXFF=1 + -DSMOOTH_FONT=1 + -DSPI_FREQUENCY=28000000 + -DSPI_TOUCH_FREQUENCY=2500000 monitor_speed = 115200 monitor_echo = yes From a3973c74842d9ef50086f84068c147ee1bb7e450 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Mon, 6 May 2024 21:53:41 +0100 Subject: [PATCH 011/146] maxrows and maxcolumns in mcufriend... --- MCUFriendScreen.cpp | 22 ++++++++++++++++++---- MCUFriendScreen.h | 4 ++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 790ca75..34b6047 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -18,22 +18,36 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint _tft.setFont(gfxFont); _tft.setTextSize(textSize); fontHeight = gfxFont->yAdvance; + uint8_t fontWidth = getCharacterWidth('A'); + maxRows = _tft.height() / fontHeight; + maxColumns = _tft.width() / fontWidth; +} + +uint8_t MCUFriendScreen::getCharacterWidth(char character) { + int16_t x1, y1; + uint16_t w, h; + _tft.getTextBounds(&character, 0, 0, &x1, &y1, &w, &h); + return w; } void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); + uint16_t textRow = (row * fontHeight) + row; + uint8_t fontWidth = getCharacterWidth('A'); + uint16_t width = fontWidth * maxLength; +/* CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); CONSOLE.print(row); CONSOLE.print(F("|")); CONSOLE.print(column); CONSOLE.print(F("|")); - CONSOLE.println(message); + CONSOLE.println(message);*/ + uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); - _tft.setCursor(column, row); + _tft.setCursor(paddedColumn, textRow); _tft.print(message); -} + } /* void EXScreen::newPage(uint8_t screenId) { diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index b38c2cd..7cc5984 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -16,9 +16,13 @@ class MCUFriendScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; + uint8_t getCharacterWidth(char character); private: MCUFRIEND_kbv &_tft; + uint8_t fontHeight; + uint8_t maxRows; + uint8_t maxColumns; }; #endif From b2b7c786e71cbb0fc816eb8927b3cd3fcfb7510c Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 7 May 2024 07:07:40 +1000 Subject: [PATCH 012/146] Change fonts --- FontOptions.h | 12 ++++++++---- MCUFriendScreen.cpp | 17 ++++++++--------- MCUFriendScreen.h | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/FontOptions.h b/FontOptions.h index be407a8..351b083 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -11,9 +11,13 @@ #define WHITE 0xFFFF /// @brief Macros for available fonts -#define SMALL &FreeSans9pt7b -#define MEDIUM &FreeSans12pt7b -#define LARGE &FreeSans18pt7b -#define XLARGE &FreeSans24pt7b +#define SMALL &FreeMono9pt7b +#define MEDIUM &FreeMono12pt7b +#define LARGE &FreeMono18pt7b +#define XLARGE &FreeMono24pt7b +#define SMALL_SANS &FreeSans9pt7b +#define MEDIUM_SANS &FreeSans12pt7b +#define LARGE_SANS &FreeSans18pt7b +#define XLARGE_SANS &FreeSans24pt7b #endif diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 34b6047..da38f85 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,8 +1,7 @@ #include "Defines.h" #include "MCUFriendScreen.h" -MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) - : EXScreen(), _tft(tft) {} +MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) { @@ -37,17 +36,17 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t textRow = (row * fontHeight) + row; uint8_t fontWidth = getCharacterWidth('A'); uint16_t width = fontWidth * maxLength; -/* CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); - CONSOLE.print(row); - CONSOLE.print(F("|")); - CONSOLE.print(column); - CONSOLE.print(F("|")); - CONSOLE.println(message);*/ + /* CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); + CONSOLE.print(row); + CONSOLE.print(F("|")); + CONSOLE.print(column); + CONSOLE.print(F("|")); + CONSOLE.println(message);*/ uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); _tft.setCursor(paddedColumn, textRow); _tft.print(message); - } +} /* void EXScreen::newPage(uint8_t screenId) { diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 7cc5984..7cce9db 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -13,7 +13,7 @@ class MCUFriendScreen : public EXScreen { uint16_t backgroundColour) override; virtual void clearScreen(uint16_t backgroundColour) override; - + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; uint8_t getCharacterWidth(char character); From c118ca684632413d4f6e49804d3f72e1c62a4621 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 7 May 2024 08:29:11 +1000 Subject: [PATCH 013/146] Fix fonts for MCU vs. TFT I hope --- EXScreen.h | 6 +++++- FontOptions.h | 11 +++++++++++ MCUFriendScreen.h | 2 +- config.example.h | 7 +++---- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/EXScreen.h b/EXScreen.h index b0b64af..6a078a6 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -1,9 +1,13 @@ #ifndef EXSCREEN_H #define EXSCREEN_H -// #include +#include "Defines.h" #include +#if SCREEN_0_TYPE==MCU +#include +#elif SCREEN_0_TYPE==TFT #include +#endif /// @brief This EXScreen class is designed to be extended by other screen classes that define the methods to perform the /// requesite activities according to the library in use to drive the physical display. diff --git a/FontOptions.h b/FontOptions.h index 351b083..3ce4550 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,6 +1,17 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H +#if SCREEN_0_TYPE==MCU +#include +#include +#include +#include +#include +#include +#include +#include +#endif + /// @brief Macros for available colours #define BLACK 0x0000 #define RED 0xF800 diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 7cce9db..e0cd485 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -2,7 +2,7 @@ #define MCUFRIENDSCREEN_H #include "EXScreen.h" -#include "MCUFRIEND_kbv.h" +#include #include class MCUFriendScreen : public EXScreen { diff --git a/config.example.h b/config.example.h index 136f918..e9ce765 100644 --- a/config.example.h +++ b/config.example.h @@ -1,10 +1,6 @@ #ifndef CONFIG_H #define CONFIG_H -// DO NOT REMOVE THIS LINE -// Include the various fonts and font colours available for use with EX-Display -#include "FontOptions.h" - // This is the configuration file for EX-Display // Entries here will control how the screen display will operate @@ -15,6 +11,9 @@ // #define SCREEN_1_TYPE MCU // #define SCREEN_2_TYPE MCU +// DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION +// Include the various fonts and font colours available for use with EX-Display +#include "FontOptions.h" // Font options #define TEXT_FONT MEDIUM #define TEXT_COLOUR WHITE From bc765e3641b7f31370268abd3d3c3415f7615e4d Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 7 May 2024 08:31:29 +1000 Subject: [PATCH 014/146] Update version --- version.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/version.h b/version.h index 9319988..e437c77 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,10 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.3" +#define VERSION "0.0.4" +// 0.0.4 includes: +// - Adjusted to use Adafruit fonts for MCUFRIEND_kbv // 0.0.3 includes: // - Fixed TFT_eSPI row height calculations and overwrite of previous text // - Moved to using TFT_eSPI fonts only From a5d6f65d29393fbe2f8146c0ed9d51a2bf18d3ca Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 7 May 2024 15:29:40 +1000 Subject: [PATCH 015/146] Quick and dirty start --- Defines.h | 3 +++ EX-Display.ino | 20 ++++++++------------ EXScreen.h | 4 ++-- FontOptions.h | 2 +- README.md | 17 +++++++++++------ config.example.h | 13 +++++++++++-- version.h | 5 ++++- 7 files changed, 40 insertions(+), 24 deletions(-) diff --git a/Defines.h b/Defines.h index 33b9fb2..e75aead 100644 --- a/Defines.h +++ b/Defines.h @@ -28,6 +28,8 @@ #define SCREEN_ROTATION 1 #endif +/* DISABLE AS THIS TIGHTLY COUPLES ONE DISPLAY TO ONE SCREEN +WE NEED TO HAVE A ONE SCREEN TO MANY DISPLAY RELATIONSHIP #if SCREEN_0_TYPE == MCU #define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); #elif SCREEN_0_TYPE == TFT @@ -35,6 +37,7 @@ #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif +*/ // Set up console and CS listener for Mega #if defined(ARDUINO_AVR_MEGA2560) diff --git a/EX-Display.ino b/EX-Display.ino index b180639..ee21c93 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -17,10 +17,12 @@ long screencount = 0; #define CS_LISTEN Serial #endif -#if SCREEN_0_TYPE == MCU +#if SCREEN_TYPE == MCU MCUFRIEND_kbv tft; -#elif SCREEN_0_TYPE == TFT +MCUFriendScreen *screen = new MCUFriendScreen(tft); +#elif SCREEN_TYPE == TFT TFT_eSPI tft = TFT_eSPI(); +TFT_eSPIScreen *screen = new TFT_eSPIScreen(tft); #endif void setup() { @@ -34,16 +36,10 @@ void setup() { // and how to call back when found. AtFinder::setup(100, updateEXDisplayRow); - // HARDWARE SETUP TODO..... Create an EXDisplay instance for each screen this ino wants to display. - // The updateEXDisplayRow will ignore messages destined for screens we dont have. - // For testing lets create some - SCREEN_0 -#ifdef SCREEN_1_TYPE - SCREEN_1 -#endif -#ifdef SCREEN_2_TYPE - SCREEN_2 -#endif + // Create display instances + new EXDisplay(DISPLAY_1_ID, screen, 30); + new EXDisplay(DISPLAY_2_ID, screen, 30); + new EXDisplay(DISPLAY_3_ID, screen, 30); for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); diff --git a/EXScreen.h b/EXScreen.h index 6a078a6..b6b4e0e 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -3,9 +3,9 @@ #include "Defines.h" #include -#if SCREEN_0_TYPE==MCU +#if SCREEN_TYPE == MCU #include -#elif SCREEN_0_TYPE==TFT +#elif SCREEN_TYPE == TFT #include #endif diff --git a/FontOptions.h b/FontOptions.h index 3ce4550..d1fcacd 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,7 +1,7 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#if SCREEN_0_TYPE==MCU +#if SCREEN_TYPE==MCU #include #include #include diff --git a/README.md b/README.md index 532587b..d5c1313 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ # EX-Display -A project for multiple displays connected to EX-CommandStation via I2C +A project for multiple displays connected to EX-CommandStation. -Raw proof of concept - developed on Mega2560 + mcufriend display shield, and using mcufriend_kbv library. Tests OK on Uno, although first half-char of each line is offscreen, TBD. +The aim is to extend the current JMRI type virtual screen functionality to be displayed on additional microcontrollers with attached screens by using the `SCREEN(screen, row, "Message")` EXRAIL command. -Connection: -- MEGA: GND-GND and RX pin 19 on mega to serial tx pin on EX-CS -- UNO: GND-GND and RX pin 0 (used testprobes to access both pins under display shield, needs a better physical solution) +## Terminology - Display vs. Screen -Zero apologies for raw first effort here +In the context of this project, the term "screen" is used when referring to a physical screen connected to a microcontroller to display information. This aligns with the use of the `SCREEN()` EXRAIL command, as it is designed to display information on a screen. + +The term "display" refers to a logical representation of a physical screen, enabling one physical screen to be used to dislay information from one or more EXRAIL defined screens. + +## Serial Connections + +- MEGA: GND-GND and RX pin 19 on mega to serial tx pin on EX-CS +- UNO: GND-GND and RX pin 0 (used testprobes to access both pins under display shield, needs a better physical solution) diff --git a/config.example.h b/config.example.h index e9ce765..7e09b29 100644 --- a/config.example.h +++ b/config.example.h @@ -4,13 +4,22 @@ // This is the configuration file for EX-Display // Entries here will control how the screen display will operate -// Define the screen types in use here - this needs to be ultra simplified at some point +// Define the pphysical screen types in use here - this needs to be ultra simplified at some point // Should we eventually support up to 3 displays? -#define SCREEN_0_TYPE MCU +// #define SCREEN_TYPE MCU +#define SCREEN_TYPE TFT +// #define SCREEN_0_TYPE MCU // #define SCREEN_0_TYPE TFT // #define SCREEN_1_TYPE MCU // #define SCREEN_2_TYPE MCU +// Define the number of logical displays here +// This is not a good way to do this +#define NUMBER_OF_DISPLAYS 3 +#define DISPLAY_1_ID 0 +#define DISPLAY_2_ID 3 +#define DISPLAY_3_ID 8 + // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display #include "FontOptions.h" diff --git a/version.h b/version.h index e437c77..e8c6654 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,11 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.4" +#define VERSION "0.0.5" +// 0.0.5 includes: +// - Refactor screen and logical display to enable multiple displays to use the same screen +// - Enable switching between logical displays // 0.0.4 includes: // - Adjusted to use Adafruit fonts for MCUFRIEND_kbv // 0.0.3 includes: From c6200a1c14225a09ec21121cc5ae35b836bf1827 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Tue, 7 May 2024 11:18:06 +0100 Subject: [PATCH 016/146] changes to MCUfriendScreen fontHeight... still not --- MCUFriendScreen.cpp | 32 +++++++++++++++++++++++++++++--- MCUFriendScreen.h | 7 ++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index da38f85..d68e77a 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -16,7 +16,10 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint _tft.fillScreen(backgroundColour); _tft.setFont(gfxFont); _tft.setTextSize(textSize); - fontHeight = gfxFont->yAdvance; + + //fontHeight = gfxFont->yAdvance; + fontHeight = getFontHeight(gfxFont); + uint8_t fontWidth = getCharacterWidth('A'); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; @@ -29,6 +32,16 @@ uint8_t MCUFriendScreen::getCharacterWidth(char character) { return w; } +uint8_t MCUFriendScreen::getFontHeight(const GFXfont *font) { + // Calculate font height (vertical advance - maximum ascent) + //return font->yAdvance - font->glyph->yOffset; + CONSOLE.print(F("| yAdvance")); + CONSOLE.print(font->yAdvance); + CONSOLE.print(F("| yOffset")); + CONSOLE.print(font->glyph->yOffset); + return font->yAdvance; +} + void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, @@ -36,16 +49,29 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t textRow = (row * fontHeight) + row; uint8_t fontWidth = getCharacterWidth('A'); uint16_t width = fontWidth * maxLength; - /* CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); + CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); CONSOLE.print(row); CONSOLE.print(F("|")); CONSOLE.print(column); CONSOLE.print(F("|")); - CONSOLE.println(message);*/ + CONSOLE.println(message); uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); _tft.setCursor(paddedColumn, textRow); _tft.print(message); + + CONSOLE.print(F("row ")); + CONSOLE.print(row); + CONSOLE.print(F("|")); + CONSOLE.print(F("textRow ")); + CONSOLE.print(textRow); + CONSOLE.print(F("|")); + CONSOLE.print(F("fontheight ")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + + + } /* diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index e0cd485..5132372 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -17,12 +17,13 @@ class MCUFriendScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; uint8_t getCharacterWidth(char character); + uint8_t getFontHeight(const GFXfont *font); private: MCUFRIEND_kbv &_tft; - uint8_t fontHeight; - uint8_t maxRows; - uint8_t maxColumns; + //uint8_t fontHeight; + //uint8_t maxRows; + //uint8_t maxColumns; }; #endif From 9d49b187776455f1e61db70a05ac3ed012c247ea Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 7 May 2024 12:12:25 +0100 Subject: [PATCH 017/146] Added InvertScreen Added config option for invert screen --- MCUFriendScreen.cpp | 3 +++ config.example.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index d68e77a..29573c2 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -13,6 +13,9 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint } _tft.begin(screenId); _tft.setRotation(rotation); + #ifdef INVERT_SCREEN + _tft.invertDisplay(screenId); + #endif _tft.fillScreen(backgroundColour); _tft.setFont(gfxFont); _tft.setTextSize(textSize); diff --git a/config.example.h b/config.example.h index e9ce765..6031499 100644 --- a/config.example.h +++ b/config.example.h @@ -23,6 +23,9 @@ // If rotation of the screen is required, set it here #define SCREEN_ROTATION 1 +// Some screens need inverting +#define INVERT_SCREEN + // First entries about the display you are using // as we display across the wider part of the screen iwdth is the larger dimension #define DISPLAY_WIDTH 320 From 86c7e8395b90215fde25af43de29eeb5bfe6b713 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 7 May 2024 12:34:35 +0100 Subject: [PATCH 018/146] Comment out INVERT INVERT_SCREEN commented out as default. --- config.example.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.example.h b/config.example.h index 6031499..1fe281e 100644 --- a/config.example.h +++ b/config.example.h @@ -23,8 +23,8 @@ // If rotation of the screen is required, set it here #define SCREEN_ROTATION 1 -// Some screens need inverting -#define INVERT_SCREEN +// Some screens need inverting. If your screen displays inverted colours uncomment the following line. +//#define INVERT_SCREEN // First entries about the display you are using // as we display across the wider part of the screen iwdth is the larger dimension From b5b39ee04efb1b72d50b8e953a08358cf2ab0c68 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Tue, 7 May 2024 12:53:55 +0100 Subject: [PATCH 019/146] Matt further mcufriend row calc debug --- MCUFriendScreen.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 29573c2..b454048 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -20,12 +20,18 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint _tft.setFont(gfxFont); _tft.setTextSize(textSize); + CONSOLE.print(F("| text Size")); + CONSOLE.print(textSize); + CONSOLE.print(F("| tft height")); + CONSOLE.print(_tft.height()); + //fontHeight = gfxFont->yAdvance; fontHeight = getFontHeight(gfxFont); uint8_t fontWidth = getCharacterWidth('A'); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; + } uint8_t MCUFriendScreen::getCharacterWidth(char character) { @@ -37,10 +43,10 @@ uint8_t MCUFriendScreen::getCharacterWidth(char character) { uint8_t MCUFriendScreen::getFontHeight(const GFXfont *font) { // Calculate font height (vertical advance - maximum ascent) - //return font->yAdvance - font->glyph->yOffset; - CONSOLE.print(F("| yAdvance")); + //return font->yAdvance; //- font->glyph->yOffset + CONSOLE.print(F("| yAdvance ")); CONSOLE.print(font->yAdvance); - CONSOLE.print(F("| yOffset")); + CONSOLE.print(F("| yOffset ")); CONSOLE.print(font->glyph->yOffset); return font->yAdvance; } From 066b14e7c28818a5eb1939a6cea0aed0216b7139 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 7 May 2024 17:34:32 +0100 Subject: [PATCH 020/146] Kludge works Kludge for MCUFRIEND --- EX-Display.ino | 8 ++++---- MCUFriendScreen.cpp | 36 +++++++++++++++++++++++++++--------- MCUFriendScreen.h | 1 + 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index b180639..c63306d 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -2,8 +2,6 @@ #include "AtFinder.h" #include "Defines.h" #include "DisplayFunctions.h" -#include "MCUFriendScreen.h" -#include "TFT_eSPIScreen.h" #include "version.h" #include @@ -18,9 +16,11 @@ long screencount = 0; #endif #if SCREEN_0_TYPE == MCU -MCUFRIEND_kbv tft; + #include "MCUFriendScreen.h" + MCUFRIEND_kbv tft; #elif SCREEN_0_TYPE == TFT -TFT_eSPI tft = TFT_eSPI(); + #include "TFT_eSPIScreen.h" + TFT_eSPI tft = TFT_eSPI(); #endif void setup() { diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index b454048..3a02f57 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -4,7 +4,8 @@ MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) { + uint16_t backgroundColour) { + uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); CONSOLE.println(screenId, HEX); @@ -13,11 +14,14 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint } _tft.begin(screenId); _tft.setRotation(rotation); + _tft.setFont(); + _tft.setFont(gfxFont); + #ifdef INVERT_SCREEN _tft.invertDisplay(screenId); #endif _tft.fillScreen(backgroundColour); - _tft.setFont(gfxFont); + _tft.setTextSize(textSize); CONSOLE.print(F("| text Size")); @@ -41,21 +45,34 @@ uint8_t MCUFriendScreen::getCharacterWidth(char character) { return w; } -uint8_t MCUFriendScreen::getFontHeight(const GFXfont *font) { +uint8_t MCUFriendScreen::getFontHeight(const GFXfont *gfxFont) { // Calculate font height (vertical advance - maximum ascent) //return font->yAdvance; //- font->glyph->yOffset +// int vpos = 0; +// switch (font) { +// case () : +// vpos = 21; +// break; +// case (SMALL || SMALL_SANS) : +// vpos = 27; +// break; +// default : +// vpos = 21; +// break; +// } + int yAdvance = 27; CONSOLE.print(F("| yAdvance ")); - CONSOLE.print(font->yAdvance); - CONSOLE.print(F("| yOffset ")); - CONSOLE.print(font->glyph->yOffset); - return font->yAdvance; + CONSOLE.print(yAdvance); + //CONSOLE.print(F("| yOffset ")); + //CONSOLE.print(font->glyph->yOffset); + return yAdvance; } void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint16_t textRow = (row * fontHeight) + row; + uint16_t textRow = ((row +2) * fontHeight) + row; uint8_t fontWidth = getCharacterWidth('A'); uint16_t width = fontWidth * maxLength; CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); @@ -66,7 +83,8 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, CONSOLE.println(message); uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); - _tft.setCursor(paddedColumn, textRow); + //_tft.setCursor(paddedColumn, textRow); + _tft.setCursor(1, textRow); _tft.print(message); CONSOLE.print(F("row ")); diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 5132372..02b7459 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -3,6 +3,7 @@ #include "EXScreen.h" #include +#include #include class MCUFriendScreen : public EXScreen { From c86dde1315e94cc1e094189ac5d8304ddd613724 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 7 May 2024 19:33:39 +0100 Subject: [PATCH 021/146] Made MCU work OK Made MCU work OK --- EX-Display.ino | 20 ++++++++++++++------ EXScreen.h | 3 +++ MCUFriendScreen.cpp | 16 ++++++++++++++-- MCUFriendScreen.h | 4 ++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index c63306d..98926c3 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -45,10 +45,20 @@ void setup() { SCREEN_2 #endif +for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { + display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); + } + for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); - display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display"); - display->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION); + display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, TEXT_SIZE, BACKGROUND_COLOUR); + #if SCREEN_0_TYPE == TFT + display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); + display->getEXScreen()->writeRow(0, 100, TEXT_COLOUR, BACKGROUND_COLOUR, 1, VERSION); + #elif SCREEN_0_TYPE == MCU + display->getEXScreen()->writeHeaderRow(1, 25, YELLOW, BACKGROUND_COLOUR, 20, "EX-Display"); + display->getEXScreen()->writeHeaderRow(200, 25, YELLOW, BACKGROUND_COLOUR, 20, VERSION); + #endif + CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); @@ -59,9 +69,7 @@ void setup() { delay(2000); - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); - } + // Setup the start screen. // if (MAX_SCREENS > 1) { diff --git a/EXScreen.h b/EXScreen.h index 6a078a6..e52eead 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -35,6 +35,9 @@ class EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); + virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + char *message); + /// @brief Height of the font in use to determine row height uint8_t fontHeight; diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 3a02f57..037e149 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -72,7 +72,7 @@ void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(b void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint16_t textRow = ((row +2) * fontHeight) + row; + uint16_t textRow = ((row +1) * fontHeight) + fontHeight; uint8_t fontWidth = getCharacterWidth('A'); uint16_t width = fontWidth * maxLength; CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); @@ -97,10 +97,22 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, CONSOLE.print(fontHeight); CONSOLE.print(F("|")); - } +void MCUFriendScreen::writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + char *message) { + + CONSOLE.print(F("Heading at column ")); + CONSOLE.print(column); + //uint16_t textRow = ((row +1) * fontHeight) + fontHeight; + _tft.setTextColor(fontColour, backgroundColour); + _tft.setCursor(row, column); + _tft.print(message); + _tft.drawFastHLine(0, 30, _tft.width(), WHITE); + +} + /* void EXScreen::newPage(uint8_t screenId) { // Method here to write new page to the display diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 02b7459..8533e5a 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -17,6 +17,10 @@ class MCUFriendScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; + + virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + char *message); + uint8_t getCharacterWidth(char character); uint8_t getFontHeight(const GFXfont *font); From 3e2317b1e282fefe22e5eebd7bce5622b2c7e836 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 8 May 2024 07:23:50 +1000 Subject: [PATCH 022/146] Hopefully MCU font fixes --- EX-Display.ino | 25 +++++------- EXDisplayRow.cpp | 2 - EXScreen.h | 7 +++- MCUFriendScreen.cpp | 97 ++++++++++++--------------------------------- MCUFriendScreen.h | 10 ++--- TFT_eSPIScreen.cpp | 14 +++++-- 6 files changed, 54 insertions(+), 101 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 98926c3..9122d8a 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -16,11 +16,11 @@ long screencount = 0; #endif #if SCREEN_0_TYPE == MCU - #include "MCUFriendScreen.h" - MCUFRIEND_kbv tft; +#include "MCUFriendScreen.h" +MCUFRIEND_kbv tft; #elif SCREEN_0_TYPE == TFT - #include "TFT_eSPIScreen.h" - TFT_eSPI tft = TFT_eSPI(); +#include "TFT_eSPIScreen.h" +TFT_eSPI tft = TFT_eSPI(); #endif void setup() { @@ -45,20 +45,15 @@ void setup() { SCREEN_2 #endif -for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { + for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); } for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, TEXT_SIZE, BACKGROUND_COLOUR); - #if SCREEN_0_TYPE == TFT - display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); - display->getEXScreen()->writeRow(0, 100, TEXT_COLOUR, BACKGROUND_COLOUR, 1, VERSION); - #elif SCREEN_0_TYPE == MCU - display->getEXScreen()->writeHeaderRow(1, 25, YELLOW, BACKGROUND_COLOUR, 20, "EX-Display"); - display->getEXScreen()->writeHeaderRow(200, 25, YELLOW, BACKGROUND_COLOUR, 20, VERSION); - #endif - + display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); + display->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, VERSION); + CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); @@ -69,8 +64,10 @@ for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->get delay(2000); + for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { + display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); + } - // Setup the start screen. // if (MAX_SCREENS > 1) { // currentScreenID = INITIAL_SCREEN; diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 037fe87..4a03c07 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -31,8 +31,6 @@ void EXDisplayRow::setRowText(char *rowText) { // the tail which we will probabaly need later anyway. _rowText = (char *)realloc(_rowText, bytesNeeded); _maxMalloc = bytesNeeded; - CONSOLE.print(F("maxMalloc: ")); - CONSOLE.println(_maxMalloc); } strcpy(_rowText, rowText); _changed = true; diff --git a/EXScreen.h b/EXScreen.h index e52eead..e4ab6d5 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -35,12 +35,15 @@ class EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); - virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message); + // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + // char *message); /// @brief Height of the font in use to determine row height uint8_t fontHeight; + /// @brief Width of the font in use to determine max columns + uint8_t fontWidth; + /// @brief Maximum number of rows this screen can physically display uint8_t maxRows; diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 037e149..c874c80 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -4,7 +4,7 @@ MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) { + uint16_t backgroundColour) { uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); @@ -14,28 +14,23 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint } _tft.begin(screenId); _tft.setRotation(rotation); - _tft.setFont(); _tft.setFont(gfxFont); - - #ifdef INVERT_SCREEN - _tft.invertDisplay(screenId); - #endif +#ifdef INVERT_SCREEN + _tft.invertDisplay(screenId); +#endif _tft.fillScreen(backgroundColour); - - _tft.setTextSize(textSize); - - CONSOLE.print(F("| text Size")); - CONSOLE.print(textSize); - CONSOLE.print(F("| tft height")); - CONSOLE.print(_tft.height()); - - //fontHeight = gfxFont->yAdvance; - fontHeight = getFontHeight(gfxFont); - - uint8_t fontWidth = getCharacterWidth('A'); + fontHeight = gfxFont->yAdvance; + fontWidth = getCharacterWidth('A'); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; - + CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + CONSOLE.print(fontWidth); + CONSOLE.print(F("|")); + CONSOLE.print(_tft.height()); + CONSOLE.print(F("|")); + CONSOLE.println(_tft.width()); } uint8_t MCUFriendScreen::getCharacterWidth(char character) { @@ -45,73 +40,31 @@ uint8_t MCUFriendScreen::getCharacterWidth(char character) { return w; } -uint8_t MCUFriendScreen::getFontHeight(const GFXfont *gfxFont) { - // Calculate font height (vertical advance - maximum ascent) - //return font->yAdvance; //- font->glyph->yOffset -// int vpos = 0; -// switch (font) { -// case () : -// vpos = 21; -// break; -// case (SMALL || SMALL_SANS) : -// vpos = 27; -// break; -// default : -// vpos = 21; -// break; -// } - int yAdvance = 27; - CONSOLE.print(F("| yAdvance ")); - CONSOLE.print(yAdvance); - //CONSOLE.print(F("| yOffset ")); - //CONSOLE.print(font->glyph->yOffset); - return yAdvance; -} - void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint16_t textRow = ((row +1) * fontHeight) + fontHeight; + uint16_t textRow = ((row + 1) * fontHeight) + fontHeight; uint8_t fontWidth = getCharacterWidth('A'); uint16_t width = fontWidth * maxLength; - CONSOLE.print(F("Write to screen DisplayRow|Column|Message: ")); - CONSOLE.print(row); - CONSOLE.print(F("|")); - CONSOLE.print(column); - CONSOLE.print(F("|")); - CONSOLE.println(message); uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); //_tft.setCursor(paddedColumn, textRow); _tft.setCursor(1, textRow); _tft.print(message); - - CONSOLE.print(F("row ")); - CONSOLE.print(row); - CONSOLE.print(F("|")); - CONSOLE.print(F("textRow ")); - CONSOLE.print(textRow); - CONSOLE.print(F("|")); - CONSOLE.print(F("fontheight ")); - CONSOLE.print(fontHeight); - CONSOLE.print(F("|")); - - } -void MCUFriendScreen::writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message) { +// void MCUFriendScreen::writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, +// uint8_t maxLength, char *message) { - CONSOLE.print(F("Heading at column ")); - CONSOLE.print(column); - //uint16_t textRow = ((row +1) * fontHeight) + fontHeight; - _tft.setTextColor(fontColour, backgroundColour); - _tft.setCursor(row, column); - _tft.print(message); - _tft.drawFastHLine(0, 30, _tft.width(), WHITE); - -} +// CONSOLE.print(F("Heading at column ")); +// CONSOLE.print(column); +// // uint16_t textRow = ((row +1) * fontHeight) + fontHeight; +// _tft.setTextColor(fontColour, backgroundColour); +// _tft.setCursor(row, column); +// _tft.print(message); +// _tft.drawFastHLine(0, 30, _tft.width(), WHITE); +// } /* void EXScreen::newPage(uint8_t screenId) { diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 8533e5a..c9dc1a2 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -2,9 +2,9 @@ #define MCUFRIENDSCREEN_H #include "EXScreen.h" -#include #include #include +#include class MCUFriendScreen : public EXScreen { public: @@ -18,17 +18,13 @@ class MCUFriendScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; - virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message); + // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, + // uint8_t maxLength, char *message); uint8_t getCharacterWidth(char character); - uint8_t getFontHeight(const GFXfont *font); private: MCUFRIEND_kbv &_tft; - //uint8_t fontHeight; - //uint8_t maxRows; - //uint8_t maxColumns; }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 6b8b198..db6f350 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,8 +1,7 @@ #include "Defines.h" #include -TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) - : EXScreen(), _tft(tft) {} +TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) { @@ -12,9 +11,17 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8 _tft.setFreeFont(gfxFont); _tft.setTextSize(textSize); fontHeight = gfxFont->yAdvance; - uint8_t fontWidth = _tft.textWidth("A"); + fontWidth = _tft.textWidth("A"); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; + CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + CONSOLE.print(fontWidth); + CONSOLE.print(F("|")); + CONSOLE.print(_tft.height()); + CONSOLE.print(F("|")); + CONSOLE.println(_tft.width()); } void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } @@ -22,7 +29,6 @@ void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(ba void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { uint16_t textRow = (row * fontHeight) + row; - uint8_t fontWidth = _tft.textWidth("A"); uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); From b0037fadb228c32da17e5075fde529d3548bb41d Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 8 May 2024 08:53:18 +1000 Subject: [PATCH 023/146] Fix MCU rows, extra debug --- EX-Display.ino | 8 ++++++++ MCUFriendScreen.cpp | 17 ++++++++++++----- MCUFriendScreen.h | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 9122d8a..99bcf4b 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -49,6 +49,14 @@ void setup() { display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); } + const GFXfont *tempFont = TEXT_FONT; + CONSOLE.print(F("DEBUG Font: first|last|yAdvance: ")); + CONSOLE.print(tempFont->first); + CONSOLE.print(F("|")); + CONSOLE.print(tempFont->last); + CONSOLE.print(F("|")); + CONSOLE.println(tempFont->yAdvance); + for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, TEXT_SIZE, BACKGROUND_COLOUR); display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index c874c80..afb2d1e 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -6,6 +6,13 @@ MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour) { + CONSOLE.print(F("DEBUG Font: first|last|yAdvance: ")); + CONSOLE.print(gfxFont->first); + CONSOLE.print(F("|")); + CONSOLE.print(gfxFont->last); + CONSOLE.print(F("|")); + CONSOLE.println(gfxFont->yAdvance); + uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); CONSOLE.println(screenId, HEX); @@ -15,12 +22,13 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint _tft.begin(screenId); _tft.setRotation(rotation); _tft.setFont(gfxFont); + _tft.setTextSize(textSize); #ifdef INVERT_SCREEN _tft.invertDisplay(screenId); #endif _tft.fillScreen(backgroundColour); fontHeight = gfxFont->yAdvance; - fontWidth = getCharacterWidth('A'); + fontWidth = getCharacterWidth("A"); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); @@ -33,10 +41,10 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint CONSOLE.println(_tft.width()); } -uint8_t MCUFriendScreen::getCharacterWidth(char character) { +uint8_t MCUFriendScreen::getCharacterWidth(const char *character) { int16_t x1, y1; uint16_t w, h; - _tft.getTextBounds(&character, 0, 0, &x1, &y1, &w, &h); + _tft.getTextBounds(character, 0, 0, &x1, &y1, &w, &h); return w; } @@ -44,8 +52,7 @@ void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(b void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint16_t textRow = ((row + 1) * fontHeight) + fontHeight; - uint8_t fontWidth = getCharacterWidth('A'); + uint16_t textRow = (row * fontHeight) + row; uint16_t width = fontWidth * maxLength; uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index c9dc1a2..9f70bb7 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -21,7 +21,7 @@ class MCUFriendScreen : public EXScreen { // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, // uint8_t maxLength, char *message); - uint8_t getCharacterWidth(char character); + uint8_t getCharacterWidth(const char *character); private: MCUFRIEND_kbv &_tft; From c04df0b9ab2ab13abb1b0af15028f75d9c9933d6 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 8 May 2024 15:20:28 +1000 Subject: [PATCH 024/146] Rudimentary timed switching working --- DisplayFunctions.cpp | 27 +++++++++++++++++++-------- DisplayFunctions.h | 7 +++++-- EX-Display.ino | 13 +++++++------ EXDisplayClass.cpp | 22 ++++++++++++++++++++++ EXDisplayClass.h | 16 ++++++++++++++++ config.example.h | 3 +++ 6 files changed, 72 insertions(+), 16 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 3be5322..d2fb8be 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -41,18 +41,29 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { } } -void updateScreens() { - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - auto *screen = display->getEXScreen(); +void updateScreen() { + EXDisplay *display = EXDisplay::getActiveDisplay(); + auto *screen = display->getEXScreen(); + if (display->needsRedraw()) { + screen->clearScreen(BACKGROUND_COLOUR); + } #ifdef SCROLLTIME - display->autoScroll(SCROLLTIME); + display->autoScroll(SCROLLTIME); #endif - for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { - if (row->needsRender() && row->isChanged()) { - screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), row->getRowText()); - } + for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { + if (row->needsRender() && (row->isChanged() || display->needsRedraw())) { + screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), row->getRowText()); } } + display->resetRedraw(); +} + +unsigned long lastDisplaySwitch = 0; +void switchDisplays() { + if (millis() - lastDisplaySwitch > DISPLAY_SWITCH_TIME) { + lastDisplaySwitch = millis(); + EXDisplay::switchActiveDisplay(); + } } void displayAllRows() { diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 9495ab4..04a8b38 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -15,8 +15,11 @@ extern bool debug; /// @param text Char array of text void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text); -/// @brief Iterate through each display object and update the display of their associated screen -void updateScreens(); +/// @brief Update the active display on its associated screen +void updateScreen(); + +/// @brief Switch active displays if enabled +void switchDisplays(); /// @brief Display all rows on all screens - handy for debug void displayAllRows(); diff --git a/EX-Display.ino b/EX-Display.ino index ee21c93..6ac3ca1 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -43,8 +43,6 @@ void setup() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); - display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display"); - display->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION); CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); @@ -53,11 +51,13 @@ void setup() { CONSOLE.println(display->getScreenMaxColumns()); } + EXDisplay *activeDisplay = EXDisplay::getActiveDisplay(); + activeDisplay->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display"); + activeDisplay->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION); + delay(2000); - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); - } + activeDisplay->getEXScreen()->clearScreen(BACKGROUND_COLOUR); // Setup the start screen. // if (MAX_SCREENS > 1) { @@ -91,7 +91,8 @@ void loop() { // No data incoming so see if we need to display anything // DISABLE IN STARTUPPHASE else { - updateScreens(); + updateScreen(); + switchDisplays(); /* DISABLE SO IT WILL COMPILE if (StartupPhase==false){ // add thie following in once display is working diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index eaaba0c..64c1118 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -3,6 +3,9 @@ /// @brief Define the first EXDisplay object as a nullptr EXDisplay *EXDisplay::_first = nullptr; +/// @brief Define the active display as nullptr also +EXDisplay *EXDisplay::_activeDisplay = nullptr; + /* * EXDisplay class implementation */ @@ -14,6 +17,10 @@ EXDisplay::EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScree _numberOfRows = 0; _scrollPosition = 0; _lastScrollTime = 0; + _needsRedraw = false; + if (!_activeDisplay) { + _activeDisplay = _first; + } } EXDisplay *EXDisplay::getFirst() { return _first; } @@ -89,6 +96,10 @@ uint8_t EXDisplay::getScreenMaxRows() { return _exScreen->maxRows; } uint8_t EXDisplay::getScreenMaxColumns() { return _exScreen->maxColumns; } +bool EXDisplay::needsRedraw() { return _needsRedraw; } + +void EXDisplay::resetRedraw() { _needsRedraw = false; } + /*** probably not needed void EXDisplay::deleteRowNumber(uint8_t rowNumber) { EXDisplayRow *currentRow = _firstRow; @@ -114,3 +125,14 @@ EXDisplay *EXDisplay::getDisplayByNumber(uint8_t displayNumber) { } return nullptr; } + +EXDisplay *EXDisplay::getActiveDisplay() { return _activeDisplay; } + +void EXDisplay::switchActiveDisplay() { + if (_activeDisplay->_next) { + _activeDisplay = _activeDisplay->_next; + } else { + _activeDisplay = _first; + } + _activeDisplay->_needsRedraw = true; +} diff --git a/EXDisplayClass.h b/EXDisplayClass.h index fc7e89c..4b307b4 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -65,6 +65,13 @@ class EXDisplay { /// @return 0 - 255 uint8_t getScreenMaxColumns(); + /// @brief Check if this display needs to be redrawn + /// @return True|False + bool needsRedraw(); + + /// @brief Reset the needsRedraw flag + void resetRedraw(); + /// @brief Check if there is already a display created at the specified number /// @param displayNumber True|False /// @return @@ -75,6 +82,13 @@ class EXDisplay { /// @return EXDisplay object, or nullptr if not exists static EXDisplay *getDisplayByNumber(uint8_t displayNumber); + /// @brief Get the currently selected display + /// @return Pointer to the currently selected display + static EXDisplay *getActiveDisplay(); + + /// @brief Switch active display to the next display in the linked list + static void switchActiveDisplay(); + private: // chaining displays static EXDisplay *_first; @@ -88,6 +102,8 @@ class EXDisplay { uint8_t _numberOfRows; // Calculated number of rows for this screen uint8_t _scrollPosition; // Row number that is top of screen for scrolling support unsigned long _lastScrollTime; // Last time in milliseconds an auto scroll was done + bool _needsRedraw; // Flag if this display needs to be redrawn + static EXDisplay *_activeDisplay; }; #endif diff --git a/config.example.h b/config.example.h index 7e09b29..9e9e954 100644 --- a/config.example.h +++ b/config.example.h @@ -57,6 +57,9 @@ // if the touch screen not in use, Now define the scroll requirements #define SCROLLTIME 5000 // 5 seconds +// If hosting multiple displays on the same screen, set switching delay +#define DISPLAY_SWITCH_TIME 5000 + // And now define the maximum text length. #define MAX_LINE_LENGTH 30 From 84dfa74ab51ea34d6e60c51eb826ca0a1383dc57 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 8 May 2024 19:42:45 +0100 Subject: [PATCH 025/146] Added include guards Added include guards to stop both sets of libraries loading. --- EX-Display.ino | 13 ++++++++----- MCUFriendScreen.cpp | 7 +++++++ MCUFriendScreen.h | 4 ++++ TFT_eSPIScreen.cpp | 6 ++++++ TFT_eSPIScreen.h | 5 +++++ 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 99bcf4b..0d34efa 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -1,10 +1,11 @@ - +#include "config.h" #include "AtFinder.h" #include "Defines.h" #include "DisplayFunctions.h" #include "version.h" #include + bool StartupPhase = true; unsigned long timestamp = 0; long screencount = 0; @@ -16,11 +17,13 @@ long screencount = 0; #endif #if SCREEN_0_TYPE == MCU -#include "MCUFriendScreen.h" -MCUFRIEND_kbv tft; + #define NEEDS_MCU + #include "MCUFriendScreen.h" + MCUFRIEND_kbv tft; #elif SCREEN_0_TYPE == TFT -#include "TFT_eSPIScreen.h" -TFT_eSPI tft = TFT_eSPI(); + #define NEEDS_TFT + #include "TFT_eSPIScreen.h" + TFT_eSPI tft = TFT_eSPI(); #endif void setup() { diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index afb2d1e..b476144 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,6 +1,11 @@ +#ifdef NEEDS_MCU + +CONSOLE.println("Loading MCUFRIEND code"); + #include "Defines.h" #include "MCUFriendScreen.h" + MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, @@ -85,3 +90,5 @@ void EXScreen::newPage(uint8_t screenId) { tft.drawFastHLine(0, 25, tft.width(), WHITE); tft.setTextColor(WHITE); // set this for all screen lines */ + +#endif \ No newline at end of file diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 9f70bb7..e3af3a1 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -1,6 +1,9 @@ +#ifdef NEEDS_MCU + #ifndef MCUFRIENDSCREEN_H #define MCUFRIENDSCREEN_H + #include "EXScreen.h" #include #include @@ -28,3 +31,4 @@ class MCUFriendScreen : public EXScreen { }; #endif +#endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index db6f350..43660da 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,3 +1,7 @@ +#ifdef NEEDS_TFT + +CONSOLE.println("Loading TFT_eSPI code"); + #include "Defines.h" #include @@ -34,3 +38,5 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); } + +#endif diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 4fcd7a3..0e85867 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -1,6 +1,9 @@ +#ifdef NEEDS_TFT + #ifndef TFT_ESPISCREEN_H #define TFT_ESPISCREEN_H + #include "EXScreen.h" #include #include @@ -23,3 +26,5 @@ class TFT_eSPIScreen : public EXScreen { }; #endif + +#endif From 26622decd7bfdbd7ac25172be292ccb82cbdc459 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 8 May 2024 20:03:42 +0100 Subject: [PATCH 026/146] Fixed compile error Fixed compile error --- DisplayFunctions.cpp | 1 + EX-Display.ino | 4 +--- EXDisplayClass.h | 3 ++- MCUFriendScreen.cpp | 3 ++- MCUFriendScreen.h | 1 + TFT_eSPIScreen.cpp | 4 +++- TFT_eSPIScreen.h | 1 + 7 files changed, 11 insertions(+), 6 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 3be5322..d8c0738 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -1,3 +1,4 @@ +#include "config.h" #include "Defines.h" #include "DisplayFunctions.h" #include "MCUFriendScreen.h" diff --git a/EX-Display.ino b/EX-Display.ino index 0d34efa..6459d9f 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -16,12 +16,10 @@ long screencount = 0; #define CS_LISTEN Serial #endif -#if SCREEN_0_TYPE == MCU - #define NEEDS_MCU +#if SCREEN_0_TYPE == MCU #include "MCUFriendScreen.h" MCUFRIEND_kbv tft; #elif SCREEN_0_TYPE == TFT - #define NEEDS_TFT #include "TFT_eSPIScreen.h" TFT_eSPI tft = TFT_eSPI(); #endif diff --git a/EXDisplayClass.h b/EXDisplayClass.h index fc7e89c..d2026fb 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -1,8 +1,9 @@ #ifndef EXDISPLAYCLASS_H #define EXDISPLAYCLASS_H -#include +#include +#include "config.h" #include "Defines.h" #include "EXDisplayRow.h" #include "EXScreen.h" diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index b476144..3550e4b 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,10 +1,11 @@ +#include "config.h" #ifdef NEEDS_MCU -CONSOLE.println("Loading MCUFRIEND code"); #include "Defines.h" #include "MCUFriendScreen.h" +//CONSOLE.println("Loading MCUFRIEND code"); MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index e3af3a1..e7c1a26 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -1,3 +1,4 @@ +#include "config.h" #ifdef NEEDS_MCU #ifndef MCUFRIENDSCREEN_H diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 43660da..c89ad68 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,10 +1,12 @@ +#include "config.h" #ifdef NEEDS_TFT -CONSOLE.println("Loading TFT_eSPI code"); #include "Defines.h" #include +//CONSOLE.println("Loading TFT_eSPI code"); + TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 0e85867..7d0281c 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -1,3 +1,4 @@ +#include "config.h" #ifdef NEEDS_TFT #ifndef TFT_ESPISCREEN_H From 61409f68be91a2849d920e34a102e8ddd9bf6517 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 8 May 2024 20:10:59 +0100 Subject: [PATCH 027/146] Update config.example.h Update config.example.h --- config.example.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/config.example.h b/config.example.h index 1fe281e..59d313b 100644 --- a/config.example.h +++ b/config.example.h @@ -11,6 +11,12 @@ // #define SCREEN_1_TYPE MCU // #define SCREEN_2_TYPE MCU +#if SCREEN_0_TYPE == MCU + #define NEEDS_MCU +#elif SCREEN_0_TYPE == TFT + #define NEEDS_TFT +#endif + // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display #include "FontOptions.h" From 783f7247ef0f2b4f6f3d25fadcdce61ff5435919 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Wed, 8 May 2024 20:16:46 +0100 Subject: [PATCH 028/146] Added to defines.h added to defines.h --- Defines.h | 6 ++++-- MCUFriendScreen.cpp | 4 ++-- MCUFriendScreen.h | 2 +- TFT_eSPIScreen.cpp | 4 ++-- TFT_eSPIScreen.h | 2 +- config.example.h | 6 +----- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Defines.h b/Defines.h index 33b9fb2..03495dd 100644 --- a/Defines.h +++ b/Defines.h @@ -29,9 +29,11 @@ #endif #if SCREEN_0_TYPE == MCU -#define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); + #define NEEDS_MCU + #define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); #elif SCREEN_0_TYPE == TFT -#define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); + #define NEEDS_TFT + #define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 3550e4b..667ec66 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,8 +1,8 @@ -#include "config.h" +#include "Defines.h" #ifdef NEEDS_MCU -#include "Defines.h" + #include "MCUFriendScreen.h" //CONSOLE.println("Loading MCUFRIEND code"); diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index e7c1a26..0a23002 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -1,4 +1,4 @@ -#include "config.h" +#include "Defines.h" #ifdef NEEDS_MCU #ifndef MCUFRIENDSCREEN_H diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index c89ad68..7f21d63 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,8 +1,8 @@ -#include "config.h" +#include "Defines.h" #ifdef NEEDS_TFT -#include "Defines.h" + #include //CONSOLE.println("Loading TFT_eSPI code"); diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 7d0281c..4ba4896 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -1,4 +1,4 @@ -#include "config.h" +#include "Defines.h" #ifdef NEEDS_TFT #ifndef TFT_ESPISCREEN_H diff --git a/config.example.h b/config.example.h index 59d313b..cfb63ac 100644 --- a/config.example.h +++ b/config.example.h @@ -11,11 +11,7 @@ // #define SCREEN_1_TYPE MCU // #define SCREEN_2_TYPE MCU -#if SCREEN_0_TYPE == MCU - #define NEEDS_MCU -#elif SCREEN_0_TYPE == TFT - #define NEEDS_TFT -#endif + // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display From 9090b02fe0bd405cedd454894981d0997828ccd1 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 9 May 2024 07:30:54 +1000 Subject: [PATCH 029/146] Working on MCU and TFT --- DisplayFunctions.cpp | 4 ++-- EX-Display.ino | 16 +++++++--------- EXDisplayClass.h | 5 ++--- EXScreen.h | 14 +++++++++----- MCUFriendScreen.cpp | 10 +++------- MCUFriendScreen.h | 5 ++--- TFT_eSPIScreen.cpp | 8 +++----- TFT_eSPIScreen.h | 4 +--- 8 files changed, 29 insertions(+), 37 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index d8c0738..45b9a36 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -1,4 +1,3 @@ -#include "config.h" #include "Defines.h" #include "DisplayFunctions.h" #include "MCUFriendScreen.h" @@ -50,7 +49,8 @@ void updateScreens() { #endif for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { if (row->needsRender() && row->isChanged()) { - screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), row->getRowText()); + screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), + row->getRowText()); } } } diff --git a/EX-Display.ino b/EX-Display.ino index 6459d9f..eede0ca 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -1,11 +1,9 @@ -#include "config.h" #include "AtFinder.h" #include "Defines.h" #include "DisplayFunctions.h" #include "version.h" #include - bool StartupPhase = true; unsigned long timestamp = 0; long screencount = 0; @@ -16,12 +14,12 @@ long screencount = 0; #define CS_LISTEN Serial #endif -#if SCREEN_0_TYPE == MCU - #include "MCUFriendScreen.h" - MCUFRIEND_kbv tft; +#if SCREEN_0_TYPE == MCU +#include "MCUFriendScreen.h" +MCUFRIEND_kbv tft; #elif SCREEN_0_TYPE == TFT - #include "TFT_eSPIScreen.h" - TFT_eSPI tft = TFT_eSPI(); +#include "TFT_eSPIScreen.h" +TFT_eSPI tft = TFT_eSPI(); #endif void setup() { @@ -59,7 +57,7 @@ void setup() { CONSOLE.println(tempFont->yAdvance); for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, TEXT_SIZE, BACKGROUND_COLOUR); + display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_SIZE, BACKGROUND_COLOUR); display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); display->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, VERSION); @@ -76,7 +74,7 @@ void setup() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); } - + // Setup the start screen. // if (MAX_SCREENS > 1) { // currentScreenID = INITIAL_SCREEN; diff --git a/EXDisplayClass.h b/EXDisplayClass.h index d2026fb..6561a3d 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -1,12 +1,11 @@ #ifndef EXDISPLAYCLASS_H #define EXDISPLAYCLASS_H - -#include -#include "config.h" #include "Defines.h" #include "EXDisplayRow.h" #include "EXScreen.h" +#include + /** * @brief Class for each display. diff --git a/EXScreen.h b/EXScreen.h index e4ab6d5..84e510e 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -3,9 +3,9 @@ #include "Defines.h" #include -#if SCREEN_0_TYPE==MCU +#if SCREEN_0_TYPE == MCU #include -#elif SCREEN_0_TYPE==TFT +#elif SCREEN_0_TYPE == TFT #include #endif @@ -24,8 +24,11 @@ class EXScreen { maxColumns = 0; } - /// @brief Virtual function to implement to setup the required parameters for the physical screen - virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, uint16_t backgroundColour); + /// @brief Virtual function to implement to setup the physical screen parameters + /// @param rotation Rotate the screen if necessary + /// @param textSize Pixel multiplier to increase text size if desired + /// @param backgroundColour Fill the screen with this colour during setup + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour); /// @brief Virtual function to implement /// @param backgroundColour @@ -35,7 +38,8 @@ class EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); - // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t + // maxLength, // char *message); /// @brief Height of the font in use to determine row height diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 667ec66..137e87e 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -1,24 +1,20 @@ #include "Defines.h" #ifdef NEEDS_MCU - - #include "MCUFriendScreen.h" -//CONSOLE.println("Loading MCUFRIEND code"); - MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} -void MCUFriendScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) { +void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { + const GFXfont *gfxFont = TEXT_FONT; CONSOLE.print(F("DEBUG Font: first|last|yAdvance: ")); CONSOLE.print(gfxFont->first); CONSOLE.print(F("|")); CONSOLE.print(gfxFont->last); CONSOLE.print(F("|")); CONSOLE.println(gfxFont->yAdvance); - + uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); CONSOLE.println(screenId, HEX); diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 0a23002..544ff14 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -4,7 +4,6 @@ #ifndef MCUFRIENDSCREEN_H #define MCUFRIENDSCREEN_H - #include "EXScreen.h" #include #include @@ -14,8 +13,7 @@ class MCUFriendScreen : public EXScreen { public: MCUFriendScreen(MCUFRIEND_kbv &tft); - virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) override; + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) override; virtual void clearScreen(uint16_t backgroundColour) override; @@ -29,6 +27,7 @@ class MCUFriendScreen : public EXScreen { private: MCUFRIEND_kbv &_tft; + GFXfont _gfxFont; }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 7f21d63..48f82fa 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,16 +1,14 @@ #include "Defines.h" #ifdef NEEDS_TFT - - #include -//CONSOLE.println("Loading TFT_eSPI code"); +// CONSOLE.println("Loading TFT_eSPI code"); TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} -void TFT_eSPIScreen::setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) { +void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { + const GFXfont *gfxFont = TEXT_FONT; _tft.init(); _tft.setRotation(rotation); _tft.fillScreen(backgroundColour); diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 4ba4896..6cffe4d 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -4,7 +4,6 @@ #ifndef TFT_ESPISCREEN_H #define TFT_ESPISCREEN_H - #include "EXScreen.h" #include #include @@ -14,8 +13,7 @@ class TFT_eSPIScreen : public EXScreen { public: TFT_eSPIScreen(TFT_eSPI &tft); - virtual void setupScreen(uint8_t rotation, const GFXfont *gfxFont, uint8_t textSize, - uint16_t backgroundColour) override; + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) override; virtual void clearScreen(uint16_t backgroundColour) override; From 8a65d18ef95e988585c69567cc91e33cc009dd5f Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 9 May 2024 07:55:02 +1000 Subject: [PATCH 030/146] Clean up --- Arial9pt7b.h | 205 ---------------------------------- EX-Display.ino | 8 -- FreeSans12pt7b.h | 272 --------------------------------------------- TFT_eSPIScreen.cpp | 2 - 4 files changed, 487 deletions(-) delete mode 100644 Arial9pt7b.h delete mode 100644 FreeSans12pt7b.h diff --git a/Arial9pt7b.h b/Arial9pt7b.h deleted file mode 100644 index d8d516b..0000000 --- a/Arial9pt7b.h +++ /dev/null @@ -1,205 +0,0 @@ -#pragma once -#include - -const uint8_t Arial9pt7bBitmaps[] PROGMEM = { - 0xFE, 0xAA, 0xA2, 0x80, 0xDE, 0xF7, 0x29, 0x00, 0x08, 0x86, 0x61, 0x18, - 0x44, 0xFF, 0xC4, 0x43, 0x30, 0x88, 0xFF, 0xC8, 0x86, 0x21, 0x98, 0x44, - 0x00, 0x10, 0x3C, 0xF6, 0xD3, 0xD0, 0xD0, 0x7C, 0x3E, 0x17, 0x13, 0x91, - 0xD3, 0xF6, 0x3C, 0x10, 0x10, 0x70, 0x23, 0x21, 0x08, 0x84, 0x23, 0x20, - 0x89, 0x83, 0x24, 0x07, 0x33, 0x80, 0x93, 0x06, 0xCC, 0x13, 0x10, 0x8C, - 0xC2, 0x12, 0x10, 0x38, 0x1C, 0x06, 0xC1, 0x8C, 0x31, 0x03, 0x60, 0x38, - 0x1F, 0x06, 0x76, 0xC6, 0x98, 0x73, 0x0E, 0x33, 0x63, 0xC4, 0xFE, 0x80, - 0x13, 0x26, 0x4C, 0xCC, 0xCC, 0xCC, 0x46, 0x22, 0x10, 0xC4, 0x62, 0x33, - 0x11, 0x11, 0x13, 0x32, 0x64, 0xC0, 0x25, 0x5C, 0xA5, 0x00, 0x08, 0x04, - 0x02, 0x1F, 0xFF, 0xF8, 0x40, 0x20, 0x10, 0xF8, 0xFF, 0xC0, 0x08, 0xC4, - 0x23, 0x10, 0x84, 0x62, 0x11, 0x88, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0x83, - 0x81, 0x81, 0x81, 0x83, 0xC3, 0xC3, 0x66, 0x3C, 0x19, 0xDF, 0xB9, 0x8C, - 0x63, 0x18, 0xC6, 0x31, 0x80, 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x03, 0x06, - 0x0C, 0x38, 0x70, 0x40, 0xFF, 0xFF, 0x3C, 0x66, 0xC2, 0xC3, 0x06, 0x1C, - 0x06, 0x03, 0x03, 0x83, 0xC3, 0x66, 0x3C, 0x02, 0x03, 0x03, 0x81, 0x41, - 0x21, 0x91, 0x88, 0x84, 0xFF, 0x81, 0x00, 0x80, 0x40, 0x20, 0x7F, 0x7F, - 0x40, 0x40, 0xDC, 0xE6, 0xC3, 0x01, 0x01, 0xC3, 0xC3, 0x66, 0x3C, 0x3C, - 0x66, 0xC3, 0xC0, 0x9C, 0xE6, 0xC3, 0xC3, 0xC1, 0xC3, 0xC3, 0x66, 0x3C, - 0xFF, 0xFF, 0x06, 0x06, 0x0C, 0x08, 0x18, 0x18, 0x30, 0x30, 0x30, 0x20, - 0x20, 0x3C, 0x66, 0xC3, 0xC3, 0x46, 0x3C, 0x66, 0xC3, 0x81, 0x81, 0xC3, - 0x66, 0x3C, 0x3C, 0x66, 0xC3, 0x83, 0x83, 0xC3, 0xE7, 0x39, 0x03, 0xC3, - 0xC2, 0x6E, 0x3C, 0xC1, 0x80, 0xC1, 0xF0, 0x01, 0x83, 0xC7, 0x8E, 0x0C, - 0x03, 0x80, 0x78, 0x0F, 0x01, 0x80, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, - 0xFC, 0x80, 0x70, 0x1E, 0x01, 0xC0, 0x18, 0x71, 0xE1, 0xC0, 0x80, 0x00, - 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x0E, 0x08, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x07, 0xF0, 0x07, 0x1E, 0x0C, 0x01, 0x84, 0x00, 0x46, 0x3D, 0x32, - 0x32, 0x8B, 0x30, 0xC5, 0x10, 0x62, 0x98, 0x21, 0x4C, 0x11, 0xA6, 0x19, - 0x99, 0x9D, 0x84, 0x73, 0x83, 0x00, 0x08, 0xC0, 0x1C, 0x3C, 0x38, 0x07, - 0xF0, 0x00, 0x06, 0x00, 0xE0, 0x0F, 0x00, 0xB0, 0x19, 0x81, 0x98, 0x30, - 0x83, 0x0C, 0x3F, 0xC6, 0x06, 0x60, 0x64, 0x06, 0xC0, 0x30, 0xFF, 0x3F, - 0xEC, 0x0B, 0x02, 0xC1, 0xBF, 0xCF, 0xFB, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, - 0xFE, 0xFF, 0x00, 0x1F, 0x07, 0x39, 0x81, 0xE0, 0x3C, 0x01, 0x80, 0x30, - 0x06, 0x00, 0xC0, 0x78, 0x0D, 0x83, 0x1C, 0xE1, 0xF0, 0xFF, 0x1F, 0xF3, - 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, - 0x7F, 0xCF, 0xF0, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x3F, 0xEF, 0xFB, - 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF0, 0x18, - 0x0C, 0x06, 0x03, 0xFD, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x0F, - 0x83, 0x9E, 0x60, 0x64, 0x03, 0xC0, 0x0C, 0x00, 0xC3, 0xFC, 0x3F, 0xC0, - 0x34, 0x03, 0x60, 0x33, 0x9E, 0x0F, 0x80, 0xC0, 0x78, 0x0F, 0x01, 0xE0, - 0x3C, 0x07, 0xFF, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, - 0x06, 0xFF, 0xF8, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x43, 0x42, 0x7E, 0x3C, 0xC0, 0xD8, 0x33, 0x0C, 0x63, 0x0C, 0xC1, 0xB8, - 0x3F, 0x07, 0x30, 0xC3, 0x18, 0x73, 0x06, 0x60, 0x6C, 0x0E, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xE0, - 0x3F, 0x01, 0xFC, 0x1F, 0xA0, 0xFD, 0x05, 0xEC, 0x6F, 0x22, 0x79, 0x13, - 0xCD, 0x9E, 0x28, 0xF1, 0x47, 0x8E, 0x3C, 0x21, 0x80, 0xC0, 0x7C, 0x0F, - 0xC1, 0xF8, 0x3D, 0x87, 0x98, 0xF3, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, - 0xE0, 0x7C, 0x0E, 0x1F, 0x83, 0x9C, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, - 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0x60, 0x63, 0x9C, 0x1F, 0x80, 0xFF, - 0x3F, 0xFC, 0x0F, 0x03, 0xC0, 0xF0, 0x3F, 0xFB, 0xF8, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x00, 0x1F, 0x83, 0x9C, 0x60, 0x6C, 0x03, 0xC0, 0x3C, - 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x33, 0x61, 0xE3, 0x9C, 0x1F, 0xE0, - 0x01, 0xFF, 0x8C, 0x1C, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, - 0x70, 0xC1, 0x8C, 0x18, 0xC0, 0xCC, 0x06, 0xC0, 0x60, 0x3E, 0x1F, 0xEC, - 0x1B, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x07, 0x00, 0xF0, 0x3C, 0x0D, 0xFE, - 0x3F, 0x00, 0xFF, 0xFF, 0xFC, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0xC0, 0x78, 0x0F, 0x01, - 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x68, 0x09, 0x83, 0x3F, - 0xC1, 0xF0, 0xC0, 0x34, 0x02, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C, 0x10, - 0x81, 0x98, 0x19, 0x80, 0x90, 0x0F, 0x00, 0x60, 0x06, 0x00, 0xC1, 0xC1, - 0xA0, 0xE0, 0x98, 0x50, 0xCC, 0x2C, 0x66, 0x36, 0x31, 0x11, 0x10, 0x88, - 0x88, 0x6C, 0x6C, 0x36, 0x34, 0x0A, 0x0A, 0x05, 0x05, 0x03, 0x83, 0x80, - 0xC1, 0x80, 0x60, 0x63, 0x04, 0x30, 0xC1, 0x98, 0x0F, 0x00, 0x60, 0x06, - 0x00, 0xF0, 0x19, 0x81, 0x98, 0x30, 0xC6, 0x06, 0xC0, 0x70, 0xC0, 0x26, - 0x06, 0x30, 0xC1, 0x98, 0x19, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, - 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x7F, 0xCF, 0xF8, 0x07, 0x00, 0xC0, - 0x30, 0x0C, 0x03, 0x00, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xFF, 0xFE, - 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xF0, 0x86, 0x10, 0x86, - 0x10, 0x84, 0x30, 0x84, 0x30, 0x80, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0xF0, 0x18, 0x1C, 0x3C, 0x34, 0x26, 0x62, 0x43, 0xFF, 0xC0, - 0xCC, 0x3E, 0xE6, 0xC3, 0x03, 0x0F, 0x7F, 0xC3, 0x83, 0xCF, 0x7B, 0xC0, - 0xC0, 0xC0, 0xDC, 0xF6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC3, 0xC3, 0xE6, 0xDC, - 0x3C, 0x66, 0xC3, 0x80, 0x80, 0x80, 0x83, 0xC3, 0x66, 0x3C, 0x03, 0x03, - 0x03, 0x3B, 0x6F, 0xC3, 0x83, 0x83, 0x83, 0x83, 0xC3, 0x6F, 0x3F, 0x3C, - 0x66, 0xC3, 0x81, 0xFF, 0x80, 0xC0, 0xC3, 0x67, 0x3C, 0x3C, 0xC2, 0x3E, - 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x3B, 0x6F, 0xC3, 0x83, 0x83, - 0x83, 0x83, 0xC3, 0x6F, 0x3B, 0x03, 0x83, 0xEE, 0x7C, 0xC0, 0xC0, 0xC0, - 0xDC, 0xF6, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xFF, - 0xFF, 0xC0, 0x33, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3B, 0xE0, 0xC0, - 0xC0, 0xC0, 0xC6, 0xCC, 0xD8, 0xF0, 0xF0, 0xD8, 0xCC, 0xCC, 0xC6, 0xC3, - 0xFF, 0xFF, 0xFF, 0xC0, 0xDC, 0xF7, 0x3D, 0xF0, 0xC7, 0x84, 0x3C, 0x21, - 0xE1, 0x0F, 0x08, 0x78, 0x43, 0xC2, 0x1E, 0x10, 0xC0, 0xDC, 0xF6, 0xC3, - 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x3C, 0x66, 0xC3, 0x81, 0x81, - 0x81, 0x81, 0xC3, 0x66, 0x3C, 0xDC, 0xF6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC1, - 0xC3, 0xE6, 0xDC, 0xC0, 0xC0, 0xC0, 0xC0, 0x3B, 0x6F, 0xC3, 0x83, 0x83, - 0x83, 0x83, 0xC3, 0x6F, 0x3B, 0x03, 0x03, 0x03, 0x03, 0xFF, 0x71, 0x8C, - 0x63, 0x18, 0xC6, 0x00, 0x7D, 0x9E, 0x1E, 0x07, 0x83, 0xC1, 0xC1, 0xEE, - 0xF8, 0x23, 0x19, 0xF6, 0x31, 0x8C, 0x63, 0x18, 0x43, 0x80, 0xC3, 0xC3, - 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x6F, 0x7B, 0xC1, 0xA0, 0x98, 0xCC, - 0x62, 0x21, 0xB0, 0x50, 0x28, 0x1C, 0x04, 0x00, 0xC2, 0x1E, 0x38, 0x91, - 0xC4, 0xCA, 0x66, 0x53, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, - 0x00, 0x63, 0x31, 0x8D, 0x83, 0x81, 0xC0, 0xE0, 0xD8, 0x6C, 0x63, 0x60, - 0xC0, 0xC1, 0xA0, 0x98, 0xC4, 0x62, 0x21, 0xB0, 0x58, 0x28, 0x1C, 0x06, - 0x02, 0x03, 0x07, 0x03, 0x80, 0x7F, 0x01, 0x81, 0x80, 0x80, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0x7F, 0xC0, 0x39, 0x18, 0xC6, 0x31, 0x88, 0x82, 0x18, - 0xC6, 0x31, 0x84, 0x38, 0xFF, 0xFF, 0x80, 0xE0, 0x83, 0x0C, 0x30, 0xC3, - 0x04, 0x0C, 0x43, 0x0C, 0x30, 0xC3, 0x08, 0xE0, 0xF8, 0xFF, 0xE3, 0xC0 }; - -const GFXglyph Arial9pt7bGlyphs[] PROGMEM = { - { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' - { 0, 2, 13, 5, 2, -12 }, // 0x21 '!' - { 4, 5, 5, 6, 1, -12 }, // 0x22 '"' - { 8, 10, 13, 10, 0, -12 }, // 0x23 '#' - { 25, 8, 16, 10, 1, -13 }, // 0x24 '$' - { 41, 14, 13, 16, 1, -12 }, // 0x25 '%' - { 64, 11, 13, 12, 1, -12 }, // 0x26 '&' - { 82, 2, 5, 3, 1, -12 }, // 0x27 ''' - { 84, 4, 17, 6, 1, -12 }, // 0x28 '(' - { 93, 4, 17, 6, 1, -12 }, // 0x29 ')' - { 102, 5, 5, 7, 1, -12 }, // 0x2A '*' - { 106, 9, 8, 11, 1, -9 }, // 0x2B '+' - { 115, 1, 5, 5, 2, -1 }, // 0x2C ',' - { 116, 4, 2, 6, 1, -4 }, // 0x2D '-' - { 117, 1, 2, 5, 2, -1 }, // 0x2E '.' - { 118, 5, 13, 5, 0, -12 }, // 0x2F '/' - { 127, 8, 13, 10, 1, -12 }, // 0x30 '0' - { 140, 5, 13, 10, 2, -12 }, // 0x31 '1' - { 149, 8, 13, 10, 1, -12 }, // 0x32 '2' - { 162, 8, 13, 10, 1, -12 }, // 0x33 '3' - { 175, 9, 13, 10, 0, -12 }, // 0x34 '4' - { 190, 8, 13, 10, 1, -12 }, // 0x35 '5' - { 203, 8, 13, 10, 1, -12 }, // 0x36 '6' - { 216, 8, 13, 10, 1, -12 }, // 0x37 '7' - { 229, 8, 13, 10, 1, -12 }, // 0x38 '8' - { 242, 8, 13, 10, 1, -12 }, // 0x39 '9' - { 255, 1, 9, 5, 2, -8 }, // 0x3A ':' - { 257, 1, 12, 5, 2, -8 }, // 0x3B ';' - { 259, 9, 9, 11, 1, -10 }, // 0x3C '<' - { 270, 9, 6, 11, 1, -8 }, // 0x3D '=' - { 277, 9, 9, 11, 1, -10 }, // 0x3E '>' - { 288, 8, 13, 10, 1, -12 }, // 0x3F '?' - { 301, 17, 17, 18, 1, -12 }, // 0x40 '@' - { 338, 12, 13, 12, 0, -12 }, // 0x41 'A' - { 358, 10, 13, 12, 1, -12 }, // 0x42 'B' - { 375, 11, 13, 13, 1, -12 }, // 0x43 'C' - { 393, 11, 13, 13, 1, -12 }, // 0x44 'D' - { 411, 10, 13, 12, 1, -12 }, // 0x45 'E' - { 428, 9, 13, 11, 1, -12 }, // 0x46 'F' - { 443, 12, 13, 14, 1, -12 }, // 0x47 'G' - { 463, 11, 13, 13, 1, -12 }, // 0x48 'H' - { 481, 1, 13, 5, 2, -12 }, // 0x49 'I' - { 483, 8, 13, 9, 0, -12 }, // 0x4A 'J' - { 496, 11, 13, 12, 1, -12 }, // 0x4B 'K' - { 514, 8, 13, 10, 1, -12 }, // 0x4C 'L' - { 527, 13, 13, 15, 1, -12 }, // 0x4D 'M' - { 549, 11, 13, 13, 1, -12 }, // 0x4E 'N' - { 567, 12, 13, 14, 1, -12 }, // 0x4F 'O' - { 587, 10, 13, 12, 1, -12 }, // 0x50 'P' - { 604, 12, 14, 14, 1, -12 }, // 0x51 'Q' - { 625, 12, 13, 13, 1, -12 }, // 0x52 'R' - { 645, 10, 13, 12, 1, -12 }, // 0x53 'S' - { 662, 11, 13, 11, 0, -12 }, // 0x54 'T' - { 680, 11, 13, 13, 1, -12 }, // 0x55 'U' - { 698, 12, 13, 12, 0, -12 }, // 0x56 'V' - { 718, 17, 13, 17, 0, -12 }, // 0x57 'W' - { 746, 12, 13, 12, 0, -12 }, // 0x58 'X' - { 766, 12, 13, 12, 0, -12 }, // 0x59 'Y' - { 786, 11, 13, 11, 0, -12 }, // 0x5A 'Z' - { 804, 4, 17, 5, 1, -12 }, // 0x5B '[' - { 813, 5, 13, 5, 0, -12 }, // 0x5C '\' - { 822, 4, 17, 5, 0, -12 }, // 0x5D ']' - { 831, 8, 7, 8, 0, -12 }, // 0x5E '^' - { 838, 10, 1, 10, 0, 3 }, // 0x5F '_' - { 840, 3, 2, 6, 1, -12 }, // 0x60 '`' - { 841, 8, 10, 10, 1, -9 }, // 0x61 'a' - { 851, 8, 13, 10, 1, -12 }, // 0x62 'b' - { 864, 8, 10, 9, 1, -9 }, // 0x63 'c' - { 874, 8, 13, 10, 1, -12 }, // 0x64 'd' - { 887, 8, 10, 10, 1, -9 }, // 0x65 'e' - { 897, 6, 13, 5, 0, -12 }, // 0x66 'f' - { 907, 8, 14, 10, 1, -9 }, // 0x67 'g' - { 921, 8, 13, 10, 1, -12 }, // 0x68 'h' - { 934, 2, 13, 4, 1, -12 }, // 0x69 'i' - { 938, 4, 17, 4, -1, -12 }, // 0x6A 'j' - { 947, 8, 13, 9, 1, -12 }, // 0x6B 'k' - { 960, 2, 13, 4, 1, -12 }, // 0x6C 'l' - { 964, 13, 10, 15, 1, -9 }, // 0x6D 'm' - { 981, 8, 10, 10, 1, -9 }, // 0x6E 'n' - { 991, 8, 10, 10, 1, -9 }, // 0x6F 'o' - { 1001, 8, 14, 10, 1, -9 }, // 0x70 'p' - { 1015, 8, 14, 10, 1, -9 }, // 0x71 'q' - { 1029, 5, 10, 6, 1, -9 }, // 0x72 'r' - { 1036, 7, 10, 9, 1, -9 }, // 0x73 's' - { 1045, 5, 13, 5, 0, -12 }, // 0x74 't' - { 1054, 8, 10, 10, 1, -9 }, // 0x75 'u' - { 1064, 9, 10, 9, 0, -9 }, // 0x76 'v' - { 1076, 13, 10, 13, 0, -9 }, // 0x77 'w' - { 1093, 9, 10, 9, 0, -9 }, // 0x78 'x' - { 1105, 9, 14, 9, 0, -9 }, // 0x79 'y' - { 1121, 9, 10, 9, 0, -9 }, // 0x7A 'z' - { 1133, 5, 17, 6, 1, -12 }, // 0x7B '{' - { 1144, 1, 17, 5, 2, -12 }, // 0x7C '|' - { 1147, 6, 17, 6, 0, -12 }, // 0x7D '}' - { 1160, 9, 3, 11, 1, -7 } }; // 0x7E '~' - -const GFXfont Arial9pt7b PROGMEM = { - (uint8_t *)Arial9pt7bBitmaps, - (GFXglyph *)Arial9pt7bGlyphs, - 0x20, 0x7E, 21 }; - -// Approx. 1836 bytes diff --git a/EX-Display.ino b/EX-Display.ino index eede0ca..d6ed88e 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -48,14 +48,6 @@ void setup() { display->getEXScreen()->clearScreen(BACKGROUND_COLOUR); } - const GFXfont *tempFont = TEXT_FONT; - CONSOLE.print(F("DEBUG Font: first|last|yAdvance: ")); - CONSOLE.print(tempFont->first); - CONSOLE.print(F("|")); - CONSOLE.print(tempFont->last); - CONSOLE.print(F("|")); - CONSOLE.println(tempFont->yAdvance); - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_SIZE, BACKGROUND_COLOUR); display->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 1, "EX-Display"); diff --git a/FreeSans12pt7b.h b/FreeSans12pt7b.h deleted file mode 100644 index 6e77392..0000000 --- a/FreeSans12pt7b.h +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once -#include - -const uint8_t FreeSans12pt7bBitmaps[] PROGMEM = { - 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xCF, 0x3C, 0xF3, 0x8A, 0x20, 0x06, 0x30, - 0x31, 0x03, 0x18, 0x18, 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x03, 0x18, 0x18, - 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x01, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30, - 0x04, 0x03, 0xE1, 0xFF, 0x72, 0x6C, 0x47, 0x88, 0xF1, 0x07, 0x20, 0x7E, - 0x03, 0xF0, 0x17, 0x02, 0x3C, 0x47, 0x88, 0xF1, 0x1B, 0x26, 0x7F, 0xC3, - 0xE0, 0x10, 0x02, 0x00, 0x00, 0x06, 0x03, 0xC0, 0x40, 0x7E, 0x0C, 0x0E, - 0x70, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xE7, 0x30, 0x07, 0xE6, 0x00, - 0x3C, 0x40, 0x00, 0x0C, 0x7C, 0x00, 0x8F, 0xE0, 0x19, 0xC7, 0x01, 0x18, - 0x30, 0x31, 0x83, 0x02, 0x1C, 0x70, 0x40, 0xFE, 0x04, 0x07, 0xC0, 0x0F, - 0x00, 0x7E, 0x03, 0x9C, 0x0C, 0x30, 0x30, 0xC0, 0xE7, 0x01, 0xF8, 0x03, - 0x80, 0x3E, 0x01, 0xCC, 0x6E, 0x19, 0xB0, 0x7C, 0xC0, 0xF3, 0x03, 0xCE, - 0x1F, 0x9F, 0xE6, 0x1E, 0x1C, 0xFF, 0xA0, 0x08, 0x8C, 0x66, 0x31, 0x98, - 0xC6, 0x31, 0x8C, 0x63, 0x08, 0x63, 0x08, 0x61, 0x0C, 0x20, 0x82, 0x18, - 0xC3, 0x18, 0xC3, 0x18, 0xC6, 0x31, 0x8C, 0x62, 0x31, 0x88, 0xC4, 0x62, - 0x00, 0x10, 0x23, 0x5B, 0xE3, 0x8D, 0x91, 0x00, 0x0C, 0x03, 0x00, 0xC0, - 0x30, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0xF5, 0x60, - 0xFF, 0xF0, 0xF0, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x02, 0x0C, 0x10, 0x20, - 0xC1, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, - 0x6E, 0x0F, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, - 0x0E, 0xC1, 0x9C, 0x71, 0xFC, 0x1F, 0x00, 0x08, 0xCF, 0xFF, 0x8C, 0x63, - 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0x1F, 0x0F, 0xF9, 0x87, 0x60, 0x7C, - 0x06, 0x00, 0xC0, 0x18, 0x07, 0x01, 0xC0, 0xF0, 0x78, 0x1C, 0x06, 0x00, - 0x80, 0x30, 0x07, 0xFF, 0xFF, 0xE0, 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x6C, - 0x0C, 0x01, 0x80, 0x70, 0x7C, 0x0F, 0x80, 0x18, 0x01, 0x80, 0x3C, 0x07, - 0x80, 0xD8, 0x73, 0xFC, 0x1F, 0x00, 0x01, 0x80, 0x70, 0x0E, 0x03, 0xC0, - 0xD8, 0x1B, 0x06, 0x61, 0x8C, 0x21, 0x8C, 0x33, 0x06, 0x7F, 0xFF, 0xFE, - 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xCF, 0xF9, 0x80, 0x30, 0x06, - 0x00, 0xDE, 0x1F, 0xE7, 0x0E, 0x00, 0xE0, 0x0C, 0x01, 0x80, 0x30, 0x07, - 0x81, 0xF8, 0x73, 0xFC, 0x1F, 0x00, 0x0F, 0x07, 0xF9, 0xC3, 0x30, 0x74, - 0x01, 0x80, 0x33, 0xC7, 0xFE, 0xF0, 0xDC, 0x1F, 0x01, 0xE0, 0x3C, 0x06, - 0xC1, 0xDC, 0x71, 0xFC, 0x1F, 0x00, 0xFF, 0xFF, 0xFC, 0x01, 0x00, 0x60, - 0x18, 0x02, 0x00, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x30, 0x04, 0x01, 0x80, - 0x30, 0x06, 0x01, 0x80, 0x30, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x66, - 0x0C, 0xC1, 0x8C, 0x61, 0xFC, 0x3F, 0x8E, 0x3B, 0x01, 0xE0, 0x3C, 0x07, - 0x80, 0xD8, 0x31, 0xFC, 0x1F, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x6C, - 0x07, 0x80, 0xF0, 0x1E, 0x07, 0x61, 0xEF, 0xFC, 0x79, 0x80, 0x30, 0x05, - 0x81, 0x98, 0x73, 0xFC, 0x1E, 0x00, 0xF0, 0x00, 0x03, 0xC0, 0xF0, 0x00, - 0x0F, 0x56, 0x00, 0x00, 0x07, 0x01, 0xE0, 0xF8, 0x3C, 0x0F, 0x00, 0xE0, - 0x07, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x78, 0x01, 0xF0, 0x07, - 0xC0, 0x0F, 0x00, 0x70, 0x1E, 0x0F, 0x03, 0xC0, 0xF0, 0x08, 0x00, 0x1F, - 0x1F, 0xEE, 0x1B, 0x03, 0xC0, 0xC0, 0x30, 0x0C, 0x06, 0x03, 0x81, 0xC0, - 0xE0, 0x30, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0xFE, - 0x00, 0x0F, 0xFE, 0x00, 0xF0, 0x3E, 0x07, 0x00, 0x3C, 0x38, 0x00, 0x30, - 0xC1, 0xE0, 0x66, 0x0F, 0xD9, 0xD8, 0x61, 0xC3, 0xC3, 0x07, 0x0F, 0x1C, - 0x1C, 0x3C, 0x60, 0x60, 0xF1, 0x81, 0x83, 0xC6, 0x06, 0x1B, 0x18, 0x38, - 0xEE, 0x71, 0xE7, 0x18, 0xFD, 0xF8, 0x71, 0xE7, 0xC0, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFC, 0x00, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x07, 0xE0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, - 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x1C, - 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x06, 0xFF, 0xC7, 0xFF, 0x30, - 0x19, 0x80, 0x6C, 0x03, 0x60, 0x1B, 0x00, 0xD8, 0x0C, 0xFF, 0xC7, 0xFF, - 0x30, 0x0D, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x06, 0xFF, 0xF7, - 0xFE, 0x00, 0x07, 0xE0, 0x3F, 0xF0, 0xE0, 0x73, 0x80, 0x66, 0x00, 0x6C, - 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, - 0x06, 0x00, 0x6C, 0x00, 0xDC, 0x03, 0x1E, 0x0E, 0x1F, 0xF8, 0x0F, 0xC0, - 0xFF, 0x83, 0xFF, 0x8C, 0x07, 0x30, 0x0E, 0xC0, 0x1B, 0x00, 0x7C, 0x00, - 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00, - 0x6C, 0x03, 0xB0, 0x1C, 0xFF, 0xE3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, - 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xEF, 0xFE, 0xC0, - 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xFF, 0xDF, - 0xFB, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00, - 0x07, 0xF0, 0x1F, 0xFC, 0x3C, 0x1E, 0x70, 0x06, 0x60, 0x03, 0xE0, 0x00, - 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 0x03, 0xC0, 0x03, - 0x60, 0x03, 0x60, 0x07, 0x30, 0x0F, 0x3C, 0x1F, 0x1F, 0xFB, 0x07, 0xE1, - 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, - 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, - 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, - 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, - 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0x7F, 0x1F, 0x00, 0xC0, 0x3B, 0x01, 0xCC, - 0x0E, 0x30, 0x70, 0xC3, 0x83, 0x1C, 0x0C, 0xE0, 0x33, 0x80, 0xDE, 0x03, - 0xDC, 0x0E, 0x38, 0x30, 0x60, 0xC1, 0xC3, 0x03, 0x8C, 0x06, 0x30, 0x1C, - 0xC0, 0x3B, 0x00, 0x60, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, - 0xFF, 0xFF, 0xF0, 0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xD0, - 0x0F, 0xD8, 0x1B, 0xD8, 0x1B, 0xD8, 0x1B, 0xCC, 0x33, 0xCC, 0x33, 0xCC, - 0x33, 0xC6, 0x63, 0xC6, 0x63, 0xC6, 0x63, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, - 0xC3, 0xC1, 0x83, 0xE0, 0x1F, 0x00, 0xFC, 0x07, 0xE0, 0x3D, 0x81, 0xEE, - 0x0F, 0x30, 0x79, 0xC3, 0xC6, 0x1E, 0x18, 0xF0, 0xE7, 0x83, 0x3C, 0x1D, - 0xE0, 0x6F, 0x01, 0xF8, 0x0F, 0xC0, 0x3E, 0x01, 0xC0, 0x03, 0xE0, 0x0F, - 0xFC, 0x0F, 0x07, 0x86, 0x00, 0xC6, 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, - 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, - 0x33, 0x00, 0x18, 0xC0, 0x18, 0x78, 0x3C, 0x1F, 0xFC, 0x03, 0xF8, 0x00, - 0xFF, 0x8F, 0xFE, 0xC0, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x07, - 0xFF, 0xEF, 0xFC, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, - 0xC0, 0x0C, 0x00, 0x03, 0xE0, 0x0F, 0xFC, 0x0F, 0x07, 0x86, 0x00, 0xC6, - 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, - 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, 0x33, 0x01, 0x98, 0xC0, 0xFC, 0x78, - 0x3C, 0x1F, 0xFF, 0x03, 0xF9, 0x80, 0x00, 0x40, 0xFF, 0xC3, 0xFF, 0xCC, - 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x0C, 0xFF, 0xE3, - 0xFF, 0xCC, 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x06, - 0xC0, 0x1B, 0x00, 0x70, 0x0F, 0xE0, 0x7F, 0xC3, 0x83, 0x9C, 0x07, 0x60, - 0x0D, 0x80, 0x06, 0x00, 0x1E, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x0F, 0x80, - 0x07, 0xC0, 0x0F, 0x00, 0x3E, 0x00, 0xDE, 0x0E, 0x3F, 0xF0, 0x3F, 0x80, - 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, - 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, - 0x06, 0x00, 0x60, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, - 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, - 0xE0, 0x0F, 0x80, 0xEE, 0x0E, 0x3F, 0xE0, 0x7C, 0x00, 0x60, 0x06, 0xC0, - 0x1D, 0xC0, 0x31, 0x80, 0x63, 0x01, 0xC7, 0x03, 0x06, 0x06, 0x0C, 0x1C, - 0x1C, 0x30, 0x18, 0x60, 0x31, 0xC0, 0x73, 0x00, 0x66, 0x00, 0xDC, 0x01, - 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0xE0, 0x30, 0x1D, 0x80, 0xE0, - 0x76, 0x07, 0x81, 0xD8, 0x1E, 0x06, 0x70, 0x7C, 0x18, 0xC1, 0xB0, 0xE3, - 0x0C, 0xC3, 0x8C, 0x33, 0x0C, 0x38, 0xC6, 0x30, 0x67, 0x18, 0xC1, 0x98, - 0x67, 0x06, 0x61, 0xD8, 0x1D, 0x83, 0x60, 0x3C, 0x0D, 0x80, 0xF0, 0x3E, - 0x03, 0xC0, 0x70, 0x0F, 0x01, 0xC0, 0x18, 0x07, 0x00, 0x70, 0x0E, 0x60, - 0x38, 0xE0, 0x60, 0xE1, 0xC0, 0xC3, 0x01, 0xCC, 0x01, 0xF8, 0x01, 0xE0, - 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x33, 0x00, 0xE7, 0x03, 0x86, 0x06, - 0x0E, 0x1C, 0x0E, 0x70, 0x0C, 0xC0, 0x1C, 0x60, 0x06, 0x70, 0x0E, 0x30, - 0x1C, 0x38, 0x18, 0x1C, 0x38, 0x0C, 0x30, 0x0E, 0x70, 0x06, 0x60, 0x03, - 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xC0, 0x0E, - 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00, 0x30, 0x03, - 0x80, 0x38, 0x03, 0x80, 0x18, 0x01, 0xC0, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, - 0xC0, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, - 0xF0, 0x81, 0x81, 0x02, 0x06, 0x04, 0x08, 0x18, 0x10, 0x20, 0x60, 0x40, - 0x81, 0x81, 0x02, 0x06, 0x04, 0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x3F, 0xF0, 0x0C, 0x0E, 0x05, 0x86, 0xC3, 0x21, 0x19, - 0x8C, 0x83, 0xC1, 0x80, 0xFF, 0xFE, 0xE3, 0x8C, 0x30, 0x3F, 0x07, 0xF8, - 0xE1, 0xCC, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xCF, 0x8C, 0xC0, 0xCC, 0x0C, - 0xE3, 0xC7, 0xEF, 0x3C, 0x70, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, - 0x0C, 0xF8, 0xDF, 0xCF, 0x0E, 0xE0, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, - 0x3C, 0x03, 0xE0, 0x6F, 0x0E, 0xDF, 0xCC, 0xF8, 0x1F, 0x0F, 0xE7, 0x1B, - 0x83, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x37, 0x1C, 0xFE, 0x1F, - 0x00, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x3C, 0xCF, 0xFB, 0x8F, - 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0x8F, 0x3F, - 0x63, 0xCC, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x3C, 0x07, 0xFF, 0xFF, 0xFE, - 0x00, 0xC0, 0x1C, 0x0D, 0xC3, 0x1F, 0xE1, 0xF0, 0x3B, 0xD8, 0xC6, 0x7F, - 0xEC, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x00, 0x1E, 0x67, 0xFD, 0xC7, - 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x9F, - 0xB1, 0xE6, 0x00, 0xC0, 0x3E, 0x0E, 0x7F, 0xC7, 0xE0, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x33, 0xCD, 0xFB, 0xC7, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, - 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x30, 0xF0, 0x3F, 0xFF, 0xFF, - 0xF0, 0x33, 0x00, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, - 0xE0, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x83, 0x30, 0xC6, 0x30, - 0xCC, 0x1B, 0x83, 0xF0, 0x77, 0x0C, 0x61, 0x8E, 0x30, 0xE6, 0x0C, 0xC1, - 0xD8, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xCF, 0x1F, 0x6F, 0xDF, 0xFC, - 0x78, 0xFC, 0x18, 0x3C, 0x0C, 0x1E, 0x06, 0x0F, 0x03, 0x07, 0x81, 0x83, - 0xC0, 0xC1, 0xE0, 0x60, 0xF0, 0x30, 0x78, 0x18, 0x3C, 0x0C, 0x18, 0xCF, - 0x37, 0xEF, 0x1F, 0x83, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, - 0x0F, 0x03, 0xC0, 0xC0, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, - 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x1F, 0xC1, 0xF0, 0xCF, 0x8D, - 0xFC, 0xF0, 0xEE, 0x06, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, - 0x07, 0xF0, 0xEF, 0xFC, 0xCF, 0x8C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x00, - 0x1E, 0x67, 0xFD, 0xC7, 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, - 0x7C, 0x1D, 0xC7, 0x9F, 0xF1, 0xE6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, - 0xCF, 0x7F, 0x38, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0x3E, 0x1F, - 0xEE, 0x1B, 0x00, 0xC0, 0x3C, 0x07, 0xF0, 0x3E, 0x01, 0xF0, 0x3E, 0x1D, - 0xFE, 0x3E, 0x00, 0x63, 0x19, 0xFF, 0xB1, 0x8C, 0x63, 0x18, 0xC6, 0x31, - 0xE7, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, - 0xF0, 0x7E, 0x3D, 0xFB, 0x3C, 0xC0, 0xE0, 0x66, 0x06, 0x60, 0x67, 0x0C, - 0x30, 0xC3, 0x0C, 0x39, 0x81, 0x98, 0x19, 0x81, 0xF0, 0x0F, 0x00, 0xE0, - 0x0E, 0x00, 0xC1, 0xC1, 0xB0, 0xE1, 0xD8, 0x70, 0xCC, 0x2C, 0x66, 0x36, - 0x31, 0x9B, 0x18, 0xCD, 0x98, 0x64, 0x6C, 0x16, 0x36, 0x0F, 0x1A, 0x07, - 0x8F, 0x03, 0x83, 0x80, 0xC1, 0xC0, 0x60, 0xEE, 0x18, 0xC6, 0x0C, 0xC1, - 0xF0, 0x1C, 0x01, 0x80, 0x78, 0x1B, 0x03, 0x30, 0xC7, 0x30, 0x66, 0x06, - 0xE0, 0x6C, 0x0D, 0x83, 0x38, 0x63, 0x0C, 0x63, 0x0E, 0x60, 0xCC, 0x1B, - 0x03, 0x60, 0x3C, 0x07, 0x00, 0xE0, 0x18, 0x03, 0x00, 0xE0, 0x78, 0x0E, - 0x00, 0xFF, 0xFF, 0xF0, 0x18, 0x0C, 0x07, 0x03, 0x81, 0xC0, 0x60, 0x30, - 0x18, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x19, 0xCC, 0x63, 0x18, 0xC6, 0x31, - 0x99, 0x86, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x1C, 0x60, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFC, 0xC7, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x0C, 0x33, 0x31, - 0x8C, 0x63, 0x18, 0xC6, 0x73, 0x00, 0x70, 0x3E, 0x09, 0xE4, 0x1F, 0x03, - 0x80}; - -const GFXglyph FreeSans12pt7bGlyphs[] PROGMEM = { - {0, 0, 0, 6, 0, 1}, // 0x20 ' ' - {0, 2, 18, 8, 3, -17}, // 0x21 '!' - {5, 6, 6, 8, 1, -16}, // 0x22 '"' - {10, 13, 16, 13, 0, -15}, // 0x23 '#' - {36, 11, 20, 13, 1, -17}, // 0x24 '$' - {64, 20, 17, 21, 1, -16}, // 0x25 '%' - {107, 14, 17, 16, 1, -16}, // 0x26 '&' - {137, 2, 6, 5, 1, -16}, // 0x27 ''' - {139, 5, 23, 8, 2, -17}, // 0x28 '(' - {154, 5, 23, 8, 1, -17}, // 0x29 ')' - {169, 7, 7, 9, 1, -17}, // 0x2A '*' - {176, 10, 11, 14, 2, -10}, // 0x2B '+' - {190, 2, 6, 7, 2, -1}, // 0x2C ',' - {192, 6, 2, 8, 1, -7}, // 0x2D '-' - {194, 2, 2, 6, 2, -1}, // 0x2E '.' - {195, 7, 18, 7, 0, -17}, // 0x2F '/' - {211, 11, 17, 13, 1, -16}, // 0x30 '0' - {235, 5, 17, 13, 3, -16}, // 0x31 '1' - {246, 11, 17, 13, 1, -16}, // 0x32 '2' - {270, 11, 17, 13, 1, -16}, // 0x33 '3' - {294, 11, 17, 13, 1, -16}, // 0x34 '4' - {318, 11, 17, 13, 1, -16}, // 0x35 '5' - {342, 11, 17, 13, 1, -16}, // 0x36 '6' - {366, 11, 17, 13, 1, -16}, // 0x37 '7' - {390, 11, 17, 13, 1, -16}, // 0x38 '8' - {414, 11, 17, 13, 1, -16}, // 0x39 '9' - {438, 2, 13, 6, 2, -12}, // 0x3A ':' - {442, 2, 16, 6, 2, -11}, // 0x3B ';' - {446, 12, 12, 14, 1, -11}, // 0x3C '<' - {464, 12, 6, 14, 1, -8}, // 0x3D '=' - {473, 12, 12, 14, 1, -11}, // 0x3E '>' - {491, 10, 18, 13, 2, -17}, // 0x3F '?' - {514, 22, 21, 24, 1, -17}, // 0x40 '@' - {572, 16, 18, 16, 0, -17}, // 0x41 'A' - {608, 13, 18, 16, 2, -17}, // 0x42 'B' - {638, 15, 18, 17, 1, -17}, // 0x43 'C' - {672, 14, 18, 17, 2, -17}, // 0x44 'D' - {704, 12, 18, 15, 2, -17}, // 0x45 'E' - {731, 11, 18, 14, 2, -17}, // 0x46 'F' - {756, 16, 18, 18, 1, -17}, // 0x47 'G' - {792, 13, 18, 17, 2, -17}, // 0x48 'H' - {822, 2, 18, 7, 2, -17}, // 0x49 'I' - {827, 9, 18, 13, 1, -17}, // 0x4A 'J' - {848, 14, 18, 16, 2, -17}, // 0x4B 'K' - {880, 10, 18, 14, 2, -17}, // 0x4C 'L' - {903, 16, 18, 20, 2, -17}, // 0x4D 'M' - {939, 13, 18, 18, 2, -17}, // 0x4E 'N' - {969, 17, 18, 19, 1, -17}, // 0x4F 'O' - {1008, 12, 18, 16, 2, -17}, // 0x50 'P' - {1035, 17, 19, 19, 1, -17}, // 0x51 'Q' - {1076, 14, 18, 17, 2, -17}, // 0x52 'R' - {1108, 14, 18, 16, 1, -17}, // 0x53 'S' - {1140, 12, 18, 15, 1, -17}, // 0x54 'T' - {1167, 13, 18, 17, 2, -17}, // 0x55 'U' - {1197, 15, 18, 15, 0, -17}, // 0x56 'V' - {1231, 22, 18, 22, 0, -17}, // 0x57 'W' - {1281, 15, 18, 16, 0, -17}, // 0x58 'X' - {1315, 16, 18, 16, 0, -17}, // 0x59 'Y' - {1351, 13, 18, 15, 1, -17}, // 0x5A 'Z' - {1381, 4, 23, 7, 2, -17}, // 0x5B '[' - {1393, 7, 18, 7, 0, -17}, // 0x5C '\' - {1409, 4, 23, 7, 1, -17}, // 0x5D ']' - {1421, 9, 9, 11, 1, -16}, // 0x5E '^' - {1432, 15, 1, 13, -1, 4}, // 0x5F '_' - {1434, 5, 4, 6, 1, -17}, // 0x60 '`' - {1437, 12, 13, 13, 1, -12}, // 0x61 'a' - {1457, 12, 18, 13, 1, -17}, // 0x62 'b' - {1484, 10, 13, 12, 1, -12}, // 0x63 'c' - {1501, 11, 18, 13, 1, -17}, // 0x64 'd' - {1526, 11, 13, 13, 1, -12}, // 0x65 'e' - {1544, 5, 18, 7, 1, -17}, // 0x66 'f' - {1556, 11, 18, 13, 1, -12}, // 0x67 'g' - {1581, 10, 18, 13, 1, -17}, // 0x68 'h' - {1604, 2, 18, 5, 2, -17}, // 0x69 'i' - {1609, 4, 23, 6, 0, -17}, // 0x6A 'j' - {1621, 11, 18, 12, 1, -17}, // 0x6B 'k' - {1646, 2, 18, 5, 1, -17}, // 0x6C 'l' - {1651, 17, 13, 19, 1, -12}, // 0x6D 'm' - {1679, 10, 13, 13, 1, -12}, // 0x6E 'n' - {1696, 11, 13, 13, 1, -12}, // 0x6F 'o' - {1714, 12, 17, 13, 1, -12}, // 0x70 'p' - {1740, 11, 17, 13, 1, -12}, // 0x71 'q' - {1764, 6, 13, 8, 1, -12}, // 0x72 'r' - {1774, 10, 13, 12, 1, -12}, // 0x73 's' - {1791, 5, 16, 7, 1, -15}, // 0x74 't' - {1801, 10, 13, 13, 1, -12}, // 0x75 'u' - {1818, 12, 13, 12, 0, -12}, // 0x76 'v' - {1838, 17, 13, 17, 0, -12}, // 0x77 'w' - {1866, 11, 13, 11, 0, -12}, // 0x78 'x' - {1884, 11, 18, 11, 0, -12}, // 0x79 'y' - {1909, 10, 13, 12, 1, -12}, // 0x7A 'z' - {1926, 5, 23, 8, 1, -17}, // 0x7B '{' - {1941, 2, 23, 6, 2, -17}, // 0x7C '|' - {1947, 5, 23, 8, 2, -17}, // 0x7D '}' - {1962, 10, 5, 12, 1, -10}}; // 0x7E '~' - -const GFXfont FreeSans12pt7b PROGMEM = {(uint8_t *)FreeSans12pt7bBitmaps, - (GFXglyph *)FreeSans12pt7bGlyphs, 0x20, - 0x7E, 29}; - -// Approx. 2641 bytes diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 48f82fa..f5f8006 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -3,8 +3,6 @@ #include -// CONSOLE.println("Loading TFT_eSPI code"); - TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { From 08d2f53f9d3abaf8677ba98ccd5a41f037432322 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Wed, 8 May 2024 23:19:56 +0100 Subject: [PATCH 031/146] fixed mcu text positioning --- MCUFriendScreen.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 137e87e..755f5ee 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -54,7 +54,11 @@ void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(b void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { - uint16_t textRow = (row * fontHeight) + row; + CONSOLE.print(F("row:")); + CONSOLE.println(row); + uint16_t textRow = ((row+1) * fontHeight) + row; + CONSOLE.print(F("textRow:")); + CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; uint16_t paddedColumn = column + width; _tft.setTextColor(fontColour, backgroundColour); From c169c988368d24154326956456292e75c1a40207 Mon Sep 17 00:00:00 2001 From: vacumcollapse Date: Wed, 8 May 2024 23:39:15 +0100 Subject: [PATCH 032/146] further mcu row layout fix --- MCUFriendScreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 755f5ee..615c05f 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -56,7 +56,8 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint8_t maxLength, char *message) { CONSOLE.print(F("row:")); CONSOLE.println(row); - uint16_t textRow = ((row+1) * fontHeight) + row; + //uint16_t textRow = ((row+1) * fontHeight) + row; + uint16_t textRow = ((row+1) * fontHeight); CONSOLE.print(F("textRow:")); CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; From 320be8f01987a4b3fae6843d6cf795323b90a58d Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 9 May 2024 14:54:38 +1000 Subject: [PATCH 033/146] Capture scroll progress --- DisplayFunctions.cpp | 11 +++------ DisplayFunctions.h | 3 --- EX-Display.ino | 1 - EXDisplayClass.cpp | 54 ++++++++++++++++++++++++++++++++++++++++---- EXDisplayClass.h | 29 ++++++++++++++++-------- 5 files changed, 73 insertions(+), 25 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index d2fb8be..80d7776 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -49,6 +49,9 @@ void updateScreen() { } #ifdef SCROLLTIME display->autoScroll(SCROLLTIME); +#endif +#ifdef DISPLAY_SWITCH_TIME + display->autoSwitch(DISPLAY_SWITCH_TIME); #endif for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { if (row->needsRender() && (row->isChanged() || display->needsRedraw())) { @@ -58,14 +61,6 @@ void updateScreen() { display->resetRedraw(); } -unsigned long lastDisplaySwitch = 0; -void switchDisplays() { - if (millis() - lastDisplaySwitch > DISPLAY_SWITCH_TIME) { - lastDisplaySwitch = millis(); - EXDisplay::switchActiveDisplay(); - } -} - void displayAllRows() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { CONSOLE.print(F("\n\nRows for display ")); diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 04a8b38..9988dd0 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -18,9 +18,6 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text); /// @brief Update the active display on its associated screen void updateScreen(); -/// @brief Switch active displays if enabled -void switchDisplays(); - /// @brief Display all rows on all screens - handy for debug void displayAllRows(); diff --git a/EX-Display.ino b/EX-Display.ino index 6ac3ca1..2610efb 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -92,7 +92,6 @@ void loop() { // DISABLE IN STARTUPPHASE else { updateScreen(); - switchDisplays(); /* DISABLE SO IT WILL COMPILE if (StartupPhase==false){ // add thie following in once display is working diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 64c1118..6f3e6ad 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -6,6 +6,9 @@ EXDisplay *EXDisplay::_first = nullptr; /// @brief Define the active display as nullptr also EXDisplay *EXDisplay::_activeDisplay = nullptr; +/// @brief Define initial last switch time as 0 +unsigned long EXDisplay::_lastSwitchTime = 0; + /* * EXDisplay class implementation */ @@ -68,13 +71,13 @@ void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { row->setDisplayRow(rowNumber, _exScreen->maxRows); } -void EXDisplay::scroll() { +void EXDisplay::scrollUp() { uint8_t screenRows = _exScreen->maxRows; uint8_t newPosition = 0; if (_numberOfRows <= screenRows) { _scrollPosition = newPosition; } else { - newPosition = _scrollPosition++; + newPosition = _scrollPosition--; if (newPosition >= _numberOfRows) { newPosition = 0; } @@ -82,11 +85,26 @@ void EXDisplay::scroll() { _scrollPosition = newPosition; } +void EXDisplay::scrollDown() { + // If the highest row number is more than will fit on the screen we need to scroll + // If not, do not redraw screen and do not update any displayRow or scroll values + uint8_t lastRow = _exScreen->maxRows - 1; + uint8_t newScroll = _scrollPosition; + if (_scrollPosition == lastRow) { + newScroll = 0; + } else { + for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { + + } + } + _needsRedraw = true; +} + void EXDisplay::autoScroll(unsigned long scrollDelay) { if (millis() - _lastScrollTime > scrollDelay) { _lastScrollTime = millis(); CONSOLE.println(F("Time to scroll")); - scroll(); + scrollDown(); } } @@ -128,7 +146,12 @@ EXDisplay *EXDisplay::getDisplayByNumber(uint8_t displayNumber) { EXDisplay *EXDisplay::getActiveDisplay() { return _activeDisplay; } -void EXDisplay::switchActiveDisplay() { +void EXDisplay::setNextDisplay() { + if (!_activeDisplay) { + _activeDisplay = _first; + _activeDisplay->_needsRedraw = true; + return; + } if (_activeDisplay->_next) { _activeDisplay = _activeDisplay->_next; } else { @@ -136,3 +159,26 @@ void EXDisplay::switchActiveDisplay() { } _activeDisplay->_needsRedraw = true; } + +void EXDisplay::setPreviousDisplay() { + if (!_activeDisplay) { + _activeDisplay = _first; + _activeDisplay->_needsRedraw = true; + return; + } + for (EXDisplay *display = _activeDisplay; display; display = display->getNext()) { + if (display->getNext() == _activeDisplay) { + _activeDisplay = display; + _activeDisplay->_needsRedraw = true; + return; + } + } +} + +void EXDisplay::autoSwitch(unsigned long switchDelay) { + if (millis() - EXDisplay::_lastSwitchTime > switchDelay) { + EXDisplay::_lastSwitchTime = millis(); + CONSOLE.println(F("Time to switch")); + setNextDisplay(); + } +} diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 4b307b4..4ff6cb7 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -46,8 +46,11 @@ class EXDisplay { /// @param rowText Char array of text for the row void updateRow(uint8_t rowNumber, char *rowText); - /// @brief Scroll one row vertically - void scroll(); + /// @brief Scroll up one row vertically + void scrollUp(); + + /// @brief Scroll down one row vertically + void scrollDown(); /// @brief Method to automatically update row positions for automatic vertical scrolling /// @param scrollDelay Time in milliseconds between vertical scrolling updates @@ -87,7 +90,14 @@ class EXDisplay { static EXDisplay *getActiveDisplay(); /// @brief Switch active display to the next display in the linked list - static void switchActiveDisplay(); + static void setNextDisplay(); + + /// @brief Switch active display to the previous display in the linked list + static void setPreviousDisplay(); + + /// @brief Method to automatically switch logical displays on a timed basis + /// @param switchDelay Time in milliseconds before switching displays + static void autoSwitch(unsigned long switchDelay); private: // chaining displays @@ -98,12 +108,13 @@ class EXDisplay { EXDisplayRow *_firstRow; EXScreen *_exScreen; // Screen management variables added here - uint8_t _maxScreenWidth; // Maximum number of chars that can fit on the physical screen - uint8_t _numberOfRows; // Calculated number of rows for this screen - uint8_t _scrollPosition; // Row number that is top of screen for scrolling support - unsigned long _lastScrollTime; // Last time in milliseconds an auto scroll was done - bool _needsRedraw; // Flag if this display needs to be redrawn - static EXDisplay *_activeDisplay; + uint8_t _maxScreenWidth; // Maximum number of chars that can fit on the physical screen + uint8_t _numberOfRows; // Calculated number of rows for this screen + uint8_t _scrollPosition; // Row number that is top of screen for scrolling support + unsigned long _lastScrollTime; // Last time in milliseconds an auto scroll was done + static unsigned long _lastSwitchTime; // Last time in milliseconds an auto switch was done + bool _needsRedraw; // Flag if this display needs to be redrawn + static EXDisplay *_activeDisplay; // Pointer to the current active display }; #endif From 331e99d71908439ed7dc41ad76a96478582ddbd4 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Thu, 9 May 2024 18:58:23 +1000 Subject: [PATCH 034/146] Some scroll progress --- EXDisplayClass.cpp | 23 ++++++++++++++++++----- EXDisplayClass.h | 1 + version.h | 3 ++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 6f3e6ad..2b76aed 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -17,6 +17,7 @@ EXDisplay::EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScree _firstRow = nullptr; _next = _first; _first = this; + _maxRowNumber = 0; _numberOfRows = 0; _scrollPosition = 0; _lastScrollTime = 0; @@ -66,6 +67,9 @@ void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { row->setNext(_firstRow); _firstRow = row; } + if (rowNumber > _maxRowNumber) { + _maxRowNumber = rowNumber; + } } row->setRowText(rowText); row->setDisplayRow(rowNumber, _exScreen->maxRows); @@ -89,13 +93,22 @@ void EXDisplay::scrollDown() { // If the highest row number is more than will fit on the screen we need to scroll // If not, do not redraw screen and do not update any displayRow or scroll values uint8_t lastRow = _exScreen->maxRows - 1; - uint8_t newScroll = _scrollPosition; - if (_scrollPosition == lastRow) { - newScroll = 0; + if (_maxRowNumber <= lastRow) { + return; + } + if (_scrollPosition >= lastRow) { + _scrollPosition = 0; } else { - for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { - + _scrollPosition++; + } + for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { + uint8_t newRow = row->getDisplayRow(); + if (newRow == 0) { + newRow = _maxRowNumber; + } else { + newRow--; } + row->setDisplayRow(newRow, _exScreen->maxRows); } _needsRedraw = true; } diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 4ff6cb7..71a5857 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -107,6 +107,7 @@ class EXDisplay { uint8_t _displayNumber; EXDisplayRow *_firstRow; EXScreen *_exScreen; + uint8_t _maxRowNumber; // Screen management variables added here uint8_t _maxScreenWidth; // Maximum number of chars that can fit on the physical screen uint8_t _numberOfRows; // Calculated number of rows for this screen diff --git a/version.h b/version.h index e8c6654..289b042 100644 --- a/version.h +++ b/version.h @@ -6,7 +6,8 @@ // 0.0.5 includes: // - Refactor screen and logical display to enable multiple displays to use the same screen -// - Enable switching between logical displays +// - Enable timed switching between logical displays +// - Enable timed vertical scrolling when there are more rows than can be on a single screen // 0.0.4 includes: // - Adjusted to use Adafruit fonts for MCUFRIEND_kbv // 0.0.3 includes: From a99c51fc3188beca0c5909e41682c0e6ab216ff7 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Thu, 9 May 2024 17:20:00 +0100 Subject: [PATCH 035/146] Fixed overtype on MCU Fixed overtype of line on MCU --- EXDisplayClass.cpp | 2 +- MCUFriendScreen.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index eaaba0c..c5cfd3e 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -78,7 +78,7 @@ void EXDisplay::scroll() { void EXDisplay::autoScroll(unsigned long scrollDelay) { if (millis() - _lastScrollTime > scrollDelay) { _lastScrollTime = millis(); - CONSOLE.println(F("Time to scroll")); + //CONSOLE.println(F("Time to scroll")); scroll(); } } diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 615c05f..a4c96a0 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -62,6 +62,8 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; uint16_t paddedColumn = column + width; + //_tft.fillRect(1, textRow, fontHeight, DISPLAY_WIDTH, backgroundColour); + _tft.fillRect(1, (textRow - fontHeight), DISPLAY_WIDTH, fontHeight, backgroundColour); _tft.setTextColor(fontColour, backgroundColour); //_tft.setCursor(paddedColumn, textRow); _tft.setCursor(1, textRow); From c8b73f07fb351cddf55df7f757a53cc2c4afcf5b Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Thu, 9 May 2024 19:11:22 +0100 Subject: [PATCH 036/146] Update MCUFriendScreen.cpp Changes to fillRect --- MCUFriendScreen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index a4c96a0..e743ad6 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -62,8 +62,7 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; uint16_t paddedColumn = column + width; - //_tft.fillRect(1, textRow, fontHeight, DISPLAY_WIDTH, backgroundColour); - _tft.fillRect(1, (textRow - fontHeight), DISPLAY_WIDTH, fontHeight, backgroundColour); + _tft.fillRect(1, ((textRow - fontHeight) + 10), DISPLAY_WIDTH, (fontHeight), backgroundColour); _tft.setTextColor(fontColour, backgroundColour); //_tft.setCursor(paddedColumn, textRow); _tft.setCursor(1, textRow); From 4cfd9d8fe189fb991576adda8ef83ca8475f83c1 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 10 May 2024 08:43:30 +1000 Subject: [PATCH 037/146] Scroll down implemented --- DisplayFunctions.cpp | 11 +---------- EXDisplayClass.cpp | 23 +++++++++++++++++------ EXDisplayClass.h | 8 ++++++-- EXScreen.h | 6 ++++++ config.example.h | 4 ---- version.h | 1 + 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 80d7776..41fd505 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -43,22 +43,13 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { void updateScreen() { EXDisplay *display = EXDisplay::getActiveDisplay(); - auto *screen = display->getEXScreen(); - if (display->needsRedraw()) { - screen->clearScreen(BACKGROUND_COLOUR); - } #ifdef SCROLLTIME display->autoScroll(SCROLLTIME); #endif #ifdef DISPLAY_SWITCH_TIME display->autoSwitch(DISPLAY_SWITCH_TIME); #endif - for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { - if (row->needsRender() && (row->isChanged() || display->needsRedraw())) { - screen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), row->getRowText()); - } - } - display->resetRedraw(); + display->redrawDisplay(); } void displayAllRows() { diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 2b76aed..44a44e0 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -90,15 +90,13 @@ void EXDisplay::scrollUp() { } void EXDisplay::scrollDown() { - // If the highest row number is more than will fit on the screen we need to scroll - // If not, do not redraw screen and do not update any displayRow or scroll values - uint8_t lastRow = _exScreen->maxRows - 1; - if (_maxRowNumber <= lastRow) { + uint8_t lastRow = _exScreen->maxRows - 1; // Highest possible row number on screen + if (_maxRowNumber <= lastRow) { // If our max row number is on screen, no scroll required return; } - if (_scrollPosition >= lastRow) { + if (_scrollPosition >= lastRow) { // If last row is top of screen, goes to bottom _scrollPosition = 0; - } else { + } else { // Otherwise next row is top of screen _scrollPosition++; } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { @@ -195,3 +193,16 @@ void EXDisplay::autoSwitch(unsigned long switchDelay) { setNextDisplay(); } } + +void EXDisplay::redrawDisplay() { + if (_needsRedraw) { + _exScreen->clearScreen(BACKGROUND_COLOUR); + } + for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { + if (row->needsRender() && (row->isChanged() || _needsRedraw)) { + _exScreen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), + row->getRowText()); + } + } + _needsRedraw = false; +} diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 71a5857..dd1a262 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -52,7 +52,7 @@ class EXDisplay { /// @brief Scroll down one row vertically void scrollDown(); - /// @brief Method to automatically update row positions for automatic vertical scrolling + /// @brief Call this method as often as possible to support timed vertical scrolling /// @param scrollDelay Time in milliseconds between vertical scrolling updates void autoScroll(unsigned long scrollDelay); @@ -95,10 +95,14 @@ class EXDisplay { /// @brief Switch active display to the previous display in the linked list static void setPreviousDisplay(); - /// @brief Method to automatically switch logical displays on a timed basis + /// @brief Call this method as often as possible to support timed display switching /// @param switchDelay Time in milliseconds before switching displays static void autoSwitch(unsigned long switchDelay); + /// @brief Call this method as often as possible to ensure a physical screen is updated correctly + /// @param display Pointer to the EXDisplay object that needs to have it's physical screen updated + void redrawDisplay(); + private: // chaining displays static EXDisplay *_first; diff --git a/EXScreen.h b/EXScreen.h index b6b4e0e..6042b5f 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -32,6 +32,12 @@ class EXScreen { virtual void clearScreen(uint16_t backgroundColour); /// @brief Virtual function to implement to write a row of text to the physical screen + /// @param row + /// @param column + /// @param fontColour + /// @param backgroundColour + /// @param maxLength + /// @param message virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); diff --git a/config.example.h b/config.example.h index 9e9e954..1adc2a4 100644 --- a/config.example.h +++ b/config.example.h @@ -8,10 +8,6 @@ // Should we eventually support up to 3 displays? // #define SCREEN_TYPE MCU #define SCREEN_TYPE TFT -// #define SCREEN_0_TYPE MCU -// #define SCREEN_0_TYPE TFT -// #define SCREEN_1_TYPE MCU -// #define SCREEN_2_TYPE MCU // Define the number of logical displays here // This is not a good way to do this diff --git a/version.h b/version.h index 289b042..9f961c8 100644 --- a/version.h +++ b/version.h @@ -8,6 +8,7 @@ // - Refactor screen and logical display to enable multiple displays to use the same screen // - Enable timed switching between logical displays // - Enable timed vertical scrolling when there are more rows than can be on a single screen +// - Moved display redraw function into the EXDisplay class to simplify screen updates // 0.0.4 includes: // - Adjusted to use Adafruit fonts for MCUFRIEND_kbv // 0.0.3 includes: From a821ac651c236d95a43359b0da31ca8378194420 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 10 May 2024 10:46:17 +1000 Subject: [PATCH 038/146] Scroll up implemented --- Arial9pt7b.h | 205 -------------------------------- DisplayFunctions.cpp | 2 - EX-Display.ino | 62 +--------- EXDisplayClass.cpp | 35 ++++-- FreeSans12pt7b.h | 272 ------------------------------------------- OLDEXScreen.cpp | 180 ---------------------------- OLDEXScreen.h | 69 ----------- 7 files changed, 29 insertions(+), 796 deletions(-) delete mode 100644 Arial9pt7b.h delete mode 100644 FreeSans12pt7b.h delete mode 100644 OLDEXScreen.cpp delete mode 100644 OLDEXScreen.h diff --git a/Arial9pt7b.h b/Arial9pt7b.h deleted file mode 100644 index d8d516b..0000000 --- a/Arial9pt7b.h +++ /dev/null @@ -1,205 +0,0 @@ -#pragma once -#include - -const uint8_t Arial9pt7bBitmaps[] PROGMEM = { - 0xFE, 0xAA, 0xA2, 0x80, 0xDE, 0xF7, 0x29, 0x00, 0x08, 0x86, 0x61, 0x18, - 0x44, 0xFF, 0xC4, 0x43, 0x30, 0x88, 0xFF, 0xC8, 0x86, 0x21, 0x98, 0x44, - 0x00, 0x10, 0x3C, 0xF6, 0xD3, 0xD0, 0xD0, 0x7C, 0x3E, 0x17, 0x13, 0x91, - 0xD3, 0xF6, 0x3C, 0x10, 0x10, 0x70, 0x23, 0x21, 0x08, 0x84, 0x23, 0x20, - 0x89, 0x83, 0x24, 0x07, 0x33, 0x80, 0x93, 0x06, 0xCC, 0x13, 0x10, 0x8C, - 0xC2, 0x12, 0x10, 0x38, 0x1C, 0x06, 0xC1, 0x8C, 0x31, 0x03, 0x60, 0x38, - 0x1F, 0x06, 0x76, 0xC6, 0x98, 0x73, 0x0E, 0x33, 0x63, 0xC4, 0xFE, 0x80, - 0x13, 0x26, 0x4C, 0xCC, 0xCC, 0xCC, 0x46, 0x22, 0x10, 0xC4, 0x62, 0x33, - 0x11, 0x11, 0x13, 0x32, 0x64, 0xC0, 0x25, 0x5C, 0xA5, 0x00, 0x08, 0x04, - 0x02, 0x1F, 0xFF, 0xF8, 0x40, 0x20, 0x10, 0xF8, 0xFF, 0xC0, 0x08, 0xC4, - 0x23, 0x10, 0x84, 0x62, 0x11, 0x88, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0x83, - 0x81, 0x81, 0x81, 0x83, 0xC3, 0xC3, 0x66, 0x3C, 0x19, 0xDF, 0xB9, 0x8C, - 0x63, 0x18, 0xC6, 0x31, 0x80, 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x03, 0x06, - 0x0C, 0x38, 0x70, 0x40, 0xFF, 0xFF, 0x3C, 0x66, 0xC2, 0xC3, 0x06, 0x1C, - 0x06, 0x03, 0x03, 0x83, 0xC3, 0x66, 0x3C, 0x02, 0x03, 0x03, 0x81, 0x41, - 0x21, 0x91, 0x88, 0x84, 0xFF, 0x81, 0x00, 0x80, 0x40, 0x20, 0x7F, 0x7F, - 0x40, 0x40, 0xDC, 0xE6, 0xC3, 0x01, 0x01, 0xC3, 0xC3, 0x66, 0x3C, 0x3C, - 0x66, 0xC3, 0xC0, 0x9C, 0xE6, 0xC3, 0xC3, 0xC1, 0xC3, 0xC3, 0x66, 0x3C, - 0xFF, 0xFF, 0x06, 0x06, 0x0C, 0x08, 0x18, 0x18, 0x30, 0x30, 0x30, 0x20, - 0x20, 0x3C, 0x66, 0xC3, 0xC3, 0x46, 0x3C, 0x66, 0xC3, 0x81, 0x81, 0xC3, - 0x66, 0x3C, 0x3C, 0x66, 0xC3, 0x83, 0x83, 0xC3, 0xE7, 0x39, 0x03, 0xC3, - 0xC2, 0x6E, 0x3C, 0xC1, 0x80, 0xC1, 0xF0, 0x01, 0x83, 0xC7, 0x8E, 0x0C, - 0x03, 0x80, 0x78, 0x0F, 0x01, 0x80, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, - 0xFC, 0x80, 0x70, 0x1E, 0x01, 0xC0, 0x18, 0x71, 0xE1, 0xC0, 0x80, 0x00, - 0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x0E, 0x08, 0x18, 0x18, 0x00, 0x18, - 0x18, 0x07, 0xF0, 0x07, 0x1E, 0x0C, 0x01, 0x84, 0x00, 0x46, 0x3D, 0x32, - 0x32, 0x8B, 0x30, 0xC5, 0x10, 0x62, 0x98, 0x21, 0x4C, 0x11, 0xA6, 0x19, - 0x99, 0x9D, 0x84, 0x73, 0x83, 0x00, 0x08, 0xC0, 0x1C, 0x3C, 0x38, 0x07, - 0xF0, 0x00, 0x06, 0x00, 0xE0, 0x0F, 0x00, 0xB0, 0x19, 0x81, 0x98, 0x30, - 0x83, 0x0C, 0x3F, 0xC6, 0x06, 0x60, 0x64, 0x06, 0xC0, 0x30, 0xFF, 0x3F, - 0xEC, 0x0B, 0x02, 0xC1, 0xBF, 0xCF, 0xFB, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, - 0xFE, 0xFF, 0x00, 0x1F, 0x07, 0x39, 0x81, 0xE0, 0x3C, 0x01, 0x80, 0x30, - 0x06, 0x00, 0xC0, 0x78, 0x0D, 0x83, 0x1C, 0xE1, 0xF0, 0xFF, 0x1F, 0xF3, - 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, - 0x7F, 0xCF, 0xF0, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x3F, 0xEF, 0xFB, - 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF0, 0x18, - 0x0C, 0x06, 0x03, 0xFD, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x0F, - 0x83, 0x9E, 0x60, 0x64, 0x03, 0xC0, 0x0C, 0x00, 0xC3, 0xFC, 0x3F, 0xC0, - 0x34, 0x03, 0x60, 0x33, 0x9E, 0x0F, 0x80, 0xC0, 0x78, 0x0F, 0x01, 0xE0, - 0x3C, 0x07, 0xFF, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, - 0x06, 0xFF, 0xF8, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x43, 0x42, 0x7E, 0x3C, 0xC0, 0xD8, 0x33, 0x0C, 0x63, 0x0C, 0xC1, 0xB8, - 0x3F, 0x07, 0x30, 0xC3, 0x18, 0x73, 0x06, 0x60, 0x6C, 0x0E, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xE0, - 0x3F, 0x01, 0xFC, 0x1F, 0xA0, 0xFD, 0x05, 0xEC, 0x6F, 0x22, 0x79, 0x13, - 0xCD, 0x9E, 0x28, 0xF1, 0x47, 0x8E, 0x3C, 0x21, 0x80, 0xC0, 0x7C, 0x0F, - 0xC1, 0xF8, 0x3D, 0x87, 0x98, 0xF3, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, - 0xE0, 0x7C, 0x0E, 0x1F, 0x83, 0x9C, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, - 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0x60, 0x63, 0x9C, 0x1F, 0x80, 0xFF, - 0x3F, 0xFC, 0x0F, 0x03, 0xC0, 0xF0, 0x3F, 0xFB, 0xF8, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x00, 0x1F, 0x83, 0x9C, 0x60, 0x6C, 0x03, 0xC0, 0x3C, - 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x33, 0x61, 0xE3, 0x9C, 0x1F, 0xE0, - 0x01, 0xFF, 0x8C, 0x1C, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, - 0x70, 0xC1, 0x8C, 0x18, 0xC0, 0xCC, 0x06, 0xC0, 0x60, 0x3E, 0x1F, 0xEC, - 0x1B, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x07, 0x00, 0xF0, 0x3C, 0x0D, 0xFE, - 0x3F, 0x00, 0xFF, 0xFF, 0xFC, 0x10, 0x02, 0x00, 0x40, 0x08, 0x01, 0x00, - 0x20, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0xC0, 0x78, 0x0F, 0x01, - 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x68, 0x09, 0x83, 0x3F, - 0xC1, 0xF0, 0xC0, 0x34, 0x02, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C, 0x10, - 0x81, 0x98, 0x19, 0x80, 0x90, 0x0F, 0x00, 0x60, 0x06, 0x00, 0xC1, 0xC1, - 0xA0, 0xE0, 0x98, 0x50, 0xCC, 0x2C, 0x66, 0x36, 0x31, 0x11, 0x10, 0x88, - 0x88, 0x6C, 0x6C, 0x36, 0x34, 0x0A, 0x0A, 0x05, 0x05, 0x03, 0x83, 0x80, - 0xC1, 0x80, 0x60, 0x63, 0x04, 0x30, 0xC1, 0x98, 0x0F, 0x00, 0x60, 0x06, - 0x00, 0xF0, 0x19, 0x81, 0x98, 0x30, 0xC6, 0x06, 0xC0, 0x70, 0xC0, 0x26, - 0x06, 0x30, 0xC1, 0x98, 0x19, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, - 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x7F, 0xCF, 0xF8, 0x07, 0x00, 0xC0, - 0x30, 0x0C, 0x03, 0x00, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xFF, 0xFE, - 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xF0, 0x86, 0x10, 0x86, - 0x10, 0x84, 0x30, 0x84, 0x30, 0x80, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0xF0, 0x18, 0x1C, 0x3C, 0x34, 0x26, 0x62, 0x43, 0xFF, 0xC0, - 0xCC, 0x3E, 0xE6, 0xC3, 0x03, 0x0F, 0x7F, 0xC3, 0x83, 0xCF, 0x7B, 0xC0, - 0xC0, 0xC0, 0xDC, 0xF6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC3, 0xC3, 0xE6, 0xDC, - 0x3C, 0x66, 0xC3, 0x80, 0x80, 0x80, 0x83, 0xC3, 0x66, 0x3C, 0x03, 0x03, - 0x03, 0x3B, 0x6F, 0xC3, 0x83, 0x83, 0x83, 0x83, 0xC3, 0x6F, 0x3F, 0x3C, - 0x66, 0xC3, 0x81, 0xFF, 0x80, 0xC0, 0xC3, 0x67, 0x3C, 0x3C, 0xC2, 0x3E, - 0x20, 0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x3B, 0x6F, 0xC3, 0x83, 0x83, - 0x83, 0x83, 0xC3, 0x6F, 0x3B, 0x03, 0x83, 0xEE, 0x7C, 0xC0, 0xC0, 0xC0, - 0xDC, 0xF6, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xF3, 0xFF, - 0xFF, 0xC0, 0x33, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3B, 0xE0, 0xC0, - 0xC0, 0xC0, 0xC6, 0xCC, 0xD8, 0xF0, 0xF0, 0xD8, 0xCC, 0xCC, 0xC6, 0xC3, - 0xFF, 0xFF, 0xFF, 0xC0, 0xDC, 0xF7, 0x3D, 0xF0, 0xC7, 0x84, 0x3C, 0x21, - 0xE1, 0x0F, 0x08, 0x78, 0x43, 0xC2, 0x1E, 0x10, 0xC0, 0xDC, 0xF6, 0xC3, - 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x3C, 0x66, 0xC3, 0x81, 0x81, - 0x81, 0x81, 0xC3, 0x66, 0x3C, 0xDC, 0xF6, 0xC3, 0xC1, 0xC1, 0xC1, 0xC1, - 0xC3, 0xE6, 0xDC, 0xC0, 0xC0, 0xC0, 0xC0, 0x3B, 0x6F, 0xC3, 0x83, 0x83, - 0x83, 0x83, 0xC3, 0x6F, 0x3B, 0x03, 0x03, 0x03, 0x03, 0xFF, 0x71, 0x8C, - 0x63, 0x18, 0xC6, 0x00, 0x7D, 0x9E, 0x1E, 0x07, 0x83, 0xC1, 0xC1, 0xEE, - 0xF8, 0x23, 0x19, 0xF6, 0x31, 0x8C, 0x63, 0x18, 0x43, 0x80, 0xC3, 0xC3, - 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x6F, 0x7B, 0xC1, 0xA0, 0x98, 0xCC, - 0x62, 0x21, 0xB0, 0x50, 0x28, 0x1C, 0x04, 0x00, 0xC2, 0x1E, 0x38, 0x91, - 0xC4, 0xCA, 0x66, 0x53, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, - 0x00, 0x63, 0x31, 0x8D, 0x83, 0x81, 0xC0, 0xE0, 0xD8, 0x6C, 0x63, 0x60, - 0xC0, 0xC1, 0xA0, 0x98, 0xC4, 0x62, 0x21, 0xB0, 0x58, 0x28, 0x1C, 0x06, - 0x02, 0x03, 0x07, 0x03, 0x80, 0x7F, 0x01, 0x81, 0x80, 0x80, 0xC0, 0xC0, - 0xC0, 0xC0, 0xC0, 0x7F, 0xC0, 0x39, 0x18, 0xC6, 0x31, 0x88, 0x82, 0x18, - 0xC6, 0x31, 0x84, 0x38, 0xFF, 0xFF, 0x80, 0xE0, 0x83, 0x0C, 0x30, 0xC3, - 0x04, 0x0C, 0x43, 0x0C, 0x30, 0xC3, 0x08, 0xE0, 0xF8, 0xFF, 0xE3, 0xC0 }; - -const GFXglyph Arial9pt7bGlyphs[] PROGMEM = { - { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' - { 0, 2, 13, 5, 2, -12 }, // 0x21 '!' - { 4, 5, 5, 6, 1, -12 }, // 0x22 '"' - { 8, 10, 13, 10, 0, -12 }, // 0x23 '#' - { 25, 8, 16, 10, 1, -13 }, // 0x24 '$' - { 41, 14, 13, 16, 1, -12 }, // 0x25 '%' - { 64, 11, 13, 12, 1, -12 }, // 0x26 '&' - { 82, 2, 5, 3, 1, -12 }, // 0x27 ''' - { 84, 4, 17, 6, 1, -12 }, // 0x28 '(' - { 93, 4, 17, 6, 1, -12 }, // 0x29 ')' - { 102, 5, 5, 7, 1, -12 }, // 0x2A '*' - { 106, 9, 8, 11, 1, -9 }, // 0x2B '+' - { 115, 1, 5, 5, 2, -1 }, // 0x2C ',' - { 116, 4, 2, 6, 1, -4 }, // 0x2D '-' - { 117, 1, 2, 5, 2, -1 }, // 0x2E '.' - { 118, 5, 13, 5, 0, -12 }, // 0x2F '/' - { 127, 8, 13, 10, 1, -12 }, // 0x30 '0' - { 140, 5, 13, 10, 2, -12 }, // 0x31 '1' - { 149, 8, 13, 10, 1, -12 }, // 0x32 '2' - { 162, 8, 13, 10, 1, -12 }, // 0x33 '3' - { 175, 9, 13, 10, 0, -12 }, // 0x34 '4' - { 190, 8, 13, 10, 1, -12 }, // 0x35 '5' - { 203, 8, 13, 10, 1, -12 }, // 0x36 '6' - { 216, 8, 13, 10, 1, -12 }, // 0x37 '7' - { 229, 8, 13, 10, 1, -12 }, // 0x38 '8' - { 242, 8, 13, 10, 1, -12 }, // 0x39 '9' - { 255, 1, 9, 5, 2, -8 }, // 0x3A ':' - { 257, 1, 12, 5, 2, -8 }, // 0x3B ';' - { 259, 9, 9, 11, 1, -10 }, // 0x3C '<' - { 270, 9, 6, 11, 1, -8 }, // 0x3D '=' - { 277, 9, 9, 11, 1, -10 }, // 0x3E '>' - { 288, 8, 13, 10, 1, -12 }, // 0x3F '?' - { 301, 17, 17, 18, 1, -12 }, // 0x40 '@' - { 338, 12, 13, 12, 0, -12 }, // 0x41 'A' - { 358, 10, 13, 12, 1, -12 }, // 0x42 'B' - { 375, 11, 13, 13, 1, -12 }, // 0x43 'C' - { 393, 11, 13, 13, 1, -12 }, // 0x44 'D' - { 411, 10, 13, 12, 1, -12 }, // 0x45 'E' - { 428, 9, 13, 11, 1, -12 }, // 0x46 'F' - { 443, 12, 13, 14, 1, -12 }, // 0x47 'G' - { 463, 11, 13, 13, 1, -12 }, // 0x48 'H' - { 481, 1, 13, 5, 2, -12 }, // 0x49 'I' - { 483, 8, 13, 9, 0, -12 }, // 0x4A 'J' - { 496, 11, 13, 12, 1, -12 }, // 0x4B 'K' - { 514, 8, 13, 10, 1, -12 }, // 0x4C 'L' - { 527, 13, 13, 15, 1, -12 }, // 0x4D 'M' - { 549, 11, 13, 13, 1, -12 }, // 0x4E 'N' - { 567, 12, 13, 14, 1, -12 }, // 0x4F 'O' - { 587, 10, 13, 12, 1, -12 }, // 0x50 'P' - { 604, 12, 14, 14, 1, -12 }, // 0x51 'Q' - { 625, 12, 13, 13, 1, -12 }, // 0x52 'R' - { 645, 10, 13, 12, 1, -12 }, // 0x53 'S' - { 662, 11, 13, 11, 0, -12 }, // 0x54 'T' - { 680, 11, 13, 13, 1, -12 }, // 0x55 'U' - { 698, 12, 13, 12, 0, -12 }, // 0x56 'V' - { 718, 17, 13, 17, 0, -12 }, // 0x57 'W' - { 746, 12, 13, 12, 0, -12 }, // 0x58 'X' - { 766, 12, 13, 12, 0, -12 }, // 0x59 'Y' - { 786, 11, 13, 11, 0, -12 }, // 0x5A 'Z' - { 804, 4, 17, 5, 1, -12 }, // 0x5B '[' - { 813, 5, 13, 5, 0, -12 }, // 0x5C '\' - { 822, 4, 17, 5, 0, -12 }, // 0x5D ']' - { 831, 8, 7, 8, 0, -12 }, // 0x5E '^' - { 838, 10, 1, 10, 0, 3 }, // 0x5F '_' - { 840, 3, 2, 6, 1, -12 }, // 0x60 '`' - { 841, 8, 10, 10, 1, -9 }, // 0x61 'a' - { 851, 8, 13, 10, 1, -12 }, // 0x62 'b' - { 864, 8, 10, 9, 1, -9 }, // 0x63 'c' - { 874, 8, 13, 10, 1, -12 }, // 0x64 'd' - { 887, 8, 10, 10, 1, -9 }, // 0x65 'e' - { 897, 6, 13, 5, 0, -12 }, // 0x66 'f' - { 907, 8, 14, 10, 1, -9 }, // 0x67 'g' - { 921, 8, 13, 10, 1, -12 }, // 0x68 'h' - { 934, 2, 13, 4, 1, -12 }, // 0x69 'i' - { 938, 4, 17, 4, -1, -12 }, // 0x6A 'j' - { 947, 8, 13, 9, 1, -12 }, // 0x6B 'k' - { 960, 2, 13, 4, 1, -12 }, // 0x6C 'l' - { 964, 13, 10, 15, 1, -9 }, // 0x6D 'm' - { 981, 8, 10, 10, 1, -9 }, // 0x6E 'n' - { 991, 8, 10, 10, 1, -9 }, // 0x6F 'o' - { 1001, 8, 14, 10, 1, -9 }, // 0x70 'p' - { 1015, 8, 14, 10, 1, -9 }, // 0x71 'q' - { 1029, 5, 10, 6, 1, -9 }, // 0x72 'r' - { 1036, 7, 10, 9, 1, -9 }, // 0x73 's' - { 1045, 5, 13, 5, 0, -12 }, // 0x74 't' - { 1054, 8, 10, 10, 1, -9 }, // 0x75 'u' - { 1064, 9, 10, 9, 0, -9 }, // 0x76 'v' - { 1076, 13, 10, 13, 0, -9 }, // 0x77 'w' - { 1093, 9, 10, 9, 0, -9 }, // 0x78 'x' - { 1105, 9, 14, 9, 0, -9 }, // 0x79 'y' - { 1121, 9, 10, 9, 0, -9 }, // 0x7A 'z' - { 1133, 5, 17, 6, 1, -12 }, // 0x7B '{' - { 1144, 1, 17, 5, 2, -12 }, // 0x7C '|' - { 1147, 6, 17, 6, 0, -12 }, // 0x7D '}' - { 1160, 9, 3, 11, 1, -7 } }; // 0x7E '~' - -const GFXfont Arial9pt7b PROGMEM = { - (uint8_t *)Arial9pt7bBitmaps, - (GFXglyph *)Arial9pt7bGlyphs, - 0x20, 0x7E, 21 }; - -// Approx. 1836 bytes diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 41fd505..4d0bc86 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -8,8 +8,6 @@ bool debug = true; bool debug = false; #endif -// EXDisplay *display0 = new EXDisplay(0, new MCUFriendScreen(8, 20), 30); - // This function is called from AtFinder when a // <@ screenid row "text"> message is discovered. diff --git a/EX-Display.ino b/EX-Display.ino index 2610efb..d94b7f7 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -11,12 +11,6 @@ bool StartupPhase = true; unsigned long timestamp = 0; long screencount = 0; -// Chris just doing this for manual testing on my mega... so I can debug down the serial monitor -#if defined(ARDUINO_AVR_MEGA2560) -#undef CS_LISTEN -#define CS_LISTEN Serial -#endif - #if SCREEN_TYPE == MCU MCUFRIEND_kbv tft; MCUFriendScreen *screen = new MCUFriendScreen(tft); @@ -37,9 +31,15 @@ void setup() { AtFinder::setup(100, updateEXDisplayRow); // Create display instances +#if defined(DISPLAY_1_ID) new EXDisplay(DISPLAY_1_ID, screen, 30); +#endif +#if defined(DISPLAY_2_ID) new EXDisplay(DISPLAY_2_ID, screen, 30); +#endif +#if defined(DISPLAY_3_ID) new EXDisplay(DISPLAY_3_ID, screen, 30); +#endif for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); @@ -59,14 +59,6 @@ void setup() { activeDisplay->getEXScreen()->clearScreen(BACKGROUND_COLOUR); - // Setup the start screen. - // if (MAX_SCREENS > 1) { - // currentScreenID = INITIAL_SCREEN; - // } - // else { - // currentScreenID = 0; - // } - timestamp = millis(); CONSOLE.println(F("End of Setup")); } @@ -92,47 +84,5 @@ void loop() { // DISABLE IN STARTUPPHASE else { updateScreen(); - /* DISABLE SO IT WILL COMPILE - if (StartupPhase==false){ - // add thie following in once display is working - // for (byte x= 0; x SCROLLTIME) { - - if (currentScreenID >= MAX_SCREENS-1) { - currentScreenID=0; - } - else { - currentScreenID++; - - } - screencount=millis(); - ScreenChanged[currentScreenID] = true; - - } - #else - if (SCREEN::check_touch) { - if (currentScreenID >= MAX_SCREENS-1) { - currentScreenID=0; - } - else { - currentScreenID++; - - } - - ScreenChanged[currentScreenID] = true; - - } - - #endif - } - */ } } diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 44a44e0..31bb9af 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -76,17 +76,28 @@ void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { } void EXDisplay::scrollUp() { - uint8_t screenRows = _exScreen->maxRows; - uint8_t newPosition = 0; - if (_numberOfRows <= screenRows) { - _scrollPosition = newPosition; - } else { - newPosition = _scrollPosition--; - if (newPosition >= _numberOfRows) { - newPosition = 0; + // Scroll up logic: + // _scrollPosition needs to decrement to bring lower rows up the screen + // If _scrollPosition ends at 0, it should become the highest possible row + uint8_t lastRow = _exScreen->maxRows - 1; // Highest possible row number on screen + if (_maxRowNumber <= lastRow) { // If our max row number is on screen, no scroll required + return; + } + if (_scrollPosition == 0) { // If row 0 is top of screen, need to move to the highest row number + _scrollPosition = _maxRowNumber; + } else { // + _scrollPosition--; + } + for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { + uint8_t newRow = row->getDisplayRow(); + if (newRow == _maxRowNumber) { // If row at bottom, it becomes first row + newRow = 0; + } else { // Otherwise move down one row + newRow++; } + row->setDisplayRow(newRow, _exScreen->maxRows); } - _scrollPosition = newPosition; + _needsRedraw = true; // Need to redraw after each scroll } void EXDisplay::scrollDown() { @@ -101,14 +112,14 @@ void EXDisplay::scrollDown() { } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { uint8_t newRow = row->getDisplayRow(); - if (newRow == 0) { + if (newRow == 0) { // If row at top of screen, it becomes last row newRow = _maxRowNumber; - } else { + } else { // Otherwise move up one row newRow--; } row->setDisplayRow(newRow, _exScreen->maxRows); } - _needsRedraw = true; + _needsRedraw = true; // Need to redraw after each scroll } void EXDisplay::autoScroll(unsigned long scrollDelay) { diff --git a/FreeSans12pt7b.h b/FreeSans12pt7b.h deleted file mode 100644 index 6e77392..0000000 --- a/FreeSans12pt7b.h +++ /dev/null @@ -1,272 +0,0 @@ -#pragma once -#include - -const uint8_t FreeSans12pt7bBitmaps[] PROGMEM = { - 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xCF, 0x3C, 0xF3, 0x8A, 0x20, 0x06, 0x30, - 0x31, 0x03, 0x18, 0x18, 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x03, 0x18, 0x18, - 0xC7, 0xFF, 0xBF, 0xFC, 0x31, 0x01, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30, - 0x04, 0x03, 0xE1, 0xFF, 0x72, 0x6C, 0x47, 0x88, 0xF1, 0x07, 0x20, 0x7E, - 0x03, 0xF0, 0x17, 0x02, 0x3C, 0x47, 0x88, 0xF1, 0x1B, 0x26, 0x7F, 0xC3, - 0xE0, 0x10, 0x02, 0x00, 0x00, 0x06, 0x03, 0xC0, 0x40, 0x7E, 0x0C, 0x0E, - 0x70, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xE7, 0x30, 0x07, 0xE6, 0x00, - 0x3C, 0x40, 0x00, 0x0C, 0x7C, 0x00, 0x8F, 0xE0, 0x19, 0xC7, 0x01, 0x18, - 0x30, 0x31, 0x83, 0x02, 0x1C, 0x70, 0x40, 0xFE, 0x04, 0x07, 0xC0, 0x0F, - 0x00, 0x7E, 0x03, 0x9C, 0x0C, 0x30, 0x30, 0xC0, 0xE7, 0x01, 0xF8, 0x03, - 0x80, 0x3E, 0x01, 0xCC, 0x6E, 0x19, 0xB0, 0x7C, 0xC0, 0xF3, 0x03, 0xCE, - 0x1F, 0x9F, 0xE6, 0x1E, 0x1C, 0xFF, 0xA0, 0x08, 0x8C, 0x66, 0x31, 0x98, - 0xC6, 0x31, 0x8C, 0x63, 0x08, 0x63, 0x08, 0x61, 0x0C, 0x20, 0x82, 0x18, - 0xC3, 0x18, 0xC3, 0x18, 0xC6, 0x31, 0x8C, 0x62, 0x31, 0x88, 0xC4, 0x62, - 0x00, 0x10, 0x23, 0x5B, 0xE3, 0x8D, 0x91, 0x00, 0x0C, 0x03, 0x00, 0xC0, - 0x30, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0xF5, 0x60, - 0xFF, 0xF0, 0xF0, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x02, 0x0C, 0x10, 0x20, - 0xC1, 0x02, 0x0C, 0x10, 0x20, 0xC1, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, - 0x6E, 0x0F, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, - 0x0E, 0xC1, 0x9C, 0x71, 0xFC, 0x1F, 0x00, 0x08, 0xCF, 0xFF, 0x8C, 0x63, - 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0x1F, 0x0F, 0xF9, 0x87, 0x60, 0x7C, - 0x06, 0x00, 0xC0, 0x18, 0x07, 0x01, 0xC0, 0xF0, 0x78, 0x1C, 0x06, 0x00, - 0x80, 0x30, 0x07, 0xFF, 0xFF, 0xE0, 0x3F, 0x0F, 0xF3, 0x87, 0x60, 0x6C, - 0x0C, 0x01, 0x80, 0x70, 0x7C, 0x0F, 0x80, 0x18, 0x01, 0x80, 0x3C, 0x07, - 0x80, 0xD8, 0x73, 0xFC, 0x1F, 0x00, 0x01, 0x80, 0x70, 0x0E, 0x03, 0xC0, - 0xD8, 0x1B, 0x06, 0x61, 0x8C, 0x21, 0x8C, 0x33, 0x06, 0x7F, 0xFF, 0xFE, - 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xCF, 0xF9, 0x80, 0x30, 0x06, - 0x00, 0xDE, 0x1F, 0xE7, 0x0E, 0x00, 0xE0, 0x0C, 0x01, 0x80, 0x30, 0x07, - 0x81, 0xF8, 0x73, 0xFC, 0x1F, 0x00, 0x0F, 0x07, 0xF9, 0xC3, 0x30, 0x74, - 0x01, 0x80, 0x33, 0xC7, 0xFE, 0xF0, 0xDC, 0x1F, 0x01, 0xE0, 0x3C, 0x06, - 0xC1, 0xDC, 0x71, 0xFC, 0x1F, 0x00, 0xFF, 0xFF, 0xFC, 0x01, 0x00, 0x60, - 0x18, 0x02, 0x00, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x30, 0x04, 0x01, 0x80, - 0x30, 0x06, 0x01, 0x80, 0x30, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x66, - 0x0C, 0xC1, 0x8C, 0x61, 0xFC, 0x3F, 0x8E, 0x3B, 0x01, 0xE0, 0x3C, 0x07, - 0x80, 0xD8, 0x31, 0xFC, 0x1F, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x6C, - 0x07, 0x80, 0xF0, 0x1E, 0x07, 0x61, 0xEF, 0xFC, 0x79, 0x80, 0x30, 0x05, - 0x81, 0x98, 0x73, 0xFC, 0x1E, 0x00, 0xF0, 0x00, 0x03, 0xC0, 0xF0, 0x00, - 0x0F, 0x56, 0x00, 0x00, 0x07, 0x01, 0xE0, 0xF8, 0x3C, 0x0F, 0x00, 0xE0, - 0x07, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0x00, - 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x78, 0x01, 0xF0, 0x07, - 0xC0, 0x0F, 0x00, 0x70, 0x1E, 0x0F, 0x03, 0xC0, 0xF0, 0x08, 0x00, 0x1F, - 0x1F, 0xEE, 0x1B, 0x03, 0xC0, 0xC0, 0x30, 0x0C, 0x06, 0x03, 0x81, 0xC0, - 0xE0, 0x30, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x03, 0x00, 0x00, 0xFE, - 0x00, 0x0F, 0xFE, 0x00, 0xF0, 0x3E, 0x07, 0x00, 0x3C, 0x38, 0x00, 0x30, - 0xC1, 0xE0, 0x66, 0x0F, 0xD9, 0xD8, 0x61, 0xC3, 0xC3, 0x07, 0x0F, 0x1C, - 0x1C, 0x3C, 0x60, 0x60, 0xF1, 0x81, 0x83, 0xC6, 0x06, 0x1B, 0x18, 0x38, - 0xEE, 0x71, 0xE7, 0x18, 0xFD, 0xF8, 0x71, 0xE7, 0xC0, 0xE0, 0x00, 0x01, - 0xE0, 0x00, 0x01, 0xFF, 0xC0, 0x01, 0xFC, 0x00, 0x03, 0xC0, 0x03, 0xC0, - 0x03, 0xC0, 0x07, 0xE0, 0x06, 0x60, 0x06, 0x60, 0x0E, 0x70, 0x0C, 0x30, - 0x0C, 0x30, 0x1C, 0x38, 0x18, 0x18, 0x1F, 0xF8, 0x3F, 0xFC, 0x30, 0x1C, - 0x30, 0x0C, 0x70, 0x0E, 0x60, 0x06, 0x60, 0x06, 0xFF, 0xC7, 0xFF, 0x30, - 0x19, 0x80, 0x6C, 0x03, 0x60, 0x1B, 0x00, 0xD8, 0x0C, 0xFF, 0xC7, 0xFF, - 0x30, 0x0D, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x06, 0xFF, 0xF7, - 0xFE, 0x00, 0x07, 0xE0, 0x3F, 0xF0, 0xE0, 0x73, 0x80, 0x66, 0x00, 0x6C, - 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x00, - 0x06, 0x00, 0x6C, 0x00, 0xDC, 0x03, 0x1E, 0x0E, 0x1F, 0xF8, 0x0F, 0xC0, - 0xFF, 0x83, 0xFF, 0x8C, 0x07, 0x30, 0x0E, 0xC0, 0x1B, 0x00, 0x7C, 0x00, - 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x1F, 0x00, - 0x6C, 0x03, 0xB0, 0x1C, 0xFF, 0xE3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xC0, - 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xEF, 0xFE, 0xC0, - 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xFF, 0xDF, - 0xFB, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00, - 0x07, 0xF0, 0x1F, 0xFC, 0x3C, 0x1E, 0x70, 0x06, 0x60, 0x03, 0xE0, 0x00, - 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x7F, 0xC0, 0x7F, 0xC0, 0x03, 0xC0, 0x03, - 0x60, 0x03, 0x60, 0x07, 0x30, 0x0F, 0x3C, 0x1F, 0x1F, 0xFB, 0x07, 0xE1, - 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, - 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, - 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x01, - 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, - 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0x7F, 0x1F, 0x00, 0xC0, 0x3B, 0x01, 0xCC, - 0x0E, 0x30, 0x70, 0xC3, 0x83, 0x1C, 0x0C, 0xE0, 0x33, 0x80, 0xDE, 0x03, - 0xDC, 0x0E, 0x38, 0x30, 0x60, 0xC1, 0xC3, 0x03, 0x8C, 0x06, 0x30, 0x1C, - 0xC0, 0x3B, 0x00, 0x60, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, - 0xFF, 0xFF, 0xF0, 0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x0F, 0xD0, - 0x0F, 0xD8, 0x1B, 0xD8, 0x1B, 0xD8, 0x1B, 0xCC, 0x33, 0xCC, 0x33, 0xCC, - 0x33, 0xC6, 0x63, 0xC6, 0x63, 0xC6, 0x63, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, - 0xC3, 0xC1, 0x83, 0xE0, 0x1F, 0x00, 0xFC, 0x07, 0xE0, 0x3D, 0x81, 0xEE, - 0x0F, 0x30, 0x79, 0xC3, 0xC6, 0x1E, 0x18, 0xF0, 0xE7, 0x83, 0x3C, 0x1D, - 0xE0, 0x6F, 0x01, 0xF8, 0x0F, 0xC0, 0x3E, 0x01, 0xC0, 0x03, 0xE0, 0x0F, - 0xFC, 0x0F, 0x07, 0x86, 0x00, 0xC6, 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, - 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, - 0x33, 0x00, 0x18, 0xC0, 0x18, 0x78, 0x3C, 0x1F, 0xFC, 0x03, 0xF8, 0x00, - 0xFF, 0x8F, 0xFE, 0xC0, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x07, - 0xFF, 0xEF, 0xFC, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, - 0xC0, 0x0C, 0x00, 0x03, 0xE0, 0x0F, 0xFC, 0x0F, 0x07, 0x86, 0x00, 0xC6, - 0x00, 0x33, 0x00, 0x1B, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, - 0xF0, 0x00, 0x78, 0x00, 0x36, 0x00, 0x33, 0x01, 0x98, 0xC0, 0xFC, 0x78, - 0x3C, 0x1F, 0xFF, 0x03, 0xF9, 0x80, 0x00, 0x40, 0xFF, 0xC3, 0xFF, 0xCC, - 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x0C, 0xFF, 0xE3, - 0xFF, 0xCC, 0x03, 0xB0, 0x06, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xB0, 0x06, - 0xC0, 0x1B, 0x00, 0x70, 0x0F, 0xE0, 0x7F, 0xC3, 0x83, 0x9C, 0x07, 0x60, - 0x0D, 0x80, 0x06, 0x00, 0x1E, 0x00, 0x3F, 0x80, 0x3F, 0xC0, 0x0F, 0x80, - 0x07, 0xC0, 0x0F, 0x00, 0x3E, 0x00, 0xDE, 0x0E, 0x3F, 0xF0, 0x3F, 0x80, - 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, - 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, - 0x06, 0x00, 0x60, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, - 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, - 0xE0, 0x0F, 0x80, 0xEE, 0x0E, 0x3F, 0xE0, 0x7C, 0x00, 0x60, 0x06, 0xC0, - 0x1D, 0xC0, 0x31, 0x80, 0x63, 0x01, 0xC7, 0x03, 0x06, 0x06, 0x0C, 0x1C, - 0x1C, 0x30, 0x18, 0x60, 0x31, 0xC0, 0x73, 0x00, 0x66, 0x00, 0xDC, 0x01, - 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0xE0, 0x30, 0x1D, 0x80, 0xE0, - 0x76, 0x07, 0x81, 0xD8, 0x1E, 0x06, 0x70, 0x7C, 0x18, 0xC1, 0xB0, 0xE3, - 0x0C, 0xC3, 0x8C, 0x33, 0x0C, 0x38, 0xC6, 0x30, 0x67, 0x18, 0xC1, 0x98, - 0x67, 0x06, 0x61, 0xD8, 0x1D, 0x83, 0x60, 0x3C, 0x0D, 0x80, 0xF0, 0x3E, - 0x03, 0xC0, 0x70, 0x0F, 0x01, 0xC0, 0x18, 0x07, 0x00, 0x70, 0x0E, 0x60, - 0x38, 0xE0, 0x60, 0xE1, 0xC0, 0xC3, 0x01, 0xCC, 0x01, 0xF8, 0x01, 0xE0, - 0x03, 0x80, 0x07, 0x80, 0x1F, 0x00, 0x33, 0x00, 0xE7, 0x03, 0x86, 0x06, - 0x0E, 0x1C, 0x0E, 0x70, 0x0C, 0xC0, 0x1C, 0x60, 0x06, 0x70, 0x0E, 0x30, - 0x1C, 0x38, 0x18, 0x1C, 0x38, 0x0C, 0x30, 0x0E, 0x70, 0x06, 0x60, 0x03, - 0xC0, 0x03, 0xC0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xC0, 0x0E, - 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00, 0x30, 0x03, - 0x80, 0x38, 0x03, 0x80, 0x18, 0x01, 0xC0, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, - 0xC0, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, - 0xF0, 0x81, 0x81, 0x02, 0x06, 0x04, 0x08, 0x18, 0x10, 0x20, 0x60, 0x40, - 0x81, 0x81, 0x02, 0x06, 0x04, 0xFF, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, - 0x33, 0x33, 0x33, 0x3F, 0xF0, 0x0C, 0x0E, 0x05, 0x86, 0xC3, 0x21, 0x19, - 0x8C, 0x83, 0xC1, 0x80, 0xFF, 0xFE, 0xE3, 0x8C, 0x30, 0x3F, 0x07, 0xF8, - 0xE1, 0xCC, 0x0C, 0x00, 0xC0, 0x1C, 0x3F, 0xCF, 0x8C, 0xC0, 0xCC, 0x0C, - 0xE3, 0xC7, 0xEF, 0x3C, 0x70, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, - 0x0C, 0xF8, 0xDF, 0xCF, 0x0E, 0xE0, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, - 0x3C, 0x03, 0xE0, 0x6F, 0x0E, 0xDF, 0xCC, 0xF8, 0x1F, 0x0F, 0xE7, 0x1B, - 0x83, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x38, 0x37, 0x1C, 0xFE, 0x1F, - 0x00, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x3C, 0xCF, 0xFB, 0x8F, - 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0x8F, 0x3F, - 0x63, 0xCC, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x3C, 0x07, 0xFF, 0xFF, 0xFE, - 0x00, 0xC0, 0x1C, 0x0D, 0xC3, 0x1F, 0xE1, 0xF0, 0x3B, 0xD8, 0xC6, 0x7F, - 0xEC, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x00, 0x1E, 0x67, 0xFD, 0xC7, - 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x9F, - 0xB1, 0xE6, 0x00, 0xC0, 0x3E, 0x0E, 0x7F, 0xC7, 0xE0, 0xC0, 0x30, 0x0C, - 0x03, 0x00, 0xC0, 0x33, 0xCD, 0xFB, 0xC7, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, - 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x30, 0xF0, 0x3F, 0xFF, 0xFF, - 0xF0, 0x33, 0x00, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, - 0xE0, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x83, 0x30, 0xC6, 0x30, - 0xCC, 0x1B, 0x83, 0xF0, 0x77, 0x0C, 0x61, 0x8E, 0x30, 0xE6, 0x0C, 0xC1, - 0xD8, 0x18, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xCF, 0x1F, 0x6F, 0xDF, 0xFC, - 0x78, 0xFC, 0x18, 0x3C, 0x0C, 0x1E, 0x06, 0x0F, 0x03, 0x07, 0x81, 0x83, - 0xC0, 0xC1, 0xE0, 0x60, 0xF0, 0x30, 0x78, 0x18, 0x3C, 0x0C, 0x18, 0xCF, - 0x37, 0xEF, 0x1F, 0x83, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, - 0x0F, 0x03, 0xC0, 0xC0, 0x1F, 0x07, 0xF1, 0xC7, 0x70, 0x7C, 0x07, 0x80, - 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1D, 0xC7, 0x1F, 0xC1, 0xF0, 0xCF, 0x8D, - 0xFC, 0xF0, 0xEE, 0x06, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, - 0x07, 0xF0, 0xEF, 0xFC, 0xCF, 0x8C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x00, - 0x1E, 0x67, 0xFD, 0xC7, 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, - 0x7C, 0x1D, 0xC7, 0x9F, 0xF1, 0xE6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, - 0xCF, 0x7F, 0x38, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, 0x3E, 0x1F, - 0xEE, 0x1B, 0x00, 0xC0, 0x3C, 0x07, 0xF0, 0x3E, 0x01, 0xF0, 0x3E, 0x1D, - 0xFE, 0x3E, 0x00, 0x63, 0x19, 0xFF, 0xB1, 0x8C, 0x63, 0x18, 0xC6, 0x31, - 0xE7, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, - 0xF0, 0x7E, 0x3D, 0xFB, 0x3C, 0xC0, 0xE0, 0x66, 0x06, 0x60, 0x67, 0x0C, - 0x30, 0xC3, 0x0C, 0x39, 0x81, 0x98, 0x19, 0x81, 0xF0, 0x0F, 0x00, 0xE0, - 0x0E, 0x00, 0xC1, 0xC1, 0xB0, 0xE1, 0xD8, 0x70, 0xCC, 0x2C, 0x66, 0x36, - 0x31, 0x9B, 0x18, 0xCD, 0x98, 0x64, 0x6C, 0x16, 0x36, 0x0F, 0x1A, 0x07, - 0x8F, 0x03, 0x83, 0x80, 0xC1, 0xC0, 0x60, 0xEE, 0x18, 0xC6, 0x0C, 0xC1, - 0xF0, 0x1C, 0x01, 0x80, 0x78, 0x1B, 0x03, 0x30, 0xC7, 0x30, 0x66, 0x06, - 0xE0, 0x6C, 0x0D, 0x83, 0x38, 0x63, 0x0C, 0x63, 0x0E, 0x60, 0xCC, 0x1B, - 0x03, 0x60, 0x3C, 0x07, 0x00, 0xE0, 0x18, 0x03, 0x00, 0xE0, 0x78, 0x0E, - 0x00, 0xFF, 0xFF, 0xF0, 0x18, 0x0C, 0x07, 0x03, 0x81, 0xC0, 0x60, 0x30, - 0x18, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0x19, 0xCC, 0x63, 0x18, 0xC6, 0x31, - 0x99, 0x86, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x1C, 0x60, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFC, 0xC7, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x0C, 0x33, 0x31, - 0x8C, 0x63, 0x18, 0xC6, 0x73, 0x00, 0x70, 0x3E, 0x09, 0xE4, 0x1F, 0x03, - 0x80}; - -const GFXglyph FreeSans12pt7bGlyphs[] PROGMEM = { - {0, 0, 0, 6, 0, 1}, // 0x20 ' ' - {0, 2, 18, 8, 3, -17}, // 0x21 '!' - {5, 6, 6, 8, 1, -16}, // 0x22 '"' - {10, 13, 16, 13, 0, -15}, // 0x23 '#' - {36, 11, 20, 13, 1, -17}, // 0x24 '$' - {64, 20, 17, 21, 1, -16}, // 0x25 '%' - {107, 14, 17, 16, 1, -16}, // 0x26 '&' - {137, 2, 6, 5, 1, -16}, // 0x27 ''' - {139, 5, 23, 8, 2, -17}, // 0x28 '(' - {154, 5, 23, 8, 1, -17}, // 0x29 ')' - {169, 7, 7, 9, 1, -17}, // 0x2A '*' - {176, 10, 11, 14, 2, -10}, // 0x2B '+' - {190, 2, 6, 7, 2, -1}, // 0x2C ',' - {192, 6, 2, 8, 1, -7}, // 0x2D '-' - {194, 2, 2, 6, 2, -1}, // 0x2E '.' - {195, 7, 18, 7, 0, -17}, // 0x2F '/' - {211, 11, 17, 13, 1, -16}, // 0x30 '0' - {235, 5, 17, 13, 3, -16}, // 0x31 '1' - {246, 11, 17, 13, 1, -16}, // 0x32 '2' - {270, 11, 17, 13, 1, -16}, // 0x33 '3' - {294, 11, 17, 13, 1, -16}, // 0x34 '4' - {318, 11, 17, 13, 1, -16}, // 0x35 '5' - {342, 11, 17, 13, 1, -16}, // 0x36 '6' - {366, 11, 17, 13, 1, -16}, // 0x37 '7' - {390, 11, 17, 13, 1, -16}, // 0x38 '8' - {414, 11, 17, 13, 1, -16}, // 0x39 '9' - {438, 2, 13, 6, 2, -12}, // 0x3A ':' - {442, 2, 16, 6, 2, -11}, // 0x3B ';' - {446, 12, 12, 14, 1, -11}, // 0x3C '<' - {464, 12, 6, 14, 1, -8}, // 0x3D '=' - {473, 12, 12, 14, 1, -11}, // 0x3E '>' - {491, 10, 18, 13, 2, -17}, // 0x3F '?' - {514, 22, 21, 24, 1, -17}, // 0x40 '@' - {572, 16, 18, 16, 0, -17}, // 0x41 'A' - {608, 13, 18, 16, 2, -17}, // 0x42 'B' - {638, 15, 18, 17, 1, -17}, // 0x43 'C' - {672, 14, 18, 17, 2, -17}, // 0x44 'D' - {704, 12, 18, 15, 2, -17}, // 0x45 'E' - {731, 11, 18, 14, 2, -17}, // 0x46 'F' - {756, 16, 18, 18, 1, -17}, // 0x47 'G' - {792, 13, 18, 17, 2, -17}, // 0x48 'H' - {822, 2, 18, 7, 2, -17}, // 0x49 'I' - {827, 9, 18, 13, 1, -17}, // 0x4A 'J' - {848, 14, 18, 16, 2, -17}, // 0x4B 'K' - {880, 10, 18, 14, 2, -17}, // 0x4C 'L' - {903, 16, 18, 20, 2, -17}, // 0x4D 'M' - {939, 13, 18, 18, 2, -17}, // 0x4E 'N' - {969, 17, 18, 19, 1, -17}, // 0x4F 'O' - {1008, 12, 18, 16, 2, -17}, // 0x50 'P' - {1035, 17, 19, 19, 1, -17}, // 0x51 'Q' - {1076, 14, 18, 17, 2, -17}, // 0x52 'R' - {1108, 14, 18, 16, 1, -17}, // 0x53 'S' - {1140, 12, 18, 15, 1, -17}, // 0x54 'T' - {1167, 13, 18, 17, 2, -17}, // 0x55 'U' - {1197, 15, 18, 15, 0, -17}, // 0x56 'V' - {1231, 22, 18, 22, 0, -17}, // 0x57 'W' - {1281, 15, 18, 16, 0, -17}, // 0x58 'X' - {1315, 16, 18, 16, 0, -17}, // 0x59 'Y' - {1351, 13, 18, 15, 1, -17}, // 0x5A 'Z' - {1381, 4, 23, 7, 2, -17}, // 0x5B '[' - {1393, 7, 18, 7, 0, -17}, // 0x5C '\' - {1409, 4, 23, 7, 1, -17}, // 0x5D ']' - {1421, 9, 9, 11, 1, -16}, // 0x5E '^' - {1432, 15, 1, 13, -1, 4}, // 0x5F '_' - {1434, 5, 4, 6, 1, -17}, // 0x60 '`' - {1437, 12, 13, 13, 1, -12}, // 0x61 'a' - {1457, 12, 18, 13, 1, -17}, // 0x62 'b' - {1484, 10, 13, 12, 1, -12}, // 0x63 'c' - {1501, 11, 18, 13, 1, -17}, // 0x64 'd' - {1526, 11, 13, 13, 1, -12}, // 0x65 'e' - {1544, 5, 18, 7, 1, -17}, // 0x66 'f' - {1556, 11, 18, 13, 1, -12}, // 0x67 'g' - {1581, 10, 18, 13, 1, -17}, // 0x68 'h' - {1604, 2, 18, 5, 2, -17}, // 0x69 'i' - {1609, 4, 23, 6, 0, -17}, // 0x6A 'j' - {1621, 11, 18, 12, 1, -17}, // 0x6B 'k' - {1646, 2, 18, 5, 1, -17}, // 0x6C 'l' - {1651, 17, 13, 19, 1, -12}, // 0x6D 'm' - {1679, 10, 13, 13, 1, -12}, // 0x6E 'n' - {1696, 11, 13, 13, 1, -12}, // 0x6F 'o' - {1714, 12, 17, 13, 1, -12}, // 0x70 'p' - {1740, 11, 17, 13, 1, -12}, // 0x71 'q' - {1764, 6, 13, 8, 1, -12}, // 0x72 'r' - {1774, 10, 13, 12, 1, -12}, // 0x73 's' - {1791, 5, 16, 7, 1, -15}, // 0x74 't' - {1801, 10, 13, 13, 1, -12}, // 0x75 'u' - {1818, 12, 13, 12, 0, -12}, // 0x76 'v' - {1838, 17, 13, 17, 0, -12}, // 0x77 'w' - {1866, 11, 13, 11, 0, -12}, // 0x78 'x' - {1884, 11, 18, 11, 0, -12}, // 0x79 'y' - {1909, 10, 13, 12, 1, -12}, // 0x7A 'z' - {1926, 5, 23, 8, 1, -17}, // 0x7B '{' - {1941, 2, 23, 6, 2, -17}, // 0x7C '|' - {1947, 5, 23, 8, 2, -17}, // 0x7D '}' - {1962, 10, 5, 12, 1, -10}}; // 0x7E '~' - -const GFXfont FreeSans12pt7b PROGMEM = {(uint8_t *)FreeSans12pt7bBitmaps, - (GFXglyph *)FreeSans12pt7bGlyphs, 0x20, - 0x7E, 29}; - -// Approx. 2641 bytes diff --git a/OLDEXScreen.cpp b/OLDEXScreen.cpp deleted file mode 100644 index 691273b..0000000 --- a/OLDEXScreen.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * © 2024, Matt Bidwell, Paul Antoine, Colin Murdoch, Chris Harlow - * All rights reserved. - * - * - * This is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * It is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with CommandStation. If not, see . - */ - -// #include "Defines.h" -// #include "DisplayFunctions.h" -// #include "EXDisplayClass.h" -// #include "EXDisplayRow.h" -// #include "OLDEXScreen.h" -// #include "config.h" -// #include -// #include -// #include - - -// MCUFRIEND_kbv tft; - -// #include "Arial9pt7b.h" -//#include "FreeSans12pt7b.h" - -// int ScreenLines; - -/* DISABLE -void TFT_Startup() -{ - - uint16_t ID = tft.readID(); - CONSOLE.print("TFT ID = 0x"); - CONSOLE.println(ID, HEX); - // #ifdef DEBUG - // CONSOLE.println("Calibrate for your Touch Panel"); - // #endif - //if (ID == 0xD3D3) ID = 0x9486; // write-only shield - - tft.begin(ID); - - tft.setRotation(1); - tft.setTextColor(0xFFFF); - tft.fillScreen(BLACK); - - // create a string of blanks for the display. - // This does not seem necessary as we draw the whole screen. - // for (byte x=0; x<=MAX_LINE_LENGTH; x++){ - // blankmsg[x]=' '; - // } - // blankmsg[MAX_LINE_LENGTH+1]='\0'; - - SCREEN::StartScreenPrint(); - -} -*/ - -/* DISABLE -void showmsgXY(int x, int y, int sz, const char *msg) -{ - tft.setFont(); - tft.setFont(&Arial9pt7b); - tft.setCursor(x, y); - tft.setTextSize(sz); - tft.print(msg); - -} -*/ - -/* DISABLE -void setScreenRows(uint8_t rowId) { - -} -*/ - -/* DISABLE -void CheckScreens(){ - - if (ScreenChanged[currentScreenID]==true) { - CONSOLE.print("Time to draw a screen"); - SCREEN::StartScreenPrint(); - PrintInProgress=false; - ScreenChanged[currentScreenID] = false; - - EXDisplay *display = EXDisplay::getDisplayByNumber(currentScreenID); - if (display) { - EXDisplayRow *row = display->getFirstRow(); - CONSOLE.println("Pinting a line"); - SCREEN::PrintALine(row->getRowNumber(), row->getRowText()); - PrintInProgress=true; - } - else { - SCREEN::PrintNoData(); - } - } - else { - if (PrintInProgress) { - EXDisplayRow *row = row->getNext(); - SCREEN::PrintALine(row->getRowNumber(), row->getRowText()); - } - - } -} -*/ - -/* DISABLE -void TFT_DrawHeader() { - char header[25] = {""}; - sprintf(header, "DCC-EX SCREEN %d\n", currentScreenID); - tft.setTextColor(YELLOW); - showmsgXY(1, 20, 1, header); - tft.drawFastHLine(0, 25, tft.width(), WHITE); - tft.setTextColor(WHITE); // set this for all screen lines -} -*/ - -/* DISABLE -void StartScreenPrint() { - CONSOLE.println("New Page"); - tft.fillScreen(BLACK); - - TFT_DrawHeader(); - - CONSOLE.println("Drawn Header\n"); - NextRowToPrint = 0; - NextScreenLine = 0; -} -*/ - -// void PrintNoData() { showmsgXY(100, 100, 1, "No Data"); } - -/* DISABLE -void PrintALine(int Row, char *text) { - - int vpos = (NextScreenLine * 21) + 44; - - // showmsgXY(1, vpos, 1, blankmsg); - - showmsgXY(1, vpos, 1, text); - // increment the screen & line count - NextRowToPrint++; - NextScreenLine++; - - if (NextRowToPrint >= MAX_ROWS) { - // We've reached the end of this data for this page - PrintInProgress = false; - - // Any blank lines needed? - while (NextScreenLine < MAX_ROWS) { - vpos = (NextScreenLine * 21) + 44; - // showmsgXY(1, vpos, 1, blankmsg); - NextScreenLine++; - } - NextRowToPrint = 0; - NextScreenLine = 0; - } -} -*/ - -/* DISABLE -void DisplayScreen() { - - for (byte x = 0; x < 10; x++) { - // printf("Line %d - Use - %d - %s\n", x, DisplayLines[currentScreenID][x].inuse, - // DisplayLines[currentScreenID][x].text); - } -} -*/ - -// bool check_touch() { return false; } diff --git a/OLDEXScreen.h b/OLDEXScreen.h deleted file mode 100644 index 7e79ce4..0000000 --- a/OLDEXScreen.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef OLDEX_SCREEN_H -#define OLDEX_SCREEN_H - -// EX-Screen.h - -// #define DEBUG - -// uint8_t currentScreenID = 0; - -// ALL Touch panels and wiring are DIFFERENT. The touch screen needs to be calibrated -// See the README files for how to run the calibration routine and -// copy-paste results from TouchScreen_Calibr_native.ino into the lines below. -// These settings are for the McuFriend 2.8" shield in Portrait tft.screenRotaion(0) - -//const byte XP = 7, XM = A1, YP = A2, YM = 6; -//const int TS_LEFT=899,TS_RT=122,TS_TOP=100,TS_BOT=898; -//const int TS_LEFT=122,TS_RT=899,TS_TOP=100,TS_BOT=898; - -// Define some colours for the display - -/* DISABLE -#define BLACK 0x0000U -#define RED 0xF800U -#define GREEN 0x07E0U -#define CYAN 0x07FFU -#define MAGENTA 0xF81FU -#define YELLOW 0xFFE0U -#define WHITE 0xFFFFU -*/ -//#define YELLOW 0xE0U -//#define WHITE 0xFFU -//const uint16_t YELLOW = 0xFFE0U; -//const uint16_t WHITE = 0xFFFFU; - - -/*#if defined(ESP32) - #define YELLOW ~YELLOW - #define WHITE ~WHITE -#endif*/ - -// variables to indicate what needs doing to display the screen -/* DISABLE -bool ScreenChanged[MAX_SCREENS]; -bool PrintInProgress=false; -byte NextRowToPrint=0; -byte NextScreenLine=0; -*/ - -/* DISABLE -namespace SCREEN -{ - - void TFT_Startup(); - void showmsgXY(int x, int y, int sz, const char *msg); - void TFT_DrawHeader(); - void testprint(byte lines); - void setScreenRows(uint8_t rowId); - void CheckScreens(); - void StartScreenPrint(); - void PrintNoData(); - //void PrintSingleLine(byte screenNo, byte screenRow); - void PrintALine(int Row, char * text); - void DisplayScreen(); - void check_touch(); - -} -*/ - -#endif \ No newline at end of file From 4b0d2cb55275448b6fa3d56f596fe0cce4bb914f Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 10 May 2024 13:17:00 +1000 Subject: [PATCH 039/146] Fix defines/includes --- Defines.h | 7 ++----- EX-Display.ino | 4 +++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Defines.h b/Defines.h index de86803..b62016b 100644 --- a/Defines.h +++ b/Defines.h @@ -28,18 +28,15 @@ #define SCREEN_ROTATION 1 #endif -/* DISABLE AS THIS TIGHTLY COUPLES ONE DISPLAY TO ONE SCREEN -WE NEED TO HAVE A ONE SCREEN TO MANY DISPLAY RELATIONSHIP -#if SCREEN_0_TYPE == MCU +#if SCREEN_TYPE == MCU #define NEEDS_MCU #define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); -#elif SCREEN_0_TYPE == TFT +#elif SCREEN_TYPE == TFT #define NEEDS_TFT #define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif -*/ // Set up console and CS listener for Mega #if defined(ARDUINO_AVR_MEGA2560) diff --git a/EX-Display.ino b/EX-Display.ino index c0875f2..b4127f5 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -9,9 +9,11 @@ unsigned long timestamp = 0; long screencount = 0; #if SCREEN_TYPE == MCU +#include "MCUFriendScreen.h" MCUFRIEND_kbv tft; MCUFriendScreen *screen = new MCUFriendScreen(tft); #elif SCREEN_TYPE == TFT +#include "TFT_eSPIScreen.h" TFT_eSPI tft = TFT_eSPI(); TFT_eSPIScreen *screen = new TFT_eSPIScreen(tft); #endif @@ -39,7 +41,7 @@ void setup() { #endif for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->setupScreen(SCREEN_ROTATION, TEXT_FONT, BACKGROUND_COLOUR, TEXT_SIZE); + display->getEXScreen()->setupScreen(SCREEN_ROTATION, BACKGROUND_COLOUR, TEXT_SIZE); CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); From 12fe5e2ce57d80260cf51f0ac5fb656b6b3fff68 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 10 May 2024 15:42:58 +1000 Subject: [PATCH 040/146] Can extract colours --- AtFinder.h | 6 ++++ Defines.h | 2 +- DisplayFunctions.cpp | 82 +++++++++++++++++++++++++++++++++++++------- DisplayFunctions.h | 12 ++++++- EXDisplayClass.cpp | 2 -- EXDisplayRow.cpp | 5 +++ EXDisplayRow.h | 7 ++++ version.h | 4 ++- 8 files changed, 102 insertions(+), 18 deletions(-) diff --git a/AtFinder.h b/AtFinder.h index 5149737..4ac40ef 100644 --- a/AtFinder.h +++ b/AtFinder.h @@ -5,7 +5,13 @@ typedef void (*DISPLAY_CALLBACK)(uint8_t screenId, uint8_t row, char *text); class AtFinder { public: + /// @brief Setup the AtFinder parser + /// @param _maxTextLength Maximum length of text the parser will accept + /// @param _callback Parser will call this function and provide display ID, row number, and a char array of text static void setup(uint8_t _maxTextLength, DISPLAY_CALLBACK _callback); + + /// @brief Call this as often as possible with a streaming input (eg. Serial.read()) + /// @param hot The next character to process in the stream static void processInputChar(char hot); private: diff --git a/Defines.h b/Defines.h index b62016b..193c37b 100644 --- a/Defines.h +++ b/Defines.h @@ -13,7 +13,7 @@ // Set default parameters if not set in config.h for some reason #ifndef TEXT_FONT -#define TEXT_FONT ARIAL9PT7B +#define TEXT_FONT MEDIUM #endif #ifndef TEXT_COLOUR #define TEXT_COLOUR WHITE diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 4d0bc86..121545a 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -1,6 +1,5 @@ #include "Defines.h" #include "DisplayFunctions.h" -#include "MCUFriendScreen.h" #ifdef DEBUG bool debug = true; @@ -21,18 +20,28 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { EXDisplay *display = EXDisplay::getDisplayByNumber(screenId); if (display) { - display->updateRow(screenRow, text); - CONSOLE.print(F("\nCallback activated for screen|row|text: ")); - CONSOLE.print(screenId); - CONSOLE.print(F("|")); - CONSOLE.print(screenRow); - CONSOLE.print(F("|")); - CONSOLE.println(text); - // Set a flag so the screen driver knows something has changed. - // ScreenChanged[screenId]=true; - // If this is the current screen we could call a row update line directly from here - // but do we know which screen row to use? - // PrintThisLine(screenId, screenRow, text) + if (embeddedColours(text)) { + uint16_t textColour; + uint16_t backgroundColour; + extractColours(text, &textColour, &backgroundColour); + CONSOLE.print(F("Got colours, text|background: ")); + CONSOLE.print(textColour, HEX); + CONSOLE.print(F("|")); + CONSOLE.println(backgroundColour, HEX); + } else { + display->updateRow(screenRow, text); + CONSOLE.print(F("\nCallback activated for screen|row|text: ")); + CONSOLE.print(screenId); + CONSOLE.print(F("|")); + CONSOLE.print(screenRow); + CONSOLE.print(F("|")); + CONSOLE.println(text); + // Set a flag so the screen driver knows something has changed. + // ScreenChanged[screenId]=true; + // If this is the current screen we could call a row update line directly from here + // but do we know which screen row to use? + // PrintThisLine(screenId, screenRow, text) + } } else { CONSOLE.print("\nCallback ignored for screen "); CONSOLE.println(screenId); @@ -68,3 +77,50 @@ void displayAllRows() { } } } + +bool embeddedColours(const char *message) { + // Check for format #0x0000#0x0000# + if (message[0] != '#' || message[7] != '#' || message[strlen(message) - 1] != '#') { + return false; + } + // Find the positions of the two '#' characters + char *start = strchr(message + 1, '#'); + if (start == NULL) { + return false; + } + char *end = strchr(start + 1, '#'); + if (end == NULL) { + return false; + } + // Check if the hexadecimal values are of the correct length (6 characters) + if (end - start - 1 != 6 || start - message - 1 != 6) { + return false; + } + // Check if the characters between the '#' are valid hexadecimal digits + if (message[1] != '0' || message[2] != 'x' || start[1] != '0' || start[2] != 'x') { + return false; + } + for (const char *p = message + 3; p < start; p++) { + if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { + return false; + } + } + for (const char *p = start + 3; p < end; p++) { + if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { + return false; + } + } + return true; +} + +void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour) { + // Find first # + char *start = strchr(message, '#'); + // Convert text colour + char *endPointer; + *textColour = (uint16_t)strtol(start + 1, &endPointer, 16); + // Find next # + start = strchr(start + 1, '#'); + // Convert background colour + *backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); +} diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 9988dd0..01392d4 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -4,7 +4,6 @@ #include "EXDisplayClass.h" #include - extern bool debug; // extern EXDisplay *display0; @@ -21,4 +20,15 @@ void updateScreen(); /// @brief Display all rows on all screens - handy for debug void displayAllRows(); +/// @brief Check if the provided message contains embedded colours +/// @param message Message to check for format #0x0000#0x0000# +/// @return True|False +bool embeddedColours(const char *message); + +/// @brief Extract text/foreground and background colours +/// @param message Message to extrat colours from +/// @param textColour Integer for the text/foreground colour +/// @param backgroundColour Integer for the background colour +void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour); + #endif diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 31bb9af..313653e 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -125,7 +125,6 @@ void EXDisplay::scrollDown() { void EXDisplay::autoScroll(unsigned long scrollDelay) { if (millis() - _lastScrollTime > scrollDelay) { _lastScrollTime = millis(); - CONSOLE.println(F("Time to scroll")); scrollDown(); } } @@ -200,7 +199,6 @@ void EXDisplay::setPreviousDisplay() { void EXDisplay::autoSwitch(unsigned long switchDelay) { if (millis() - EXDisplay::_lastSwitchTime > switchDelay) { EXDisplay::_lastSwitchTime = millis(); - CONSOLE.println(F("Time to switch")); setNextDisplay(); } } diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 4a03c07..5981c35 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -59,3 +59,8 @@ bool EXDisplayRow::needsRender() { return _needsRender; } EXDisplayRow *EXDisplayRow::getNext() { return _next; } void EXDisplayRow::setNext(EXDisplayRow *next) { _next = next; } + +void EXDisplayRow::setColours(uint16_t textColour, uint16_t backgroundColour) { + _textColour = textColour; + _backgroundColour = backgroundColour; +} diff --git a/EXDisplayRow.h b/EXDisplayRow.h index c0766eb..f21ef76 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -55,6 +55,11 @@ class EXDisplayRow { /// @return Pointer to the next EXDisplayRow object in the linked list EXDisplayRow *getNext(); + /// @brief Set the text/foreground and background colour for this row + /// @param textColour Hex value of the text/foreground colour + /// @param backgroundColour Hex value of the background colour + void setColours(uint16_t textColour, uint16_t backgroundColour); + private: uint8_t _rowNumber; // This is the row number received from the parser uint8_t _maxMalloc; // This is the calculated maximum length of the text received from the parser @@ -63,5 +68,7 @@ class EXDisplayRow { uint8_t _displayRow; // This is the calculated physical row on a display that this line belongs on bool _needsRender; // Flag that is set when row belongs on a physical display, false when off-screen EXDisplayRow *_next; + uint16_t _textColour; // Text/foreground colour for this row + uint16_t _backgroundColour; // Background colour for this row }; #endif \ No newline at end of file diff --git a/version.h b/version.h index 9f961c8..827a496 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,10 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.5" +#define VERSION "0.0.6" +// 0.0.6 includes: +// - Add ability to set individual row colours via the parser // 0.0.5 includes: // - Refactor screen and logical display to enable multiple displays to use the same screen // - Enable timed switching between logical displays From 2a3e177e086ff04861fa24c272de2f950ac47ce5 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Fri, 10 May 2024 18:41:41 +1000 Subject: [PATCH 041/146] Colours working --- DisplayFunctions.cpp | 1 + EXDisplayClass.cpp | 70 +++++++++++++++++++++++++++----------------- EXDisplayClass.h | 11 +++++++ EXDisplayRow.cpp | 7 ++++- EXDisplayRow.h | 10 ++++++- TFT_eSPIScreen.cpp | 4 +++ 6 files changed, 74 insertions(+), 29 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 121545a..3b39093 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -24,6 +24,7 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { uint16_t textColour; uint16_t backgroundColour; extractColours(text, &textColour, &backgroundColour); + display->updateRowColours(screenRow, textColour, backgroundColour); CONSOLE.print(F("Got colours, text|background: ")); CONSOLE.print(textColour, HEX); CONSOLE.print(F("|")); diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 313653e..fa71aa6 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -47,32 +47,19 @@ EXDisplayRow *EXDisplay::getRowByNumber(uint8_t rowNumber) { void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { auto *row = getRowByNumber(rowNumber); if (!row) { - // create a new row and chain it in - row = new EXDisplayRow(rowNumber); - _numberOfRows++; - - // find the row prior to the one we want to add - EXDisplayRow *previous = nullptr; - for (auto peek = _firstRow; peek; peek = peek->getNext()) { - if (peek->getRowNumber() > rowNumber) - break; - previous = peek; - } - if (previous) { - // chain after previous - row->setNext(previous->getNext()); - previous->setNext(row); - } else { - // chain at start of list - row->setNext(_firstRow); - _firstRow = row; - } - if (rowNumber > _maxRowNumber) { - _maxRowNumber = rowNumber; - } + row = _addRow(rowNumber); + row->setDisplayRow(rowNumber, _exScreen->maxRows); } row->setRowText(rowText); - row->setDisplayRow(rowNumber, _exScreen->maxRows); +} + +void EXDisplay::updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour) { + auto *row = getRowByNumber(rowNumber); + if (!row) { + row = _addRow(rowNumber); + row->setDisplayRow(rowNumber, _exScreen->maxRows); + } + row->setRowColours(textColour, backgroundColour); } void EXDisplay::scrollUp() { @@ -85,7 +72,7 @@ void EXDisplay::scrollUp() { } if (_scrollPosition == 0) { // If row 0 is top of screen, need to move to the highest row number _scrollPosition = _maxRowNumber; - } else { // + } else { // _scrollPosition--; } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { @@ -209,9 +196,38 @@ void EXDisplay::redrawDisplay() { } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { if (row->needsRender() && (row->isChanged() || _needsRedraw)) { - _exScreen->writeRow(row->getDisplayRow(), 0, TEXT_COLOUR, BACKGROUND_COLOUR, row->getMaxRowLength(), - row->getRowText()); + _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), + row->getMaxRowLength(), row->getRowText()); } } _needsRedraw = false; } + +EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber) { + // create a new row and chain it in + EXDisplayRow *row = new EXDisplayRow(rowNumber); + _numberOfRows++; + + // find the row prior to the one we want to add + EXDisplayRow *previous = nullptr; + for (auto peek = _firstRow; peek; peek = peek->getNext()) { + if (peek->getRowNumber() > rowNumber) + break; + previous = peek; + } + if (previous) { + // chain after previous + row->setNext(previous->getNext()); + previous->setNext(row); + } else { + // chain at start of list + row->setNext(_firstRow); + _firstRow = row; + } + if (rowNumber > _maxRowNumber) { + _maxRowNumber = rowNumber; + } + row->setRowColours(TEXT_COLOUR, BACKGROUND_COLOUR); + row->setRowText(""); + return row; +} diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 23adfff..da31841 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -46,6 +46,12 @@ class EXDisplay { /// @param rowText Char array of text for the row void updateRow(uint8_t rowNumber, char *rowText); + /// @brief Update text/foreground and background colours for the specified row + /// @param rowNumber Row number for colours, 0 - 255 + /// @param textColour Any valid hex colour code + /// @param backgroundColour Any valid hex colour code + void updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour); + /// @brief Scroll up one row vertically void scrollUp(); @@ -120,6 +126,11 @@ class EXDisplay { static unsigned long _lastSwitchTime; // Last time in milliseconds an auto switch was done bool _needsRedraw; // Flag if this display needs to be redrawn static EXDisplay *_activeDisplay; // Pointer to the current active display + + /// @brief Private method to add a row + /// @param rowNumber 0 - 255 + /// @return Pointer to the created EXDisplayRow object + EXDisplayRow *_addRow(uint8_t rowNumber); }; #endif diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 5981c35..e9945d9 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -60,7 +60,12 @@ EXDisplayRow *EXDisplayRow::getNext() { return _next; } void EXDisplayRow::setNext(EXDisplayRow *next) { _next = next; } -void EXDisplayRow::setColours(uint16_t textColour, uint16_t backgroundColour) { +void EXDisplayRow::setRowColours(uint16_t textColour, uint16_t backgroundColour) { _textColour = textColour; _backgroundColour = backgroundColour; + _changed = true; } + +uint16_t EXDisplayRow::getTextColour() { return _textColour; } + +uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index f21ef76..6cd066b 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -58,7 +58,15 @@ class EXDisplayRow { /// @brief Set the text/foreground and background colour for this row /// @param textColour Hex value of the text/foreground colour /// @param backgroundColour Hex value of the background colour - void setColours(uint16_t textColour, uint16_t backgroundColour); + void setRowColours(uint16_t textColour, uint16_t backgroundColour); + + /// @brief Get the text/foreground colour for this row + /// @return Colour code + uint16_t getTextColour(); + + /// @brief Get the background colour for this row + /// @return Colour code + uint16_t getBackgroundColour(); private: uint8_t _rowNumber; // This is the row number received from the parser diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index f5f8006..90519dc 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -33,6 +33,10 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t textRow = (row * fontHeight) + row; uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); + CONSOLE.print(F("fontColour|backgroundColour: 0x")); + CONSOLE.print(fontColour, HEX); + CONSOLE.print(F("|0x")); + CONSOLE.println(backgroundColour, HEX); _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); } From 104d4fbf9492f6b9a0f89f834cca141e07cf8244 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sat, 11 May 2024 07:26:51 +1000 Subject: [PATCH 042/146] Start on line --- EXDisplayClass.cpp | 9 +++++++-- EXDisplayRow.cpp | 10 ++++++++++ EXDisplayRow.h | 21 +++++++++++++++++++-- EXScreen.h | 24 +++++++++++++++--------- MCUFriendScreen.cpp | 31 +++---------------------------- MCUFriendScreen.h | 3 --- TFT_eSPIScreen.cpp | 15 +++++++++++---- TFT_eSPIScreen.h | 3 +++ version.h | 1 + 9 files changed, 69 insertions(+), 48 deletions(-) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index fa71aa6..982a4ff 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -196,8 +196,13 @@ void EXDisplay::redrawDisplay() { } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { if (row->needsRender() && (row->isChanged() || _needsRedraw)) { - _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), - row->getMaxRowLength(), row->getRowText()); + if (row->isLine()) { + _exScreen->writeLine(row->getDisplayRow(), 0, 5, _exScreen->maxColumns, row->getTextColour(), + row->getBackgroundColour()); + } else { + _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), + _exScreen->maxColumns, row->getRowText()); + } } } _needsRedraw = false; diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index e9945d9..31d4281 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -69,3 +69,13 @@ void EXDisplayRow::setRowColours(uint16_t textColour, uint16_t backgroundColour) uint16_t EXDisplayRow::getTextColour() { return _textColour; } uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } + +void EXDisplayRow::setLine(bool line) { + _rowAttributes.line = line; + _changed = true; + if (line) { + _rowText = nullptr; + } +} + +bool EXDisplayRow::isLine() { return _rowAttributes.line; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 6cd066b..5e7af18 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -9,6 +9,14 @@ * */ class EXDisplayRow { + + /// @brief Struct for row attributes, which allows for 8 in total + struct RowAttributes { + bool line : 1; + bool neverTicker : 1; + bool alwaysTicker : 1; + }; + public: /// @brief Constructor for the EXDisplayRow object /// @param rowNumber Row number on the display, 0 - 255 @@ -68,6 +76,14 @@ class EXDisplayRow { /// @return Colour code uint16_t getBackgroundColour(); + /// @brief Set if this row is a line or not, if it is, will clear any text + /// @param line true|false + void setLine(bool line); + + /// @brief Check if this row is a line + /// @return true|false + bool isLine(); + private: uint8_t _rowNumber; // This is the row number received from the parser uint8_t _maxMalloc; // This is the calculated maximum length of the text received from the parser @@ -76,7 +92,8 @@ class EXDisplayRow { uint8_t _displayRow; // This is the calculated physical row on a display that this line belongs on bool _needsRender; // Flag that is set when row belongs on a physical display, false when off-screen EXDisplayRow *_next; - uint16_t _textColour; // Text/foreground colour for this row - uint16_t _backgroundColour; // Background colour for this row + uint16_t _textColour; // Text/foreground colour for this row + uint16_t _backgroundColour; // Background colour for this row + EXDisplayRow::RowAttributes _rowAttributes; // One bit per attribute to allow 8 total }; #endif \ No newline at end of file diff --git a/EXScreen.h b/EXScreen.h index a83c94d..a018fc2 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -35,18 +35,24 @@ class EXScreen { virtual void clearScreen(uint16_t backgroundColour); /// @brief Virtual function to implement to write a row of text to the physical screen - /// @param row - /// @param column - /// @param fontColour - /// @param backgroundColour - /// @param maxLength - /// @param message + /// @param row Row on screen, 0 - 255 (not pixels) + /// @param column Column on screen, 0 - 255 (not pixels) + /// @param fontColour Valid colour for the text + /// @param backgroundColour Valid colour for the background + /// @param maxLength Maximum number of columns (not pixels) that can fit on the screen + /// @param message Char array containing the text to display virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message); - // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t - // maxLength, - // char *message); + /// @brief Virtual function to implement to write a horizontal line on the specified row + /// @param row Row on screen, 0 - 255 (not pixels) + /// @param column Column to start the line, 0 - 255 (not pixels) + /// @param lineWidth Pixel width to make the line + /// @param lineLength Number of columns for the line (not pixels), 0 - 255 + /// @param lineColour Valid colour for the line + /// @param backgroundColour Valid colour for the background + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour); /// @brief Height of the font in use to determine row height uint8_t fontHeight; diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index e743ad6..2dac65f 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -56,8 +56,8 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint8_t maxLength, char *message) { CONSOLE.print(F("row:")); CONSOLE.println(row); - //uint16_t textRow = ((row+1) * fontHeight) + row; - uint16_t textRow = ((row+1) * fontHeight); + // uint16_t textRow = ((row+1) * fontHeight) + row; + uint16_t textRow = ((row + 1) * fontHeight); CONSOLE.print(F("textRow:")); CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; @@ -69,29 +69,4 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, _tft.print(message); } -// void MCUFriendScreen::writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, -// uint8_t maxLength, char *message) { - -// CONSOLE.print(F("Heading at column ")); -// CONSOLE.print(column); -// // uint16_t textRow = ((row +1) * fontHeight) + fontHeight; -// _tft.setTextColor(fontColour, backgroundColour); -// _tft.setCursor(row, column); -// _tft.print(message); -// _tft.drawFastHLine(0, 30, _tft.width(), WHITE); -// } - -/* -void EXScreen::newPage(uint8_t screenId) { - // Method here to write new page to the display - CONSOLE.println("New Page"); - tft.fillScreen(BLACK); - char header[25] = {""}; - sprintf(header, "DCC-EX SCREEN %d\n", screenId); - tft.setTextColor(YELLOW); - showmsgXY(1, 20, 1, header); - tft.drawFastHLine(0, 25, tft.width(), WHITE); - tft.setTextColor(WHITE); // set this for all screen lines -*/ - -#endif \ No newline at end of file +#endif diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 544ff14..d5c530c 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -20,9 +20,6 @@ class MCUFriendScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; - // virtual void writeHeaderRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, - // uint8_t maxLength, char *message); - uint8_t getCharacterWidth(const char *character); private: diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 90519dc..4793b4d 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -33,12 +33,19 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t textRow = (row * fontHeight) + row; uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); - CONSOLE.print(F("fontColour|backgroundColour: 0x")); - CONSOLE.print(fontColour, HEX); - CONSOLE.print(F("|0x")); - CONSOLE.println(backgroundColour, HEX); _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); } +void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) { + // The line should be drawn in the middle of the row + // x1/y1 start of line, x2/y2 end of line + int32_t x1 = column; + int32_t y1 = (row * fontHeight) + row; + int32_t x2 = fontWidth * lineLength; + int32_t y2 = y1 + lineWidth; + _tft.drawLine(x1, y1, x2, y2, lineColour); +} + #endif diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 6cffe4d..d0ed20f 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -20,6 +20,9 @@ class TFT_eSPIScreen : public EXScreen { virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) override; + private: TFT_eSPI &_tft; }; diff --git a/version.h b/version.h index 827a496..1ef7ff4 100644 --- a/version.h +++ b/version.h @@ -6,6 +6,7 @@ // 0.0.6 includes: // - Add ability to set individual row colours via the parser +// - Add ability to draw a horizontal line via the parser // 0.0.5 includes: // - Refactor screen and logical display to enable multiple displays to use the same screen // - Enable timed switching between logical displays From 8e5f58128ecd259fe802684d35abfe3ecc5a73df Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 13 May 2024 05:04:07 +1000 Subject: [PATCH 043/146] Capture line progress --- DisplayFunctions.cpp | 61 ++++++++++++++++++++++++++++++++++---------- DisplayFunctions.h | 29 +++++++++++++++++++-- EXDisplayClass.cpp | 19 ++++++++++---- EXDisplayClass.h | 12 ++++++--- EXDisplayRow.cpp | 23 ++++++++++++----- EXDisplayRow.h | 24 +++++++---------- EXScreen.h | 11 +++++--- TFT_eSPIScreen.cpp | 30 ++++++++++++++++++---- TFT_eSPIScreen.h | 4 ++- 9 files changed, 159 insertions(+), 54 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 3b39093..379baaa 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -25,12 +25,12 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { uint16_t backgroundColour; extractColours(text, &textColour, &backgroundColour); display->updateRowColours(screenRow, textColour, backgroundColour); - CONSOLE.print(F("Got colours, text|background: ")); - CONSOLE.print(textColour, HEX); - CONSOLE.print(F("|")); - CONSOLE.println(backgroundColour, HEX); + } else if (embeddedAttributes(text)) { + uint8_t attributes; + extractAttributes(text, &attributes); + display->updateRowAttributes(screenRow, attributes); } else { - display->updateRow(screenRow, text); + display->updateRowText(screenRow, text); CONSOLE.print(F("\nCallback activated for screen|row|text: ")); CONSOLE.print(screenId); CONSOLE.print(F("|")); @@ -57,7 +57,7 @@ void updateScreen() { #ifdef DISPLAY_SWITCH_TIME display->autoSwitch(DISPLAY_SWITCH_TIME); #endif - display->redrawDisplay(); + display->processDisplay(); } void displayAllRows() { @@ -84,29 +84,33 @@ bool embeddedColours(const char *message) { if (message[0] != '#' || message[7] != '#' || message[strlen(message) - 1] != '#') { return false; } - // Find the positions of the two '#' characters - char *start = strchr(message + 1, '#'); + // Find the positions of the three '#' characters + char *start = strchr(message, '#'); if (start == NULL) { return false; } - char *end = strchr(start + 1, '#'); + char *middle = strchr(start + 1, '#'); + if (middle ==NULL) { + return false; + } + char *end = strchr(middle + 1, '#'); if (end == NULL) { return false; } // Check if the hexadecimal values are of the correct length (6 characters) - if (end - start - 1 != 6 || start - message - 1 != 6) { + if (end - middle - 1 != 6 || middle - start - 1 != 6) { return false; } // Check if the characters between the '#' are valid hexadecimal digits - if (message[1] != '0' || message[2] != 'x' || start[1] != '0' || start[2] != 'x') { + if (message[1] != '0' || message[2] != 'x' || middle[1] != '0' || middle[2] != 'x') { return false; } - for (const char *p = message + 3; p < start; p++) { + for (const char *p = message + 3; p < middle; p++) { if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { return false; } } - for (const char *p = start + 3; p < end; p++) { + for (const char *p = middle + 3; p < end; p++) { if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { return false; } @@ -125,3 +129,34 @@ void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundCol // Convert background colour *backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); } + +bool embeddedAttributes(const char *message) { + // Check for format #00000000# + if (message[0] != '#' || message[strlen(message) - 1] != '#') { + return false; + } + // Find the positions of the two '#' characters + char *start = strchr(message, '#'); + if (start == NULL) { + return false; + } + char *end = strchr(start + 1, '#'); + if (end == NULL) { + return false; + } + // Validate that each char is a 0 or 1 only + for (const char *p = message + 1; p < end; p++) { + if (!(p[0] >= '0' && p[0] <= '1')) { + return false; + } + } + return true; +} + +void extractAttributes(char *message, uint8_t *attributes) { + // Find first @ + char *start = strchr(message, '#'); + // Convert text colour + char *endPointer; + *attributes = (uint8_t)strtol(start + 1, &endPointer, 10); +} diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 01392d4..a45c22b 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -22,13 +22,38 @@ void displayAllRows(); /// @brief Check if the provided message contains embedded colours /// @param message Message to check for format #0x0000#0x0000# -/// @return True|False +/// @return frue|false bool embeddedColours(const char *message); /// @brief Extract text/foreground and background colours -/// @param message Message to extrat colours from +/// @param message Message to extract colours from (see embeddedColours) /// @param textColour Integer for the text/foreground colour /// @param backgroundColour Integer for the background colour void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour); +/// @brief Check if the provided message contains embedded colours +/// @param message Message to check for format @00000000@ +/// @return true|false +bool embeddedAttributes(const char *message); + +/// @brief Extract attributes from the provided message +/// @param message Message to extract attributes from (see embeddedAttritubes) +/// @param attributes 8 bit integer for the attributes +void extractAttributes(char *message, uint8_t *attributes); + +/// @brief Check if the line attribute (bit 1) is set in the provided message +/// @param message Attribute message (see embeddedAttributes) +/// @return true|false +bool isLine(const char *message); + +/// @brief Check if the always ticker attribute (bit 2) is set in the provided message +/// @param message Attribute message (see embeddedAttributes) +/// @return true|false +bool alwaysTicker(const char *message); + +/// @brief Check if the never ticker attribute (bit 3) is set in the provided message +/// @param message Attribute message (see embeddedAttributes) +/// @return true|false +bool neverTicker(const char *message); + #endif diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 982a4ff..e81c5e3 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -44,7 +44,7 @@ EXDisplayRow *EXDisplay::getRowByNumber(uint8_t rowNumber) { return nullptr; } -void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { +void EXDisplay::updateRowText(uint8_t rowNumber, char *rowText) { auto *row = getRowByNumber(rowNumber); if (!row) { row = _addRow(rowNumber); @@ -59,7 +59,16 @@ void EXDisplay::updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_ row = _addRow(rowNumber); row->setDisplayRow(rowNumber, _exScreen->maxRows); } - row->setRowColours(textColour, backgroundColour); + row->setColours(textColour, backgroundColour); +} + +void EXDisplay::updateRowAttributes(uint8_t rowNumber, uint8_t attributes) { + auto *row = getRowByNumber(rowNumber); + if (!row) { + row = _addRow(rowNumber); + row->setDisplayRow(rowNumber, _exScreen->maxRows); + } + row->setAttributes(attributes); } void EXDisplay::scrollUp() { @@ -190,14 +199,14 @@ void EXDisplay::autoSwitch(unsigned long switchDelay) { } } -void EXDisplay::redrawDisplay() { +void EXDisplay::processDisplay() { if (_needsRedraw) { _exScreen->clearScreen(BACKGROUND_COLOUR); } for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { if (row->needsRender() && (row->isChanged() || _needsRedraw)) { if (row->isLine()) { - _exScreen->writeLine(row->getDisplayRow(), 0, 5, _exScreen->maxColumns, row->getTextColour(), + _exScreen->writeLine(row->getDisplayRow(), 0, _exScreen->maxColumns, row->getTextColour(), row->getBackgroundColour()); } else { _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), @@ -232,7 +241,7 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber) { if (rowNumber > _maxRowNumber) { _maxRowNumber = rowNumber; } - row->setRowColours(TEXT_COLOUR, BACKGROUND_COLOUR); + row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); row->setRowText(""); return row; } diff --git a/EXDisplayClass.h b/EXDisplayClass.h index da31841..a71031b 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -6,7 +6,6 @@ #include "EXScreen.h" #include - /** * @brief Class for each display. * Each display is in a linked list, with associated rows in a linked list as an attribute of the EXDisplay object. @@ -44,14 +43,19 @@ class EXDisplay { /// @brief Update text and ticker for the specified row number, will add if it doesn't exist /// @param rowNumber Row number to display text on, 0 - 255 /// @param rowText Char array of text for the row - void updateRow(uint8_t rowNumber, char *rowText); + void updateRowText(uint8_t rowNumber, char *rowText); /// @brief Update text/foreground and background colours for the specified row /// @param rowNumber Row number for colours, 0 - 255 /// @param textColour Any valid hex colour code /// @param backgroundColour Any valid hex colour code void updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour); - + + /// @brief Update attributes for the specified row + /// @param rowNumber Row number for the attribute, 0 - 255 + /// @param attributes 8 bit integer for attribute states + void updateRowAttributes(uint8_t rowNumber, uint8_t attributes); + /// @brief Scroll up one row vertically void scrollUp(); @@ -107,7 +111,7 @@ class EXDisplay { /// @brief Call this method as often as possible to ensure a physical screen is updated correctly /// @param display Pointer to the EXDisplay object that needs to have it's physical screen updated - void redrawDisplay(); + void processDisplay(); private: // chaining displays diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 31d4281..b1e1c64 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -10,6 +10,7 @@ EXDisplayRow::EXDisplayRow(uint8_t rowNumber) { _rowText = nullptr; _changed = true; _needsRender = false; + _rowAttributes = 0; } uint8_t EXDisplayRow::getRowNumber() { return _rowNumber; } @@ -33,6 +34,9 @@ void EXDisplayRow::setRowText(char *rowText) { _maxMalloc = bytesNeeded; } strcpy(_rowText, rowText); + if (isLine()) { + bitClear(_rowAttributes, 0); + } _changed = true; } @@ -60,7 +64,7 @@ EXDisplayRow *EXDisplayRow::getNext() { return _next; } void EXDisplayRow::setNext(EXDisplayRow *next) { _next = next; } -void EXDisplayRow::setRowColours(uint16_t textColour, uint16_t backgroundColour) { +void EXDisplayRow::setColours(uint16_t textColour, uint16_t backgroundColour) { _textColour = textColour; _backgroundColour = backgroundColour; _changed = true; @@ -70,12 +74,19 @@ uint16_t EXDisplayRow::getTextColour() { return _textColour; } uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } -void EXDisplayRow::setLine(bool line) { - _rowAttributes.line = line; - _changed = true; - if (line) { +void EXDisplayRow::setAttributes(uint8_t attributes) { + _rowAttributes = attributes; + if (bitRead(_rowAttributes, 0)) { _rowText = nullptr; } + _changed = true; } -bool EXDisplayRow::isLine() { return _rowAttributes.line; } +bool EXDisplayRow::isLine() { + _changed = false; + if (bitRead(_rowAttributes, 0)) { + return true; + } else { + return false; + } +} diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 5e7af18..3541690 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -10,13 +10,6 @@ */ class EXDisplayRow { - /// @brief Struct for row attributes, which allows for 8 in total - struct RowAttributes { - bool line : 1; - bool neverTicker : 1; - bool alwaysTicker : 1; - }; - public: /// @brief Constructor for the EXDisplayRow object /// @param rowNumber Row number on the display, 0 - 255 @@ -66,7 +59,7 @@ class EXDisplayRow { /// @brief Set the text/foreground and background colour for this row /// @param textColour Hex value of the text/foreground colour /// @param backgroundColour Hex value of the background colour - void setRowColours(uint16_t textColour, uint16_t backgroundColour); + void setColours(uint16_t textColour, uint16_t backgroundColour); /// @brief Get the text/foreground colour for this row /// @return Colour code @@ -76,11 +69,12 @@ class EXDisplayRow { /// @return Colour code uint16_t getBackgroundColour(); - /// @brief Set if this row is a line or not, if it is, will clear any text - /// @param line true|false - void setLine(bool line); + /// @brief Set the state of the specified attribute + /// @param attribute EXDisplayRow::RowAttributes attribute to set + /// @param state true|false + void setAttributes(uint8_t attributes); - /// @brief Check if this row is a line + /// @brief Check if this row is a horizontal line /// @return true|false bool isLine(); @@ -92,8 +86,8 @@ class EXDisplayRow { uint8_t _displayRow; // This is the calculated physical row on a display that this line belongs on bool _needsRender; // Flag that is set when row belongs on a physical display, false when off-screen EXDisplayRow *_next; - uint16_t _textColour; // Text/foreground colour for this row - uint16_t _backgroundColour; // Background colour for this row - EXDisplayRow::RowAttributes _rowAttributes; // One bit per attribute to allow 8 total + uint16_t _textColour; // Text/foreground colour for this row + uint16_t _backgroundColour; // Background colour for this row + uint8_t _rowAttributes; // One bit per attribute to allow 8 total }; #endif \ No newline at end of file diff --git a/EXScreen.h b/EXScreen.h index a018fc2..842f602 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -30,10 +30,15 @@ class EXScreen { /// @param backgroundColour Fill the screen with this colour during setup virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour); - /// @brief Virtual function to implement - /// @param backgroundColour + /// @brief Virtual function to implement to clear the entire screen + /// @param backgroundColour Valid colour to set the entire screen to virtual void clearScreen(uint16_t backgroundColour); + /// @brief Virtual function to implement to clear the specified row + /// @param row Row number to clear, 0 - 255 + /// @param backgroundColour Valid colour to set the row to + virtual void clearRow(uint8_t row, uint16_t backgroundColour); + /// @brief Virtual function to implement to write a row of text to the physical screen /// @param row Row on screen, 0 - 255 (not pixels) /// @param column Column on screen, 0 - 255 (not pixels) @@ -51,7 +56,7 @@ class EXScreen { /// @param lineLength Number of columns for the line (not pixels), 0 - 255 /// @param lineColour Valid colour for the line /// @param backgroundColour Valid colour for the background - virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour); /// @brief Height of the font in use to determine row height diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 4793b4d..d6c5d95 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -28,6 +28,25 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t ba void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } +void TFT_eSPIScreen::clearRow(uint8_t row, uint16_t backgroundColour) { + int32_t x = (row * fontHeight) + row; + int32_t y = 0; + int32_t w = fontWidth * maxColumns; + int32_t h = fontHeight; + CONSOLE.print(F("clearRow x|y|w|h|colour: ")); + CONSOLE.print(F("|")); + CONSOLE.print(x); + CONSOLE.print(F("|")); + CONSOLE.print(y); + CONSOLE.print(F("|")); + CONSOLE.print(w); + CONSOLE.print(F("|")); + CONSOLE.print(h); + CONSOLE.print(F("|0x")); + CONSOLE.println(backgroundColour, HEX); + _tft.drawRect(x, y, w, h, backgroundColour); +} + void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) { uint16_t textRow = (row * fontHeight) + row; @@ -37,14 +56,15 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, _tft.drawString(message, column, textRow); } -void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, +void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) { - // The line should be drawn in the middle of the row - // x1/y1 start of line, x2/y2 end of line + // Horizontal start/end int32_t x1 = column; - int32_t y1 = (row * fontHeight) + row; int32_t x2 = fontWidth * lineLength; - int32_t y2 = y1 + lineWidth; + // Vertical start - half way up the font height + int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int32_t y2 = y1; + clearRow(row, backgroundColour); _tft.drawLine(x1, y1, x2, y2, lineColour); } diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index d0ed20f..83b793a 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -17,10 +17,12 @@ class TFT_eSPIScreen : public EXScreen { virtual void clearScreen(uint16_t backgroundColour) override; + virtual void clearRow(uint8_t row, uint16_t backgroundColour) override; + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message) override; - virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineWidth, uint8_t lineLength, uint16_t lineColour, + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) override; private: From 30c0332c062c96c0a8bba23e8137d504abfec73b Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 13 May 2024 07:43:03 +1000 Subject: [PATCH 044/146] TFT line working --- DisplayFunctions.cpp | 6 ++++-- EXDisplayRow.cpp | 9 +++++++-- EXDisplayRow.h | 4 ++++ TFT_eSPIScreen.cpp | 17 +++-------------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 379baaa..338f3e3 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -64,7 +64,7 @@ void displayAllRows() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { CONSOLE.print(F("\n\nRows for display ")); CONSOLE.println(display->getDisplayNumber()); - CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender")); + CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender|rowAttributes")); for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { CONSOLE.print(row->getRowNumber()); CONSOLE.print(F("|")); @@ -74,7 +74,9 @@ void displayAllRows() { CONSOLE.print(F("|")); CONSOLE.print(row->isChanged()); CONSOLE.print(F("|")); - CONSOLE.println(row->needsRender()); + CONSOLE.print(row->needsRender()); + CONSOLE.print(F("|")); + CONSOLE.println(row->getAttributes(), BIN); } } } diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index b1e1c64..0192242 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -41,7 +41,7 @@ void EXDisplayRow::setRowText(char *rowText) { } char *EXDisplayRow::getRowText() { - _changed = false; // are you sure... every time? + _changed = false; return _rowText; } @@ -76,8 +76,11 @@ uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } void EXDisplayRow::setAttributes(uint8_t attributes) { _rowAttributes = attributes; + char blankText[1] = {'\0'}; if (bitRead(_rowAttributes, 0)) { - _rowText = nullptr; + _rowText = blankText; + } else if (!bitRead(_rowAttributes, 0) && !_rowText) { + _rowText = blankText; } _changed = true; } @@ -90,3 +93,5 @@ bool EXDisplayRow::isLine() { return false; } } + +uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 3541690..fdd9dee 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -78,6 +78,10 @@ class EXDisplayRow { /// @return true|false bool isLine(); + /// @brief Get all current attributes for the row + /// @return 0 - 255 + uint8_t getAttributes(); + private: uint8_t _rowNumber; // This is the row number received from the parser uint8_t _maxMalloc; // This is the calculated maximum length of the text received from the parser diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index d6c5d95..eba45b4 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -29,22 +29,11 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t ba void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void TFT_eSPIScreen::clearRow(uint8_t row, uint16_t backgroundColour) { - int32_t x = (row * fontHeight) + row; - int32_t y = 0; + int32_t x = 0; + int32_t y = (row * fontHeight) + row; int32_t w = fontWidth * maxColumns; int32_t h = fontHeight; - CONSOLE.print(F("clearRow x|y|w|h|colour: ")); - CONSOLE.print(F("|")); - CONSOLE.print(x); - CONSOLE.print(F("|")); - CONSOLE.print(y); - CONSOLE.print(F("|")); - CONSOLE.print(w); - CONSOLE.print(F("|")); - CONSOLE.print(h); - CONSOLE.print(F("|0x")); - CONSOLE.println(backgroundColour, HEX); - _tft.drawRect(x, y, w, h, backgroundColour); + _tft.fillRect(x, y, w, h, backgroundColour); } void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, From ca64468e2956113f608bf4a0fce7d6b43b4bf17e Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 13 May 2024 08:32:44 +1000 Subject: [PATCH 045/146] Add underline, implement MCU --- EX-Display.ino | 4 ++-- EXDisplayClass.cpp | 2 +- EXDisplayRow.cpp | 8 ++++++++ EXDisplayRow.h | 4 ++++ EXScreen.h | 2 +- MCUFriendScreen.cpp | 41 +++++++++++++++++++++++++---------------- MCUFriendScreen.h | 8 ++++++-- TFT_eSPIScreen.cpp | 5 ++++- TFT_eSPIScreen.h | 2 +- 9 files changed, 52 insertions(+), 24 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index b4127f5..4897637 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -51,8 +51,8 @@ void setup() { } EXDisplay *activeDisplay = EXDisplay::getActiveDisplay(); - activeDisplay->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display"); - activeDisplay->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION); + activeDisplay->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display", false); + activeDisplay->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION, false); delay(2000); diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index e81c5e3..5138d81 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -210,7 +210,7 @@ void EXDisplay::processDisplay() { row->getBackgroundColour()); } else { _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), - _exScreen->maxColumns, row->getRowText()); + _exScreen->maxColumns, row->getRowText(), row->isUnderlined()); } } } diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 0192242..3c16e1e 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -94,4 +94,12 @@ bool EXDisplayRow::isLine() { } } +bool EXDisplayRow::isUnderlined() { + if (bitRead(_rowAttributes, 1)) { + return true; + } else { + return false; + } +} + uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index fdd9dee..70e2e86 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -78,6 +78,10 @@ class EXDisplayRow { /// @return true|false bool isLine(); + /// @brief Check if this row should be underlined + /// @return true|false + bool isUnderlined(); + /// @brief Get all current attributes for the row /// @return 0 - 255 uint8_t getAttributes(); diff --git a/EXScreen.h b/EXScreen.h index 842f602..c178d2f 100644 --- a/EXScreen.h +++ b/EXScreen.h @@ -47,7 +47,7 @@ class EXScreen { /// @param maxLength Maximum number of columns (not pixels) that can fit on the screen /// @param message Char array containing the text to display virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message); + char *message, bool underlined); /// @brief Virtual function to implement to write a horizontal line on the specified row /// @param row Row on screen, 0 - 255 (not pixels) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 2dac65f..5248e36 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -33,14 +33,6 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b fontWidth = getCharacterWidth("A"); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; - CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); - CONSOLE.print(fontHeight); - CONSOLE.print(F("|")); - CONSOLE.print(fontWidth); - CONSOLE.print(F("|")); - CONSOLE.print(_tft.height()); - CONSOLE.print(F("|")); - CONSOLE.println(_tft.width()); } uint8_t MCUFriendScreen::getCharacterWidth(const char *character) { @@ -52,21 +44,38 @@ uint8_t MCUFriendScreen::getCharacterWidth(const char *character) { void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } +void MCUFriendScreen::clearRow(uint8_t row, uint16_t backgroundColour) { + uint16_t textRow = ((row + 1) * fontHeight); + int32_t x = 0; + int32_t y = ((textRow - fontHeight) + 10); + int32_t w = fontWidth * maxColumns; + int32_t h = fontHeight; + _tft.fillRect(x, y, w, h, backgroundColour); +} + void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, - uint8_t maxLength, char *message) { - CONSOLE.print(F("row:")); - CONSOLE.println(row); - // uint16_t textRow = ((row+1) * fontHeight) + row; + uint8_t maxLength, char *message, bool underlined) { uint16_t textRow = ((row + 1) * fontHeight); - CONSOLE.print(F("textRow:")); - CONSOLE.println(textRow); uint16_t width = fontWidth * maxLength; - uint16_t paddedColumn = column + width; _tft.fillRect(1, ((textRow - fontHeight) + 10), DISPLAY_WIDTH, (fontHeight), backgroundColour); _tft.setTextColor(fontColour, backgroundColour); - //_tft.setCursor(paddedColumn, textRow); _tft.setCursor(1, textRow); _tft.print(message); + if (underlined) { + _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); + } +} + +void MCUFriendScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) { + // Horizontal start/end + int32_t x1 = column; + int32_t x2 = fontWidth * lineLength; + // Vertical start - half way up the font height + int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int32_t y2 = y1; + clearRow(row, backgroundColour); + _tft.drawLine(x1, y1, x2, y2, lineColour); } #endif diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index d5c530c..6b22327 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -17,14 +17,18 @@ class MCUFriendScreen : public EXScreen { virtual void clearScreen(uint16_t backgroundColour) override; + virtual void clearRow(uint8_t row, uint16_t backgroundColour) override; + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message) override; + char *message, bool underlined) override; + + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) override; uint8_t getCharacterWidth(const char *character); private: MCUFRIEND_kbv &_tft; - GFXfont _gfxFont; }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index eba45b4..f137c4f 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -37,12 +37,15 @@ void TFT_eSPIScreen::clearRow(uint8_t row, uint16_t backgroundColour) { } void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, - uint8_t maxLength, char *message) { + uint8_t maxLength, char *message, bool underlined) { uint16_t textRow = (row * fontHeight) + row; uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); _tft.drawString(message, column, textRow); + if (underlined) { + _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); + } } void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 83b793a..bea1ac5 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -20,7 +20,7 @@ class TFT_eSPIScreen : public EXScreen { virtual void clearRow(uint8_t row, uint16_t backgroundColour) override; virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message) override; + char *message, bool underlined) override; virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) override; From f4bd2916c9e13c83ab8add6847689639da9f9224 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Mon, 13 May 2024 19:09:19 +1000 Subject: [PATCH 046/146] Update README, revisit attributes --- DisplayFunctions.cpp | 33 +++++++++++++++++++++++++++++++ DisplayFunctions.h | 21 ++++++++++++-------- EXDisplayClass.cpp | 9 +++++++++ EXDisplayClass.h | 7 ++++++- EXDisplayRow.h | 8 ++++++++ README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 9 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 338f3e3..f94f0d0 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -31,6 +31,7 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { display->updateRowAttributes(screenRow, attributes); } else { display->updateRowText(screenRow, text); + display->updateRowUnderline(screenRow, underline(text)); CONSOLE.print(F("\nCallback activated for screen|row|text: ")); CONSOLE.print(screenId); CONSOLE.print(F("|")); @@ -162,3 +163,35 @@ void extractAttributes(char *message, uint8_t *attributes) { char *endPointer; *attributes = (uint8_t)strtol(start + 1, &endPointer, 10); } + +bool underline(const char *message) { + // Check for leading and trailing "_" + if (message[0] != '_' || message[strlen(message) - 1] != '_') { + return false; + } + return true; +} + +bool line(const char *message) { + // Check for exactly "--" + if (strlen(message) != 3 || (message[0] != '-' && message[strlen(message) - 1] != '-')) { + return false; + } + return true; +} + +bool alwaysTicker(const char *message) { + // Check for leading "~~" + if (message[0] != '~' || message[1] != '~') { + return false; + } + return true; +} + +bool neverTicker(const char *message) { + // Check for leading "~~" + if (message[0] != '!' || message[1] != '~') { + return false; + } + return true; +} diff --git a/DisplayFunctions.h b/DisplayFunctions.h index a45c22b..4bff15d 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -32,7 +32,7 @@ bool embeddedColours(const char *message); void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour); /// @brief Check if the provided message contains embedded colours -/// @param message Message to check for format @00000000@ +/// @param message Message to check for format #00000000# /// @return true|false bool embeddedAttributes(const char *message); @@ -41,18 +41,23 @@ bool embeddedAttributes(const char *message); /// @param attributes 8 bit integer for the attributes void extractAttributes(char *message, uint8_t *attributes); -/// @brief Check if the line attribute (bit 1) is set in the provided message -/// @param message Attribute message (see embeddedAttributes) +/// @brief Check if the provided message indicates it should be underlined +/// @param message Message to check for leading and trailing "_" /// @return true|false -bool isLine(const char *message); +bool underline(const char *message); -/// @brief Check if the always ticker attribute (bit 2) is set in the provided message -/// @param message Attribute message (see embeddedAttributes) +/// @brief Check if the provided message indicates it should be a horizontal line +/// @param message Message to check for "--" +/// @return true|false +bool line(const char *message); + +/// @brief Check if this text should always ticker +/// @param message Message to check for leading "~~" /// @return true|false bool alwaysTicker(const char *message); -/// @brief Check if the never ticker attribute (bit 3) is set in the provided message -/// @param message Attribute message (see embeddedAttributes) +/// @brief Check if this text should never ticker +/// @param message Message to check for leading "!~" /// @return true|false bool neverTicker(const char *message); diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 5138d81..3d22022 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -71,6 +71,15 @@ void EXDisplay::updateRowAttributes(uint8_t rowNumber, uint8_t attributes) { row->setAttributes(attributes); } +void EXDisplay::updateRowUnderline(uint8_t rowNumber, bool underline) { + auto *row = getRowByNumber(rowNumber); + if (!row) { + row = _addRow(rowNumber); + row->setDisplayRow(rowNumber, _exScreen->maxRows); + } + // Set underline attribute here +} + void EXDisplay::scrollUp() { // Scroll up logic: // _scrollPosition needs to decrement to bring lower rows up the screen diff --git a/EXDisplayClass.h b/EXDisplayClass.h index a71031b..85a2ef3 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -54,7 +54,12 @@ class EXDisplay { /// @brief Update attributes for the specified row /// @param rowNumber Row number for the attribute, 0 - 255 /// @param attributes 8 bit integer for attribute states - void updateRowAttributes(uint8_t rowNumber, uint8_t attributes); + void updateRowAttributes(uint8_t rowNumber, uint8_t attributes); + + /// @brief Update underline attribute for the specified row + /// @param rowNumber Row number to set underline for, 0 - 255 + /// @param underline true|false + void updateRowUnderline(uint8_t rowNumber, bool underline); /// @brief Scroll up one row vertically void scrollUp(); diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 70e2e86..c38b8ce 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -11,6 +11,14 @@ class EXDisplayRow { public: + // Where does this really belong, and how can we use it to query and set attributes externally? + struct RowAttributes { + bool line : 1; + bool underline : 1; + bool alwaysTicker : 1; + bool neverTicker : 1; + }; + /// @brief Constructor for the EXDisplayRow object /// @param rowNumber Row number on the display, 0 - 255 EXDisplayRow(uint8_t rowNumber); diff --git a/README.md b/README.md index d5c1313..d9f0447 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,53 @@ In the context of this project, the term "screen" is used when referring to a ph The term "display" refers to a logical representation of a physical screen, enabling one physical screen to be used to dislay information from one or more EXRAIL defined screens. +## Configuration + +Copy "config.example.h" to "config.h". + +The key parameters to set are... + +## Features and Usage + +As features are added they will be outlined here, with examples on how to use them. + +### Basic EXRAIL commands + +The basic EXRAIL command format is `SCREEN(screen, row, "Message")`. + +This example displays the text "This is row 0" on the first row of the first screen: + +`SCREEN(0, 0, "This is row 0")` + +### Setting Colours + +It is possible to set the text/foreground and background colours to any valid hex colour code when setting the colours using the "Message" field of the command. + +This is done by using the format `<@ screen row "#0x#0x#">`. Note that the hex values must be in the format "0xdddd", where "d" represents a four digit colour code. + +This example displays the text "Yellow" on the first row of the first screen with yellow coloured text on a black background: + +``` +SCREEN(0, 0, "#0xFFE0#0x0000") +SCREEN(0, 0, "Yellow") +``` + +### Horizontal Line + +`SCREEN(0, 0, "--")` + +### Underlined Text + +`SCREEN(0, 0, "_This is underlined_")` + +### Always Ticker This Row + +`SCREEN(0, 0, "~~This will always ticker")` + +### Never Ticker This Row + +`SCREEN(0, 0, "!~This will never ticker")` + ## Serial Connections - MEGA: GND-GND and RX pin 19 on mega to serial tx pin on EX-CS From a5213d092b77988d1bba56dcd6ca7d9348a6faae Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 May 2024 07:59:15 +1000 Subject: [PATCH 047/146] Attributes working on TFT --- DisplayFunctions.cpp | 61 +++++--------------------------------------- DisplayFunctions.h | 14 ++-------- EXDisplayClass.cpp | 19 +++++++++++--- EXDisplayClass.h | 9 ++++--- EXDisplayRow.cpp | 29 ++++++++++----------- EXDisplayRow.h | 13 ++++++---- README.md | 4 +++ version.h | 3 ++- 8 files changed, 56 insertions(+), 96 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index f94f0d0..17ddba1 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -25,28 +25,12 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { uint16_t backgroundColour; extractColours(text, &textColour, &backgroundColour); display->updateRowColours(screenRow, textColour, backgroundColour); - } else if (embeddedAttributes(text)) { - uint8_t attributes; - extractAttributes(text, &attributes); - display->updateRowAttributes(screenRow, attributes); + } else if (isLine(text)) { + display->updateRowLine(screenRow, isLine(text)); } else { display->updateRowText(screenRow, text); - display->updateRowUnderline(screenRow, underline(text)); - CONSOLE.print(F("\nCallback activated for screen|row|text: ")); - CONSOLE.print(screenId); - CONSOLE.print(F("|")); - CONSOLE.print(screenRow); - CONSOLE.print(F("|")); - CONSOLE.println(text); - // Set a flag so the screen driver knows something has changed. - // ScreenChanged[screenId]=true; - // If this is the current screen we could call a row update line directly from here - // but do we know which screen row to use? - // PrintThisLine(screenId, screenRow, text) + display->updateRowUnderline(screenRow, isUnderline(text)); } - } else { - CONSOLE.print("\nCallback ignored for screen "); - CONSOLE.println(screenId); } } @@ -133,38 +117,7 @@ void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundCol *backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); } -bool embeddedAttributes(const char *message) { - // Check for format #00000000# - if (message[0] != '#' || message[strlen(message) - 1] != '#') { - return false; - } - // Find the positions of the two '#' characters - char *start = strchr(message, '#'); - if (start == NULL) { - return false; - } - char *end = strchr(start + 1, '#'); - if (end == NULL) { - return false; - } - // Validate that each char is a 0 or 1 only - for (const char *p = message + 1; p < end; p++) { - if (!(p[0] >= '0' && p[0] <= '1')) { - return false; - } - } - return true; -} - -void extractAttributes(char *message, uint8_t *attributes) { - // Find first @ - char *start = strchr(message, '#'); - // Convert text colour - char *endPointer; - *attributes = (uint8_t)strtol(start + 1, &endPointer, 10); -} - -bool underline(const char *message) { +bool isUnderline(const char *message) { // Check for leading and trailing "_" if (message[0] != '_' || message[strlen(message) - 1] != '_') { return false; @@ -172,9 +125,9 @@ bool underline(const char *message) { return true; } -bool line(const char *message) { +bool isLine(const char *message) { // Check for exactly "--" - if (strlen(message) != 3 || (message[0] != '-' && message[strlen(message) - 1] != '-')) { + if (strlen(message) != 2 || message[0] != '-' || message[strlen(message) - 1] != '-') { return false; } return true; @@ -189,7 +142,7 @@ bool alwaysTicker(const char *message) { } bool neverTicker(const char *message) { - // Check for leading "~~" + // Check for leading "!~" if (message[0] != '!' || message[1] != '~') { return false; } diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 4bff15d..0c5e086 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -31,25 +31,15 @@ bool embeddedColours(const char *message); /// @param backgroundColour Integer for the background colour void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour); -/// @brief Check if the provided message contains embedded colours -/// @param message Message to check for format #00000000# -/// @return true|false -bool embeddedAttributes(const char *message); - -/// @brief Extract attributes from the provided message -/// @param message Message to extract attributes from (see embeddedAttritubes) -/// @param attributes 8 bit integer for the attributes -void extractAttributes(char *message, uint8_t *attributes); - /// @brief Check if the provided message indicates it should be underlined /// @param message Message to check for leading and trailing "_" /// @return true|false -bool underline(const char *message); +bool isUnderline(const char *message); /// @brief Check if the provided message indicates it should be a horizontal line /// @param message Message to check for "--" /// @return true|false -bool line(const char *message); +bool isLine(const char *message); /// @brief Check if this text should always ticker /// @param message Message to check for leading "~~" diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 3d22022..5a56ff9 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -9,6 +9,9 @@ EXDisplay *EXDisplay::_activeDisplay = nullptr; /// @brief Define initial last switch time as 0 unsigned long EXDisplay::_lastSwitchTime = 0; +/// @brief Count of displays +uint8_t EXDisplay::_displayCount = 0; + /* * EXDisplay class implementation */ @@ -25,6 +28,7 @@ EXDisplay::EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScree if (!_activeDisplay) { _activeDisplay = _first; } + _displayCount++; } EXDisplay *EXDisplay::getFirst() { return _first; } @@ -62,13 +66,13 @@ void EXDisplay::updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_ row->setColours(textColour, backgroundColour); } -void EXDisplay::updateRowAttributes(uint8_t rowNumber, uint8_t attributes) { +void EXDisplay::updateRowLine(uint8_t rowNumber, bool line) { auto *row = getRowByNumber(rowNumber); if (!row) { row = _addRow(rowNumber); row->setDisplayRow(rowNumber, _exScreen->maxRows); } - row->setAttributes(attributes); + row->setLine(line); } void EXDisplay::updateRowUnderline(uint8_t rowNumber, bool underline) { @@ -77,7 +81,7 @@ void EXDisplay::updateRowUnderline(uint8_t rowNumber, bool underline) { row = _addRow(rowNumber); row->setDisplayRow(rowNumber, _exScreen->maxRows); } - // Set underline attribute here + row->setUnderline(underline); } void EXDisplay::scrollUp() { @@ -178,6 +182,9 @@ void EXDisplay::setNextDisplay() { _activeDisplay->_needsRedraw = true; return; } + if (_displayCount == 1) { + return; + } if (_activeDisplay->_next) { _activeDisplay = _activeDisplay->_next; } else { @@ -192,6 +199,9 @@ void EXDisplay::setPreviousDisplay() { _activeDisplay->_needsRedraw = true; return; } + if (_displayCount == 1) { + return; + } for (EXDisplay *display = _activeDisplay; display; display = display->getNext()) { if (display->getNext() == _activeDisplay) { _activeDisplay = display; @@ -250,7 +260,8 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber) { if (rowNumber > _maxRowNumber) { _maxRowNumber = rowNumber; } + char blank[1] = {'\0'}; row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); - row->setRowText(""); + row->setRowText(blank); return row; } diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 85a2ef3..2f853cc 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -51,10 +51,10 @@ class EXDisplay { /// @param backgroundColour Any valid hex colour code void updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour); - /// @brief Update attributes for the specified row - /// @param rowNumber Row number for the attribute, 0 - 255 - /// @param attributes 8 bit integer for attribute states - void updateRowAttributes(uint8_t rowNumber, uint8_t attributes); + /// @brief Update the line attribute for the specified row + /// @param rowNumber Row number to set to a line, 0 - 255 + /// @param line true|false + void updateRowLine(uint8_t rowNumber, bool line); /// @brief Update underline attribute for the specified row /// @param rowNumber Row number to set underline for, 0 - 255 @@ -135,6 +135,7 @@ class EXDisplay { static unsigned long _lastSwitchTime; // Last time in milliseconds an auto switch was done bool _needsRedraw; // Flag if this display needs to be redrawn static EXDisplay *_activeDisplay; // Pointer to the current active display + static uint8_t _displayCount; /// @brief Private method to add a row /// @param rowNumber 0 - 255 diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 3c16e1e..085df7c 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -74,32 +74,29 @@ uint16_t EXDisplayRow::getTextColour() { return _textColour; } uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } -void EXDisplayRow::setAttributes(uint8_t attributes) { - _rowAttributes = attributes; - char blankText[1] = {'\0'}; - if (bitRead(_rowAttributes, 0)) { - _rowText = blankText; - } else if (!bitRead(_rowAttributes, 0) && !_rowText) { - _rowText = blankText; +void EXDisplayRow::setLine(bool line) { + if (line) { + bitSet(_rowAttributes, 0); + } else { + bitClear(_rowAttributes, 0); } _changed = true; } bool EXDisplayRow::isLine() { _changed = false; - if (bitRead(_rowAttributes, 0)) { - return true; - } else { - return false; - } + return bitRead(_rowAttributes, 0); } -bool EXDisplayRow::isUnderlined() { - if (bitRead(_rowAttributes, 1)) { - return true; +void EXDisplayRow::setUnderline(bool underline) { + if (underline) { + bitSet(_rowAttributes, 1); } else { - return false; + bitClear(_rowAttributes, 1); } + _changed = true; } +bool EXDisplayRow::isUnderlined() { return bitRead(_rowAttributes, 1); } + uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index c38b8ce..b590692 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -77,15 +77,18 @@ class EXDisplayRow { /// @return Colour code uint16_t getBackgroundColour(); - /// @brief Set the state of the specified attribute - /// @param attribute EXDisplayRow::RowAttributes attribute to set - /// @param state true|false - void setAttributes(uint8_t attributes); + /// @brief Set the line attribute for this row + /// @param line true|false + void setLine(bool line); /// @brief Check if this row is a horizontal line /// @return true|false bool isLine(); + /// @brief Set the underline attribute for this row + /// @param underline true|false + void setUnderline(bool underline); + /// @brief Check if this row should be underlined /// @return true|false bool isUnderlined(); @@ -104,6 +107,6 @@ class EXDisplayRow { EXDisplayRow *_next; uint16_t _textColour; // Text/foreground colour for this row uint16_t _backgroundColour; // Background colour for this row - uint8_t _rowAttributes; // One bit per attribute to allow 8 total + byte _rowAttributes; // One bit per attribute to allow 8 total }; #endif \ No newline at end of file diff --git a/README.md b/README.md index d9f0447..e2bbb7b 100644 --- a/README.md +++ b/README.md @@ -51,10 +51,14 @@ SCREEN(0, 0, "Yellow") ### Always Ticker This Row +*Not implemented yet* + `SCREEN(0, 0, "~~This will always ticker")` ### Never Ticker This Row +*Not implemented yet* + `SCREEN(0, 0, "!~This will never ticker")` ## Serial Connections diff --git a/version.h b/version.h index 1ef7ff4..51d02d6 100644 --- a/version.h +++ b/version.h @@ -6,7 +6,8 @@ // 0.0.6 includes: // - Add ability to set individual row colours via the parser -// - Add ability to draw a horizontal line via the parser +// - Add ability to draw a horizontal line on a row rather than text +// - Add ability to underline a row // 0.0.5 includes: // - Refactor screen and logical display to enable multiple displays to use the same screen // - Enable timed switching between logical displays From 91cbcf9623f74e35f447755007a211998aab2771 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 May 2024 08:05:28 +1000 Subject: [PATCH 048/146] Format only --- AtFinder.cpp | 6 ++---- Defines.h | 8 ++++---- DisplayFunctions.cpp | 2 +- EXDisplayRow.h | 2 +- FontOptions.h | 7 ++++--- config.example.h | 4 +--- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/AtFinder.cpp b/AtFinder.cpp index b7554c1..d0fe9fa 100644 --- a/AtFinder.cpp +++ b/AtFinder.cpp @@ -1,7 +1,6 @@ #include "AtFinder.h" #include - /* This is a finite state automation (FSA) to recognize a dccex output message in the format <@ screenid screenrow "text">. @@ -22,13 +21,12 @@ char *AtFinder::text = nullptr; // Set callback function that will be called when message detected. // Note: the code is safe if setup is not called before use because the -// code can not reach the text handling or callback states. +// code can not reach the text handling or callback states. // If the sketch has no reference to the setup function at all, // then compiler constant propagation is smart enough to realise // that it can never reach the text handling states, and thus // the entire function has no effect and is eliminated from the link. - void AtFinder::setup(uint8_t _maxTextLength, DISPLAY_CALLBACK _callback) { maxTextLength = _maxTextLength; text = (char *)malloc(maxTextLength + 1); @@ -82,7 +80,7 @@ void AtFinder::processInputChar(char hot) { screenRow = 0; state = BUILD_ROW; [[fallthrough]]; // character will be reinterpreted - case BUILD_ROW: // building screen row + case BUILD_ROW: // building screen row if (hot == ' ') { state = SKIP_SPACES3; return; diff --git a/Defines.h b/Defines.h index 193c37b..0aa26d6 100644 --- a/Defines.h +++ b/Defines.h @@ -29,11 +29,11 @@ #endif #if SCREEN_TYPE == MCU - #define NEEDS_MCU - #define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); +#define NEEDS_MCU +#define SCREEN_0 new EXDisplay(0, new MCUFriendScreen(tft), 30); #elif SCREEN_TYPE == TFT - #define NEEDS_TFT - #define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); +#define NEEDS_TFT +#define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 17ddba1..844deeb 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -77,7 +77,7 @@ bool embeddedColours(const char *message) { return false; } char *middle = strchr(start + 1, '#'); - if (middle ==NULL) { + if (middle == NULL) { return false; } char *end = strchr(middle + 1, '#'); diff --git a/EXDisplayRow.h b/EXDisplayRow.h index b590692..e405e4a 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -107,6 +107,6 @@ class EXDisplayRow { EXDisplayRow *_next; uint16_t _textColour; // Text/foreground colour for this row uint16_t _backgroundColour; // Background colour for this row - byte _rowAttributes; // One bit per attribute to allow 8 total + byte _rowAttributes; // One bit per attribute to allow 8 total }; #endif \ No newline at end of file diff --git a/FontOptions.h b/FontOptions.h index d1fcacd..4f3aaa1 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,15 +1,16 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#if SCREEN_TYPE==MCU -#include +#if SCREEN_TYPE == MCU #include #include #include -#include +#include #include #include #include +#include + #endif /// @brief Macros for available colours diff --git a/config.example.h b/config.example.h index 19ea760..988eaae 100644 --- a/config.example.h +++ b/config.example.h @@ -16,8 +16,6 @@ #define DISPLAY_2_ID 3 #define DISPLAY_3_ID 8 - - // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display #include "FontOptions.h" @@ -56,7 +54,7 @@ // #define USE_TOUCH // if the touch screen not in use, Now define the scroll requirements -#define SCROLLTIME 5000 // 5 seconds +#define SCROLLTIME 1000 // 5 seconds // If hosting multiple displays on the same screen, set switching delay #define DISPLAY_SWITCH_TIME 5000 From d9f8ff16aaa54176b144e05254207449963e5002 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 May 2024 08:45:14 +1000 Subject: [PATCH 049/146] Start adding MCU debug output --- MCUFriendScreen.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 5248e36..363f1bc 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -8,12 +8,6 @@ MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { const GFXfont *gfxFont = TEXT_FONT; - CONSOLE.print(F("DEBUG Font: first|last|yAdvance: ")); - CONSOLE.print(gfxFont->first); - CONSOLE.print(F("|")); - CONSOLE.print(gfxFont->last); - CONSOLE.print(F("|")); - CONSOLE.println(gfxFont->yAdvance); uint16_t screenId = _tft.readID(); CONSOLE.print("TFT ID: 0x"); @@ -21,6 +15,10 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b if (screenId == 0xD3D3) { screenId = 0x9486; } + if (screenId == 0x0) { + CONSOLE.println(F("NO SCREEN DODGY FORCE TO 0x9486")); + screenId = 0x9486; + } _tft.begin(screenId); _tft.setRotation(rotation); _tft.setFont(gfxFont); @@ -33,6 +31,24 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b fontWidth = getCharacterWidth("A"); maxRows = _tft.height() / fontHeight; maxColumns = _tft.width() / fontWidth; + CONSOLE.println(F("\n~~ SETUP PARAMETERS ~~")); + CONSOLE.print(F("MCUFRIEND_kbv parameters: _tft.height()|_tft.width(): ")); + CONSOLE.print(_tft.height()); + CONSOLE.print(F("|")); + CONSOLE.println(_tft.width()); + CONSOLE.print(F("config.h parameters DISPLAY_HEIGHT|DISPLAY_WIDTH: ")); + CONSOLE.print(DISPLAY_HEIGHT); + CONSOLE.print(F("|")); + CONSOLE.println(DISPLAY_WIDTH); + CONSOLE.print(F("maxRows|maxColumns|fontHeight|fontWidth: ")); + CONSOLE.print(maxRows); + CONSOLE.print(F("|")); + CONSOLE.print(maxColumns); + CONSOLE.print(F("|")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + CONSOLE.println(fontWidth); + CONSOLE.println(F("~~ END SETUP PARAMETERS ~~\n")); } uint8_t MCUFriendScreen::getCharacterWidth(const char *character) { @@ -64,6 +80,12 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, if (underlined) { _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); } + CONSOLE.println(F("\n~~ WRITE ROW PARAMETERS ~~")); + CONSOLE.print(F("textRow|width: ")); + CONSOLE.print(textRow); + CONSOLE.print(F("|")); + CONSOLE.println(width); + CONSOLE.println(F("~~ END WRITE ROW PARAMETERS ~~\n")); } void MCUFriendScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, From 6762d4ec3f5a0e69ef34e2d7767ec9d5d27c844d Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 May 2024 15:31:02 +1000 Subject: [PATCH 050/146] Notes on adding _rowFormatter --- EXDisplayRow.cpp | 10 ++++++++++ EXDisplayRow.h | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 085df7c..69c1d7c 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -100,3 +100,13 @@ void EXDisplayRow::setUnderline(bool underline) { bool EXDisplayRow::isUnderlined() { return bitRead(_rowAttributes, 1); } uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } + +void EXDisplayRow::_rowFormatter(EXDisplayRow *row) { + /* + Need to check for all possible formatting codes here + When formatting codes discovered: + - Apply attributes to _rowAttributes as required + - Copy _rowText to a temp char + - Use strncpy to copy only the text from temp back to _rowText (drop format codes) + */ +} diff --git a/EXDisplayRow.h b/EXDisplayRow.h index e405e4a..f53dc70 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -108,5 +108,9 @@ class EXDisplayRow { uint16_t _textColour; // Text/foreground colour for this row uint16_t _backgroundColour; // Background colour for this row byte _rowAttributes; // One bit per attribute to allow 8 total + + /// @brief Private method to format the row attributes for the specified row + /// @param row Pointer to an EXDisplayRow object + static void _rowFormatter(EXDisplayRow *row); }; #endif \ No newline at end of file From 4b3668d5ddfe3a94de8511de1987944c1de8be43 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Tue, 14 May 2024 15:45:04 +1000 Subject: [PATCH 051/146] More notes --- EXDisplayRow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 69c1d7c..e007bdf 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -108,5 +108,7 @@ void EXDisplayRow::_rowFormatter(EXDisplayRow *row) { - Apply attributes to _rowAttributes as required - Copy _rowText to a temp char - Use strncpy to copy only the text from temp back to _rowText (drop format codes) + - Delete temp char + - Need to add a formatter for DELETING a row, which must delete from linked list + _rowText */ } From c41842d1c54b4f8a43b0820f4f058a6b33159ca1 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Wed, 15 May 2024 06:57:05 +1000 Subject: [PATCH 052/146] Capture progress, formatting not working yet --- DisplayFunctions.cpp | 95 +-------------------------- DisplayFunctions.h | 31 --------- EXDisplayClass.cpp | 41 ++---------- EXDisplayClass.h | 21 +----- EXDisplayRow.cpp | 151 ++++++++++++++++++++++++++++++++++++------- EXDisplayRow.h | 47 +++++++++++--- version.h | 4 +- 7 files changed, 180 insertions(+), 210 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 844deeb..09ceb6c 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -20,17 +20,7 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { EXDisplay *display = EXDisplay::getDisplayByNumber(screenId); if (display) { - if (embeddedColours(text)) { - uint16_t textColour; - uint16_t backgroundColour; - extractColours(text, &textColour, &backgroundColour); - display->updateRowColours(screenRow, textColour, backgroundColour); - } else if (isLine(text)) { - display->updateRowLine(screenRow, isLine(text)); - } else { - display->updateRowText(screenRow, text); - display->updateRowUnderline(screenRow, isUnderline(text)); - } + display->updateRow(screenRow, text); } } @@ -65,86 +55,3 @@ void displayAllRows() { } } } - -bool embeddedColours(const char *message) { - // Check for format #0x0000#0x0000# - if (message[0] != '#' || message[7] != '#' || message[strlen(message) - 1] != '#') { - return false; - } - // Find the positions of the three '#' characters - char *start = strchr(message, '#'); - if (start == NULL) { - return false; - } - char *middle = strchr(start + 1, '#'); - if (middle == NULL) { - return false; - } - char *end = strchr(middle + 1, '#'); - if (end == NULL) { - return false; - } - // Check if the hexadecimal values are of the correct length (6 characters) - if (end - middle - 1 != 6 || middle - start - 1 != 6) { - return false; - } - // Check if the characters between the '#' are valid hexadecimal digits - if (message[1] != '0' || message[2] != 'x' || middle[1] != '0' || middle[2] != 'x') { - return false; - } - for (const char *p = message + 3; p < middle; p++) { - if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { - return false; - } - } - for (const char *p = middle + 3; p < end; p++) { - if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { - return false; - } - } - return true; -} - -void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour) { - // Find first # - char *start = strchr(message, '#'); - // Convert text colour - char *endPointer; - *textColour = (uint16_t)strtol(start + 1, &endPointer, 16); - // Find next # - start = strchr(start + 1, '#'); - // Convert background colour - *backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); -} - -bool isUnderline(const char *message) { - // Check for leading and trailing "_" - if (message[0] != '_' || message[strlen(message) - 1] != '_') { - return false; - } - return true; -} - -bool isLine(const char *message) { - // Check for exactly "--" - if (strlen(message) != 2 || message[0] != '-' || message[strlen(message) - 1] != '-') { - return false; - } - return true; -} - -bool alwaysTicker(const char *message) { - // Check for leading "~~" - if (message[0] != '~' || message[1] != '~') { - return false; - } - return true; -} - -bool neverTicker(const char *message) { - // Check for leading "!~" - if (message[0] != '!' || message[1] != '~') { - return false; - } - return true; -} diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 0c5e086..2da7d9d 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -20,35 +20,4 @@ void updateScreen(); /// @brief Display all rows on all screens - handy for debug void displayAllRows(); -/// @brief Check if the provided message contains embedded colours -/// @param message Message to check for format #0x0000#0x0000# -/// @return frue|false -bool embeddedColours(const char *message); - -/// @brief Extract text/foreground and background colours -/// @param message Message to extract colours from (see embeddedColours) -/// @param textColour Integer for the text/foreground colour -/// @param backgroundColour Integer for the background colour -void extractColours(char *message, uint16_t *textColour, uint16_t *backgroundColour); - -/// @brief Check if the provided message indicates it should be underlined -/// @param message Message to check for leading and trailing "_" -/// @return true|false -bool isUnderline(const char *message); - -/// @brief Check if the provided message indicates it should be a horizontal line -/// @param message Message to check for "--" -/// @return true|false -bool isLine(const char *message); - -/// @brief Check if this text should always ticker -/// @param message Message to check for leading "~~" -/// @return true|false -bool alwaysTicker(const char *message); - -/// @brief Check if this text should never ticker -/// @param message Message to check for leading "!~" -/// @return true|false -bool neverTicker(const char *message); - #endif diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 5a56ff9..3429100 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -48,40 +48,13 @@ EXDisplayRow *EXDisplay::getRowByNumber(uint8_t rowNumber) { return nullptr; } -void EXDisplay::updateRowText(uint8_t rowNumber, char *rowText) { +void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { auto *row = getRowByNumber(rowNumber); if (!row) { - row = _addRow(rowNumber); - row->setDisplayRow(rowNumber, _exScreen->maxRows); - } - row->setRowText(rowText); -} - -void EXDisplay::updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour) { - auto *row = getRowByNumber(rowNumber); - if (!row) { - row = _addRow(rowNumber); - row->setDisplayRow(rowNumber, _exScreen->maxRows); - } - row->setColours(textColour, backgroundColour); -} - -void EXDisplay::updateRowLine(uint8_t rowNumber, bool line) { - auto *row = getRowByNumber(rowNumber); - if (!row) { - row = _addRow(rowNumber); - row->setDisplayRow(rowNumber, _exScreen->maxRows); - } - row->setLine(line); -} - -void EXDisplay::updateRowUnderline(uint8_t rowNumber, bool underline) { - auto *row = getRowByNumber(rowNumber); - if (!row) { - row = _addRow(rowNumber); - row->setDisplayRow(rowNumber, _exScreen->maxRows); + row = _addRow(rowNumber, rowText); + } else { + row->setRowText(rowText); } - row->setUnderline(underline); } void EXDisplay::scrollUp() { @@ -236,7 +209,7 @@ void EXDisplay::processDisplay() { _needsRedraw = false; } -EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber) { +EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber, char *rowText) { // create a new row and chain it in EXDisplayRow *row = new EXDisplayRow(rowNumber); _numberOfRows++; @@ -260,8 +233,8 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber) { if (rowNumber > _maxRowNumber) { _maxRowNumber = rowNumber; } - char blank[1] = {'\0'}; row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); - row->setRowText(blank); + row->setRowText(rowText); + row->setDisplayRow(rowNumber, _exScreen->maxRows); return row; } diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 2f853cc..23803fc 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -43,23 +43,7 @@ class EXDisplay { /// @brief Update text and ticker for the specified row number, will add if it doesn't exist /// @param rowNumber Row number to display text on, 0 - 255 /// @param rowText Char array of text for the row - void updateRowText(uint8_t rowNumber, char *rowText); - - /// @brief Update text/foreground and background colours for the specified row - /// @param rowNumber Row number for colours, 0 - 255 - /// @param textColour Any valid hex colour code - /// @param backgroundColour Any valid hex colour code - void updateRowColours(uint8_t rowNumber, uint16_t textColour, uint16_t backgroundColour); - - /// @brief Update the line attribute for the specified row - /// @param rowNumber Row number to set to a line, 0 - 255 - /// @param line true|false - void updateRowLine(uint8_t rowNumber, bool line); - - /// @brief Update underline attribute for the specified row - /// @param rowNumber Row number to set underline for, 0 - 255 - /// @param underline true|false - void updateRowUnderline(uint8_t rowNumber, bool underline); + void updateRow(uint8_t rowNumber, char *rowText); /// @brief Scroll up one row vertically void scrollUp(); @@ -139,8 +123,9 @@ class EXDisplay { /// @brief Private method to add a row /// @param rowNumber 0 - 255 + /// @param rowText Pointer to the char array containing the text for this row /// @return Pointer to the created EXDisplayRow object - EXDisplayRow *_addRow(uint8_t rowNumber); + EXDisplayRow *_addRow(uint8_t rowNumber, char *rowText); }; #endif diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index e007bdf..eff4b2d 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -20,6 +20,10 @@ uint8_t EXDisplayRow::getMaxRowLength() { return _maxMalloc; } void EXDisplayRow::setRowText(char *rowText) { // Note size limit is 254 chars but that is beyond // the capability of the caller anyway. + + // First thing is to format this row + _rowFormatter(this, rowText); + // Ignore change if text the same... if (_rowText && strcmp(_rowText, rowText) == 0) return; @@ -34,9 +38,6 @@ void EXDisplayRow::setRowText(char *rowText) { _maxMalloc = bytesNeeded; } strcpy(_rowText, rowText); - if (isLine()) { - bitClear(_rowAttributes, 0); - } _changed = true; } @@ -74,41 +75,145 @@ uint16_t EXDisplayRow::getTextColour() { return _textColour; } uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } -void EXDisplayRow::setLine(bool line) { - if (line) { - bitSet(_rowAttributes, 0); - } else { - bitClear(_rowAttributes, 0); - } - _changed = true; -} - bool EXDisplayRow::isLine() { _changed = false; return bitRead(_rowAttributes, 0); } -void EXDisplayRow::setUnderline(bool underline) { - if (underline) { - bitSet(_rowAttributes, 1); - } else { - bitClear(_rowAttributes, 1); - } - _changed = true; -} - bool EXDisplayRow::isUnderlined() { return bitRead(_rowAttributes, 1); } uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } -void EXDisplayRow::_rowFormatter(EXDisplayRow *row) { +void EXDisplayRow::_rowFormatter(EXDisplayRow *row, char *rowText) { /* Need to check for all possible formatting codes here When formatting codes discovered: - Apply attributes to _rowAttributes as required + - Embedded colours: "#0xdddd#0xdddd#" (no text taken from this) + - Row underlined: "_This text is underlined_" + - Row is a horizontal line: "--" + - Row always tickers: "~~Text to ticker" + - Row never tickers: "!~Never ticker text" + - Delete row: "" - Copy _rowText to a temp char - Use strncpy to copy only the text from temp back to _rowText (drop format codes) - Delete temp char - - Need to add a formatter for DELETING a row, which must delete from linked list + _rowText + - Return true if something has changed */ + bool changed = true; + if (_isEmbeddedColours(rowText)) { + row->_extractColours(rowText); + } else if (_isLine(rowText)) { + row->_setLine(); + } else if (_isUnderline(rowText)) { + row->_setUnderline(); + } else if (_alwaysTicker(rowText)) { + // always ticker here + } else if (_neverTicker(rowText)) { + // never ticker here + } else { + changed = false; + } + row->_changed = changed; +} + +bool EXDisplayRow::_isEmbeddedColours(const char *text) { + // Check for format #0x0000#0x0000# + if (text[0] != '#' || text[7] != '#' || text[strlen(text) - 1] != '#') { + return false; + } + // Find the positions of the three '#' characters + char *start = strchr(text, '#'); + if (start == NULL) { + return false; + } + char *middle = strchr(start + 1, '#'); + if (middle == NULL) { + return false; + } + char *end = strchr(middle + 1, '#'); + if (end == NULL) { + return false; + } + // Check if the hexadecimal values are of the correct length (6 characters) + if (end - middle - 1 != 6 || middle - start - 1 != 6) { + return false; + } + // Check if the characters between the '#' are valid hexadecimal digits + if (text[1] != '0' || text[2] != 'x' || middle[1] != '0' || middle[2] != 'x') { + return false; + } + for (const char *p = text + 3; p < middle; p++) { + if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { + return false; + } + } + for (const char *p = middle + 3; p < end; p++) { + if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { + return false; + } + } + return true; +} + +void EXDisplayRow::_extractColours(const char *text) { + // Find first # + char *start = strchr(text, '#'); + // Convert text colour + char *endPointer; + _textColour = (uint16_t)strtol(start + 1, &endPointer, 16); + // Find next # + start = strchr(start + 1, '#'); + // Convert background colour + _backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); + char blank[1] = {'\0'}; + char *temp = _rowText; + _rowText = blank; + delete(temp); +} + +void EXDisplayRow::_setLine() { + bitSet(_rowAttributes, 0); + char blank[1] = {'\0'}; + char *temp = _rowText; + _rowText = blank; + delete(temp); + _changed = true; +} + +bool EXDisplayRow::_isLine(const char *text) { + // Check for exactly "--" + if (strlen(text) != 2 || text[0] != '-' || text[strlen(text) - 1] != '-') { + return false; + } + return true; +} + +void EXDisplayRow::_setUnderline() { + bitSet(_rowAttributes, 1); + _changed = true; +} + +bool EXDisplayRow::_isUnderline(const char *text) { + // Check for leading and trailing "_" + if (text[0] != '_' || text[strlen(text) - 1] != '_') { + return false; + } + return true; +} + +bool EXDisplayRow::_alwaysTicker(const char *text) { + // Check for leading "~~" + if (text[0] != '~' || text[1] != '~') { + return false; + } + return true; +} + +bool EXDisplayRow::_neverTicker(const char *text) { + // Check for leading "!~" + if (text[0] != '!' || text[1] != '~') { + return false; + } + return true; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index f53dc70..8659532 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -77,18 +77,10 @@ class EXDisplayRow { /// @return Colour code uint16_t getBackgroundColour(); - /// @brief Set the line attribute for this row - /// @param line true|false - void setLine(bool line); - /// @brief Check if this row is a horizontal line /// @return true|false bool isLine(); - /// @brief Set the underline attribute for this row - /// @param underline true|false - void setUnderline(bool underline); - /// @brief Check if this row should be underlined /// @return true|false bool isUnderlined(); @@ -111,6 +103,43 @@ class EXDisplayRow { /// @brief Private method to format the row attributes for the specified row /// @param row Pointer to an EXDisplayRow object - static void _rowFormatter(EXDisplayRow *row); + static void _rowFormatter(EXDisplayRow *row, char *rowText); + + /// @brief Check for "#0xdddd#0xdddd#" + /// @param text Char array to check + /// @return true|false + static bool _isEmbeddedColours(const char *text); + + /// @brief Extract colour codes from text + /// @param text Char array containing codes (see _isEmbeddedColours) + void _extractColours(const char *text); + + /// @brief Set the line attribute for this row + /// @param line true|false + void _setLine(); + + /// @brief Check for "--" + /// @param text Char array to check + /// @return true|false + static bool _isLine(const char *text); + + /// @brief Set the underline attribute for this row + /// @param underline true|false + void _setUnderline(); + + /// @brief Check for "_Underlined text_" + /// @param text Char array to check + /// @return true|false + static bool _isUnderline(const char *text); + + /// @brief Check for "~~Always ticker this text" + /// @param text Char array to check + /// @return true|false + static bool _alwaysTicker(const char *text); + + /// @brief Check for "!~Never ticker this text" + /// @param text Char array to check + /// @return true|false + static bool _neverTicker(const char *text); }; #endif \ No newline at end of file diff --git a/version.h b/version.h index 51d02d6..4937f0d 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,10 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.6" +#define VERSION "0.0.7" +// 0.0.7 includes: +// - Move row formatting to the EXDisplayRow class so only one call is needed to set a row up // 0.0.6 includes: // - Add ability to set individual row colours via the parser // - Add ability to draw a horizontal line on a row rather than text From fa85b2c90f123e6a9bfd6d05fa82d82a528fe629 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Thu, 16 May 2024 05:01:22 +1000 Subject: [PATCH 053/146] FIxing crashes --- EXDisplayRow.cpp | 19 +++++++++++-------- TFT_eSPIScreen.cpp | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index eff4b2d..96cf218 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -166,18 +166,21 @@ void EXDisplayRow::_extractColours(const char *text) { start = strchr(start + 1, '#'); // Convert background colour _backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); - char blank[1] = {'\0'}; - char *temp = _rowText; - _rowText = blank; - delete(temp); + // char blank[1] = {'\0'}; + // if (_rowText != nullptr) { + // delete _rowText; + // } + // _rowText = blank; } void EXDisplayRow::_setLine() { bitSet(_rowAttributes, 0); - char blank[1] = {'\0'}; - char *temp = _rowText; - _rowText = blank; - delete(temp); + // char blank[1] = {'\0'}; + // char *temp = _rowText; + // _rowText = blank; + // if (temp) { + // delete temp; + // } _changed = true; } diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index f137c4f..1ee3413 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -1,7 +1,7 @@ #include "Defines.h" #ifdef NEEDS_TFT -#include +#include "TFT_eSPIScreen.h" TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} From c41a4f7ab612a6886a7d1d87167faa22196c33b3 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 16 May 2024 13:55:38 +1000 Subject: [PATCH 054/146] Working --- DisplayFunctions.cpp | 6 +- EXDisplayClass.cpp | 35 +++++----- EXDisplayClass.h | 4 ++ EXDisplayRow.cpp | 157 +++++++++++++++++++------------------------ EXDisplayRow.h | 47 ++++--------- README.md | 33 +++++++-- TFT_eSPIScreen.cpp | 4 +- version.h | 1 + 8 files changed, 140 insertions(+), 147 deletions(-) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index 09ceb6c..ec72f7d 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -39,7 +39,7 @@ void displayAllRows() { for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { CONSOLE.print(F("\n\nRows for display ")); CONSOLE.println(display->getDisplayNumber()); - CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender|rowAttributes")); + CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender")); for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { CONSOLE.print(row->getRowNumber()); CONSOLE.print(F("|")); @@ -49,9 +49,7 @@ void displayAllRows() { CONSOLE.print(F("|")); CONSOLE.print(row->isChanged()); CONSOLE.print(F("|")); - CONSOLE.print(row->needsRender()); - CONSOLE.print(F("|")); - CONSOLE.println(row->getAttributes(), BIN); + CONSOLE.println(row->needsRender()); } } } diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 3429100..ff91386 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -50,7 +50,11 @@ EXDisplayRow *EXDisplay::getRowByNumber(uint8_t rowNumber) { void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { auto *row = getRowByNumber(rowNumber); - if (!row) { + if (row && strlen(rowText) == 0) { + _deleteRow(row); + } else if (!row && strlen(rowText) == 0) { + return; + } else if (!row) { row = _addRow(rowNumber, rowText); } else { row->setRowText(rowText); @@ -121,21 +125,6 @@ bool EXDisplay::needsRedraw() { return _needsRedraw; } void EXDisplay::resetRedraw() { _needsRedraw = false; } -/*** probably not needed - void EXDisplay::deleteRowNumber(uint8_t rowNumber) { - EXDisplayRow *currentRow = _firstRow; - while (currentRow != nullptr && currentRow->getNext() != nullptr) { - if (currentRow->getNext()->getRowNumber() == rowNumber) { - EXDisplayRow *temp = currentRow->getNext(); - currentRow->setNext(temp->getNext()); - delete temp; // CAUTION DESTRUCTOR MUST DELETE TEXT TOO - return; - } - currentRow = currentRow->getNext(); - } -} -***/ - bool EXDisplay::displayNumberExists(uint8_t displayNumber) { return getDisplayByNumber(displayNumber) != nullptr; } EXDisplay *EXDisplay::getDisplayByNumber(uint8_t displayNumber) { @@ -238,3 +227,17 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber, char *rowText) { row->setDisplayRow(rowNumber, _exScreen->maxRows); return row; } + +void EXDisplay::_deleteRow(EXDisplayRow *row) { + CONSOLE.print(F("Need to implement deleting row ")); + CONSOLE.println(row->getRowNumber()); + // EXDisplayRow *currentRow = _firstRow; + // while (currentRow != nullptr && currentRow->getNext() != nullptr) { + // if (currentRow->getNext()->getRowNumber() == rowNumber) { + // EXDisplayRow *temp = currentRow->getNext(); + // currentRow->setNext(temp->getNext()); + // delete temp; // CAUTION DESTRUCTOR MUST DELETE TEXT TOO + // return; + // } + // currentRow = currentRow->getNext(); +} diff --git a/EXDisplayClass.h b/EXDisplayClass.h index 23803fc..b1adc56 100644 --- a/EXDisplayClass.h +++ b/EXDisplayClass.h @@ -126,6 +126,10 @@ class EXDisplay { /// @param rowText Pointer to the char array containing the text for this row /// @return Pointer to the created EXDisplayRow object EXDisplayRow *_addRow(uint8_t rowNumber, char *rowText); + + /// @brief Delete the specified row number + /// @param rowNumber Row number to delete, 0 - 255 + void _deleteRow(EXDisplayRow *row); }; #endif diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 96cf218..2852916 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -10,7 +10,7 @@ EXDisplayRow::EXDisplayRow(uint8_t rowNumber) { _rowText = nullptr; _changed = true; _needsRender = false; - _rowAttributes = 0; + _rowAttributes = {false, false, false, false}; } uint8_t EXDisplayRow::getRowNumber() { return _rowNumber; } @@ -21,9 +21,6 @@ void EXDisplayRow::setRowText(char *rowText) { // Note size limit is 254 chars but that is beyond // the capability of the caller anyway. - // First thing is to format this row - _rowFormatter(this, rowText); - // Ignore change if text the same... if (_rowText && strcmp(_rowText, rowText) == 0) return; @@ -38,6 +35,10 @@ void EXDisplayRow::setRowText(char *rowText) { _maxMalloc = bytesNeeded; } strcpy(_rowText, rowText); + + // Now we have our new text, check for formatters + _rowFormatter(); + _changed = true; } @@ -77,88 +78,68 @@ uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } bool EXDisplayRow::isLine() { _changed = false; - return bitRead(_rowAttributes, 0); + return _rowAttributes.line; } -bool EXDisplayRow::isUnderlined() { return bitRead(_rowAttributes, 1); } - -uint8_t EXDisplayRow::getAttributes() { return _rowAttributes; } +bool EXDisplayRow::isUnderlined() { + return _rowAttributes.underline; } -void EXDisplayRow::_rowFormatter(EXDisplayRow *row, char *rowText) { +void EXDisplayRow::_rowFormatter() { /* Need to check for all possible formatting codes here When formatting codes discovered: - Apply attributes to _rowAttributes as required - - Embedded colours: "#0xdddd#0xdddd#" (no text taken from this) + - Embedded colours: "#0xdddd#0xdddd#Coloured text" - Row underlined: "_This text is underlined_" - Row is a horizontal line: "--" - Row always tickers: "~~Text to ticker" - Row never tickers: "!~Never ticker text" - - Delete row: "" - - Copy _rowText to a temp char - - Use strncpy to copy only the text from temp back to _rowText (drop format codes) - - Delete temp char - - Return true if something has changed */ - bool changed = true; - if (_isEmbeddedColours(rowText)) { - row->_extractColours(rowText); - } else if (_isLine(rowText)) { - row->_setLine(); - } else if (_isUnderline(rowText)) { - row->_setUnderline(); - } else if (_alwaysTicker(rowText)) { - // always ticker here - } else if (_neverTicker(rowText)) { - // never ticker here - } else { - changed = false; - } - row->_changed = changed; + _setColours(); + _setLine(); + _setUnderline(); + _alwaysTicker(); + _neverTicker(); } -bool EXDisplayRow::_isEmbeddedColours(const char *text) { - // Check for format #0x0000#0x0000# - if (text[0] != '#' || text[7] != '#' || text[strlen(text) - 1] != '#') { - return false; +void EXDisplayRow::_setColours() { + // Check for format #0xdddd#0xdddd# + if (_rowText[0] != '#' || _rowText[7] != '#' || _rowText[14] != '#') { + return; } // Find the positions of the three '#' characters - char *start = strchr(text, '#'); + char *start = strchr(_rowText, '#'); if (start == NULL) { - return false; + return; } char *middle = strchr(start + 1, '#'); if (middle == NULL) { - return false; + return; } char *end = strchr(middle + 1, '#'); if (end == NULL) { - return false; + return; } - // Check if the hexadecimal values are of the correct length (6 characters) + // Check if the hexadecimal values are of the correct length (4 characters) if (end - middle - 1 != 6 || middle - start - 1 != 6) { - return false; + return; } // Check if the characters between the '#' are valid hexadecimal digits - if (text[1] != '0' || text[2] != 'x' || middle[1] != '0' || middle[2] != 'x') { - return false; + if (_rowText[1] != '0' || _rowText[2] != 'x' || middle[1] != '0' || middle[2] != 'x') { + return; } - for (const char *p = text + 3; p < middle; p++) { + for (const char *p = _rowText + 3; p < middle; p++) { if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { - return false; + return; } } for (const char *p = middle + 3; p < end; p++) { if (!((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F'))) { - return false; + return; } } - return true; -} - -void EXDisplayRow::_extractColours(const char *text) { // Find first # - char *start = strchr(text, '#'); + start = strchr(_rowText, '#'); // Convert text colour char *endPointer; _textColour = (uint16_t)strtol(start + 1, &endPointer, 16); @@ -166,57 +147,59 @@ void EXDisplayRow::_extractColours(const char *text) { start = strchr(start + 1, '#'); // Convert background colour _backgroundColour = (uint16_t)strtol(start + 1, &endPointer, 16); - // char blank[1] = {'\0'}; - // if (_rowText != nullptr) { - // delete _rowText; - // } - // _rowText = blank; + _removeFormatters(15); } void EXDisplayRow::_setLine() { - bitSet(_rowAttributes, 0); - // char blank[1] = {'\0'}; - // char *temp = _rowText; - // _rowText = blank; - // if (temp) { - // delete temp; - // } - _changed = true; -} - -bool EXDisplayRow::_isLine(const char *text) { - // Check for exactly "--" - if (strlen(text) != 2 || text[0] != '-' || text[strlen(text) - 1] != '-') { - return false; + if (strlen(_rowText) != 2 || _rowText[0] != '-' || _rowText[strlen(_rowText) - 1] != '-') { + _rowAttributes.line = false; + return; } - return true; + _rowAttributes.line = true; + _removeFormatters(2); } void EXDisplayRow::_setUnderline() { - bitSet(_rowAttributes, 1); - _changed = true; -} - -bool EXDisplayRow::_isUnderline(const char *text) { - // Check for leading and trailing "_" - if (text[0] != '_' || text[strlen(text) - 1] != '_') { - return false; + if (_rowText[0] != '_' || _rowText[1] != '_') { + if (_rowAttributes.underline) { + _rowAttributes.underline = false; + } + return; } - return true; + _rowAttributes.underline = true; + _removeFormatters(2); } -bool EXDisplayRow::_alwaysTicker(const char *text) { +void EXDisplayRow::_alwaysTicker() { // Check for leading "~~" - if (text[0] != '~' || text[1] != '~') { - return false; + if (_rowText[0] != '~' || _rowText[1] != '~') { + _rowAttributes.alwaysTicker = false; + return; } - return true; + _rowAttributes.alwaysTicker = true; + return; } -bool EXDisplayRow::_neverTicker(const char *text) { +void EXDisplayRow::_neverTicker() { // Check for leading "!~" - if (text[0] != '!' || text[1] != '~') { - return false; + if (_rowText[0] != '!' || _rowText[1] != '~') { + _rowAttributes.neverTicker = false; + return; } - return true; + _rowAttributes.neverTicker = true; + return; +} + +void EXDisplayRow::_removeFormatters(uint8_t size) { + // New length for "text" needs to be length - formatters (size) + null pointer (1) + uint8_t textLength = strlen(_rowText) - size + 1; + // Set our temp char array to what we already have defined as our max size + char *temp = (char *)malloc(_maxMalloc); + // Copy the text minus formatters to temp and null terminate + strncpy(temp, _rowText + size, textLength); + temp[textLength] = '\0'; + // Free the no longer required _rowText memory + free(_rowText); + // Temp is now _rowText + _rowText = temp; } diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 8659532..2f7c7f1 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -9,9 +9,7 @@ * */ class EXDisplayRow { - -public: - // Where does this really belong, and how can we use it to query and set attributes externally? + /// @brief Structure for the _rowAttributes attribute for row formatting struct RowAttributes { bool line : 1; bool underline : 1; @@ -19,6 +17,7 @@ class EXDisplayRow { bool neverTicker : 1; }; +public: /// @brief Constructor for the EXDisplayRow object /// @param rowNumber Row number on the display, 0 - 255 EXDisplayRow(uint8_t rowNumber); @@ -85,10 +84,6 @@ class EXDisplayRow { /// @return true|false bool isUnderlined(); - /// @brief Get all current attributes for the row - /// @return 0 - 255 - uint8_t getAttributes(); - private: uint8_t _rowNumber; // This is the row number received from the parser uint8_t _maxMalloc; // This is the calculated maximum length of the text received from the parser @@ -97,49 +92,35 @@ class EXDisplayRow { uint8_t _displayRow; // This is the calculated physical row on a display that this line belongs on bool _needsRender; // Flag that is set when row belongs on a physical display, false when off-screen EXDisplayRow *_next; - uint16_t _textColour; // Text/foreground colour for this row - uint16_t _backgroundColour; // Background colour for this row - byte _rowAttributes; // One bit per attribute to allow 8 total + uint16_t _textColour; // Text/foreground colour for this row + uint16_t _backgroundColour; // Background colour for this row + RowAttributes _rowAttributes; // One bit per attribute to allow 8 total /// @brief Private method to format the row attributes for the specified row /// @param row Pointer to an EXDisplayRow object - static void _rowFormatter(EXDisplayRow *row, char *rowText); - - /// @brief Check for "#0xdddd#0xdddd#" - /// @param text Char array to check - /// @return true|false - static bool _isEmbeddedColours(const char *text); + void _rowFormatter(); /// @brief Extract colour codes from text - /// @param text Char array containing codes (see _isEmbeddedColours) - void _extractColours(const char *text); + void _setColours(); /// @brief Set the line attribute for this row - /// @param line true|false void _setLine(); - - /// @brief Check for "--" - /// @param text Char array to check - /// @return true|false - static bool _isLine(const char *text); /// @brief Set the underline attribute for this row /// @param underline true|false void _setUnderline(); - /// @brief Check for "_Underlined text_" - /// @param text Char array to check - /// @return true|false - static bool _isUnderline(const char *text); - /// @brief Check for "~~Always ticker this text" - /// @param text Char array to check /// @return true|false - static bool _alwaysTicker(const char *text); + void _alwaysTicker(); /// @brief Check for "!~Never ticker this text" - /// @param text Char array to check /// @return true|false - static bool _neverTicker(const char *text); + void _neverTicker(); + + /// @brief Remove leading formatting characters from the provided char array + /// @param text Pointer to the char array + /// @param size Number of leading formatting characters to remove + void _removeFormatters(uint8_t size); }; #endif \ No newline at end of file diff --git a/README.md b/README.md index e2bbb7b..21d24d7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ The key parameters to set are... As features are added they will be outlined here, with examples on how to use them. -### Basic EXRAIL commands +## Basic EXRAIL commands The basic EXRAIL command format is `SCREEN(screen, row, "Message")`. @@ -28,26 +28,39 @@ This example displays the text "This is row 0" on the first row of the first scr `SCREEN(0, 0, "This is row 0")` +## Formatting rows + +It is possible to perform limited formatting of rows using the below methods. + +Formatting is done once per row, and the formatting codes must be at the beginning of the text. The formatting codes are removed from the text and will not be displayed. + ### Setting Colours It is possible to set the text/foreground and background colours to any valid hex colour code when setting the colours using the "Message" field of the command. -This is done by using the format `<@ screen row "#0x#0x#">`. Note that the hex values must be in the format "0xdddd", where "d" represents a four digit colour code. +This is done by using the format `<@ screen row "#0x#0x#Message">`. Note that the hex values must be in the format "0xdddd", where "d" represents a four digit colour code. + +If you wish to set colours for a row as well as setting another formatting option, then set the row colour first, followed by a second row that sets the text and required formatting. This example displays the text "Yellow" on the first row of the first screen with yellow coloured text on a black background: +`SCREEN(0, 0, "#0xFFE0#0x0000#Yellow")` + +If you wish to have a coloured line that is also underlined, do it like this: + ``` -SCREEN(0, 0, "#0xFFE0#0x0000") -SCREEN(0, 0, "Yellow") -``` +SCREEN(0, 0, "#0xFFE0#0x0000#") +SCREEN(0, 0, "__This is now yellow and underlined") ### Horizontal Line +Note that setting a horizontal line will remove any text previously set for that particular row. To replace a line, simply update it without the line formatting with text, or delete it. + `SCREEN(0, 0, "--")` ### Underlined Text -`SCREEN(0, 0, "_This is underlined_")` +`SCREEN(0, 0, "__This is underlined")` ### Always Ticker This Row @@ -61,6 +74,14 @@ SCREEN(0, 0, "Yellow") `SCREEN(0, 0, "!~This will never ticker")` +### Delete Row + +*Not implemented yet* + +Simply set the row message to zero length to delete it, noting that this doesn't just blank the text out, but deletes the row in its entirety, including all formatting attributes. + +`SCREEN(0, 1, "")` + ## Serial Connections - MEGA: GND-GND and RX pin 19 on mega to serial tx pin on EX-CS diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 1ee3413..d3dea08 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -42,10 +42,12 @@ void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t width = fontWidth * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); - _tft.drawString(message, column, textRow); if (underlined) { _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); + } else { + _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, backgroundColour); } + _tft.drawString(message, column, textRow); } void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, diff --git a/version.h b/version.h index 4937f0d..adb65ba 100644 --- a/version.h +++ b/version.h @@ -6,6 +6,7 @@ // 0.0.7 includes: // - Move row formatting to the EXDisplayRow class so only one call is needed to set a row up +// - Change colour attributes to match other formatting options so they can be sent with text // 0.0.6 includes: // - Add ability to set individual row colours via the parser // - Add ability to draw a horizontal line on a row rather than text From 349fe512245612a0886c54325ab0590ae547e6d9 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 16 May 2024 14:48:32 +1000 Subject: [PATCH 055/146] Delete working --- EXDisplayClass.cpp | 45 ++++++++++++++++++++++++++++++++++----------- EXDisplayRow.cpp | 5 +++-- EXDisplayRow.h | 3 +++ README.md | 2 -- version.h | 1 + 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index ff91386..5ae36f3 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -229,15 +229,38 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber, char *rowText) { } void EXDisplay::_deleteRow(EXDisplayRow *row) { - CONSOLE.print(F("Need to implement deleting row ")); - CONSOLE.println(row->getRowNumber()); - // EXDisplayRow *currentRow = _firstRow; - // while (currentRow != nullptr && currentRow->getNext() != nullptr) { - // if (currentRow->getNext()->getRowNumber() == rowNumber) { - // EXDisplayRow *temp = currentRow->getNext(); - // currentRow->setNext(temp->getNext()); - // delete temp; // CAUTION DESTRUCTOR MUST DELETE TEXT TOO - // return; - // } - // currentRow = currentRow->getNext(); + if (!row) { + return; // Return if the row is nullptr + } + + // Find the previous node in the linked list + EXDisplayRow *previous = nullptr; + EXDisplayRow *current = _firstRow; + while (current != row) { + previous = current; + current = current->getNext(); + } + + // Remove the node from the linked list + if (previous) { + previous->setNext(row->getNext()); + } else { + _firstRow = row->getNext(); + } + + // Decrement the number of rows + _numberOfRows--; + + // Update the maximum row number if necessary + if (row->getRowNumber() == _maxRowNumber) { + _maxRowNumber = 0; + for (EXDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { + if (temp->getRowNumber() > _maxRowNumber) { + _maxRowNumber = temp->getRowNumber(); + } + } + } + + // Delete the row object + delete row; } diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 2852916..1e33d0f 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -81,8 +81,9 @@ bool EXDisplayRow::isLine() { return _rowAttributes.line; } -bool EXDisplayRow::isUnderlined() { - return _rowAttributes.underline; } +bool EXDisplayRow::isUnderlined() { return _rowAttributes.underline; } + +EXDisplayRow::~EXDisplayRow() { free(_rowText); } void EXDisplayRow::_rowFormatter() { /* diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 2f7c7f1..415966a 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -84,6 +84,9 @@ class EXDisplayRow { /// @return true|false bool isUnderlined(); + /// @brief Destructor for the EXDisplayRow object + ~EXDisplayRow(); + private: uint8_t _rowNumber; // This is the row number received from the parser uint8_t _maxMalloc; // This is the calculated maximum length of the text received from the parser diff --git a/README.md b/README.md index 21d24d7..ae9a5d9 100644 --- a/README.md +++ b/README.md @@ -76,8 +76,6 @@ Note that setting a horizontal line will remove any text previously set for that ### Delete Row -*Not implemented yet* - Simply set the row message to zero length to delete it, noting that this doesn't just blank the text out, but deletes the row in its entirety, including all formatting attributes. `SCREEN(0, 1, "")` diff --git a/version.h b/version.h index adb65ba..91aa1d0 100644 --- a/version.h +++ b/version.h @@ -7,6 +7,7 @@ // 0.0.7 includes: // - Move row formatting to the EXDisplayRow class so only one call is needed to set a row up // - Change colour attributes to match other formatting options so they can be sent with text +// - Implement support for deleting a row when sending "" as the message // 0.0.6 includes: // - Add ability to set individual row colours via the parser // - Add ability to draw a horizontal line on a row rather than text From f44af7c4dc771b09dce706fd0f56d5fed8d6694a Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 16 May 2024 15:14:38 +1000 Subject: [PATCH 056/146] Reset scroll after row delete --- EXDisplayClass.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 5ae36f3..4fb3b99 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -261,6 +261,15 @@ void EXDisplay::_deleteRow(EXDisplayRow *row) { } } + // If we're now within the confines of the screen, need to reset display rows and redraw + if (_maxRowNumber <= _exScreen->maxRows) { + _scrollPosition = 0; + for (EXDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { + temp->setDisplayRow(temp->getRowNumber(), _exScreen->maxRows); + } + _needsRedraw = true; + } + // Delete the row object delete row; } From bfa0641727bc0887e5fdb54a58167f9eb215eb63 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Thu, 16 May 2024 19:09:21 +1000 Subject: [PATCH 057/146] Start considering logic --- EXDisplayRow.cpp | 4 ++-- EXDisplayRow.h | 7 ++++--- version.h | 4 +++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index 1e33d0f..f8613ee 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -49,8 +49,8 @@ char *EXDisplayRow::getRowText() { bool EXDisplayRow::isChanged() { return _changed; } -void EXDisplayRow::setDisplayRow(uint8_t displayRow, uint8_t maxScreenRows) { - _displayRow = displayRow; +void EXDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, uint8_t maxRowNumber) { + _displayRow = _rowNumber - scrollPosition; if (_displayRow >= maxScreenRows) { _needsRender = false; } else { diff --git a/EXDisplayRow.h b/EXDisplayRow.h index 415966a..0697cc9 100644 --- a/EXDisplayRow.h +++ b/EXDisplayRow.h @@ -42,10 +42,11 @@ class EXDisplayRow { /// @return True|False bool isChanged(); - /// @brief Set the physical screen row this row should be rendered/drawn on and provide the max rows for the screen - /// @param displayRow 0 - 255 + /// @brief Set the physical screen row this row should be rendered/drawn on + /// @param scrollPosition The current row that is at the top of the screen /// @param maxScreenRows Maximum number of rows the screen can display - sets _needsRender - void setDisplayRow(uint8_t displayRow, uint8_t maxScreenRows); + /// @param maxRowNumber The highest row number in the list of rows + void setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, uint8_t maxRowNumber); /// @brief calculated to determine which screen row is used /// @return 0 - 255 diff --git a/version.h b/version.h index 91aa1d0..c6eff07 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,10 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.7" +#define VERSION "0.0.8" +// 0.0.8 includes: +// - Fix a bug where adding new rows while the screen is scrolling puts them on the wrong row // 0.0.7 includes: // - Move row formatting to the EXDisplayRow class so only one call is needed to set a row up // - Change colour attributes to match other formatting options so they can be sent with text From 04cfcceba46db0778e0ffe99acf5449c2c8714ed Mon Sep 17 00:00:00 2001 From: peteGSX Date: Fri, 17 May 2024 05:23:19 +1000 Subject: [PATCH 058/146] Ready to test fix --- EXDisplayClass.cpp | 8 ++++---- EXDisplayRow.cpp | 14 +++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp index 4fb3b99..bcac05b 100644 --- a/EXDisplayClass.cpp +++ b/EXDisplayClass.cpp @@ -81,7 +81,7 @@ void EXDisplay::scrollUp() { } else { // Otherwise move down one row newRow++; } - row->setDisplayRow(newRow, _exScreen->maxRows); + row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); } _needsRedraw = true; // Need to redraw after each scroll } @@ -103,7 +103,7 @@ void EXDisplay::scrollDown() { } else { // Otherwise move up one row newRow--; } - row->setDisplayRow(newRow, _exScreen->maxRows); + row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); } _needsRedraw = true; // Need to redraw after each scroll } @@ -224,7 +224,7 @@ EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber, char *rowText) { } row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); row->setRowText(rowText); - row->setDisplayRow(rowNumber, _exScreen->maxRows); + row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); return row; } @@ -265,7 +265,7 @@ void EXDisplay::_deleteRow(EXDisplayRow *row) { if (_maxRowNumber <= _exScreen->maxRows) { _scrollPosition = 0; for (EXDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { - temp->setDisplayRow(temp->getRowNumber(), _exScreen->maxRows); + temp->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); } _needsRedraw = true; } diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index f8613ee..df8e88e 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -50,7 +50,19 @@ char *EXDisplayRow::getRowText() { bool EXDisplayRow::isChanged() { return _changed; } void EXDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, uint8_t maxRowNumber) { - _displayRow = _rowNumber - scrollPosition; + if (_rowNumber >= scrollPosition) { + _displayRow = _rowNumber - scrollPosition; + } else { + _displayRow = maxRowNumber - (scrollPosition - _rowNumber + 1); + } + CONSOLE.print(F("setDisplayRow _rowNumber|scrollPosition|maxRowNumber|_displayRow: ")); + CONSOLE.print(_rowNumber); + CONSOLE.print(F("|")); + CONSOLE.print(scrollPosition); + CONSOLE.print(F("|")); + CONSOLE.print(maxRowNumber); + CONSOLE.print(F("|")); + CONSOLE.println(_displayRow); if (_displayRow >= maxScreenRows) { _needsRender = false; } else { From 52122b824b8600d19be47cc6dba9cacd3b080f81 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 17 May 2024 07:01:33 +1000 Subject: [PATCH 059/146] Fixed calculation --- EXDisplayRow.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/EXDisplayRow.cpp b/EXDisplayRow.cpp index df8e88e..f1a2a90 100644 --- a/EXDisplayRow.cpp +++ b/EXDisplayRow.cpp @@ -53,16 +53,8 @@ void EXDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, if (_rowNumber >= scrollPosition) { _displayRow = _rowNumber - scrollPosition; } else { - _displayRow = maxRowNumber - (scrollPosition - _rowNumber + 1); + _displayRow = maxRowNumber - (scrollPosition - _rowNumber - 1); } - CONSOLE.print(F("setDisplayRow _rowNumber|scrollPosition|maxRowNumber|_displayRow: ")); - CONSOLE.print(_rowNumber); - CONSOLE.print(F("|")); - CONSOLE.print(scrollPosition); - CONSOLE.print(F("|")); - CONSOLE.print(maxRowNumber); - CONSOLE.print(F("|")); - CONSOLE.println(_displayRow); if (_displayRow >= maxScreenRows) { _needsRender = false; } else { From 8427fae3eac42ebfd8b9258c48d0de54d4be0827 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 17 May 2024 07:26:21 +1000 Subject: [PATCH 060/146] Update dodgy MCU force 9341 for testing --- MCUFriendScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 363f1bc..1df6779 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -17,7 +17,7 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b } if (screenId == 0x0) { CONSOLE.println(F("NO SCREEN DODGY FORCE TO 0x9486")); - screenId = 0x9486; + screenId = 0x9341; } _tft.begin(screenId); _tft.setRotation(rotation); From 4ef5d2c0ad7587c724b88eac07425cd75f412da9 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 19 May 2024 10:39:36 +1000 Subject: [PATCH 061/146] Start on OLED --- Defines.h | 10 +++++ EX-Display.ino | 12 ++++++ FontOptions.h | 2 +- MCUFriendScreen.cpp | 6 +-- OLEDScreen.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++ OLEDScreen.h | 56 +++++++++++++++++++++++++ config.example.h | 22 +++++++--- platformio.ini | 29 ++++--------- version.h | 4 +- 9 files changed, 209 insertions(+), 32 deletions(-) create mode 100644 OLEDScreen.cpp create mode 100644 OLEDScreen.h diff --git a/Defines.h b/Defines.h index 0aa26d6..afe7414 100644 --- a/Defines.h +++ b/Defines.h @@ -3,6 +3,8 @@ #define MCU 1 #define TFT 2 +#define OLED_SSD1306 3 +#define OLED_SH1106 4 #if __has_include("config.h") #include "config.h" @@ -34,6 +36,9 @@ #elif SCREEN_TYPE == TFT #define NEEDS_TFT #define SCREEN_0 new EXDisplay(0, new TFT_eSPIScreen(tft), 30); +#elif SCREEN_TYPE == OLED_SSD1306 || SCREEN_TYPE == OLED_SH1106 +#define NEEDS_OLED +#define SCREEN_0 new EXDisplay(0, new OLEDScreen(oled), 30); #else #error A screen type for the first screen has not been set, you must define either MCU or TFT #endif @@ -66,7 +71,12 @@ HardwareSerial Serial1(PB7, PA15); // Rx=PB7, Tx=PA15 -- CN7 pins 17 and 21 - F4 HardwareSerial Serial5(PD2, PC12); // Rx=PD2, Tx=PC12 -- UART5 - F446RE #define CS_LISTEN Serial5 #define RX_PIN PD2; +#endif +// If user has defined SERIAL_ONLY, override CS_LISTEN +#ifdef SERIAL_ONLY +#undef CS_LISTEN +#define CS_LISTEN Serial #endif #endif \ No newline at end of file diff --git a/EX-Display.ino b/EX-Display.ino index 4897637..cc2bd5a 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -16,6 +16,14 @@ MCUFriendScreen *screen = new MCUFriendScreen(tft); #include "TFT_eSPIScreen.h" TFT_eSPI tft = TFT_eSPI(); TFT_eSPIScreen *screen = new TFT_eSPIScreen(tft); +#elif SCREEN_TYPE == OLED_SSD1306 +#include "OLEDScreen.h" +Adafruit_SSD1306 oled = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); +OLEDScreen *screen = new OLEDScreen(oled); +#elif SCREEN_TYPE == OLED_SH1106 +#include "OLEDScreen.h" +Adafruit_SH1106G oled = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); +OLEDScreen *screen = new OLEDScreen(oled); #endif void setup() { @@ -25,6 +33,10 @@ void setup() { CONSOLE.print(F("EX-Display v")); CONSOLE.println(VERSION); +#ifdef NEEDS_OLED + Wire.begin(); +#endif + // Tell AtFinder our maximum supported text length, // and how to call back when found. AtFinder::setup(100, updateEXDisplayRow); diff --git a/FontOptions.h b/FontOptions.h index 4f3aaa1..00c2e83 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -1,7 +1,7 @@ #ifndef FONTOPTIONS_H #define FONTOPTIONS_H -#if SCREEN_TYPE == MCU +#if SCREEN_TYPE == MCU || SCREEN_TYPE == OLED_SSD1306 || SCREEN_TYPE == OLED_SH1106 #include #include #include diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 1df6779..6ea0a87 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -37,9 +37,9 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b CONSOLE.print(F("|")); CONSOLE.println(_tft.width()); CONSOLE.print(F("config.h parameters DISPLAY_HEIGHT|DISPLAY_WIDTH: ")); - CONSOLE.print(DISPLAY_HEIGHT); + CONSOLE.print(SCREEN_HEIGHT); CONSOLE.print(F("|")); - CONSOLE.println(DISPLAY_WIDTH); + CONSOLE.println(SCREEN_WIDTH); CONSOLE.print(F("maxRows|maxColumns|fontHeight|fontWidth: ")); CONSOLE.print(maxRows); CONSOLE.print(F("|")); @@ -73,7 +73,7 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint8_t maxLength, char *message, bool underlined) { uint16_t textRow = ((row + 1) * fontHeight); uint16_t width = fontWidth * maxLength; - _tft.fillRect(1, ((textRow - fontHeight) + 10), DISPLAY_WIDTH, (fontHeight), backgroundColour); + _tft.fillRect(1, ((textRow - fontHeight) + 10), _tft.width(), (fontHeight), backgroundColour); _tft.setTextColor(fontColour, backgroundColour); _tft.setCursor(1, textRow); _tft.print(message); diff --git a/OLEDScreen.cpp b/OLEDScreen.cpp new file mode 100644 index 0000000..11e9ecc --- /dev/null +++ b/OLEDScreen.cpp @@ -0,0 +1,100 @@ +#include "Defines.h" +#ifdef NEEDS_OLED +#include "OLEDScreen.h" + +#if SCREEN_TYPE == OLED_SSD1306 +OLEDScreen::OLEDScreen(Adafruit_SSD1306 &oled, uint8_t muxAddress, uint8_t subBus) + : EXScreen(), _oled(oled), _muxAddress(muxAddress), _subBus(subBus) {} +#elif SCREEN_TYPE == OLED_SH1106 +OLEDScreen::OLEDScreen(Adafruit_SH1106G &oled, uint8_t muxAddress, uint8_t subBus) + : EXScreen(), _oled(oled), _muxAddress(muxAddress), _subBus(subBus) {} +#endif + +void OLEDScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { + const GFXfont *gfxFont = TEXT_FONT; +#if SCREEN_TYPE == OLED_SSD1306 + _oled.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS); +#elif SCREEN_TYPE == OLED_SH1106 + _oled.begin(OLED_ADDRESS); +#endif + _oled.setRotation(rotation); + _oled.setFont(gfxFont); + _oled.setTextSize(textSize); + _oled.clearDisplay(); + _oled.display(); + fontHeight = gfxFont->yAdvance; + fontWidth = _getTextWidth(); + maxRows = _oled.height() / fontHeight; + maxColumns = _oled.width() / fontWidth; + CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); + CONSOLE.print(fontHeight); + CONSOLE.print(F("|")); + CONSOLE.print(fontWidth); + CONSOLE.print(F("|")); + CONSOLE.print(_oled.height()); + CONSOLE.print(F("|")); + CONSOLE.println(_oled.width()); +} + +void OLEDScreen::clearScreen(uint16_t backgroundColour) { + _oled.clearDisplay(); + _oled.display(); +} + +void OLEDScreen::clearRow(uint8_t row, uint16_t backgroundColour) { + int32_t x = 0; + int32_t y = (row * fontHeight) + row; + int32_t w = fontWidth * maxColumns; + int32_t h = fontHeight; + _oled.fillRect(x, y, w, h, backgroundColour); +} + +void OLEDScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, + uint8_t maxLength, char *message, bool underlined) { + uint16_t x = column; + uint16_t y = (row * fontHeight) + fontHeight; + _oled.setTextColor(fontColour, backgroundColour); + _oled.setCursor(x, y); + _oled.print(message); + if (underlined) { + _oled.drawLine(column, y + fontHeight, _oled.width(), y + fontHeight, fontColour); + } else { + _oled.drawLine(column, y + fontHeight, _oled.width(), y + fontHeight, backgroundColour); + } + _oled.display(); + CONSOLE.print(F("\nwriteRow textRow|message: ")); + CONSOLE.print(y); + CONSOLE.print(F("|")); + CONSOLE.println(message); +} + +void OLEDScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) { + // Horizontal start/end + int32_t x1 = column; + int32_t x2 = fontWidth * lineLength; + // Vertical start - half way up the font height + int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int32_t y2 = y1; + clearRow(row, backgroundColour); + _oled.drawLine(x1, y1, x2, y2, lineColour); + _oled.display(); +} + +uint8_t OLEDScreen::_getTextWidth() { + int16_t x1, y1; + uint16_t w, h; + _oled.getTextBounds("A", 0, 0, &x1, &y1, &w, &h); + return w; +} + +void OLEDScreen::_switchMUX(uint8_t muxAddress, uint8_t subBus) { + if (muxAddress == 0 || subBus == 255) { + return; + } + Wire.beginTransmission(muxAddress); + Wire.write(subBus); + Wire.endTransmission(); +} + +#endif diff --git a/OLEDScreen.h b/OLEDScreen.h new file mode 100644 index 0000000..3f04e6b --- /dev/null +++ b/OLEDScreen.h @@ -0,0 +1,56 @@ +#include "Defines.h" +#ifdef NEEDS_OLED + +#ifndef OLEDSCREEN_H +#define OLEDSCREEN_H + +#include "EXScreen.h" +#include +#include +#include +#include +#include + +/// @brief Class to drive monochrome OLEDs with EX-Display, noting all colours are ignored +class OLEDScreen : public EXScreen { +public: +#if SCREEN_TYPE == OLED_SSD1306 + OLEDScreen(Adafruit_SSD1306 &oled, uint8_t muxAddress = 0, uint8_t subBus = 255); +#elif SCREEN_TYPE == OLED_SH1106 + OLEDScreen(Adafruit_SH1106G &oled, uint8_t muxAddress = 0, uint8_t subBus = 255); +#endif + + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) override; + + virtual void clearScreen(uint16_t backgroundColour) override; + + virtual void clearRow(uint8_t row, uint16_t backgroundColour) override; + + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + char *message, bool underlined) override; + + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour) override; + +private: +#if SCREEN_TYPE == OLED_SSD1306 + Adafruit_SSD1306 &_oled; +#elif SCREEN_TYPE == OLED_SH1106 + Adafruit_SH1106G &_oled; +#endif + uint8_t _muxAddress; + uint8_t _subBus; + + /// @brief Private method to get the text width using current font settings + /// @return Text width + uint8_t _getTextWidth(); + + /// @brief Private method to select the correct MUX and sub bus if required for this screen + /// @param muxAddress Valid MUX address, 0x70 - 0x77 + /// @param subBus Valid MUX sub bus, 0 - 7 + static void _switchMUX(uint8_t muxAddress, uint8_t subBus); +}; + +#endif + +#endif diff --git a/config.example.h b/config.example.h index 988eaae..e55c543 100644 --- a/config.example.h +++ b/config.example.h @@ -7,14 +7,20 @@ // Define the pphysical screen types in use here - this needs to be ultra simplified at some point // Should we eventually support up to 3 displays? // #define SCREEN_TYPE MCU -#define SCREEN_TYPE TFT +// #define SCREEN_TYPE TFT +#define SCREEN_TYPE OLED_SSD1306 +// #define SCREEN_TYPE OLED_SH1106 + +#define OLED_WIDTH 128 +#define OLED_HEIGHT 64 +#define OLED_ADDRESS 0x3C // Define the number of logical displays here // This is not a good way to do this -#define NUMBER_OF_DISPLAYS 3 +#define NUMBER_OF_DISPLAYS 1 #define DISPLAY_1_ID 0 -#define DISPLAY_2_ID 3 -#define DISPLAY_3_ID 8 +// #define DISPLAY_2_ID 3 +// #define DISPLAY_3_ID 8 // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display @@ -33,8 +39,8 @@ // First entries about the display you are using // as we display across the wider part of the screen iwdth is the larger dimension -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 240 // Now we have to define how many screens you wish to display // The system output screen is 0. @@ -68,4 +74,8 @@ // Uncomment this line to display debug output #define DEBUG +// Uncomment this line when wanting to test with serial in put only, and no CS connection +// This overrides the input and only accepts input from the serial console +// #define SERIAL_ONLY + #endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 24aaa4e..d6857e4 100644 --- a/platformio.ini +++ b/platformio.ini @@ -12,10 +12,9 @@ default_envs = mega2560 uno - ESP32 + ESP32 Nucleo-F411RE Nucleo-F446RE - #blackpill_f411ce src_dir = . include_dir = . @@ -27,6 +26,8 @@ lib_deps = prenticedavid/MCUFRIEND_kbv@^3.1.0-Beta adafruit/Adafruit GFX Library@^1.11.9 bodmer/TFT_eSPI + adafruit/Adafruit SSD1306@^2.5.10 + adafruit/Adafruit SH110X@^2.1.10 [env:mega2560] platform = atmelavr @@ -55,11 +56,10 @@ platform = espressif32 board = esp32dev framework = arduino lib_deps = - ${env.lib_deps} + ${env.lib_deps} build_flags = ${env.build_flags} -DUSER_SETUP_LOADED=1 - #-DRPI_DISPLAY_TYPE=0 -DST7796_DRIVER=1 -DTFT_SDA_READ=1 -DTFT_BL=5 @@ -119,9 +119,9 @@ platform = ststm32 board = nucleo_f446re framework = arduino lib_deps = - ${env.lib_deps} + ${env.lib_deps} upload_protocol = stlink -build_flags = +build_flags = ${env.build_flags} -std=c++17 -Os -g2 monitor_speed = 115200 @@ -132,23 +132,10 @@ platform = ststm32 board = nucleo_f411re framework = arduino lib_deps = - ${env.lib_deps} + ${env.lib_deps} upload_protocol = stlink -build_flags = +build_flags = ${env.build_flags} -std=c++17 -Os -g2 monitor_speed = 115200 monitor_echo = yes - -#[env:blackpill_f411ce] -#platform = ststm32 -#board = blackpill_f411ce -#framework = arduino -#lib_deps = -# ${env.lib_deps} -# https://github.com/prenticedavid/MCUFRIEND_kbv -# https://github.com/adafruit/Adafruit-GFX-Library -# embeddedartistry/LibPrintf@^1.2.13 -# dcc-ex/DCCEXProtocol@^0.0.11 -#monitor_speed = 115200 -#monitor_echo = yes diff --git a/version.h b/version.h index c6eff07..3578595 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,10 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.8" +#define VERSION "0.0.9" +// 0.0.9 includes: +// - Add support for SSD1306 and SH1106 I2C connected OLEDs // 0.0.8 includes: // - Fix a bug where adding new rows while the screen is scrolling puts them on the wrong row // 0.0.7 includes: From d18248e7fdea6999854df0938ddfed084e1828c4 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 20 May 2024 07:47:43 +1000 Subject: [PATCH 062/146] Semi-working --- EX-Display.ino | 6 +++--- FontOptions.h | 3 +++ OLEDScreen.cpp | 23 ++++++++++++----------- README.md | 12 ++++++++++-- config.example.h | 35 ++++++++++++++--------------------- 5 files changed, 42 insertions(+), 37 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index cc2bd5a..6aeb259 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -43,13 +43,13 @@ void setup() { // Create display instances #if defined(DISPLAY_1_ID) - new EXDisplay(DISPLAY_1_ID, screen, 30); + new EXDisplay(DISPLAY_1_ID, screen, MAX_LINE_LENGTH); #endif #if defined(DISPLAY_2_ID) - new EXDisplay(DISPLAY_2_ID, screen, 30); + new EXDisplay(DISPLAY_2_ID, screen, MAX_LINE_LENGTH); #endif #if defined(DISPLAY_3_ID) - new EXDisplay(DISPLAY_3_ID, screen, 30); + new EXDisplay(DISPLAY_3_ID, screen, MAX_LINE_LENGTH); #endif for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { diff --git a/FontOptions.h b/FontOptions.h index 00c2e83..9167033 100644 --- a/FontOptions.h +++ b/FontOptions.h @@ -21,6 +21,9 @@ #define MAGENTA 0xF81F #define YELLOW 0xFFE0 #define WHITE 0xFFFF +#define OLED_BLACK 0 +#define OLED_WHITE 1 +#define OLED_INVERT 2 /// @brief Macros for available fonts #define SMALL &FreeMono9pt7b diff --git a/OLEDScreen.cpp b/OLEDScreen.cpp index 11e9ecc..fbb6862 100644 --- a/OLEDScreen.cpp +++ b/OLEDScreen.cpp @@ -42,24 +42,25 @@ void OLEDScreen::clearScreen(uint16_t backgroundColour) { } void OLEDScreen::clearRow(uint8_t row, uint16_t backgroundColour) { - int32_t x = 0; - int32_t y = (row * fontHeight) + row; - int32_t w = fontWidth * maxColumns; - int32_t h = fontHeight; + int16_t x = 0; + int16_t y = (row * fontHeight) + row; + int16_t w = fontWidth * maxColumns; + int16_t h = fontHeight; _oled.fillRect(x, y, w, h, backgroundColour); + _oled.display(); } void OLEDScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message, bool underlined) { uint16_t x = column; uint16_t y = (row * fontHeight) + fontHeight; - _oled.setTextColor(fontColour, backgroundColour); + _oled.setTextColor(fontColour); _oled.setCursor(x, y); _oled.print(message); if (underlined) { - _oled.drawLine(column, y + fontHeight, _oled.width(), y + fontHeight, fontColour); + _oled.drawLine(column, y+1, _oled.width(), y+1, fontColour); } else { - _oled.drawLine(column, y + fontHeight, _oled.width(), y + fontHeight, backgroundColour); + _oled.drawLine(column, y+1, _oled.width(), y+1, backgroundColour); } _oled.display(); CONSOLE.print(F("\nwriteRow textRow|message: ")); @@ -71,11 +72,11 @@ void OLEDScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint void OLEDScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) { // Horizontal start/end - int32_t x1 = column; - int32_t x2 = fontWidth * lineLength; + int16_t x1 = column; + int16_t x2 = fontWidth * lineLength; // Vertical start - half way up the font height - int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); - int32_t y2 = y1; + int16_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int16_t y2 = y1; clearRow(row, backgroundColour); _oled.drawLine(x1, y1, x2, y2, lineColour); _oled.display(); diff --git a/README.md b/README.md index ae9a5d9..30d64bf 100644 --- a/README.md +++ b/README.md @@ -4,17 +4,25 @@ A project for multiple displays connected to EX-CommandStation. The aim is to extend the current JMRI type virtual screen functionality to be displayed on additional microcontrollers with attached screens by using the `SCREEN(screen, row, "Message")` EXRAIL command. +There will be support for displaying output for multiple logical displays on one single physical screen, as well as displaying output on multiple physical screens. + ## Terminology - Display vs. Screen In the context of this project, the term "screen" is used when referring to a physical screen connected to a microcontroller to display information. This aligns with the use of the `SCREEN()` EXRAIL command, as it is designed to display information on a screen. The term "display" refers to a logical representation of a physical screen, enabling one physical screen to be used to dislay information from one or more EXRAIL defined screens. +## Supported Screen Types + +It is possible to use any physical screen that is supported by either the MCUFRIEND_kbv or TFT_eSPI libraries. + +In addition, it is also possible to use OLEDs based on either the SSD1306 or SH1106 drivers. + ## Configuration -Copy "config.example.h" to "config.h". +Copy "config.example.h" to "config.h" and set the desired parameters. -The key parameters to set are... +The key parameters to set depend on the physical screen type in use and are commented in the example config file. ## Features and Usage diff --git a/config.example.h b/config.example.h index e55c543..4334bef 100644 --- a/config.example.h +++ b/config.example.h @@ -6,14 +6,12 @@ // Define the pphysical screen types in use here - this needs to be ultra simplified at some point // Should we eventually support up to 3 displays? -// #define SCREEN_TYPE MCU +#define SCREEN_TYPE MCU // #define SCREEN_TYPE TFT -#define SCREEN_TYPE OLED_SSD1306 +// #define SCREEN_TYPE OLED_SSD1306 // #define SCREEN_TYPE OLED_SH1106 -#define OLED_WIDTH 128 -#define OLED_HEIGHT 64 -#define OLED_ADDRESS 0x3C +// #define OLED_ADDRESS 0x3C // Define the number of logical displays here // This is not a good way to do this @@ -24,36 +22,31 @@ // DO NOT REMOVE OR MOVE THIS LINE - MUST BE BEFORE FONT DEFINITION // Include the various fonts and font colours available for use with EX-Display +// Note for monochrome OLEDs you will need to set the OLED colour option here #include "FontOptions.h" // Font options #define TEXT_FONT MEDIUM #define TEXT_COLOUR WHITE +// #define TEXT_COLOUR OLED_WHITE #define TEXT_SIZE 1 #define BACKGROUND_COLOUR BLACK +// #define BACKGROUND_COLOUR OLED_BLACK // If rotation of the screen is required, set it here +// TFT type screen typically require 1, OLEDs typically require 0 +// #define SCREEN_ROTATION 0 #define SCREEN_ROTATION 1 +// #define SCREEN_ROTATION 2 +// #define SCREEN_ROTATION 3 // Some screens need inverting. If your screen displays inverted colours uncomment the following line. //#define INVERT_SCREEN // First entries about the display you are using // as we display across the wider part of the screen iwdth is the larger dimension -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 240 - -// Now we have to define how many screens you wish to display -// The system output screen is 0. -// An arduino Uno is capable of storing and displaying about 60 lines -// before running out of RAM e.g. (using 30 char lines) -// 4 screens of 16 lines -// 6 screens of 10 lines -// The first paramater tells EX-Display which initial screen to display -#define INITIAL_SCREEN 0 - -// Now define how many screens you wish to be used in turn -#define MAX_SCREENS 2 -#define MAX_ROWS 10 +// These should only be required if using OLED screen type +// #define SCREEN_WIDTH 128 +// #define SCREEN_HEIGHT 64 // If a touch screen is in use a touch will swap from screen to screen // if in use uncomment the following @@ -66,7 +59,7 @@ #define DISPLAY_SWITCH_TIME 5000 // And now define the maximum text length. -#define MAX_LINE_LENGTH 30 +#define MAX_LINE_LENGTH 50 // The startup Timelapse - allows time to handle all the CS output #define STARTUP_TIME 2000 From f9d18098969693eb16bb73671f594de324fd1a5b Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Mon, 20 May 2024 07:56:37 +1000 Subject: [PATCH 063/146] Disable text wrap --- MCUFriendScreen.cpp | 1 + OLEDScreen.cpp | 1 + version.h | 1 + 3 files changed, 3 insertions(+) diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 6ea0a87..afd3b9b 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -23,6 +23,7 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b _tft.setRotation(rotation); _tft.setFont(gfxFont); _tft.setTextSize(textSize); + _tft.setTextWrap(false); #ifdef INVERT_SCREEN _tft.invertDisplay(screenId); #endif diff --git a/OLEDScreen.cpp b/OLEDScreen.cpp index fbb6862..4b0ef41 100644 --- a/OLEDScreen.cpp +++ b/OLEDScreen.cpp @@ -20,6 +20,7 @@ void OLEDScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgr _oled.setRotation(rotation); _oled.setFont(gfxFont); _oled.setTextSize(textSize); + _oled.setTextWrap(false); _oled.clearDisplay(); _oled.display(); fontHeight = gfxFont->yAdvance; diff --git a/version.h b/version.h index 3578595..854972c 100644 --- a/version.h +++ b/version.h @@ -6,6 +6,7 @@ // 0.0.9 includes: // - Add support for SSD1306 and SH1106 I2C connected OLEDs +// - Disable text wrap // 0.0.8 includes: // - Fix a bug where adding new rows while the screen is scrolling puts them on the wrong row // 0.0.7 includes: From d26b8ec3f2133c544f71b52858c09658fa633656 Mon Sep 17 00:00:00 2001 From: Colin Murdoch Date: Tue, 21 May 2024 12:21:14 +0100 Subject: [PATCH 064/146] Update startup timing Update startup timing --- EX-Display.ino | 4 +++- MCUFriendScreen.cpp | 22 ++++++++++++---------- platformio.ini | 1 + 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 6aeb259..a7b2d3a 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -94,6 +94,8 @@ void loop() { // No data incoming so see if we need to display anything // DISABLE IN STARTUPPHASE else { - updateScreen(); + if (!StartupPhase) { + updateScreen(); + } } } diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index afd3b9b..2bdbb7a 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -37,10 +37,10 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b CONSOLE.print(_tft.height()); CONSOLE.print(F("|")); CONSOLE.println(_tft.width()); - CONSOLE.print(F("config.h parameters DISPLAY_HEIGHT|DISPLAY_WIDTH: ")); - CONSOLE.print(SCREEN_HEIGHT); - CONSOLE.print(F("|")); - CONSOLE.println(SCREEN_WIDTH); + // CONSOLE.print(F("config.h parameters DISPLAY_HEIGHT|DISPLAY_WIDTH: ")); + // CONSOLE.print(SCREEN_HEIGHT); + // CONSOLE.print(F("|")); + // CONSOLE.println(SCREEN_WIDTH); CONSOLE.print(F("maxRows|maxColumns|fontHeight|fontWidth: ")); CONSOLE.print(maxRows); CONSOLE.print(F("|")); @@ -81,12 +81,14 @@ void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, if (underlined) { _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); } - CONSOLE.println(F("\n~~ WRITE ROW PARAMETERS ~~")); - CONSOLE.print(F("textRow|width: ")); - CONSOLE.print(textRow); - CONSOLE.print(F("|")); - CONSOLE.println(width); - CONSOLE.println(F("~~ END WRITE ROW PARAMETERS ~~\n")); + // CONSOLE.println(F("\n~~ WRITE ROW PARAMETERS ~~")); + // CONSOLE.print(F("textRow|width: ")); + // CONSOLE.print(textRow); + // CONSOLE.print(F("|")); + // CONSOLE.println(width); + // CONSOLE.println(F("~~ END WRITE ROW PARAMETERS ~~\n")); + CONSOLE.print(F("Printing row: ")); + CONSOLE.println(message); } void MCUFriendScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, diff --git a/platformio.ini b/platformio.ini index d6857e4..b65fc99 100644 --- a/platformio.ini +++ b/platformio.ini @@ -48,6 +48,7 @@ lib_deps = ${env.lib_deps} build_flags = ${env.build_flags} + -D SERIAL_RX_BUFFER_SIZE=256 monitor_speed = 115200 monitor_echo = yes From 86dfa4d6a02d74f1b0c1bfb9113cbf5c012e180a Mon Sep 17 00:00:00 2001 From: peteGSX Date: Wed, 22 May 2024 05:31:52 +1000 Subject: [PATCH 065/146] Start refactor --- LogicalDisplay.cpp | 178 ++++++++++++++++++++++ LogicalDisplay.h | 80 ++++++++++ EXDisplayRow.cpp => LogicalDisplayRow.cpp | 52 +++---- EXDisplayRow.h => LogicalDisplayRow.h | 28 ++-- PhysicalScreen.cpp | 4 + PhysicalScreen.h | 85 +++++++++++ 6 files changed, 387 insertions(+), 40 deletions(-) create mode 100644 LogicalDisplay.cpp create mode 100644 LogicalDisplay.h rename EXDisplayRow.cpp => LogicalDisplayRow.cpp (75%) rename EXDisplayRow.h => LogicalDisplayRow.h (86%) create mode 100644 PhysicalScreen.cpp create mode 100644 PhysicalScreen.h diff --git a/LogicalDisplay.cpp b/LogicalDisplay.cpp new file mode 100644 index 0000000..822e33d --- /dev/null +++ b/LogicalDisplay.cpp @@ -0,0 +1,178 @@ +#include "Defines.h" +#include "LogicalDisplay.h" + +/* + * LogicalDisplay class implementation + */ +LogicalDisplay::LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber) + : _displayNumber(displayNumber), _maxRowLength(maxRowLength), _maxRowNumber(maxRowNumber) { + _firstRow = nullptr; + _next = nullptr; + _highestRowNumber = 0; + _numberOfRows = 0; + _scrollPosition = 0; + _lastScrollTime = 0; + _needsRedraw = false; +} + +LogicalDisplay *LogicalDisplay::getNext() { return _next; } + +LogicalDisplayRow *LogicalDisplay::getFirstRow() { return _firstRow; } + +uint8_t LogicalDisplay::getDisplayNumber() { return _displayNumber; } + +LogicalDisplayRow *LogicalDisplay::getRowByNumber(uint8_t rowNumber) { + for (auto *row = _firstRow; row; row = row->getNext()) { + if (row->getRowNumber() == rowNumber) { + return row; + } + } + return nullptr; +} + +void LogicalDisplay::updateRow(uint8_t rowNumber, char *rowText) { + auto *row = getRowByNumber(rowNumber); + if (row && strlen(rowText) == 0) { + _deleteRow(row); + } else if (!row && strlen(rowText) == 0) { + return; + } else if (!row) { + row = _addRow(rowNumber, rowText); + } else { + row->setRowText(rowText); + } +} + +void LogicalDisplay::scrollUp() { + // Scroll up logic: + // _scrollPosition needs to decrement to bring lower rows up the screen + // If _scrollPosition ends at 0, it should become the highest possible row + uint8_t lastRow = _maxRowNumber - 1; // Highest possible row number on screen + if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required + return; + } + if (_scrollPosition == 0) { // If row 0 is top of screen, need to move to the highest row number + _scrollPosition = _highestRowNumber; + } else { // + _scrollPosition--; + } + for (LogicalDisplayRow *row = _firstRow; row; row = row->getNext()) { + uint8_t newRow = row->getDisplayRow(); + if (newRow == _highestRowNumber) { // If row at bottom, it becomes first row + newRow = 0; + } else { // Otherwise move down one row + newRow++; + } + row->setDisplayRow(_scrollPosition, _maxRowNumber, _highestRowNumber); + } + _needsRedraw = true; // Need to redraw after each scroll +} + +void LogicalDisplay::scrollDown() { + uint8_t lastRow = _maxRowNumber - 1; // Highest possible row number on screen + if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required + return; + } + if (_scrollPosition >= lastRow) { // If last row is top of screen, goes to bottom + _scrollPosition = 0; + } else { // Otherwise next row is top of screen + _scrollPosition++; + } + for (LogicalDisplayRow *row = _firstRow; row; row = row->getNext()) { + uint8_t newRow = row->getDisplayRow(); + if (newRow == 0) { // If row at top of screen, it becomes last row + newRow = _highestRowNumber; + } else { // Otherwise move up one row + newRow--; + } + row->setDisplayRow(_scrollPosition, _maxRowNumber, _highestRowNumber); + } + _needsRedraw = true; // Need to redraw after each scroll +} + +void LogicalDisplay::autoScroll(unsigned long scrollDelay) { + if (millis() - _lastScrollTime > scrollDelay) { + _lastScrollTime = millis(); + scrollDown(); + } +} + +bool LogicalDisplay::needsRedraw() { return _needsRedraw; } + +void LogicalDisplay::resetRedraw() { _needsRedraw = false; } + +LogicalDisplayRow *LogicalDisplay::_addRow(uint8_t rowNumber, char *rowText) { + // create a new row and chain it in + LogicalDisplayRow *row = new LogicalDisplayRow(rowNumber); + _numberOfRows++; + + // find the row prior to the one we want to add + LogicalDisplayRow *previous = nullptr; + for (auto peek = _firstRow; peek; peek = peek->getNext()) { + if (peek->getRowNumber() > rowNumber) + break; + previous = peek; + } + if (previous) { + // chain after previous + row->setNext(previous->getNext()); + previous->setNext(row); + } else { + // chain at start of list + row->setNext(_firstRow); + _firstRow = row; + } + if (rowNumber > _highestRowNumber) { + _highestRowNumber = rowNumber; + } + row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); + row->setRowText(rowText); + row->setDisplayRow(_scrollPosition, _maxRowNumber, _highestRowNumber); + return row; +} + +void LogicalDisplay::_deleteRow(LogicalDisplayRow *row) { + if (!row) { + return; // Return if the row is nullptr + } + + // Find the previous node in the linked list + LogicalDisplayRow *previous = nullptr; + LogicalDisplayRow *current = _firstRow; + while (current != row) { + previous = current; + current = current->getNext(); + } + + // Remove the node from the linked list + if (previous) { + previous->setNext(row->getNext()); + } else { + _firstRow = row->getNext(); + } + + // Decrement the number of rows + _numberOfRows--; + + // Update the maximum row number if necessary + if (row->getRowNumber() == _highestRowNumber) { + _highestRowNumber = 0; + for (LogicalDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { + if (temp->getRowNumber() > _highestRowNumber) { + _highestRowNumber = temp->getRowNumber(); + } + } + } + + // If we're now within the confines of the screen, need to reset display rows and redraw + if (_highestRowNumber <= _maxRowNumber) { + _scrollPosition = 0; + for (LogicalDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { + temp->setDisplayRow(_scrollPosition, _maxRowNumber, _highestRowNumber); + } + _needsRedraw = true; + } + + // Delete the row object + delete row; +} diff --git a/LogicalDisplay.h b/LogicalDisplay.h new file mode 100644 index 0000000..a6d040d --- /dev/null +++ b/LogicalDisplay.h @@ -0,0 +1,80 @@ +#ifndef LOGICALDISPLAY_H +#define LOGICALDISPLAY_H + +#include "Defines.h" +#include "LogicalDisplayRow.h" +#include + +class LogicalDisplay { +public: + /// @brief Constructor for the LogicalDisplay class + /// @param displayNumber The ID of this display, 0 - 254 + /// @param maxRowLength The maximum number of characters that will fit on the physical screen + /// @param maxRowNumber The maximum number of rows that will fit on the physical screen + LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber); + + /// @brief Get the next LogicalDisplay object in the linked list + /// @return Pointer to the next LogicalDisplay object + LogicalDisplay *getNext(); + + /// @brief Get the first LogicalDisplayRow object associated with this display + /// @return Pointer to the first LogicalDisplayRow object for this display + LogicalDisplayRow *getFirstRow(); + + /// @brief Get the display's number + /// @return 0 - 255 + uint8_t getDisplayNumber(); + + /// @brief Get an LogicalDisplayRow object for this display by the specified row number + /// @param rowNumber Row number to retrieve, 0 - 255 + /// @return Pointer to an LogicalDisplayRow object, or nullptr if not exists + LogicalDisplayRow *getRowByNumber(uint8_t rowNumber); + + /// @brief Update text and ticker for the specified row number, will add if it doesn't exist + /// @param rowNumber Row number to display text on, 0 - 255 + /// @param rowText Char array of text for the row + void updateRow(uint8_t rowNumber, char *rowText); + + /// @brief Scroll up one row vertically + void scrollUp(); + + /// @brief Scroll down one row vertically + void scrollDown(); + + /// @brief Call this method as often as possible to support timed vertical scrolling + /// @param scrollDelay Time in milliseconds between vertical scrolling updates + void autoScroll(unsigned long scrollDelay); + + /// @brief Check if this display needs to be redrawn + /// @return True|False + bool needsRedraw(); + + /// @brief Reset the needsRedraw flag + void resetRedraw(); + +private: + LogicalDisplay *_next; // Pointer to the next display in the list + uint8_t _displayNumber; // ID of this display + LogicalDisplayRow *_firstRow; // Pointer to the first LogicalDisplayRow instances in the linked list + uint8_t _highestRowNumber; // Highest row number from the associated linked list instances + uint8_t _maxRowLength; // Number of characters that will fit on the physical screen + uint8_t _maxRowNumber; // Max row number that will fit on the physical screen + uint8_t _numberOfRows; // Calculated number of rows in the linked list + uint8_t _scrollPosition; // Row number that is at the top of the display to support scrolling + unsigned long _lastScrollTime; // Last time in ms a scroll function was performed + bool _needsRedraw; // Flag if this display needs to be redrawn + uint8_t _fontHeight; // Height of the font for this display + uint8_t _fontWidth; // Width of the font for this display + + /// @brief Private method to add a row + /// @param rowNumber 0 - 255 + /// @param rowText Pointer to the char array containing the text for this row + /// @return Pointer to the created LogicalDisplayRow instance + LogicalDisplayRow *_addRow(uint8_t rowNumber, char *rowText); + + /// @brief Delete the specified row number + /// @param row Pointer to the LogicalDisplayRow instance to delete + void _deleteRow(LogicalDisplayRow *row); +}; + +#endif diff --git a/EXDisplayRow.cpp b/LogicalDisplayRow.cpp similarity index 75% rename from EXDisplayRow.cpp rename to LogicalDisplayRow.cpp index f1a2a90..11994d0 100644 --- a/EXDisplayRow.cpp +++ b/LogicalDisplayRow.cpp @@ -1,10 +1,10 @@ #include "Defines.h" -#include "EXDisplayRow.h" +#include "LogicalDisplayRow.h" /* - * EXDisplayRow class implementation + * LogicalDisplayRow class implementation */ -EXDisplayRow::EXDisplayRow(uint8_t rowNumber) { +LogicalDisplayRow::LogicalDisplayRow(uint8_t rowNumber) { _rowNumber = rowNumber; _maxMalloc = 0; _rowText = nullptr; @@ -13,11 +13,11 @@ EXDisplayRow::EXDisplayRow(uint8_t rowNumber) { _rowAttributes = {false, false, false, false}; } -uint8_t EXDisplayRow::getRowNumber() { return _rowNumber; } +uint8_t LogicalDisplayRow::getRowNumber() { return _rowNumber; } -uint8_t EXDisplayRow::getMaxRowLength() { return _maxMalloc; } +uint8_t LogicalDisplayRow::getMaxRowLength() { return _maxMalloc; } -void EXDisplayRow::setRowText(char *rowText) { +void LogicalDisplayRow::setRowText(char *rowText) { // Note size limit is 254 chars but that is beyond // the capability of the caller anyway. @@ -42,14 +42,14 @@ void EXDisplayRow::setRowText(char *rowText) { _changed = true; } -char *EXDisplayRow::getRowText() { +char *LogicalDisplayRow::getRowText() { _changed = false; return _rowText; } -bool EXDisplayRow::isChanged() { return _changed; } +bool LogicalDisplayRow::isChanged() { return _changed; } -void EXDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, uint8_t maxRowNumber) { +void LogicalDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, uint8_t maxRowNumber) { if (_rowNumber >= scrollPosition) { _displayRow = _rowNumber - scrollPosition; } else { @@ -62,34 +62,34 @@ void EXDisplayRow::setDisplayRow(uint8_t scrollPosition, uint8_t maxScreenRows, } } -uint8_t EXDisplayRow::getDisplayRow() { return _displayRow; } +uint8_t LogicalDisplayRow::getDisplayRow() { return _displayRow; } -bool EXDisplayRow::needsRender() { return _needsRender; } +bool LogicalDisplayRow::needsRender() { return _needsRender; } -EXDisplayRow *EXDisplayRow::getNext() { return _next; } +LogicalDisplayRow *LogicalDisplayRow::getNext() { return _next; } -void EXDisplayRow::setNext(EXDisplayRow *next) { _next = next; } +void LogicalDisplayRow::setNext(LogicalDisplayRow *next) { _next = next; } -void EXDisplayRow::setColours(uint16_t textColour, uint16_t backgroundColour) { +void LogicalDisplayRow::setColours(uint16_t textColour, uint16_t backgroundColour) { _textColour = textColour; _backgroundColour = backgroundColour; _changed = true; } -uint16_t EXDisplayRow::getTextColour() { return _textColour; } +uint16_t LogicalDisplayRow::getTextColour() { return _textColour; } -uint16_t EXDisplayRow::getBackgroundColour() { return _backgroundColour; } +uint16_t LogicalDisplayRow::getBackgroundColour() { return _backgroundColour; } -bool EXDisplayRow::isLine() { +bool LogicalDisplayRow::isLine() { _changed = false; return _rowAttributes.line; } -bool EXDisplayRow::isUnderlined() { return _rowAttributes.underline; } +bool LogicalDisplayRow::isUnderlined() { return _rowAttributes.underline; } -EXDisplayRow::~EXDisplayRow() { free(_rowText); } +LogicalDisplayRow::~LogicalDisplayRow() { free(_rowText); } -void EXDisplayRow::_rowFormatter() { +void LogicalDisplayRow::_rowFormatter() { /* Need to check for all possible formatting codes here When formatting codes discovered: @@ -107,7 +107,7 @@ void EXDisplayRow::_rowFormatter() { _neverTicker(); } -void EXDisplayRow::_setColours() { +void LogicalDisplayRow::_setColours() { // Check for format #0xdddd#0xdddd# if (_rowText[0] != '#' || _rowText[7] != '#' || _rowText[14] != '#') { return; @@ -155,7 +155,7 @@ void EXDisplayRow::_setColours() { _removeFormatters(15); } -void EXDisplayRow::_setLine() { +void LogicalDisplayRow::_setLine() { if (strlen(_rowText) != 2 || _rowText[0] != '-' || _rowText[strlen(_rowText) - 1] != '-') { _rowAttributes.line = false; return; @@ -164,7 +164,7 @@ void EXDisplayRow::_setLine() { _removeFormatters(2); } -void EXDisplayRow::_setUnderline() { +void LogicalDisplayRow::_setUnderline() { if (_rowText[0] != '_' || _rowText[1] != '_') { if (_rowAttributes.underline) { _rowAttributes.underline = false; @@ -175,7 +175,7 @@ void EXDisplayRow::_setUnderline() { _removeFormatters(2); } -void EXDisplayRow::_alwaysTicker() { +void LogicalDisplayRow::_alwaysTicker() { // Check for leading "~~" if (_rowText[0] != '~' || _rowText[1] != '~') { _rowAttributes.alwaysTicker = false; @@ -185,7 +185,7 @@ void EXDisplayRow::_alwaysTicker() { return; } -void EXDisplayRow::_neverTicker() { +void LogicalDisplayRow::_neverTicker() { // Check for leading "!~" if (_rowText[0] != '!' || _rowText[1] != '~') { _rowAttributes.neverTicker = false; @@ -195,7 +195,7 @@ void EXDisplayRow::_neverTicker() { return; } -void EXDisplayRow::_removeFormatters(uint8_t size) { +void LogicalDisplayRow::_removeFormatters(uint8_t size) { // New length for "text" needs to be length - formatters (size) + null pointer (1) uint8_t textLength = strlen(_rowText) - size + 1; // Set our temp char array to what we already have defined as our max size diff --git a/EXDisplayRow.h b/LogicalDisplayRow.h similarity index 86% rename from EXDisplayRow.h rename to LogicalDisplayRow.h index 0697cc9..ebdb0c3 100644 --- a/EXDisplayRow.h +++ b/LogicalDisplayRow.h @@ -1,5 +1,5 @@ -#ifndef EXDisplayRow_H -#define EXDisplayRow_H +#ifndef LOGICALDISPLAYROW_H +#define LOGICALDISPLAYROW_H #include @@ -8,7 +8,7 @@ * Each row is a member of a linked list which is an attribute of an EXDisplay object. * */ -class EXDisplayRow { +class LogicalDisplayRow { /// @brief Structure for the _rowAttributes attribute for row formatting struct RowAttributes { bool line : 1; @@ -18,9 +18,9 @@ class EXDisplayRow { }; public: - /// @brief Constructor for the EXDisplayRow object + /// @brief Constructor for the LogicalDisplayRow object /// @param rowNumber Row number on the display, 0 - 255 - EXDisplayRow(uint8_t rowNumber); + LogicalDisplayRow(uint8_t rowNumber); /// @brief Get the row number this should be displayed on /// @return 0 - 255 @@ -56,13 +56,13 @@ class EXDisplayRow { /// @return True|False bool needsRender(); - /// @brief Set the pointer to the next EXDisplayRow object in the linked list - /// @param next Pointer to the next EXDisplayRow object - void setNext(EXDisplayRow *next); + /// @brief Set the pointer to the next LogicalDisplayRow object in the linked list + /// @param next Pointer to the next LogicalDisplayRow object + void setNext(LogicalDisplayRow *next); /// @brief Get the next row - /// @return Pointer to the next EXDisplayRow object in the linked list - EXDisplayRow *getNext(); + /// @return Pointer to the next LogicalDisplayRow object in the linked list + LogicalDisplayRow *getNext(); /// @brief Set the text/foreground and background colour for this row /// @param textColour Hex value of the text/foreground colour @@ -85,8 +85,8 @@ class EXDisplayRow { /// @return true|false bool isUnderlined(); - /// @brief Destructor for the EXDisplayRow object - ~EXDisplayRow(); + /// @brief Destructor for the LogicalDisplayRow object + ~LogicalDisplayRow(); private: uint8_t _rowNumber; // This is the row number received from the parser @@ -95,13 +95,13 @@ class EXDisplayRow { bool _changed; // Flag set when text received from the parser is different to rowText uint8_t _displayRow; // This is the calculated physical row on a display that this line belongs on bool _needsRender; // Flag that is set when row belongs on a physical display, false when off-screen - EXDisplayRow *_next; + LogicalDisplayRow *_next; uint16_t _textColour; // Text/foreground colour for this row uint16_t _backgroundColour; // Background colour for this row RowAttributes _rowAttributes; // One bit per attribute to allow 8 total /// @brief Private method to format the row attributes for the specified row - /// @param row Pointer to an EXDisplayRow object + /// @param row Pointer to an LogicalDisplayRow object void _rowFormatter(); /// @brief Extract colour codes from text diff --git a/PhysicalScreen.cpp b/PhysicalScreen.cpp new file mode 100644 index 0000000..4866205 --- /dev/null +++ b/PhysicalScreen.cpp @@ -0,0 +1,4 @@ +#include "Defines.h" +#include "PhysicalScreen.h" +#include + diff --git a/PhysicalScreen.h b/PhysicalScreen.h new file mode 100644 index 0000000..4730ea2 --- /dev/null +++ b/PhysicalScreen.h @@ -0,0 +1,85 @@ +#ifndef PHYSICALSCREEN_H +#define PHYSICALSCREEN_H + +#include "Defines.h" +#include "LogicalDisplay.h" +#include + +/// @brief This PhysicalScreen class is designed to be extended by other screen classes that define the methods to +/// perform the requesite activities according to the library in use to drive the physical screen. This allows all +/// physical screen methods to be consistent regardless of the library or driver in use, allowing this code to support +/// multiple different screen types without needing to have the main functions call different libraries/methods. Every +/// virtual method must be declared and defined in the class that extends this. +class PhysicalScreen { +public: + PhysicalScreen() { _logicalDisplay = nullptr; } + + /// @brief Virtual function to implement to setup the physical screen parameters + /// @param rotation Rotate the screen if necessary + /// @param textSize Pixel multiplier to increase text size if desired + /// @param backgroundColour Fill the screen with this colour during setup + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour); + + /// @brief Virtual function to implement to clear the entire screen + /// @param backgroundColour Valid colour to set the entire screen to + virtual void clearScreen(uint16_t backgroundColour); + + /// @brief Virtual function to implement to clear the specified row + /// @param row Row number to clear, 0 - 255 + /// @param backgroundColour Valid colour to set the row to + virtual void clearRow(uint8_t row, uint16_t backgroundColour); + + /// @brief Virtual function to implement to write a row of text to the physical screen + /// @param row Row on screen, 0 - 255 (not pixels) + /// @param column Column on screen, 0 - 255 (not pixels) + /// @param fontColour Valid colour for the text + /// @param backgroundColour Valid colour for the background + /// @param maxLength Maximum number of columns (not pixels) that can fit on the screen + /// @param message Char array containing the text to display + virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, + char *message, bool underlined); + + /// @brief Virtual function to implement to write a horizontal line on the specified row + /// @param row Row on screen, 0 - 255 (not pixels) + /// @param column Column to start the line, 0 - 255 (not pixels) + /// @param lineWidth Pixel width to make the line + /// @param lineLength Number of columns for the line (not pixels), 0 - 255 + /// @param lineColour Valid colour for the line + /// @param backgroundColour Valid colour for the background + virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, + uint16_t backgroundColour); + + /// @brief Get the first EXDisplay object in the linked list + /// @return Pointer to the first EXDisplay object + LogicalDisplay *getFirstDisplay(); + + /// @brief Check if there is already a display created at the specified number + /// @param displayNumber True|False + /// @return + bool displayNumberExists(uint8_t displayNumber); + + /// @brief Get the display and associated row linked list for the specified display number + /// @param displayNumber Display number to get, 0 - 255 + /// @return EXDisplay object, or nullptr if not exists + static LogicalDisplay *getDisplayByNumber(uint8_t displayNumber); + + /// @brief Get the currently selected display + /// @return Pointer to the currently selected display + LogicalDisplay *getActiveDisplay(); + + /// @brief Switch active display to the next display in the linked list + void setNextDisplay(); + + /// @brief Switch active display to the previous display in the linked list + void setPreviousDisplay(); + + /// @brief Call this method as often as possible to support timed display switching + /// @param switchDelay Time in milliseconds before switching displays + void autoSwitch(unsigned long switchDelay); + +protected: + LogicalDisplay *_logicalDisplay; // Pointer to the first associated logical display + LogicalDisplay *_activeDisplay; // Current logical display this physical screen needs to show +}; + +#endif From 52f371131fcefe84dfb1c018eaa94628d6f9fe03 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Wed, 22 May 2024 16:36:22 +1000 Subject: [PATCH 066/146] Some progress --- LogicalDisplay.cpp | 18 +++++++--- LogicalDisplay.h | 50 +++++++++++++++++--------- PhysicalScreen.cpp | 87 ++++++++++++++++++++++++++++++++++++++++++++++ PhysicalScreen.h | 42 +++++++++++++++------- TFT_eSPIScreen.cpp | 2 +- TFT_eSPIScreen.h | 4 +-- 6 files changed, 165 insertions(+), 38 deletions(-) diff --git a/LogicalDisplay.cpp b/LogicalDisplay.cpp index 822e33d..19c0c6c 100644 --- a/LogicalDisplay.cpp +++ b/LogicalDisplay.cpp @@ -4,8 +4,10 @@ /* * LogicalDisplay class implementation */ -LogicalDisplay::LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber) - : _displayNumber(displayNumber), _maxRowLength(maxRowLength), _maxRowNumber(maxRowNumber) { +LogicalDisplay::LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber, uint16_t textColour, + uint16_t backgroundColour) + : _displayNumber(displayNumber), _maxRowLength(maxRowLength), _maxRowNumber(maxRowNumber), + _defaultTextColour(textColour), _defaultBackgroundColour(backgroundColour) { _firstRow = nullptr; _next = nullptr; _highestRowNumber = 0; @@ -48,7 +50,7 @@ void LogicalDisplay::scrollUp() { // _scrollPosition needs to decrement to bring lower rows up the screen // If _scrollPosition ends at 0, it should become the highest possible row uint8_t lastRow = _maxRowNumber - 1; // Highest possible row number on screen - if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required + if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required return; } if (_scrollPosition == 0) { // If row 0 is top of screen, need to move to the highest row number @@ -70,7 +72,7 @@ void LogicalDisplay::scrollUp() { void LogicalDisplay::scrollDown() { uint8_t lastRow = _maxRowNumber - 1; // Highest possible row number on screen - if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required + if (_highestRowNumber <= lastRow) { // If our max row number is on screen, no scroll required return; } if (_scrollPosition >= lastRow) { // If last row is top of screen, goes to bottom @@ -99,7 +101,13 @@ void LogicalDisplay::autoScroll(unsigned long scrollDelay) { bool LogicalDisplay::needsRedraw() { return _needsRedraw; } -void LogicalDisplay::resetRedraw() { _needsRedraw = false; } +void LogicalDisplay::setRedraw(bool redraw) { _needsRedraw = redraw; } + +uint16_t LogicalDisplay::getDefaultTextColour() { return _defaultTextColour; } + +uint16_t LogicalDisplay::getDefaultBackgroundColour() { return _defaultBackgroundColour; } + +uint8_t LogicalDisplay::getMaxRowLength() { return _maxRowLength; } LogicalDisplayRow *LogicalDisplay::_addRow(uint8_t rowNumber, char *rowText) { // create a new row and chain it in diff --git a/LogicalDisplay.h b/LogicalDisplay.h index a6d040d..6044625 100644 --- a/LogicalDisplay.h +++ b/LogicalDisplay.h @@ -9,9 +9,10 @@ class LogicalDisplay { public: /// @brief Constructor for the LogicalDisplay class /// @param displayNumber The ID of this display, 0 - 254 - /// @param maxRowLength The maximum number of characters that will fit on the physical screen - /// @param maxRowNumber The maximum number of rows that will fit on the physical screen - LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber); + /// @param textColour Valid colour code for the default text colour + /// @param backgroundColour Valid colour code for the default background colour + LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber, uint16_t textColour, + uint16_t backgroundColour); /// @brief Get the next LogicalDisplay object in the linked list /// @return Pointer to the next LogicalDisplay object @@ -49,22 +50,37 @@ class LogicalDisplay { /// @return True|False bool needsRedraw(); - /// @brief Reset the needsRedraw flag - void resetRedraw(); + /// @brief Set the needsRedraw flag + /// @param redraw true|false + void setRedraw(bool redraw); + + /// @brief Get the default text colour for this display + /// @return 16 bit colour code + uint16_t getDefaultTextColour(); + + /// @brief Get the default background colour for this display + /// @return 16 bit colour code + uint16_t getDefaultBackgroundColour(); + + /// @brief Get the maximum number of characters that will fit on a row + /// @return 0 - 255 + uint8_t getMaxRowLength(); private: - LogicalDisplay *_next; // Pointer to the next display in the list - uint8_t _displayNumber; // ID of this display - LogicalDisplayRow *_firstRow; // Pointer to the first LogicalDisplayRow instances in the linked list - uint8_t _highestRowNumber; // Highest row number from the associated linked list instances - uint8_t _maxRowLength; // Number of characters that will fit on the physical screen - uint8_t _maxRowNumber; // Max row number that will fit on the physical screen - uint8_t _numberOfRows; // Calculated number of rows in the linked list - uint8_t _scrollPosition; // Row number that is at the top of the display to support scrolling - unsigned long _lastScrollTime; // Last time in ms a scroll function was performed - bool _needsRedraw; // Flag if this display needs to be redrawn - uint8_t _fontHeight; // Height of the font for this display - uint8_t _fontWidth; // Width of the font for this display + LogicalDisplay *_next; // Pointer to the next display in the list + uint8_t _displayNumber; // ID of this display + LogicalDisplayRow *_firstRow; // Pointer to the first LogicalDisplayRow instances in the linked list + uint8_t _highestRowNumber; // Highest row number from the associated linked list instances + uint8_t _maxRowLength; // Number of characters that will fit on the physical screen + uint8_t _maxRowNumber; // Max number of rows that will fit on the physical screen + uint8_t _numberOfRows; // Calculated number of rows in the linked list + uint8_t _scrollPosition; // Row number that is at the top of the display to support scrolling + unsigned long _lastScrollTime; // Last time in ms a scroll function was performed + bool _needsRedraw; // Flag if this display needs to be redrawn + uint8_t _fontHeight; // Height of the font for this display + uint8_t _fontWidth; // Width of the font for this display + uint8_t _defaultTextColour; // Default colour for text for this display + uint8_t _defaultBackgroundColour; // Default background colour for this display /// @brief Private method to add a row /// @param rowNumber 0 - 255 diff --git a/PhysicalScreen.cpp b/PhysicalScreen.cpp index 4866205..1cb32b7 100644 --- a/PhysicalScreen.cpp +++ b/PhysicalScreen.cpp @@ -2,3 +2,90 @@ #include "PhysicalScreen.h" #include +PhysicalScreen::PhysicalScreen() { + _firstDisplay = nullptr; + _activeDisplay = nullptr; + _displayCount = 0; + _lastSwitchTime = 0; + _maxRows = 0; + _maxRowLength = 0; +} + +void PhysicalScreen::addDisplay(uint8_t displayNumber, uint16_t defaultTextColour, uint16_t defaultBackgroundColour) { + +} + +LogicalDisplay *PhysicalScreen::getFirstDisplay() { return _firstDisplay; } + +LogicalDisplay *PhysicalScreen::getActiveDisplay() { return _activeDisplay; } + +bool PhysicalScreen::displayNumberExists(uint8_t displayNumber) { return getDisplayByNumber(displayNumber) != nullptr; } + +LogicalDisplay *PhysicalScreen::getDisplayByNumber(uint8_t displayNumber) { + for (auto *display = _firstDisplay; display; display = display->getNext()) { + if (display->getDisplayNumber() == displayNumber) { + return display; + } + } + return nullptr; +} + +void PhysicalScreen::switchToNextDisplay() { + if (!_activeDisplay) { + _activeDisplay = _firstDisplay; + _activeDisplay->setRedraw(true); + return; + } + if (_displayCount == 1) { + return; + } + if (_activeDisplay->getNext()) { + _activeDisplay = _activeDisplay->getNext(); + } else { + _activeDisplay = _firstDisplay; + } + _activeDisplay->setRedraw(true); +} + +void PhysicalScreen::switchToPreviousDisplay() { + if (!_activeDisplay) { + _activeDisplay = _firstDisplay; + _activeDisplay->setRedraw(true); + return; + } + if (_displayCount == 1) { + return; + } + for (LogicalDisplay *display = _activeDisplay; display; display = display->getNext()) { + if (display->getNext() == _activeDisplay) { + _activeDisplay = display; + _activeDisplay->setRedraw(true); + return; + } + } +} + +void PhysicalScreen::autoSwitch(unsigned long switchDelay) { + if (millis() - _lastSwitchTime > switchDelay) { + _lastSwitchTime = millis(); + switchToNextDisplay(); + } +} + +void PhysicalScreen::processActiveDisplay() { + if (_activeDisplay->needsRedraw()) { + clearScreen(_activeDisplay->getDefaultBackgroundColour()); + } + for (LogicalDisplayRow *row = _activeDisplay->getFirstRow(); row; row = row->getNext()) { + if (row->needsRender() && (row->isChanged() || _activeDisplay->needsRedraw())) { + if (row->isLine()) { + writeLine(row->getDisplayRow(), 0, _activeDisplay->getMaxRowLength(), row->getTextColour(), + row->getBackgroundColour()); + } else { + writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), + _activeDisplay->getMaxRowLength(), row->getRowText(), row->isUnderlined()); + } + } + } + _activeDisplay->setRedraw(false); +} diff --git a/PhysicalScreen.h b/PhysicalScreen.h index 4730ea2..75ffa6d 100644 --- a/PhysicalScreen.h +++ b/PhysicalScreen.h @@ -12,7 +12,8 @@ /// virtual method must be declared and defined in the class that extends this. class PhysicalScreen { public: - PhysicalScreen() { _logicalDisplay = nullptr; } + /// @brief Constructor for a new PhysicalScreen instance + PhysicalScreen(); /// @brief Virtual function to implement to setup the physical screen parameters /// @param rotation Rotate the screen if necessary @@ -49,10 +50,22 @@ class PhysicalScreen { virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour); - /// @brief Get the first EXDisplay object in the linked list - /// @return Pointer to the first EXDisplay object + /// @brief Add a new LogicalDisplay instance to be displayed on this screen + /// @param displayNumber Display ID for the instance + void addDisplay(uint8_t displayNumber, uint16_t defaultTextColour, uint16_t defaultBackgroundColour); + + /// @brief Get the first LogicalDisplay instance in the linked list + /// @return Pointer to the first LogicalDisplay instance LogicalDisplay *getFirstDisplay(); + /// @brief Get the active LogicalDisplay instance that should display on this screen + /// @return Pointer to the active LogicalDisplay instance + LogicalDisplay *getActiveDisplay(); + + /// @brief Set the active LogicalDisplay instance to display on this screen + /// @param activeDisplay Pointer to the LogicalDisplay instance to mark as active + void setActiveDisplay(LogicalDisplay *activeDisplay); + /// @brief Check if there is already a display created at the specified number /// @param displayNumber True|False /// @return @@ -60,26 +73,29 @@ class PhysicalScreen { /// @brief Get the display and associated row linked list for the specified display number /// @param displayNumber Display number to get, 0 - 255 - /// @return EXDisplay object, or nullptr if not exists - static LogicalDisplay *getDisplayByNumber(uint8_t displayNumber); - - /// @brief Get the currently selected display - /// @return Pointer to the currently selected display - LogicalDisplay *getActiveDisplay(); + /// @return Pointer to a LogicalDisplay instance, or nullptr if not exists + LogicalDisplay *getDisplayByNumber(uint8_t displayNumber); /// @brief Switch active display to the next display in the linked list - void setNextDisplay(); + void switchToNextDisplay(); /// @brief Switch active display to the previous display in the linked list - void setPreviousDisplay(); + void switchToPreviousDisplay(); /// @brief Call this method as often as possible to support timed display switching /// @param switchDelay Time in milliseconds before switching displays void autoSwitch(unsigned long switchDelay); + /// @brief Call this method as often as possible to ensure this physical screen is updated correctly + void processActiveDisplay(); + protected: - LogicalDisplay *_logicalDisplay; // Pointer to the first associated logical display - LogicalDisplay *_activeDisplay; // Current logical display this physical screen needs to show + LogicalDisplay *_firstDisplay; // Pointer to the first associated logical display + LogicalDisplay *_activeDisplay; // Current logical display this physical screen needs to show + uint8_t _displayCount; // Number of logical displays associated with this screen + unsigned long _lastSwitchTime; // Last time an auto switch to the next display instance occurred + uint8_t _maxRows; // Calculated maximum number of rows that will fit on screen based on font size + uint8_t _maxRowLength; // Calculated maximum number of characters that will fit on screen based on font size }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index d3dea08..c343cc2 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -3,7 +3,7 @@ #include "TFT_eSPIScreen.h" -TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : EXScreen(), _tft(tft) {} +TFT_eSPIScreen::TFT_eSPIScreen(TFT_eSPI &tft) : PhysicalScreen(), _tft(tft) {} void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { const GFXfont *gfxFont = TEXT_FONT; diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index bea1ac5..52c641d 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -4,12 +4,12 @@ #ifndef TFT_ESPISCREEN_H #define TFT_ESPISCREEN_H -#include "EXScreen.h" +#include "PhysicalScreen.h" #include #include #include -class TFT_eSPIScreen : public EXScreen { +class TFT_eSPIScreen : public PhysicalScreen { public: TFT_eSPIScreen(TFT_eSPI &tft); From 700be903fa67187fda003d38731b14206990c0ab Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 23 May 2024 08:48:44 +1000 Subject: [PATCH 067/146] Initial TFT testing good --- DisplayFunctions.cpp | 57 ++++++++++++-------- DisplayFunctions.h | 6 +-- EX-Display.ino | 32 +++++------ EXDisplayClass.cpp => EXDisplayClass.cpp.txt | 0 EXDisplayClass.h => EXDisplayClass.h.txt | 0 EXScreen.h => EXScreen.h.txt | 0 LogicalDisplay.cpp | 2 + LogicalDisplay.h | 4 ++ PhysicalScreen.cpp | 56 ++++++++++++++++++- PhysicalScreen.h | 47 ++++++++++++---- TFT_eSPIScreen.cpp | 34 ++++++------ 11 files changed, 169 insertions(+), 69 deletions(-) rename EXDisplayClass.cpp => EXDisplayClass.cpp.txt (100%) rename EXDisplayClass.h => EXDisplayClass.h.txt (100%) rename EXScreen.h => EXScreen.h.txt (100%) diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index ec72f7d..f40537d 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -10,7 +10,7 @@ bool debug = false; // This function is called from AtFinder when a // <@ screenid row "text"> message is discovered. -void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { +void updateDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { // special diagnostic to dump buffers on request if (screenId == 255) { @@ -18,38 +18,51 @@ void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text) { return; } - EXDisplay *display = EXDisplay::getDisplayByNumber(screenId); - if (display) { - display->updateRow(screenRow, text); + for (PhysicalScreen *screen = PhysicalScreen::getFirst(); screen; screen = screen->getNext()) { + for (LogicalDisplay *display = screen->getFirstDisplay(); display; display = display->getNext()) { + if (display->getDisplayNumber() == screenId) { + display->updateRow(screenRow, text); + return; + } + } } } void updateScreen() { - EXDisplay *display = EXDisplay::getActiveDisplay(); + for (PhysicalScreen *screen = PhysicalScreen::getFirst(); screen; screen = screen->getNext()) { #ifdef SCROLLTIME - display->autoScroll(SCROLLTIME); + for (LogicalDisplay *display = screen->getFirstDisplay(); display; display = display->getNext()) { + display->autoScroll(SCROLLTIME); + } #endif #ifdef DISPLAY_SWITCH_TIME - display->autoSwitch(DISPLAY_SWITCH_TIME); + screen->autoSwitch(DISPLAY_SWITCH_TIME); #endif - display->processDisplay(); + screen->processActiveDisplay(); + } } void displayAllRows() { - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - CONSOLE.print(F("\n\nRows for display ")); - CONSOLE.println(display->getDisplayNumber()); - CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender")); - for (EXDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { - CONSOLE.print(row->getRowNumber()); - CONSOLE.print(F("|")); - CONSOLE.print(row->getDisplayRow()); - CONSOLE.print(F("|")); - CONSOLE.print(row->getRowText()); - CONSOLE.print(F("|")); - CONSOLE.print(row->isChanged()); - CONSOLE.print(F("|")); - CONSOLE.println(row->needsRender()); + for (PhysicalScreen *screen = PhysicalScreen::getFirst(); screen; screen = screen->getNext()) { + CONSOLE.print(F("\n~~ All displays and rows for screen ")); + CONSOLE.print(screen->getScreenNumber()); + CONSOLE.println(F(" ~~")); + + for (LogicalDisplay *display = screen->getFirstDisplay(); display; display = display->getNext()) { + CONSOLE.print(F("\nRows for display ")); + CONSOLE.println(display->getDisplayNumber()); + CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender")); + for (LogicalDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { + CONSOLE.print(row->getRowNumber()); + CONSOLE.print(F("|")); + CONSOLE.print(row->getDisplayRow()); + CONSOLE.print(F("|")); + CONSOLE.print(row->getRowText()); + CONSOLE.print(F("|")); + CONSOLE.print(row->isChanged()); + CONSOLE.print(F("|")); + CONSOLE.println(row->needsRender()); + } } } } diff --git a/DisplayFunctions.h b/DisplayFunctions.h index 2da7d9d..e9f8278 100644 --- a/DisplayFunctions.h +++ b/DisplayFunctions.h @@ -1,18 +1,16 @@ #ifndef DISPLAYFUNCTIONS_H #define DISPLAYFUNCTIONS_H -#include "EXDisplayClass.h" +#include "PhysicalScreen.h" #include extern bool debug; -// extern EXDisplay *display0; - /// @brief Callback function for AtFinder /// @param screenId ID of the screen to update /// @param screenRow Row of the screen to update /// @param text Char array of text -void updateEXDisplayRow(uint8_t screenId, uint8_t screenRow, char *text); +void updateDisplayRow(uint8_t screenId, uint8_t screenRow, char *text); /// @brief Update the active display on its associated screen void updateScreen(); diff --git a/EX-Display.ino b/EX-Display.ino index 6aeb259..6d0ade9 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -37,38 +37,40 @@ void setup() { Wire.begin(); #endif - // Tell AtFinder our maximum supported text length, - // and how to call back when found. - AtFinder::setup(100, updateEXDisplayRow); + // Setup our physical screens first - required before adding displays + screen->setupScreen(SCREEN_ROTATION, TEXT_SIZE, BACKGROUND_COLOUR); - // Create display instances + // Add the displays to the screen #if defined(DISPLAY_1_ID) - new EXDisplay(DISPLAY_1_ID, screen, MAX_LINE_LENGTH); + screen->addDisplay(DISPLAY_1_ID, TEXT_COLOUR, BACKGROUND_COLOUR); #endif #if defined(DISPLAY_2_ID) - new EXDisplay(DISPLAY_2_ID, screen, MAX_LINE_LENGTH); +screen->addDisplay(DISPLAY_2_ID, TEXT_COLOUR, BACKGROUND_COLOUR); #endif #if defined(DISPLAY_3_ID) - new EXDisplay(DISPLAY_3_ID, screen, MAX_LINE_LENGTH); + screen->addDisplay(DISPLAY_3_ID, TEXT_COLOUR, BACKGROUND_COLOUR); #endif - for (EXDisplay *display = EXDisplay::getFirst(); display; display = display->getNext()) { - display->getEXScreen()->setupScreen(SCREEN_ROTATION, BACKGROUND_COLOUR, TEXT_SIZE); + // Tell AtFinder our maximum supported text length, + // and how to call back when found. + AtFinder::setup(100, updateDisplayRow); + + // Create display instances + for (LogicalDisplay *display = screen->getFirstDisplay(); display; display = display->getNext()) { CONSOLE.print(F("Display ID|Max Rows|Max Columns: ")); CONSOLE.print(display->getDisplayNumber()); CONSOLE.print(F("|")); - CONSOLE.print(display->getScreenMaxRows()); + CONSOLE.print(screen->getMaxRows()); CONSOLE.print(F("|")); - CONSOLE.println(display->getScreenMaxColumns()); + CONSOLE.println(display->getMaxRowLength()); } - EXDisplay *activeDisplay = EXDisplay::getActiveDisplay(); - activeDisplay->getEXScreen()->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display", false); - activeDisplay->getEXScreen()->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION, false); + screen->writeRow(0, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, "EX-Display", false); + screen->writeRow(1, 0, TEXT_COLOUR, BACKGROUND_COLOUR, 0, VERSION, false); delay(2000); - activeDisplay->getEXScreen()->clearScreen(BACKGROUND_COLOUR); + screen->clearScreen(BACKGROUND_COLOUR); timestamp = millis(); CONSOLE.println(F("End of Setup")); diff --git a/EXDisplayClass.cpp b/EXDisplayClass.cpp.txt similarity index 100% rename from EXDisplayClass.cpp rename to EXDisplayClass.cpp.txt diff --git a/EXDisplayClass.h b/EXDisplayClass.h.txt similarity index 100% rename from EXDisplayClass.h rename to EXDisplayClass.h.txt diff --git a/EXScreen.h b/EXScreen.h.txt similarity index 100% rename from EXScreen.h rename to EXScreen.h.txt diff --git a/LogicalDisplay.cpp b/LogicalDisplay.cpp index 19c0c6c..58bb9b9 100644 --- a/LogicalDisplay.cpp +++ b/LogicalDisplay.cpp @@ -17,6 +17,8 @@ LogicalDisplay::LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint _needsRedraw = false; } +void LogicalDisplay::setNext(LogicalDisplay *display) { _next = display; } + LogicalDisplay *LogicalDisplay::getNext() { return _next; } LogicalDisplayRow *LogicalDisplay::getFirstRow() { return _firstRow; } diff --git a/LogicalDisplay.h b/LogicalDisplay.h index 6044625..943f079 100644 --- a/LogicalDisplay.h +++ b/LogicalDisplay.h @@ -14,6 +14,10 @@ class LogicalDisplay { LogicalDisplay(uint8_t displayNumber, uint8_t maxRowLength, uint8_t maxRowNumber, uint16_t textColour, uint16_t backgroundColour); + /// @brief Set the next display in the linked list + /// @param display Pointer to the next LogicalDisplay instance + void setNext(LogicalDisplay *display); + /// @brief Get the next LogicalDisplay object in the linked list /// @return Pointer to the next LogicalDisplay object LogicalDisplay *getNext(); diff --git a/PhysicalScreen.cpp b/PhysicalScreen.cpp index 1cb32b7..797e020 100644 --- a/PhysicalScreen.cpp +++ b/PhysicalScreen.cpp @@ -2,6 +2,9 @@ #include "PhysicalScreen.h" #include +PhysicalScreen *PhysicalScreen::_first = nullptr; +uint8_t PhysicalScreen::_screenCount = 0; + PhysicalScreen::PhysicalScreen() { _firstDisplay = nullptr; _activeDisplay = nullptr; @@ -9,14 +12,57 @@ PhysicalScreen::PhysicalScreen() { _lastSwitchTime = 0; _maxRows = 0; _maxRowLength = 0; + _fontHeight = 0; + _fontWidth = 0; + _screenNumber = _screenCount++; + if (!_first) { + _first = this; + _next = nullptr; + } else { + for (PhysicalScreen *screen = PhysicalScreen::getFirst(); screen; screen = screen->_next) { + if (!screen->_next) { + screen->_next = this; + } + } + } } +PhysicalScreen *PhysicalScreen::getFirst() { return _first; } + +PhysicalScreen *PhysicalScreen::getNext() { return _next; } + void PhysicalScreen::addDisplay(uint8_t displayNumber, uint16_t defaultTextColour, uint16_t defaultBackgroundColour) { - + // Create a new display + LogicalDisplay *display = + new LogicalDisplay(displayNumber, _maxRowLength, _maxRows, defaultTextColour, defaultBackgroundColour); + + // Find previous display + LogicalDisplay *previous = nullptr; + for (auto peek = _firstDisplay; peek; peek = peek->getNext()) { + if (peek->getDisplayNumber() > displayNumber) { + break; + } + previous = peek; + } + if (previous) { + // If there's a previous display, chain after it + display->setNext(previous->getNext()); + previous->setNext(display); + } else { + // Put at start of list + display->setNext(_firstDisplay); + _firstDisplay = display; + } + if (!_activeDisplay) { + _activeDisplay = display; + } + _displayCount++; } LogicalDisplay *PhysicalScreen::getFirstDisplay() { return _firstDisplay; } +void PhysicalScreen::setActiveDisplay(LogicalDisplay *activeDisplay) { _activeDisplay = activeDisplay; } + LogicalDisplay *PhysicalScreen::getActiveDisplay() { return _activeDisplay; } bool PhysicalScreen::displayNumberExists(uint8_t displayNumber) { return getDisplayByNumber(displayNumber) != nullptr; } @@ -73,6 +119,8 @@ void PhysicalScreen::autoSwitch(unsigned long switchDelay) { } void PhysicalScreen::processActiveDisplay() { + if (!_activeDisplay) + return; if (_activeDisplay->needsRedraw()) { clearScreen(_activeDisplay->getDefaultBackgroundColour()); } @@ -89,3 +137,9 @@ void PhysicalScreen::processActiveDisplay() { } _activeDisplay->setRedraw(false); } + +uint8_t PhysicalScreen::getScreenNumber() { return _screenNumber; } + +uint8_t PhysicalScreen::getMaxRows() { return _maxRows; } + +uint8_t PhysicalScreen::getMaxRowLength() { return _maxRowLength; } diff --git a/PhysicalScreen.h b/PhysicalScreen.h index 75ffa6d..7c93f04 100644 --- a/PhysicalScreen.h +++ b/PhysicalScreen.h @@ -19,16 +19,16 @@ class PhysicalScreen { /// @param rotation Rotate the screen if necessary /// @param textSize Pixel multiplier to increase text size if desired /// @param backgroundColour Fill the screen with this colour during setup - virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour); + virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) = 0; /// @brief Virtual function to implement to clear the entire screen /// @param backgroundColour Valid colour to set the entire screen to - virtual void clearScreen(uint16_t backgroundColour); + virtual void clearScreen(uint16_t backgroundColour) = 0; /// @brief Virtual function to implement to clear the specified row /// @param row Row number to clear, 0 - 255 /// @param backgroundColour Valid colour to set the row to - virtual void clearRow(uint8_t row, uint16_t backgroundColour); + virtual void clearRow(uint8_t row, uint16_t backgroundColour) = 0; /// @brief Virtual function to implement to write a row of text to the physical screen /// @param row Row on screen, 0 - 255 (not pixels) @@ -38,7 +38,7 @@ class PhysicalScreen { /// @param maxLength Maximum number of columns (not pixels) that can fit on the screen /// @param message Char array containing the text to display virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message, bool underlined); + char *message, bool underlined) = 0; /// @brief Virtual function to implement to write a horizontal line on the specified row /// @param row Row on screen, 0 - 255 (not pixels) @@ -48,9 +48,17 @@ class PhysicalScreen { /// @param lineColour Valid colour for the line /// @param backgroundColour Valid colour for the background virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, - uint16_t backgroundColour); + uint16_t backgroundColour) = 0; - /// @brief Add a new LogicalDisplay instance to be displayed on this screen + /// @brief Get the first screen + /// @return Pointer to the first PhysicalScreen instance + static PhysicalScreen *getFirst(); + + /// @brief Get the next screen in the list + /// @return Pointer to the next PhysicalScreen instance + PhysicalScreen *getNext(); + + /// @brief Add a new LogicalDisplay instance to be displayed on this screen, ordered by display number /// @param displayNumber Display ID for the instance void addDisplay(uint8_t displayNumber, uint16_t defaultTextColour, uint16_t defaultBackgroundColour); @@ -58,14 +66,14 @@ class PhysicalScreen { /// @return Pointer to the first LogicalDisplay instance LogicalDisplay *getFirstDisplay(); - /// @brief Get the active LogicalDisplay instance that should display on this screen - /// @return Pointer to the active LogicalDisplay instance - LogicalDisplay *getActiveDisplay(); - /// @brief Set the active LogicalDisplay instance to display on this screen /// @param activeDisplay Pointer to the LogicalDisplay instance to mark as active void setActiveDisplay(LogicalDisplay *activeDisplay); + /// @brief Get the active LogicalDisplay instance that should display on this screen + /// @return Pointer to the active LogicalDisplay instance + LogicalDisplay *getActiveDisplay(); + /// @brief Check if there is already a display created at the specified number /// @param displayNumber True|False /// @return @@ -89,13 +97,32 @@ class PhysicalScreen { /// @brief Call this method as often as possible to ensure this physical screen is updated correctly void processActiveDisplay(); + /// @brief Get this screen instance's number + /// @return 0 - 255 + uint8_t getScreenNumber(); + + /// @brief Get the maximum number of rows that will fit on this screen + /// @return 0 - 255 + uint8_t getMaxRows(); + + /// @brief Get the maximum number of characters that will fit on this screen + /// @return 0 - 255; + uint8_t getMaxRowLength(); + protected: + PhysicalScreen *_next; // Pointer to the next screen instance LogicalDisplay *_firstDisplay; // Pointer to the first associated logical display LogicalDisplay *_activeDisplay; // Current logical display this physical screen needs to show uint8_t _displayCount; // Number of logical displays associated with this screen unsigned long _lastSwitchTime; // Last time an auto switch to the next display instance occurred uint8_t _maxRows; // Calculated maximum number of rows that will fit on screen based on font size uint8_t _maxRowLength; // Calculated maximum number of characters that will fit on screen based on font size + uint8_t _fontHeight; // Calculated height of the font to determine row count + uint8_t _fontWidth; // Calculated width of the font to determine row length + uint8_t _screenNumber; // Number of this screen + + static PhysicalScreen *_first; // Pointer to the first screen instance + static uint8_t _screenCount; // Count of screen instances }; #endif diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index c343cc2..1d5e957 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -12,14 +12,14 @@ void TFT_eSPIScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t ba _tft.fillScreen(backgroundColour); _tft.setFreeFont(gfxFont); _tft.setTextSize(textSize); - fontHeight = gfxFont->yAdvance; - fontWidth = _tft.textWidth("A"); - maxRows = _tft.height() / fontHeight; - maxColumns = _tft.width() / fontWidth; - CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); - CONSOLE.print(fontHeight); + _fontHeight = gfxFont->yAdvance; + _fontWidth = _tft.textWidth("A"); + _maxRows = _tft.height() / _fontHeight; + _maxRowLength = _tft.width() / _fontWidth; + CONSOLE.print(F("Setup done: _fontHeight|_fontWidth|_tft.Height()|_tft.Width(): ")); + CONSOLE.print(_fontHeight); CONSOLE.print(F("|")); - CONSOLE.print(fontWidth); + CONSOLE.print(_fontWidth); CONSOLE.print(F("|")); CONSOLE.print(_tft.height()); CONSOLE.print(F("|")); @@ -30,33 +30,33 @@ void TFT_eSPIScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(ba void TFT_eSPIScreen::clearRow(uint8_t row, uint16_t backgroundColour) { int32_t x = 0; - int32_t y = (row * fontHeight) + row; - int32_t w = fontWidth * maxColumns; - int32_t h = fontHeight; + int32_t y = (row * _fontHeight) + row; + int32_t w = _fontWidth * _maxRowLength; + int32_t h = _fontHeight; _tft.fillRect(x, y, w, h, backgroundColour); } void TFT_eSPIScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message, bool underlined) { - uint16_t textRow = (row * fontHeight) + row; - uint16_t width = fontWidth * maxLength; + uint16_t y = (row * _fontHeight) + row; + uint16_t width = _fontWidth * maxLength; _tft.setTextPadding(width); _tft.setTextColor(fontColour, backgroundColour); if (underlined) { - _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); + _tft.drawLine(column, y + _fontHeight, width, y + _fontHeight, fontColour); } else { - _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, backgroundColour); + _tft.drawLine(column, y + _fontHeight, width, y + _fontHeight, backgroundColour); } - _tft.drawString(message, column, textRow); + _tft.drawString(message, column, y); } void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) { // Horizontal start/end int32_t x1 = column; - int32_t x2 = fontWidth * lineLength; + int32_t x2 = _fontWidth * lineLength; // Vertical start - half way up the font height - int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int32_t y1 = (row * _fontHeight) + row + (_fontHeight / 2); int32_t y2 = y1; clearRow(row, backgroundColour); _tft.drawLine(x1, y1, x2, y2, lineColour); From 3baeb3f27d030d51253810ce9894b71c11ff84b6 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 23 May 2024 09:14:23 +1000 Subject: [PATCH 068/146] Update version, update MCU and OLED --- EXDisplayClass.cpp.txt | 275 ----------------------------------------- EXDisplayClass.h.txt | 135 -------------------- EXScreen.h.txt | 75 ----------- MCUFriendScreen.cpp | 44 +++---- MCUFriendScreen.h | 4 +- OLEDScreen.cpp | 32 ++--- OLEDScreen.h | 4 +- version.h | 6 +- 8 files changed, 45 insertions(+), 530 deletions(-) delete mode 100644 EXDisplayClass.cpp.txt delete mode 100644 EXDisplayClass.h.txt delete mode 100644 EXScreen.h.txt diff --git a/EXDisplayClass.cpp.txt b/EXDisplayClass.cpp.txt deleted file mode 100644 index bcac05b..0000000 --- a/EXDisplayClass.cpp.txt +++ /dev/null @@ -1,275 +0,0 @@ -#include "EXDisplayClass.h" - -/// @brief Define the first EXDisplay object as a nullptr -EXDisplay *EXDisplay::_first = nullptr; - -/// @brief Define the active display as nullptr also -EXDisplay *EXDisplay::_activeDisplay = nullptr; - -/// @brief Define initial last switch time as 0 -unsigned long EXDisplay::_lastSwitchTime = 0; - -/// @brief Count of displays -uint8_t EXDisplay::_displayCount = 0; - -/* - * EXDisplay class implementation - */ -EXDisplay::EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScreenWidth) - : _displayNumber(displayNumber), _exScreen(exScreen), _maxScreenWidth(maxScreenWidth) { - _firstRow = nullptr; - _next = _first; - _first = this; - _maxRowNumber = 0; - _numberOfRows = 0; - _scrollPosition = 0; - _lastScrollTime = 0; - _needsRedraw = false; - if (!_activeDisplay) { - _activeDisplay = _first; - } - _displayCount++; -} - -EXDisplay *EXDisplay::getFirst() { return _first; } - -EXDisplay *EXDisplay::getNext() { return _next; } - -EXDisplayRow *EXDisplay::getFirstRow() { return _firstRow; } - -uint8_t EXDisplay::getDisplayNumber() { return _displayNumber; } - -EXDisplayRow *EXDisplay::getRowByNumber(uint8_t rowNumber) { - for (auto *row = _firstRow; row; row = row->getNext()) { - if (row->getRowNumber() == rowNumber) { - return row; - } - } - return nullptr; -} - -void EXDisplay::updateRow(uint8_t rowNumber, char *rowText) { - auto *row = getRowByNumber(rowNumber); - if (row && strlen(rowText) == 0) { - _deleteRow(row); - } else if (!row && strlen(rowText) == 0) { - return; - } else if (!row) { - row = _addRow(rowNumber, rowText); - } else { - row->setRowText(rowText); - } -} - -void EXDisplay::scrollUp() { - // Scroll up logic: - // _scrollPosition needs to decrement to bring lower rows up the screen - // If _scrollPosition ends at 0, it should become the highest possible row - uint8_t lastRow = _exScreen->maxRows - 1; // Highest possible row number on screen - if (_maxRowNumber <= lastRow) { // If our max row number is on screen, no scroll required - return; - } - if (_scrollPosition == 0) { // If row 0 is top of screen, need to move to the highest row number - _scrollPosition = _maxRowNumber; - } else { // - _scrollPosition--; - } - for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { - uint8_t newRow = row->getDisplayRow(); - if (newRow == _maxRowNumber) { // If row at bottom, it becomes first row - newRow = 0; - } else { // Otherwise move down one row - newRow++; - } - row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); - } - _needsRedraw = true; // Need to redraw after each scroll -} - -void EXDisplay::scrollDown() { - uint8_t lastRow = _exScreen->maxRows - 1; // Highest possible row number on screen - if (_maxRowNumber <= lastRow) { // If our max row number is on screen, no scroll required - return; - } - if (_scrollPosition >= lastRow) { // If last row is top of screen, goes to bottom - _scrollPosition = 0; - } else { // Otherwise next row is top of screen - _scrollPosition++; - } - for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { - uint8_t newRow = row->getDisplayRow(); - if (newRow == 0) { // If row at top of screen, it becomes last row - newRow = _maxRowNumber; - } else { // Otherwise move up one row - newRow--; - } - row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); - } - _needsRedraw = true; // Need to redraw after each scroll -} - -void EXDisplay::autoScroll(unsigned long scrollDelay) { - if (millis() - _lastScrollTime > scrollDelay) { - _lastScrollTime = millis(); - scrollDown(); - } -} - -EXScreen *EXDisplay::getEXScreen() { return _exScreen; } - -uint8_t EXDisplay::getScreenMaxRows() { return _exScreen->maxRows; } - -uint8_t EXDisplay::getScreenMaxColumns() { return _exScreen->maxColumns; } - -bool EXDisplay::needsRedraw() { return _needsRedraw; } - -void EXDisplay::resetRedraw() { _needsRedraw = false; } - -bool EXDisplay::displayNumberExists(uint8_t displayNumber) { return getDisplayByNumber(displayNumber) != nullptr; } - -EXDisplay *EXDisplay::getDisplayByNumber(uint8_t displayNumber) { - for (auto *display = _first; display; display = display->_next) { - if (display->_displayNumber == displayNumber) { - return display; - } - } - return nullptr; -} - -EXDisplay *EXDisplay::getActiveDisplay() { return _activeDisplay; } - -void EXDisplay::setNextDisplay() { - if (!_activeDisplay) { - _activeDisplay = _first; - _activeDisplay->_needsRedraw = true; - return; - } - if (_displayCount == 1) { - return; - } - if (_activeDisplay->_next) { - _activeDisplay = _activeDisplay->_next; - } else { - _activeDisplay = _first; - } - _activeDisplay->_needsRedraw = true; -} - -void EXDisplay::setPreviousDisplay() { - if (!_activeDisplay) { - _activeDisplay = _first; - _activeDisplay->_needsRedraw = true; - return; - } - if (_displayCount == 1) { - return; - } - for (EXDisplay *display = _activeDisplay; display; display = display->getNext()) { - if (display->getNext() == _activeDisplay) { - _activeDisplay = display; - _activeDisplay->_needsRedraw = true; - return; - } - } -} - -void EXDisplay::autoSwitch(unsigned long switchDelay) { - if (millis() - EXDisplay::_lastSwitchTime > switchDelay) { - EXDisplay::_lastSwitchTime = millis(); - setNextDisplay(); - } -} - -void EXDisplay::processDisplay() { - if (_needsRedraw) { - _exScreen->clearScreen(BACKGROUND_COLOUR); - } - for (EXDisplayRow *row = _firstRow; row; row = row->getNext()) { - if (row->needsRender() && (row->isChanged() || _needsRedraw)) { - if (row->isLine()) { - _exScreen->writeLine(row->getDisplayRow(), 0, _exScreen->maxColumns, row->getTextColour(), - row->getBackgroundColour()); - } else { - _exScreen->writeRow(row->getDisplayRow(), 0, row->getTextColour(), row->getBackgroundColour(), - _exScreen->maxColumns, row->getRowText(), row->isUnderlined()); - } - } - } - _needsRedraw = false; -} - -EXDisplayRow *EXDisplay::_addRow(uint8_t rowNumber, char *rowText) { - // create a new row and chain it in - EXDisplayRow *row = new EXDisplayRow(rowNumber); - _numberOfRows++; - - // find the row prior to the one we want to add - EXDisplayRow *previous = nullptr; - for (auto peek = _firstRow; peek; peek = peek->getNext()) { - if (peek->getRowNumber() > rowNumber) - break; - previous = peek; - } - if (previous) { - // chain after previous - row->setNext(previous->getNext()); - previous->setNext(row); - } else { - // chain at start of list - row->setNext(_firstRow); - _firstRow = row; - } - if (rowNumber > _maxRowNumber) { - _maxRowNumber = rowNumber; - } - row->setColours(TEXT_COLOUR, BACKGROUND_COLOUR); - row->setRowText(rowText); - row->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); - return row; -} - -void EXDisplay::_deleteRow(EXDisplayRow *row) { - if (!row) { - return; // Return if the row is nullptr - } - - // Find the previous node in the linked list - EXDisplayRow *previous = nullptr; - EXDisplayRow *current = _firstRow; - while (current != row) { - previous = current; - current = current->getNext(); - } - - // Remove the node from the linked list - if (previous) { - previous->setNext(row->getNext()); - } else { - _firstRow = row->getNext(); - } - - // Decrement the number of rows - _numberOfRows--; - - // Update the maximum row number if necessary - if (row->getRowNumber() == _maxRowNumber) { - _maxRowNumber = 0; - for (EXDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { - if (temp->getRowNumber() > _maxRowNumber) { - _maxRowNumber = temp->getRowNumber(); - } - } - } - - // If we're now within the confines of the screen, need to reset display rows and redraw - if (_maxRowNumber <= _exScreen->maxRows) { - _scrollPosition = 0; - for (EXDisplayRow *temp = _firstRow; temp; temp = temp->getNext()) { - temp->setDisplayRow(_scrollPosition, _exScreen->maxRows, _maxRowNumber); - } - _needsRedraw = true; - } - - // Delete the row object - delete row; -} diff --git a/EXDisplayClass.h.txt b/EXDisplayClass.h.txt deleted file mode 100644 index b1adc56..0000000 --- a/EXDisplayClass.h.txt +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef EXDISPLAYCLASS_H -#define EXDISPLAYCLASS_H - -#include "Defines.h" -#include "EXDisplayRow.h" -#include "EXScreen.h" -#include - -/** - * @brief Class for each display. - * Each display is in a linked list, with associated rows in a linked list as an attribute of the EXDisplay object. - * - */ -class EXDisplay { -public: - /// @brief Constructor for the EXDisplay class - /// @param displayNumber The ID of this display, 0 - 254 - /// @param exScreen Pointer to an associated EXScreen object to use for the physical display - /// @param maxScreenWidth Maximum number of characters that will fit on the physical screen, 0 - 255 - EXDisplay(uint8_t displayNumber, EXScreen *exScreen, uint8_t maxScreenWidth); - - /// @brief Get the first EXDisplay object in the linked list - /// @return Pointer to the first EXDisplay object - static EXDisplay *getFirst(); - - /// @brief Get the next EXDisplay object in the linked list - /// @return Pointer to the next EXDisplay object - EXDisplay *getNext(); - - /// @brief Get the first EXDisplayRow object associated with this display - /// @return Pointer to the first EXDisplayRow object for this display - EXDisplayRow *getFirstRow(); - - /// @brief Get the display's number - /// @return 0 - 255 - uint8_t getDisplayNumber(); - - /// @brief Get an EXDisplayRow object for this display by the specified row number - /// @param rowNumber Row number to retrieve, 0 - 255 - /// @return Pointer to an EXDisplayRow object, or nullptr if not exists - EXDisplayRow *getRowByNumber(uint8_t rowNumber); - - /// @brief Update text and ticker for the specified row number, will add if it doesn't exist - /// @param rowNumber Row number to display text on, 0 - 255 - /// @param rowText Char array of text for the row - void updateRow(uint8_t rowNumber, char *rowText); - - /// @brief Scroll up one row vertically - void scrollUp(); - - /// @brief Scroll down one row vertically - void scrollDown(); - - /// @brief Call this method as often as possible to support timed vertical scrolling - /// @param scrollDelay Time in milliseconds between vertical scrolling updates - void autoScroll(unsigned long scrollDelay); - - /// @brief Get the EXScreen object associated with this display - /// @return Pointer to the associated EXScreen object - EXScreen *getEXScreen(); - - /// @brief Get the maximum number of rows displayable on the associated screen - /// @return 0 - 255 - uint8_t getScreenMaxRows(); - - /// @brief Get the maximum number of columns displayable on the associated screen - /// @return 0 - 255 - uint8_t getScreenMaxColumns(); - - /// @brief Check if this display needs to be redrawn - /// @return True|False - bool needsRedraw(); - - /// @brief Reset the needsRedraw flag - void resetRedraw(); - - /// @brief Check if there is already a display created at the specified number - /// @param displayNumber True|False - /// @return - static bool displayNumberExists(uint8_t displayNumber); - - /// @brief Get the display and associated row linked list for the specified display number - /// @param displayNumber Display number to get, 0 - 255 - /// @return EXDisplay object, or nullptr if not exists - static EXDisplay *getDisplayByNumber(uint8_t displayNumber); - - /// @brief Get the currently selected display - /// @return Pointer to the currently selected display - static EXDisplay *getActiveDisplay(); - - /// @brief Switch active display to the next display in the linked list - static void setNextDisplay(); - - /// @brief Switch active display to the previous display in the linked list - static void setPreviousDisplay(); - - /// @brief Call this method as often as possible to support timed display switching - /// @param switchDelay Time in milliseconds before switching displays - static void autoSwitch(unsigned long switchDelay); - - /// @brief Call this method as often as possible to ensure a physical screen is updated correctly - /// @param display Pointer to the EXDisplay object that needs to have it's physical screen updated - void processDisplay(); - -private: - // chaining displays - static EXDisplay *_first; - EXDisplay *_next; - // display data and rows - uint8_t _displayNumber; - EXDisplayRow *_firstRow; - EXScreen *_exScreen; - uint8_t _maxRowNumber; - // Screen management variables added here - uint8_t _maxScreenWidth; // Maximum number of chars that can fit on the physical screen - uint8_t _numberOfRows; // Calculated number of rows for this screen - uint8_t _scrollPosition; // Row number that is top of screen for scrolling support - unsigned long _lastScrollTime; // Last time in milliseconds an auto scroll was done - static unsigned long _lastSwitchTime; // Last time in milliseconds an auto switch was done - bool _needsRedraw; // Flag if this display needs to be redrawn - static EXDisplay *_activeDisplay; // Pointer to the current active display - static uint8_t _displayCount; - - /// @brief Private method to add a row - /// @param rowNumber 0 - 255 - /// @param rowText Pointer to the char array containing the text for this row - /// @return Pointer to the created EXDisplayRow object - EXDisplayRow *_addRow(uint8_t rowNumber, char *rowText); - - /// @brief Delete the specified row number - /// @param rowNumber Row number to delete, 0 - 255 - void _deleteRow(EXDisplayRow *row); -}; - -#endif diff --git a/EXScreen.h.txt b/EXScreen.h.txt deleted file mode 100644 index c178d2f..0000000 --- a/EXScreen.h.txt +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef EXSCREEN_H -#define EXSCREEN_H - -#include "Defines.h" -#include -#if SCREEN_TYPE == MCU -#include -#elif SCREEN_TYPE == TFT -#include -#endif - -/// @brief This EXScreen class is designed to be extended by other screen classes that define the methods to perform the -/// requesite activities according to the library in use to drive the physical display. -/// This allows all physical screen methods to be consistent regardless of the library or driver in use, allowing this -/// code to support multiple different display types without needing to have the main functions call different -/// libraries/methods. As this is a virtual only class, every virtual method must be declared and defined in the class -/// that extends this. -class EXScreen { -public: - /// @brief Constructor for a new EXScreen object - EXScreen() { - fontHeight = 0; - maxRows = 0; - maxColumns = 0; - } - - /// @brief Virtual function to implement to setup the physical screen parameters - /// @param rotation Rotate the screen if necessary - /// @param textSize Pixel multiplier to increase text size if desired - /// @param backgroundColour Fill the screen with this colour during setup - virtual void setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour); - - /// @brief Virtual function to implement to clear the entire screen - /// @param backgroundColour Valid colour to set the entire screen to - virtual void clearScreen(uint16_t backgroundColour); - - /// @brief Virtual function to implement to clear the specified row - /// @param row Row number to clear, 0 - 255 - /// @param backgroundColour Valid colour to set the row to - virtual void clearRow(uint8_t row, uint16_t backgroundColour); - - /// @brief Virtual function to implement to write a row of text to the physical screen - /// @param row Row on screen, 0 - 255 (not pixels) - /// @param column Column on screen, 0 - 255 (not pixels) - /// @param fontColour Valid colour for the text - /// @param backgroundColour Valid colour for the background - /// @param maxLength Maximum number of columns (not pixels) that can fit on the screen - /// @param message Char array containing the text to display - virtual void writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, - char *message, bool underlined); - - /// @brief Virtual function to implement to write a horizontal line on the specified row - /// @param row Row on screen, 0 - 255 (not pixels) - /// @param column Column to start the line, 0 - 255 (not pixels) - /// @param lineWidth Pixel width to make the line - /// @param lineLength Number of columns for the line (not pixels), 0 - 255 - /// @param lineColour Valid colour for the line - /// @param backgroundColour Valid colour for the background - virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, - uint16_t backgroundColour); - - /// @brief Height of the font in use to determine row height - uint8_t fontHeight; - - /// @brief Width of the font in use to determine max columns - uint8_t fontWidth; - - /// @brief Maximum number of rows this screen can physically display - uint8_t maxRows; - - /// @brief Maximum number of columns this screen can physically display - uint8_t maxColumns; -}; - -#endif diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index afd3b9b..123808a 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -3,7 +3,7 @@ #include "MCUFriendScreen.h" -MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : EXScreen(), _tft(tft) {} +MCUFriendScreen::MCUFriendScreen(MCUFRIEND_kbv &tft) : PhysicalScreen(), _tft(tft) {} void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgroundColour) { @@ -28,27 +28,23 @@ void MCUFriendScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t b _tft.invertDisplay(screenId); #endif _tft.fillScreen(backgroundColour); - fontHeight = gfxFont->yAdvance; - fontWidth = getCharacterWidth("A"); - maxRows = _tft.height() / fontHeight; - maxColumns = _tft.width() / fontWidth; + _fontHeight = gfxFont->yAdvance; + _fontWidth = getCharacterWidth("A"); + _maxRows = _tft.height() / _fontHeight; + _maxRowLength = _tft.width() / _fontWidth; CONSOLE.println(F("\n~~ SETUP PARAMETERS ~~")); CONSOLE.print(F("MCUFRIEND_kbv parameters: _tft.height()|_tft.width(): ")); CONSOLE.print(_tft.height()); CONSOLE.print(F("|")); CONSOLE.println(_tft.width()); - CONSOLE.print(F("config.h parameters DISPLAY_HEIGHT|DISPLAY_WIDTH: ")); - CONSOLE.print(SCREEN_HEIGHT); + CONSOLE.print(F("_maxRows|_maxRowLength|_fontHeight|_fontWidth: ")); + CONSOLE.print(_maxRows); CONSOLE.print(F("|")); - CONSOLE.println(SCREEN_WIDTH); - CONSOLE.print(F("maxRows|maxColumns|fontHeight|fontWidth: ")); - CONSOLE.print(maxRows); + CONSOLE.print(_maxRowLength); CONSOLE.print(F("|")); - CONSOLE.print(maxColumns); + CONSOLE.print(_fontHeight); CONSOLE.print(F("|")); - CONSOLE.print(fontHeight); - CONSOLE.print(F("|")); - CONSOLE.println(fontWidth); + CONSOLE.println(_fontWidth); CONSOLE.println(F("~~ END SETUP PARAMETERS ~~\n")); } @@ -62,24 +58,24 @@ uint8_t MCUFriendScreen::getCharacterWidth(const char *character) { void MCUFriendScreen::clearScreen(uint16_t backgroundColour) { _tft.fillScreen(backgroundColour); } void MCUFriendScreen::clearRow(uint8_t row, uint16_t backgroundColour) { - uint16_t textRow = ((row + 1) * fontHeight); + uint16_t textRow = ((row + 1) * _fontHeight); int32_t x = 0; - int32_t y = ((textRow - fontHeight) + 10); - int32_t w = fontWidth * maxColumns; - int32_t h = fontHeight; + int32_t y = ((textRow - _fontHeight) + 10); + int32_t w = _fontWidth * _maxRowLength; + int32_t h = _fontHeight; _tft.fillRect(x, y, w, h, backgroundColour); } void MCUFriendScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message, bool underlined) { - uint16_t textRow = ((row + 1) * fontHeight); - uint16_t width = fontWidth * maxLength; - _tft.fillRect(1, ((textRow - fontHeight) + 10), _tft.width(), (fontHeight), backgroundColour); + uint16_t textRow = ((row + 1) * _fontHeight); + uint16_t width = _fontWidth * maxLength; + _tft.fillRect(1, ((textRow - _fontHeight) + 10), _tft.width(), (_fontHeight), backgroundColour); _tft.setTextColor(fontColour, backgroundColour); _tft.setCursor(1, textRow); _tft.print(message); if (underlined) { - _tft.drawLine(column, textRow + fontHeight, width, textRow + fontHeight, fontColour); + _tft.drawLine(column, textRow + _fontHeight, width, textRow + _fontHeight, fontColour); } CONSOLE.println(F("\n~~ WRITE ROW PARAMETERS ~~")); CONSOLE.print(F("textRow|width: ")); @@ -93,9 +89,9 @@ void MCUFriendScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t backgroundColour) { // Horizontal start/end int32_t x1 = column; - int32_t x2 = fontWidth * lineLength; + int32_t x2 = _fontWidth * lineLength; // Vertical start - half way up the font height - int32_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int32_t y1 = (row * _fontHeight) + row + (_fontHeight / 2); int32_t y2 = y1; clearRow(row, backgroundColour); _tft.drawLine(x1, y1, x2, y2, lineColour); diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 6b22327..37cca38 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -4,12 +4,12 @@ #ifndef MCUFRIENDSCREEN_H #define MCUFRIENDSCREEN_H -#include "EXScreen.h" +#include "PhysicalScreen.h" #include #include #include -class MCUFriendScreen : public EXScreen { +class MCUFriendScreen : public PhysicalScreen { public: MCUFriendScreen(MCUFRIEND_kbv &tft); diff --git a/OLEDScreen.cpp b/OLEDScreen.cpp index 4b0ef41..213b660 100644 --- a/OLEDScreen.cpp +++ b/OLEDScreen.cpp @@ -4,7 +4,7 @@ #if SCREEN_TYPE == OLED_SSD1306 OLEDScreen::OLEDScreen(Adafruit_SSD1306 &oled, uint8_t muxAddress, uint8_t subBus) - : EXScreen(), _oled(oled), _muxAddress(muxAddress), _subBus(subBus) {} + : PhysicalScreen(), _oled(oled), _muxAddress(muxAddress), _subBus(subBus) {} #elif SCREEN_TYPE == OLED_SH1106 OLEDScreen::OLEDScreen(Adafruit_SH1106G &oled, uint8_t muxAddress, uint8_t subBus) : EXScreen(), _oled(oled), _muxAddress(muxAddress), _subBus(subBus) {} @@ -23,14 +23,14 @@ void OLEDScreen::setupScreen(uint8_t rotation, uint8_t textSize, uint16_t backgr _oled.setTextWrap(false); _oled.clearDisplay(); _oled.display(); - fontHeight = gfxFont->yAdvance; - fontWidth = _getTextWidth(); - maxRows = _oled.height() / fontHeight; - maxColumns = _oled.width() / fontWidth; - CONSOLE.print(F("Setup done: fontHeight|fontWidth|tftHeight|tftWidth: ")); - CONSOLE.print(fontHeight); + _fontHeight = gfxFont->yAdvance; + _fontWidth = _getTextWidth(); + _maxRows = _oled.height() / _fontHeight; + _maxRowLength = _oled.width() / _fontWidth; + CONSOLE.print(F("Setup done: _fontHeight|_fontWidth|_oled.Height|_oled.Width: ")); + CONSOLE.print(_fontHeight); CONSOLE.print(F("|")); - CONSOLE.print(fontWidth); + CONSOLE.print(_fontWidth); CONSOLE.print(F("|")); CONSOLE.print(_oled.height()); CONSOLE.print(F("|")); @@ -44,9 +44,9 @@ void OLEDScreen::clearScreen(uint16_t backgroundColour) { void OLEDScreen::clearRow(uint8_t row, uint16_t backgroundColour) { int16_t x = 0; - int16_t y = (row * fontHeight) + row; - int16_t w = fontWidth * maxColumns; - int16_t h = fontHeight; + int16_t y = (row * _fontHeight) + row; + int16_t w = _fontWidth * _maxRowLength; + int16_t h = _fontHeight; _oled.fillRect(x, y, w, h, backgroundColour); _oled.display(); } @@ -54,14 +54,14 @@ void OLEDScreen::clearRow(uint8_t row, uint16_t backgroundColour) { void OLEDScreen::writeRow(uint8_t row, uint8_t column, uint16_t fontColour, uint16_t backgroundColour, uint8_t maxLength, char *message, bool underlined) { uint16_t x = column; - uint16_t y = (row * fontHeight) + fontHeight; + uint16_t y = (row * _fontHeight) + _fontHeight; _oled.setTextColor(fontColour); _oled.setCursor(x, y); _oled.print(message); if (underlined) { - _oled.drawLine(column, y+1, _oled.width(), y+1, fontColour); + _oled.drawLine(column, y + 1, _oled.width(), y + 1, fontColour); } else { - _oled.drawLine(column, y+1, _oled.width(), y+1, backgroundColour); + _oled.drawLine(column, y + 1, _oled.width(), y + 1, backgroundColour); } _oled.display(); CONSOLE.print(F("\nwriteRow textRow|message: ")); @@ -74,9 +74,9 @@ void OLEDScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint uint16_t backgroundColour) { // Horizontal start/end int16_t x1 = column; - int16_t x2 = fontWidth * lineLength; + int16_t x2 = _fontWidth * lineLength; // Vertical start - half way up the font height - int16_t y1 = (row * fontHeight) + row + (fontHeight / 2); + int16_t y1 = (row * _fontHeight) + row + (_fontHeight / 2); int16_t y2 = y1; clearRow(row, backgroundColour); _oled.drawLine(x1, y1, x2, y2, lineColour); diff --git a/OLEDScreen.h b/OLEDScreen.h index 3f04e6b..db29c55 100644 --- a/OLEDScreen.h +++ b/OLEDScreen.h @@ -4,7 +4,7 @@ #ifndef OLEDSCREEN_H #define OLEDSCREEN_H -#include "EXScreen.h" +#include "PhysicalScreen.h" #include #include #include @@ -12,7 +12,7 @@ #include /// @brief Class to drive monochrome OLEDs with EX-Display, noting all colours are ignored -class OLEDScreen : public EXScreen { +class OLEDScreen : public PhysicalScreen { public: #if SCREEN_TYPE == OLED_SSD1306 OLEDScreen(Adafruit_SSD1306 &oled, uint8_t muxAddress = 0, uint8_t subBus = 255); diff --git a/version.h b/version.h index 854972c..65c12c4 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,12 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.9" +#define VERSION "0.0.10" +// 0.0.10 includes: +// - Refactor so that logical displays are attributes of physical screens +// - This should simplify addition of touch/input control +// - Ensure order of logical displays in linked list are in ascending order of number // 0.0.9 includes: // - Add support for SSD1306 and SH1106 I2C connected OLEDs // - Disable text wrap From 19ac0d9e93a95681f442b4ff0fa653a3adde3c40 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Thu, 23 May 2024 10:10:39 +1000 Subject: [PATCH 069/146] Enable startupPhase check --- EX-Display.ino | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EX-Display.ino b/EX-Display.ino index 6d0ade9..2384675 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -45,7 +45,7 @@ void setup() { screen->addDisplay(DISPLAY_1_ID, TEXT_COLOUR, BACKGROUND_COLOUR); #endif #if defined(DISPLAY_2_ID) -screen->addDisplay(DISPLAY_2_ID, TEXT_COLOUR, BACKGROUND_COLOUR); + screen->addDisplay(DISPLAY_2_ID, TEXT_COLOUR, BACKGROUND_COLOUR); #endif #if defined(DISPLAY_3_ID) screen->addDisplay(DISPLAY_3_ID, TEXT_COLOUR, BACKGROUND_COLOUR); @@ -96,6 +96,8 @@ void loop() { // No data incoming so see if we need to display anything // DISABLE IN STARTUPPHASE else { - updateScreen(); + if (!StartupPhase) { + updateScreen(); + } } } From bec2f73ed5bc468a43ce7bc60aea5a0f057ffe64 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Fri, 24 May 2024 05:30:07 +1000 Subject: [PATCH 070/146] Brief start --- InputMethod.cpp | 8 ++++++++ InputMethod.h | 36 ++++++++++++++++++++++++++++++++++++ TFT_eSPITouch.cpp | 8 ++++++++ TFT_eSPITouch.h | 23 +++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 InputMethod.cpp create mode 100644 InputMethod.h create mode 100644 TFT_eSPITouch.cpp create mode 100644 TFT_eSPITouch.h diff --git a/InputMethod.cpp b/InputMethod.cpp new file mode 100644 index 0000000..72c3e25 --- /dev/null +++ b/InputMethod.cpp @@ -0,0 +1,8 @@ +#include "Defines.h" +#include "InputMethod.h" + +InputMethod *InputMethod::_first = nullptr; + +InputMethod::InputMethod() { _next = nullptr; } + +void InputMethod::setScreen(PhysicalScreen *screen) { _screen = screen; } diff --git a/InputMethod.h b/InputMethod.h new file mode 100644 index 0000000..06759f3 --- /dev/null +++ b/InputMethod.h @@ -0,0 +1,36 @@ +#ifndef INPUTMETHOD_H +#define INPUTMETHOD_H + +#include "Defines.h" +#include "PhysicalScreen.h" +#include + +/* +This class is to abstract input methods from controlling the physical screen. + +This class should be extended by hardware specific classes that implement the virtual methods in this class to interact +with a physical screen. + +The aim is to have five buttons (or equivalent sections on a touch screen) that represent left, right, up, down, and +centre. These may have both push and hold methods to perform different actions. + +InputMethod instances will be in a linked list to cycle through to process inputs, and each InputMethod instance should +have a pointer to a screen to control. +*/ + +class InputMethod { +public: + /// @brief Constructor for the InputMethod class + InputMethod(); + + virtual void process() = 0; + + void setScreen(PhysicalScreen *screen); + +private: + static InputMethod *_first; // + InputMethod *_next; + PhysicalScreen *_screen; +}; + +#endif diff --git a/TFT_eSPITouch.cpp b/TFT_eSPITouch.cpp new file mode 100644 index 0000000..1d7bb80 --- /dev/null +++ b/TFT_eSPITouch.cpp @@ -0,0 +1,8 @@ +#include "Defines.h" +#include "TFT_eSPITouch.h" + +#ifdef NEEDS_TFT + +TFT_eSPITouch::TFT_eSPITouch(TFT_eSPI &tftTouch) : InputMethod(), _tftTouch(tftTouch) {} + +#endif diff --git a/TFT_eSPITouch.h b/TFT_eSPITouch.h new file mode 100644 index 0000000..c971313 --- /dev/null +++ b/TFT_eSPITouch.h @@ -0,0 +1,23 @@ +#ifndef TFT_ESPITOUCH_H +#define TFT_ESPITOUCH_H + +#include "Defines.h" + +#ifdef NEEDS_TFT +#include "InputMethod.h" +#include +#include + +class TFT_eSPITouch : public InputMethod { +public: + /// @brief Constructor for the TFT_eSPITouch instance + /// @param tftTouch Reference to an existing TFT_eSPI instance + TFT_eSPITouch(TFT_eSPI &tftTouch); + +private: + TFT_eSPI &_tftTouch; +}; + +#endif // NEEDS_TFT + +#endif From 737b7023d8317f29e3b0090d9f6843d1ae3330d7 Mon Sep 17 00:00:00 2001 From: peteGSX <97784652+peteGSX@users.noreply.github.com> Date: Fri, 24 May 2024 15:31:47 +1000 Subject: [PATCH 071/146] Some progress --- AdafruitTouch.cpp | 23 +++++++++++++++++++++++ AdafruitTouch.h | 29 +++++++++++++++++++++++++++++ Debouncer.cpp | 7 +++++++ Debouncer.h | 12 ++++++++++++ EX-Display.ino | 16 ++++++++++++++++ InputMethod.cpp | 6 +++++- InputMethod.h | 6 ++++-- MCUFriendScreen.cpp | 4 ++++ MCUFriendScreen.h | 4 ++++ OLEDScreen.cpp | 4 ++++ OLEDScreen.h | 4 ++++ PhysicalScreen.h | 8 ++++++++ TFT_eSPIScreen.cpp | 4 ++++ TFT_eSPIScreen.h | 4 ++++ TFT_eSPITouch.cpp | 17 +++++++++++++++-- TFT_eSPITouch.h | 8 ++++++-- config.example.h | 17 +++++++++++++++++ platformio.ini | 1 + version.h | 5 ++++- 19 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 AdafruitTouch.cpp create mode 100644 AdafruitTouch.h create mode 100644 Debouncer.cpp create mode 100644 Debouncer.h diff --git a/AdafruitTouch.cpp b/AdafruitTouch.cpp new file mode 100644 index 0000000..b7eadb7 --- /dev/null +++ b/AdafruitTouch.cpp @@ -0,0 +1,23 @@ +#include "Defines.h" + +#if defined(NEEDS_MCU) && defined(USE_TOUCH) + +#include "AdafruitTouch.h" + +AdafruitTouch::AdafruitTouch(TouchScreen &touchScreen) : InputMethod(), _touchScreen(touchScreen) {} + +void AdafruitTouch::begin() { + if (!_screen) { + return; + } + CONSOLE.print(F("Screen Height|Width: ")); + CONSOLE.print(_screen->getHeight()); + CONSOLE.print(F("|")); + CONSOLE.println(_screen->getWidth()); +} + +void AdafruitTouch::processInput() { + _touchScreen.getPoint(); +} + +#endif diff --git a/AdafruitTouch.h b/AdafruitTouch.h new file mode 100644 index 0000000..5c0ca85 --- /dev/null +++ b/AdafruitTouch.h @@ -0,0 +1,29 @@ +#ifndef ADAFRUITTOUCH_H +#define ADAFRUITTOUCH_H + +#include "Defines.h" + +#if defined(NEEDS_MCU) && defined(USE_TOUCH) + +#include "InputMethod.h" +#include +#include +#include + +class AdafruitTouch : public InputMethod { +public: + /// @brief Constructor for an AdafruitTouch instance + /// @param touchScreen Reference to an Adafruit TouchScreen instance + AdafruitTouch(TouchScreen &touchScreen); + + void begin(); + + void processInput(); + +private: + TouchScreen &_touchScreen; +}; + +#endif // NEEDS_MCU and USE_TOUCH + +#endif diff --git a/Debouncer.cpp b/Debouncer.cpp new file mode 100644 index 0000000..2607bb7 --- /dev/null +++ b/Debouncer.cpp @@ -0,0 +1,7 @@ +#include "Defines.h" + +#if defined(USE_TOUCH) || defined(USE_BUTTONS) + +#include "Debouncer.h" + +#endif // USE_TOUCH or USE_BUTTONS diff --git a/Debouncer.h b/Debouncer.h new file mode 100644 index 0000000..332ff5d --- /dev/null +++ b/Debouncer.h @@ -0,0 +1,12 @@ +#ifndef DEBOUNCER_H +#define DEBOUNCER_H + +#include "Defines.h" + +#if defined(USE_TOUCH) || defined(USE_BUTTONS) + +#include + +#endif // USE_TOUCH or USE_BUTTONS + +#endif diff --git a/EX-Display.ino b/EX-Display.ino index 2384675..584a349 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -1,9 +1,11 @@ #include "AtFinder.h" #include "Defines.h" #include "DisplayFunctions.h" +#include "InputMethod.h" #include "version.h" #include + bool StartupPhase = true; unsigned long timestamp = 0; long screencount = 0; @@ -12,10 +14,19 @@ long screencount = 0; #include "MCUFriendScreen.h" MCUFRIEND_kbv tft; MCUFriendScreen *screen = new MCUFriendScreen(tft); +#ifdef USE_TOUCH +#include "AdafruitTouch.h" +TouchScreen touchScreen = TouchScreen(XP, YP, XM, YM, 300); +InputMethod *input = new AdafruitTouch(touchScreen); +#endif #elif SCREEN_TYPE == TFT #include "TFT_eSPIScreen.h" TFT_eSPI tft = TFT_eSPI(); TFT_eSPIScreen *screen = new TFT_eSPIScreen(tft); +#ifdef USE_TOUCH +#include "TFT_eSPITouch.h" +InputMethod *input = new TFT_eSPITouch(tft); +#endif #elif SCREEN_TYPE == OLED_SSD1306 #include "OLEDScreen.h" Adafruit_SSD1306 oled = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire); @@ -73,6 +84,10 @@ void setup() { screen->clearScreen(BACKGROUND_COLOUR); timestamp = millis(); + + input->setScreen(screen); + input->begin(); + CONSOLE.println(F("End of Setup")); } @@ -98,6 +113,7 @@ void loop() { else { if (!StartupPhase) { updateScreen(); + input->processInput(); } } } diff --git a/InputMethod.cpp b/InputMethod.cpp index 72c3e25..458b27a 100644 --- a/InputMethod.cpp +++ b/InputMethod.cpp @@ -5,4 +5,8 @@ InputMethod *InputMethod::_first = nullptr; InputMethod::InputMethod() { _next = nullptr; } -void InputMethod::setScreen(PhysicalScreen *screen) { _screen = screen; } +void InputMethod::setScreen(PhysicalScreen *screen) { + _screen = screen; + CONSOLE.print(F("Added screen ")); + CONSOLE.println(_screen->getScreenNumber()); +} diff --git a/InputMethod.h b/InputMethod.h index 06759f3..b8b6553 100644 --- a/InputMethod.h +++ b/InputMethod.h @@ -23,11 +23,13 @@ class InputMethod { /// @brief Constructor for the InputMethod class InputMethod(); - virtual void process() = 0; + virtual void begin() = 0; + + virtual void processInput() = 0; void setScreen(PhysicalScreen *screen); -private: +protected: static InputMethod *_first; // InputMethod *_next; PhysicalScreen *_screen; diff --git a/MCUFriendScreen.cpp b/MCUFriendScreen.cpp index 26d163c..7173e72 100644 --- a/MCUFriendScreen.cpp +++ b/MCUFriendScreen.cpp @@ -99,4 +99,8 @@ void MCUFriendScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, _tft.drawLine(x1, y1, x2, y2, lineColour); } +uint16_t MCUFriendScreen::getHeight() { return _tft.height(); } + +uint16_t MCUFriendScreen::getWidth() { return _tft.width(); } + #endif diff --git a/MCUFriendScreen.h b/MCUFriendScreen.h index 37cca38..eae469a 100644 --- a/MCUFriendScreen.h +++ b/MCUFriendScreen.h @@ -25,6 +25,10 @@ class MCUFriendScreen : public PhysicalScreen { virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) override; + virtual uint16_t getHeight() override; + + virtual uint16_t getWidth() override; + uint8_t getCharacterWidth(const char *character); private: diff --git a/OLEDScreen.cpp b/OLEDScreen.cpp index 213b660..5501b4e 100644 --- a/OLEDScreen.cpp +++ b/OLEDScreen.cpp @@ -83,6 +83,10 @@ void OLEDScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint _oled.display(); } +uint16_t OLEDScreen::getHeight() { return _oled.height(); } + +uint16_t OLEDScreen::getWidth() { return _oled.width(); } + uint8_t OLEDScreen::_getTextWidth() { int16_t x1, y1; uint16_t w, h; diff --git a/OLEDScreen.h b/OLEDScreen.h index db29c55..e4d6d87 100644 --- a/OLEDScreen.h +++ b/OLEDScreen.h @@ -32,6 +32,10 @@ class OLEDScreen : public PhysicalScreen { virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) override; + virtual uint16_t getHeight() override; + + virtual uint16_t getWidth() override; + private: #if SCREEN_TYPE == OLED_SSD1306 Adafruit_SSD1306 &_oled; diff --git a/PhysicalScreen.h b/PhysicalScreen.h index 7c93f04..6798751 100644 --- a/PhysicalScreen.h +++ b/PhysicalScreen.h @@ -50,6 +50,14 @@ class PhysicalScreen { virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) = 0; + /// @brief Get the physical screen height + /// @return Screen height in pixels + virtual uint16_t getHeight() = 0; + + /// @brief Get they physical screen width + /// @return Screen width in pixels + virtual uint16_t getWidth() = 0; + /// @brief Get the first screen /// @return Pointer to the first PhysicalScreen instance static PhysicalScreen *getFirst(); diff --git a/TFT_eSPIScreen.cpp b/TFT_eSPIScreen.cpp index 1d5e957..d441cd1 100644 --- a/TFT_eSPIScreen.cpp +++ b/TFT_eSPIScreen.cpp @@ -62,4 +62,8 @@ void TFT_eSPIScreen::writeLine(uint8_t row, uint8_t column, uint8_t lineLength, _tft.drawLine(x1, y1, x2, y2, lineColour); } +uint16_t TFT_eSPIScreen::getHeight() { return _tft.height(); } + +uint16_t TFT_eSPIScreen::getWidth() { return _tft.width(); } + #endif diff --git a/TFT_eSPIScreen.h b/TFT_eSPIScreen.h index 52c641d..3eb492c 100644 --- a/TFT_eSPIScreen.h +++ b/TFT_eSPIScreen.h @@ -25,6 +25,10 @@ class TFT_eSPIScreen : public PhysicalScreen { virtual void writeLine(uint8_t row, uint8_t column, uint8_t lineLength, uint16_t lineColour, uint16_t backgroundColour) override; + virtual uint16_t getHeight() override; + + virtual uint16_t getWidth() override; + private: TFT_eSPI &_tft; }; diff --git a/TFT_eSPITouch.cpp b/TFT_eSPITouch.cpp index 1d7bb80..49824aa 100644 --- a/TFT_eSPITouch.cpp +++ b/TFT_eSPITouch.cpp @@ -1,8 +1,21 @@ #include "Defines.h" -#include "TFT_eSPITouch.h" -#ifdef NEEDS_TFT +#if defined(NEEDS_TFT) && defined(USE_TOUCH) + +#include "TFT_eSPITouch.h" TFT_eSPITouch::TFT_eSPITouch(TFT_eSPI &tftTouch) : InputMethod(), _tftTouch(tftTouch) {} +void TFT_eSPITouch::begin() {} + +void TFT_eSPITouch::processInput() { + uint16_t touchX, touchY; + if (_tftTouch.getTouch(&touchX, &touchY)) { + CONSOLE.print(F("Touched X|Y: ")); + CONSOLE.print(touchX); + CONSOLE.print(F("|")); + CONSOLE.println(touchY); + } +} + #endif diff --git a/TFT_eSPITouch.h b/TFT_eSPITouch.h index c971313..bc34666 100644 --- a/TFT_eSPITouch.h +++ b/TFT_eSPITouch.h @@ -3,7 +3,7 @@ #include "Defines.h" -#ifdef NEEDS_TFT +#if defined(NEEDS_TFT) && defined(USE_TOUCH) #include "InputMethod.h" #include #include @@ -14,10 +14,14 @@ class TFT_eSPITouch : public InputMethod { /// @param tftTouch Reference to an existing TFT_eSPI instance TFT_eSPITouch(TFT_eSPI &tftTouch); + void begin() override; + + void processInput() override; + private: TFT_eSPI &_tftTouch; }; -#endif // NEEDS_TFT +#endif // NEEDS_TFT and USE_TOUCH #endif diff --git a/config.example.h b/config.example.h index 4334bef..1a77eda 100644 --- a/config.example.h +++ b/config.example.h @@ -52,6 +52,23 @@ // if in use uncomment the following // #define USE_TOUCH +// If using an MCUFRIEND_kbv type screen it requires the Adafruit TouchScreen driver +// You must define the below parameters for this scenario +// #define YP A1 // must be an analog pin, use "An" notation! +// #define XM A2 // must be an analog pin, use "An" notation! +// #define YM 7 // can be a digital pin +// #define XP 6 // can be a digital pin + +// If using push buttons rather than a touch screen, comment out USE_TOUCH above and uncomment the below +// Also efine the GPIO pin used by each push button +// #define USE_BUTTONS + +// #define LEFT_BUTTON 22 +// #define RIGHT_BUTTON 23 +// #define UP_BUTTON 24 +// #define DOWN_BUTTON 25 +// #define CENTRE_BUTTON 26 + // if the touch screen not in use, Now define the scroll requirements #define SCROLLTIME 1000 // 5 seconds diff --git a/platformio.ini b/platformio.ini index b65fc99..18a2d26 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,6 +28,7 @@ lib_deps = bodmer/TFT_eSPI adafruit/Adafruit SSD1306@^2.5.10 adafruit/Adafruit SH110X@^2.1.10 + adafruit/Adafruit TouchScreen@^1.1.5 [env:mega2560] platform = atmelavr diff --git a/version.h b/version.h index 65c12c4..300eed8 100644 --- a/version.h +++ b/version.h @@ -2,8 +2,11 @@ #define VERSION_H // Numeric version here: major.minor.patch -#define VERSION "0.0.10" +#define VERSION "0.0.11" +// 0.0.11 includes: +// - Add InputMethod class with support for TFT_eSPI and MCUFRIEND_kbv touch screens +// - Also add support for physical push buttons // 0.0.10 includes: // - Refactor so that logical displays are attributes of physical screens // - This should simplify addition of touch/input control From 0a7755662ae95717c37d146dd8980a35ca34eba6 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Fri, 24 May 2024 16:39:11 +1000 Subject: [PATCH 072/146] TFT getting screen dimensions --- TFT_eSPITouch.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/TFT_eSPITouch.cpp b/TFT_eSPITouch.cpp index 49824aa..5c6d000 100644 --- a/TFT_eSPITouch.cpp +++ b/TFT_eSPITouch.cpp @@ -6,7 +6,13 @@ TFT_eSPITouch::TFT_eSPITouch(TFT_eSPI &tftTouch) : InputMethod(), _tftTouch(tftTouch) {} -void TFT_eSPITouch::begin() {} +void TFT_eSPITouch::begin() { + if (!_screen) {return;} + CONSOLE.print(F("Screen Height|Width: ")); + CONSOLE.print(_screen->getHeight()); + CONSOLE.print(F("|")); + CONSOLE.println(_screen->getWidth()); +} void TFT_eSPITouch::processInput() { uint16_t touchX, touchY; From 9cf5969664460294b43d1095b3a31b29dd57eb16 Mon Sep 17 00:00:00 2001 From: peteGSX Date: Sun, 26 May 2024 09:11:41 +1000 Subject: [PATCH 073/146] TFT_eSPI buttons created --- Defines.h | 7 +++- DisplayFunctions.cpp | 6 +-- EX-Display.ino | 30 ++++++++++++++- InputMethod.cpp | 39 ++++++++++++++++--- InputMethod.h | 34 +++++++++++++++-- README.md | 6 +++ TFT_eSPITouch.cpp | 89 ++++++++++++++++++++++++++++++++++++++++---- TFT_eSPITouch.h | 15 ++++++-- config.example.h | 3 ++ 9 files changed, 204 insertions(+), 25 deletions(-) diff --git a/Defines.h b/Defines.h index afe7414..4ef02e7 100644 --- a/Defines.h +++ b/Defines.h @@ -49,28 +49,33 @@ #define CONSOLE Serial #define CS_LISTEN Serial1 //#define RX_PIN 19 // Define the RX pin for Serial1 +#define USE_EEPROM // Set up console and CS listener for Uno #elif defined(ARDUINO_AVR_UNO) #define RX_PIN 0 #define CONSOLE Serial #define CS_LISTEN Serial +#define USE_EEPROM // Set up console and CS listener for ESP32 -#elif defined(ESP32) +#elif defined(ARDUINO_ARCH_ESP32) #define RX_PIN 0 #define CONSOLE Serial #define CS_LISTEN Serial +#define USE_SPIFFS // Set up console and CS listener for F411RE #elif defined(ARDUINO_NUCLEO_F411RE) #define CONSOLE Serial HardwareSerial Serial1(PB7, PA15); // Rx=PB7, Tx=PA15 -- CN7 pins 17 and 21 - F411RE #define CS_LISTEN Serial1 #define RX_PIN PB7; +#define USE_FLASH // Set up console and CS listener for F446RE #elif defined(ARDUINO_NUCLEO_F446RE) #define CONSOLE Serial HardwareSerial Serial5(PD2, PC12); // Rx=PD2, Tx=PC12 -- UART5 - F446RE #define CS_LISTEN Serial5 #define RX_PIN PD2; +#define USE_FLASH #endif // If user has defined SERIAL_ONLY, override CS_LISTEN diff --git a/DisplayFunctions.cpp b/DisplayFunctions.cpp index f40537d..fc09179 100644 --- a/DisplayFunctions.cpp +++ b/DisplayFunctions.cpp @@ -49,9 +49,9 @@ void displayAllRows() { CONSOLE.println(F(" ~~")); for (LogicalDisplay *display = screen->getFirstDisplay(); display; display = display->getNext()) { - CONSOLE.print(F("\nRows for display ")); - CONSOLE.println(display->getDisplayNumber()); - CONSOLE.println(F("Row|Display Row|Message|isChanged|needsRender")); + CONSOLE.print(F("~~ Display ")); + CONSOLE.print(display->getDisplayNumber()); + CONSOLE.println(F(" ~~\nRow|Display Row|Message|isChanged|needsRender")); for (LogicalDisplayRow *row = display->getFirstRow(); row; row = row->getNext()) { CONSOLE.print(row->getRowNumber()); CONSOLE.print(F("|")); diff --git a/EX-Display.ino b/EX-Display.ino index 584a349..9a5f245 100644 --- a/EX-Display.ino +++ b/EX-Display.ino @@ -85,8 +85,10 @@ void setup() { timestamp = millis(); +#if defined(USE_TOUCH) || defined(USE_BUTTONS) input->setScreen(screen); input->begin(); +#endif CONSOLE.println(F("End of Setup")); } @@ -113,7 +115,33 @@ void loop() { else { if (!StartupPhase) { updateScreen(); - input->processInput(); +#if defined(USE_TOUCH) || defined(USE_BUTTONS) + Button inputButton = input->processInput(); + switch (inputButton) { + case LeftButton: + CONSOLE.println(F("Left button pressed")); + break; + + case RightButton: + CONSOLE.println(F("Right button pressed")); + break; + + case CentreButton: + CONSOLE.println(F("Centre button pressed")); + break; + + case UpButton: + CONSOLE.println(F("Up button pressed")); + break; + + case DownButton: + CONSOLE.println(F("Down button pressed")); + break; + + default: + break; + } +#endif } } } diff --git a/InputMethod.cpp b/InputMethod.cpp index 458b27a..bfeb99c 100644 --- a/InputMethod.cpp +++ b/InputMethod.cpp @@ -2,11 +2,40 @@ #include "InputMethod.h" InputMethod *InputMethod::_first = nullptr; +uint8_t InputMethod::_inputCount = 0; -InputMethod::InputMethod() { _next = nullptr; } +InputMethod::InputMethod() { + _next = nullptr; + _screen = nullptr; + _inputNumber = _inputCount++; +} + +void InputMethod::setScreen(PhysicalScreen *screen) { _screen = screen; } -void InputMethod::setScreen(PhysicalScreen *screen) { - _screen = screen; - CONSOLE.print(F("Added screen ")); - CONSOLE.println(_screen->getScreenNumber()); +#ifdef USE_TOUCH +void InputMethod::_calculateButtons() { + // Left third of full screen height is left button, right third right button + // Upper third of centre section is up button, lower third down button + // Centre third of centre section is centre button + _buttons[LeftButton].xStart = 0; + _buttons[LeftButton].xEnd = _screen->getWidth() / 3; + _buttons[LeftButton].yStart = 0; + _buttons[LeftButton].yEnd = _screen->getHeight(); + _buttons[UpButton].xStart = _buttons[LeftButton].xEnd + 1; + _buttons[UpButton].xEnd = (_screen->getWidth() / 3) + _buttons[LeftButton].xEnd; + _buttons[UpButton].yStart = 0; + _buttons[UpButton].yEnd = (_screen->getHeight() / 3); + _buttons[CentreButton].xStart = _buttons[UpButton].xStart; + _buttons[CentreButton].xEnd = _buttons[UpButton].xEnd; + _buttons[CentreButton].yStart = _buttons[UpButton].yEnd + 1; + _buttons[CentreButton].yEnd = (_screen->getHeight() / 3) + _buttons[UpButton].yEnd; + _buttons[DownButton].xStart = _buttons[UpButton].xStart; + _buttons[DownButton].xEnd = _buttons[UpButton].xEnd; + _buttons[DownButton].yStart = _buttons[CentreButton].yEnd + 1; + _buttons[DownButton].yEnd = _screen->getHeight(); + _buttons[RightButton].xStart = _buttons[CentreButton].xEnd + 1; + _buttons[RightButton].xEnd = _screen->getWidth(); + _buttons[RightButton].yStart = 0; + _buttons[RightButton].yEnd = _screen->getHeight(); } +#endif diff --git a/InputMethod.h b/InputMethod.h index b8b6553..a0ff29a 100644 --- a/InputMethod.h +++ b/InputMethod.h @@ -18,6 +18,24 @@ InputMethod instances will be in a linked list to cycle through to process input have a pointer to a screen to control. */ +#ifdef USE_TOUCH +struct ButtonDimensions { + uint16_t xStart = 0; + uint16_t xEnd = 0; + uint16_t yStart = 0; + uint16_t yEnd = 0; +}; +#endif + +enum Button { + LeftButton = 0, + RightButton = 1, + CentreButton = 2, + UpButton = 3, + DownButton = 4, + NoButton = 5, +}; + class InputMethod { public: /// @brief Constructor for the InputMethod class @@ -25,14 +43,22 @@ class InputMethod { virtual void begin() = 0; - virtual void processInput() = 0; + virtual Button processInput() = 0; void setScreen(PhysicalScreen *screen); protected: - static InputMethod *_first; // - InputMethod *_next; - PhysicalScreen *_screen; + InputMethod *_next; // Next input instance in the list + PhysicalScreen *_screen; // Physical screen instance associated with this input + uint8_t _inputNumber; // Auto incrementing number, enables multiple touch screens + +#ifdef USE_TOUCH + ButtonDimensions _buttons[5]; + void _calculateButtons(); +#endif + + static InputMethod *_first; // Start a linked list to cater for multiple inputs + static uint8_t _inputCount; // Count of all inputs }; #endif diff --git a/README.md b/README.md index 30d64bf..7c560d3 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,12 @@ It is possible to use any physical screen that is supported by either the MCUFRI In addition, it is also possible to use OLEDs based on either the SSD1306 or SH1106 drivers. +### Device limitations + +In its current form, it is only possible to configure one physical screen due to the way the config.h file has been implemented, however the classes have been written to facilitate multiple physical screens, and multiple input methods in future. + +**However** there are conflicts between the MCUFRIEND_kbv and TFT_eSPI libraries that mean when we do support multiple physical screens, we will not be able to have a mix of MCUFRIEND_kbv and TFT_eSPI types. + ## Configuration Copy "config.example.h" to "config.h" and set the desired parameters. diff --git a/TFT_eSPITouch.cpp b/TFT_eSPITouch.cpp index 5c6d000..292f9e7 100644 --- a/TFT_eSPITouch.cpp +++ b/TFT_eSPITouch.cpp @@ -4,24 +4,97 @@ #include "TFT_eSPITouch.h" -TFT_eSPITouch::TFT_eSPITouch(TFT_eSPI &tftTouch) : InputMethod(), _tftTouch(tftTouch) {} +#ifdef USE_SPIFFS +const char _calibrationFileBase[] = "/calibrationData"; +#endif + +TFT_eSPITouch::TFT_eSPITouch(TFT_eSPI &tft) : InputMethod(), _tft(tft) { +#ifdef USE_SPIFFS + sprintf(_calibrationFile, "%s%d", _calibrationFileBase, _inputNumber); +#endif +} void TFT_eSPITouch::begin() { - if (!_screen) {return;} + if (!_screen) { + return; + } CONSOLE.print(F("Screen Height|Width: ")); CONSOLE.print(_screen->getHeight()); CONSOLE.print(F("|")); CONSOLE.println(_screen->getWidth()); +#ifdef USE_SPIFFS + if (!SPIFFS.begin()) { + CONSOLE.println(F("Formatting file system")); + SPIFFS.format(); + SPIFFS.begin(); + } +#endif + if (!_setCalibration()) { + CONSOLE.println(F("Calibration data not valid")); + if (!_doCalibration()) { + _screen->clearScreen(TFT_BLACK); + _screen->writeRow(0, 0, TFT_WHITE, TFT_RED, _screen->getMaxRowLength(), "ERROR", true); + _screen->writeRow(1, 0, TFT_WHITE, TFT_BLACK, _screen->getMaxRowLength(), "Could not save calibration data", false); + CONSOLE.println(F("ERROR: Could not save calibration data")); + delay(3000); + _screen->clearScreen(TFT_BLACK); + } else { + _screen->clearScreen(TFT_BLACK); + } + } else { + CONSOLE.println(F("Calibration data valid")); + _screen->clearScreen(TFT_BLACK); + } + _calculateButtons(); } -void TFT_eSPITouch::processInput() { +Button TFT_eSPITouch::processInput() { uint16_t touchX, touchY; - if (_tftTouch.getTouch(&touchX, &touchY)) { - CONSOLE.print(F("Touched X|Y: ")); - CONSOLE.print(touchX); - CONSOLE.print(F("|")); - CONSOLE.println(touchY); + if (_tft.getTouch(&touchX, &touchY)) { + for (Button b = LeftButton; b < NoButton; b = static_cast