Menu freezes UNO hard

For some reason this particular function will cause the uno to lock up as in everything stopping functioning and some strings returned to serial are garbage just before freeze. I narrowed it down to here by commenting out call and finding it works fine when bypassed. I can't post whole code as it's too long.

void menuM1() {
  char lcdOut0[20];
  char lcdOut1[20];
  char timeM[4][20] = { {"Time Set"}, {"Auto/NTP Time Set"}, {"Temp Timeout"}, {"Fan Timeout."} };
  char scheduleM[4][20] =  { {"Set # of blocks"}, {"Select Block"}, {"Set block time"}, {"Set block Temp"}};
  char fanM[4][20] = { {"On with H/C"}, {"On all time"}, {"Post-mix..."}, {"On Every..."} };
  char tempM[4][20] = { {"Hysteresis"}, {"Temp. Alerts"}, {"."}};
  char lockM[4][20] = { {"Lock On/Off"} , { "Lock Timeout" }, { '.' }, { '.' }};
  switch (menuIDa) {
    case 0: //Time Menu
      strncpy(lcdOut0, timeM[menuIndex], 20);
      strncpy(lcdOut1, timeM[menuIndex + 1], 20);
      break;
    case 1: //Schedule Menu
      strncpy(lcdOut0, scheduleM[menuIndex], 20);
      strncpy(lcdOut1, scheduleM[menuIndex + 1], 20);
      break;
    case 2: //Fan Menu
      strncpy(lcdOut0, fanM[menuIndex], 20);
      strncpy(lcdOut1, fanM[menuIndex + 1], 20);
      break;
    case 3: //Lock Menu
      strncpy(lcdOut0, lockM[menuIndex], 20);
      strncpy(lcdOut1, lockM[menuIndex + 1], 20);
    case 4: //Temperature Menu
      strncpy(lcdOut0, tempM[menuIndex], 20);
      strncpy(lcdOut1, tempM[menuIndex + 1], 20);
      break;
  }
  Serial.print('*');
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");
}

That throws at least 440 bytes on the stack. You think you've got enough memory?

I'm getting close. I think I need more than an Uno for this thermostat project. I tend to over-use globals, but I use functions that need to share any number of vars. I comment out a lot of global but the usage never goes down. Funny thing is I comment out the function in question, global var usage drops.

Sketch uses 15344 bytes (47%) of program storage space. Maximum is 32256 bytes.
Global variables use 1406 bytes (68%) of dynamic memory, leaving 642 bytes for local variables. Maximum is 2048 bytes.

Here are my global declares:

int currentMM, currentHH;
int HHOffset, MMOffset, cursorPosition = 0, menuIndex = 0, menuIDa = 0, menuIDb, menuIDc, menuDepth = 0;
int millisPrior, subLoop, tempReadI, locked, seed, scheduleHH, scheduleMM, scheduleTemp, tempSetting, currentTemp, systemOnMS, systemPrev;
int ntpOn;
int flasherA[5][7] = { 0 };
unsigned long menuStartMS, flasherL[5];
char* lcdMode, currentBlock;
//float tempRounded = 70.5;
String currentTimeStr, modeName;


// PIN-MAP
//*****************************************************************************************************************************************************************
// -1: InputPullup, 0: Not installed, 1: Input Positive, 2: OUTPUT
int installed[20] = {   0,  0,   2,      2,    2,     0,    2,    0,    0,     2,     2,     2,    1,      0,    1,     0,      0,    0,     0,          0 };
char* pinNames[20] = { '0', '1', '2',   '3',   '4',   '5', '6', '7',   '8',   '9',  "10",  "11", "12",  "13",  "A0",  "A1",  "A2",  "A3",  "A4",      "A5"  };
char* ssNames[20] = {  "x", "x", "FN6", "HT6", "AC6", "x", "LB6", "x", "x", "LO6", "LR6", "LG6",  "tm6", "LED",   "sd6", "x", "x", "x", "x", "x" };
const int                       FN6 = 2,     AC6 = 4,     LB6 = 6,                         LG6 = 11,     LED = 13,       sd6 = A0     ;
const int                             HT6 = 3,                          LO6 = 9, LR6 = 10,      tm6 = 12      ;
// *****************************************************************************************************************************************************************

All of these character constants can be stored in flash memory, instead of wasting precious RAM.

 char timeM[4][20] = { {"Time Set"}, {"Auto/NTP Time Set"}, {"Temp Timeout"}, {"Fan Timeout."} };