Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

# lcd.c

Go to the documentation of this file.

    00001 /*! \file lcd.c \brief Character LCD driver for HD44780/SED1278 displays. */
    00002 //*****************************************************************************
    00003 //
    00004 // File Name    : 'lcd.c'
    00005 // Title        : Character LCD driver for HD44780/SED1278 displays
    00006 //                  (usable in mem-mapped, or I/O mode)
    00007 // Author       : Pascal Stang
    00008 // Created      : 11/22/2000
    00009 // Revised      : 4/30/2002
    00010 // Version      : 1.1
    00011 // Target MCU   : Atmel AVR series
    00012 // Editor Tabs  : 4
    00013 //
    00014 // This code is distributed under the GNU Public License
    00015 //      which can be found at http://www.gnu.org/licenses/gpl.txt
    00016 //
    00017 //*****************************************************************************
    00018
    00019 #include <avr/io.h>
    00020 #include <avr/pgmspace.h>
    00021
    00022 #include "global.h"
    00023 #include "timer.h"
    00024
    00025 #include "lcd.h"
    00026
    00027 // custom LCD characters
    00028 unsigned char __attribute__ ((progmem)) LcdCustomChar[] =
    00029 {
    00030     0x00, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, // 0. 0/5 full progress block
    00031     0x00, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x1F, 0x00, // 1. 1/5 full progress block
    00032     0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, // 2. 2/5 full progress block
    00033     0x00, 0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x00, // 3. 3/5 full progress block
    00034     0x00, 0x1F, 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x00, // 4. 4/5 full progress block
    00035     0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 5. 5/5 full progress block
    00036     0x03, 0x07, 0x0F, 0x1F, 0x0F, 0x07, 0x03, 0x00, // 6. rewind arrow
    00037     0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, // 7. stop block
    00038     0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, // 8. pause bars
    00039     0x18, 0x1C, 0x1E, 0x1F, 0x1E, 0x1C, 0x18, 0x00, // 9. fast-forward arrow
    00040     0x00, 0x04, 0x04, 0x0E, 0x0E, 0x1F, 0x1F, 0x00, // 10. scroll up arrow
    00041     0x00, 0x1F, 0x1F, 0x0E, 0x0E, 0x04, 0x04, 0x00, // 11. scroll down arrow
    00042     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 12. blank character
    00043     0x00, 0x0E, 0x19, 0x15, 0x13, 0x0E, 0x00, 0x00, // 13. animated play icon frame 0
    00044     0x00, 0x0E, 0x15, 0x15, 0x15, 0x0E, 0x00, 0x00, // 14. animated play icon frame 1
    00045     0x00, 0x0E, 0x13, 0x15, 0x19, 0x0E, 0x00, 0x00, // 15. animated play icon frame 2
    00046     0x00, 0x0E, 0x11, 0x1F, 0x11, 0x0E, 0x00, 0x00, // 16. animated play icon frame 3
    00047 };
    00048
    00049 /*************************************************************/
    00050 /********************** LOCAL FUNCTIONS **********************/
    00051 /*************************************************************/
    00052
    00053 void lcdInitHW(void)
    00054 {
    00055     // initialize I/O ports
    00056     // if I/O interface is in use
    00057 #ifdef LCD_PORT_INTERFACE
    00058     // initialize LCD control lines
    00059     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
    00060     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
    00061     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
    00062     // initialize LCD control lines to output
    00063     sbi(LCD_CTRL_DDR, LCD_CTRL_RS);
    00064     sbi(LCD_CTRL_DDR, LCD_CTRL_RW);
    00065     sbi(LCD_CTRL_DDR, LCD_CTRL_E);
    00066     // initialize LCD data port to input
    00067     // initialize LCD data lines to pull-up
    00068     #ifdef LCD_DATA_4BIT
    00069         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F);     // set data I/O lines to input (4bit)
    00070         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00071     #else
    00072         outb(LCD_DATA_DDR, 0x00);                       // set data I/O lines to input (8bit)
    00073         outb(LCD_DATA_POUT, 0xFF);                      // set pull-ups to on (8bit)
    00074     #endif
    00075 #else
    00076     // enable external memory bus if not already enabled
    00077     sbi(MCUCR, SRE);            // enable bus interface
    00078 #endif
    00079 }
    00080
    00081 void lcdBusyWait(void)
    00082 {
    00083     // wait until LCD busy bit goes to zero
    00084     // do a read from control register
    00085 #ifdef LCD_PORT_INTERFACE
    00086     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);                // set RS to "control"
    00087     #ifdef LCD_DATA_4BIT
    00088         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F); // set data I/O lines to input (4bit)
    00089         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00090     #else
    00091         outb(LCD_DATA_DDR, 0x00);                   // set data I/O lines to input (8bit)
    00092         outb(LCD_DATA_POUT, 0xFF);                  // set pull-ups to on (8bit)
    00093     #endif
    00094     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);                // set R/W to "read"
    00095     sbi(LCD_CTRL_PORT, LCD_CTRL_E);                 // set "E" line
    00096     LCD_DELAY;                              // wait
    00097     while(inb(LCD_DATA_PIN) & 1<<LCD_BUSY)
    00098     {
    00099         cbi(LCD_CTRL_PORT, LCD_CTRL_E);     // clear "E" line
    00100         LCD_DELAY;                                  // wait
    00101         LCD_DELAY;                                  // wait
    00102         sbi(LCD_CTRL_PORT, LCD_CTRL_E);     // set "E" line
    00103         LCD_DELAY;                                  // wait
    00104         LCD_DELAY;                                  // wait
    00105         #ifdef LCD_DATA_4BIT                        // do an extra clock for 4 bit reads
    00106             cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00107             LCD_DELAY;                              // wait
    00108             LCD_DELAY;                              // wait
    00109             sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00110             LCD_DELAY;                              // wait
    00111             LCD_DELAY;                              // wait
    00112         #endif
    00113     }
    00114     cbi(LCD_CTRL_PORT, LCD_CTRL_E);         // clear "E" line
    00115     //  leave data lines in input mode so they can be most easily used for other purposes
    00116 #else
    00117     // memory bus read
    00118     // sbi(MCUCR, SRW);         // enable RAM waitstate
    00119     // wait until LCD busy bit goes to zero
    00120     while( (*((volatile unsigned char *) (LCD_CTRL_ADDR))) & (1<<LCD_BUSY) );
    00121     // cbi(MCUCR, SRW);         // disable RAM waitstate
    00122 #endif
    00123 }
    00124
    00125 void lcdControlWrite(u08 data)
    00126 {
    00127 // write the control byte to the display controller
    00128 #ifdef LCD_PORT_INTERFACE
    00129     lcdBusyWait();                          // wait until LCD not busy
    00130     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);            // set RS to "control"
    00131     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);            // set R/W to "write"
    00132     #ifdef LCD_DATA_4BIT
    00133         // 4 bit write
    00134         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00135         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
    00136         outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) );  // output data, high 4 bits
    00137         LCD_DELAY;                              // wait
    00138         LCD_DELAY;                              // wait
    00139         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00140         LCD_DELAY;                              // wait
    00141         LCD_DELAY;                              // wait
    00142         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00143         outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) );    // output data, low 4 bits
    00144         LCD_DELAY;                              // wait
    00145         LCD_DELAY;                              // wait
    00146         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00147     #else
    00148         // 8 bit write
    00149         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00150         outb(LCD_DATA_DDR, 0xFF);               // set data I/O lines to output (8bit)
    00151         outb(LCD_DATA_POUT, data);              // output data, 8bits
    00152         LCD_DELAY;                              // wait
    00153         LCD_DELAY;                              // wait
    00154         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00155     #endif
    00156     //  leave data lines in input mode so they can be most easily used for other purposes
    00157     #ifdef LCD_DATA_4BIT
    00158         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F);     // set data I/O lines to input (4bit)
    00159         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00160     #else
    00161         outb(LCD_DATA_DDR, 0x00);           // set data I/O lines to input (8bit)
    00162         outb(LCD_DATA_POUT, 0xFF);          // set pull-ups to on (8bit)
    00163     #endif
    00164 #else
    00165     // memory bus write
    00166     //sbi(MCUCR, SRW);          // enable RAM waitstate
    00167     lcdBusyWait();              // wait until LCD not busy
    00168     *((volatile unsigned char *) (LCD_CTRL_ADDR)) = data;
    00169     //cbi(MCUCR, SRW);          // disable RAM waitstate
    00170 #endif
    00171 }
    00172
    00173 u08 lcdControlRead(void)
    00174 {
    00175 // read the control byte from the display controller
    00176     register u08 data;
    00177 #ifdef LCD_PORT_INTERFACE
    00178     lcdBusyWait();              // wait until LCD not busy
    00179     #ifdef LCD_DATA_4BIT
    00180         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F);     // set data I/O lines to input (4bit)
    00181         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00182     #else
    00183         outb(LCD_DATA_DDR, 0x00);           // set data I/O lines to input (8bit)
    00184         outb(LCD_DATA_POUT, 0xFF);          // set pull-ups to on (8bit)
    00185     #endif
    00186     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);        // set RS to "control"
    00187     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);        // set R/W to "read"
    00188     #ifdef LCD_DATA_4BIT
    00189         // 4 bit read
    00190         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00191         LCD_DELAY;                      // wait
    00192         LCD_DELAY;                      // wait
    00193         data = inb(LCD_DATA_PIN)&0xF0;  // input data, high 4 bits
    00194         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00195         LCD_DELAY;                      // wait
    00196         LCD_DELAY;                      // wait
    00197         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00198         LCD_DELAY;                      // wait
    00199         LCD_DELAY;                      // wait
    00200         data |= inb(LCD_DATA_PIN)>>4;   // input data, low 4 bits
    00201         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00202     #else
    00203         // 8 bit read
    00204         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00205         LCD_DELAY;                      // wait
    00206         LCD_DELAY;                      // wait
    00207         data = inb(LCD_DATA_PIN);       // input data, 8bits
    00208         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00209     #endif
    00210     //  leave data lines in input mode so they can be most easily used for other purposes
    00211 #else
    00212     //sbi(MCUCR, SRW);          // enable RAM waitstate
    00213     lcdBusyWait();              // wait until LCD not busy
    00214     data = *((volatile unsigned char *) (LCD_CTRL_ADDR));
    00215     //cbi(MCUCR, SRW);          // disable RAM waitstate
    00216 #endif
    00217     return data;
    00218 }
    00219
    00220 void lcdDataWrite(u08 data)
    00221 {
    00222 // write a data byte to the display
    00223 #ifdef LCD_PORT_INTERFACE
    00224     lcdBusyWait();                          // wait until LCD not busy
    00225     sbi(LCD_CTRL_PORT, LCD_CTRL_RS);        // set RS to "data"
    00226     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);        // set R/W to "write"
    00227     #ifdef LCD_DATA_4BIT
    00228         // 4 bit write
    00229         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00230         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)|0xF0); // set data I/O lines to output (4bit)
    00231         outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data&0xF0) );  // output data, high 4 bits
    00232         LCD_DELAY;                              // wait
    00233         LCD_DELAY;                              // wait
    00234         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00235         LCD_DELAY;                              // wait
    00236         LCD_DELAY;                              // wait
    00237         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00238         outb(LCD_DATA_POUT, (inb(LCD_DATA_POUT)&0x0F) | (data<<4) );    // output data, low 4 bits
    00239         LCD_DELAY;                              // wait
    00240         LCD_DELAY;                              // wait
    00241         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00242     #else
    00243         // 8 bit write
    00244         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00245         outb(LCD_DATA_DDR, 0xFF);           // set data I/O lines to output (8bit)
    00246         outb(LCD_DATA_POUT, data);          // output data, 8bits
    00247         LCD_DELAY;                              // wait
    00248         LCD_DELAY;                              // wait
    00249         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00250     #endif
    00251     //  leave data lines in input mode so they can be most easily used for other purposes
    00252     #ifdef LCD_DATA_4BIT
    00253         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F);     // set data I/O lines to input (4bit)
    00254         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00255     #else
    00256         outb(LCD_DATA_DDR, 0x00);           // set data I/O lines to input (8bit)
    00257         outb(LCD_DATA_POUT, 0xFF);          // set pull-ups to on (8bit)
    00258     #endif
    00259 #else
    00260     // memory bus write
    00261     //sbi(MCUCR, SRW);          // enable RAM waitstate
    00262     lcdBusyWait();              // wait until LCD not busy
    00263     *((volatile unsigned char *) (LCD_DATA_ADDR)) = data;
    00264     //cbi(MCUCR, SRW);          // disable RAM waitstate
    00265 #endif
    00266 }
    00267
    00268 u08 lcdDataRead(void)
    00269 {
    00270 // read a data byte from the display
    00271     register u08 data;
    00272 #ifdef LCD_PORT_INTERFACE
    00273     lcdBusyWait();              // wait until LCD not busy
    00274     #ifdef LCD_DATA_4BIT
    00275         outb(LCD_DATA_DDR, inb(LCD_DATA_DDR)&0x0F);     // set data I/O lines to input (4bit)
    00276         outb(LCD_DATA_POUT, inb(LCD_DATA_POUT)|0xF0);   // set pull-ups to on (4bit)
    00277     #else
    00278         outb(LCD_DATA_DDR, 0x00);           // set data I/O lines to input (8bit)
    00279         outb(LCD_DATA_POUT, 0xFF);          // set pull-ups to on (8bit)
    00280     #endif
    00281     sbi(LCD_CTRL_PORT, LCD_CTRL_RS);        // set RS to "data"
    00282     sbi(LCD_CTRL_PORT, LCD_CTRL_RW);        // set R/W to "read"
    00283     #ifdef LCD_DATA_4BIT
    00284         // 4 bit read
    00285         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00286         LCD_DELAY;                              // wait
    00287         LCD_DELAY;                              // wait
    00288         data = inb(LCD_DATA_PIN)&0xF0;  // input data, high 4 bits
    00289         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00290         LCD_DELAY;                              // wait
    00291         LCD_DELAY;                              // wait
    00292         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00293         LCD_DELAY;                              // wait
    00294         LCD_DELAY;                              // wait
    00295         data |= inb(LCD_DATA_PIN)>>4;           // input data, low 4 bits
    00296         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00297     #else
    00298         // 8 bit read
    00299         sbi(LCD_CTRL_PORT, LCD_CTRL_E); // set "E" line
    00300         LCD_DELAY;                              // wait
    00301         LCD_DELAY;                              // wait
    00302         data = inb(LCD_DATA_PIN);           // input data, 8bits
    00303         cbi(LCD_CTRL_PORT, LCD_CTRL_E); // clear "E" line
    00304     #endif
    00305     //  leave data lines in input mode so they can be most easily used for other purposes
    00306 #else
    00307     // memory bus read
    00308     //sbi(MCUCR, SRW);          // enable RAM waitstate
    00309     lcdBusyWait();              // wait until LCD not busy
    00310     data = *((volatile unsigned char *) (LCD_DATA_ADDR));
    00311     //cbi(MCUCR, SRW);          // disable RAM waitstate
    00312 #endif
    00313     return data;
    00314 }
    00315
    00316
    00317
    00318 /*************************************************************/
    00319 /********************* PUBLIC FUNCTIONS **********************/
    00320 /*************************************************************/
    00321
    00322 void lcdInit()
    00323 {
    00324     // initialize hardware
    00325     lcdInitHW();
    00326     // LCD function set
    00327     lcdControlWrite(LCD_FUNCTION_DEFAULT);
    00328     // clear LCD
    00329     lcdControlWrite(1<<LCD_CLR);
    00330     delay(60000);   // wait 60ms
    00331     // set entry mode
    00332     lcdControlWrite(1<<LCD_ENTRY_MODE | 1<<LCD_ENTRY_INC);
    00333     // set display to on
    00334     //lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY | 1<<LCD_ON_BLINK);
    00335     lcdControlWrite(1<<LCD_ON_CTRL | 1<<LCD_ON_DISPLAY );
    00336     // move cursor to home
    00337     lcdControlWrite(1<<LCD_HOME);
    00338     // set data address to 0
    00339     lcdControlWrite(1<<LCD_DDRAM | 0x00);
    00340
    00341     // load the first 8 custom characters
    00342     lcdLoadCustomChar((u08*)LcdCustomChar,0,0);
    00343     lcdLoadCustomChar((u08*)LcdCustomChar,1,1);
    00344     lcdLoadCustomChar((u08*)LcdCustomChar,2,2);
    00345     lcdLoadCustomChar((u08*)LcdCustomChar,3,3);
    00346     lcdLoadCustomChar((u08*)LcdCustomChar,4,4);
    00347     lcdLoadCustomChar((u08*)LcdCustomChar,5,5);
    00348     lcdLoadCustomChar((u08*)LcdCustomChar,6,6);
    00349     lcdLoadCustomChar((u08*)LcdCustomChar,7,7);
    00350 }
    00351
    00352 void lcdHome(void)
    00353 {
    00354     // move cursor to home
    00355     lcdControlWrite(1<<LCD_HOME);
    00356 }
    00357
    00358 void lcdClear(void)
    00359 {
    00360     // clear LCD
    00361     lcdControlWrite(1<<LCD_CLR);
    00362 }
    00363
    00364 void lcdGotoXY(u08 x, u08 y)
    00365 {
    00366     register u08 DDRAMAddr;
    00367
    00368     // remap lines into proper order
    00369     switch(y)
    00370     {
    00371     case 0: DDRAMAddr = LCD_LINE0_DDRAMADDR+x; break;
    00372     case 1: DDRAMAddr = LCD_LINE1_DDRAMADDR+x; break;
    00373     case 2: DDRAMAddr = LCD_LINE2_DDRAMADDR+x; break;
    00374     case 3: DDRAMAddr = LCD_LINE3_DDRAMADDR+x; break;
    00375     default: DDRAMAddr = LCD_LINE0_DDRAMADDR+x;
    00376     }
    00377
    00378     // set data address
    00379     lcdControlWrite(1<<LCD_DDRAM | DDRAMAddr);
    00380 }
    00381
    00382 void lcdLoadCustomChar(u08* lcdCustomCharArray, u08 romCharNum, u08 lcdCharNum)
    00383 {
    00384     register u08 i;
    00385     u08 saveDDRAMAddr;
    00386
    00387     // backup the current cursor position
    00388     saveDDRAMAddr = lcdControlRead() & 0x7F;
    00389
    00390     // multiply the character index by 8
    00391     lcdCharNum = (lcdCharNum<<3);   // each character occupies 8 bytes
    00392     romCharNum = (romCharNum<<3);   // each character occupies 8 bytes
    00393
    00394     // copy the 8 bytes into CG (character generator) RAM
    00395     for(i=0; i<8; i++)
    00396     {
    00397         // set CG RAM address
    00398         lcdControlWrite((1<<LCD_CGRAM) | (lcdCharNum+i));
    00399         // write character data
    00400         lcdDataWrite( pgm_read_byte(lcdCustomCharArray+romCharNum+i) );
    00401     }
    00402
    00403     // restore the previous cursor position
    00404     lcdControlWrite(1<<LCD_DDRAM | saveDDRAMAddr);
    00405
    00406 }
    00407
    00408 void lcdPrintData(char* data, u08 nBytes)
    00409 {
    00410     register u08 i;
    00411
    00412     // check to make sure we have a good pointer
    00413     if (!data) return;
    00414
    00415     // print data
    00416     for(i=0; i<nBytes; i++)
    00417     {
    00418         lcdDataWrite(data[i]);
    00419     }
    00420 }
    00421
    00422 void lcdProgressBar(u16 progress, u16 maxprogress, u08 length)
    00423 {
    00424     u08 i;
    00425     u32 pixelprogress;
    00426     u08 c;
    00427
    00428     // draw a progress bar displaying (progress / maxprogress)
    00429     // starting from the current cursor position
    00430     // with a total length of "length" characters
    00431     // ***note, LCD chars 0-5 must be programmed as the bar characters
    00432     // char 0 = empty ... char 5 = full
    00433
    00434     // total pixel length of bargraph equals length*PROGRESSPIXELS_PER_CHAR;
    00435     // pixel length of bar itself is
    00436     pixelprogress = ((progress*(length*PROGRESSPIXELS_PER_CHAR))/maxprogress);
    00437
    00438     // print exactly "length" characters
    00439     for(i=0; i<length; i++)
    00440     {
    00441         // check if this is a full block, or partial or empty
    00442         // (u16) cast is needed to avoid sign comparison warning
    00443         if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)+5) > pixelprogress )
    00444         {
    00445             // this is a partial or empty block
    00446             if( ((i*(u16)PROGRESSPIXELS_PER_CHAR)) > pixelprogress )
    00447             {
    00448                 // this is an empty block
    00449                 // use space character?
    00450                 c = 0;
    00451             }
    00452             else
    00453             {
    00454                 // this is a partial block
    00455                 c = pixelprogress % PROGRESSPIXELS_PER_CHAR;
    00456             }
    00457         }
    00458         else
    00459         {
    00460             // this is a full block
    00461             c = 5;
    00462         }
    00463
    00464         // write character to display
    00465         lcdDataWrite(c);
    00466     }
    00467
    00468 }
    00469