?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file lcd.c \brief Character LCD driver for HD44780/SED1278 displays. */
2 //*****************************************************************************
3 //
4 // File Name : 'lcd.c'
5 // Title : Character LCD driver for HD44780/SED1278 displays
6 // (usable in mem-mapped, or I/O mode)
7 // Author : Pascal Stang
8 // Created : 11/22/2000
9 // Revised : 4/30/2002
10 // Version : 1.1
11 // Target MCU : Atmel AVR series
12 // Editor Tabs : 4
13 //
14 // This code is distributed under the GNU Public License
15 // which can be found at http://www.gnu.org/licenses/gpl.txt
16 //
17 //*****************************************************************************
18  
19 #include <avr/io.h>
20 #include <avr/pgmspace.h>
21  
22 #include "global.h"
23 #include "timer.h"
24  
25 #include "lcd.h"
26  
27 // custom LCD characters
28 unsigned char __attribute__ ((progmem)) LcdCustomChar[] =
29 {
30 0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block
31 0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block
32 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block
33 0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block
34 0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block
35 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block
36 0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow
37 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 7. stop block
38 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, // 8. pause bars
39 0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00, // 9. fast-forward arrow
40 0x00, 0x04, 0x04, 0x0E, 0x0E, 0x1F, 0x1F, 0x00, // 10. scroll up arrow
41 0x00, 0x1F, 0x1F, 0x0E, 0x0E, 0x04, 0x04, 0x00, // 11. scroll down arrow
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12. blank character
43 0x00, 0x0E, 0x19, 0x15, 0x13, 0x0E, 0x00, 0x00, // 13. animated play icon frame 0
44 0x00, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x00, 0x00, // 14. animated play icon frame 1
45 0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00, 0x00, // 15. animated play icon frame 2
46 0x00, 0x0E, 0x11, 0x1F, 0x11, 0x0E, 0x00, 0x00, // 16. animated play icon frame 3
47 };
48  
49 /*************************************************************/
50 /********************** LOCAL FUNCTIONS **********************/
51 /*************************************************************/
52  
53 void lcdInitHW(void)
54 {
55 // initialize I/O ports
56 // if I/O interface is in use
57 #ifdef LCD_PORT_INTERFACE
58 // initialize LCD control lines
59 cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
60 cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
61 cbi(LCD_CTRL_PORT, LCD_CTRL_E);
62 // initialize LCD control lines to output
63 sbi(LCD_CTRL_DDR, LCD_CTRL_RS);
64 sbi(LCD_CTRL_DDR, LCD_CTRL_RW);
65 sbi(LCD_CTRL_DDR, LCD_CTRL_E);
66 // initialize LCD data port to input
67 // initialize LCD data lines to pull-up
68 #ifdef LCD_DATA_4BIT
69 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
70 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
71 #else
72 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
73 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
74 #endif
75 #else
76 // enable external memory bus if not already enabled
77 sbi(MCUCR, SRE); // enable bus interface
78 #endif
79 }
80  
81 void lcdBusyWait(void)
82 {
83 // wait until LCD busy bit goes to zero
84 // do a read from control register
85 #ifdef LCD_PORT_INTERFACE
86 cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
87 #ifdef LCD_DATA_4BIT
88 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
89 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
90 #else
91 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
92 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
93 #endif
94 sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
95 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
96 LCD_DELAY; // wait
97 while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY)
98 {
99 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
100 LCD_DELAY; // wait
101 LCD_DELAY; // wait
102 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
103 LCD_DELAY; // wait
104 LCD_DELAY; // wait
105 #ifdef LCD_DATA_4BIT // do an extra clock for 4 bit reads
106 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
107 LCD_DELAY; // wait
108 LCD_DELAY; // wait
109 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
110 LCD_DELAY; // wait
111 LCD_DELAY; // wait
112 #endif
113 }
114 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
115 // leave data lines in input mode so they can be most easily used for other purposes
116 #else
117 // memory bus read
118 // sbi(MCUCR, SRW); // enable RAM waitstate
119 // wait until LCD busy bit goes to zero
120 while( (*((volatile unsigned char *) (LCD_CTRL_ADDR))) & (1<<LCD_BUSY) );
121 // cbi(MCUCR, SRW); // disable RAM waitstate
122 #endif
123 }
124  
125 void lcdControlWrite(u08 data)
126 {
127 // write the control byte to the display controller
128 #ifdef LCD_PORT_INTERFACE
129 lcdBusyWait(); // wait until LCD not busy
130 cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
131 cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write"
132 #ifdef LCD_DATA_4BIT
133 // 4 bit write
134 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
135 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
136 outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits
137 LCD_DELAY; // wait
138 LCD_DELAY; // wait
139 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
140 LCD_DELAY; // wait
141 LCD_DELAY; // wait
142 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
143 outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits
144 LCD_DELAY; // wait
145 LCD_DELAY; // wait
146 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
147 #else
148 // 8 bit write
149 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
150 outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit)
151 outb(LCD_DATA_POUT, data); // output data, 8bits
152 LCD_DELAY; // wait
153 LCD_DELAY; // wait
154 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
155 #endif
156 // leave data lines in input mode so they can be most easily used for other purposes
157 #ifdef LCD_DATA_4BIT
158 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
159 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
160 #else
161 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
162 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
163 #endif
164 #else
165 // memory bus write
166 //sbi(MCUCR, SRW); // enable RAM waitstate
167 lcdBusyWait(); // wait until LCD not busy
168 *((volatile unsigned char *) (LCD_CTRL_ADDR)) = data;
169 //cbi(MCUCR, SRW); // disable RAM waitstate
170 #endif
171 }
172  
173 u08 lcdControlRead(void)
174 {
175 // read the control byte from the display controller
176 register u08 data;
177 #ifdef LCD_PORT_INTERFACE
178 lcdBusyWait(); // wait until LCD not busy
179 #ifdef LCD_DATA_4BIT
180 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
181 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
182 #else
183 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
184 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
185 #endif
186 cbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "control"
187 sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
188 #ifdef LCD_DATA_4BIT
189 // 4 bit read
190 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
191 LCD_DELAY; // wait
192 LCD_DELAY; // wait
193 data = inb(LCD_DATA_PIN)&0xF0; // input data, high 4 bits
194 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
195 LCD_DELAY; // wait
196 LCD_DELAY; // wait
197 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
198 LCD_DELAY; // wait
199 LCD_DELAY; // wait
200 data |= inb(LCD_DATA_PIN)>>4; // input data, low 4 bits
201 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
202 #else
203 // 8 bit read
204 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
205 LCD_DELAY; // wait
206 LCD_DELAY; // wait
207 data = inb(LCD_DATA_PIN); // input data, 8bits
208 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
209 #endif
210 // leave data lines in input mode so they can be most easily used for other purposes
211 #else
212 //sbi(MCUCR, SRW); // enable RAM waitstate
213 lcdBusyWait(); // wait until LCD not busy
214 data = *((volatile unsigned char *) (LCD_CTRL_ADDR));
215 //cbi(MCUCR, SRW); // disable RAM waitstate
216 #endif
217 return data;
218 }
219  
220 void lcdDataWrite(u08 data)
221 {
222 // write a data byte to the display
223 #ifdef LCD_PORT_INTERFACE
224 lcdBusyWait(); // wait until LCD not busy
225 sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data"
226 cbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "write"
227 #ifdef LCD_DATA_4BIT
228 // 4 bit write
229 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
230 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
231 outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) ); // output data, high 4 bits
232 LCD_DELAY; // wait
233 LCD_DELAY; // wait
234 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
235 LCD_DELAY; // wait
236 LCD_DELAY; // wait
237 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
238 outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) ); // output data, low 4 bits
239 LCD_DELAY; // wait
240 LCD_DELAY; // wait
241 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
242 #else
243 // 8 bit write
244 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
245 outb(LCD_DATA_DDR, 0xFF); // set data I/O lines to output (8bit)
246 outb(LCD_DATA_POUT, data); // output data, 8bits
247 LCD_DELAY; // wait
248 LCD_DELAY; // wait
249 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
250 #endif
251 // leave data lines in input mode so they can be most easily used for other purposes
252 #ifdef LCD_DATA_4BIT
253 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
254 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
255 #else
256 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
257 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
258 #endif
259 #else
260 // memory bus write
261 //sbi(MCUCR, SRW); // enable RAM waitstate
262 lcdBusyWait(); // wait until LCD not busy
263 *((volatile unsigned char *) (LCD_DATA_ADDR)) = data;
264 //cbi(MCUCR, SRW); // disable RAM waitstate
265 #endif
266 }
267  
268 u08 lcdDataRead(void)
269 {
270 // read a data byte from the display
271 register u08 data;
272 #ifdef LCD_PORT_INTERFACE
273 lcdBusyWait(); // wait until LCD not busy
274 #ifdef LCD_DATA_4BIT
275 outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
276 outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0); // set pull-ups to on (4bit)
277 #else
278 outb(LCD_DATA_DDR, 0x00); // set data I/O lines to input (8bit)
279 outb(LCD_DATA_POUT, 0xFF); // set pull-ups to on (8bit)
280 #endif
281 sbi(LCD_CTRL_PORT, LCD_CTRL_RS); // set RS to "data"
282 sbi(LCD_CTRL_PORT, LCD_CTRL_RW); // set R/W to "read"
283 #ifdef LCD_DATA_4BIT
284 // 4 bit read
285 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
286 LCD_DELAY; // wait
287 LCD_DELAY; // wait
288 data = inb(LCD_DATA_PIN)&0xF0; // input data, high 4 bits
289 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
290 LCD_DELAY; // wait
291 LCD_DELAY; // wait
292 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
293 LCD_DELAY; // wait
294 LCD_DELAY; // wait
295 data |= inb(LCD_DATA_PIN)>>4; // input data, low 4 bits
296 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
297 #else
298 // 8 bit read
299 sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
300 LCD_DELAY; // wait
301 LCD_DELAY; // wait
302 data = inb(LCD_DATA_PIN); // input data, 8bits
303 cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
304 #endif
305 // leave data lines in input mode so they can be most easily used for other purposes
306 #else
307 // memory bus read
308 //sbi(MCUCR, SRW); // enable RAM waitstate
309 lcdBusyWait(); // wait until LCD not busy
310 data = *((volatile unsigned char *) (LCD_DATA_ADDR));
311 //cbi(MCUCR, SRW); // disable RAM waitstate
312 #endif
313 return data;
314 }
315  
316  
317  
318 /*************************************************************/
319 /********************* PUBLIC FUNCTIONS **********************/
320 /*************************************************************/
321  
322 void lcdInit()
323 {
324 // initialize hardware
325 lcdInitHW();
326 // LCD function set
327 lcdControlWrite(LCD_FUNCTION_DEFAULT);
328 // clear LCD
329 lcdControlWrite(1<<LCD_CLR);
330 delay(60000); // wait 60ms
331 // set entry mode
332 lcdControlWrite(1<<LCD_ENTRY_MODE | 1<<LCD_ENTRY_INC);
333 // set display to on
334 //lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY | 1<<LCD_ON_BLINK);
335 lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY );
336 // move cursor to home
337 lcdControlWrite(1<<LCD_HOME);
338 // set data address to 0
339 lcdControlWrite(1<<LCD_DDRAM | 0x00);
340  
341 // load the first 8 custom characters
342 lcdLoadCustomChar((u08*)LcdCustomChar,0,0);
343 lcdLoadCustomChar((u08*)LcdCustomChar,1,1);
344 lcdLoadCustomChar((u08*)LcdCustomChar,2,2);
345 lcdLoadCustomChar((u08*)LcdCustomChar,3,3);
346 lcdLoadCustomChar((u08*)LcdCustomChar,4,4);
347 lcdLoadCustomChar((u08*)LcdCustomChar,5,5);
348 lcdLoadCustomChar((u08*)LcdCustomChar,6,6);
349 lcdLoadCustomChar((u08*)LcdCustomChar,7,7);
350 }
351  
352 void lcdHome(void)
353 {
354 // move cursor to home
355 lcdControlWrite(1<<LCD_HOME);
356 }
357  
358 void lcdClear(void)
359 {
360 // clear LCD
361 lcdControlWrite(1<<LCD_CLR);
362 }
363  
364 void lcdGotoXY(u08 x, u08 y)
365 {
366 register u08 DDRAMAddr;
367  
368 // remap lines into proper order
369 switch(y)
370 {
371 case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; break;
372 case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+x; break;
373 case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+x; break;
374 case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+x; break;
375 default: DDRAMAddr = LCD_LINE0_DDRAMADDR+x;
376 }
377  
378 // set data address
379 lcdControlWrite(1<<LCD_DDRAM | DDRAMAddr);
380 }
381  
382 void lcdLoadCustomChar(u08* lcdCustomCharArray, u08 romCharNum, u08 lcdCharNum)
383 {
384 register u08 i;
385 u08 saveDDRAMAddr;
386  
387 // backup the current cursor position
388 saveDDRAMAddr = lcdControlRead() & 0x7F;
389  
390 // multiply the character index by 8
391 lcdCharNum = (lcdCharNum<<3); // each character occupies 8 bytes
392 romCharNum = (romCharNum<<3); // each character occupies 8 bytes
393  
394 // copy the 8 bytes into CG (character generator) RAM
395 for(i=0; i<8; i++)
396 {
397 // set CG RAM address
398 lcdControlWrite((1<<LCD_CGRAM) | (lcdCharNum+i));
399 // write character data
400 lcdDataWrite( pgm_read_byte(lcdCustomCharArray+romCharNum+i) );
401 }
402  
403 // restore the previous cursor position
404 lcdControlWrite(1<<LCD_DDRAM | saveDDRAMAddr);
405  
406 }
407  
408 void lcdPrintData(char* data, u08 nBytes)
409 {
410 register u08 i;
411  
412 // check to make sure we have a good pointer
413 if (!data) return;
414  
415 // print data
416 for(i=0; i<nBytes; i++)
417 {
418 lcdDataWrite(data[i]);
419 }
420 }
421  
422 void lcdProgressBar(u16 progress, u16 maxprogress, u08 length)
423 {
424 u08 i;
425 u32 pixelprogress;
426 u08 c;
427  
428 // draw a progress bar displaying (progress / maxprogress)
429 // starting from the current cursor position
430 // with a total length of "length" characters
431 // ***note, LCD chars 0-5 must be programmed as the bar characters
432 // char 0 = empty ... char 5 = full
433  
434 // total pixel length of bargraph equals length*PROGRESSPIXELS_PER_CHAR;
435 // pixel length of bar itself is
436 pixelprogress = ((progress*(length*PROGRESSPIXELS_PER_CHAR))/maxprogress);
437  
438 // print exactly "length" characters
439 for(i=0; i<length; i++)
440 {
441 // check if this is a full block, or partial or empty
442 // (u16) cast is needed to avoid sign comparison warning
443 if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)+5) > pixelprogress )
444 {
445 // this is a partial or empty block
446 if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)) > pixelprogress )
447 {
448 // this is an empty block
449 // use space character?
450 c = 0;
451 }
452 else
453 {
454 // this is a partial block
455 c = pixelprogress % PROGRESSPIXELS_PER_CHAR;
456 }
457 }
458 else
459 {
460 // this is a full block
461 c = 5;
462 }
463  
464 // write character to display
465 lcdDataWrite(c);
466 }
467  
468 }
469  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3