added notes for how to setup android dev environment in Fedora - /athena/notes/androi...
[athena:athena.git] / firmware / ref / archive-code / LCDTest / lcd_16.c
1 \r
2 #include <inttypes.h>\r
3 #include <avr/io.h>\r
4 #include <avr/pgmspace.h>\r
5 #include "lcd_16.h"\r
6 \r
7 /* \r
8 ** constants/macros \r
9 */\r
10 #define DDR(x) (*(&x - 1))      /* address of data direction register of port x */\r
11 #if defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)\r
12     /* on ATmega64/128 PINF is on port 0x00 and not 0x60 */\r
13     #define PIN(x) ( &PORTF==&(x) ? _SFR_IO8(0x00) : (*(&x - 2)) )\r
14 #else\r
15         #define PIN(x) (*(&x - 2))    /* address of input register of port x          */\r
16 #endif\r
17 \r
18 \r
19 #if LCD_IO_MODE\r
20 #define lcd_e_delay()   __asm__ __volatile__( "rjmp 1f\n 1:" );\r
21 #define lcd_e_high()    LCD_E_PORT  |=  _BV(LCD_E_PIN);\r
22 #define lcd_e_low()     LCD_E_PORT  &= ~_BV(LCD_E_PIN);\r
23 #define lcd_e_toggle()  toggle_e()\r
24 #define lcd_rw_high()   LCD_RW_PORT |=  _BV(LCD_RW_PIN)\r
25 #define lcd_rw_low()    LCD_RW_PORT &= ~_BV(LCD_RW_PIN)\r
26 #define lcd_rs_high()   LCD_RS_PORT |=  _BV(LCD_RS_PIN)\r
27 #define lcd_rs_low()    LCD_RS_PORT &= ~_BV(LCD_RS_PIN)\r
28 #endif\r
29 \r
30 #if LCD_IO_MODE\r
31 #if LCD_LINES==1\r
32 #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_1LINE \r
33 #else\r
34 #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_4BIT_2LINES \r
35 #endif\r
36 #else\r
37 #if LCD_LINES==1\r
38 #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_1LINE\r
39 #else\r
40 #define LCD_FUNCTION_DEFAULT    LCD_FUNCTION_8BIT_2LINES\r
41 #endif\r
42 #endif\r
43 \r
44 #if LCD_CONTROLLER_KS0073\r
45 #if LCD_LINES==4\r
46 \r
47 #define KS0073_EXTENDED_FUNCTION_REGISTER_ON  0x24   /* |0|010|0100 4-bit mode extension-bit RE = 1 */\r
48 #define KS0073_EXTENDED_FUNCTION_REGISTER_OFF 0x20   /* |0|000|1001 4 lines mode */\r
49 #define KS0073_4LINES_MODE                    0x09   /* |0|001|0000 4-bit mode, extension-bit RE = 0 */\r
50 \r
51 #endif\r
52 #endif\r
53 \r
54 /* \r
55 ** function prototypes \r
56 */\r
57 #if LCD_IO_MODE\r
58 static void toggle_e(void);\r
59 #endif\r
60 \r
61 /*\r
62 ** local functions\r
63 */\r
64 \r
65 \r
66 \r
67 /*************************************************************************\r
68  delay loop for small accurate delays: 16-bit counter, 4 cycles/loop\r
69 *************************************************************************/\r
70 static inline void _delayFourCycles(unsigned int __count)\r
71 {\r
72     if ( __count == 0 )    \r
73         __asm__ __volatile__( "rjmp 1f\n 1:" );    // 2 cycles\r
74     else\r
75         __asm__ __volatile__ (\r
76             "1: sbiw %0,1" "\n\t"                  \r
77             "brne 1b"                              // 4 cycles/loop\r
78             : "=w" (__count)\r
79             : "0" (__count)\r
80            );\r
81 }\r
82 \r
83 \r
84 /************************************************************************* \r
85 delay for a minimum of <us> microseconds\r
86 the number of loops is calculated at compile-time from MCU clock frequency\r
87 *************************************************************************/\r
88 #define delay(us)  _delayFourCycles( ( ( 1*(XTAL/4000) )*us)/1000 )\r
89 \r
90 \r
91 #if LCD_IO_MODE\r
92 /* toggle Enable Pin to initiate write */\r
93 static void toggle_e(void)\r
94 {\r
95     lcd_e_high();\r
96     lcd_e_delay();\r
97     lcd_e_low();\r
98 }\r
99 #endif\r
100 \r
101 \r
102 /*************************************************************************\r
103 Low-level function to write byte to LCD controller\r
104 Input:    data   byte to write to LCD\r
105           rs     1: write data    \r
106                  0: write instruction\r
107 Returns:  none\r
108 *************************************************************************/\r
109 #if LCD_IO_MODE\r
110 static void lcd_write(uint8_t data,uint8_t rs) \r
111 {\r
112     unsigned char dataBits ;\r
113 \r
114 \r
115     if (rs) {   /* write data        (RS=1, RW=0) */\r
116        lcd_rs_high();\r
117     } else {    /* write instruction (RS=0, RW=0) */\r
118        lcd_rs_low();\r
119     }\r
120     lcd_rw_low();\r
121 \r
122     if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )\r
123       && (LCD_DATA0_PIN == 0) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )\r
124     {\r
125         /* configure data pins as output */\r
126         DDR(LCD_DATA0_PORT) |= 0x0F;\r
127 \r
128         /* output high nibble first */\r
129         dataBits = LCD_DATA0_PORT & 0xF0;\r
130         LCD_DATA0_PORT = dataBits |((data>>4)&0x0F);\r
131         lcd_e_toggle();\r
132 \r
133         /* output low nibble */\r
134         LCD_DATA0_PORT = dataBits | (data&0x0F);\r
135         lcd_e_toggle();\r
136 \r
137         /* all data pins high (inactive) */\r
138         LCD_DATA0_PORT = dataBits | 0x0F;\r
139     }\r
140     else\r
141     {\r
142         /* configure data pins as output */\r
143         DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);\r
144         DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);\r
145         DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);\r
146         DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);\r
147         \r
148         /* output high nibble first */\r
149         LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);\r
150         LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);\r
151         LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);\r
152         LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);\r
153         if(data & 0x80) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);\r
154         if(data & 0x40) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);\r
155         if(data & 0x20) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);\r
156         if(data & 0x10) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);   \r
157         lcd_e_toggle();\r
158         \r
159         /* output low nibble */\r
160         LCD_DATA3_PORT &= ~_BV(LCD_DATA3_PIN);\r
161         LCD_DATA2_PORT &= ~_BV(LCD_DATA2_PIN);\r
162         LCD_DATA1_PORT &= ~_BV(LCD_DATA1_PIN);\r
163         LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);\r
164         if(data & 0x08) LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);\r
165         if(data & 0x04) LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);\r
166         if(data & 0x02) LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);\r
167         if(data & 0x01) LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);\r
168         lcd_e_toggle();        \r
169         \r
170         /* all data pins high (inactive) */\r
171         LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);\r
172         LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);\r
173         LCD_DATA2_PORT |= _BV(LCD_DATA2_PIN);\r
174         LCD_DATA3_PORT |= _BV(LCD_DATA3_PIN);\r
175     }\r
176 }\r
177 #else\r
178 #define lcd_write(d,rs) if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d;\r
179 /* rs==0 -> write instruction to LCD_IO_FUNCTION */\r
180 /* rs==1 -> write data to LCD_IO_DATA */\r
181 #endif\r
182 \r
183 \r
184 /*************************************************************************\r
185 Low-level function to read byte from LCD controller\r
186 Input:    rs     1: read data    \r
187                  0: read busy flag / address counter\r
188 Returns:  byte read from LCD controller\r
189 *************************************************************************/\r
190 #if LCD_IO_MODE\r
191 static uint8_t lcd_read(uint8_t rs) \r
192 {\r
193     uint8_t data;\r
194     \r
195     \r
196     if (rs)\r
197         lcd_rs_high();                       /* RS=1: read data      */\r
198     else\r
199         lcd_rs_low();                        /* RS=0: read busy flag */\r
200     lcd_rw_high();                           /* RW=1  read mode      */\r
201     \r
202     if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )\r
203       && ( LCD_DATA0_PIN == 0 )&& (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )\r
204     {\r
205         DDR(LCD_DATA0_PORT) &= 0xF0;         /* configure data pins as input */\r
206         \r
207         lcd_e_high();\r
208         lcd_e_delay();        \r
209         data = PIN(LCD_DATA0_PORT) << 4;     /* read high nibble first */\r
210         lcd_e_low();\r
211         \r
212         lcd_e_delay();                       /* Enable 500ns low       */\r
213         \r
214         lcd_e_high();\r
215         lcd_e_delay();\r
216         data |= PIN(LCD_DATA0_PORT)&0x0F;    /* read low nibble        */\r
217         lcd_e_low();\r
218     }\r
219     else\r
220     {\r
221         /* configure data pins as input */\r
222         DDR(LCD_DATA0_PORT) &= ~_BV(LCD_DATA0_PIN);\r
223         DDR(LCD_DATA1_PORT) &= ~_BV(LCD_DATA1_PIN);\r
224         DDR(LCD_DATA2_PORT) &= ~_BV(LCD_DATA2_PIN);\r
225         DDR(LCD_DATA3_PORT) &= ~_BV(LCD_DATA3_PIN);\r
226                 \r
227         /* read high nibble first */\r
228         lcd_e_high();\r
229         lcd_e_delay();        \r
230         data = 0;\r
231         if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x10;\r
232         if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x20;\r
233         if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x40;\r
234         if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x80;\r
235         lcd_e_low();\r
236 \r
237         lcd_e_delay();                       /* Enable 500ns low       */\r
238     \r
239         /* read low nibble */    \r
240         lcd_e_high();\r
241         lcd_e_delay();\r
242         if ( PIN(LCD_DATA0_PORT) & _BV(LCD_DATA0_PIN) ) data |= 0x01;\r
243         if ( PIN(LCD_DATA1_PORT) & _BV(LCD_DATA1_PIN) ) data |= 0x02;\r
244         if ( PIN(LCD_DATA2_PORT) & _BV(LCD_DATA2_PIN) ) data |= 0x04;\r
245         if ( PIN(LCD_DATA3_PORT) & _BV(LCD_DATA3_PIN) ) data |= 0x08;        \r
246         lcd_e_low();\r
247     }\r
248     return data;\r
249 }\r
250 #else\r
251 #define lcd_read(rs) (rs) ? *(volatile uint8_t*)(LCD_IO_DATA+LCD_IO_READ) : *(volatile uint8_t*)(LCD_IO_FUNCTION+LCD_IO_READ)\r
252 /* rs==0 -> read instruction from LCD_IO_FUNCTION */\r
253 /* rs==1 -> read data from LCD_IO_DATA */\r
254 #endif\r
255 \r
256 \r
257 /*************************************************************************\r
258 loops while lcd is busy, returns address counter\r
259 *************************************************************************/\r
260 static uint8_t lcd_waitbusy(void)\r
261 \r
262 {\r
263     register uint8_t c;\r
264     \r
265     /* wait until busy flag is cleared */\r
266     while ( (c=lcd_read(0)) & (1<<LCD_BUSY)) {}\r
267     \r
268     /* the address counter is updated 4us after the busy flag is cleared */\r
269     delay(2);\r
270 \r
271     /* now read the address counter */\r
272     return (lcd_read(0));  // return address counter\r
273     \r
274 }/* lcd_waitbusy */\r
275 \r
276 \r
277 /*************************************************************************\r
278 Move cursor to the start of next line or to the first line if the cursor \r
279 is already on the last line.\r
280 *************************************************************************/\r
281 static inline void lcd_newline(uint8_t pos)\r
282 {\r
283     register uint8_t addressCounter;\r
284 \r
285 \r
286 #if LCD_LINES==1\r
287     addressCounter = 0;\r
288 #endif\r
289 #if LCD_LINES==2\r
290     if ( pos < (LCD_START_LINE2) )\r
291         addressCounter = LCD_START_LINE2;\r
292     else\r
293         addressCounter = LCD_START_LINE1;\r
294 #endif\r
295 #if LCD_LINES==4\r
296 #if KS0073_4LINES_MODE\r
297     if ( pos < LCD_START_LINE2 )\r
298         addressCounter = LCD_START_LINE2;\r
299     else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE3) )\r
300         addressCounter = LCD_START_LINE3;\r
301     else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE4) )\r
302         addressCounter = LCD_START_LINE4;\r
303     else \r
304         addressCounter = LCD_START_LINE1;\r
305 #else\r
306     if ( pos < LCD_START_LINE3 )\r
307         addressCounter = LCD_START_LINE2;\r
308     else if ( (pos >= LCD_START_LINE2) && (pos < LCD_START_LINE4) )\r
309         addressCounter = LCD_START_LINE3;\r
310     else if ( (pos >= LCD_START_LINE3) && (pos < LCD_START_LINE2) )\r
311         addressCounter = LCD_START_LINE4;\r
312     else \r
313         addressCounter = LCD_START_LINE1;\r
314 #endif\r
315 #endif\r
316     lcd_command((1<<LCD_DDRAM)+addressCounter);\r
317 \r
318 }/* lcd_newline */\r
319 \r
320 \r
321 /*\r
322 ** PUBLIC FUNCTIONS \r
323 */\r
324 \r
325 /*************************************************************************\r
326 Send LCD controller instruction command\r
327 Input:   instruction to send to LCD controller, see HD44780 data sheet\r
328 Returns: none\r
329 *************************************************************************/\r
330 void lcd_command(uint8_t cmd)\r
331 {\r
332     lcd_waitbusy();\r
333     lcd_write(cmd,0);\r
334 }\r
335 \r
336 \r
337 /*************************************************************************\r
338 Send data byte to LCD controller \r
339 Input:   data to send to LCD controller, see HD44780 data sheet\r
340 Returns: none\r
341 *************************************************************************/\r
342 void lcd_data(uint8_t data)\r
343 {\r
344     lcd_waitbusy();\r
345     lcd_write(data,1);\r
346 }\r
347 \r
348 \r
349 \r
350 /*************************************************************************\r
351 Set cursor to specified position\r
352 Input:    x  horizontal position  (0: left most position)\r
353           y  vertical position    (0: first line)\r
354 Returns:  none\r
355 *************************************************************************/\r
356 void lcd_gotoxy(uint8_t x, uint8_t y)\r
357 {\r
358 #if LCD_LINES==1\r
359     lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);\r
360 #endif\r
361 #if LCD_LINES==2\r
362     if ( y==0 ) \r
363         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);\r
364     else\r
365         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);\r
366 #endif\r
367 #if LCD_LINES==4\r
368     if ( y==0 )\r
369         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE1+x);\r
370     else if ( y==1)\r
371         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE2+x);\r
372     else if ( y==2)\r
373         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE3+x);\r
374     else /* y==3 */\r
375         lcd_command((1<<LCD_DDRAM)+LCD_START_LINE4+x);\r
376 #endif\r
377 \r
378 }/* lcd_gotoxy */\r
379 \r
380 \r
381 /*************************************************************************\r
382 *************************************************************************/\r
383 int lcd_getxy(void)\r
384 {\r
385     return lcd_waitbusy();\r
386 }\r
387 \r
388 \r
389 /*************************************************************************\r
390 Clear display and set cursor to home position\r
391 *************************************************************************/\r
392 void lcd_clrscr(void)\r
393 {\r
394     lcd_command(1<<LCD_CLR);\r
395 }\r
396 \r
397 \r
398 /*************************************************************************\r
399 Set cursor to home position\r
400 *************************************************************************/\r
401 void lcd_home(void)\r
402 {\r
403     lcd_command(1<<LCD_HOME);\r
404 }\r
405 \r
406 \r
407 /*************************************************************************\r
408 Display character at current cursor position \r
409 Input:    character to be displayed                                       \r
410 Returns:  none\r
411 *************************************************************************/\r
412 void lcd_putc(char c)\r
413 {\r
414     uint8_t pos;\r
415 \r
416 \r
417     pos = lcd_waitbusy();   // read busy-flag and address counter\r
418     if (c=='\n')\r
419     {\r
420         lcd_newline(pos);\r
421     }\r
422     else\r
423     {\r
424 #if LCD_WRAP_LINES==1\r
425 #if LCD_LINES==1\r
426         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {\r
427             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);\r
428         }\r
429 #elif LCD_LINES==2\r
430         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {\r
431             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);    \r
432         }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ){\r
433             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);\r
434         }\r
435 #elif LCD_LINES==4\r
436         if ( pos == LCD_START_LINE1+LCD_DISP_LENGTH ) {\r
437             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE2,0);    \r
438         }else if ( pos == LCD_START_LINE2+LCD_DISP_LENGTH ) {\r
439             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE3,0);\r
440         }else if ( pos == LCD_START_LINE3+LCD_DISP_LENGTH ) {\r
441             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE4,0);\r
442         }else if ( pos == LCD_START_LINE4+LCD_DISP_LENGTH ) {\r
443             lcd_write((1<<LCD_DDRAM)+LCD_START_LINE1,0);\r
444         }\r
445 #endif\r
446         lcd_waitbusy();\r
447 #endif\r
448         lcd_write(c, 1);\r
449     }\r
450 \r
451 }/* lcd_putc */\r
452 \r
453 \r
454 /*************************************************************************\r
455 Display string without auto linefeed \r
456 Input:    string to be displayed\r
457 Returns:  none\r
458 *************************************************************************/\r
459 void lcd_puts(const char *s)\r
460 /* print string on lcd (no auto linefeed) */\r
461 {\r
462     register char c;\r
463 \r
464     while ( (c = *s++) ) {\r
465         lcd_putc(c);\r
466     }\r
467 \r
468 }/* lcd_puts */\r
469 \r
470 \r
471 /*************************************************************************\r
472 Display string from program memory without auto linefeed \r
473 Input:     string from program memory be be displayed                                        \r
474 Returns:   none\r
475 *************************************************************************/\r
476 void lcd_puts_p(const char *progmem_s)\r
477 /* print string from program memory on lcd (no auto linefeed) */\r
478 {\r
479     register char c;\r
480 \r
481     while ( (c = pgm_read_byte(progmem_s++)) ) {\r
482         lcd_putc(c);\r
483     }\r
484 \r
485 }/* lcd_puts_p */\r
486 \r
487 \r
488 /*************************************************************************\r
489 Initialize display and select type of cursor \r
490 Input:    dispAttr LCD_DISP_OFF            display off\r
491                    LCD_DISP_ON             display on, cursor off\r
492                    LCD_DISP_ON_CURSOR      display on, cursor on\r
493                    LCD_DISP_CURSOR_BLINK   display on, cursor on flashing\r
494 Returns:  none\r
495 *************************************************************************/\r
496 void lcd_init(uint8_t dispAttr)\r
497 {\r
498 #if LCD_IO_MODE\r
499     /*\r
500      *  Initialize LCD to 4 bit I/O mode\r
501      */\r
502      \r
503     if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )\r
504       && ( &LCD_RS_PORT == &LCD_DATA0_PORT) && ( &LCD_RW_PORT == &LCD_DATA0_PORT) && (&LCD_E_PORT == &LCD_DATA0_PORT)\r
505       && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) \r
506       && (LCD_RS_PIN == 4 ) && (LCD_RW_PIN == 5) && (LCD_E_PIN == 6 ) )\r
507     {\r
508         /* configure all port bits as output (all LCD lines on same port) */\r
509         DDR(LCD_DATA0_PORT) |= 0x7F;\r
510     }\r
511     else if ( ( &LCD_DATA0_PORT == &LCD_DATA1_PORT) && ( &LCD_DATA1_PORT == &LCD_DATA2_PORT ) && ( &LCD_DATA2_PORT == &LCD_DATA3_PORT )\r
512            && (LCD_DATA0_PIN == 0 ) && (LCD_DATA1_PIN == 1) && (LCD_DATA2_PIN == 2) && (LCD_DATA3_PIN == 3) )\r
513     {\r
514         /* configure all port bits as output (all LCD data lines on same port, but control lines on different ports) */\r
515         DDR(LCD_DATA0_PORT) |= 0x0F;\r
516         DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);\r
517         DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);\r
518         DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);\r
519     }\r
520     else\r
521     {\r
522         /* configure all port bits as output (LCD data and control lines on different ports */\r
523         DDR(LCD_RS_PORT)    |= _BV(LCD_RS_PIN);\r
524         DDR(LCD_RW_PORT)    |= _BV(LCD_RW_PIN);\r
525         DDR(LCD_E_PORT)     |= _BV(LCD_E_PIN);\r
526         DDR(LCD_DATA0_PORT) |= _BV(LCD_DATA0_PIN);\r
527         DDR(LCD_DATA1_PORT) |= _BV(LCD_DATA1_PIN);\r
528         DDR(LCD_DATA2_PORT) |= _BV(LCD_DATA2_PIN);\r
529         DDR(LCD_DATA3_PORT) |= _BV(LCD_DATA3_PIN);\r
530     }\r
531     delay(16000);        /* wait 16ms or more after power-on       */\r
532     \r
533     /* initial write to lcd is 8bit */\r
534     LCD_DATA1_PORT |= _BV(LCD_DATA1_PIN);  // _BV(LCD_FUNCTION)>>4;\r
535     LCD_DATA0_PORT |= _BV(LCD_DATA0_PIN);  // _BV(LCD_FUNCTION_8BIT)>>4;\r
536     lcd_e_toggle();\r
537     delay(4992);         /* delay, busy flag can't be checked here */\r
538    \r
539     /* repeat last command */ \r
540     lcd_e_toggle();      \r
541     delay(64);           /* delay, busy flag can't be checked here */\r
542     \r
543     /* repeat last command a third time */\r
544     lcd_e_toggle();      \r
545     delay(64);           /* delay, busy flag can't be checked here */\r
546 \r
547     /* now configure for 4bit mode */\r
548     LCD_DATA0_PORT &= ~_BV(LCD_DATA0_PIN);   // LCD_FUNCTION_4BIT_1LINE>>4\r
549     lcd_e_toggle();\r
550     delay(64);           /* some displays need this additional delay */\r
551     \r
552     /* from now the LCD only accepts 4 bit I/O, we can use lcd_command() */    \r
553 #else\r
554     /*\r
555      * Initialize LCD to 8 bit memory mapped mode\r
556      */\r
557     \r
558     /* enable external SRAM (memory mapped lcd) and one wait state */        \r
559     MCUCR = _BV(SRE) | _BV(SRW);\r
560 \r
561     /* reset LCD */\r
562     delay(16000);                           /* wait 16ms after power-on     */\r
563     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                   \r
564     delay(4992);                            /* wait 5ms                     */\r
565     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                 \r
566     delay(64);                              /* wait 64us                    */\r
567     lcd_write(LCD_FUNCTION_8BIT_1LINE,0);   /* function set: 8bit interface */                \r
568     delay(64);                              /* wait 64us                    */\r
569 #endif\r
570 \r
571 #if KS0073_4LINES_MODE\r
572     /* Display with KS0073 controller requires special commands for enabling 4 line mode */\r
573         lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_ON);\r
574         lcd_command(KS0073_4LINES_MODE);\r
575         lcd_command(KS0073_EXTENDED_FUNCTION_REGISTER_OFF);\r
576 #else\r
577     lcd_command(LCD_FUNCTION_DEFAULT);      /* function set: display lines  */\r
578 #endif\r
579     lcd_command(LCD_DISP_OFF);              /* display off                  */\r
580     lcd_clrscr();                           /* display clear                */ \r
581     lcd_command(LCD_MODE_DEFAULT);          /* set entry mode               */\r
582     lcd_command(dispAttr);                  /* display/cursor control       */\r
583 \r
584 }/* lcd_init */\r