
//S65 display (LPH88) - http://www.watterott.net


//#define LCD_MIRROR         //define to mirror the display
#define LCD_WIDTH            (176)
#define LCD_HEIGHT           (132)
#define RGB(r,g,b)           (((r&0xF8)<<8)|((g&0xFC)<<3)|((b&0xF8)>>3)) //5 red | 6 green | 5 blue

#define LCD_RST_DISABLE()    RST high
#define LCD_RST_ENABLE()     RST low
#define LCD_CS_DISABLE()     CS high
#define LCD_CS_ENABLE()      CS low
#define LCD_RS_DISABLE()     RS high //not used
#define LCD_RS_ENABLE()      RS low  //not used


void lcd_clear(unsigned int color)
{
  unsigned int i;

  lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1));

  lcd_drawstart();
  for(i=(LCD_WIDTH*LCD_HEIGHT/8); i!=0; i--)
  {
    lcd_draw(color); //1
    lcd_draw(color); //2
    lcd_draw(color); //3
    lcd_draw(color); //4
    lcd_draw(color); //5
    lcd_draw(color); //6
    lcd_draw(color); //7
    lcd_draw(color); //8
  }
  lcd_drawstop();

  return;
}


void lcd_draw(unsigned int color)
{
  spi_write(color>>8);
  spi_write(color);

  return;
}


void lcd_drawstop(void)
{
  spi_wait();
  LCD_CS_DISABLE();

  return;
}


void lcd_drawstart(void)
{
  lcd_reg(0x22);
  LCD_CS_ENABLE();
  spi_write(0x76);

  return;
}


void lcd_area(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
{
  //set area
#if defined(LCD_MIRROR)
  lcd_cmd(0x16, (((LCD_HEIGHT-1)-y0)<<8) | (((LCD_HEIGHT-1)-y1))); //set y
  lcd_cmd(0x17, (((LCD_WIDTH-1)-x0)<<8)  | (((LCD_WIDTH-1)-x1)));  //set x
#else
  lcd_cmd(0x16, (y1<<8)|(y0)); //set y
  lcd_cmd(0x17, (x1<<8)|(x0)); //set x
#endif

  //set cursor
  lcd_cursor(x0, y0);

  return;
}


void lcd_cursor(unsigned int x, unsigned int y)
{
#if defined(LCD_MIRROR)
  lcd_cmd(0x21, ((((LCD_WIDTH-1)-x)<<8)|((LCD_HEIGHT-1)-y))); //set cursor pos
#else
  lcd_cmd(0x21, ((x<<8)|y)); //set cursor pos
#endif

  return;
}


void lcd_cmd(unsigned int reg, unsigned int param)
{
  lcd_reg(reg);
  lcd_data(param);

  return;
}


void lcd_data(unsigned int c)
{
  LCD_CS_ENABLE();
  spi_write(0x76); //instruction or RAM data
  spi_write(c>>8);
  spi_write(c);
  spi_wait();
  LCD_CS_DISABLE();

  return;
}


void lcd_reg(unsigned int c)
{
  LCD_CS_ENABLE();
  spi_write(0x74); //index register
  spi_write(0x00);
  spi_write(c);
  spi_wait();
  LCD_CS_DISABLE();

  return;
}


void lcd_reset(void)
{
  //reset
  LCD_CS_DISABLE();
  LCD_RS_DISABLE();
  LCD_RST_ENABLE();
  delay_ms(50);
  LCD_RST_DISABLE();
  delay_ms(50);

  lcd_cmd(0x07, 0x0000); //display off
  delay_ms(10);

  //power on sequence
  lcd_cmd(0x02, 0x0400); //lcd drive control
  lcd_cmd(0x0C, 0x0001); //power control 3: VC        //step 1
  lcd_cmd(0x0D, 0x0006); //power control 4: VRH
  lcd_cmd(0x04, 0x0000); //power control 2: CAD
  lcd_cmd(0x0D, 0x0616); //power control 4: VRL
  lcd_cmd(0x0E, 0x0010); //power control 5: VCM
  lcd_cmd(0x0E, 0x1010); //power control 5: VDV
  lcd_cmd(0x03, 0x0000); //power control 1: BT        //step 2
  lcd_cmd(0x03, 0x0000); //power control 1: DC
  lcd_cmd(0x03, 0x000C); //power control 1: AP
  delay_ms(40);
  lcd_cmd(0x0E, 0x2D1F); //power control 5: VCOMG     //step 3
  delay_ms(40);
  lcd_cmd(0x0D, 0x0616); //power control 4: PON       //step 4
  delay_ms(100);

  //display options
#if defined(LCD_MIRROR)
  lcd_cmd(0x05, 0x0008); //Entry mode --
#else
  lcd_cmd(0x05, 0x0038); //Entry mode ++
#endif
  lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1));

  //display on sequence (bit2 = reversed colors)
  lcd_cmd(0x07, 0x0005); //display control: D0
  lcd_cmd(0x07, 0x0025); //display control: GON
  lcd_cmd(0x07, 0x0027); //display control: D1
  lcd_cmd(0x07, 0x0037); //display control: DTE

  delay_ms(10);

  return;
}

