00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #ifdef __GNUC__
00081
00082 #include <stdlib.h>
00083 #include <string.h>
00084 #include <stdio.h>
00085
00086 #include <sys/nutconfig.h>
00087 #include <dev/hd44780_bus.h>
00088 #include <dev/term.h>
00089 #include <sys/timer.h>
00090
00091 static u_short lcd_base = 0x0000;
00092
00093 #ifndef LCD_4x20
00094 #ifndef LCD_4x16
00095 #ifndef LCD_2x40
00096 #ifndef LCD_2x20
00097 #ifndef LCD_2x16
00098 #ifndef LCD_2x8
00099 #ifndef LCD_1x20
00100 #ifndef LCD_1x16
00101 #ifndef LCD_1x8
00102 #ifndef KS0073_CONTROLLER
00103 #define LCD_2x16
00104 #endif
00105 #endif
00106 #endif
00107 #endif
00108 #endif
00109 #endif
00110 #endif
00111 #endif
00112 #endif
00113 #endif
00114
00115 #define LCD_DELAY asm volatile ("nop"); asm volatile ("nop")
00116
00117
00122
00128 static inline void LcdBusyWait(void)
00129 {
00130 #ifndef MMNET02
00131
00132
00133 while (*(volatile u_char *) (LCD_CTRL_ADDR + LCD_READ_OFFSET) & 1 << LCD_BUSY)
00134 LCD_DELAY;
00135 LCD_DELAY;
00136 LCD_DELAY;
00137 LCD_DELAY;
00138 LCD_DELAY;
00139 LCD_DELAY;
00140 LCD_DELAY;
00141 LCD_DELAY;
00142 LCD_DELAY;
00143 LCD_DELAY;
00144 LCD_DELAY;
00145 LCD_DELAY;
00146 LCD_DELAY;
00147 #else
00148
00149 NutDelay(5);
00150 #endif
00151 }
00152
00159 static void LcdWriteData(u_char data)
00160 {
00161 LcdBusyWait();
00162 *(volatile u_char *) (LCD_DATA_ADDR) = data;
00163 }
00164
00168 static void LcdWriteCmd(u_char cmd, u_char delay)
00169 {
00170 LcdBusyWait();
00171 *(volatile u_char *) (LCD_CTRL_ADDR) = cmd;
00172 }
00173
00174 static void LcdSetCursor(u_char pos)
00175 {
00176 u_char x = 0;
00177 u_char y = 0;
00178
00179 #ifdef KS0073_CONTROLLER
00180 u_char offset[4] = {0x00, 0x20, 0x40, 0x60};
00181 y = pos / 20;
00182 x = pos % 20;
00183 if (y > 3) y = 3;
00184 #endif
00185
00186 #if defined(LCD_2x40)
00187 u_char offset [2] = {0x00, 0x40};
00188 y = pos / 40;
00189 x = pos % 40;
00190 if (y > 1) y = 1;
00191 #endif
00192
00193 #if defined(LCD_4x20) || defined(LCD_2x20)
00194 u_char offset [4] = {0x00, 0x40, 0x14, 0x54};
00195 y = pos / 20;
00196 x = pos % 20;
00197 if (y>3) y=3;
00198 #endif
00199
00200 #if defined(LCD_4x16) || defined(LCD_2x16)
00201 u_char offset [4] = {0x00, 0x40, 0x10, 0x50};
00202 y = pos / 16;
00203 x = pos % 16;
00204 if (y>3) y=3;
00205 #endif
00206
00207 #if defined(LCD_2x8)
00208 u_char offset [2] = {0x00, 0x40};
00209 y = pos / 8;
00210 x = pos % 8;
00211 if (y>1) y=1;
00212 #endif
00213
00214 #if defined(LCD_1x8) || defined(LCD_1x16) || defined(LCD_1x20)
00215 u_char offset [1] = { 0x00 };
00216 y = 0;
00217 x = pos;
00218 #endif
00219
00220 pos = x + offset[y];
00221 LcdWriteCmd(1 << LCD_DDRAM | pos, 0);
00222 }
00223
00224 static void LcdCursorHome(void)
00225 {
00226 LcdWriteCmd(1 << LCD_HOME, 0);
00227 }
00228
00229 static void LcdCursorLeft(void)
00230 {
00231 LcdWriteCmd(1 << LCD_MOVE, 0);
00232 }
00233
00234 static void LcdCursorRight(void)
00235 {
00236 LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT, 0);
00237 }
00238
00239 static void LcdClear(void)
00240 {
00241 LcdWriteCmd(1 << LCD_CLR, 0);
00242 }
00243
00244 static void LcdCursorMode(u_char on)
00245 {
00246 LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00, 0);
00247 }
00248
00253 static void LcdInit(NUTDEVICE * dev)
00254 {
00255 lcd_base = dev->dev_base;
00256 #ifdef KS0073_CONTROLLER
00257
00258 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00259 NutDelay(50);
00260 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00261 NutDelay(50);
00262 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00263 NutDelay(50);
00264
00265 LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), 0);
00266 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT, 0);
00267
00268 #else
00269
00270
00271
00272 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00273 NutDelay(50);
00274 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00275 NutDelay(50);
00276 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00277 NutDelay(50);
00278 #endif
00279
00280 LcdWriteCmd(1 << LCD_CLR, 0);
00281
00282 LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, 0);
00283
00284 LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, 0);
00285
00286 LcdWriteCmd(1 << LCD_HOME, 0);
00287
00288 LcdWriteCmd(1 << LCD_DDRAM | 0x00, 0);
00289 }
00290
00294 TERMDCB dcb_term = {
00295 LcdInit,
00296 LcdWriteData,
00297 LcdWriteCmd,
00298 LcdClear,
00299 LcdSetCursor,
00300 LcdCursorHome,
00301 LcdCursorLeft,
00302 LcdCursorRight,
00303 LcdCursorMode,
00304 0,
00305 0,
00306 #ifdef KS0073_CONTROLLER
00307 4,
00308 20,
00309 20,
00310 #endif
00311 #ifdef LCD_4x20
00312 4,
00313 20,
00314 20,
00315 #endif
00316 #ifdef LCD_4x16
00317 4,
00318 16,
00319 16,
00320 #endif
00321 #ifdef LCD_2x40
00322 2,
00323 40,
00324 40,
00325 #endif
00326 #ifdef LCD_2x20
00327 2,
00328 20,
00329 20,
00330 #endif
00331 #ifdef LCD_2x16
00332 2,
00333 16,
00334 16,
00335 #endif
00336 #ifdef LCD_2x8
00337 2,
00338 8,
00339 8,
00340 #endif
00341 #ifdef LCD_1x20
00342 1,
00343 20,
00344 20,
00345 #endif
00346 #ifdef LCD_1x16
00347 1,
00348 16,
00349 16,
00350 #endif
00351 #ifdef LCD_1x8
00352 1,
00353 8,
00354 8,
00355 #endif
00356 0,
00357 0,
00358 0
00359 };
00360
00364 NUTDEVICE devLcdBus = {
00365 0,
00366 {'l', 'c', 'd', 'b', 'u', 's', 0, 0, 0},
00367 IFTYP_STREAM,
00368 0,
00369 0,
00370 0,
00371 &dcb_term,
00372 TermInit,
00373 TermIOCtl,
00374 0,
00375 TermWrite,
00376 TermWrite_P,
00377 TermOpen,
00378 TermClose,
00379 0
00380 };
00381
00382
00383 #else
00384 void keep_icc_happy(void)
00385 {
00386 }
00387
00388 #endif
00389