#include <SPI.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "2inch9_epd.h"

/////////////////////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++)
        ;
    }
  }
}


void SPI_Delay(unsigned char xrate) {
  unsigned char i;
  while (xrate) {
    for (i = 0; i < 2; i++)
      ;
    xrate--;
  }
}

//SPI write byte
void SPI_Write(unsigned char value) {
  SPI.transfer(value);
}

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

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


void EPD_HW_Init(void) {
  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 < ALLSCREEN_BYTES; 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 < ALLSCREEN_BYTES; 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();
}
