Library for Nuelectronics Nokia 3310/5110 LCD Display and joystick.

Dependents:   LEDFun NetTester

Fork of N3310LCD by Andrew Lindsay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers N3310LCD.cpp Source File

N3310LCD.cpp

00001 /*
00002 * N3310LCD. A program to interface mbed with the nuelectronics
00003 * Nokia 3310 LCD shield from www.nuelectronics.com. Ported from
00004 * the nuelectronics Arduino code.
00005 *
00006 * Copyright (C) <2009> Petras Saduikis <petras@petras.co.uk>
00007 *
00008 * Converted to a mbed library by Andrew D. Lindsay
00009 *
00010 * This file is part of N3310LCD.
00011 *
00012 * N3310LCD is free software: you can redistribute it and/or modify
00013 * it under the terms of the GNU General Public License as published by
00014 * the Free Software Foundation, either version 3 of the License, or
00015 * (at your option) any later version.
00016 *
00017 * N3310LCD is distributed in the hope that it will be useful,
00018 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 * GNU General Public License for more details.
00021 *
00022 * You should have received a copy of the GNU General Public License
00023 * along with N3310LCD.  If not, see <http://www.gnu.org/licenses/>.
00024 */
00025 
00026 #include "N3310LCD.h"
00027 #include "N3310Fonts.h"
00028 #include "variables.h"
00029 
00030 int contrast = 0xB5;
00031 
00032 static unsigned char lcd_buffer[LCDROWMAX][LCDCOLMAX];
00033 // current cursor postition
00034 static unsigned char cursor_row = 0; /* 0-5 */
00035 static unsigned char cursor_col = 0; /* 0-83 */
00036 unsigned char *fontStart;  // Start of font data
00037 int8_t fontWidth;       // Font width
00038 int8_t fontHeight;      // Font height
00039 int16_t fontStartChar;   // Start, usually 32
00040 int16_t fontEndChar;     // End character, usually 127 or 128
00041 
00042 N3310LCD::N3310LCD (PinName mosi, PinName miso, PinName sck,
00043                     PinName ce, PinName dat_cmd, PinName lcd_rst, PinName bl_on) :
00044     lcdPort(mosi, miso, sck),
00045     ceWire(ce), dcWire(dat_cmd), rstWire(lcd_rst), blWire(bl_on) {
00046 }
00047 
00048 void N3310LCD::init()
00049 {
00050     // use default SPI format
00051     lcdPort.format(8,0);
00052     lcdPort.frequency(8000000);     // Lets try 8MHz
00053 
00054     // lcd reset
00055     wait_ms(1);
00056     rstWire = 0;
00057     wait_ms(1);
00058     rstWire = 1;
00059 
00060     writeCommand(0x21);     // LCD Extended Commands
00061     writeCommand(contrast);     // Set LCD Vop (Contrast)
00062     writeCommand(0x06);     // Set temp coefficient
00063     writeCommand(0x13);     // LCD bias mode1:48
00064     writeCommand(0x20);     // LCD Standard Commands, Horizontal addressing mode
00065     writeCommand(0x0c);     // LCD in normal mode
00066     cls();
00067     setFont( FONT_5x7 );
00068 
00069 
00070 }
00071 
00072 void N3310LCD::setFont(BYTE font )
00073 {
00074 
00075     switch( font ) {
00076         case FONT_6x8:
00077             fontWidth = 6;
00078             fontHeight = 8;
00079             fontStartChar = 32;
00080             fontEndChar = 128;
00081             fontStart = font6_8;
00082             break;
00083 
00084         default:
00085             fontWidth = 5;
00086             fontHeight = 7;
00087             fontStartChar = 32;
00088             fontEndChar = 128;
00089             fontStart = font5_7;
00090             break;
00091     }
00092 }
00093 
00094 void N3310LCD::cls()
00095 {
00096     writeCommand(0x40);      // column
00097     writeCommand(0x80);      // row
00098     for(int i=0; i< LCDROWMAX; i++) {
00099         for(int j=0; j< LCDCOLMAX; j++) {
00100             writeData( 0x00 );
00101             lcd_buffer[i][j] = 0x00;
00102         }
00103     }
00104 }
00105 
00106 void N3310LCD::backlight(eBacklight state)
00107 {
00108     // switch off/on back light
00109     blWire = state;
00110 }
00111 
00112 void N3310LCD::writeCommand(BYTE data)
00113 {
00114     // bring CS low for write
00115     ceWire = 0;
00116     dcWire = 0;
00117 
00118     lcdPort.write(data);
00119 
00120     // write finished
00121     ceWire = 1;
00122 }
00123 
00124 void N3310LCD::writeData(BYTE data)
00125 {
00126     // bring CS low for write
00127     ceWire = 0;
00128     dcWire = 1;
00129 
00130     lcdPort.write(data);
00131 
00132     // write finished
00133     ceWire = 1;
00134 }
00135 
00136 void N3310LCD::locate(BYTE xPos, BYTE yPos)
00137 {
00138     writeCommand(0x40 | yPos);      // column
00139     writeCommand(0x80 | xPos);      // row
00140     cursor_row = yPos;
00141     cursor_col = xPos;
00142 }
00143 
00144 void N3310LCD::drawBitmap(BYTE xPos, BYTE yPos, BYTE* bitmap, BYTE bmpXSize, BYTE bmpYSize)
00145 {
00146     BYTE row;
00147 
00148     if (0 == bmpYSize % 8)
00149         row = bmpYSize/8;
00150     else
00151         row = bmpYSize/8 + 1;
00152 
00153     for (BYTE n = 0; n < row; n++) {
00154         locate(xPos, yPos);
00155         for(BYTE i = 0; i < bmpXSize; i++) {
00156             writeData(bitmap[i + (n * bmpXSize)]);
00157         }
00158         yPos++;
00159     }
00160 }
00161 
00162 /*
00163  * Name         : clearBitmap
00164  * Description  : Clear an area of the screen, usually to blank out a
00165  *        previously drawn image or part of image.
00166  * Argument(s)  : x, y - Position on screen, x 0-83, y 1-6
00167  *                size_x,size_y - Size of the image in pixels,
00168  *                size_y is multiple of 8
00169  * Return value : none
00170  */
00171 void N3310LCD::clearBitmap( unsigned char x,unsigned char y,
00172                             unsigned char size_x,unsigned char size_y)
00173 {
00174     unsigned int i,n;
00175     unsigned char row;
00176 
00177     row = (size_y % 8 == 0 ) ? size_y / 8 : size_y / 8 + 1;
00178 
00179     for (n=0; n<row; n++) {
00180         locate(x,y);
00181         for(i=0; i<size_x; i++) {
00182             writeData( 0x00 );
00183         }
00184         y++;
00185     }
00186 }
00187 
00188 void N3310LCD::writeString(BYTE xPos, BYTE yPos, char* string, eDisplayMode mode)
00189 {
00190     locate(xPos, yPos);
00191 
00192     while (*string) {
00193         writeChar(*string++, mode);
00194     }
00195 }
00196 
00197 void N3310LCD::writeStringBig(BYTE xPos, BYTE yPos, char* string, eDisplayMode mode)
00198 {
00199     while (*string) {
00200         writeCharBig(xPos, yPos, *string , mode);
00201 
00202         if('.' == *string++)
00203             xPos += 5;
00204         else
00205             xPos += 12;
00206     }
00207 }
00208 
00209 void N3310LCD::writeChar(BYTE ch, eDisplayMode mode)
00210 {
00211     ch -= fontStartChar;
00212 
00213     if (cursor_col > LCDCOLMAX - (fontWidth+1)) cursor_col = LCDCOLMAX - (fontWidth+1); // ensure space is available for the character
00214     if (cursor_row > LCDROWMAX - 1) cursor_row = LCDROWMAX - 1; // ensure space is available for the character
00215     lcd_buffer[cursor_row][cursor_col] = 0x00;
00216     for(int8_t j=0; j< fontHeight; j++) {
00217         lcd_buffer[cursor_row][cursor_col + j] =  fontStart[(ch)*fontWidth + j];
00218     }
00219 
00220     lcd_buffer[cursor_row][cursor_col + fontWidth] = 0x00;
00221 
00222     for(int8_t j=0; j< (fontWidth+1); j++) {
00223         if( mode == NORMAL )
00224             writeData(lcd_buffer[cursor_row][cursor_col++]);
00225         else
00226             writeData(lcd_buffer[cursor_row][cursor_col++] ^ 0xff);
00227         if (cursor_col >= LCDCOLMAX) {
00228             cursor_col=0;
00229             cursor_row++;
00230             if (cursor_row >= LCDROWMAX) cursor_row=0;
00231         }
00232     }
00233 }
00234 
00235 int  N3310LCD::_putc(int c) {
00236   writeChar(c, NORMAL);
00237   return c;
00238 }
00239 int N3310LCD::_getc() {
00240     return -1;
00241 }
00242 
00243 void N3310LCD::writeCharBig(BYTE xPos, BYTE yPos, BYTE ch, eDisplayMode mode)
00244 {
00245     BYTE sendByte;
00246     int8_t colsUsed = 12;
00247     unsigned char* pFont = (unsigned char *) big_number;
00248 
00249 
00250     if(ch == '.') {
00251         ch = 10;
00252         colsUsed=5;
00253     } else if (ch == '+')
00254         ch = 11;
00255     else if (ch == '-')
00256         ch = 12;
00257     else if (ch == ':')
00258         ch = 13;
00259     else if (ch == '/')
00260         ch = 14;
00261     else
00262         ch = ch & 0x0f;
00263 
00264     /*
00265         for(BYTE i = 0; i < 3; i++) {
00266             locate(xPos, yPos + i);
00267 
00268             for(BYTE j = 0; j < 16; j++) {
00269                 sendByte =  *(pFont + ch*48 + i*16 + j);
00270                 writeData((mode == NORMAL)? sendByte : (sendByte^0xff));
00271             }
00272         }
00273     */
00274     if (xPos > LCDCOLMAX - colsUsed) xPos = LCDCOLMAX - colsUsed ; // ensure space is available for the character
00275     if (yPos > LCDROWMAX - 3) yPos = LCDROWMAX - 3 ; // ensure space is available for the character
00276 
00277     for(int8_t i=0; i<3; i++) {
00278         locate( xPos, yPos + i);
00279 
00280         for(int8_t j=0; j<colsUsed; j++) {
00281             sendByte =  *(pFont + ch*48 + i*16 + j);
00282             lcd_buffer[cursor_row][cursor_col + j] = (mode == NORMAL)? sendByte : (sendByte^0xff);
00283             writeData( lcd_buffer[cursor_row][cursor_col + j] );
00284         }
00285     }
00286 }
00287 
00288 /*
00289  * Name         : setPixel
00290  * Description  : Set a single pixel either on or off, update display buffer.
00291  * Argument(s)  : x,y - position, x = 0-83, y = 0-6
00292  *                c - colour, either PIXEL_ON, PIXEL_OFF or PIXEL_XOR
00293  * Return value : none
00294  */
00295 void N3310LCD::setPixel( unsigned char x, unsigned char y, unsigned char c )
00296 {
00297     unsigned char value;
00298     unsigned char row;
00299 
00300 //    if( x < 0 || x >= LCDCOLMAX || y < 0 || y >= LCDPIXELROWMAX ) return;
00301     if( x >= LCDCOLMAX || y >= LCDPIXELROWMAX ) return;
00302 
00303     row = y / 8;
00304 
00305     value = lcd_buffer[row][x];
00306     if( c == PIXEL_ON ) {
00307         value |= (1 << (y % 8));
00308     } else if( c == PIXEL_XOR ) {
00309         value ^= (1 << (y % 8));
00310     } else {
00311         value &= ~(1 << (y % 8));
00312     }
00313 
00314     lcd_buffer[row][x] = value;
00315     locate (x,row);
00316     writeData(value);
00317 }
00318 
00319 
00320 /*
00321  * Name         : drawLine
00322  * Description  : Draws a line between two points on the display.
00323  * Argument(s)  : x1, y1 - Absolute pixel coordinates for line origin.
00324  *                x2, y2 - Absolute pixel coordinates for line end.
00325  *                c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR
00326  * Return value : none
00327  */
00328 void N3310LCD::drawLine(unsigned char x1, unsigned char y1,
00329                         unsigned char x2, unsigned char y2, unsigned char c)
00330 {
00331     int dx, dy, stepx, stepy, fraction;
00332 
00333     /* Calculate differential form */
00334     /* dy   y2 - y1 */
00335     /* -- = ------- */
00336     /* dx   x2 - x1 */
00337 
00338     /* Take differences */
00339     dy = y2 - y1;
00340     dx = x2 - x1;
00341 
00342     /* dy is negative */
00343     if ( dy < 0 ) {
00344         dy    = -dy;
00345         stepy = -1;
00346     } else {
00347         stepy = 1;
00348     }
00349 
00350     /* dx is negative */
00351     if ( dx < 0 ) {
00352         dx    = -dx;
00353         stepx = -1;
00354     } else {
00355         stepx = 1;
00356     }
00357 
00358     dx <<= 1;
00359     dy <<= 1;
00360 
00361     /* Draw initial position */
00362     setPixel( x1, y1, c );
00363 
00364     /* Draw next positions until end */
00365     if ( dx > dy ) {
00366         /* Take fraction */
00367         fraction = dy - ( dx >> 1);
00368         while ( x1 != x2 ) {
00369             if ( fraction >= 0 ) {
00370                 y1 += stepy;
00371                 fraction -= dx;
00372             }
00373             x1 += stepx;
00374             fraction += dy;
00375 
00376             /* Draw calculated point */
00377             setPixel( x1, y1, c );
00378         }
00379     } else {
00380         /* Take fraction */
00381         fraction = dx - ( dy >> 1);
00382         while ( y1 != y2 ) {
00383             if ( fraction >= 0 ) {
00384                 x1 += stepx;
00385                 fraction -= dy;
00386             }
00387             y1 += stepy;
00388             fraction += dx;
00389 
00390             /* Draw calculated point */
00391             setPixel( x1, y1, c );
00392         }
00393     }
00394 }
00395 
00396 
00397 /*
00398  * Name         : drawRectangle
00399  * Description  : Draw a rectangle given to top left and bottom right points
00400  * Argument(s)  : x1, y1 - Absolute pixel coordinates for top left corner
00401  *                x2, y2 - Absolute pixel coordinates for bottom right corner
00402  *                c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR
00403  * Return value : none
00404  */
00405 void N3310LCD::drawRectangle(unsigned char x1, unsigned char y1,
00406                              unsigned char x2, unsigned char y2, unsigned char c)
00407 {
00408     drawLine( x1, y1, x2, y1, c );
00409     drawLine( x1, y1, x1, y2, c );
00410     drawLine( x1, y2, x2, y2, c );
00411     drawLine( x2, y1, x2, y2, c );
00412 }
00413 
00414 
00415 /*
00416  * Name         : drawFilledRectangle
00417  * Description  : Draw a filled rectangle given to top left and bottom right points
00418  *        just simply draws horizontal lines where the rectangle would be
00419  * Argument(s)  : x1, y1 - Absolute pixel coordinates for top left corner
00420  *                x2, y2 - Absolute pixel coordinates for bottom right corner
00421  *                c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR
00422  * Return value : none
00423  */
00424 void N3310LCD::drawFilledRectangle(unsigned char x1, unsigned char y1,
00425                                    unsigned char x2, unsigned char y2, unsigned char c)
00426 {
00427     for(int i=y1; i <= y2; i++ ) {
00428         drawLine( x1, i, x2, i, c );
00429     }
00430 }
00431 
00432 
00433 /*
00434  * Name         : drawCircle
00435  * Description  : Draw a circle using Bresenham's algorithm.
00436  *        Some small circles will look like squares!!
00437  * Argument(s)  : xc, yc - Centre of circle
00438  *        r - Radius
00439  *        c - either PIXEL_ON, PIXEL_OFF or PIXEL_XOR
00440  * Return value : None
00441  */
00442 void N3310LCD::drawCircle(unsigned char xc, unsigned char yc,
00443                           unsigned char r, unsigned char c)
00444 {
00445     int x=0;
00446     int y=r;
00447     int p=3-(2*r);
00448 
00449     setPixel( (uint8_t)(xc+x),(uint8_t)(yc-y), c);
00450 
00451     for(x=0; x<=y; x++) {
00452         if (p<0) {
00453             y=y;
00454             p=(p+(4*x)+6);
00455         } else {
00456             y=y-1;
00457             p=p+((4*(x-y)+10));
00458         }
00459 
00460         setPixel((uint8_t)(xc+x),(uint8_t)(yc-y), c);
00461         setPixel((uint8_t)(xc-x),(uint8_t)(yc-y), c);
00462         setPixel((uint8_t)(xc+x),(uint8_t)(yc+y), c);
00463         setPixel((uint8_t)(xc-x),(uint8_t)(yc+y), c);
00464         setPixel((uint8_t)(xc+y),(uint8_t)(yc-x), c);
00465         setPixel((uint8_t)(xc-y),(uint8_t)(yc-x), c);
00466         setPixel((uint8_t)(xc+y),(uint8_t)(yc+x), c);
00467         setPixel((uint8_t)(xc-y),(uint8_t)(yc+x), c);
00468     }
00469 }