00001 /* 00002 * Filename: lcd.h 00003 * Version: 0.2.2 00004 * Description: HD44780 Display Library for ATMEL AVR 00005 * License: Public Domain 00006 * 00007 * Author: Copyright (C) Max Gaukler <development@maxgaukler.de> 00008 * Date: 2010 00009 * 00010 * I, the copyright holder of this work, hereby release it into the public domain. This applies worldwide. 00011 * In case this is not legally possible: 00012 * I grant anyone the right to use this work for any purpose, without any conditions, unless such conditions are required by law. 00013 * 00014 */ 00015 // Until a good way is found, you have to include lcd.c, not lcd.h 00016 #include <avr/pgmspace.h> 00017 #include <avr/io.h> 00018 #include <util/delay.h> 00019 00020 #ifndef _LCD_H_INCLUDED 00021 #define _LCD_H_INCLUDED 00022 00023 // IO Helper macros 00024 #ifndef cbi 00025 #define cbi(sfr, bit) (sfr &= ~_BV(bit)) 00026 #endif 00027 00028 #ifndef sbi 00029 #define sbi(sfr, bit) (sfr |= _BV(bit)) 00030 #endif 00031 00032 00033 /** \mainpage HD44780 Display Library for Atmel AVR Microcontrollers 00034 00035 \section including-into-prog Including the library into your program 00036 00037 Just include the file lcd.c (not .h!) into your main program. 00038 @code #include "./lcd/lcd.c" @endcode 00039 00040 \section features Features 00041 00042 As long as the interrupt does not change the port that the display is connected to, the library should be interrupt-safe. 00043 00044 \section interfacing Interfacing the Display to the Microcontroller 00045 \subsection direct_4bit Direct Interfacing in 4-bit mode 00046 00047 In 4-bit mode, 6 IO pins are needed. Data lines D4-D7, E and RS are connected to the microcontroller. RW can be directly connected to ground. If you already connected RW to the microcontroller, define LCD_RW_PIN and it will automatically be set to low. D0-D3 can be left unconnected. 4-bit-mode needs only about 1 microsecond longer per command than 8-bit-mode, but 8-bit-mode needs four more IO pins. 00048 00049 This mode is selected by defining LCD_MODE_4BIT. LCD_PORT, LCD_DDR, LCD_EN_PIN, LCD_RS_PIN and LCD_D4_PIN need to be defined. D4,D5,D6,D7 are connected to LCD_D4_PIN, LCD_D4_PIN+1, and so on. 00050 00051 Example: 00052 @code 00053 #define LCD_MODE_4BIT 00054 #define LCD_PORT PORTA 00055 #define LCD_DDR DDRA 00056 #define LCD_EN_PIN PA4 00057 #define LCD_RS_PIN PA5 00058 // D4 -> PA0, D5 -> PA1, D6 -> PA2, D7 -> PA3 00059 #define LCD_D4_PIN PA0 00060 // optional: 00061 #define LCD_RW_PIN PA6 00062 @endcode 00063 00064 \subsection shiftregister_4bit Shift Register in 4-bit-mode 00065 00066 Only three IO pins are needed for shift register mode. These are connected to a shift register (74(V)HC(T)595 or similar, 8 bit, serial input, parallel output with latch). 00067 00068 This mode is selected by defining LCD_MODE_SHIFT_4BIT. LCD_SHIFT_PORT, LCD_SHIFT_DDR, LCD_SHIFT_DATA_PIN, LCD_SHIFT_CLOCK_PIN, LCD_SHIFT_LATCH_PIN define the connections to the shift register. For 595-style shift registers, clock is SCK (shift clock), latch is RCK (register clock) and data is D. Set LCD_EN_PIN, LCD_RS_PIN and LCD_D4_PIN to the pin numbers at the shift register. D4, D5, D6 and D7 of the LCD are connected to output LCD_D4_PIN, LCD_D4_pin+1, and so on. 00069 00070 \section display_conf Display Size Configuration 00071 00072 The display size is set with LCD_COLS and LCD_LINES. For most displays, this is the real value of columns and lines. Usually each line can be a maximum of 40 characters wide, a display may be a maximum of 4 lines high. Displays with more than two lines or non-standard displays require special configuration, which is described in the next sections. 00073 00074 \subsection one_ctrl_more_lines One-Controller Displays with "half" lines 00075 00076 Some displays behave as if they were twice as wide and half as high. They just display every long internal line as two lines. For such displays, use the real value for columns and lines, and define LCD_HALF_LINES. In this mode a display may be up to 8 lines high, but only up to 20 characters wide. 00077 00078 The only difference between using this mode and setting double width and half height is that lcd_set_line works correctly. 00079 00080 \subsection one_ctrl_four_lines Displays with special memory layout 00081 00082 Some displays have a memory layout that doesn't follow the default of line 1 = 0x00, line 2 = 0x40. A different memory layout can be used by defining LCD_SPECIAL_LINE_LAYOUT and LCD_LINE1_ADDR to LCD_LINE4_ADDR. The typical layout for 4x16 character displays with only one controller is 0x00, 0x40, 0x10, 0x50. If you configured such a display as 2x32 characters (or 4x16 with LCD_HALF_LINES), the second and third line would be swapped. 00083 00084 Example: 00085 @code 00086 #define LCD_SPECIAL_LINE_LAYOUT 00087 #define LCD_LINE1_ADDR 0x00 00088 #define LCD_LINE2_ADDR 0x40 00089 #define LCD_LINE3_ADDR 0x10 00090 #define LCD_LINE4_ADDR 0x50 00091 @endcode 00092 00093 \subsection two_ctrl_display Two-Controller Displays with four lines 00094 00095 If a display has two controllers, it has two separate EN pins. You need to define the EN2 pin number with LCD_EN2_PIN. Such a display has to be configured for at least two lines. If you really have a one-line display that is more than 80 characters wide, configure it as two lines high and twice as wide. 00096 00097 @code 00098 #define LCD_TWO_CONTROLLERS 00099 @endcode 00100 00101 */ 00102 00103 00104 /** \defgroup raw_commands Raw Commands sent to the controller 00105 00106 These constants are used when communicating directly with the controller with lcd_command(). The bit names in the description refer to the Hitachi HD44780U datasheet. Usually calling these commands from your code should not be necessary. If you use them, be careful that the LCD position should always match the internal variable lcd_position. If the position was moved, call lcd_set_position() to go to your new position, lcd_home(), go back to the old position with @code lcd_set_position(lcd_position);@endcode, or set @code lcd_position=your_new_known_position;@endcode (faster, does not send command to the LCD) 00107 */ 00108 00109 /*@{*/ 00110 /// Clear: clear display and go to position 0 00111 #define LCD_CLEAR 0x01 00112 00113 /// Home: go to position 0 00114 #define LCD_HOME 0x02 00115 00116 /// <b>Entry Mode</b>: set cursor and display movement 00117 #define LCD_ENTRYMODE 0x04 00118 /// Option: I/D=1: auto-increment (left-to-right) of character position 00119 #define LCD_ENTRYMODE_INCREMENT 0x02 00120 /// Option: I/D=0: auto-decrement (right-to-left) 00121 /// right-to-left is not really supported by this library yet, its internal position will not match the LCD position in this setting, it may cause trouble 00122 #define LCD_ENTRYMODE_DECREMENT 0x00 00123 00124 /// Option: S: shift: the cursor does not move, but the display does 00125 /// This is currently unsupported, automatic linebreak may do wrong things 00126 /// The shifting does not work across line borders 00127 #define LCD_ENTRYMODE_SHIFT 0x01 00128 00129 /// <b>Display On/Off Control</b> - used by lcd_set_cursor() 00130 #define LCD_CONTROL 0x08 00131 /// Option: D=1: display on 00132 #define LCD_CONTROL_DISPLAY_ON 0x04 00133 /// Option: D=0: display off (clear) 00134 #define LCD_CONTROL_DISPLAY_OFF 0x00 00135 /// Option: C=1: display cursor 00136 #define LCD_CONTROL_CURSOR_ON 0x02 00137 /// Option: C=0: no cursor 00138 #define LCD_CONTROL_CURSOR_OFF 0x00 00139 /// Option: B=1: blink current character 00140 #define LCD_CONTROL_BLINK 0x01 00141 00142 /// <b>Cursor (or Display) shift</b>: move cursor or display content - please call lcd_set_position() after moving the cursor with this command, not really supported 00143 #define LCD_SHIFT 0x10 00144 /// Option: S/C=1: move cursor position 00145 #define LCD_SHIFT_DISPLAY 0x08 00146 /// Option: S/C=0: move display content, cursor stays at the same position (not really supported) 00147 #define LCD_SHIFT_CURSOR 0x00 00148 /// Option: R/L=1: right 00149 #define LCD_SHIFT_RIGHT 0x04 00150 /// Option: R/L=0: left 00151 #define LCD_SHIFT_LEFT 0x00 00152 00153 /// <b>Function Set</b>: Initialize the Controllers - used by lcd_init() 00154 #define LCD_FUNCTION 0x20 00155 /// Option: DL=1: interface data length 8bit 00156 #define LCD_FUNCTION_8BIT 0x10 00157 /// Option: DL=0: interface data length 4bit 00158 #define LCD_FUNCTION_4BIT 0x00 00159 /// Option: N=1: two display lines (per controller) 00160 #define LCD_FUNCTION_2LINES 0x08 00161 /// Option: N=0: one display line (per controller) 00162 #define LCD_FUNCTION_1LINE 0x00 00163 /// Option: F=1: character font 00164 #define LCD_FUNCTION_5x10 0x04 00165 /// Option: F=0: character font 00166 #define LCD_FUNCTION_5x8 0x00 00167 00168 /// <b>Set Character Generator RAM Address</b> 00169 #define LCD_SET_CGRAM_ADDR 0x40 00170 00171 /// <b>Set Display Data RAM Address</b> (LCD Position) - used by lcd_set_position(), lcd_set_line() 00172 #define LCD_SET_DDRAM_ADDR 0x80 00173 /*@}*/ 00174 00175 00176 00177 #define LCD_ALL_CONTROLLERS 255 00178 00179 00180 #if defined(LCD_MODE_4BIT) && ( !defined(LCD_PORT) || !defined(LCD_DDR) || !defined(LCD_EN_PIN) || !defined(LCD_RS_PIN) || !defined(LCD_D4_PIN) || !defined(LCD_LINES) || !defined(LCD_COLS)) 00181 #error for LCD_MODE_4BIT the constants LCD_PORT, LCD_DDR, LCD_EN_PIN, LCD_RS_PIN, LCD_D4_PIN, LCD_LINES, LCD_COLS need to be defined 00182 #endif 00183 00184 #if defined(LCD_MODE_SHIFT_4BIT) && ( !defined(LCD_SHIFT_PORT) || !defined(LCD_SHIFT_DDR) || !defined(LCD_SHIFT_DATA_PIN) || !defined(LCD_SHIFT_CLOCK_PIN) || !defined(LCD_SHIFT_LATCH_PIN) || !defined(LCD_EN_PIN) || !defined(LCD_RS_PIN) || !defined(LCD_D4_PIN) || !defined(LCD_LINES) || !defined(LCD_COLS)) 00185 #error for LCD_MODE_4BIT the constants LCD_SHIFT_PORT, LCD_SHIFT_DDR, LCD_SHIFT_DATA_PIN, LCD_SHIFT_CLOCK_PIN, LCD_SHIFT_LATCH_PIN, LCD_EN_PIN, LCD_RS_PIN, LCD_D4_PIN, LCD_LINES, LCD_COLS need to be defined 00186 #endif 00187 00188 #if !defined(LCD_MODE_4BIT) && !defined(LCD_MODE_8BIT) && !defined(LCD_MODE_SHIFT_4BIT) 00189 #error please define LCD interface mode (currently only LCD_MODE_4BIT and LCD_MODE_SHIFT_4BIT is supported) 00190 #endif 00191 // TODO: planned: 8bit, 8bit with two shift registers soft-spi (3 pins) 00192 00193 00194 #if (LCD_LINES>2) && !defined(LCD_TWO_CONTROLLERS) && !defined(LCD_SPECIAL_LINE_LAYOUT) 00195 #error LCDs with more than two lines usually need two controllers. If there is a second LCD_EN pin, define LCD_TWO_CONTROLLERS and LCD_EN2_PIN. If there is no second LCD_EN_PIN, try using double LCD_COLS and half LCD_LINES. Otherwise, try defining a memory layout with LCD_SPECIAL_LINE_LAYOUT. (see documentation) 00196 #endif 00197 00198 #if defined(LCD_SPECIAL_LINE_LAYOUT) && ( !defined(LCD_LINE1_ADDR) || !defined(LCD_LINE2_ADDR) || !defined(LCD_LINE3_ADDR) || !defined(LCD_LINE4_ADDR) ) 00199 #error For LCD_SPECIAL_LINE_LAYOUT you need to define LCD_LINE1_ADDR, LCD_LINE2_ADDR, LCD_LINE3_ADDR and LCD_LINE4_ADDR. If you have less than four lines, simply define the unneeded constans as 0. 00200 #endif 00201 00202 #if defined(LCD_SPECIAL_LINE_LAYOUT) && ( (!defined(LCD_HALF_LINES) && (LCD_LINES>4)) || (defined(LCD_HALF_LINES) && (LCD_LINES>8))) 00203 #error LCD_SPECIAL_LINE_LAYOUT only works for up to 4 lines (or up to 8 "half" lines with LCD_HALF_LINES) 00204 #endif 00205 00206 #if (LCD_LINES*LCD_COLS>80) && !defined(LCD_TWO_CONTROLLERS) 00207 #error There can be maximum 80 characters per controller, you should define LCD_TWO_CONTROLLERS and LCD_EN2_PIN. 00208 #endif 00209 00210 #if defined(LCD_TWO_CONTROLLERS) && !defined(LCD_EN2_PIN) 00211 #error For LCD_TWO_CONTROLLERS you need LCD_EN2_PIN 00212 #endif 00213 00214 00215 #if defined(LCD_MODE_4BIT) || defined(LCD_MODE_8BIT) 00216 #define LCD_OUT LCD_PORT 00217 #else 00218 // buffer for shift-register output 00219 uint8_t lcd_out_buf=0; 00220 #define LCD_OUT lcd_out_buf 00221 #endif 00222 00223 // Prototypes created with cat lcd.c | sed -n "s/^\([a-z].*(.*)\)[ \\t]*[\{][^;]*\$/\1;/p" 00224 inline void LCD_DATA_OUT(uint8_t data); 00225 inline void LCD_RS(uint8_t rs); 00226 inline void LCD_EN(uint8_t en); 00227 void LCD_OUT_UPDATE(void); 00228 void lcd_command(uint8_t data); 00229 void lcd_data(uint8_t data); 00230 void lcd_write(uint8_t data, uint8_t rs); 00231 void lcd_nibble(uint8_t data); 00232 void lcd_init(void); 00233 void lcd_home(void); 00234 void lcd_set_controller(uint8_t num); 00235 void lcd_clear(void); 00236 void lcd_set_line(uint8_t x); 00237 void lcd_set_position(uint8_t position); 00238 void lcd_set_cursor(uint8_t mode); 00239 void lcd_linewrap(void); 00240 void lcd_putchar(char chr); 00241 void lcd_putstr(char *str); 00242 void lcd_putstr_P(PGM_P str); 00243 void lcd_print(char *str); 00244 void lcd_customchar(uint8_t number, uint8_t *data); 00245 void lcd_customchar_P(uint8_t number, PGM_P data); 00246 #endif // _LCD_H_INCLUDED