Color TfT Clock Sketch

Definitions and Declarations

/*

   This is for the wood box controller with a color display.

   It has the following components:

   A 3.5" tft color 480x360 color display shield with a micro SD socket,

   An ATMEGA 2560 Rev3 Arduino,

   An intermediary proto shield with attached battery charger and discrete components,

   A 3-way toggle switch and an incremental encoder with pushbutton,

   An RC8803 real-time clock-calendar,

   A DME688 environmental sensor,

   John Saunders 1/17/2022

*/

// --------------- Display includes, etc ---------------

#include <MCUFRIEND_kbv.h>   // Hardware-specific library

#include <Adafruit_GFX.h>    // Core graphics library

#include <EEPROM.h>

#include <FreeDefaultFonts.h>

#include <Fonts/FreeSerif18pt7b.h>

#include <Fonts/FreeSans24pt7b.h>

MCUFRIEND_kbv tft;

#define BLACK   0x0000

#define RED     0xF800

#define ORANGE  0xFDA0

#define YELLOW  0xFFE0

#define GREEN   0x07E0

#define WHITE   0xFFFF

#define BLUE    0X00FF

#define CYAN    0x07FF

#define MAGENTA 0xF81F

#define GREY    0x8410


#define ID      0x9486


// -------- Secure Digital Drive includes, etc -----------

#include <SPI.h>

#include <SD.h>

#define SS 53

#define CMDS 67

#define DISPS 68


// --------------- RTC includes, etc ---------------

#include <SparkFun_RV8803.h>

RV8803 rtc;


// --------------- DME688 includes, etc ---------------

#include "Zanshin_BME680.h"

BME680_Class BME680;


// ------------ Control & Sensing defines ---------------

#define SWUP 22              // Toggle switch up, low active

#define SWDN 24               // Toggle switch dowwn, low active

#define usbTestPort A5

#define testControlPort 47

#define HOMEPAGE 15

#define INFOPAGE 11

#define PAGE2 12

#define PAGE3 14

#define PAGE4 10

#define PAGE5 8

#define PAGE6 0

#define PAGE1 13

#define ADJHOUR 7

#define ADJWD 5

#define ADJDATE 4

#define ADJMONTH 6

#define ADJYEAR 2

#define ADJMIN 3

#define SETTEMP 9

#define SETPRESS 1



// ------------ Constants -----------------------

const int bigTimeLoc = 150;

const int infoTimeLoc = 240;

const int adjFlagLoc = 260;

const uint8_t hiLimit[5] = {59, 23, 6, 31, 11};

const uint8_t loLimit[5] = { 0,  0, 0,  1,  0};

const int hiMode = 368;

// const int loMode = 301;

const int loMode = 280;               //11/17/2022

const int tempEAddr = 5;

const int pressEAddr = 7;


const String days[7] = {

  "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"

};

const String months[12] = {

  "January", "February", "March", "April", "May", "June", "July",

  "August", "September", "October", "November", "December"

};


const String hdrText[] = {

  "Living Room Lights", "Outside Lights", "Cube Alarm", "Atmosphere", "Color LED Display", "Tower Display"

};


const byte codeType[] = {

  CMDS, CMDS, CMDS, DISPS, DISPS, DISPS

};


const int onPos = 330;

const int offPos = 400;

const int codePos = 380;

const int numPlates = 87;

const int numUnames = 14;

const int numCaps = 40;

const int numFiles = 18;

// The program shows an 8-character password with lower and upper-case letters,

// numbers and symbols from plates and caps. 

// The combination is a 6-number code in a file on a micro SD chip, including

// the login name from unames.

const String plates[numPlates] = {

  // 0            1           2              3           4            5            6           7            8          9

 "00to09","Betsy2","gh7097","yrb598","Midnig","A399/6","fgh345","4pty14","Betsy2","2+5:3”

"10to19","6ksub3","312spa","132spa","2aur32","bla649","5y4499","681frg","6ksub3","aa01a3”

”20to29","dhy790","1cF228","bny289","betsy2","fcc832","2cf460","dfg265","dhy790","4dkj21”

”30to39","gnr490","fvv775","1fr662","jqw061","kgy114","ghe136","ghj345","gnr490","jgh345”

"40to49","kku966","khh678","khh644","kvp773","2kwn25","khh669","khj284","kku966","kpd247”

"50to59","mcj782","lhh678","le7926","mnb293","old861","lkl947","2m8782","mcj782","mdt700”

”60to69","pvo085","ptd922","ozk901","rzv493","sheel3","pty147","pty516","pvo085","pxj106”

”70to79","vhj491"," srarty","sna338","xvz665","yax738","suy808","tuk425","vhj491","wkc453”

”80to89","cvh140","sdp765","U49-pl","cvh140","dfg765","lsy942","jkl890"

};


const String unames[numUnames] = {

  // 0                  1                       2                  3

    //Deleted for security. These are actual email addresses or login names

  //   4          5             6                7           8             9

    //Deleted for security

  //  10             11              12           13

    //Deleted for security};


const String caps[numCaps] = {  // These are made up

  //0    1    2       3    4     5      6    7      8    9

  //Deleted for security. These are two additional characters

  //10   1     2      3     4     5      6     7    8     9

    //Deleted for security

  //20    1     2     3    4      5      6      7     8    9

  //Deleted for security

    //30    1    2       3    4      5      6     7      8    9

  //Deleted for security

  "};


String filenameList[numFiles] = {

  // 0      1      2      3      4      5

  "C00", "C01", "C02", "D00", "D01", "D02",

  // 6      7      8     9      10    11

  "W01", "W02", "W03", "W04", "W05", "W06",

  //12     13     14    15      16     17

  "W07", "W08", "W09", "W10", "W11", "W12"

};


enum enumTimeDate {

  EMIN, EHR, EWD, EDAT, EMTH

};


// ------------------------- Global Variables ---------------------

uint8_t nowInts[5];   //minutes,hours,weekday,date,month)

boolean chgFlag, modeFlag;

int tempFlag, pressFlag;

enumTimeDate setIndex;

uint8_t currSeconds, prevSeconds, prevMinutes, prevHours, prevWeekday;

uint16_t fullYear;

int32_t prevTemp, prevHumidity, prevPressure, prevGas, prevVccVolts;

int adjTimeLoc = 130;

int spacing = 43;

int indent = 5;

int pwPos = 320;

int ypos = 20;

bool sdInit;          //11/17/2023

Setup and Loop

void setup() {

  pinMode(SS, OUTPUT);              // Wired CS pin for SDI

  digitalWrite(SS, HIGH);

  pinMode(testControlPort, OUTPUT);

  digitalWrite(testControlPort, 0);

  for (byte i = 22; i <= 34; i++) {  //Controls

    pinMode(i, INPUT_PULLUP);

  }


  // display

  tft.begin(ID);

  tft.setRotation(1);

  tempFlag = EEPROM.read(tempEAddr);

  pressFlag = EEPROM.read(pressEAddr);

  analogReference(DEFAULT);

  modeFlag = false;


  // rtc

  Wire.begin();

  rtc.begin();

  prevSeconds = 0;

  prevMinutes = 0;

  prevHours = 0;

  fillTimeDate();

  prevWeekday = nowInts[EWD];

  chgFlag = false;

  rtc.set24Hour();

  tft.fillScreen(BLACK);



  // BME688

  BME680.begin(I2C_FAST_MODE); // Start BME680 using I2C protocol

  BME680.setOversampling(TemperatureSensor, Oversample16); // Use enumerated type values

  BME680.setOversampling(HumiditySensor,   Oversample16); // Use enumerated type values

  BME680.setOversampling(PressureSensor,   Oversample16); // Use enumerated type values

  BME680.setIIRFilter(IIR4); // Use enumerated type values

  BME680.setGas(320, 150); // 320c for 150 milliseconds


  randomSeed(rtc.getSeconds());

  //   delay(300);

  delay(500);                   // 11/17/2022

  // Secure Digital Drive

  sdInit = SD.begin(SS);        //11/17/2022


}


void loop() {

  static int prevEncoderPosition = HOMEPAGE;

  modeFlag = (analogRead(usbTestPort) < hiMode) && (analogRead(usbTestPort) > loMode);

  if (modeFlag) {

    adjTimeLoc = 120;

  }

  else {

    adjTimeLoc = 130;

  }

  fillTimeDate();

  int encoderPosition = digitalRead(26) + (2 * digitalRead(28)) + (4 * digitalRead(30)) + (8 * digitalRead(32));

  if ((encoderPosition != prevEncoderPosition) || (nowInts[EWD] != prevWeekday)) {

    tft.fillScreen(BLACK);

    displayFixed(encoderPosition);

    prevEncoderPosition = encoderPosition;

    prevSeconds = 0;

    prevMinutes = 0;

    prevHours = 0;

  }

  displayVariable(encoderPosition);

}

Functions

// ------------------------- Second level Functions ---------------------


void fillTimeDate(void) {

  rtc.updateTime();

  currSeconds = rtc.getSeconds();;

  nowInts[EMIN] = rtc.getMinutes();

  nowInts[EHR] = rtc.getHours();

  nowInts[EWD] = rtc.getWeekday();

  nowInts[EDAT] = rtc.getDate();

  nowInts[EMTH] = rtc.getMonth() - 1;

  fullYear = rtc.getYear();

}


void setTimeDate(enumTimeDate index) {

  switch (index) {

    case EMIN:

      rtc.setMinutes(nowInts[EMIN]);

      break;

    case EHR:

      rtc.setHours(nowInts[EHR]);

      break;

    case EWD:

      rtc.setWeekday(nowInts[EWD]);

      break;

    case EDAT:

      rtc.setDate(nowInts[EDAT]);

      break;

    case EMTH:

      rtc.setMonth((nowInts[EMTH] + 1));

      break;

  }

}


void displayTime(int row) {

  if (row > 360) {

    return;

  }

  tft.setFont(&FreeSerif18pt7b);

  tft.setTextSize(1);

  if (nowInts[EHR] != prevHours) {

    tft.setCursor(10, row);

    tft.setTextColor(BLACK);

    tft.print(prevHours);

    tft.setTextColor(WHITE);

    tft.setCursor(10, row);

    tft.print(nowInts[EHR]);

    prevHours = nowInts[EHR];

  }

  if (nowInts[EMIN] != prevMinutes) {

    tft.setCursor(60, row);

    tft.setTextColor(BLACK);

    tft.print(prevMinutes);

    tft.setTextColor(WHITE);

    tft.setCursor(60, row);

    tft.print(nowInts[EMIN]);

    prevMinutes = nowInts[EMIN];

  }

}


void displayDate(int row) {

  tft.setFont(&FreeSerif18pt7b);

  tft.setTextColor(WHITE);

  tft.setCursor(50, row);

  tft.print(":");

  tft.setCursor(105, row);

  tft.print(days[nowInts[EWD]]);

  tft.setCursor(105, (row + 45));

  tft.print(months[nowInts[EMTH]]);

  tft.print(" ");

  tft.print(nowInts[EDAT]);

  tft.print(" ");

  tft.print(fullYear);

  prevWeekday = nowInts[EWD];

}

void displayHeading(byte indx) {

  const int vlc1Pos = 350;

  const int vlc2Pos = 422;

  const int vldPos = 420;

  const int hlPos = 50;

  indent = 10;

  ypos = 35;

  tft.setFont(&FreeSerif18pt7b);

  tft.setTextColor(WHITE);

  tft.setCursor(indent, ypos);

  tft.print(hdrText[indx]);

  if (codeType[indx] == CMDS) {

    tft.drawFastVLine(vlc1Pos, hlPos, 300, GREEN);

    tft.setCursor(onPos, ypos);

    tft.print("ON");

    tft.drawFastVLine(vlc2Pos, hlPos, 300, GREEN);

    tft.setCursor(offPos, ypos);

    tft.print("OFF");


  }

  else {

    tft.drawFastVLine(vldPos, hlPos, 300, GREEN);

    tft.setCursor(codePos, ypos);

    tft.print("CODE");

  }

  tft.drawFastHLine(0, hlPos, 475, GREEN);

}


void Adjust(enumTimeDate indx) {

  if (modeFlag) {

    return;

  }

  if (!chgFlag) {

    if (digitalRead(SWUP) == 0) {

      if (nowInts[indx] < hiLimit[indx]) {

        nowInts[indx]++;

      }

      else {

        nowInts[indx] = loLimit[indx];

      }

      chgFlag = true;

      setIndex = indx;

    }

    if (digitalRead(SWDN) == 0) {

      if (nowInts[indx] > loLimit[indx]) {

        nowInts[indx]--;

      }

      else {

        nowInts[indx] = hiLimit[indx];

      }

      chgFlag = true;

      setIndex = indx;

    }

    if (chgFlag) {

      setTimeDate(indx);

      fillTimeDate();

      displayTime(adjTimeLoc);

      tft.fillRect(105, (adjTimeLoc - 42), 300, 80, BLACK);

      displayDate(adjTimeLoc);

      chgFlag = false;

      while ((digitalRead(SWUP) == 0) || (digitalRead(SWDN) == 0));

    }

  }

}


void adjustYear(void) {

  if (modeFlag) {

    return;

  }

  uint16_t currYear = rtc.getYear();

  if (!chgFlag) {

    if (digitalRead(SWUP) == 0) {

      if (currYear < 2040) {

        currYear++;

      }

      else {

        currYear = 2000;

      }

      chgFlag = true;

    }

    if (digitalRead(SWDN) == 0) {

      if (currYear > 1934) {

        currYear--;

      }

      else {

        currYear = 2000;

      }

      chgFlag = true;

    }

    if (chgFlag) {

      rtc.setYear(currYear);

      fillTimeDate();

      displayTime(adjTimeLoc);

      tft.fillRect(105, (adjTimeLoc - 31), 270, 80, BLACK);

      displayDate(adjTimeLoc);

      chgFlag = false;

      while ((digitalRead(SWUP) == 0) || (digitalRead(SWDN) == 0));

    }

  }

}


// ------------ Top-level Display Functions ---------------


void displayWfile(byte filenameIndex) {

  File myFile;

  String filename;

  char item;

  int line = 0;

  int numBuf[8];

  int indx;

  ypos = 22;

  indent = 0;

  spacing = 29;

  if ((filenameIndex < 0) || (filenameIndex >= numFiles)) {

    filenameIndex = 6;

  }

  filename = String("/");

  filename += String(filenameList[filenameIndex]);

  filename += String(".txt");

  Serial.println(filename);

  if (sdInit) {                     // 11/17/2022

    myFile = SD.open(filename);

  }

  else {

    sdInit = SD.begin(SS);

  }

  if (myFile) {

    // read from the file until there's nothing else in it:

    tft.fillScreen(BLACK);

    tft.setCursor(indent, ypos);

    tft.setFont(&FreeSerif18pt7b);

    tft.setTextColor(WHITE);

    while ((myFile.available()) && (digitalRead(SWDN) == 1)) {

      for (int i = 0; i < 6; i ++) {

        item = myFile.read();

        numBuf[i] = item;

      }

      do {

        item = myFile.read();

        tft.print(item);

      } while (item != '\n');

      ypos += spacing;

      tft.setCursor(indent, ypos);

      indx = 10 * numBuf[0] + numBuf[1] - 528;

      tft.print(unames[indx]);

      tft.setCursor(pwPos, ypos);

      indx = 10 * numBuf[2] + numBuf[3] - 528;

      tft.print(plates[indx]);

      indx = 10 * numBuf[4] + numBuf[5] - 528;

      tft.print(caps[indx]);

      line++;

      if (line < 4) {

        ypos += 20;

        tft.drawFastHLine(0, ypos, 420, GREEN);

        ypos += 10;

      }

      else {

        break;

      }

      ypos += spacing;

      tft.setCursor(indent, ypos);

    }

  }

  else {

    tft.setCursor(indent, 150);

    tft.setFont(&FreeSerif18pt7b);

    tft.print("Could not open file ");

    tft.print(filename);

  }

  // close the file:

  myFile.close();

  delay(1000);

}


void displayList(byte filenameIndex) {

  File myFile;

  String filename;

  char item;

  ypos = 90;

  indent = 0;

  spacing = 32;

  char codes[2];

  if ((filenameIndex < 0) || (filenameIndex >= numFiles)) {

    filenameIndex = 6;

  }

  filename = String("/");

  filename += String(filenameList[filenameIndex]);

  filename += String(".txt");

  Serial.println(filename);

  if (sdInit) {

    myFile = SD.open(filename);

  }

  else {

    sdInit = SD.begin(SS);

  }

  if (myFile) {

    tft.setCursor(indent, ypos);

    tft.setFont(&FreeSerif18pt7b);

    while ((myFile.available()) && (digitalRead(SWDN) == 1)) {

      for (int i = 0; i < 2; i ++) {

        item = myFile.read();

        codes[i] = item;

      }

      do {

        item = myFile.read();

        tft.print(item);

      } while (item != '\n');

      if (codeType[filenameIndex] == CMDS) {

        tft.setCursor((onPos + 40), ypos);

        tft.print(codes[0]);

        tft.setCursor((offPos + 40), ypos);

        tft.print(codes[1]);

      }

      else {

        tft.setCursor((codePos + 50), ypos);

        tft.print(codes[0]);

        tft.print(codes[1]);

      }

      ypos += spacing;

      tft.setCursor(indent, ypos);

    }

  }

  else {

    tft.setCursor(indent, 150);

    tft.setFont(&FreeSerif18pt7b);

    tft.print("Could not open file ");

    tft.print(filename);

  }

  // close the file:

  myFile.close();

}


void displayFixed(int pos) {

  tft.setFont(&FreeSans24pt7b);

  tft.setTextColor(CYAN);

  tft.setTextSize(1);

  tft.setCursor(10, 50);

  switch (pos) {

    case HOMEPAGE:

      tft.setFont(&FreeSans24pt7b);

      tft.setCursor(20, 50);

      tft.setTextColor(WHITE);

      tft.print("John's ");

      tft.setTextColor(RED);

      tft.print("C");

      tft.setTextColor(ORANGE);

      tft.print("O");

      tft.setTextColor(YELLOW);

      tft.print("L");

      tft.setTextColor(GREEN);

      tft.print("O");

      tft.setTextColor(BLUE);

      tft.print("R");

      tft.setTextColor(WHITE);

      tft.print(" Clock");

      tft.setFont(&FreeSerif18pt7b);

      tft.setTextSize(2);

      tft.setCursor(150, bigTimeLoc);

      tft.print(":");

      tft.setCursor(250, bigTimeLoc);

      tft.print(":");

      tft.setTextSize(1);

      tft.setCursor(20, 220);

      tft.println(" John Saunders");

      tft.println(" Designed and made it in 2022");

      tft.print(" He was 88 years old!");

      break;

    case INFOPAGE:

      displayDate(infoTimeLoc);

      tft.setCursor(10, 35);

      tft.setFont(&FreeSerif18pt7b);

      tft.setTextColor(MAGENTA);

      tft.print("Temperature = ");

      tft.setCursor(330, 35);

      tft.print((char)tempFlag);

      tft.setCursor(10, 70);

      tft.setTextColor(GREEN);

      tft.print( "Humidity = ");

      tft.setCursor(300, 70);

      tft.print("%");

      tft.setCursor(10, 105);

      tft.setTextColor(YELLOW);

      tft.print("Pressure = ");

      tft.setCursor(300, 105);

      if (pressFlag == 80) {

        tft.print("hPa");

      }

      else {

        tft.print("in Hg");

      }

      tft.setTextColor(CYAN);

      tft.setCursor(10, 140);

      tft.print( "Gas resistance = ");

      tft.setTextColor(ORANGE);

      tft.setCursor(10, 175);

      tft.print( "USB Volts = ");

      tft.setCursor(280, 175);

      tft.print("V");

      prevTemp = 0;

      prevHumidity = 0;

      prevPressure = 0;

      prevGas = 0;

      prevVccVolts = 0;

      break;

    case PAGE1:

      displayHeading(0);

      if (modeFlag) {

        displayWfile(6);

      }

      else {

        displayList(0);

      }

      break;

    case PAGE2:

      displayHeading(1);

      if (modeFlag) {

        displayWfile(7);

      }

      else {

        displayList(1);

      }

      break;

    case PAGE3:

      displayHeading(2);

      if (modeFlag) {

        displayWfile(8);

      }

      else {

        displayList(2);

      }

      break;

    case PAGE4:

      displayHeading(3);

      if (modeFlag) {

        displayWfile(9);

      }

      else {

        displayList(3);

      }

      break;

    case PAGE5:

      displayHeading(4);

      if (modeFlag) {

        displayWfile(10);

      }

      else {

        displayList(4);

      }

      break;

    case PAGE6:

      displayHeading(5);

      if (modeFlag) {

        displayWfile(11);

      }

      else {

        displayList(5);

      }

      break;

    case ADJHOUR:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(16);

      }

      else {

        tft.print("Adjust Hour");

        displayDate(adjTimeLoc);

      }

      break;

    case ADJWD:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(15);

      }

      else {

        tft.print("Adjust Weekday");

        displayDate(adjTimeLoc);

      }

      break;

    case ADJDATE:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(14);

      }

      else {

        tft.print("Adjust Date");

        displayDate(adjTimeLoc);

      }

      break;

    case ADJMONTH:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(13);

      }

      else {

        tft.print("Adjust Month");

        displayDate(adjTimeLoc);

      }

      break;

    case ADJYEAR:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(12);

      }

      else {

        tft.print("AdjustYear");

        displayDate(adjTimeLoc);

      }

      break;

    case ADJMIN:

      spacing = 29;

      ypos = 22;

      indent = 0;

      if (modeFlag) {

        displayWfile(17);

      }

      else {

        tft.print("Adjust Minutes");

        displayDate(adjTimeLoc);

      }

      break;

    case SETTEMP:

      if (modeFlag) {

        tft.println(" Password Generator");

      }

      else {

        tft.println("Set Temperature Units");

        tft.setCursor(10, adjTimeLoc);

        tft.print("Units set to ");

      }

      break;

    case SETPRESS:

      tft.print("Set Pressure Units");

      tft.setCursor(10, adjTimeLoc);

      tft.print("Units set to ");

      break;

  }

}


void displayVariable(int pos) {

  const byte pwLoLimit[8] = { 97, 97, 97, 48, 48, 48, 35, 65};

  const byte pwHiLimit[8] = {122, 122, 122, 57, 57, 57, 43, 90};

  switch (pos) {

    case HOMEPAGE:

      tft.setFont(&FreeSerif18pt7b);

      tft.setTextSize(2);

      if (nowInts[EHR] != prevHours) {

        tft.setCursor(75, bigTimeLoc);

        tft.setTextColor(BLACK);

        tft.print(prevHours);

        tft.setTextColor(WHITE);

        tft.setCursor(75, bigTimeLoc);

        tft.print(nowInts[EHR]);

        prevHours = nowInts[EHR];

      }

      if (nowInts[EMIN] != prevMinutes) {

        tft.setCursor(175, bigTimeLoc);

        tft.setTextColor(BLACK);

        tft.print(prevMinutes);

        tft.setTextColor(WHITE);

        tft.setCursor(175, bigTimeLoc);

        tft.print(nowInts[EMIN]);

        prevMinutes = nowInts[EMIN];

      }

      if (currSeconds != prevSeconds) {

        tft.setTextColor(BLACK);

        tft.setCursor(275, bigTimeLoc);

        tft.print(prevSeconds);

        tft.setTextColor(WHITE);

        tft.setCursor(275, bigTimeLoc);

        tft.print(currSeconds);

        prevSeconds = currSeconds;

      }

      break;

    case INFOPAGE:

      displayEnvironmental();

      displayTime(infoTimeLoc);

      break;

    case PAGE2:

      break;

    case PAGE3:

      break;

    case PAGE4:

      break;

    case PAGE5:

      break;

    case PAGE6:

      break;

    case PAGE1:

      break;

    case ADJHOUR:

      displayTime(adjTimeLoc);

      Adjust(EHR);

      break;

    case ADJWD:

      displayTime(adjTimeLoc);

      Adjust(EWD);

      break;

    case ADJDATE:

      displayTime(adjTimeLoc);

      Adjust(EDAT);

      break;

    case ADJMONTH:

      displayTime(adjTimeLoc);

      Adjust(EMTH);

      break;

    case ADJYEAR:

      displayTime(adjTimeLoc);

      adjustYear();

      break;

    case ADJMIN:

      displayTime(adjTimeLoc);

      Adjust(EMIN);

      break;

    case SETTEMP:

      tft.setTextColor(WHITE);

      if (modeFlag) {

        tft.fillRect(35, (adjTimeLoc - 40), 300, 50, BLACK);

        tft.setCursor(40, adjTimeLoc);

        for (int i = 0; i < 8; i++) {

          tft.print((char)random(pwLoLimit[i], pwHiLimit[i]));

        }

        while (digitalRead(SWDN) == 1);

      }

      else {

        tft.fillRect(adjFlagLoc, (adjTimeLoc - 40), 70, 50, BLACK);

        tft.setCursor(adjFlagLoc, adjTimeLoc);

        tft.print((char)tempFlag);

        if ((digitalRead(SWUP) == 1)  && (digitalRead(SWDN) == 1 )) {

          delay(1000);

        }

        if (digitalRead(SWUP) == 0) {

          tempFlag = 67;

          tft.print("C");

          EEPROM.write(tempEAddr, 67);

          while (digitalRead(SWUP) == 0);

        }

        if (digitalRead(SWDN) == 0) {

          tempFlag = 70;

          tft.print("F");

          EEPROM.write(tempEAddr, 70);

        }

        while (digitalRead(SWDN) == 0);

      }


      break;

    case SETPRESS:

      tft.fillRect(adjFlagLoc, (adjTimeLoc - 40), 110, 50, BLACK);

      tft.setCursor(adjFlagLoc, adjTimeLoc);

      tft.setTextColor(WHITE);

      if (pressFlag == 80) {

        tft.print("hPa");

      }

      else {

        tft.print("in Hg");

      }

      if ((digitalRead(SWUP) == 1)  && (digitalRead(SWDN) == 1 )) {

        delay(1000);

      }

      if (digitalRead(SWUP) == 0) {

        pressFlag = 80;

        tft.fillRect(adjFlagLoc, (adjTimeLoc - 40), 110, 50, BLACK);

        tft.setCursor(adjFlagLoc, (adjTimeLoc));

        tft.setTextColor(WHITE);

        tft.print("hPa");

        EEPROM.write(pressEAddr, 80);

        while (digitalRead(SWUP) == 0);

      }

      if (digitalRead(SWDN) == 0) {

        pressFlag = 72;

        tft.fillRect(adjFlagLoc, (adjTimeLoc - 40), 110, 50, BLACK);

        tft.setCursor(adjFlagLoc, adjTimeLoc);

        tft.setTextColor(WHITE);

        tft.print("in Hg");

        EEPROM.write(pressEAddr, 72);

        while (digitalRead(SWDN) == 0);

      }

      break;

  }

}



void displayEnvironmental(void) {

  boolean changed = false;

  int32_t  temp, humidity, pressure, gas, vccVolts;                         // Variable to store readings

  int32_t altVal;

  char buf[15];

  digitalWrite(testControlPort, 1);

  altVal = analogRead(usbTestPort);

  digitalWrite(testControlPort, 0);

  vccVolts = 244736 / altVal;

  BME680.getSensorData(temp, humidity, pressure, gas);

  delay(50);

  delay(50); tft.setFont(&FreeSerif18pt7b);

  if (temp != prevTemp) {

    tft.fillRect(220, 12, 95, 35, BLACK);

    prevTemp = temp;

    if (tempFlag == 67) {

      altVal = temp;

    }

    else {

      altVal = (temp * 9.0) / 5.0;

      altVal += 3200;

    }

    tft.setTextColor(MAGENTA);

    tft.setCursor(225, 35);

    sprintf(buf, "%3d.%01d", (int8_t)(altVal / 100), (uint8_t)(altVal % 100));     // Temperature in decidegrees

    tft.print(buf);

    changed = true;

  }

  if (humidity != prevHumidity) {

    tft.fillRect(160, 40, 115, 35, BLACK);

    prevHumidity = humidity;

    tft.setCursor(170, 70);

    tft.setTextColor(GREEN);

    sprintf(buf, "%3d.%01d", (int8_t)(humidity / 1000), (uint16_t)(humidity % 1000)); // Humidity in milli-percent

    tft.print(buf);

    changed = true;

  }

  if (pressure != prevPressure) {

    tft.fillRect(170, 75, 115, 35, BLACK);

    if (pressFlag == 80) {

      altVal = pressure;

    }

    else {

      altVal = pressure * 0.02983;

    }

    prevPressure = pressure;

    tft.setCursor(150, 105);

    tft.setTextColor(YELLOW);

    sprintf(buf, "%7d.%01d", (int16_t)(altVal / 100), (uint8_t)(altVal % 100));   // Pressure in hepa Pascals or in Hg

    tft.print(buf);

    changed = true;

  }

  if (gas != prevGas) {

    tft.fillRect(320, 110, 105, 35, BLACK);

    prevGas = gas;

    tft.setCursor(250, 140);

    tft.setTextColor(CYAN);

    sprintf(buf, "%4d.%01d", (int16_t)(gas / 100), (uint8_t)(gas % 100));           // Resistance in milliohms

    tft.print(buf);

    changed = true;

  }

  if (vccVolts != prevVccVolts) {

    tft.fillRect(160, 145, 105, 35, BLACK);

    prevVccVolts = vccVolts;

    tft.setCursor(200, 175);

    tft.setTextColor(ORANGE);

    sprintf(buf, "%1d.%02d", (int16_t)(vccVolts / 100), (uint8_t)(vccVolts % 100));           // Resistance in milliohms

    tft.print(buf);

    changed = true;

  }

  if (changed) {

    delay(1000);

  }