/***************************************************
//Web: http://www.buydisplay.com
EastRising Technology Co.,LTD
Examples for ER-TFT021-1 with ER-PCBA5981-1 Capacitive touch screen test
Display is Hardward SPI 4-Wire SPI Interface and 5V Power Supply,CTP is I2C interface.
Tested and worked with:
Works with Arduino 2.3.4 IDE  
NOTE: test OK:ESP32-WROOM-32 
****************************************************/

/*
  ==TFT Hardware SPI to ESP32  ==
    TFT   =>    ESP32
  *1,2. GND       ->    GND
  *3,4. VCC       ->    5V    3.3V OR 5V is optional, depending on the voltage of the module purchased 
  *5. CS        ->       5
  *6. MISO        ->    19  
  *7. MOSI       ->    23  
  *8. SCK       ->    18  
  *9. BL        ->     3.3V  (HIGH:ON  LOW:OFF)
  *11. RES       ->    16   
  *12. CTPINT     ->    17
  *13. CTPRST     ->    15
  *14. CTPSDA    ->    21
  *15. CTPSCL    ->    22 

  *16. CS        ->    14 
  *18. SDI       ->    12 
  *19. SCK       ->    13 
*/
#include <SPI.h>
#include <Wire.h>
#include "LCD.h"
#include "LCD_init.h"
#include <stdint.h>
#include "Arduino.h"
#include "Print.h"


uint8_t addr  = 0x38;  //CTP IIC ADDRESS

#define FT3267_RST 15
#define FT3267_INT   17  



enum {
  eNORMAL = 0,
  eTEST   = 0x04,
  eSYSTEM = 0x01
};


struct TouchLocation
{
  uint16_t x;
  uint16_t y;
};

TouchLocation touchLocations[2];

uint8_t readFT3267TouchRegister( uint8_t reg );
uint8_t readFT3267TouchLocation( TouchLocation * pLoc, uint8_t num );
uint8_t readFT3267TouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len );



uint8_t buf[20];

uint8_t readFT3267TouchRegister( uint8_t reg )
{
  Wire.beginTransmission(addr);
  Wire.write( reg );  // register 0
  uint8_t retVal = Wire.endTransmission();
  
  uint8_t returned = Wire.requestFrom(addr, uint8_t(1) );    // request 6 uint8_ts from slave device #2
  
  if (Wire.available())
  {
    retVal = Wire.read();
  }
  
  return retVal;
}

uint8_t readFT3267TouchAddr( uint8_t regAddr, uint8_t * pBuf, uint8_t len )
{
  Wire.beginTransmission(addr);
  Wire.write( regAddr );  // register 0
  uint8_t retVal = Wire.endTransmission();
  
  uint8_t returned = Wire.requestFrom(addr, len);    // request 1 bytes from slave device #2
  
  uint8_t i;
  for (i = 0; (i < len) && Wire.available(); i++)
  {
    pBuf[i] = Wire.read();
  }
  
  return i;
}

uint8_t readFT3267TouchLocation( TouchLocation * pLoc, uint8_t num )
{
  uint8_t retVal = 0;
  uint8_t i;
  uint8_t k;
  
  do
  {
    if (!pLoc) break; // must have a buffer
    if (!num)  break; // must be able to take at least one
    
    uint8_t status = readFT3267TouchRegister(2);
    
    static uint8_t tbuf[20];
    
    if ((status & 0x0f) == 0) break; // no points detected
    
    uint8_t hitPoints = status & 0x0f;
    
    Serial.print("number of hit points = ");
    Serial.println( hitPoints );
    
    readFT3267TouchAddr( 0x03, tbuf, hitPoints*6);
    
    for (k=0,i = 0; (i < hitPoints*6)&&(k < num); k++, i += 6)
    {
      pLoc[k].x = (tbuf[i+0] & 0x0f) << 8 | tbuf[i+1];
      pLoc[k].y = (tbuf[i+2] & 0x0f) << 8 | tbuf[i+3];
    }
    
    retVal = k;
    
  } while (0);
  
  return retVal;
}

void writeFT3267TouchRegister( uint8_t reg, uint8_t val)
{
  Wire.beginTransmission(addr);
  Wire.write( reg );  // register 0
  Wire.write( val );  // value
  
  uint8_t retVal = Wire.endTransmission();  
}




void setup() {
  Serial.begin(9600);
 Wire.setClock(400000);
  Wire.begin();        // join i2c bus (address optional for master)   
   
  pinMode     (FT3267_INT, INPUT);//CTP INT INPUT
  pinMode(FT3267_RST, OUTPUT);  //CTP RESET OUTPUT
  digitalWrite(FT3267_RST, HIGH);//on
  delay(10);
  digitalWrite(FT3267_RST, LOW);//on
  delay(10);
  digitalWrite(FT3267_RST, HIGH);//on
 
  
  ER_TFT.Parallel_Init();
  ER_TFT.HW_Reset();
  ER_TFT.System_Check_Temp();
  delay(100);
  while(ER_TFT.LCD_StatusRead()&0x02);
  ER_TFT.initial();
  ST7701S_Initial();   
  ER_TFT.Display_ON();

}
void loop() {
   static uint16_t w = LCD_XSIZE_TFT;
  static uint16_t h = LCD_YSIZE_TFT; 
   unsigned int i;
   double float_data;  
  uint8_t flag = 1;
  
  ER_TFT.Select_Main_Window_16bpp();
  ER_TFT.Main_Image_Start_Address(layer1_start_addr);        
  ER_TFT.Main_Image_Width(LCD_XSIZE_TFT);
  ER_TFT.Main_Window_Start_XY(0,0);
  ER_TFT.Canvas_Image_Start_address(0);
  ER_TFT.Canvas_image_width(LCD_XSIZE_TFT);
  ER_TFT.Active_Window_XY(0,0);
  ER_TFT.Active_Window_WH(LCD_XSIZE_TFT,LCD_YSIZE_TFT); 
  
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill(); 
  
   ER_TFT.Foreground_color_65k(White);
  ER_TFT.Background_color_65k(Black);
  ER_TFT.CGROM_Select_Internal_CGROM();  
   ER_TFT.Font_Height_X1(); 
   ER_TFT.Font_Width_X1();  
  ER_TFT.Font_Select_8x16_16x16();
  ER_TFT.Goto_Text_XY(40,200); 
  ER_TFT.Show_String( "Capacitive touch screen test"); 
  ER_TFT.Goto_Text_XY(LCD_XSIZE_TFT/2-20,5);
  ER_TFT.Show_String("Clear");   
  ER_TFT.Goto_Text_XY(LCD_XSIZE_TFT/2-20,LCD_YSIZE_TFT-25);
  ER_TFT.Show_String("Exit");       
  

  
  while(flag) 
  {uint8_t attention = digitalRead(FT3267_INT);
     if (!attention) 
    {  
      Serial.println("Touch: ");
      
      uint8_t count = readFT3267TouchLocation( touchLocations, 2 );
               
        for (i = 0; i < count; i++)
        {  
        if((touchLocations[i].x>LCD_XSIZE_TFT/2-30)&&(touchLocations[i].x<LCD_XSIZE_TFT/2+30)&&(touchLocations[i].y>440)) flag=0; 
	if((touchLocations[i].x>LCD_XSIZE_TFT/2-30)&&(touchLocations[i].x<LCD_XSIZE_TFT/2+30)&&(touchLocations[i].y<40))
              {    ER_TFT.Foreground_color_65k(Black);
                  ER_TFT.Line_Start_XY(0,0);
                  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
                  ER_TFT.Start_Square_Fill(); 
                  
                   ER_TFT.Foreground_color_65k(White);
                  ER_TFT.Background_color_65k(Black);
                  ER_TFT.CGROM_Select_Internal_CGROM();  
                  ER_TFT.Font_Select_8x16_16x16();
                 ER_TFT.Goto_Text_XY(40,200); 
                ER_TFT.Show_String( "Capacitive touch screen test"); 
                ER_TFT.Goto_Text_XY(LCD_XSIZE_TFT/2-20,5);
                ER_TFT.Show_String("Clear");   
                ER_TFT.Goto_Text_XY(LCD_XSIZE_TFT/2-20,LCD_YSIZE_TFT-25);
                ER_TFT.Show_String("Exit");
                  break;                  
              }  
              
          else{                                    
              snprintf((char*)buf,sizeof(buf),"(%3d,%3d)",touchLocations[i].x,touchLocations[i].y); 
            const  char *str=(const char *)buf;
             ER_TFT.Foreground_color_65k(Red);  
            ER_TFT.Text_Mode();
            ER_TFT.Goto_Text_XY(60,100+16*i);
            ER_TFT.LCD_CmdWrite(0x04);
            while(*str != '\0')
            {
            ER_TFT.LCD_DataWrite(*str);
            ER_TFT.Check_Mem_WR_FIFO_not_Full();      
            ++str; 
            } 
            ER_TFT.Check_2D_Busy();
            ER_TFT.Graphic_Mode(); //back to graphic mode;
           
            if(i==0)  ER_TFT.DrawCircle_Fill(touchLocations[i].x,touchLocations[i].y, 3, Red);  
            else if(i==1)  ER_TFT.DrawCircle_Fill(touchLocations[i].x,touchLocations[i].y, 3, Green); 
      
          }
        }
     } 
    
  }
  
  ////////Drawing
  ER_TFT.Select_Main_Window_16bpp();
  ER_TFT.Main_Image_Start_Address(layer1_start_addr);				
  ER_TFT.Main_Image_Width(LCD_XSIZE_TFT);
  ER_TFT.Main_Window_Start_XY(0,0);
  ER_TFT.Canvas_Image_Start_address(layer1_start_addr);
  ER_TFT.Canvas_image_width(LCD_XSIZE_TFT);
  ER_TFT.Active_Window_XY(0,0);
  ER_TFT.Active_Window_WH(LCD_XSIZE_TFT,LCD_YSIZE_TFT);	

  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Red);
  ER_TFT.Line_Start_XY(0+i,0+i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Start_Square();
  delay(10);
  }

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0+i,0+i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Start_Square();
  delay(10);
  }
 delay(100);
///////////////////////////Square Of Circle
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Green);
  ER_TFT.Line_Start_XY(0+i,0+i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Circle_Square_Radius_RxRy(10,10);
  ER_TFT.Start_Circle_Square();
  delay(10);
  }

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0+i,0+i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Circle_Square_Radius_RxRy(10,10);
  ER_TFT.Start_Circle_Square();
  delay(10);
  }
  delay(100);

///////////////////////////Circle
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Blue);
  ER_TFT.Circle_Center_XY(LCD_XSIZE_TFT/2,LCD_YSIZE_TFT/2);
  ER_TFT.Circle_Radius_R(i);
  ER_TFT.Start_Circle_or_Ellipse();
  delay(10);
  }

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Circle_Center_XY(LCD_XSIZE_TFT/2,LCD_YSIZE_TFT/2);
  ER_TFT.Circle_Radius_R(i);
  ER_TFT.Start_Circle_or_Ellipse();
  delay(10);
  }
  delay(100);

///////////////////////////Ellipse
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT/2-100;i+=8)
  {ER_TFT.Foreground_color_65k(White);
  ER_TFT.Circle_Center_XY(LCD_XSIZE_TFT/2,LCD_YSIZE_TFT/2);
  ER_TFT.Ellipse_Radius_RxRy(i+100,i);
  ER_TFT.Start_Circle_or_Ellipse();
  delay(10);
  }

  for(i=0;i<=LCD_XSIZE_TFT/2-100;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Circle_Center_XY(LCD_XSIZE_TFT/2,LCD_YSIZE_TFT/2);
  ER_TFT.Ellipse_Radius_RxRy(i+100,i);
  ER_TFT.Start_Circle_or_Ellipse();
  delay(10);
  }
  delay(100);

 ////////////////////////////Triangle
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Yellow);
  ER_TFT.Triangle_Point1_XY(LCD_XSIZE_TFT/2,i);
  ER_TFT.Triangle_Point2_XY(i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Triangle_Point3_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Start_Triangle();
  delay(10);
  }

  for(i=0;i<=LCD_XSIZE_TFT/2-10;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Triangle_Point1_XY(LCD_XSIZE_TFT/2,i);
  ER_TFT.Triangle_Point2_XY(i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Triangle_Point3_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1-i);
  ER_TFT.Start_Triangle();
  delay(10);
  }
  delay(100);


 ////////////////////////////line
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();

  for(i=0;i<=LCD_XSIZE_TFT;i+=8)
  {ER_TFT.Foreground_color_65k(Red);
  ER_TFT.Line_Start_XY(i,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Line();
  delay(10);
  }
  for(i=0;i<=LCD_YSIZE_TFT;i+=8)
  {ER_TFT.Foreground_color_65k(Red);
  ER_TFT.Line_Start_XY(0,LCD_YSIZE_TFT-1-i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,i);
  ER_TFT.Start_Line();
  delay(10);
  }


  for(i=0;i<=LCD_XSIZE_TFT;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(i,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1-i,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Line();
  delay(10);
  }
  for(i=0;i<=LCD_YSIZE_TFT;i+=8)
  {ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,LCD_YSIZE_TFT-1-i);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,i);
  ER_TFT.Start_Line();
  delay(10);
  }


  delay(100);  

/////////////Internal characters 
  ER_TFT.Select_Main_Window_16bpp();
  ER_TFT.Main_Image_Start_Address(layer1_start_addr);				
  ER_TFT.Main_Image_Width(LCD_XSIZE_TFT);
  ER_TFT.Main_Window_Start_XY(0,0);
  ER_TFT.Canvas_Image_Start_address(layer1_start_addr);
  ER_TFT.Canvas_image_width(LCD_XSIZE_TFT);
  ER_TFT.Active_Window_XY(0,0);
  ER_TFT.Active_Window_WH(LCD_XSIZE_TFT,LCD_YSIZE_TFT);	
 
  
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();



  ER_TFT.Background_color_65k(Black);
  ER_TFT.Foreground_color_65k(Red);  
  ER_TFT.CGROM_Select_Internal_CGROM();
  ER_TFT.Font_Select_8x16_16x16();
  ER_TFT.Goto_Text_XY(0,10);
  ER_TFT.Show_String("buydisplay.com");
  
  ER_TFT.Foreground_color_65k(Green);
  ER_TFT.Font_Select_12x24_24x24();
  ER_TFT.Goto_Text_XY(0,26);
  ER_TFT.Show_String("buydisplay.com");

  ER_TFT.Foreground_color_65k(Blue);
  ER_TFT.Font_Select_16x32_32x32();
  ER_TFT.Goto_Text_XY(0,50);
  ER_TFT.Show_String("buydisplay.com");  
  
  ER_TFT.Foreground_color_65k(Yellow);
  ER_TFT.Font_Width_X4(); 
  ER_TFT.Font_Height_X4();
  ER_TFT.Goto_Text_XY(0,90);  
  ER_TFT.Show_String("buydisplay.com");    
  delay(2000); 

 
 ///////////////////////// DMA
  ER_TFT.Select_Main_Window_16bpp();
  ER_TFT.Main_Image_Start_Address(layer1_start_addr);				
  ER_TFT.Main_Image_Width(LCD_XSIZE_TFT);
  ER_TFT.Main_Window_Start_XY(0,0);
  ER_TFT.Canvas_Image_Start_address(layer1_start_addr);
  ER_TFT.Canvas_image_width(LCD_XSIZE_TFT);
  ER_TFT.Active_Window_XY(0,0);
  ER_TFT.Active_Window_WH(LCD_XSIZE_TFT,LCD_YSIZE_TFT);	
 
  
  ER_TFT.Foreground_color_65k(Black);
  ER_TFT.Line_Start_XY(0,0);
  ER_TFT.Line_End_XY(LCD_XSIZE_TFT-1,LCD_YSIZE_TFT-1);
  ER_TFT.Start_Square_Fill();
 
 
        unsigned long im;
 	 for(im=0;im<4;im++)
	 {
        ER_TFT.DMA_24bit_Block(1,0,0,0,LCD_XSIZE_TFT,LCD_YSIZE_TFT,LCD_XSIZE_TFT,im*LCD_XSIZE_TFT*LCD_YSIZE_TFT*2);
        // Select SPI : SCS��0       SCS��1
        // SPI Clock = System Clock /{(Clk+1)*2}
        // Transfer to SDRAM address:X1
         // Transfer to SDRAM address:Y1
        // DMA data width
        // DMA data height
        // Picture's width
        // Flash address	
	  delay(2000);
 	
	 }


}



