//***************************************************************************
//  File........: nokia_lcd.lib
//  Author(s)...: Chiper vs ujin for use in the cvavr program is adapted
//  URL(s)......: http://digitalchip.ru/
//  Device(s)...: ATMega...
//  Compiler....: special for cvavr
//  Description.: Драйвер LCD-контроллера от Nokia1100
//  Data........: 18.08.14
//  Version.....: 1.0 
//***************************************************************************
//  Notice: Все управляющие контакты LCD-контроллера должны быть подключены к
//  одному и тому же порту на микроконтроллере
//***************************************************************************
// изменено для квар column_ptr[i] = pgm_read_byte(&(S_box[ column_ptr[i] ]));->column_ptr[i]=S_box[column_ptr[i]]; 
#include <nokia_lcd.h>
#include <nokia_lcd_fnt.h>    // Подключаем шрифт (будет размещен в программной памяти)
//#include <delay.h>
//******************************************************************************
// Инициализация контроллера
void nlcd_Init(void)
{    
    // Инициализируем порт на вывод для работы с LCD-контроллером
    DDR_LCD |= (1<<SCLK_LCD_PIN)|(1<<SDA_LCD_PIN)|(1<<CS_LCD_PIN)|(1<<RST_LCD_PIN);

    CS_LCD_RESET;
    RST_LCD_RESET;

    delay_ms(10);            // выжидем не менее 5мс для установки генератора(менее 5 мс может неработать)

    RST_LCD_SET;

    nlcd_SendByte(CMD_LCD_MODE,0x20); // Запись в регистр Vop 
    nlcd_SendByte(CMD_LCD_MODE,0x90);
    nlcd_SendByte(CMD_LCD_MODE,0xA4); // all on/normal display
    nlcd_SendByte(CMD_LCD_MODE,0x2F); // Power control set(charge pump on/off)
    nlcd_SendByte(CMD_LCD_MODE,0x40); // set start row address = 0
    nlcd_SendByte(CMD_LCD_MODE,0xB0); // установить Y-адрес = 0
    nlcd_SendByte(CMD_LCD_MODE,0x10); // установить X-адрес, старшие 3 бита
    nlcd_SendByte(CMD_LCD_MODE,0x0);  // установить X-адрес, младшие 4 бита
    nlcd_SendByte(CMD_LCD_MODE,0xC8); // mirror Y axis (about X axis)
    nlcd_SendByte(CMD_LCD_MODE,0xA1); // Инвертировать экран по горизонтали
    nlcd_SendByte(CMD_LCD_MODE,0xAC); // set initial row (R0) of the display
    nlcd_SendByte(CMD_LCD_MODE,0x07);
    //nlcd_SendByte(CMD_LCD_MODE,0xF9); //
    nlcd_SendByte(CMD_LCD_MODE,0xAF); // экран вкл/выкл

    nlcd_Clear(); // clear LCD

    nlcd_SendByte(CMD_LCD_MODE,0xA7);     // инвертированный экран
    delay_ms(300);//было по умолчанию (500) изменил для протеуса-долго и тормоз// 1/2 Sec delay
    nlcd_SendByte(CMD_LCD_MODE,0xA6);     // нормальный экран (не инвертированный)
    delay_ms(100);//(1000)-тоже самое здесь для протеуса                       // 1 Sec delay
}

//******************************************************************************
// Очистка экрана
void nlcd_Clear(void)
{
    int i=0;
    nlcd_SendByte(CMD_LCD_MODE,0x40); // Y = 0
    nlcd_SendByte(CMD_LCD_MODE,0xB0);
    nlcd_SendByte(CMD_LCD_MODE,0x10); // X = 0
    nlcd_SendByte(CMD_LCD_MODE,0x00);
    //nlcd_SendByte(CMD_LCD_MODE,0xAE); // disable display;
    
    for (i=0;i<864;i++) {nlcd_SendByte(DATA_LCD_MODE,0x00);};
    
    //nlcd_SendByte(CMD_LCD_MODE,0x07);
    //nlcd_SendByte(CMD_LCD_MODE,0xAF); // enable display;
}


//******************************************************************************
// Передача байта (команды или данных) на LCD-контроллер
//  mode: CMD_LCD_MODE - передаем команду
//          DATA_LCD_MODE - передаем данные
//  c: значение передаваемого байта
void nlcd_SendByte(char mode,unsigned char c)
{   unsigned char i=0;
    CS_LCD_RESET;
    SCLK_LCD_RESET;
   
    if(mode) SDA_LCD_SET;
     else     SDA_LCD_RESET;
    
    SCLK_LCD_SET;

    for(i=0;i<8;i++)
    {
        SCLK_LCD_RESET;

        if(c & 0x80) SDA_LCD_SET;
         else         SDA_LCD_RESET;

        SCLK_LCD_SET;
        c <<= 1;
        delay_ms(3);
     }

    CS_LCD_SET;
}

//******************************************************************************
// Вывод символа на LCD-контроллер в текущее место
//  c: код символа
void nlcd_Putc(unsigned char c)
{   unsigned char i = 0;
    for ( i = 0; i < 5; i++ )
    {
        nlcd_SendByte(DATA_LCD_MODE,nlcd_Font[c-32][i]);
    }
    
    nlcd_SendByte(DATA_LCD_MODE,0x00); // Зазор между символами по горизонтали в 1 пиксель
}

//******************************************************************************
// Вывод строки символов на LCD-контроллер в текущее место. Если строка выходит
// за экран в текущей строке, то остаток переносится на следующую строку.
//  message: указатель на строку символов. 0x00 - признак конца строки.
void nlcd_Print(char * message)
{
    while (*message) // Конец строки обозначен нулем
    { 
        nlcd_Putc(*message++);
    }
}

//******************************************************************************
// Вывод строки символов на LCD-контроллер в текущее место из программной памяти.
// Если строка выходит за экран в текущей строке, то остаток переносится на следующую строку.
//  message: указатель на строку символов в программной памяти. 0x00 - признак конца строки.
void nlcd_PrintF(unsigned flash char * message)
{
    unsigned char data;
    data=*message;
    while (data)
    { 
        nlcd_Putc(data);
        message++;
        data=*message;
    }
}


//******************************************************************************
// Устанавливает курсор в необходимое положение. Отсчет начинается в верхнем 
// левом углу. По горизонтали 16 знакомест, по вертикали - 8
//  x: 0..15
//  y: 0..7    
void nlcd_GotoXY(char x,char y)
{
    x=x*6;    // Переходим от координаты в пикселях к координатам в знакоместах
    nlcd_SendByte(CMD_LCD_MODE,(0xB0|(y&0x0F)));      // установка адреса по Y: 0100 yyyy         
    nlcd_SendByte(CMD_LCD_MODE,(0x00|(x&0x0F)));      // установка адреса по X: 0000 xxxx - биты (x3 x2 x1 x0)
    nlcd_SendByte(CMD_LCD_MODE,(0x10|((x>>4)&0x07))); // установка адреса по X: 0010 0xxx - биты (x6 x5 x4)

}

//******************************************************************************
// Устанавливаер режим инверсии всего экрана. Данные на экране не изменяются, только инвертируются
//  mode: INV_MODE_ON или INV_MODE_OFF
void nlcd_Inverse(unsigned char mode)
{
    if (mode) nlcd_SendByte(CMD_LCD_MODE,0xA6);
     else nlcd_SendByte(CMD_LCD_MODE,0xA7);
}

