/**
* @file lcd.c
* @brief LCD HD44780 Module
*
* Support LCD module
*
* @author Rustem Kalimullin
* @par E-mail:
* hellos@mail.ru
*/
#include "common.h"
// HD44780 LCD controller command set (do not modify these)
// writing:
#define LCD_CLR 0 // DB0: clear display
#define LCD_HOME 1 // DB1: return to home position
#define LCD_ENTRY_MODE 2 // DB2: set entry mode
#define LCD_ENTRY_INC 1 // DB1: increment
#define LCD_ENTRY_SHIFT 0 // DB2: shift
#define LCD_ON_CTRL 3 // DB3: turn lcd/cursor on
#define LCD_ON_DISPLAY 2 // DB2: turn display on
#define LCD_ON_CURSOR 1 // DB1: turn cursor on
#define LCD_ON_BLINK 0 // DB0: blinking cursor
#define LCD_MOVE 4 // DB4: move cursor/display
#define LCD_MOVE_DISP 3 // DB3: move display (0-> move cursor)
#define LCD_MOVE_RIGHT 2 // DB2: move right (0-> left)
#define LCD_FUNCTION 5 // DB5: function set
#define LCD_FUNCTION_8BIT 4 // DB4: set 8BIT mode (0->4BIT mode)
#define LCD_FUNCTION_2LINES 3 // DB3: two lines (0->one line)
#define LCD_FUNCTION_10DOTS 2 // DB2: 5x10 font (0->5x7 font)
#define LCD_CGRAM 6 // DB6: set CG RAM address
#define LCD_DDRAM 7 // DB7: set DD RAM address
// reading:
#define LCD_BUSY 7 // DB7: LCD is busy
//---------------------------------------------------------
//! win1251 - LCD translation table
const unsigned char TransTable[] = {
0x41,0xA0,0x42,0xA1,0xE0,0x45,0xAB,0xA4,0xA5,0xA6,0x4B,0xA7,0x4D,0x48,0x4F,0xA8,
0x50,0x43,0x54,0xA9,0xAA,0x58,0xE1,0xAB,0xAC,0xE2,0xAD,0xAE,0x62,0xAF,0xB0,0xB1,
0x61,0xB2,0xB3,0xB4,0xE3,0x65,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0x6F,0xBE,
0x70,0x63,0xBF,0x79,0xE4,0x78,0xE5,0xC0,0xC1,0xE6,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,
};
//---------------------------------------------------------
//! Вывести байт на шину данных
void bus_write_byte( unsigned char x )
{
LED_BUS_OUT = x;
LED_BUS_DIR = 0xFF;
}
//---------------------------------------------------------
//! Задержка
void lcd_delay(unsigned int ms)
{
do {
for (int i=0; i<460;i++) __no_operation();
} while (--ms);
}
//---------------------------------------------------------
void lcd_strobe(void)
{
LCD_ENABLE();
lcd_delay(1);
LCD_DISABLE();
lcd_delay(1);
LED_BUS_OUT = 0xFF;
LED_BUS_DIR = 0xFF;
}
//---------------------------------------------------------
//! Записать байт в регистр команда контроллера ЖКИ
void lcd_command( unsigned char cmd )
{
LCD_RS_COMMAND();
bus_write_byte(cmd);
lcd_strobe();
lcd_delay(1);
}
//---------------------------------------------------------
//! Записать байт в регистр данных контроллера ЖКИ
void lcd_putbyte( unsigned char ch )
{
LCD_RS_DATA();
bus_write_byte(ch);
lcd_strobe();
}
//---------------------------------------------------------
void lcdLoadCustomChars(const unsigned char *data, unsigned int size)
{
for(unsigned int i=0; i<size; i++) {
// set CG RAM address
lcd_command((1<<LCD_CGRAM) | i );
// write character data
lcd_putbyte( data[i] );
}
}
//---------------------------------------------------------
//! Инициализация LCD
void lcd_init (void)
{
lcd_command( (1<<LCD_FUNCTION)|(1<<LCD_FUNCTION_8BIT) );
lcd_delay(30);
lcd_command( (1<<LCD_FUNCTION)|(1<<LCD_FUNCTION_8BIT) );
lcd_delay(30);
lcd_command( (1<<LCD_FUNCTION)|(0<<LCD_FUNCTION_2LINES)|(1<<LCD_FUNCTION_8BIT) );
lcd_delay(30);
// LCD function set
lcd_command( (1<<LCD_FUNCTION)|(1<<LCD_FUNCTION_2LINES)|(1<<LCD_FUNCTION_8BIT) );
// clear LCD
lcd_command(1<<LCD_CLR);
lcd_delay(60);
// set entry mode
lcd_command(1<<LCD_ENTRY_MODE | 1<<LCD_ENTRY_INC);
// set display to on
lcd_command(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY);// | 1<<LCD_ON_CURSOR);
// move cursor to home
lcd_command(1<<LCD_HOME);
// set data address to 0
lcd_command(1<<LCD_DDRAM | 0x00);
// load the first 8 custom characters
//lcdLoadCustomChars((const unsigned char *)&LcdCustomChar[0][0], sizeof(LcdCustomChar) );
}
//---------------------------------------------------------
void lcd_cursor_mode( int mode )
{
if( mode == 2) {
lcd_command(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY | 1<<LCD_ON_BLINK);
} else if (mode == 1) {
lcd_command(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY | 1<<LCD_ON_CURSOR);
} else {
lcd_command(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY);
}
}
//---------------------------------------------------------
//! Вывести символ на экран ЖКИ
void lcd_putchar( unsigned char ch )
{
if (ch > 0xBF) ch = TransTable[(ch-0xC0)];
lcd_putbyte (ch);
}
//---------------------------------------------------------
//! Установить позицию вывода. x - колонка, y - строка
void lcd_gotoxy( int x, int y )
{
if (y & (1<<0)) x += 0x40;
if (y & (1<<1)) x += 20;
x |= (1<<LCD_DDRAM);
lcd_command( x );
}
//---------------------------------------------------------
//! Очистить экран ЖКИ
void lcd_clear( void )
{
lcd_command(1<<LCD_CLR);
}
//---------------------------------------------------------
//! Очистить строку
void lcd_clear_row( int y )
{
lcd_gotoxy(0, y);
for( int x=0; x<LCD_SCR_WIDTH; x++ ) lcd_putbyte(' ');
lcd_gotoxy(0, y);
}
//---------------------------------------------------------
//! Вывести строку
void lcd_puts( const char *s )
{
while( *s ) lcd_putchar( *s++ );
}
//---------------------------------------------------------
//! Вывести строку
void lcd_puts_center( const char *s, int y )
{
int k = LCD_SCR_WIDTH - strlen(s);
if (k <= 0) {
k = 0;
} else {
k >>= 1;
}
lcd_gotoxy( k, y);
lcd_puts(s);
}