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
00081
00082
00083
00084
00085
00086
00087
00088
00089 #ifdef __GNUC__
00090
00091 #include <stdlib.h>
00092 #include <string.h>
00093 #include <stdio.h>
00094
00095 #include <sys/nutconfig.h>
00096 #include <dev/hd44780_bus.h>
00097 #include <dev/term.h>
00098 #include <sys/timer.h>
00099
00100 static uint16_t lcd_base = 0x0000;
00101
00102 #ifndef LCD_4x20
00103 #ifndef LCD_4x16
00104 #ifndef LCD_2x40
00105 #ifndef LCD_2x20
00106 #ifndef LCD_2x16
00107 #ifndef LCD_2x8
00108 #ifndef LCD_1x20
00109 #ifndef LCD_1x16
00110 #ifndef LCD_1x8
00111 #ifndef KS0073_CONTROLLER
00112 #define LCD_2x16
00113 #endif
00114 #endif
00115 #endif
00116 #endif
00117 #endif
00118 #endif
00119 #endif
00120 #endif
00121 #endif
00122 #endif
00123
00124 #define LCD_DELAY asm volatile ("nop"); asm volatile ("nop")
00125
00126
00131
00137 static inline void LcdBusyWait(void)
00138 {
00139 #if !defined(MMNET02) && !defined(MMNET03) && !defined(MMNET04) && \
00140 !defined(MMNET102) && !defined(MMNET103) && !defined(MMNET104)
00141
00142
00143 while (*(volatile uint8_t *) (LCD_CTRL_ADDR + LCD_READ_OFFSET) & 1 << LCD_BUSY)
00144 LCD_DELAY;
00145 LCD_DELAY;
00146 LCD_DELAY;
00147 LCD_DELAY;
00148 LCD_DELAY;
00149 LCD_DELAY;
00150 LCD_DELAY;
00151 LCD_DELAY;
00152 LCD_DELAY;
00153 LCD_DELAY;
00154 LCD_DELAY;
00155 LCD_DELAY;
00156 LCD_DELAY;
00157 #else
00158
00159 NutDelay(5);
00160 #endif
00161 }
00162
00169 static void LcdWriteData(uint8_t data)
00170 {
00171 LcdBusyWait();
00172 *(volatile uint8_t *) (LCD_DATA_ADDR) = data;
00173 }
00174
00178 static void LcdWriteCmd(uint8_t cmd, uint8_t delay)
00179 {
00180 LcdBusyWait();
00181 *(volatile uint8_t *) (LCD_CTRL_ADDR) = cmd;
00182 }
00183
00184 static void LcdSetCursor(uint8_t pos)
00185 {
00186 uint8_t x = 0;
00187 uint8_t y = 0;
00188
00189 #ifdef KS0073_CONTROLLER
00190 uint8_t offset[4] = {0x00, 0x20, 0x40, 0x60};
00191 y = pos / 20;
00192 x = pos % 20;
00193 if (y > 3) y = 3;
00194 #endif
00195
00196 #if defined(LCD_2x40)
00197 uint8_t offset [2] = {0x00, 0x40};
00198 y = pos / 40;
00199 x = pos % 40;
00200 if (y > 1) y = 1;
00201 #endif
00202
00203 #if defined(LCD_4x20) || defined(LCD_2x20)
00204 uint8_t offset [4] = {0x00, 0x40, 0x14, 0x54};
00205 y = pos / 20;
00206 x = pos % 20;
00207 if (y>3) y=3;
00208 #endif
00209
00210 #if defined(LCD_4x16) || defined(LCD_2x16)
00211 uint8_t offset [4] = {0x00, 0x40, 0x10, 0x50};
00212 y = pos / 16;
00213 x = pos % 16;
00214 if (y>3) y=3;
00215 #endif
00216
00217 #if defined(LCD_2x8)
00218 uint8_t offset [2] = {0x00, 0x40};
00219 y = pos / 8;
00220 x = pos % 8;
00221 if (y>1) y=1;
00222 #endif
00223
00224 #if defined(LCD_1x8) || defined(LCD_1x16) || defined(LCD_1x20)
00225 uint8_t offset [1] = { 0x00 };
00226 y = 0;
00227 x = pos;
00228 #endif
00229
00230 pos = x + offset[y];
00231 LcdWriteCmd(1 << LCD_DDRAM | pos, 0);
00232 }
00233
00234 static void LcdCursorHome(void)
00235 {
00236 LcdWriteCmd(1 << LCD_HOME, 0);
00237 }
00238
00239 static void LcdCursorLeft(void)
00240 {
00241 LcdWriteCmd(1 << LCD_MOVE, 0);
00242 }
00243
00244 static void LcdCursorRight(void)
00245 {
00246 LcdWriteCmd(1 << LCD_MOVE | 1 << LCD_MOVE_RIGHT, 0);
00247 }
00248
00249 static void LcdClear(void)
00250 {
00251 LcdWriteCmd(1 << LCD_CLR, 0);
00252 }
00253
00254 static void LcdCursorMode(uint8_t on)
00255 {
00256 LcdWriteCmd(1 << LCD_ON_CTRL | on ? 1 << LCD_ON_CURSOR : 0x00, 0);
00257 }
00258
00263 static int LcdInit(NUTDEVICE * dev)
00264 {
00265 lcd_base = dev->dev_base;
00266 #ifdef KS0073_CONTROLLER
00267
00268 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00269 NutDelay(50);
00270 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00271 NutDelay(50);
00272 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_RE), 0);
00273 NutDelay(50);
00274
00275 LcdWriteCmd((1 << LCD_EXT) | ((((TERMDCB *) dev->dev_dcb)->dcb_nrows > 2) ? (1 << LCD_EXT_4LINES) : 0), 0);
00276 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT, 0);
00277
00278 #else
00279
00280
00281
00282 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00283 NutDelay(50);
00284 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00285 NutDelay(50);
00286 LcdWriteCmd((1 << LCD_FUNCTION) | 1 << LCD_FUNCTION_8BIT | (1 << LCD_FUNCTION_2LINES), 0);
00287 NutDelay(50);
00288 #endif
00289
00290 LcdWriteCmd(1 << LCD_CLR, 0);
00291
00292 LcdWriteCmd(1 << LCD_ENTRY_MODE | 1 << LCD_ENTRY_INC, 0);
00293
00294 LcdWriteCmd(1 << LCD_ON_CTRL | 1 << LCD_ON_DISPLAY, 0);
00295
00296 LcdWriteCmd(1 << LCD_HOME, 0);
00297
00298 LcdWriteCmd(1 << LCD_DDRAM | 0x00, 0);
00299
00300 return 0;
00301 }
00302
00306 TERMDCB dcb_term = {
00307 LcdInit,
00308 LcdWriteData,
00309 LcdWriteCmd,
00310 LcdClear,
00311 LcdSetCursor,
00312 LcdCursorHome,
00313 LcdCursorLeft,
00314 LcdCursorRight,
00315 LcdCursorMode,
00316 0,
00317 0,
00318 #ifdef KS0073_CONTROLLER
00319 4,
00320 20,
00321 20,
00322 #endif
00323 #ifdef LCD_4x20
00324 4,
00325 20,
00326 20,
00327 #endif
00328 #ifdef LCD_4x16
00329 4,
00330 16,
00331 16,
00332 #endif
00333 #ifdef LCD_2x40
00334 2,
00335 40,
00336 40,
00337 #endif
00338 #ifdef LCD_2x20
00339 2,
00340 20,
00341 20,
00342 #endif
00343 #ifdef LCD_2x16
00344 2,
00345 16,
00346 16,
00347 #endif
00348 #ifdef LCD_2x8
00349 2,
00350 8,
00351 8,
00352 #endif
00353 #ifdef LCD_1x20
00354 1,
00355 20,
00356 20,
00357 #endif
00358 #ifdef LCD_1x16
00359 1,
00360 16,
00361 16,
00362 #endif
00363 #ifdef LCD_1x8
00364 1,
00365 8,
00366 8,
00367 #endif
00368 0,
00369 0,
00370 0
00371 };
00372
00376 NUTDEVICE devLcdBus = {
00377 0,
00378 {'l', 'c', 'd', 'b', 'u', 's', 0, 0, 0},
00379 IFTYP_STREAM,
00380 0,
00381 0,
00382 0,
00383 &dcb_term,
00384 TermInit,
00385 TermIOCtl,
00386 0,
00387 TermWrite,
00388 TermWrite_P,
00389 TermOpen,
00390 TermClose,
00391 0
00392 };
00393
00394
00395 #else
00396 void keep_icc_happy(void)
00397 {
00398 }
00399
00400 #endif
00401