#include <SPI.h>
#include "2inch9_epd.h"

//SPI write byte
void SPI_Write(unsigned char value)
{				   			 
   SPI.transfer(value);
}
//SPI write command
void Epaper_Write_Command(unsigned char command)
{
	EPD_W21_CS_0;
	EPD_W21_DC_0;  // D/C#   0:command  1:data  
	SPI_Write(command);
	EPD_W21_CS_1;
}
//SPI write data
void Epaper_Write_Data(unsigned char datas)
{
	EPD_W21_CS_0;
	EPD_W21_DC_1;  // D/C#   0:command  1:data
	SPI_Write(datas);
	EPD_W21_CS_1;
}

////////////////////////////////////E-paper demo//////////////////////////////////////////////////////////
//Busy function
void Epaper_READBUSY(void)
{ 
  while(1)
  {  //=1 BUSY
     if(isEPD_W21_BUSY==1) break;
  }  
}

void EPD_HW_Init(void)
{
//Full screen refresh initialization
 EPD_W21_RST_0;  // Module reset   
  delay(10);//At least 10ms delay 
  EPD_W21_RST_1;
  delay(10); //At least 10ms delay 
  
  Epaper_READBUSY();   
Epaper_Write_Command(0x4D);
  Epaper_Write_Data(0x78);

  Epaper_Write_Command(0x00); //PSR
  Epaper_Write_Data(0x0F);
  Epaper_Write_Data(0x29);

  Epaper_Write_Command(0x01); //PWRR
  Epaper_Write_Data(0x07);
  Epaper_Write_Data(0x00);
  
  Epaper_Write_Command(0x03); //POFS
  Epaper_Write_Data(0x10);
  Epaper_Write_Data(0x54);
  Epaper_Write_Data(0x44);
  
  Epaper_Write_Command(0x06); //BTST_P
  Epaper_Write_Data(0x05);
  Epaper_Write_Data(0x00);
  Epaper_Write_Data(0x3F);
  Epaper_Write_Data(0x0A);
  Epaper_Write_Data(0x25);
  Epaper_Write_Data(0x12);
  Epaper_Write_Data(0x1A); 

  Epaper_Write_Command(0x50); //CDI
  Epaper_Write_Data(0x37);
  
  Epaper_Write_Command(0x60); //TCON
  Epaper_Write_Data(0x02);
  Epaper_Write_Data(0x02);
  
  Epaper_Write_Command(0x61); //TRES
  Epaper_Write_Data(Source_BITS/256);   // Source_BITS_H
  Epaper_Write_Data(Source_BITS%256);   // Source_BITS_L
  Epaper_Write_Data(Gate_BITS/256);     // Gate_BITS_H
  Epaper_Write_Data(Gate_BITS%256);     // Gate_BITS_L  
  
  Epaper_Write_Command(0xE7);
  Epaper_Write_Data(0x1C);
  
  Epaper_Write_Command(0xE3); 
  Epaper_Write_Data(0x22);
  
  Epaper_Write_Command(0xB4);
  Epaper_Write_Data(0xD0);
  Epaper_Write_Command(0xB5);
  Epaper_Write_Data(0x03);
  
  Epaper_Write_Command(0xE9);
  Epaper_Write_Data(0x01); 

  Epaper_Write_Command(0x30);
  Epaper_Write_Data(0x08);  
  
  Epaper_Write_Command(0x04);
  Epaper_READBUSY();
}

//////////////////////////////Display Update Function///////////////////////////////////////////////////////
//Full screen refresh update function
void EPD_Update(void)
{   
  Epaper_Write_Command(0x12); 
  Epaper_Write_Data(0x00);   
  Epaper_READBUSY();  

}


//////////////////////////////Display Data Transfer Function////////////////////////////////////////////
//Clear screen display
void EPD_WhiteScreen_White(void)
{
  unsigned int i;
  //Write Data
  Epaper_Write_Command(0x10);      
  for(i=0;i<EPD_ARRAY;i++)       
  {
    Epaper_Write_Data(0X55);  
  }
  EPD_Update();   
}

//Display all black
void EPD_WhiteScreen_Black(void)
{
  unsigned int i;
  //Write Data
  Epaper_Write_Command(0x10);      
  for(i=0;i<EPD_ARRAY;i++)       
  {
    Epaper_Write_Data(0X00);  
  }
  EPD_Update();
}

//Display all red
void EPD_WhiteScreen_Red(void)
{
  unsigned int i;
  //Write Data
  Epaper_Write_Command(0x10);      
  for(i=0;i<EPD_ARRAY;i++)       
  {
    Epaper_Write_Data(0Xff);  
  }
  EPD_Update();
}

//Display all yellow
void EPD_WhiteScreen_Yellow(void)
{
  unsigned int i;
  //Write Data
  Epaper_Write_Command(0x10);      
  for(i=0;i<EPD_ARRAY;i++)       
  {
    Epaper_Write_Data(0Xaa);  
  }
  EPD_Update();
}


//Deep sleep function
void EPD_DeepSleep(void)
{  
  Epaper_Write_Command(0x02); 
  Epaper_READBUSY();
  delay(100);

  Epaper_Write_Command(0x07); 
  Epaper_Write_Data(0xA5); 
}

unsigned char Color_get(unsigned char color)
{
  unsigned datas;
  switch(color)
  {
    case 0x00:
      datas=white;  
      break;    
    case 0x01:
      datas=yellow;
      break;
    case 0x02:
      datas=red;
      break;    
    case 0x03:
      datas=black;
      break;      
    default:
      break;      
  }
   return datas;
}

void PIC_display(const unsigned char* picData)
{
  unsigned int i,j;
  unsigned char temp1;
  unsigned char data_H1,data_H2,data_L1,data_L2,data;
   
  Epaper_Write_Command(0x10);        
  for(i=0;i<Gate_BITS;i++)  //Source_BITS*Gate_BITS/4
  { 
    for(j=0;j<Source_BITS/4;j++)
    {   
      temp1=pgm_read_byte(&picData[i*Source_BITS/4+j]); 

      data_H1=Color_get(temp1>>6&0x03)<<6;      
      data_H2=Color_get(temp1>>4&0x03)<<4;
      data_L1=Color_get(temp1>>2&0x03)<<2;
      data_L2=Color_get(temp1&0x03);
      
      data=data_H1|data_H2|data_L1|data_L2;
      Epaper_Write_Data(data);
    }
  } 
   //Refresh
    EPD_Update();  
}


void GUI_display(const unsigned char* picData)
{
  unsigned int Width, Height,i,j; 
    Width = (EPD_WIDTH % 4 == 0)? (EPD_WIDTH / 4 ): (EPD_WIDTH / 4 + 1);
    Height = EPD_HEIGHT;
    
    Epaper_Write_Command(0x04);
    Epaper_READBUSY();

    Epaper_Write_Command(0x10);
    for ( j = 0; j < Height; j++) {
        for ( i = 0; i < Width; i++) {
            Epaper_Write_Data(picData[i + j * Width]);
        }
    }

    EPD_Update();

}
