
//S65 display (LS020) - http://www.watterott.net


//#define LCD_MIRROR         //define to mirror the display
//#define LCD_ROTATE         //define to rotate the display
#if defined(LCD_ROTATE)
# define LCD_WIDTH           (132)
# define LCD_HEIGHT          (176)
#else
# define LCD_WIDTH           (176)
# define LCD_HEIGHT          (132)
#endif
#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
#define LCD_RS_ENABLE()      RS low


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_RS_ENABLE(); //data
  LCD_CS_ENABLE();

  return;
}


void lcd_area(unsigned int x0, unsigned int y0, unsigned int x1, unsigned int y1)
{
  //set area
  lcd_cmd(0xEF, 0x90);
#if defined(LCD_ROTATE)
# if defined(LCD_MIRROR)
  lcd_cmd(0x08, (LCD_WIDTH-1)-x0);  //set x0
  lcd_cmd(0x09, (LCD_WIDTH-1)-x1);  //set x1
  lcd_cmd(0x0A, (LCD_HEIGHT-1)-y0); //set y0
  lcd_cmd(0x0B, (LCD_HEIGHT-1)-y1); //set y1
# else
  lcd_cmd(0x08, x0);                //set x0
  lcd_cmd(0x09, x1);                //set x1
  lcd_cmd(0x0A, y0);                //set y0
  lcd_cmd(0x0B, y1);                //set y1
# endif
#else
# if defined(LCD_MIRROR)
  lcd_cmd(0x08, (LCD_HEIGHT-1)-y0); //set y0
  lcd_cmd(0x09, (LCD_HEIGHT-1)-y1); //set y1
  lcd_cmd(0x0A, x0);                //set x0
  lcd_cmd(0x0B, x1);                //set x1
# else
  lcd_cmd(0x08, y0);                //set y0
  lcd_cmd(0x09, y1);                //set y1
  lcd_cmd(0x0A, (LCD_WIDTH-1)-x0);  //set x0
  lcd_cmd(0x0B, (LCD_WIDTH-1)-x1);  //set x1
# endif
#endif

  //set cursor
  lcd_cursor(x0, y0);

  return;
}


void lcd_cursor(unsigned int x, unsigned int y)
{
  lcd_cmd(0xEF, 0x90);
#if defined(LCD_ROTATE)
# if defined(LCD_MIRROR)
  lcd_cmd(0x06, (LCD_WIDTH-1)-x);  //set x cursor pos
  lcd_cmd(0x07, (LCD_HEIGHT-1)-y); //set y cursor pos
# else
  lcd_cmd(0x06, x);                //set x cursor pos
  lcd_cmd(0x07, y);                //set y cursor pos
# endif
#else
# if defined(LCD_MIRROR)
  lcd_cmd(0x06, (LCD_HEIGHT-1)-y); //set y cursor pos
  lcd_cmd(0x07, x);                //set x cursor pos
# else
  lcd_cmd(0x06, y);                //set y cursor pos
  lcd_cmd(0x07, (LCD_WIDTH-1)-x);  //set x cursor pos
# endif
#endif

  return;
}


void lcd_cmd(unsigned int reg, unsigned int param)
{
  LCD_RS_DISABLE(); //cmd
  LCD_CS_ENABLE();
  spi_write(reg);
  spi_write(param);
  spi_wait();
  LCD_CS_DISABLE();

  return;
}


void lcd_data(unsigned int c)
{
  LCD_RS_ENABLE(); //data
  LCD_CS_ENABLE();
  spi_write(c>>8);
  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(0xFD, 0xFD);
  lcd_cmd(0xFD, 0xFD);

  delay_ms(50);

  //init 1
  lcd_cmd(0xEF, 0x00);
  lcd_cmd(0xEE, 0x04);
  lcd_cmd(0x1B, 0x04);
  lcd_cmd(0xFE, 0xFE);
  lcd_cmd(0xFE, 0xFE);
  lcd_cmd(0xEF, 0x90);
  lcd_cmd(0x4A, 0x04);
  lcd_cmd(0x7F, 0x3F);
  lcd_cmd(0xEE, 0x04);
  lcd_cmd(0x43, 0x06);

  delay_ms(7); //important: 7ms

  //init 2
  lcd_cmd(0xEF, 0x90);
  lcd_cmd(0x09, 0x83);
  lcd_cmd(0x08, 0x00);
  lcd_cmd(0x0B, 0xAF);
  lcd_cmd(0x0A, 0x00);
  lcd_cmd(0x05, 0x00);
  lcd_cmd(0x06, 0x00);
  lcd_cmd(0x07, 0x00);
  lcd_cmd(0xEF, 0x00);
  lcd_cmd(0xEE, 0x0C);
  lcd_cmd(0xEF, 0x90);
  lcd_cmd(0x00, 0x80);
  lcd_cmd(0xEF, 0xB0);
  lcd_cmd(0x49, 0x02);
  lcd_cmd(0xEF, 0x00);
  lcd_cmd(0x7F, 0x01);
  lcd_cmd(0xE1, 0x81);
  lcd_cmd(0xE2, 0x02);
  lcd_cmd(0xE2, 0x76);
  lcd_cmd(0xE1, 0x83);

  delay_ms(50);

  //display on
  lcd_cmd(0x80, 0x01);
  lcd_cmd(0xEF, 0x90);
  lcd_cmd(0x00, 0x00);

  //display options
  lcd_cmd(0xEF, 0x90);
#if defined(LCD_ROTATE)
# if defined(LCD_MIRROR)
  lcd_cmd(0x01, 0xC0); //x1->x0, y1->y0
  lcd_cmd(0x05, 0x00); //0x04=rotate, 0x00=normal
# else
  lcd_cmd(0x01, 0x00); //x0->x1, y0->y1
  lcd_cmd(0x05, 0x00); //0x04=rotate, 0x00=normal
# endif
#else
# if defined(LCD_MIRROR)
  lcd_cmd(0x01, 0x80); //x0->x1, y1->y0
  lcd_cmd(0x05, 0x04); //0x04=rotate, 0x00=normal
# else
  lcd_cmd(0x01, 0x40); //x1->x0, y0->y1
  lcd_cmd(0x05, 0x04); //0x04=rotate, 0x00=normal
# endif
#endif
  lcd_area(0, 0, (LCD_WIDTH-1), (LCD_HEIGHT-1));

  return;
}

