//************************************************************************
// lcd /define nSCLK, nSDIN, nDC, nSC, nRESET /

//uint8_t init_n5110[9]={0x21,0xc5,0x13,0x20,0x09,0x08,0xc,0x40,0x80};

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdint.h>
#include <stdio.h>
#include "lcd.h"
#include "ascii_table.h"

void delay_ms1(uint16_t time)
{
	while(time--) _delay_ms(1);
}

void N5110_send(uint8_t data)
{
	uint8_t a;

	for (a=0;a<8;a++)
	{
		nSCLK_L;
		if (data & 0x80) nSDIN_H;
		else nSDIN_L;
		data <<= 1;
		nSCLK_H;
	}	
}

void N5110_send_data(uint8_t data)
{
	nDC_H;
	nCS_L;
	N5110_send(data);
	nCS_H;
}

void N5110_send_command(uint8_t data)
{
	nDC_L;
	nCS_L;
	N5110_send(data);
	nCS_H;
}

void LCD_N5110_INIT(void)
{
	//uint8_t a;
	
	nDC_H;
	nSCLK_H;
	nCS_H;
	nRESET_L;
	delay_ms1(20);
	nRESET_H;

	//mise lcd
	//for (a=0;a<9;a++) N5110_send_command(init_n5110[a]);
		N5110_send_command(EXTENDED_SET);
		N5110_send_command(VOP|0x45);		//default 0x45
		N5110_send_command(BIAS_1);
	N5110_send_command(H_ADDR);
		N5110_send_command(DISPLAY_ALL_ON);
		//clear_lcd();
		//delay_ms1(1000);
		N5110_send_command(DISPLAY_BLANK);
		//delay_ms1(1000);
	N5110_send_command(DISPLAY_NORMAL);

	/*	//mija lcd
	//for (a=0;a<9;a++) N5110_send_command(init_n5110[a]);
	//N5110_send_command(EXTENDED_SET);
	//N5110_send_command(VOP|69);		//default 0x45
	//N5110_send_command(BIAS_3);
	N5110_send_command(H_ADDR);
	//N5110_send_command(DISPLAY_ALL_ON);
	//clear_lcd();
	//delay_ms(1000);
	//N5110_send_command(DISPLAY_BLANK);
	//delay_ms(1000);
	N5110_send_command(DISPLAY_NORMAL);
	*/
}

//************************************************************************
// buffer lcd

uint8_t video_buf[504];
uint8_t *offset_text;

int lcd_put(char c, FILE *stream)
{
	uint8_t a;
	uint16_t pos;
	
	pos = (c - 0x20) * 5;
	for(a=0; a<5;a++)
	{
		*(offset_text++) = pgm_read_byte(&ASCII_TABLE1[pos+a]);
	}
	*(offset_text++)  = 0;
	return 0;
}

int lcd_put2(char c, FILE *stream)
{
	uint8_t a;
	uint8_t b;
	uint16_t pos;
	uint8_t pom;
	uint8_t l_text;
	uint8_t h_text;

	pos = (c - 0x20) * 5;
	for(a=0; a<5;a++)
	{
		h_text=0;
		l_text=0;
		pom = pgm_read_byte(&ASCII_TABLE1[pos+a]);
		for (b=0;b<4;b++)
		{
			if (pom & 0x01) l_text |= 3<<(2*b);
			if (pom & 0x10) h_text |= 3<<(2*b);
			pom>>=1;
		}
		*(offset_text+84) = h_text;
		*(offset_text++)  = l_text;
	}
	*(offset_text+84) = 0;
	*(offset_text++)  = 0;
	return 0;
}


void gotoxy(uint8_t x,uint8_t y)
{
	offset_text= video_buf + (y-1)*84 + 6*(x-1);
}

void lcd_refresh(void)
{
	uint16_t a;
	uint8_t *point;

	N5110_send_command(0x40);
	N5110_send_command(0x80);
	point = video_buf;
	for (a=0;a<504;a++) N5110_send_data(*(point++));
	
}

void buffer_clr(void)
{
	uint16_t a;

	for (a=0;a<504;a++) video_buf[a]=0;
	offset_text = video_buf;
}

//************************************************************************
// graphics

void lcd_plot(uint8_t x, uint8_t y)
{
	uint8_t *point;

	if (x>(LCD_WIDTH-1) || y>(LCD_HEIGHT-1)) return;
	point = video_buf + LCD_WIDTH*((LCD_HEIGHT-y-1)/8)+x;
	*point |= 1<<(7-(y%8));
}

void lcd_line(uint8_t x1,uint8_t y1,uint8_t x2, uint8_t y2)
{
	uint8_t a;
	uint8_t savex,savey;

	if (x1>x2) {savex=x1;savey=y1;x1=x2;y1=y2;x2=savex;y2=savey;}
	if (y1>y2)
	{
		if ((x2-x1)>(y1-y2))for (a=x1;a<=x2;a++)lcd_plot(a,y1-((y1-y2)*(a-x1)/(x2-x1)));
		else for (a=y2;a<=y1;a++)lcd_plot(x2-((x2-x1)*(a-y2)/(y1-y2)),a);
		return;
	}
	if ((x2-x1)>(y2-y1))for (a=x1;a<=x2;a++)lcd_plot(a,y1+((y2-y1)*(a-x1)/(x2-x1)));
	else for (a=y1;a<=y2;a++)lcd_plot(x1+((x2-x1)*(a-y1)/(y2-y1)),a);
}

