#include "main.h"
#include "lcd_drv.h"


u8 lcd_mem[32] = "Test Valout:    ";		// LCD 2*16

u8 idx;


ISR( TIMER2_COMP_vect )		// 1ms
{
  u8 d;

  switch( ++idx ){
    case 0x40:
      d = 0x80;				// Line 1
      idx = 0xFF;			// lcd_mem: 00 .. 0F
      LCD_RS = 0;
      break;

    case 0x10:
      d = 0xC0;				// Line 2
      idx = 0x2F;			// lcd_mem: 10 .. 1F
      LCD_RS = 0;
      break;

    default:
      LCD_RS = 1;
      d = lcd_mem[idx & 0x1F];
  }
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
  LCD_E0 = 1;
  _delay_us( 1 );			// 1us
  LCD_E0 = 0;
  LCD_D7 = 0; if( d & 1<<3 ) LCD_D7 = 1;
  LCD_D6 = 0; if( d & 1<<2 ) LCD_D6 = 1;
  LCD_D5 = 0; if( d & 1<<1 ) LCD_D5 = 1;
  LCD_D4 = 0; if( d & 1<<0 ) LCD_D4 = 1;
  LCD_E0 = 1;
  _delay_us( 1 );			// 1us
  LCD_E0 = 0;
}


static void lcd_nibble( u8 d )
{
  LCD_D7 = 0; if( d & 1<<7 ) LCD_D7 = 1;
  LCD_D6 = 0; if( d & 1<<6 ) LCD_D6 = 1;
  LCD_D5 = 0; if( d & 1<<5 ) LCD_D5 = 1;
  LCD_D4 = 0; if( d & 1<<4 ) LCD_D4 = 1;
  LCD_E0 = 1;
  _delay_us( 1 );			// 1us
  LCD_E0 = 0;
  _delay_us( 100 );			// 100us
}


static void lcd_byte( u8 d )
{
  lcd_nibble( d );
  lcd_nibble( d<<4 );
}


void lcd_init( void )
{
  LCD_DDR_D4 = 1;
  LCD_DDR_D5 = 1;
  LCD_DDR_D6 = 1;
  LCD_DDR_D7 = 1;
  LCD_DDR_RS = 1;
  LCD_DDR_E0 = 1;
  LCD_E0 = 0;
  LCD_RS = 0;				// send commands

  _delay_ms( 15 );			// 15ms
  lcd_nibble( 0x30 );
  _delay_ms( 5 );			// 5ms
  lcd_nibble( 0x30 );			// 8 bit mode
  lcd_nibble( 0x30 );			// 8 bit mode
  lcd_nibble( 0x20 );			// 4 bit mode
  lcd_byte( 0x28 );			// 2 lines 5*7
  lcd_byte( 0x06 );			// cursor increment
  lcd_byte( 0x0C );			// on, no cursor, no blink

  TCCR2 = 1<<WGM21;			// CTC mode
  TCCR2 = 1<<CS22;			// XTAL / 64
  OCR2 = (uint8_t)(XTAL / 64.0 * 1e-3 - 0.5);  // 1ms
  TIMSK |= 1<<OCIE2;
}
