This library is designed to make it easy for anyone to get the Nokia 5110 84x48 display 3.3V module up and running without delay It provides a convenient interface for printing single characters or strings of characters and vertical bar graphs, all at various magnifications. It is free to use and modify. I accept NO liability for malfunctions or damage caused by this software I hope it is useful to the community and am open to suggestions for improvement.

Dependents:   5110_Display

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers N_5110_Display.cpp Source File

N_5110_Display.cpp

00001 #include "mbed.h"
00002 #include "N_5110_Display.h"
00003 #include "N_5110_Font.h"
00004 
00005 
00006 N_5110_Display::N_5110_Display(  PinName _mosi, PinName _miso, PinName _sclk, PinName _dc, PinName _reset, PinName _cs): 
00007                         spi( _mosi, _miso, _sclk ), dc( _dc ), rst( _reset ), cs( _cs )
00008 {
00009     initDisplay();
00010 }
00011 
00012 //----------------------------------------------------------------------
00013 
00014 void N_5110_Display::initDisplay()
00015 {
00016     rst=0;                  //display reset
00017     cs=1;                   //Chip Disabled
00018     
00019     wait(0.5);              //allow chip to settle for half second
00020         
00021     spi.format(8,3);        //set the SPI interface perameters for the Display
00022     spi.frequency(1000000); //1 MHz clock speed
00023     PixX = 0;               //zero the x, y variables
00024     CharX = 0;
00025     CharY = 0;
00026     
00027     rst=1;                  //display reset done
00028     
00029     dc=0;                   //select Control mode
00030     cs=0;                   //Chip Enabled
00031         
00032     spi.write(0x21);        //Function Set (Extenden Instructions)
00033     spi.write(0x04);        //set 'Temp Coef' value
00034     spi.write(0x13);        //set 'Bias' value
00035     spi.write(0xBF);        //set 'V_op' value
00036     spi.write(0x22);        //Function Set (Basic Instructions)
00037     spi.write(0x0C);        //Display Control
00038         
00039     clrDisp();              //Clear the Display
00040 }
00041 
00042 //----------------------------------------------------------------------
00043 
00044 void N_5110_Display::clrDisp()
00045 {
00046     long x;
00047 
00048     dc=1;                   //select Data mode
00049     cs=0;                   //Chip Enabled
00050     
00051     for (x=0; x<504; x++)   //Clear the display memory
00052     {
00053         spi.write( 0 );
00054     }
00055     
00056     cs=1;                   //Chip Disabled
00057 }
00058 
00059 //----------------------------------------------------------------------
00060 
00061 void N_5110_Display::setDispPos(int DispX, int DispY)
00062 {
00063     unsigned char Xtemp, Ytemp;
00064 
00065     Xtemp = DispX | 0x80;       //add in the column select BIT
00066     Ytemp = (DispY & 0x07) | 0x40;
00067     
00068     dc=0;                       //select Control mode
00069     cs=0;                       //Chip Enabled
00070         
00071     spi.write(Xtemp);           //Set the column value
00072     spi.write(Ytemp);           //set the row value
00073     
00074     cs=1;                       //Chip Disabled
00075 }
00076 
00077 //----------------------------------------------------------------------
00078 
00079 int N_5110_Display::setCharPos(int x, int y)
00080 //x is the character column number 0 to 13. y is the character row number 0 to 5.
00081 //The column is multiplied by 6 to get the display column value, as each 5 x 8 char occupies a 6 x 8 space
00082 {
00083     unsigned char Xacc;
00084 
00085     if (x>13 || y>5) return -1; //check magnitude of co-ordinates and store
00086     
00087     Xacc = x<<2;                //multiply the char column (x) by 6 to get the Display column
00088     Xacc = Xacc + (x<<1);
00089 
00090     PixX = Xacc;
00091     CharX = x;
00092     CharY = y;
00093 
00094     setDispPos(PixX, CharY);
00095     
00096     return 0;
00097 }
00098 
00099 //----------------------------------------------------------------------
00100 
00101 void N_5110_Display::clrMagArray( unsigned char Xmag, unsigned char Ymag, bool FullWidth )
00102 {
00103     unsigned char magDataX, magDataY, width;
00104 
00105     width = FullWidth?6:5;
00106     
00107     for (magDataX=0; magDataX<Xmag*width; magDataX++)   //clear the magnification array
00108     {
00109         for (magDataY=0; magDataY<Ymag; magDataY++)
00110         {
00111             magData[magDataX][magDataY] = 0;
00112         }
00113     }
00114 }
00115 
00116 //----------------------------------------------------------------------
00117 
00118 void N_5110_Display::smoothEdges( unsigned char Xmag, unsigned char Ymag )
00119 //Quick and dirty character smoothing but only if there is magnification in both X and Y directions. Intended to improve readability
00120 //at higher magnifications but doesn't realy smooth very well.
00121 //I'm sure that someone can come up with a better solution than this, but I didn't have time to code an Interpolation algorithm or
00122 //creata vectored drawing system.
00123 {
00124     unsigned char Xpos, Ypos, tempByte1, tempByte2, tempByte3, and1, and2, totaland, repeater;
00125     
00126     if (Xmag<2 || Ymag<2) return;                               //check for enough magnification to work with
00127     
00128     for (repeater=0; repeater<(Xmag*Ymag)/(Xmag+Ymag); repeater++)  //calc sensible number of itterations
00129     {
00130     
00131         for (Ypos=0; Ypos<Ymag; Ypos++)
00132         {
00133             for (Xpos=0; Xpos<Xmag*6-1; Xpos++)                     //scan left to right
00134             {
00135                 tempByte1 = magData[Xpos+1][Ypos];                  //get the following byte
00136                 tempByte2 = magData[Xpos][Ypos];                    //get the current byte
00137                 tempByte3 = tempByte1 ^ tempByte2;                  //check for a change
00138             
00139                 if (tempByte3 != 0)
00140                 {
00141                     tempByte2 >>= 1;                                //shift up (Right towards LSB)
00142                 
00143                     if (Ypos+1 <= Ymag)
00144                     {
00145                         tempByte3 = magData[Xpos][Ypos+1];          //get missing BIT from byte below
00146                         tempByte3 <<= 7;
00147                         tempByte2 |= tempByte3;
00148                     }
00149                 
00150                     and1 = tempByte1 & tempByte2;
00151                         
00152                     tempByte2 = magData[Xpos][Ypos];                //re-load the current byte
00153                     tempByte2 <<= 1;                                //shift down (Left towards the MSB)
00154            
00155                     if (Ypos > 0)
00156                     {
00157                         tempByte3 = magData[Xpos][Ypos-1];          //get missing BIT from byte above
00158                         tempByte3 >>= 7;
00159                         tempByte2 |= tempByte3;
00160                     }
00161                 
00162                     and2 = tempByte1 & tempByte2;
00163             
00164                     totaland = (and1 | and2);
00165                     magData[Xpos][Ypos] |= totaland;                //incorpoate the extra bits into the magData                }
00166                 }
00167             }
00168         
00169             for (Xpos=Xmag*6; Xpos>0; Xpos--)                       //scan right to left
00170             {
00171                 tempByte1 = magData[Xpos-2][Ypos];                  //get following byte
00172                 tempByte2 = magData[Xpos-1][Ypos];                  //get the current byte
00173                 tempByte3 = tempByte1 ^ tempByte2;                  //check for change
00174                 
00175                 if (tempByte3 != 0)
00176                 {
00177                     tempByte2 >>= 1;                                //shift up (Right towards the LSB)
00178 
00179                     if (Ypos+1 <= Ymag)
00180                     {
00181                         tempByte3 = magData[Xpos-1][Ypos+1];        //get missing BIT from byte below
00182                         tempByte3 <<= 7;
00183                         tempByte2 |= tempByte3;
00184                     }
00185                 
00186                     and1 = tempByte1 & tempByte2;
00187             
00188                     tempByte2 = magData[Xpos-1][Ypos];              //re-load the current byte
00189                     tempByte2 <<= 1;                                //shift down (Left towards the MSB)
00190                 
00191                     if (Ypos > 0)
00192                     {
00193                         tempByte3 = magData[Xpos-1][Ypos-1];        //get missing Bits from byte above
00194                         tempByte3 >>= 7;
00195                         tempByte2 |= tempByte3;
00196                     }
00197                     and2 = tempByte1 & tempByte2;
00198             
00199                     totaland = (and1 | and2);
00200                     magData[Xpos - 1][Ypos] |= totaland;
00201                 }
00202             }
00203         }
00204     }
00205 }
00206 
00207 //----------------------------------------------------------------------
00208 
00209 void N_5110_Display::magChar( unsigned char c, unsigned char Xmag, unsigned char Ymag )
00210 //Expand the basic 5 x 8 char def to the required X and y magnification using an buffer Array
00211 {
00212     unsigned char tempPat, count, Idx, Xexp, Yexp, bitCounter, bitAcc, srcBit, magDataX, magDataY;
00213     
00214     clrMagArray( Xmag, Ymag, false );
00215     
00216     Idx = c - 32;                               //shift the ASCII code so it starts from zero
00217     
00218     magDataX = 0;
00219     
00220     for (count=0; count<5; count++)             //5 bytes per char def
00221     {
00222         bitCounter = Ymag/2;                    //offset the image Y position by half the Y magnification factor
00223         bitAcc = 0;
00224         magDataY = 0;
00225         tempPat = font_data[Idx][count];        //get column Bit pattern to expand in the y direction by bit replication
00226                                                 //LSB is top Bit position
00227         
00228         for (srcBit=0; srcBit<8; srcBit++)      //process each of the 8 bits in the source byte
00229         {
00230             for (Yexp=0; Yexp<Ymag; Yexp++)     //each Bit in each def byte is duplicated Ymag times in the Y direction
00231             {
00232                 bitAcc >>= 1;                   //shift the accumulator 1 bit to the left
00233                 
00234                 if ((tempPat & 1) > 0)
00235                 {
00236                     bitAcc |= 0x80;             //set msb
00237                 } else {
00238                     bitAcc &= 0x7F;             //clear msb
00239                 }
00240                 
00241                 bitCounter++;
00242                 
00243                 if (bitCounter > 7)             //if the bit accumulator is full then store it and clear it to continue
00244                 {
00245                     for (Xexp=0; Xexp<Xmag; Xexp++) //do the X magnification while storingthe Bit Accumulator
00246                     {
00247                         magData[magDataX + Xexp][magDataY] = bitAcc;
00248                     }
00249                     
00250                     bitAcc = 0;
00251                     magDataY++;
00252                     bitCounter = 0;
00253                 }
00254             }
00255             tempPat>>=1;
00256         }
00257         magDataX += Xmag;
00258     }
00259     smoothEdges( Xmag, Ymag );
00260 }
00261 
00262 //----------------------------------------------------------------------
00263 
00264 int N_5110_Display::outputMagData (unsigned char Xmag, unsigned char Ymag, bool FullWidth )
00265 {
00266     unsigned char XpixTemp, mx, my, width;
00267     
00268     XpixTemp = PixX;
00269     width = FullWidth?6:5;
00270     
00271     if (FullWidth == false)
00272     {
00273         for (mx=0; mx<Xmag/2; mx++)
00274         {
00275             dc=1;                       //select Data mode
00276             cs=0;                       //Chip Enabled
00277     
00278             for (my=0; my<Ymag; my++)
00279             {
00280                 spi.write( 0 );
00281             }
00282         
00283             cs=1;                       //Chip Disabled
00284     
00285             XpixTemp += 1;
00286             setDispPos(XpixTemp, CharY);
00287         }
00288     }
00289     
00290     for (mx=0; mx<Xmag*width; mx++)
00291     {
00292         dc=1;                       //select Data mode
00293         cs=0;                       //Chip Enabled
00294         
00295         for (my=0; my<Ymag; my++)
00296         {
00297             spi.write( magData[mx][my] );
00298         }
00299         
00300         cs=1;                       //Chip Disabled
00301         
00302         XpixTemp += 1;
00303         setDispPos( XpixTemp, CharY );
00304     }
00305     
00306     if (FullWidth == false)
00307     {
00308         for (mx=0; mx<(Xmag+1)/2; mx++)
00309         {
00310             dc=1;                       //select Data mode
00311             cs=0;                       //Chip Enabled
00312     
00313             for (my=0; my<Ymag; my++)
00314             {
00315                 spi.write( 0 );
00316             }
00317         
00318             cs=1;                       //Chip Disabled
00319     
00320             XpixTemp += 1;
00321             setDispPos(XpixTemp, CharY);
00322         }
00323     }
00324     
00325     PixX = XpixTemp;
00326     CharX += Xmag;
00327     
00328     return 0;
00329 }
00330 
00331 //----------------------------------------------------------------------
00332 
00333 int N_5110_Display::print1char(unsigned char c, unsigned char Xmag, unsigned char Ymag)
00334 {    
00335     if (c<32 | c>127) return -1;    //Exit if char is out of range
00336     
00337     if (Xmag<1) Xmag=1;             //Clamp the magnification values
00338     if (Ymag<1) Ymag=1;
00339     if (Xmag>6) Xmag=6;
00340     if (Ymag>6) Ymag=6;
00341         
00342     magChar( c, Xmag, Ymag );
00343 
00344     outputMagData( Xmag, Ymag, false );
00345     
00346     return 0;
00347 }
00348 
00349 //----------------------------------------------------------------------
00350 
00351 void N_5110_Display::printString( char * str2prt, unsigned char Xmag, unsigned char Ymag)
00352 {
00353     unsigned char c;
00354     
00355     for (c=0; c<strlen(str2prt); c++)
00356     {
00357         print1char( str2prt[c], Xmag, Ymag );
00358     }
00359 }
00360 
00361 //----------------------------------------------------------------------
00362 
00363 void N_5110_Display::VertBarGraph( int Percentage, unsigned char Xmag, unsigned char Ymag )
00364 {
00365     unsigned char Xidx, Yidx, activeHeight, wholeBytes, pixRemaining, mask, count, dither;
00366     
00367     if (Xmag<1) Xmag=1;                                     //Clamp the magnification values
00368     if (Ymag<1) Ymag=1;
00369     if (Xmag>6) Xmag=6;
00370     if (Ymag>6) Ymag=6;
00371     
00372     clrMagArray( Xmag, Ymag, true );
00373     
00374     activeHeight = 8 * Ymag * Percentage /100;              //Calc the magnitude of the Bar
00375     wholeBytes = activeHeight / 8;
00376     pixRemaining = activeHeight % 8;
00377     
00378     mask = 0xFF;
00379     for(count=0; count<8-pixRemaining; count++)             //creat the mask for pixRemaining
00380     {
00381         mask <<= 1;
00382     }
00383     
00384     for (Xidx=0; Xidx<6*Xmag-1; Xidx++)                     //step along the pixel columns
00385     {
00386         dither = Xidx&1?0x55:0xAA;                          //Dither value alternates for each odd, ecen pixel column
00387     
00388         for (Yidx=0; Yidx<Ymag; Yidx++)                     //step through each row
00389         {
00390             if (Yidx == Ymag - wholeBytes - 1)              //do the remainder
00391             {
00392                 magData[Xidx][Yidx] |= dither;
00393                 magData[Xidx][Yidx] &= mask;
00394             }
00395             else if (Yidx >= Ymag-wholeBytes)                //else do the whole bytes
00396             {
00397                 magData[Xidx][Yidx] |= dither;
00398             }
00399                                                             //now add the border
00400             if (Xidx==0 || Xidx==6*Xmag-2)                  //Left & Right
00401             {
00402                 magData[Xidx][Yidx] |= 0xFF;
00403             }
00404             
00405             if (Yidx==0)                                    //Top
00406             {
00407                 magData[Xidx][Yidx] |= 0x01;
00408             }
00409             
00410             if (Yidx==Ymag-1)                               //Bottom
00411             {
00412                 magData[Xidx][Yidx] |= 0x40;
00413                 magData[Xidx][Yidx] &= 0x7F;
00414             }
00415         }
00416     }
00417     
00418     outputMagData( Xmag, Ymag, true );
00419 }
00420