/******************************************************************************** KS0066-compatible LCD display driver Copyright (C) 2006 Alexey "Gall" Galakhov This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *********************************************************************************/ #include #include #include #include "bit.h" #include "lcd.h" #include "lcdcmd.h" static const uint8_t LCD_LINE [LCD_NUM_LINES] = { 0x00, #if (LCD_NUM_LINES >= 2) 0x40, #endif #if (LCD_NUM_LINES >= 4) #if (LCD_NUM_CHARS == 16) 0x10, 0x50, #else 0x14, 0x54, #endif #endif }; FILE lcd_fdev = FDEV_SETUP_STREAM (lcd_putchar, NULL, _FDEV_SETUP_WRITE); #define lcd_set_e_high() sbi (LCD_CTRL_PORT, LCD_PIN_E) #define lcd_set_e_low() cbi (LCD_CTRL_PORT, LCD_PIN_E) #define lcd_set_rs_cmd() cbi (LCD_CTRL_PORT, LCD_PIN_RS) #define lcd_set_rs_data() sbi (LCD_CTRL_PORT, LCD_PIN_RS) #define lcd_set_rw_read() sbi (LCD_CTRL_PORT, LCD_PIN_RW) #define lcd_set_rw_write() cbi (LCD_CTRL_PORT, LCD_PIN_RW) #define lcd_set_input() \ { \ LCD_DATA_DDR = 0x00; \ LCD_DATA_PORT = 0xff; \ } #define lcd_set_output() \ { \ LCD_DATA_DDR = 0xff; \ } static void lcd_delay (void) { asm volatile ("nop; nop; nop" ::); } void lcd_init (void) { (void) lcd_fdev; /* Initialize hardware interface */ LCD_CTRL_PORT &= ~(BV (LCD_PIN_RS) | BV (LCD_PIN_RW) | BV (LCD_PIN_E)); #ifdef LCD_PIN_LIGHT sbi (LCD_CTRL_PORT, LCD_PIN_LIGHT); #endif LCD_CTRL_DDR |= (BV (LCD_PIN_RS) | BV (LCD_PIN_RW) #ifdef LCD_PIN_LIGHT | BV (LCD_PIN_LIGHT) #endif | BV (LCD_PIN_E)); /* Do LCD start-up sequence */ lcd_control (LCD_CMD_FUNC | LCD_FUNC_8BIT | LCD_FUNC_2LINE); lcd_control (LCD_CMD_CLS); lcd_control (LCD_CMD_ENTRY | LCD_ENTRY_INCR); /* Turn on display */ lcd_control (LCD_CMD_ONOFF | LCD_ONOFF_ON); lcd_control (LCD_CMD_HOME); lcd_control (LCD_CMD_DDRAM | 0x00); } void lcd_wait (void) { lcd_set_rs_cmd (); lcd_set_input (); lcd_set_rw_read (); lcd_set_e_high (); while (LCD_DATA_PIN & LCD_BUSY) { lcd_set_e_low (); lcd_delay (); lcd_set_e_high (); lcd_delay (); } lcd_set_e_low (); } static void lcd_lowlevel_write (const uint8_t data) { lcd_set_rw_write (); lcd_set_output (); LCD_DATA_PORT = data; lcd_set_e_high (); lcd_delay (); lcd_set_e_low (); lcd_set_input (); } void lcd_control (const uint8_t cmd) { lcd_wait (); lcd_set_rs_cmd (); lcd_lowlevel_write (cmd); } void lcd_putch (const char chr) { lcd_wait (); lcd_set_rs_data (); lcd_lowlevel_write ((uint8_t) chr); } int lcd_putchar (const char chr, FILE* stream) { (void) stream; if ((uint8_t) chr >= 0x20) lcd_putch (chr); return 0; } void lcd_gotoxy (const uint8_t x, const uint8_t y) { if ((y >= LCD_NUM_LINES) || (x >= LCD_NUM_CHARS)) return; lcd_control (LCD_CMD_DDRAM | (LCD_LINE [y] + x)); }