From e049eac38a5dbb4cf7797a3d5a4c062557dbbcc3 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 15:06:52 -0700 Subject: [PATCH] TFT display kinda draws stuff (badly) --- src/graphics/Screen.h | 61 +++++++++++++++++++++++++--------------- src/graphics/TFT.cpp | 32 +++++++++++++++++++-- src/graphics/TFT.h | 33 +++++++++++++++++++++- src/main.cpp | 4 +++ src/nrf52/main-nrf52.cpp | 5 ---- 5 files changed, 104 insertions(+), 31 deletions(-) diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 2ad015a46..e4fea2f2b 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -10,11 +10,12 @@ #include #endif -#include "concurrency/PeriodicTask.h" +#include "TFT.h" #include "TypedQueue.h" -#include "concurrency/LockGuard.h" -#include "power.h" #include "commands.h" +#include "concurrency/LockGuard.h" +#include "concurrency/PeriodicTask.h" +#include "power.h" #include namespace graphics @@ -53,16 +54,19 @@ class DebugInfo /** * @brief This class deals with showing things on the screen of the device. - * - * @details Other than setup(), this class is thread-safe as long as drawFrame is not called - * multiple times simultaneously. All state-changing calls are queued and executed + * + * @details Other than setup(), this class is thread-safe as long as drawFrame is not called + * multiple times simultaneously. All state-changing calls are queued and executed * when the main loop calls us. */ class Screen : public concurrency::PeriodicTask { - CallbackObserver powerStatusObserver = CallbackObserver(this, &Screen::handleStatusUpdate); - CallbackObserver gpsStatusObserver = CallbackObserver(this, &Screen::handleStatusUpdate); - CallbackObserver nodeStatusObserver = CallbackObserver(this, &Screen::handleStatusUpdate); + CallbackObserver powerStatusObserver = + CallbackObserver(this, &Screen::handleStatusUpdate); + CallbackObserver gpsStatusObserver = + CallbackObserver(this, &Screen::handleStatusUpdate); + CallbackObserver nodeStatusObserver = + CallbackObserver(this, &Screen::handleStatusUpdate); public: Screen(uint8_t address, int sda = -1, int scl = -1); @@ -125,11 +129,12 @@ class Screen : public concurrency::PeriodicTask } /// Overrides the default utf8 character conversion, to replace empty space with question marks - static char customFontTableLookup(const uint8_t ch) { + static char customFontTableLookup(const uint8_t ch) + { // UTF-8 to font table index converter // Code form http://playground.arduino.cc/Main/Utf8ascii static uint8_t LASTCHAR; - static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters + static bool SKIPREST; // Only display a single unconvertable-character symbol per sequence of unconvertable characters if (ch < 128) { // Standard ASCII-set 0..0x7F handling LASTCHAR = 0; @@ -137,28 +142,38 @@ class Screen : public concurrency::PeriodicTask return ch; } - uint8_t last = LASTCHAR; // get last char + uint8_t last = LASTCHAR; // get last char LASTCHAR = ch; - switch (last) { // conversion depnding on first UTF8-character - case 0xC2: { SKIPREST = false; return (uint8_t) ch; } - case 0xC3: { SKIPREST = false; return (uint8_t) (ch | 0xC0); } + switch (last) { // conversion depnding on first UTF8-character + case 0xC2: { + SKIPREST = false; + return (uint8_t)ch; + } + case 0xC3: { + SKIPREST = false; + return (uint8_t)(ch | 0xC0); + } } // We want to strip out prefix chars for two-byte char formats - if (ch == 0xC2 || ch == 0xC3 || ch == 0x82) return (uint8_t) 0; + if (ch == 0xC2 || ch == 0xC3 || ch == 0x82) + return (uint8_t)0; - // If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the rest of it - if (SKIPREST) return (uint8_t) 0; + // If we already returned an unconvertable-character symbol for this unconvertable-character sequence, return NULs for the + // rest of it + if (SKIPREST) + return (uint8_t)0; SKIPREST = true; - return (uint8_t) 191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't stick to standard EASCII codes) + return (uint8_t)191; // otherwise: return ¿ if character can't be converted (note that the font map we're using doesn't + // stick to standard EASCII codes) } /// Returns a handle to the DebugInfo screen. // // Use this handle to set things like battery status, user count, GPS status, etc. - DebugInfo* debug_info() { return &debugInfo; } + DebugInfo *debug_info() { return &debugInfo; } int handleStatusUpdate(const meshtastic::Status *arg); @@ -215,8 +230,10 @@ class Screen : public concurrency::PeriodicTask DebugInfo debugInfo; /// Display device - /** @todo display abstraction */ -#ifdef USE_SH1106 + /** FIXME cleanup display abstraction */ +#ifdef ST7735_CS + TFTDisplay dispdev; +#elif defined(USE_SH1106) SH1106Wire dispdev; #else SSD1306Wire dispdev; diff --git a/src/graphics/TFT.cpp b/src/graphics/TFT.cpp index ac9b2ec9d..9acd81e69 100644 --- a/src/graphics/TFT.cpp +++ b/src/graphics/TFT.cpp @@ -2,12 +2,35 @@ #ifdef ST7735_CS +#include "TFT.h" #include #include // Graphics and font library for ST7735 driver chip TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h -void TFTinit() + +TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) +{ + setGeometry( + GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will work +} + +// Write the buffer to the display memory +void TFTDisplay::display(void) +{ + // FIXME - only draw bits have changed (use backbuf similar to the other displays) + tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); +} + +// Send a command to the display (low level function) +void TFTDisplay::sendCommand(uint8_t com) +{ + (void)com; + // Drop all commands to device (we just update the buffer) +} + +// Connect to the display +bool TFTDisplay::connect() { DEBUG_MSG("Doing TFT init\n"); @@ -17,8 +40,11 @@ void TFTinit() #endif tft.init(); - tft.setRotation(1); - tft.fillScreen(TFT_GREEN); + tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label + tft.fillScreen(TFT_BLUE); + // tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left + + return true; } #endif diff --git a/src/graphics/TFT.h b/src/graphics/TFT.h index 752793756..eec6d07b5 100644 --- a/src/graphics/TFT.h +++ b/src/graphics/TFT.h @@ -1,3 +1,34 @@ #pragma once -void TFTinit(); +#include + +/** + * An adapter class that allows using the TFT_eSPI library as if it was an OLEDDisplay implementation. + * + * Remaining TODO: + * optimize display() to only draw changed pixels (see other OLED subclasses for examples) + * implement displayOn/displayOff to turn off the TFT device (and backlight) + * Use the fast NRF52 SPI API rather than the slow standard arduino version + * turn radio back on + */ +class TFTDisplay : public OLEDDisplay +{ + public: + /* constructor + FIXME - the parameters are not used, just a temporary hack to keep working like the old displays + */ + TFTDisplay(uint8_t address, int sda, int scl); + + // Write the buffer to the display memory + virtual void display(void); + + protected: + // the header size of the buffer used, e.g. for the SPI command header + virtual int getBufferOffset(void) { return 0; } + + // Send a command to the display (low level function) + virtual void sendCommand(uint8_t com); + + // Connect to the display + virtual bool connect(); +}; diff --git a/src/main.cpp b/src/main.cpp index ce9e3d46b..bd4bd079b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -221,8 +221,12 @@ void setup() #endif // Initialize the screen first so we can show the logo while we start up everything else. +#ifdef ST7735_CS + screen.setup(); +#else if (ssd1306_found) screen.setup(); +#endif screen.print("Started...\n"); diff --git a/src/nrf52/main-nrf52.cpp b/src/nrf52/main-nrf52.cpp index a537c8268..40ca6266a 100644 --- a/src/nrf52/main-nrf52.cpp +++ b/src/nrf52/main-nrf52.cpp @@ -99,9 +99,4 @@ void nrf52Setup() // randomSeed(r); DEBUG_MSG("FIXME, call randomSeed\n"); // ::printf("TESTING PRINTF\n"); - -// Setup TFT display - FIXME do somewhere else -#ifdef ST7735_CS - TFTinit(); -#endif } \ No newline at end of file