#include <SPI.h>
#include <string.h>
#include <stdlib.h>		

#include "epd_7inch3.h"
#include "epd_gui.h"

static const int SPICLK = 3000000;
SPIClass* spi_epd = NULL;

void E_Paper_Gpio_Init(void)
{
   pinMode(BUSY_Pin, INPUT_PULLUP); 
   pinMode(RES_Pin, OUTPUT);  
   pinMode(DC_Pin, OUTPUT);    
   pinMode(CS_Pin, OUTPUT);  
   if(spi_epd==NULL)
   {  
       spi_epd = new SPIClass(HSPI);
       spi_epd->begin(SCK_Pin,-1, SDI_Pin, CS_Pin);
       spi_epd->beginTransaction(SPISettings(SPICLK, MSBFIRST, SPI_MODE3)); 
   } 
}   

///////////////////EXTERNAL FUNCTION////////////////////////////////////////////////////////////////////////
/////////////////////delay//////////////////////////////////////
void driver_delay_us(unsigned int xus)  //1us
{
  for(;xus>1;xus--);
}
void driver_delay_xms(unsigned long xms) //1ms
{  
    unsigned long i = 0 , j=0;

    for(j=0;j<xms;j++)
  {
        for(i=0; i<256; i++);
    }
}
void DELAY_S(unsigned int delaytime)     
{
  int i,j,k;
  for(i=0;i<delaytime;i++)
  {
    for(j=0;j<4000;j++)           
    {
      for(k=0;k<222;k++);
                
    }
  }
}
//////////////////////SPI///////////////////////////////////
void SPI_Delay(unsigned char xrate)
{
  unsigned char i;
  while(xrate)
  {
    for(i=0;i<2;i++);
    xrate--;
  }
}

void SPI_Write(unsigned char value)                                    
{   
    spi_epd->transfer(value);                                                        
}

void Epaper_Write_Command(unsigned char command)
{
  SPI_Delay(1);
  EPD_W21_CS_0;                   
  EPD_W21_DC_0;   // command write
  SPI_Write(command);
  EPD_W21_CS_1;
}
void Epaper_Write_Data(unsigned char command)
{
  SPI_Delay(1);
  EPD_W21_CS_0;                   
  EPD_W21_DC_1;   // command write
  SPI_Write(command);
  EPD_W21_CS_1;
}

/////////////////EPD settings Functions/////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
void EPD_Init(void)
{  
  delay(80); 
  EPD_W21_RST_0;   
  delay(10); 
  EPD_W21_RST_1; //hard reset  
  delay(10); 

  Epaper_Write_Command(0xAA);    // CMDH
  Epaper_Write_Data(0x49);
  Epaper_Write_Data(0x55);
  Epaper_Write_Data(0x20);
  Epaper_Write_Data(0x08);
  Epaper_Write_Data(0x09);
  Epaper_Write_Data(0x18);

  Epaper_Write_Command(PWRR);//
  Epaper_Write_Data(0x3F);
  
  Epaper_Write_Command(PSR);  
  Epaper_Write_Data(0x5F);
  Epaper_Write_Data(0x69);
  
  Epaper_Write_Command(POFS);
  Epaper_Write_Data(0x00);
  Epaper_Write_Data(0x54);
  Epaper_Write_Data(0x00);
  Epaper_Write_Data(0x44); 

  Epaper_Write_Command(BTST1);
  Epaper_Write_Data(0x40);
  Epaper_Write_Data(0x1F);
  Epaper_Write_Data(0x1F);
  Epaper_Write_Data(0x2C);
  
  Epaper_Write_Command(BTST2);
  Epaper_Write_Data(0x6F);
  Epaper_Write_Data(0x1F);
  Epaper_Write_Data(0x17);
  Epaper_Write_Data(0x49);

  Epaper_Write_Command(BTST3);
  Epaper_Write_Data(0x6F);
  Epaper_Write_Data(0x1F);
  Epaper_Write_Data(0x1F);
  Epaper_Write_Data(0x22);
  
  Epaper_Write_Command(PLL);
  Epaper_Write_Data(0x08);//原始0x08
  Epaper_Write_Command(CDI);
  Epaper_Write_Data(0x3F);
  
  Epaper_Write_Command(TCON);
  Epaper_Write_Data(0x02);
  Epaper_Write_Data(0x00);
  
  Epaper_Write_Command(TRES);
  Epaper_Write_Data(0x03);
  Epaper_Write_Data(0x20);
  Epaper_Write_Data(0x01); 
  Epaper_Write_Data(0xE0);

  Epaper_Write_Command(T_VDCS);
  Epaper_Write_Data(0x01);
  
  Epaper_Write_Command(PWS);
  Epaper_Write_Data(0x2F);

  Epaper_Write_Command(0x04);     //PWR on  
  Serial.println("e-paper read busy...");
  Epaper_READBUSY();   
  
}
//////////////////////////////All screen update////////////////////////////////////////////
void EPD_Clear(unsigned char color) {
    Epaper_Write_Command(0x10);
    for(int i=0; i<EPD_7IN3F_WIDTH/2; i++) {
        for(int j=0; j<EPD_7IN3F_HEIGHT; j++) {
          Epaper_Write_Data((color<<4)|color);
		}
	}
  Epaper_Write_Command(0x12);
  Epaper_Write_Data(0x00);
  Epaper_READBUSY(); 
}
/******************************************************************************
function :  Sends the image buffer in RAM to e-Paper and displays
parameter:
******************************************************************************/
void EPD_7IN3F_Display(const unsigned char *Image)
{
    uint16_t width, height;
    width = (EPD_7IN3F_WIDTH % 2 == 0)? (EPD_7IN3F_WIDTH / 2 ): (EPD_7IN3F_WIDTH / 2 + 1);
    height = EPD_7IN3F_HEIGHT;

    Epaper_Write_Command(0x10);
    for (uint16_t j = 0; j < height; j++) {
        for (uint16_t i = 0; i < width; i++) {
            Epaper_Write_Data(Image[i + j * width]);
        }
    }
    Epaper_Write_Command(0x12);   //DISPLAY REFRESH   
    Epaper_Write_Data(0x00);
    Serial.println("wait idle");
    delay(1);   //!!!The delay here is necessary, 200uS at least!!!     
    Epaper_READBUSY();          //waiting for the electronic paper IC to release the idle signal
    Serial.println("display done!");
}

void EPD_Display_6colors(void)
{
  unsigned long i;
  Epaper_Write_Command(DTM);
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(Black);
  }
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(White);
  }
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(Red);
  }
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(Green);
  }
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(Blue);
  }
  for(i=0;i<32000;i++)
  {
    Epaper_Write_Data(Yellow);
  }
  Epaper_Write_Command(0x12);
  Epaper_Write_Data(0x00);
  Epaper_READBUSY();
}

void EPD_DeepSleep(void)
{  
  Epaper_Write_Command(0x02);
  Epaper_Write_Data(0x00);
  Epaper_READBUSY();
}
void Epaper_READBUSY(void)
{ 
  while(!isEPD_W21_BUSY)
  {   
    delay(2);
  }  
}
