Updating RAK14014 TFT Display

I’m using a RAK4631 with a RAK14014 TFT Display. I’ve tested a couple ways of updating text that I am displaying on the screen, both of them are based on this example code: WisBlock/examples/common/IO/RAK14014_TFT_ST7789/RAK14014_TFT_ST7789.ino at master · RAKWireless/WisBlock · GitHub

The first method I use to update the screen paints the entire screen black, then uses a function like “testdrawtext” (from the above example) to write over it. The other method simply rewrites the existing white text but in black text at the same location on the screen (so now the entire screen is black) and then writes the new text onto the screen in white.

I’m trying to make it so that when text gets updated on the TFT screen, I there is no very visible refresh that is obvious to users. I would like the text update on the screen to just look the same way text updating on my computer or phone looks.

I linked a video below of what the TFT screen update looks like right now using both methods. It has a very clear refresh of the entire screen when using method 1, and a clear refresh of the individual section when using method 2.

Welcome back to forum @Dhruv ,

Will you be able to share us the code? This way, we can see how the refresh of display implemented as well as overall architecture of the code flow. There could some delay that could hinder the immediate display update.

Here is code that does the refresh/rewrite thing, let me know if you have any questions. The testDrawText is the function that rewrites text on the screen.

/**
 * @file LoRaP2P_RX.ino
 * @author rakwireless.com
 * @brief Receiver node for LoRa point to point communication
 * @version 0.1
 * @date 2020-08-21
 * 
 * @copyright Copyright (c) 2020
 * 
 * @note RAK4631 GPIO mapping to nRF52840 GPIO ports
   RAK4631    <->  nRF52840
   WB_IO1     <->  P0.17 (GPIO 17)
   WB_IO2     <->  P1.02 (GPIO 34)
   WB_IO3     <->  P0.21 (GPIO 21)
   WB_IO4     <->  P0.04 (GPIO 4)
   WB_IO5     <->  P0.09 (GPIO 9)
   WB_IO6     <->  P0.10 (GPIO 10)
   WB_SW1     <->  P0.01 (GPIO 1)
   WB_A0      <->  P0.04/AIN2 (AnalogIn A2)
   WB_A1      <->  P0.31/AIN7 (AnalogIn A7)
 */
#include <Arduino.h>
#include <SX126x-RAK4630.h> //http://librarymanager/All#SX126x
#include <Adafruit_GFX.h>            // Click here to get the library: http://librarymanager/All#Adafruit_GFX
#include <Adafruit_ST7789.h>    // Click here to get the library: http://librarymanager/All#Adafruit_ST7789
#include <./Fonts/FreeMonoBold12pt7b.h>  // Font file, you can include your favorite fonts.
#include <SPI.h>

// Function declarations
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr);
void OnRxTimeout(void);
void OnRxError(void);

#ifdef NRF52_SERIES
#define LED_BUILTIN 35
#endif

// Define LoRa parameters
#define RF_FREQUENCY 868300000    // Hz
#define TX_OUTPUT_POWER 22        // dBm
#define LORA_BANDWIDTH 0        // [0: 125 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
#define LORA_SPREADING_FACTOR 7 // [SF7..SF12]
#define LORA_CODINGRATE 1        // [1: 4/5, 2: 4/6,  3: 4/7,  4: 4/8]
#define LORA_PREAMBLE_LENGTH 8    // Same for Tx and Rx
#define LORA_SYMBOL_TIMEOUT 0    // Symbols
#define LORA_FIX_LENGTH_PAYLOAD_ON false
#define LORA_IQ_INVERSION_ON false
#define RX_TIMEOUT_VALUE 3000
#define TX_TIMEOUT_VALUE 3000

static RadioEvents_t RadioEvents;

static uint8_t RcvBuffer[64];
char* receivedData = nullptr;

#define CS            SS
#define BL            WB_IO3
#define RST           WB_IO5
#define DC            WB_IO4

Adafruit_ST7789 tft = Adafruit_ST7789(CS, DC, RST);

#ifndef GUI_CONST_STORAGE
  #define GUI_CONST_STORAGE const
#endif

/**
 * @The data structure saved in Flash cannot exceed 128 bytes@NRF52840.
 */
 typedef struct 
{
  uint16_t xSize;
  uint16_t ySize;
  uint8_t  bitsPerPixel;
  GUI_CONST_STORAGE unsigned short * date;
}GUI_BITMAP; 

static GUI_CONST_STORAGE unsigned short _acdemo[] = {//HUMBLE LOGO
};

GUI_CONST_STORAGE GUI_BITMAP bmdemo = {
  320,  // xSize
  240,  // ySize
  16,   // BitsPerPixel
  _acdemo,  // Pointer to picture data
};

void setup()
{
  pinMode(WB_IO2, OUTPUT);
  digitalWrite(WB_IO2, HIGH);
  
  pinMode(BL, OUTPUT);
  digitalWrite(BL, HIGH); // Enable the backlight, you can also adjust the backlight brightness through PWM.

    // Initialize Serial for debug output
    time_t timeout = millis();
    Serial.begin(115200);
    Serial.println("=====================================");
    Serial.println("LoRaP2P Rx Test");
    Serial.println("=====================================");
    // Initialize LoRa chip.
    lora_rak4630_init();
    // Initialize the Radio callbacks
    RadioEvents.TxDone = NULL;
    RadioEvents.RxDone = OnRxDone;
    RadioEvents.TxTimeout = NULL;
    RadioEvents.RxTimeout = OnRxTimeout;
    RadioEvents.RxError = OnRxError;
    RadioEvents.CadDone = NULL;

  tft.init(240, 320); // Init ST7789 240x240.
  tft.setRotation(3);
  tft.fillScreen(ST77XX_BLACK);
  drawBmp(&bmdemo,0,0);
  delay(1500);

    // Initialize the Radio
    Radio.Init(&RadioEvents);

    // Set Radio channel
    Radio.SetChannel(RF_FREQUENCY);

    // Set Radio RX configuration
    Radio.SetRxConfig(MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
                      LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
                      LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
                      0, true, 0, 0, LORA_IQ_INVERSION_ON, true);

    // Start LoRa
    Serial.println("Starting Radio.Rx");
    Radio.Rx(RX_TIMEOUT_VALUE);
}

void loop()
{
  delay(1000);
}

static void testdrawtext(char *text, uint16_t color) 
{
  tft.setTextSize(0);
  tft.setFont(&FreeMonoBold12pt7b); 
  tft.setCursor(10, 110);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.print(text);
}

static void drawBmp(const GUI_BITMAP *bmp , uint8_t x, uint8_t y) 
{
  uint16_t color = bmp->date[0];
  uint32_t count = 0;
  uint64_t bufSize = bmp->xSize * bmp->ySize;
  tft.startWrite();
  tft.setAddrWindow(x, y, bmp->xSize, bmp->ySize);

  for ( uint64_t i = 0 ; i < bufSize ; i++ ) 
  {
    if(color == bmp->date[i])
    {
      count++;
    }
    else
    {
      tft.writeColor(color,count); 
      count = 1;
      color = bmp->date[i];
    }
  }
  tft.writeColor(color,count); 
  tft.endWrite();
}


/**@brief Function to be executed on Radio Rx Done event */
void OnRxDone(uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr)
{
    Serial.println("OnRxDone");
    delay(10);
    memcpy(RcvBuffer, payload, size);
    Serial.printf("RssiValue=%d dBm, SnrValue=%d\n", rssi, snr);

if(strcmp(reinterpret_cast<const char*>(RcvBuffer), reinterpret_cast<const char*>(receivedData)) != 0){
      // Free previously allocated memory if any
      if (receivedData) {
          delete[] receivedData;
      }

      // Allocate memory to store the payload + 1 for the null terminator
      receivedData = new char[size + 1];

      // Copy the actual characters from RcvBuffer to receivedData
      memcpy(receivedData, RcvBuffer, size);
      
      // Null-terminate the string
      receivedData[size] = '\0';

      // Print receivedData to see the content
      Serial.println(receivedData);

      tft.fillScreen(ST77XX_BLACK);
      testdrawtext(receivedData,ST77XX_WHITE);

      
      Radio.Rx(RX_TIMEOUT_VALUE); 
    }
}

/**@brief Function to be executed on Radio Rx Timeout event
 */
void OnRxTimeout(void)
{
    Serial.println("OnRxTimeout");
    Radio.Rx(RX_TIMEOUT_VALUE);
}

/**@brief Function to be executed on Radio Rx Error event
 */
void OnRxError(void)
{
    Serial.println("OnRxError");
    Radio.Rx(RX_TIMEOUT_VALUE);
}

Hi @Dhruv ,

I run your code but it doesn’t display anything. Obviously, there are parts of the code removed.

There various ways how to handle displays but one you can use as reference is the open source code of the RAK10701 field tester which uses MillisTaskManager library. You can also use millis() without using the library or implement your application with RTOS to ensure the timing on refreshing values is minimal and predictable.

These are the github link for reference.