#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include "sg_lgpio.h"
#include "2in9_epd.h"
// define pin conection in BCM number
/****************************
 * PIN_CS     8
 * PIN_RST    17
 * PIN_DC     25
 * PIN_BUSY   24
 ***************************/

unsigned char tmp[2];

void EPD_GPIO_Init(void)
{
  Lgpio_export();
  printf("Init gpio for lgpio\r\n");
  // Lgpio_set_pinmode(PIN_CS, LGPIO_OUTPUT);
  Lgpio_set_pinmode(PIN_RST, LGPIO_OUTPUT);
  Lgpio_set_pinmode(PIN_DC, LGPIO_OUTPUT);
  Lgpio_set_pinmode(PIN_BUSY, LGPIO_INPUT);
  // pullUpDnControl(PIN_BUSY, PUD_DOWN);
  LG_SPI_Init(0, 0, 8000000);
  if (SPI_handle < 0) // use lgpio Pin number
  {
    printf("lgpio lib init failed! \r\n");
  }
}

void delay_xms(unsigned int xms)
{
  unsigned int i;
  while (xms--)
  {
    i = 12000;
    while (i--)
      ;
  }
}

void Epaper_READBUSY(void)
{
  while (1)
  { //=1 BUSY
    if (Lgpio_read_pin(PIN_BUSY) == LGPIO_HIGH)
      break;
  }
}

void Epaper_Write_Command(unsigned char cmd)
{
  tmp[0] = cmd;
  // digitalWrite(PIN_CS, 1);
  // digitalWrite(PIN_CS, 0);
  Lgpio_write_pin(PIN_DC, LGPIO_LOW); // D/C#   0:command  1:data
  lgSpiWrite(SPI_handle, tmp, 1);
  //	Epaper_Spi_WriteByte(cmd);
  // digitalWrite(PIN_CS, 1);
}

void Epaper_Write_Data(unsigned char data)
{
  tmp[0] = data;
  // digitalWrite(PIN_CS, 1);
  // digitalWrite(PIN_CS, 0);
  Lgpio_write_pin(PIN_DC, LGPIO_HIGH); // D/C#   0:command  1:data
                                       // wiringPiSPIDataRW(0,&data,1);
  lgSpiWrite(SPI_handle, tmp, 1);
  //	Epaper_Spi_WriteByte(data);
  // digitalWrite(PIN_CS, 1);
}

/////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////

// SSD1681
void EPD_HW_Init(void)
{

  Lgpio_write_pin(PIN_RST, LGPIO_LOW); // Module reset
  delay_xms(10);                       // At least 10ms delay
  Lgpio_write_pin(PIN_RST, LGPIO_HIGH);
  delay_xms(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();
}

void EPD_DeepSleep(void)
{
  Epaper_Write_Command(0x02); // enter deep sleep
  Epaper_READBUSY();          // waiting for the electronic paper IC to release the idle signal
  delay(100);
  Epaper_Write_Command(0x07); // enter deep sleep
  Epaper_Write_Data(0xA5);    // enter deep sleep
}

void EPD_refresh(void)
{
  Epaper_Write_Command(0x12); // Display Update Control
  Epaper_Write_Data(0x00);
  Epaper_READBUSY();
}

void EPD_WhiteScreen_White(void)

{
  unsigned int i, k;
  Epaper_Write_Command(0x10); // write RAM for black(0)/white (1)
  for (k = 0; k < 9472; k++)
  {
    Epaper_Write_Data(0x55);
  }
  EPD_refresh();
}

void EPD_WhiteScreen_black(void)

{
  unsigned int i, k;
  Epaper_Write_Command(0x10); // write RAM for black(0)/white (1)
  for (k = 0; k < 9472; k++)
  {
    Epaper_Write_Data(0x00);
  }
  EPD_refresh();
}

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

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

unsigned char Color_get(unsigned char color)
{
  unsigned datas;
  switch (color)
  {
  case 0x00:
    datas = 0x01;
    break;
  case 0x01:
    datas = 0x02;
    break;
  case 0x02:
    datas = 0x03;
    break;
  case 0x03:
    datas = 0x00;
    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=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_refresh();  
}

void GUI_display(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_refresh();
}

/***********************************************************
            end file
***********************************************************/
