/*****************************************************
  This code was written for the Arduino Mega and allows to choose between 8080 parallel interface and 3-wire SPI Interface.
  Newhaven Display invests time and resources providing this open source code,
  Please support Newhaven Display by purchasing products from Newhaven Display!

  Copyright (c) 2023, Newhaven Display International
  This code is provided as an example only and without any warranty by Newhaven Display.
  Newhaven Display accepts no responsibility for any issues resulting from its use.
  The developer of the final application incorporating any parts of this
  sample code is responsible for ensuring its safe and correct operation
  and for any consequences resulting from its use.
  See the GNU General Public License for more details.
  /*----------------------------------------------------------------------------
  Arduino Mega            TFT Display                                          |
  ------------------------------------------------------------------------------
  GND           1   GND   - Ground                                           |
  NC            2-5       - No Connect                                       |
  NC            6   SDO   - Serial data out                                  |
  3.3V          7   VDD   - Supply Voltage for LCD (3.3v)                    |
  3.3V          8   VDDI  - Supply Voltage for Logic (3.3)                   |
  24            9   SDA   - Serial data in                                   |
  23            10  CSX   - Active LOW Chip Select signal(can tie to GND)    |
  25            11  DCX   - D/C Data =1 , Command =0                         |
  29            12  WRX   - Active LOW Write signal                          |
  28            13  RDX   - Active LOW Read signal                           |
  NC            14-21     - No Connect                                       |
  49            22  DB0                                                      |
  48            23  DB1                                                      |
  47            24  DB2                                                      |
  46            25  DB3                                                      |
  45            26  DB4                                                      |
  44            27  DB5                                                      |
  43            28  DB6                                                      |
  42            29  DB7                                                      |
  10            30  RESX                                                     |
  26            31  IM0   = 1 HIGH for 8080-II  ;   IM0 = 1 HIGH 3-wire SPI  |
  27            32  IM2   = 0 LOW for 8080-II   ;   IM2 = 1 HIGH 3-wire SPI  |
  GND           33  GND   - Ground                                           |
  GND           34  LED-K1 Backlight Cathode                                 |
  GND           35  LED-K2 Backlight Cathode                                 |
  GND           36  LED-K3 Backlight Cathode                                 |
  GND           37  LED-K4 Backlight Cathode                                 |
  3.1V          38  LED-A  Backlight Anode(160mA @ 3.1V)                     |
  GND           39  Ground                                                   |
  NC            40  TE                                                       |
  ----------------------------------------------------------------------------*/
#define RESX  8  /*RESX signal connected to Arduino digital pin  8*/
#define CSX   9  /*CSX  signal connected to Arduino digital pin  9*/
#define SDA  11  /*SDA  signal connected to Arduino digital pin 11*/
#define DCX  13  /*DCX  signal connected to Arduino digital pin 13*/      //SCL pin when SPI 


void Command_out(unsigned char c)  //Function used for sending commands to TFT
{
  PORTB &= ~(1 << PORTB3);   //Set SDA LOW for D/C Bit
  PORTB |=  (1 << PORTB5);   //Set SCL LOW
  PORTB &= ~(1 << PORTB5);   //Set SCL HIGH
  PORTB |=  (1 << PORTB5);   //Set SCL LOW
  for (int i = 0; i < 8; i++) {
    if ((c & 0x80) == 0x80)
      PORTB |=  (1 << PORTB3);   //Set SDA HIGH
    else
      PORTB &= ~(1 << PORTB3);   //Set SDA LOW
    c = (c << 1);              //Shift byte
    PORTB |=  (1 << PORTB5);   //Set SCL LOW
    PORTB &= ~(1 << PORTB5);   //Set SCL HIGH
    PORTB |=  (1 << PORTB5);   //Set SCL LOW
  }
}

void data_out(unsigned char d) {   //Function used for sending data to TFT
  PORTB |=  (1 << PORTB3);   //Set SDA HIGH for D/C Bit
  PORTB |=  (1 << PORTB5);   //Set SCL LOW
  PORTB &= ~(1 << PORTB5);   //Set SCL HIGH
  PORTB |=  (1 << PORTB5);   //Set SCL LOW
  for (int i = 0; i < 8; i++) {
    if ((d & 0x80) == 0x80)
      PORTB |=  (1 << PORTB3);  //Set SDA HIGH
    else
      PORTB &= ~(1 << PORTB3);  //Set SDA LOW
    d = (d << 1);
    PORTB |=  (1 << PORTB5);  //Set SCL LOW
    PORTB &= ~(1 << PORTB5);  //Set SCL HIGH
    PORTB |=  (1 << PORTB5);  //Set SCL LOW
  }
}

void Set_XY_Address() {
  Command_out(0x2A);           /*Set x column */
  data_out(0x00);
  data_out(0x00);
  data_out(0x00);
  data_out(0xEF);
  Command_out(0x2B);           /*Set y row */
  data_out(0x00);
  data_out(0x00);
  data_out(0x01);
  data_out(0x3F);
  Command_out(0x2C);           /*command to begin writing to frame memory */
}

void disp() {

  Set_XY_Address();
  unsigned int i;
  for ( i = 0; i < 38400; i++)
  {
    data_out(0x00);
    data_out(0x1f);                  //Fills screen with Red pixels
    data_out(0x00);
    data_out(0x1f);
  }
  delay(2000);
  Set_XY_Address();
  for ( i = 0; i < 38400; i++)
  {
    data_out(0x07);                  //Fills screen with Green pixels
    data_out(0xe0);
    data_out(0x07);
    data_out(0xe0);
  }
  delay(2000);
  Set_XY_Address();
  for ( i = 0; i < 38400; i++)
  {
    data_out(0xf8);                  //Fills screen with Blue pixels
    data_out(0x00);
    data_out(0xf8);
    data_out(0x00);
  }
  delay(2000);
}

void Ports_SPI() {
  DDRB = 0xFF;            //Enable All pins as output on PortB
  PORTB = 0x00;           //Clears PortB
  digitalWrite(CSX, LOW);
}

void TFT_init() {

  digitalWrite(RESX, LOW);
  delay(250);
  digitalWrite(RESX, HIGH);
  delay(250);

  Command_out(0x28);  //display off
  Command_out(0x11);  //exit SLEEP mode
  delay(100);

  Command_out(0x36);  //MADCTL: memory data access control
  data_out(0x88);

  Command_out(0x3A);  //COLMOD: Interface Pixel format  *** 65K-colors in 16bit/pixel (5-6-5) format when using 16-bit interface to allow 1-byte per pixel
  data_out(0x55);

  Command_out(0xB2);  //PORCTRK: Porch setting
  data_out(0x0C);
  data_out(0x0C);
  data_out(0x00);
  data_out(0x33);
  data_out(0x33);

  Command_out(0xB7);  //GCTRL: Gate Control
  data_out(0x35);

  Command_out(0xBB);  //VCOMS: VCOM setting
  data_out(0x2B);

  Command_out(0xC0);  //LCMCTRL: LCM Control
  data_out(0x2C);

  Command_out(0xC2);  //VDVVRHEN: VDV and VRH Command Enable
  data_out(0x01);
  data_out(0xFF);

  Command_out(0xC3);  //VRHS: VRH Set
  data_out(0x11);

  Command_out(0xC4);  //VDVS: VDV Set
  data_out(0x20);

  Command_out(0xC6);  //FRCTRL2: Frame Rate control in normal mode
  data_out(0x0F);

  Command_out(0xD0);  //PWCTRL1: Power Control 1
  data_out(0xA4);
  data_out(0xA1);

  Command_out(0xE0);  //PVGAMCTRL: Positive Voltage Gamma control
  data_out(0xD0);
  data_out(0x00);
  data_out(0x05);
  data_out(0x0E);
  data_out(0x15);
  data_out(0x0D);
  data_out(0x37);
  data_out(0x43);
  data_out(0x47);
  data_out(0x09);
  data_out(0x15);
  data_out(0x12);
  data_out(0x16);
  data_out(0x19);

  Command_out(0xE1);  //NVGAMCTRL: Negative Voltage Gamma control
  data_out(0xD0);
  data_out(0x00);
  data_out(0x05);
  data_out(0x0D);
  data_out(0x0C);
  data_out(0x06);
  data_out(0x2D);
  data_out(0x44);
  data_out(0x40);
  data_out(0x0E);
  data_out(0x1C);
  data_out(0x18);
  data_out(0x16);
  data_out(0x19);

  Command_out(0x2A);  //X address set
  data_out(0x00);
  data_out(0x00);
  data_out(0x00);
  data_out(0xEF);

  Command_out(0x2B);  //Y address set
  data_out(0x00);
  data_out(0x00);
  data_out(0x01);
  data_out(0x3F);
  delay(10);
  Command_out(0x21);  //Color inversion for ips
  Command_out(0x29);  //display ON
  delay(10);
}

void setup() {
  Ports_SPI();  //Ports setup for SPI Interface

  TFT_init();                      //TFT initialazation

}

void loop() {
  disp();           //Outputs RGB colors loop
}