From 338445d175d69290a313c8aed6c8982b1fe854c1 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 14:24:22 -0700 Subject: [PATCH 1/5] basic init of the Corvus TFT display works --- platformio.ini | 12 +- src/User_Setup.h | 339 ------------------------------------------- src/graphics/TFT.cpp | 9 +- 3 files changed, 19 insertions(+), 341 deletions(-) delete mode 100644 src/User_Setup.h diff --git a/platformio.ini b/platformio.ini index d887022f4..57b4be3fe 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = tbeam # lora-relay-v1 +default_envs = lora-relay-v1 [common] ; common is not currently used @@ -220,7 +220,17 @@ lib_deps = extends = nrf52_base board = lora-relay-v1 # add our variants files to the include and src paths +# define build flags for the TFT_eSPI library build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v1 + -DUSER_SETUP_LOADED + -DTFT_WIDTH=80 + -DTFT_HEIGHT=160 + -DST7735_GREENTAB160x80 + -DST7735_DRIVER + -DTFT_CS=ST7735_CS + -DTFT_DC=ST7735_RS + -DTFT_RST=ST7735_RESET + -DSPI_FREQUENCY=27000000 src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v1> lib_deps = ${env.lib_deps} diff --git a/src/User_Setup.h b/src/User_Setup.h deleted file mode 100644 index d1aef836b..000000000 --- a/src/User_Setup.h +++ /dev/null @@ -1,339 +0,0 @@ -// This file is used to set TFT/eInk preferences for the TFT.cpp driver - -#include - -// USER DEFINED SETTINGS -// Set driver type, fonts to be loaded, pins used and SPI control method etc -// -// See the User_Setup_Select.h file if you wish to be able to define multiple -// setups and then easily select which setup file is used by the compiler. -// -// If this file is edited correctly then all the library example sketches should -// run without the need to make any more changes for a particular hardware setup! -// Note that some sketches are designed for a particular TFT pixel width/height - - -// ################################################################################## -// -// Section 1. Call up the right driver file and any options for it -// -// ################################################################################## - -// Define STM32 to invoke optimised processor support (only for STM32) -//#define STM32 - -// Defining the STM32 board allows the library to optimise the performance -// for UNO compatible "MCUfriend" style shields -//#define NUCLEO_64_TFT -//#define NUCLEO_144_TFT - -// STM32 8 bit parallel only: -// If STN32 Port A or B pins 0-7 are used for 8 bit parallel data bus bits 0-7 -// then this will improve rendering performance by a factor of ~8x -//#define STM_PORTA_DATA_BUS -//#define STM_PORTA_DATA_BUS - -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) -//#define TFT_PARALLEL_8_BIT - -// Display type - only define if RPi display -//#define RPI_DISPLAY_TYPE // 20MHz maximum SPI - -// Only define one driver, the other ones must be commented out -//#define ILI9341_DRIVER -#define ST7735_DRIVER // Define additional parameters below for this display -//#define ILI9163_DRIVER // Define additional parameters below for this display -//#define S6D02A1_DRIVER -//#define RPI_ILI9486_DRIVER // 20MHz maximum SPI -//#define HX8357D_DRIVER -//#define ILI9481_DRIVER -//#define ILI9486_DRIVER -//#define ILI9488_DRIVER // WARNING: Do not connect ILI9488 display SDO to MISO if other devices share the SPI bus (TFT SDO does NOT tristate when CS is high) -//#define ST7789_DRIVER // Full configuration option, define additional parameters below for this display -//#define ST7789_2_DRIVER // Minimal configuration option, define additional parameters below for this display -//#define R61581_DRIVER -//#define RM68140_DRIVER -//#define ST7796_DRIVER -//#define SSD1963_480_DRIVER // Untested -//#define SSD1963_800_DRIVER // Untested -//#define SSD1963_800ALT_DRIVER // Untested - -// Some displays support SPI reads via the MISO pin, other displays have a single -// bi-directional SDA pin and the library will try to read this via the MOSI line. -// To use the SDA line for reading data from the TFT uncomment the following line: - -// #define TFT_SDA_READ // This option is for ESP32 ONLY, tested with ST7789 display only - -// For ST7789 and ILI9341 ONLY, define the colour order IF the blue and red are swapped on your display -// Try ONE option at a time to find the correct colour order for your display - -// #define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue -// #define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red - -// For M5Stack ESP32 module with integrated ILI9341 display ONLY, remove // in line below - -// #define M5STACK - -// For ST7789, ST7735 and ILI9163 ONLY, define the pixel width and height in portrait orientation -#define TFT_WIDTH 80 -// #define TFT_WIDTH 128 -// #define TFT_WIDTH 240 // ST7789 240 x 240 and 240 x 320 -#define TFT_HEIGHT 160 -// #define TFT_HEIGHT 128 -// #define TFT_HEIGHT 240 // ST7789 240 x 240 -// #define TFT_HEIGHT 320 // ST7789 240 x 320 - -// For ST7735 ONLY, define the type of display, originally this was based on the -// colour of the tab on the screen protector film but this is not always true, so try -// out the different options below if the screen does not display graphics correctly, -// e.g. colours wrong, mirror images, or tray pixels at the edges. -// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this -// this User_Setup file, then rebuild and upload the sketch to the board again: - -// #define ST7735_INITB -#define ST7735_GREENTAB -// #define ST7735_GREENTAB2 -// #define ST7735_GREENTAB3 -// #define ST7735_GREENTAB128 // For 128 x 128 display -// #define ST7735_GREENTAB160x80 // For 160 x 80 display (BGR, inverted, 26 offset) -// #define ST7735_REDTAB -// #define ST7735_BLACKTAB -// #define ST7735_REDTAB160x80 // For 160 x 80 display with 24 pixel offset - -// If colours are inverted (white shows as black) then uncomment one of the next -// 2 lines try both options, one of the options should correct the inversion. - -// #define TFT_INVERSION_ON -// #define TFT_INVERSION_OFF - - -// ################################################################################## -// -// Section 2. Define the pins that are used to interface with the display here -// -// ################################################################################## - -// If a backlight control signal is available then define the TFT_BL pin in Section 2 -// below. The backlight will be turned ON when tft.begin() is called, but the library -// needs to know if the LEDs are ON with the pin HIGH or LOW. If the LEDs are to be -// driven with a PWM signal or turned OFF/ON then this must be handled by the user -// sketch. e.g. with digitalWrite(TFT_BL, LOW); - -#define TFT_BL ST7735_BACKLIGHT_EN // LED back-light control pin -#define TFT_BACKLIGHT_ON HIGH // Level to turn ON back-light (HIGH or LOW) - - - -// We must use hardware SPI, a minimum of 3 GPIO pins is needed. -// Typical setup for ESP8266 NodeMCU ESP-12 is : -// -// Display SDO/MISO to NodeMCU pin D6 (or leave disconnected if not reading TFT) -// Display LED to NodeMCU pin VIN (or 5V, see below) -// Display SCK to NodeMCU pin D5 -// Display SDI/MOSI to NodeMCU pin D7 -// Display DC (RS/AO)to NodeMCU pin D3 -// Display RESET to NodeMCU pin D4 (or RST, see below) -// Display CS to NodeMCU pin D8 (or GND, see below) -// Display GND to NodeMCU pin GND (0V) -// Display VCC to NodeMCU 5V or 3.3V -// -// The TFT RESET pin can be connected to the NodeMCU RST pin or 3.3V to free up a control pin -// -// The DC (Data Command) pin may be labeled AO or RS (Register Select) -// -// With some displays such as the ILI9341 the TFT CS pin can be connected to GND if no more -// SPI devices (e.g. an SD Card) are connected, in this case comment out the #define TFT_CS -// line below so it is NOT defined. Other displays such at the ST7735 require the TFT CS pin -// to be toggled during setup, so in these cases the TFT_CS line must be defined and connected. -// -// The NodeMCU D0 pin can be used for RST -// -// -// Note: only some versions of the NodeMCU provide the USB 5V on the VIN pin -// If 5V is not available at a pin you can use 3.3V but backlight brightness -// will be lower. - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP8266 SETUP ###### - -// For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -#define TFT_CS ST7735_CS // Chip select control pin D8 -#define TFT_DC ST7735_RS // Data Command control pin -#define TFT_RST ST7735_RESET // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - -//#define TFT_BL PIN_D1 // LED back-light (only for ST7789 with backlight control pin) - -//#define TOUCH_CS PIN_D2 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR PIN_D2 // Write strobe for modified Raspberry Pi TFT only - - -// ###### FOR ESP8266 OVERLAP MODE EDIT THE PIN NUMBERS IN THE FOLLOWING LINES ###### - -// Overlap mode shares the ESP8266 FLASH SPI bus with the TFT so has a performance impact -// but saves pins for other functions. It is best not to connect MISO as some displays -// do not tristate that line wjen chip select is high! -// On NodeMCU 1.0 SD0=MISO, SD1=MOSI, CLK=SCLK to connect to TFT in overlap mode -// On NodeMCU V3 S0 =MISO, S1 =MOSI, S2 =SCLK -// In ESP8266 overlap mode the following must be defined - -//#define TFT_SPI_OVERLAP - -// In ESP8266 overlap mode the TFT chip select MUST connect to pin D3 -//#define TFT_CS PIN_D3 -//#define TFT_DC PIN_D5 // Data Command control pin -//#define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V - - -// ###### EDIT THE PIN NUMBERS IN THE LINES FOLLOWING TO SUIT YOUR ESP32 SETUP ###### - -// For ESP32 Dev board (only tested with ILI9341 display) -// The hardware SPI can be mapped to any pins - -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 15 // Chip select control pin -//#define TFT_DC 2 // Data Command control pin -//#define TFT_RST 4 // Reset pin (could connect to RST pin) -//#define TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST - -//#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen - -//#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only - -// For the M5Stack module use these #define lines -//#define TFT_MISO 19 -//#define TFT_MOSI 23 -//#define TFT_SCLK 18 -//#define TFT_CS 14 // Chip select control pin -//#define TFT_DC 27 // Data Command control pin -//#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) -//#define TFT_BL 32 // LED back-light (required for M5Stack) - -// ###### EDIT THE PINs BELOW TO SUIT YOUR ESP32 PARALLEL TFT SETUP ###### - -// The library supports 8 bit parallel TFTs with the ESP32, the pin -// selection below is compatible with ESP32 boards in UNO format. -// Wemos D32 boards need to be modified, see diagram in Tools folder. -// Only ILI9481 and ILI9341 based displays have been tested! - -// Parallel bus is only supported for the STM32 and ESP32 -// Example below is for ESP32 Parallel interface with UNO displays - -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) -//#define TFT_PARALLEL_8_BIT - -// The ESP32 and TFT the pins used for testing are: -//#define TFT_CS 33 // Chip select control pin (library pulls permanently low -//#define TFT_DC 15 // Data Command control pin - must use a pin in the range 0-31 -//#define TFT_RST 32 // Reset pin, toggles on startup - -//#define TFT_WR 4 // Write strobe control pin - must use a pin in the range 0-31 -//#define TFT_RD 2 // Read strobe control pin - -//#define TFT_D0 12 // Must use pins in the range 0-31 for the data bus -//#define TFT_D1 13 // so a single register write sets/clears all bits. -//#define TFT_D2 26 // Pins can be randomly assigned, this does not affect -//#define TFT_D3 25 // TFT screen update performance. -//#define TFT_D4 17 -//#define TFT_D5 16 -//#define TFT_D6 27 -//#define TFT_D7 14 - -// ###### EDIT THE PINs BELOW TO SUIT YOUR STM32 SPI TFT SETUP ###### - -// The TFT can be connected to SPI port 1 or 2 -//#define TFT_SPI_PORT 1 // SPI port 1 maximum clock rate is 55MHz -//#define TFT_MOSI PA7 -//#define TFT_MISO PA6 -//#define TFT_SCLK PA5 - -//#define TFT_SPI_PORT 2 // SPI port 2 maximum clock rate is 27MHz -//#define TFT_MOSI PB15 -//#define TFT_MISO PB14 -//#define TFT_SCLK PB13 - -// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select -//#define TFT_CS D5 // Chip select control pin to TFT CS -//#define TFT_DC D6 // Data Command control pin to TFT DC (may be labelled RS = Register Select) -//#define TFT_RST D7 // Reset pin to TFT RST (or RESET) -// OR alternatively, we can use STM32 port reference names PXnn -//#define TFT_CS PE11 // Nucleo-F767ZI equivalent of D5 -//#define TFT_DC PE9 // Nucleo-F767ZI equivalent of D6 -//#define TFT_RST PF13 // Nucleo-F767ZI equivalent of D7 - -//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset - // Use an Arduino pin for initial testing as connecting to processor reset - // may not work (pulse too short at power up?) - -// ################################################################################## -// -// Section 3. Define the fonts that are to be used here -// -// ################################################################################## - -// Comment out the #defines below with // to stop that font being loaded -// The ESP8366 and ESP32 have plenty of memory so commenting out fonts is not -// normally necessary. If all fonts are loaded the extra FLASH space required is -// about 17Kbytes. To save FLASH space only enable the fonts you need! - -//#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH -//#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters -//#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters -//#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm -//#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. -//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT -//#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts - -// Comment out the #define below to stop the SPIFFS filing system and smooth font code being loaded -// this will save ~20kbytes of FLASH -//#define SMOOTH_FONT - - -// ################################################################################## -// -// Section 4. Other options -// -// ################################################################################## - -// Define the SPI clock frequency, this affects the graphics rendering speed. Too -// fast and the TFT driver will not keep up and display corruption appears. -// With an ILI9341 display 40MHz works OK, 80MHz sometimes fails -// With a ST7735 display more than 27MHz may not work (spurious pixels and lines) -// With an ILI9163 display 27 MHz works OK. - -// #define SPI_FREQUENCY 1000000 -// #define SPI_FREQUENCY 5000000 -// #define SPI_FREQUENCY 10000000 -// #define SPI_FREQUENCY 20000000 -#define SPI_FREQUENCY 27000000 -// #define SPI_FREQUENCY 40000000 -// #define SPI_FREQUENCY 55000000 // STM32 SPI1 only (SPI2 maximum is 27MHz) -// #define SPI_FREQUENCY 80000000 - -// Optional reduced SPI frequency for reading TFT -#define SPI_READ_FREQUENCY 20000000 - -// The XPT2046 requires a lower SPI clock rate of 2.5MHz so we define that here: -#define SPI_TOUCH_FREQUENCY 2500000 - -// The ESP32 has 2 free SPI ports i.e. VSPI and HSPI, the VSPI is the default. -// If the VSPI port is in use and pins are not accessible (e.g. TTGO T-Beam) -// then uncomment the following line: -//#define USE_HSPI_PORT - -// Comment out the following #define if "SPI Transactions" do not need to be -// supported. When commented out the code size will be smaller and sketches will -// run slightly faster, so leave it commented out unless you need it! - -// Transaction support is needed to work with SD library but not needed with TFT_SdFat -// Transaction support is required if other SPI devices are connected. - -// Transactions are automatically enabled by the library for an ESP32 (to use HAL mutex) -// so changing it here has no effect - -// #define SUPPORT_TRANSACTIONS diff --git a/src/graphics/TFT.cpp b/src/graphics/TFT.cpp index 7e2afb58b..ac9b2ec9d 100644 --- a/src/graphics/TFT.cpp +++ b/src/graphics/TFT.cpp @@ -9,9 +9,16 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h void TFTinit() { + DEBUG_MSG("Doing TFT init\n"); + +#ifdef ST7735_BACKLIGHT_EN + digitalWrite(ST7735_BACKLIGHT_EN, HIGH); + pinMode(ST7735_BACKLIGHT_EN, OUTPUT); +#endif + tft.init(); tft.setRotation(1); - tft.fillScreen(TFT_BLUE); + tft.fillScreen(TFT_GREEN); } #endif From e049eac38a5dbb4cf7797a3d5a4c062557dbbcc3 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 15:06:52 -0700 Subject: [PATCH 2/5] 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 From 7f214ffbb039232109bd7e1757017958b0cd0898 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 15:33:33 -0700 Subject: [PATCH 3/5] TFT kinda correct now - but slow because of bit banging --- src/graphics/TFT.cpp | 20 ++++++++++++++------ src/mesh/SX1262Interface.cpp | 4 ++-- variants/lora_relay_v1/variant.h | 6 ++++-- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/graphics/TFT.cpp b/src/graphics/TFT.cpp index 9acd81e69..ed3679908 100644 --- a/src/graphics/TFT.cpp +++ b/src/graphics/TFT.cpp @@ -1,25 +1,33 @@ #include "configuration.h" #ifdef ST7735_CS - #include "TFT.h" +#include "graphics/configs.h" #include #include // Graphics and font library for ST7735 driver chip TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h - 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 + setGeometry(GEOMETRY_128_64); // FIXME - currently we lie and claim 128x64 because I'm not yet sure other resolutions will + // work ie GEOMETRY_RAWMODE } // 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); + // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); + for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) { + for (uint8_t x = 0; x < SCREEN_WIDTH; x++) { + + // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent + auto b = buffer[x + (y / 8) * SCREEN_WIDTH]; + auto isset = b & (1 << (y & 7)); + tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK); + } + } } // Send a command to the display (low level function) @@ -41,7 +49,7 @@ bool TFTDisplay::connect() tft.init(); tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label - tft.fillScreen(TFT_BLUE); + // tft.fillScreen(TFT_BLUE); // tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left return true; diff --git a/src/mesh/SX1262Interface.cpp b/src/mesh/SX1262Interface.cpp index b7fe422f3..f581cdb1c 100644 --- a/src/mesh/SX1262Interface.cpp +++ b/src/mesh/SX1262Interface.cpp @@ -75,8 +75,8 @@ bool SX1262Interface::reconfigure() assert(err == ERR_NONE); // Hmm - seems to lower SNR when the signal levels are high. Leaving off for now... - //err = lora.setRxGain(true); - //assert(err == ERR_NONE); + // err = lora.setRxGain(true); + // assert(err == ERR_NONE); err = lora.setSyncWord(syncWord); assert(err == ERR_NONE); diff --git a/variants/lora_relay_v1/variant.h b/variants/lora_relay_v1/variant.h index 0f4ac4886..3562724f7 100644 --- a/variants/lora_relay_v1/variant.h +++ b/variants/lora_relay_v1/variant.h @@ -117,7 +117,9 @@ static const uint8_t SCK = PIN_SPI_SCK; #define I2C_ADDR_BQ27441 0x55 // Battery gauge // CUSTOM GPIOs the SX1262 -#define SX1262_CS (32) +// #define SX1262_CS (32) +#define USE_SIM_RADIO +#define USE_SEGGER #define SX1262_DIO1 (29) #define SX1262_DIO2 (30) #define SX1262_BUSY (33) // Supposed to be P0.18 but because of reworks, now on P0.31 (18) @@ -130,7 +132,7 @@ static const uint8_t SCK = PIN_SPI_SCK; #define SX1262_E22 // Indicates this SX1262 is inside of an ebyte E22 module and special config should be done for that #define ST7735_RESET (11) // Output -#define ST7735_CS (12) +#define ST7735_CS (12) #define ST7735_BACKLIGHT_EN (13) #define ST7735_RS (9) From dffb6c2f0639bc842b77077ebf87a9dd804be612 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 28 Aug 2020 17:38:23 -0700 Subject: [PATCH 4/5] If display is on on the @BigCorvus board and we xmit the board browns out? --- platformio.ini | 2 +- src/SPILock.cpp | 11 ++++++++ src/SPILock.h | 12 +++++++++ src/graphics/TFT.cpp | 11 ++++++-- src/graphics/TFT.h | 3 ++- src/main.cpp | 20 +++++++------- src/mesh/RadioLibInterface.cpp | 14 ++++++++++ src/mesh/RadioLibInterface.h | 45 +++++++++++++++++++++++++++++++- variants/lora_relay_v1/variant.h | 8 ++++-- 9 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 src/SPILock.cpp create mode 100644 src/SPILock.h diff --git a/platformio.ini b/platformio.ini index 57b4be3fe..6c42ec407 100644 --- a/platformio.ini +++ b/platformio.ini @@ -66,7 +66,7 @@ lib_deps = Wire ; explicitly needed here because the AXP202 library forgets to add it https://github.com/meshtastic/arduino-fsm.git https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git - https://github.com/meshtastic/RadioLib.git#d6b12f7eb0a06bd2414c79b437b25d377e3f603f + https://github.com/meshtastic/RadioLib.git#7989a269be590a5d4914ac04069b58f4930c45c1 https://github.com/meshtastic/TinyGPSPlus.git https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460 diff --git a/src/SPILock.cpp b/src/SPILock.cpp new file mode 100644 index 000000000..43d841fc8 --- /dev/null +++ b/src/SPILock.cpp @@ -0,0 +1,11 @@ +#include "SPILock.h" +#include +#include + +concurrency::Lock *spiLock; + +void initSPI() +{ + assert(!spiLock); + spiLock = new concurrency::Lock(); +} \ No newline at end of file diff --git a/src/SPILock.h b/src/SPILock.h new file mode 100644 index 000000000..8a4bd5dbb --- /dev/null +++ b/src/SPILock.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../concurrency/LockGuard.h" + +/** + * Used to provide mutual exclusion for access to the SPI bus. Usage: + * concurrency::LockGuard g(spiLock); + */ +extern concurrency::Lock *spiLock; + +/** Setup SPI access and create the spiLock lock. */ +void initSPI(); \ No newline at end of file diff --git a/src/graphics/TFT.cpp b/src/graphics/TFT.cpp index ed3679908..dcaf53ec4 100644 --- a/src/graphics/TFT.cpp +++ b/src/graphics/TFT.cpp @@ -1,12 +1,13 @@ #include "configuration.h" #ifdef ST7735_CS +#include "SPILock.h" #include "TFT.h" #include "graphics/configs.h" #include #include // Graphics and font library for ST7735 driver chip -TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h +static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) { @@ -17,6 +18,9 @@ TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl) // Write the buffer to the display memory void TFTDisplay::display(void) { + concurrency::LockGuard g(spiLock); + +#if 1 // FIXME - only draw bits have changed (use backbuf similar to the other displays) // tft.drawBitmap(0, 0, buffer, 128, 64, TFT_YELLOW, TFT_BLACK); for (uint8_t y = 0; y < SCREEN_HEIGHT; y++) { @@ -28,6 +32,7 @@ void TFTDisplay::display(void) tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK); } } +#endif } // Send a command to the display (low level function) @@ -47,10 +52,12 @@ bool TFTDisplay::connect() pinMode(ST7735_BACKLIGHT_EN, OUTPUT); #endif +#if 1 tft.init(); tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label - // tft.fillScreen(TFT_BLUE); + tft.fillScreen(TFT_BLACK); // tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left +#endif return true; } diff --git a/src/graphics/TFT.h b/src/graphics/TFT.h index eec6d07b5..83168e2e1 100644 --- a/src/graphics/TFT.h +++ b/src/graphics/TFT.h @@ -9,7 +9,8 @@ * 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 + * + * turn radio back on - currently with both on spi bus is fucked? or are we leaving chip select asserted? */ class TFTDisplay : public OLEDDisplay { diff --git a/src/main.cpp b/src/main.cpp index bd4bd079b..53780f6fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ // #include "rom/rtc.h" #include "DSRRouter.h" // #include "debug.h" +#include "SPILock.h" #include "graphics/Screen.h" #include "main.h" #include "sleep.h" @@ -220,6 +221,16 @@ void setup() nrf52Setup(); #endif + // Init our SPI controller (must be before screen and lora) + initSPI(); +#ifdef NRF52_SERIES + SPI.begin(); +#else + // ESP32 + SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); + SPI.setFrequency(4000000); +#endif + // Initialize the screen first so we can show the logo while we start up everything else. #ifdef ST7735_CS screen.setup(); @@ -278,15 +289,6 @@ void setup() digitalWrite(SX1262_ANT_SW, 1); #endif - // Init our SPI controller -#ifdef NRF52_SERIES - SPI.begin(); -#else - // ESP32 - SPI.begin(RF95_SCK, RF95_MISO, RF95_MOSI, RF95_NSS); - SPI.setFrequency(4000000); -#endif - // MUST BE AFTER service.init, so we have our radio config settings (from nodedb init) RadioInterface *rIf = NULL; diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index ae94231d2..30f7de50e 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -1,6 +1,7 @@ #include "RadioLibInterface.h" #include "MeshTypes.h" #include "NodeDB.h" +#include "SPILock.h" #include "mesh-pb-constants.h" #include #include @@ -9,6 +10,13 @@ // FIXME, we default to 4MHz SPI, SPI mode 0, check if the datasheet says it can really do that static SPISettings spiSettings(4000000, MSBFIRST, SPI_MODE0); +void LockingModule::SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes) +{ + concurrency::LockGuard g(spiLock); + + Module::SPItransfer(cmd, reg, dataOut, dataIn, numBytes); +} + RadioLibInterface::RadioLibInterface(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE busy, SPIClass &spi, PhysicalLayer *_iface) : concurrency::PeriodicTask(0), module(cs, irq, rst, busy, spi, spiSettings), iface(_iface) @@ -126,6 +134,8 @@ bool RadioLibInterface::canSendImmediately() /// bluetooth comms code. If the txmit queue is empty it might return an error ErrorCode RadioLibInterface::send(MeshPacket *p) { + // Sometimes when testing it is useful to be able to never turn on the xmitter +#ifndef LORA_DISABLE_SENDING printPacket("enqueuing for send", p); DEBUG_MSG("txGood=%d,rxGood=%d,rxBad=%d\n", txGood, rxGood, rxBad); ErrorCode res = txQueue.enqueue(p, 0) ? ERRNO_OK : ERRNO_UNKNOWN; @@ -140,6 +150,10 @@ ErrorCode RadioLibInterface::send(MeshPacket *p) startTransmitTimer(true); return res; +#else + packetPool.release(p); + return ERRNO_UNKNOWN; +#endif } bool RadioLibInterface::canSleep() diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index a19c47412..d393077b5 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -16,6 +16,49 @@ #define INTERRUPT_ATTR #endif +/** + * A wrapper for the RadioLib Module class, that adds mutex for SPI bus access + */ +class LockingModule : public Module +{ + public: + /*! + \brief Extended SPI-based module constructor. + + \param cs Arduino pin to be used as chip select. + + \param irq Arduino pin to be used as interrupt/GPIO. + + \param rst Arduino pin to be used as hardware reset for the module. + + \param gpio Arduino pin to be used as additional interrupt/GPIO. + + \param spi SPI interface to be used, can also use software SPI implementations. + + \param spiSettings SPI interface settings. + */ + LockingModule(RADIOLIB_PIN_TYPE cs, RADIOLIB_PIN_TYPE irq, RADIOLIB_PIN_TYPE rst, RADIOLIB_PIN_TYPE gpio, SPIClass &spi, + SPISettings spiSettings) + : Module(cs, irq, rst, gpio, spi, spiSettings) + { + } + + /*! + \brief SPI single transfer method. + + \param cmd SPI access command (read/write/burst/...). + + \param reg Address of SPI register to transfer to/from. + + \param dataOut Data that will be transfered from master to slave. + + \param dataIn Data that was transfered from slave to master. + + \param numBytes Number of bytes to transfer. + */ + virtual void SPItransfer(uint8_t cmd, uint8_t reg, uint8_t *dataOut, uint8_t *dataIn, uint8_t numBytes); +}; + class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTask { /// Used as our notification from the ISR @@ -49,7 +92,7 @@ class RadioLibInterface : public RadioInterface, private concurrency::PeriodicTa float currentLimit = 100; // FIXME uint16_t preambleLength = 32; // 8 is default, but FIXME use longer to increase the amount of sleep time when receiving - Module module; // The HW interface to the radio + LockingModule module; // The HW interface to the radio /** * provides lowest common denominator RadioLib API diff --git a/variants/lora_relay_v1/variant.h b/variants/lora_relay_v1/variant.h index 3562724f7..763cac00f 100644 --- a/variants/lora_relay_v1/variant.h +++ b/variants/lora_relay_v1/variant.h @@ -117,8 +117,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define I2C_ADDR_BQ27441 0x55 // Battery gauge // CUSTOM GPIOs the SX1262 -// #define SX1262_CS (32) -#define USE_SIM_RADIO +#define SX1262_CS (32) + #define USE_SEGGER #define SX1262_DIO1 (29) #define SX1262_DIO2 (30) @@ -136,6 +136,10 @@ static const uint8_t SCK = PIN_SPI_SCK; #define ST7735_BACKLIGHT_EN (13) #define ST7735_RS (9) +#define LORA_DISABLE_SENDING // The 1.1 version of this board browns out if the SX1262 transmits while the screen is on. So you + // can +// have either a working SX1262 or a working screen + #ifdef __cplusplus } #endif From f1ca1ee3c09bbe4490f295f10b08e7bb93f099f6 Mon Sep 17 00:00:00 2001 From: geeksville Date: Sat, 29 Aug 2020 12:46:42 -0700 Subject: [PATCH 5/5] okay basic support for @bigcorvus board is done --- platformio.ini | 2 +- variants/lora_relay_v1/variant.h | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index 6c42ec407..2ba2ba5fa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ ; https://docs.platformio.org/page/projectconf.html [platformio] -default_envs = lora-relay-v1 +default_envs = tbeam # or if you'd like to change the default to something like lora-relay-v1 put that here [common] ; common is not currently used diff --git a/variants/lora_relay_v1/variant.h b/variants/lora_relay_v1/variant.h index 763cac00f..f7ade9586 100644 --- a/variants/lora_relay_v1/variant.h +++ b/variants/lora_relay_v1/variant.h @@ -119,7 +119,9 @@ static const uint8_t SCK = PIN_SPI_SCK; // CUSTOM GPIOs the SX1262 #define SX1262_CS (32) -#define USE_SEGGER +// If you would prefer to get console debug output over the JTAG ICE connection rather than the CDC-ACM USB serial device, just +// define this. #define USE_SEGGER + #define SX1262_DIO1 (29) #define SX1262_DIO2 (30) #define SX1262_BUSY (33) // Supposed to be P0.18 but because of reworks, now on P0.31 (18) @@ -136,9 +138,8 @@ static const uint8_t SCK = PIN_SPI_SCK; #define ST7735_BACKLIGHT_EN (13) #define ST7735_RS (9) -#define LORA_DISABLE_SENDING // The 1.1 version of this board browns out if the SX1262 transmits while the screen is on. So you - // can -// have either a working SX1262 or a working screen +// #define LORA_DISABLE_SENDING // The board can brownout during lora TX if you don't have a battery connected. Disable sending +// to allow USB power only based debugging #ifdef __cplusplus }