#include "c55_lcd.h"

void lcd_Delay(void)
{
  for (unsigned int i = 0x00; i < 0xffff; i++);
}

void lcd_GoToXY(char x, char y)
{
  lcd_Send( 0x80 | x, LCD_CMD );
  lcd_Send( 0x40 | y, LCD_CMD );
}

void lcd_Init(void)
{
#ifdef USE_POWER_PIN
  LCD_PORT &= ~LCD_PWR_PIN;
#endif
  LCD_PORT &= ~(LCD_RST_PIN | LCD_DC_PIN | LCD_MOSI_PIN | LCD_CLK_PIN);
  LCD_CE_PORT &= ~LCD_CE_PIN;
#ifdef USE_POWER_PIN
  LCD_DDR |= LCD_PWR_PIN;
#endif
  lcd_Delay();
  LCD_DDR |= LCD_RST_PIN | LCD_DC_PIN | LCD_MOSI_PIN | LCD_CLK_PIN;
  LCD_CE_DDR |= LCD_CE_PIN;
#ifdef USE_POWER_PIN
  LCD_PORT |= LCD_PWR_PIN;
#endif
  LCD_PORT |= LCD_RST_PIN | LCD_DC_PIN | LCD_MOSI_PIN | LCD_CLK_PIN;
  LCD_CE_PORT |= LCD_CE_PIN;
  LCD_PORT &= ~LCD_RST_PIN;
  lcd_Delay();
  LCD_PORT |= LCD_RST_PIN;
  lcd_Send(0x21,LCD_CMD); // PowerON, ExtCommandSet
  lcd_Send(0x09,LCD_CMD); // Internal HV-gen x3
  lcd_Send(0xE0,LCD_CMD); // Set Vop
  lcd_Send(0x16,LCD_CMD); // Bias n=2    //15
  lcd_Send(0x06,LCD_CMD); // Temperature coeff 2 //6
  lcd_Send(0x20,LCD_CMD); // StandartCommandSet
  lcd_Send(0x0C,LCD_CMD); // normal mode, display non-inverted
  lcd_Clear();
}

void lcd_Clear(void)
{
  lcd_GoToXY(0, 0);
  for (int i = 0; i < 102 * 8; i++)
    lcd_Send(0x00, LCD_DATA);
}

void lcd_ClearInverse(void)
{
  lcd_GoToXY(0, 0);
  for (int i = 0; i < 102 * 8; i++)
    lcd_Send(0xff, LCD_DATA);
}

void lcd_Contrast (char contrast)
{
  lcd_Send(0x21, LCD_CMD);
  lcd_Send(0x80 | contrast, LCD_CMD);
  lcd_Send(0x20, LCD_CMD);
  for (int i = -32000; i < 32000; i++);
}

void lcd_ClockData(char data)
{
  for (char i = 0x00; i < 0x08; i++)
  {
    LCD_PORT &= ~LCD_CLK_PIN;
    if (((data << i) & 0x80) != 0x00)
	  LCD_PORT |= LCD_MOSI_PIN;
    else LCD_PORT &= ~LCD_MOSI_PIN;
    LCD_PORT |= LCD_CLK_PIN;
  }
}

void lcd_Send (char data, LcdCmdData cd)
{
  LCD_DDR |= LCD_RST_PIN | LCD_DC_PIN | LCD_MOSI_PIN | LCD_CLK_PIN;
  LCD_CE_PORT &= ~LCD_CE_PIN;
  if ( cd == LCD_DATA )
    LCD_PORT |= LCD_DC_PIN;
  else LCD_PORT &= ~LCD_DC_PIN;
  lcd_ClockData(data);
  LCD_CE_PORT |= LCD_CE_PIN;
  LCD_DDR &= ~(LCD_RST_PIN | LCD_DC_PIN | LCD_MOSI_PIN | LCD_CLK_PIN);
}

void lcd_PutChar(char c)
{
  for (char i = 0; i < 5; i++)
    if (c < 0xc0)
	  lcd_Send(pgm_read_byte(&LCD_FONT[c - 0x20][i]), LCD_DATA);
	else if (c < 0xed)
	       lcd_Send(pgm_read_byte(&LCD_FONT[c - 0x65][i]), LCD_DATA);
         else if (c < 0xfc)
		        lcd_Send(pgm_read_byte(&LCD_FONT[c - 0x64][i]), LCD_DATA);
			  else lcd_Send(pgm_read_byte(&LCD_FONT[c - 0x63][i]), LCD_DATA);
}

void lcd_PutStr(char *s)
{
  while (*s)
    lcd_PutChar(*s++);
}

void lcd_PutInverseChar(char c)
{
  for (char i = 0; i < 5; i++)
    if (c < 0xc0)
	  lcd_Send(~pgm_read_byte(&LCD_FONT[c - 0x20][i]), LCD_DATA);
	else if (c < 0xed)
	       lcd_Send(~pgm_read_byte(&LCD_FONT[c - 0x65][i]), LCD_DATA);
         else if (c < 0xfc)
		        lcd_Send(~pgm_read_byte(&LCD_FONT[c - 0x64][i]), LCD_DATA);
			  else lcd_Send(~pgm_read_byte(&LCD_FONT[c - 0x63][i]), LCD_DATA);
}

void lcd_PutInverseStr(char *s)
{
  while (*s)
    lcd_PutInverseChar(*s++);
}

