//************************************************************************
// 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);
}