


void s65_writeSPI(uint8_t data)
{
#if defined(S65_SOFTWARE_SPI)
  uint8_t mask;
  
  for(mask=0x80; mask!=0; mask>>=1)
  {
    S65_CLK_LOW();
    if(mask & data)
    {
      S65_DAT_HIGH();
    }
    else
    {
      S65_DAT_LOW();
    }
    S65_CLK_HIGH();
  }
  S65_CLK_LOW();

#else
	SPDR = data;
  while(!(SPSR & (1<<SPIF)));
#endif

  return;
}


void s65_writeData(uint16_t data)
{
  S65_RS_ENABLE(); //data
  S65_CS_ENABLE();
  s65_writeSPI(data>>8);
  s65_writeSPI(data);
  S65_CS_DISABLE();

  return;
}


void s65_writeCmd(uint8_t reg, uint8_t param)
{
  S65_RS_DISABLE(); //cmd
  S65_CS_ENABLE();
  s65_writeSPI(reg);
  s65_writeSPI(param);
  S65_CS_DISABLE();

  return;
}

void s65_drawStart(void)
{
  S65_RS_ENABLE(); //data
  S65_CS_ENABLE();

  return;
}


void s65_init(void)
{
  //reset
  S65_CS_DISABLE();
  S65_RS_DISABLE();
  S65_RST_ENABLE();
  delay(50);
  S65_RST_DISABLE();
  delay(50);

  s65_writeCmd(0xFD, 0xFD);
  s65_writeCmd(0xFD, 0xFD);

  delay(50);

  //init 1
  s65_writeCmd(0xEF, 0x00);
  s65_writeCmd(0xEE, 0x04);
  s65_writeCmd(0x1B, 0x04);
  s65_writeCmd(0xFE, 0xFE);
  s65_writeCmd(0xFE, 0xFE);
  s65_writeCmd(0xEF, 0x90);
  s65_writeCmd(0x4A, 0x04);
  s65_writeCmd(0x7F, 0x3F);
  s65_writeCmd(0xEE, 0x04);
  s65_writeCmd(0x43, 0x06);

  _delay_ms(7); //important 7ms

  //init 2
  s65_writeCmd(0xEF, 0x90);
  s65_writeCmd(0x09, 0x83);
  s65_writeCmd(0x08, 0x00);
  s65_writeCmd(0x0B, 0xAF);
  s65_writeCmd(0x0A, 0x00);
  s65_writeCmd(0x05, 0x00);
  s65_writeCmd(0x06, 0x00);
  s65_writeCmd(0x07, 0x00);
  s65_writeCmd(0xEF, 0x00);
  s65_writeCmd(0xEE, 0x0C);
  s65_writeCmd(0xEF, 0x90);
  s65_writeCmd(0x00, 0x80);
  s65_writeCmd(0xEF, 0xB0);
  s65_writeCmd(0x49, 0x02);
  s65_writeCmd(0xEF, 0x00);
  s65_writeCmd(0x7F, 0x01);
  s65_writeCmd(0xE1, 0x81);
  s65_writeCmd(0xE2, 0x02);
  s65_writeCmd(0xE2, 0x76);
  s65_writeCmd(0xE1, 0x83);

  delay(50);

  //display on
  s65_writeCmd(0x80, 0x01);
  s65_writeCmd(0xEF, 0x90);
  s65_writeCmd(0x00, 0x00);
  
  //display options
  s65_writeCmd(0xEF, 0x90);
#if defined(S65_ROTATE)
# if defined(S65_MIRROR)
  s65_writeCmd(0x01, 0xC0); //x1->x0, y1->y0
  s65_writeCmd(0x05, 0x00); //0x04=rotate, 0x00=normal
# else
  s65_writeCmd(0x01, 0x00); //x0->x1, y0->y1
  s65_writeCmd(0x05, 0x00); //0x04=rotate, 0x00=normal
# endif
#else
# if defined(S65_MIRROR)
  s65_writeCmd(0x01, 0x80); //x0->x1, y1->y0
  s65_writeCmd(0x05, 0x04); //0x04=rotate, 0x00=normal
# else
  s65_writeCmd(0x01, 0x40); //x1->x0, y0->y1
  s65_writeCmd(0x05, 0x04); //0x04=rotate, 0x00=normal
# endif
#endif
  s65_setArea(0, 0, (S65_WIDTH-1), (S65_HEIGHT-1));

  return;
}

void s65_contrast(uint8_t value) //display contrast
{
  s65_writeCmd(0x24, value);
  s65_writeCmd(0x00, 0x00);

  return;
}

void s65_on(void)//display ON
{
  s65_writeCmd(0xEF, 0x90);
  s65_writeCmd(0x00, 0x00);

  return;
}


void s65_off(uint8_t bw)//display OFF with black/white background
{
  s65_writeCmd(0xEF, 0x90);
  if(bw == 0)
  {
      s65_writeCmd(0x00, 0x40); //black background
  }
  else
  {
      s65_writeCmd(0x00, 0x80); //white background
  }

  return;
}

void s65_setCursor(uint8_t x, uint8_t y)
{
  s65_writeCmd(0xEF, 0x90);
#if defined(S65_ROTATE)
# if defined(S65_MIRROR)
  s65_writeCmd(0x06, (S65_WIDTH-1)-x);  //set x cursor pos
  s65_writeCmd(0x07, (S65_HEIGHT-1)-y); //set y cursor pos
# else
  s65_writeCmd(0x06, x);                //set y cursor pos
  s65_writeCmd(0x07, y);                //set x cursor pos
# endif
#else
# if defined(S65_MIRROR)
  s65_writeCmd(0x06, (S65_HEIGHT-1)-y); //set y cursor pos
  s65_writeCmd(0x07, x);                //set x cursor pos
# else
  s65_writeCmd(0x06, y);                //set y cursor pos
  s65_writeCmd(0x07, (S65_WIDTH-1)-x);  //set x cursor pos
# endif
#endif

  return;
}

void s65_draw(uint16_t color)
{
  s65_writeSPI(color>>8);
  s65_writeSPI(color);

  return;
