Adafruit 3.5" tft display, GFX, HX8357 locking up

The combination of Adafruit 3.5" display, GFX, and HX8357 libraries is locking up in the sketch below. The sketch just calls ShiftKey() to switch between lower case and upper case chars every 2 seconds.

Unfortunately, it starts out with lower case, switches to upper case, back to lower case, and then locks up every time.

I am using the latest versions of both libraries and Arduino UNO with Arduino version 1.8.10 software.

The lower and upper case displays are attached. What am I missing?

#include "Adafruit_HX8357.h"
#include <Adafruit_GFX.h>
#include "TouchScreen.h"

// The display uses hardware SPI, plus #9 & #10
#define TFT_RST -1  // tied to arduino RST 
#define TFT_DC 9
#define TFT_CS 10

// These are the four touchscreen analog pins
#define YP A2  // must be an analog pin, use "An" notation!
#define XM A3  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 8   // can be a digital pin

// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 115   // bottom
#define TS_MINY 75
#define TS_MAXX 910
#define TS_MAXY 925
#define MINPRESSURE 5
#define MAXPRESSURE 1000

// cell and text size
#define CELLWIDTH 35
#define CELLHEIGHT 45
#define TEXTSIZE 3

// Blinking cursor home
#define CURXSTART 72
#define CURYSTART 12

// Colors
#define SCREENCOLOR 0xB5B6
#define BLACK 0x0000
#define WHITE 0xFFFF

Adafruit_HX8357 tft = Adafruit_HX8357(TFT_CS, TFT_DC, TFT_RST);
TouchScreen tscr = TouchScreen(XP, YP, XM, YM, 500);

int ts[7][2] = {{4, 6}, {6, 6}, {10, 12}, {16, 20}, {22, 28}, {28, 34}, {32, 42}};
boolean shifted = false;
boolean keyboardActive = false;
boolean cursorOn = false;
int curX = CURXSTART;
int curY = CURYSTART;
int index = 0;
boolean escape = false;
boolean textComplete = false;
String lowQwert = "qwertyuiopasdfghjkl-zxcvbnm<>+,.[]\\/|\"""_'";
String uprQwert = "QWERTYUIOPASDFGHJKL-ZXCVBNM<>+,.[]\\/|\"""_'";
String numbers = "1234567890";
String symbols = "!@#$%^&*()";
char text[19];
unsigned long timeNow, timeLast;

typedef struct charLocations
{
  char lChar;
  char uChar;
  int x;
  int y;
};
charLocations charLocs[50];

typedef struct specialLocations
{
  int x;
  int y;
  int16_t (*funct)();
};
specialLocations specialLocs[6];

void setup()
{
  Serial.begin(115200);
  tft.begin();
  lowQwert.replace("\"", "\\\"");             // fix the escape charater (\) in the lowQwert string
  uprQwert.replace("\"", "\\\"");             // fix the escape charater (\) in the uprQwert string
  loadArray();
  tft.fillScreen(SCREENCOLOR);
  DrawTextBox();
  DrawKeyboard();
  // timeLast = millis();
}

void loop()
{
  delay(1000);
  ShiftKey();
}

void BackSpaceKey()
{
}

void EnterKey()
{
}

void EscapeKey()
{
}

void SpaceKey()
{
}

void ShiftKey()
{
  shifted = !shifted;
  ReDrawCharacters();
}

String ReDrawCharacters()
{
  tft.setRotation(1);
  tft.setTextSize(3);
  tft.setTextColor(BLACK);

  // clear the first 4 rows of characters (row 5 never changes)
  for (int r = 0; r < 4; r++)                                       // 5 row loop
  {
    for (int c = 0; c < 10; c++)                                    // 10 column loop
    {
      tft.fillRect(70 + c * CELLWIDTH, r * (CELLHEIGHT - 1) + 78, 20, 24, SCREENCOLOR);
    }
  }

  // redraw the first 4 rows of characters
  for (int r = 0; r < 4; r++)                                       // 5 row loop
  {
    for (int c = 0; c < 10; c++)                                    // 10 column loop
    {
      tft.setCursor(70 + c * CELLWIDTH, r * CELLHEIGHT - 1 + 78);
      if (shifted)                                                 // is the keyboard shifted?
      {
        tft.print(charLocs[r * 10 + c].uChar);                     // yes
      }
      else
      {
        tft.print(charLocs[r * 10 + c].lChar);                     // no
      }
    }
  }
}

void ChangeCursor()
{
  cursorOn = !cursorOn;

  tft.setRotation(1);

  if (cursorOn)
    tft.fillRect(curX, curY, 8, 36, BLACK);
  else
    tft.fillRect(curX, curY, 8, 36, WHITE);
}

void DrawKeyboard()
{
  keyboardActive = true;
  tft.setRotation(1);
  tft.setTextSize(3);
  tft.setTextColor(BLACK);

  // draw the outside box
  tft.drawRect(60, 65, 354, 225, BLACK);

  // draw the vertical and horizontal cell divider lines
  for (int i = 0; i < 9; i++)
  {
    tft.drawFastVLine(100 + i * 34, 65, 218, BLACK);
    if (i % 2 == 0)
      tft.drawFastHLine(61, 65 + 44 * i / 2, 352, BLACK);
  }

  // draw 5 rows of characters
  for (int r = 0; r < 5; r++)                                     // 5 row loop
  {
    for (int c = 0; c < 10; c++)                                  // 10 column loop
    {
      tft.setCursor(70 + c * CELLWIDTH, r * 44 + 78);
      if (shifted)                                                // is the keyboard shifted?
      {
        tft.print(charLocs[r * 10 + c].uChar);                    // yes
      }
      else
      {
        tft.print(charLocs[r * 10 + c].lChar);                    // no
      }
    }
  }

  // draw the special keys
  tft.drawRect(1, 65, 60, CELLHEIGHT, BLACK);                     // draw the escape key
  tft.setCursor(5, 78);
  tft.print("ESC");

  tft.drawRect(413, 65, 65, CELLHEIGHT, BLACK);                   // draw the backspace key
  tft.setCursor(432, 78);
  tft.print("BS");

  tft.drawRect(413, 109, 65, 89, BLACK);                          // draw the enter key
  tft.setCursor(421, 145);
  tft.print("ENT");

  tft.drawRect(1, 241, 60, 49, BLACK);                            // draw the shift key
  tft.setCursor(5, 255);
  tft.print("SFT");

  tft.drawRect(413, 197, 65, 93, BLACK);                          // draw the space key
  tft.setCursor(431, 232);
  tft.print("SP");
}

void DrawTextBox()
{
  curX = CURXSTART;
  curY = CURYSTART;
  index = 0;
  tft.setRotation(1);
  tft.fillScreen(SCREENCOLOR);
  tft.fillRect(70, 10, 336, 40, WHITE);        // draw the input text box
}

void loadArray()
{
  // load numbers and symbols
  for (int i = 0; i < 10; i++)
  {
    charLocs[i].lChar = numbers[i];
    charLocs[i].uChar = symbols[i];
  }

  // load characters
  for (int i = 10; i < 50; i++)
  {
    charLocs[i].lChar = lowQwert[i - 10];
    charLocs[i].uChar = uprQwert[i - 10];
  }

  // load character locations
  int i = 0;
  for (int r = 0; r < 5; r++)
    for (int c = 0; c < 10; c++)
    {
      charLocs[i].x = 70 + c * CELLWIDTH;
      charLocs[i++].y = r * 44 + 78;
    }

  // load the special keys
  specialLocs[4].x = 1;                                 // load the escape key
  specialLocs[4].y = 65;
  specialLocs[4].funct = EscapeKey;

  specialLocs[3].x = 413;                               // load the backspace key
  specialLocs[3].y = 65;
  specialLocs[3].funct = BackSpaceKey;

  specialLocs[1].x = 413;                               // load the enter key
  specialLocs[1].y = 109;
  specialLocs[1].funct = EnterKey;

  specialLocs[0].x = 1;                                 // load the shift key
  specialLocs[0].y = 241;
  specialLocs[0].funct = ShiftKey;

  specialLocs[2].x = 413;                               // load the space key
  specialLocs[2].y = 197;
  specialLocs[2].funct = SpaceKey;
}

[/code]

IMG_4520.jpg

IMG_4521.jpg

After 2 days, I got this working but I do not understand why it was broken in the first place.

At line 116 the function is "String ReDrawCharacters()". I changed that to "void ReDrawCharacters()" because I was no longer returning anything and that fixed it. The sketch has been running fine for 2 hours.

Apparently creating a function with a return type and not actually returning something doesn't cause an error, but it certainly broke this sketch.

I am happily continuing on now but would appreciate any insight as to why that broke the sketch.