/*   TFT display

// SCK  D13 blue
// MISO D12 yellow
// MOSI D11 green
// DC   D10 brown
// CS   D09 white
// YP orange must be an analog pin, use "An" notation!
// XM yellow must be an analog pin, use "An" notation!
// YM gray can be a digital pin
// XP white can be a digital pin

with SPI connectors up, setRotation(3) for landscape
with SPI connectors left, setRotation(4) for portrait

                     portrait            landscape
font      size  chars/line  rows    chars/line  rows
default     1       52       60        76        40
default     2       24       30        37        20
default     3       16       20        24        13
default     4       11       15        18        10
default     5        9       12        14         8

assume that display will be used in portrait orientation, usual font size = 2
*/
/*
         111111111122222
123456789012345678901234
sensor read report damp
furn    3m   10m   0.95
A/C
infurn
inA/C
anemom
rain
pond
depth
tempF
inHg
CO2
light
vane
PM2.5
CCTV
L amps
R amps
*/

/*colors
  ILI9341_BLACK
  ILI9341_RED
  ILI9341_ORANGE
  ILI9341_YELLOW
  ILI9341_GREEN
  ILI9341_CYAN
  ILI9341_BLUE
  ILI9341_MAGENTA
  ILI9341_PURPLE
  ILI9341_WHITE

*/

#include "Adafruit_GFX.h"
#include <G:\source code\Teensy\home control\HC4\peripheral\peripheral11\libraries\Adafruit_ILI9341\Adafruit_ILI9341.h>
Adafruit_ILI9341 BaseTFT = Adafruit_ILI9341(pinTFT_CS, pinTFT_DC);


#include <stdint.h>
#include "TouchScreen.h"
#define XP_XM_ohms 288
TouchScreen BaseTouch = TouchScreen(pinTouchXP, pinTouchYP, pinTouchXM, pinTouchYM, XP_XM_ohms);


class tTFTDisplay
  { private:
      int           BigFontSize;
      char          Buffer[60][53];
      int           CharsInRow[60];
      int           CurrentFontSize;
      int           CurrentRow;
      int           DefaultFontSize;
      bool          FixedHeader;
      int           LastCol;
      int           LastRow;
      elapsedMillis msSinceTouch;
      bool          Portrait;

      void LoadRow(const int Row, const char TheLine[]);
      void ScrollUp();

    public:
      void BigTwoLines(const char Line1[], const char Line2[]);
      void BlackScreen()
              { FillScreen(ILI9341_BLACK); }
      void FillScreen(const uint16_t TheColor);
      void NewLine();
      void Print(const char C);
      void SetFixedHeader(const char TheLine[]);
      void SetFontColor(const uint16_t TheColor)
              { BaseTFT.setTextColor(TheColor); }
      void SetFontSize(const int TheSize);
      void setup(const int TheDefaultFontSize, const int TheBigFontSize);
      bool Touched();
  }; // tTFTDisplay


void tTFTDisplay::BigTwoLines(const char Line1[], const char Line2[])
  { SetFontSize(BigFontSize);
    BlackScreen();
    LoadRow(0, Line1);
    BaseTFT.println(Line1);
    LoadRow(1, Line2);
    BaseTFT.println(Line2);
    SetFontSize(DefaultFontSize);
  } // tTFTDisplay::BigTwoLines

void tTFTDisplay::FillScreen(const uint16_t TheColor)
  { BaseTFT.fillScreen(TheColor);
    BaseTFT.setCursor(0, 0);
  } // tTFTDisplay::FillScreen

void tTFTDisplay::LoadRow(const int Row, const char TheLine[])
  { for (int I = 0; (TheLine[I] != 0) && (I <= LastCol); I++)
      { Buffer[Row][I] = TheLine[I];
        Buffer[Row][I+1] = 0;
      }
  } // tTFTDisplay::LoadRow

void tTFTDisplay::NewLine()
  { CharsInRow[CurrentRow] = LastCol + 1;
  } // tTFTDisplay::NewLine(

void tTFTDisplay::Print(const char C)
  { if (CharsInRow[CurrentRow] > LastCol)
      { if (CurrentRow >= LastRow)
          { ScrollUp(); }
        else
          { BaseTFT.println();
            CurrentRow++;
          }
        CharsInRow[CurrentRow] = 0;
        Buffer[CurrentRow][0] = 0;
      }

    Buffer[CurrentRow][CharsInRow[CurrentRow]] = C;
    CharsInRow[CurrentRow]++;
    Buffer[CurrentRow][CharsInRow[CurrentRow]] = 0;
    BaseTFT.print(C);
  } // tTFTDisplay::Print

void tTFTDisplay::ScrollUp()
  { int FirstSinkRow;
    BlackScreen();

    if (FixedHeader)
      { FirstSinkRow = 1;
        BaseTFT.println(Buffer[0]);
      }
    else
      { FirstSinkRow = 0; }

    for (int SinkRow = FirstSinkRow; SinkRow < LastRow; SinkRow++)
      { strncpy(Buffer[SinkRow], Buffer[SinkRow+1], LastCol+1);
        CharsInRow[SinkRow] = CharsInRow[SinkRow+1];
        Buffer[SinkRow][CharsInRow[SinkRow]] = 0;
        BaseTFT.println(Buffer[SinkRow]);
      }
    CurrentRow = LastRow;
    CharsInRow[CurrentRow] = 0;
    Buffer[CurrentRow][0] = 0;
  } // tTFTDisplay::ScrollUp
  
void tTFTDisplay::SetFixedHeader(const char TheLine[])
  { if (TheLine[0] == 0)
      { FixedHeader = false; }
    else
      { FixedHeader = true;
        BlackScreen();
        LoadRow(0, TheLine);
        BaseTFT.setCursor(0, 0);
        BaseTV.println(TheLine);
        CurrentRow = 1;
      }
  } // tTFTDisplay::SetFixedHeader

void tTFTDisplay::SetFontSize(const int TheSize)
  { //   portrait                     1   2   3   4   5
    const int TFTRowLengthP[6] = {0, 53, 26, 17, 13, 10};
    const int TFTRowsP[6]      = {0, 60, 30, 20, 15, 12};
    //   landscape                    1   2   3   4   5
    const int TFTRowLengthL[6] = {0, 80, 40, 26, 20, 16};
    const int TFTRowsL[6]      = {0, 40, 20, 13, 10,  8};

    BaseTFT.setTextSize(TheSize);

    if (Portrait)
      { LastRow = TFTRowsP[TheSize] - 1;
        LastCol = TFTRowLengthP[TheSize] - 1;
      }
    else
      { LastRow = TFTRowsL[TheSize] - 1;
        LastCol = TFTRowLengthL[TheSize] - 1;
      }
  } // tTFTDisplay::SetFontSize

void tTFTDisplay::setup(const int TheDefaultFontSize, const int TheBigFontSize)
  { BigFontSize     = TheBigFontSize;
    DefaultFontSize = TheDefaultFontSize;
    FixedHeader     = false;
    msSinceTouch    = 0;
    Portrait        = true;

    CurrentRow             = 0;
    CharsInRow[CurrentRow] = 0;
    Buffer[CurrentRow][0]  = 0;

    BaseTFT.begin();
    BlackScreen();

    SetFontSize(TheBigFontSize);
    SetFontColor(ILI9341_RED);
    BaseTFT.print(DateCompiled);
    BaseTFT.print(" @ ");
    BaseTFT.println(TimeCompiled);
    BaseTFT.println();
    
    SetFontSize(TheDefaultFontSize);
    SetFontColor(ILI9341_WHITE);
    delay(5 * msOneSecond);
  } // tTFTDisplay::setup

bool tTFTDisplay::Touched()
  { const unsigned long msMinInterTouchTime =  2 * msOneSecond;
    TSPoint Where;
    bool Result = false;

    if (msSinceTouch > msMinInterTouchTime)
      { // not too soon
        Where = BaseTouch.getPoint();
        if ((Where.z > BaseTouch.pressureThreshhold) && (Where.x > 2))
          { // Serial.printf("touched at (%d, %d) pressure %d\n", Where.x, Where.y, Where.z);
            Result = true;
            msSinceTouch = 0;
          }
      } // not too soon
    return Result;
  } // tTFTDisplay::Touched

#undef XP_XM_ohms






