N5110 Library for "Racing Cars" Game

Dependents:   RacingCarsGame

Fork of N5110 by Craig Evans

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers N5110.cpp Source File

N5110.cpp

Go to the documentation of this file.
00001 /**
00002 @file N5110.cpp
00003 
00004 @brief Member functions implementations
00005 
00006 */
00007 #include "mbed.h"
00008 #include "N5110.h"
00009 
00010 
00011 N5110::N5110(PinName pwrPin, PinName scePin, PinName rstPin, PinName dcPin, PinName mosiPin, PinName sclkPin, PinName ledPin)
00012 {
00013 
00014     spi = new SPI(mosiPin,NC,sclkPin); // create new SPI instance and initialise
00015     initSPI();
00016 
00017     // set up pins as required
00018     led = new PwmOut(ledPin);
00019     pwr = new DigitalOut(pwrPin);
00020     sce = new DigitalOut(scePin);
00021     rst = new DigitalOut(rstPin);
00022     dc = new DigitalOut(dcPin);
00023 
00024 }
00025 
00026 // initialise function - powers up and sends the initialisation commands
00027 void N5110::init()
00028 {
00029     turnOn();     // power up
00030     wait_ms(10);  // small delay seems to prevent spurious pixels during mbed reset
00031     reset();      // reset LCD - must be done within 100 ms
00032 
00033     // function set - extended
00034     sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
00035     // Don't completely understand these parameters - they seem to work as they are
00036     // Consult the datasheet if you need to change them
00037     sendCommand(CMD_VOP_7V38);    // operating voltage - these values are from Chris Yan's Library
00038     sendCommand(CMD_TC_TEMP_2);   // temperature control
00039     sendCommand(CMD_BI_MUX_48);   // bias
00040 
00041     // function set - basic
00042     sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
00043     normalMode();  // normal video mode by default
00044     sendCommand(CMD_DC_NORMAL_MODE);  // black on white
00045 
00046     // RAM is undefined at power-up so clear
00047     clearRAM();
00048 
00049 }
00050 
00051 // sets normal video mode (black on white)
00052 void N5110::normalMode()
00053 {
00054     sendCommand(CMD_DC_NORMAL_MODE);
00055 
00056 }
00057 
00058 // sets normal video mode (white on black)
00059 void N5110::inverseMode()
00060 {
00061     sendCommand(CMD_DC_INVERT_VIDEO);
00062 }
00063 
00064 // function to power up the LCD and backlight
00065 void N5110::turnOn()
00066 {
00067     // set brightness of LED - 0.0 to 1.0 - default is 50%
00068     setBrightness(0.5);
00069     pwr->write(1);  // apply power
00070 }
00071 
00072 // function to power down LCD
00073 void N5110::turnOff()
00074 {
00075     setBrightness(0.0);  // turn backlight off
00076     clearRAM();   // clear RAM to ensure specified current consumption
00077     // send command to ensure we are in basic mode
00078     sendCommand(0x20 | CMD_FS_ACTIVE_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_BASIC_MODE);
00079     // clear the display
00080     sendCommand(CMD_DC_CLEAR_DISPLAY);
00081     // enter the extended mode and power down
00082     sendCommand(0x20 | CMD_FS_POWER_DOWN_MODE | CMD_FS_HORIZONTAL_MODE | CMD_FS_EXTENDED_MODE);
00083     // small delay and then turn off the power pin
00084     wait_ms(10);
00085     pwr->write(0);
00086 
00087 }
00088 
00089 // function to change LED backlight brightness
00090 void N5110::setBrightness(float brightness)
00091 {
00092     // check whether brightness is within range
00093     if (brightness < 0.0)
00094         brightness = 0.0;
00095     if (brightness > 1.0)
00096         brightness = 1.0;
00097     // set PWM duty cycle
00098     led->write(brightness);
00099 }
00100 
00101 
00102 // pulse the active low reset line
00103 void N5110::reset()
00104 {
00105     rst->write(0);  // reset the LCD
00106     rst->write(1);
00107 }
00108 
00109 // function to initialise SPI peripheral
00110 void N5110::initSPI()
00111 {
00112     spi->format(8,1);    // 8 bits, Mode 1 - polarity 0, phase 1 - base value of clock is 0, data captured on falling edge/propagated on rising edge
00113     spi->frequency(4000000);  // maximum of screen is 4 MHz
00114 }
00115 
00116 // send a command to the display
00117 void N5110::sendCommand(unsigned char command)
00118 {
00119     dc->write(0);  // set DC low for command
00120     sce->write(0); // set CE low to begin frame
00121     spi->write(command);  // send command
00122     dc->write(1);  // turn back to data by default
00123     sce->write(1); // set CE high to end frame (expected for transmission of single byte)
00124 
00125 }
00126 
00127 // send data to the display at the current XY address
00128 // dc is set to 1 (i.e. data) after sending a command and so should
00129 // be the default mode.
00130 void N5110::sendData(unsigned char data)
00131 {
00132     sce->write(0);   // set CE low to begin frame
00133     spi->write(data);
00134     sce->write(1);  // set CE high to end frame (expected for transmission of single byte)
00135 }
00136 
00137 // this function writes 0 to the 504 bytes to clear the RAM
00138 void N5110::clearRAM()
00139 {
00140     int i;
00141     sce->write(0);  //set CE low to begin frame
00142     for(i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes
00143         spi->write(0x00);  // send 0's
00144     }
00145     sce->write(1); // set CE high to end frame
00146 
00147 }
00148 
00149 // function to set the XY address in RAM for subsequenct data write
00150 void N5110::setXYAddress(int x, int y)
00151 {
00152     if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
00153         sendCommand(0x80 | x);  // send addresses to display with relevant mask
00154         sendCommand(0x40 | y);
00155     }
00156 }
00157 
00158 // These functions are used to set, clear and get the value of pixels in the display
00159 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x).  The refresh()
00160 // function must be called after set and clear in order to update the display
00161 void N5110::setPixel(int x, int y)
00162 {
00163 
00164     if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
00165         // calculate bank and shift 1 to required position in the data byte
00166         buffer[x][y/8] |= (1 << y%8);
00167     }
00168     
00169 }
00170 
00171 void N5110::clearPixel(int x, int y)
00172 {
00173     if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
00174         // calculate bank and shift 1 to required position (using bit clear)
00175         buffer[x][y/8] &= ~(1 << y%8);
00176     }
00177 }
00178 
00179 int N5110::getPixel(int x, int y)
00180 {
00181     if (x>=0 && x<WIDTH && y>=0 && y<HEIGHT) {  // check within range
00182         // return relevant bank and mask required bit
00183         return (int) buffer[x][y/8] & (1 << y%8);
00184     } else {
00185         return 0;
00186     }
00187 }
00188 
00189 // function to refresh the display
00190 void N5110::refresh()
00191 {
00192     int i,j;
00193 
00194     setXYAddress(0,0);  // important to set address back to 0,0 before refreshing display
00195     // address auto increments after printing string, so buffer[0][0] will not coincide
00196     // with top-left pixel after priting string
00197 
00198     sce->write(0);  //set CE low to begin frame
00199 
00200     for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
00201         for(i = 0; i < WIDTH; i++) {
00202             spi->write(buffer[i][j]);  // send buffer
00203         }
00204     }
00205     sce->write(1); // set CE high to end frame
00206 
00207 }
00208 
00209 // fills the buffer with random bytes.  Can be used to test the display.
00210 // The rand() function isn't seeded so it probably creates the same pattern everytime
00211 void N5110::randomiseBuffer()
00212 {
00213     int i,j;
00214     for(j = 0; j < BANKS; j++) {  // be careful to use correct order (j,i) for horizontal addressing
00215         for(i = 0; i < WIDTH; i++) {
00216             buffer[i][j] = rand()%256;  // generate random byte
00217         }
00218     }
00219 
00220 }
00221 
00222 // function to print 5x7 font
00223 void N5110::printChar(char c,int x,int y)
00224 {
00225     for (int i = 0; i < 5 ; i++ ) {
00226         buffer[x+i][y] = font5x7[(c - 32)*5 + i];
00227         // array is offset by 32 relative to ASCII, each character is 5 pixels wide
00228     }
00229 
00230     refresh();  // this sends the buffer to the display and sets address (cursor) back to 0,0
00231 }
00232 
00233 // function to print string at specified position
00234 void N5110::printString(const char * str,int x,int y)
00235 {
00236     int n = 0 ; // counter for number of characters in string
00237     // loop through string and print character
00238     while(*str) {
00239 
00240         // writes the character bitmap data to the buffer, so that
00241         // text and pixels can be displayed at the same time
00242         for (int i = 0; i < 5 ; i++ ) {
00243             buffer[x+i+n*6][y] = font5x7[(*str - 32)*5 + i];
00244         }
00245 
00246         str++;  // go to next character in string
00247         n++;    // increment index
00248     }
00249 
00250     refresh();  // this sends the buffer to the display and sets address (cursor) back to 0,0
00251 
00252 }
00253 
00254 // function to clear the screen
00255 void N5110::clear()
00256 {
00257     clearBuffer();  // clear the buffer then call the refresh function
00258     refresh();
00259 }
00260 
00261 // function to clear the buffer
00262 void N5110::clearBuffer()
00263 {
00264     int i,j;
00265     for (i=0; i<WIDTH; i++) {  // loop through the banks and set the buffer to 0
00266         for (j=0; j<BANKS; j++) {
00267             buffer[i][j]=0;
00268         }
00269     }
00270 }
00271 
00272 // function to plot array on display
00273 void N5110::plotArray(float array[])
00274 {
00275 
00276     int i;
00277 
00278     for (i=0; i<WIDTH; i++) {  // loop through array
00279         // elements are normalised from 0.0 to 1.0, so multiply
00280         // by 47 to convert to pixel range, and subtract from 47
00281         // since top-left is 0,0 in the display geometry
00282         setPixel(i,47 - int(array[i]*47.0));
00283     }
00284 
00285     refresh();
00286 
00287 }
00288 
00289 // function to draw circle
00290 void N5110:: drawCircle(int x0,int y0,int radius,int fill)
00291 {
00292     // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
00293     int x = radius;
00294     int y = 0;
00295     int radiusError = 1-x;
00296 
00297     while(x >= y) {
00298 
00299         // if transparent, just draw outline
00300         if (fill == 0) {
00301             setPixel( x + x0,  y + y0);
00302             setPixel(-x + x0,  y + y0);
00303             setPixel( y + x0,  x + y0);
00304             setPixel(-y + x0,  x + y0);
00305             setPixel(-y + x0, -x + y0);
00306             setPixel( y + x0, -x + y0);
00307             setPixel( x + x0, -y + y0);
00308             setPixel(-x + x0, -y + y0);
00309         } else {  // drawing filled circle, so draw lines between points at same y value
00310 
00311             int type = (fill==1) ? 1:0;  // black or white fill
00312 
00313             drawLine(x+x0,y+y0,-x+x0,y+y0,type);
00314             drawLine(y+x0,x+y0,-y+x0,x+y0,type);
00315             drawLine(y+x0,-x+y0,-y+x0,-x+y0,type);
00316             drawLine(x+x0,-y+y0,-x+x0,-y+y0,type);
00317         }
00318 
00319 
00320         y++;
00321         if (radiusError<0) {
00322             radiusError += 2 * y + 1;
00323         } else {
00324             x--;
00325             radiusError += 2 * (y - x) + 1;
00326         }
00327     }
00328 
00329     refresh();
00330 }
00331 
00332 void N5110:: clearCircle(int x0,int y0,int radius,int fill){
00333         // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
00334     int x = radius;
00335     int y = 0;
00336     int radiusError = 1-x;
00337 
00338     while(x >= y) {
00339 
00340         // if transparent, just draw outline
00341         if (fill == 0) {
00342             clearPixel( x + x0,  y + y0);
00343             clearPixel(-x + x0,  y + y0);
00344             clearPixel( y + x0,  x + y0);
00345             clearPixel(-y + x0,  x + y0);
00346             clearPixel(-y + x0, -x + y0);
00347             clearPixel( y + x0, -x + y0);
00348             clearPixel( x + x0, -y + y0);
00349             clearPixel(-x + x0, -y + y0);
00350         } else {  // drawing filled circle, so draw lines between points at same y value
00351 
00352             int type = (fill==1) ? 1:0;  // black or white fill
00353 
00354             clearLine(x+x0,y+y0,-x+x0,y+y0,type);
00355             clearLine(y+x0,x+y0,-y+x0,x+y0,type);
00356             clearLine(y+x0,-x+y0,-y+x0,-x+y0,type);
00357             clearLine(x+x0,-y+y0,-x+x0,-y+y0,type);
00358         }
00359 
00360 
00361         y++;
00362         if (radiusError<0) {
00363             radiusError += 2 * y + 1;
00364         } else {
00365             x--;
00366             radiusError += 2 * (y - x) + 1;
00367         }
00368     }
00369 
00370     refresh();
00371 }
00372     
00373 
00374 
00375 
00376 void N5110::drawLine(int x0,int y0,int x1,int y1,int type)
00377 {
00378     int y_range = y1-y0;  // calc range of y and x
00379     int x_range = x1-x0;
00380     int start,stop,step;
00381     
00382     // if dotted line, set step to 2, else step is 1
00383     step = (type==2) ? 2:1;
00384 
00385     // make sure we loop over the largest range to get the most pixels on the display
00386     // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
00387     // or else we'll only end up with 1 pixel in the x column
00388     if ( abs(x_range) > abs(y_range) ) {
00389 
00390         // ensure we loop from smallest to largest or else for-loop won't run as expected
00391         start = x1>x0 ? x0:x1;
00392         stop =  x1>x0 ? x1:x0;
00393 
00394         // loop between x pixels
00395         for (int x = start; x<= stop ; x+=step) {
00396             // do linear interpolation
00397             int y = y0 + (y1-y0)*(x-x0)/(x1-x0);
00398 
00399             if (type == 0)   // if 'white' line, turn off pixel
00400                 clearPixel(x,y);
00401             else
00402                 setPixel(x,y);  // else if 'black' or 'dotted' turn on pixel
00403 
00404         }
00405     } else {
00406 
00407         // ensure we loop from smallest to largest or else for-loop won't run as expected
00408         start = y1>y0 ? y0:y1;
00409         stop =  y1>y0 ? y1:y0;
00410 
00411         for (int y = start; y<= stop ; y+=step) {
00412             // do linear interpolation
00413             int x = x0 + (x1-x0)*(y-y0)/(y1-y0);
00414 
00415             if (type == 0)   // if 'white' line, turn off pixel
00416                 clearPixel(x,y);
00417             else
00418                 setPixel(x,y);  // else if 'black' or 'dotted' turn on pixel
00419 
00420         }
00421     }
00422 
00423     refresh();
00424 }
00425 
00426 
00427 void N5110::clearLine(int x0,int y0,int x1,int y1,int type)
00428 {
00429     int y_range = y1-y0;  // calc range of y and x
00430     int x_range = x1-x0;
00431     int start,stop,step;
00432     
00433     // if dotted line, set step to 2, else step is 1
00434     step = (type==2) ? 2:1;
00435 
00436     // make sure we loop over the largest range to get the most pixels on the display
00437     // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels
00438     // or else we'll only end up with 1 pixel in the x column
00439     if ( abs(x_range) > abs(y_range) ) {
00440 
00441         // ensure we loop from smallest to largest or else for-loop won't run as expected
00442         start = x1>x0 ? x0:x1;
00443         stop =  x1>x0 ? x1:x0;
00444 
00445         // loop between x pixels
00446         for (int x = start; x<= stop ; x+=step) {
00447             // do linear interpolation
00448             int y = y0 + (y1-y0)*(x-x0)/(x1-x0);
00449 
00450             if (type == 0)   // if 'white' line, turn off pixel
00451                 clearPixel(x,y);
00452             else
00453                 clearPixel(x,y);  // else if 'black' or 'dotted' turn off pixel
00454 
00455         }
00456     } else {
00457 
00458         // ensure we loop from smallest to largest or else for-loop won't run as expected
00459         start = y1>y0 ? y0:y1;
00460         stop =  y1>y0 ? y1:y0;
00461 
00462         for (int y = start; y<= stop ; y+=step) {
00463             // do linear interpolation
00464             int x = x0 + (x1-x0)*(y-y0)/(y1-y0);
00465 
00466             if (type == 0)   // if 'white' line, turn off pixel
00467                 clearPixel(x,y);
00468             else
00469                 clearPixel(x,y);  // else if 'black' or 'dotted' turn on pixel
00470 
00471         }
00472     }
00473 
00474     refresh();
00475 }
00476 
00477 void N5110::drawRect(int x0,int y0,int width,int height,int fill)
00478 {
00479     gameLanes();
00480     if (fill == 0) { // transparent, just outline
00481         drawLine(x0,y0,x0+width,y0,1);  // top
00482         drawLine(x0,y0+height,x0+width,y0+height,1);  // bottom
00483         drawLine(x0,y0,x0,y0+height,1);  // left
00484         drawLine(x0+width,y0,x0+width,y0+height,1);  // right
00485     } else { // filled rectangle
00486         int type = (fill==1) ? 1:0;  // black or white fill
00487         for (int y = y0; y<= y0+height; y++) {  // loop through rows of rectangle
00488             drawLine(x0,y,x0+width,y,type);  // draw line across screen
00489         }
00490     }
00491 }
00492 
00493 void N5110::gameLanes(){
00494     
00495     //road lanes
00496     drawLine(60,0,60,48,1);
00497     drawLine(60,16,84,16,1);
00498     drawLine(60,32,84,32,1);
00499     drawLine(20,0,20,48,2);
00500     drawLine(40,0,40,48,2);
00501   
00502     //heart shape
00503     setPixel(62,9);
00504     setPixel(62,10);
00505     setPixel(62,11);
00506     
00507     setPixel(63,8);
00508     setPixel(63,9);
00509     setPixel(63,10);
00510     setPixel(63,11);
00511     setPixel(63,12);
00512   
00513     setPixel(64,7);
00514     setPixel(64,8);
00515     setPixel(64,9);
00516     setPixel(64,10);
00517     setPixel(64,11);
00518     setPixel(64,12);
00519     setPixel(64,13);
00520     
00521     setPixel(65,8);
00522     setPixel(65,9);
00523     setPixel(65,10);
00524     setPixel(65,11);
00525     setPixel(65,12);
00526     setPixel(65,13);
00527     setPixel(65,14);
00528     
00529     setPixel(66,9);
00530     setPixel(66,10);
00531     setPixel(66,11);
00532     setPixel(66,12);
00533     setPixel(66,13);
00534     setPixel(66,14);
00535     setPixel(66,15);
00536     
00537     setPixel(67,8);
00538     setPixel(67,9);
00539     setPixel(67,10);
00540     setPixel(67,11);
00541     setPixel(67,12);
00542     setPixel(67,13);
00543     setPixel(67,14);
00544     
00545     setPixel(68,7);
00546     setPixel(68,8);
00547     setPixel(68,9);
00548     setPixel(68,10);
00549     setPixel(68,11);
00550     setPixel(68,12);
00551     setPixel(68,13);
00552     
00553     setPixel(69,8);
00554     setPixel(69,9);
00555     setPixel(69,10);
00556     setPixel(69,11);
00557     setPixel(69,12);
00558   
00559     setPixel(70,9);
00560     setPixel(70,10);
00561     setPixel(70,11);
00562     
00563     
00564     //print Round Indicator
00565     printChar('R',62,3);
00566     printChar(':',68,3);
00567     
00568     
00569     //set the Coin Shape
00570     drawCircle(66,43,4,0);
00571     
00572     setPixel(66,41);
00573     setPixel(66,44);
00574     
00575     setPixel(67,41);
00576     setPixel(67,44);
00577     
00578     setPixel(65,42);
00579     setPixel(65,43);
00580     
00581     }