#include <avr/io.h>
#include "i2cmaster.h"
#include    "PCF8535.h"
#include "font.h"

// Start write transaction:
// Generate START condition, send device address and control byte
// return non-zero on success, 0 if NACK received

static uint8_t lcd_start_write(uint8_t control_byte)
{
    i2c_start(PCF8535_BUS_ADDRESS);
    //if(i2c_write(PCF8535_BUS_ADDRESS)!= 0)
    //return 0;
    if(i2c_write(control_byte)!= 0)
        return 0;
    return 1;
}

// Send [size] bytes to LCD
// return non-zero on success, 0 if NACK received
static uint8_t lcd_send_array(uint8_t *data, uint16_t size)
{
    do
    {
        if(i2c_write(*data++)!= 0)
            return 0;
    }
    while (--size);
    return 1;
}

//  LCD controller init sequence
static uint8_t lcd_init_sequence[] =
{

    cmdLCD_DEFAULT_PAGE
    ,
    cmdLCD_COMMAND_PAGE
    | paramLCD_PAGE_DISPLAY_SETTINGS
    ,
    cmdLCD_BIAS_SYSTEM
    | paramLCD_BIAS_9   // Bias 1/9,  MUX 1:65
    ,
    cmdLCD_MULTILPEX_RATE
    | paramLCD_MUX_65
    ,
    cmdLCD_DISPLAY_CONTROL
    | paramLCD_NORMAL
    ,
    cmdLCD_EXT_DISPLAY_CTL
    | paramLCD_XDIRECTION_NORMAL
    | paramLCD_YDIRECTION_NORMAL
    ,
    cmdLCD_DISPLAY_SIZE
    | paramLCD_LARGE_DISPLAY
    ,

    cmdLCD_DEFAULT_PAGE
    ,
    cmdLCD_COMMAND_PAGE
    | paramLCD_PAGE_HV_GEN
    ,
    cmdLCD_HV_GEN_CONTROL
    | paramLCD_HV_ENABLED
    | paramLCD_VLCD_LOW
    ,
    cmdLCD_HV_GEN_STAGES
    | paramLCD_HV_MUL5
    ,
    cmdLCD_TEMP_COEFF
    | paramLCD_TC_274
    ,
    cmdLCD_VLCD_CONTROL
    | 51
    ,

    cmdLCD_DEFAULT_PAGE
    ,
    cmdLCD_COMMAND_PAGE
    | paramLCD_PAGE_SPECIAL_FEATURE
    ,
    cmdLCD_STATE_CONTROL
    | 0
    ,
    cmdLCD_OSC_SETTING
    | paramLCD_OSC_INTERNAL
    ,
    cmdLCD_COG_TCP
    //| paramLCD_BOT_ROW_SWAP_ENABLED
    //| paramLCD_TOP_ROW_SWAP_ENABLED
    ,

    cmdLCD_DEFAULT_PAGE
    ,
    cmdLCD_FUNCTION_SET
    | paramLCD_ACTIVE
    | paramLCD_HORIZONTAL_ADDRESSING
    ,
    cmdLCD_RAM_PAGE
    | paramLCD_PAGE0
    ,
    cmdLCD_SET_Y
    | 0
    ,
    cmdLCD_SET_X
    | 0
    ,
};

static uint8_t lcd_set_home_sequence[] =
{
    cmdLCD_DEFAULT_PAGE
    ,
    cmdLCD_SET_Y
    | 0
    ,
    cmdLCD_SET_X
    | 0
    ,
};
void lcd_home()
{
    lcd_start_write(modeLCD_CMD_TILL_STOP);
    lcd_send_array(lcd_set_home_sequence, sizeof(lcd_set_home_sequence));
    i2c_stop();
}

void lcd_init()
{
    uint16_t i;
    // Set lcd reset pin as output
    // Set lcd reset pin low
    /*OFF(LCD_RESET);
    _delay_us(1);    // tW(RESL)
    ON(LCD_RESET);
    _delay_us(5);    // tW(RESH)
    OFF(LCD_RESET);
    _delay_us(1);    // tW(RESL)
    ON(LCD_RESET);
    _delay_us(3);    // tR(OP)*/

    //***************************************************
    //* Lcd init commands                               *
    //***************************************************
    lcd_start_write(modeLCD_CMD_TILL_STOP);
    lcd_send_array(lcd_init_sequence, sizeof(lcd_init_sequence));
    i2c_stop();

    // Now lcd address pointer set to row 0, col. 0.
    // fill whole screen with black pattern
    lcd_start_write(modeLCD_DATA_TILL_STOP);
    // lcd address pointer autoincrements,
    // so we can just draw LCD_SIZE_X*LCD_SIZE_Y points.
    // one byte fills 8 dots on screen,

    for(i = 0; i < LCD_SIZE_X * LCD_SIZE_Y / 16; ++i)
    {
        i2c_write(0x55);
        i2c_write(0xAA);
    }
    i2c_stop();
}

void lcd_set_contrast(uint8_t contrast)
{
    lcd_start_write(modeLCD_CMD_TILL_STOP);
    i2c_write(cmdLCD_DEFAULT_PAGE);
    i2c_write(cmdLCD_COMMAND_PAGE | paramLCD_PAGE_HV_GEN);
    /*
        if(contrast > 128)
        {
            i2c_write(cmdLCD_HV_GEN_CONTROL
                        | paramLCD_HV_ENABLED
                        | paramLCD_VLCD_HIGH
                        );
            contrast -= 128;
        }
        else
    */
    i2c_write(cmdLCD_HV_GEN_CONTROL
              | paramLCD_HV_ENABLED
              | paramLCD_VLCD_LOW
             );
    i2c_write(cmdLCD_VLCD_CONTROL | contrast >> 1);
    i2c_stop();
}


void lcd_set_pos ( unsigned char x,unsigned char y )//x=0..132,y=0..7
{
    i2c_start(PCF8535_BUS_ADDRESS);
    //i2c_write(PCF8535_BUS_ADDRESS);
    i2c_write(modeLCD_CMD_TILL_STOP);//control byte C0=0,D/C=0;
    i2c_write(cmdLCD_DEFAULT_PAGE);
    i2c_write(cmdLCD_SET_Y|y);//set y pos
    if(x<128)
    {
        i2c_write(cmdLCD_RAM_PAGE| paramLCD_PAGE0);//set ram page 0
        i2c_write(cmdLCD_SET_X|x);//set x pos
    }
    else
    {
        i2c_write(cmdLCD_RAM_PAGE| paramLCD_PAGE1);//set ram page 1
        i2c_write(cmdLCD_SET_X|(x-128));//set x pos
    }
    i2c_stop();
}


void lcd_clear( void )
{
    uint16_t i;

    lcd_set_pos(0,0);

    // Now lcd address pointer set to row 0, col. 0.
    // fill whole screen with black pattern
    lcd_start_write(modeLCD_DATA_TILL_STOP);
    // lcd address pointer autoincrements,
    // so we can just draw LCD_SIZE_X*LCD_SIZE_Y points.
    // one byte fills 8 dots on screen,

    for(i = 0; i < LCD_SIZE_X * LCD_SIZE_Y / 16; ++i)
    {
        i2c_write(0x00);
        i2c_write(0x00);
    }
    i2c_stop();
}


void lcd_dot( uint8_t xpos, uint8_t ypos)
{
    uint16_t offset,y;

    y=ypos/8;
    offset=ypos%8;

    lcd_set_pos(xpos,y);
    i2c_start(PCF8535_BUS_ADDRESS);              //repeat start
    i2c_write(cmdLCD_SET_Y);
    i2c_write(cmdLCD_SET_X>>offset);
    i2c_stop();
}

void lcd_puttext(int X, int Y,//координаты
                    char *str,//строка вывода
                //unsigned char *n, //количество символов
                unsigned char inv)//инвертирование символов
{
    uint8_t i, t, s, x, textL;

    lcd_set_pos(X,Y);
    lcd_start_write(modeLCD_DATA_TILL_STOP);

    while(*str != '\0')
    {
        s = *(str);

        if  (s < 0x90)  {
            textL=0x20;
        } else {
            textL=0x60;
        }

        for(i=0;i<5;i++)
        {
            t = sym[s - textL-1][i];
            i2c_write(t);
        }
        str++;
    }
    i2c_stop();

};
