Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
N5110.cpp
00001 #include "mbed.h" 00002 #include "N5110.h" 00003 00004 // overloaded constructor includes power pin - LCD Vcc connected to GPIO pin 00005 // this constructor works fine with LPC1768 - enough current sourced from GPIO 00006 // to power LCD. Doesn't work well with K64F. 00007 N5110::N5110(PinName const pwrPin, 00008 PinName const scePin, 00009 PinName const rstPin, 00010 PinName const dcPin, 00011 PinName const mosiPin, 00012 PinName const sclkPin, 00013 PinName const ledPin) 00014 : 00015 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise 00016 _led(new DigitalOut(ledPin)), 00017 _pwr(new DigitalOut(pwrPin)), 00018 _sce(new DigitalOut(scePin)), 00019 _rst(new DigitalOut(rstPin)), 00020 _dc(new DigitalOut(dcPin)) 00021 {} 00022 00023 // overloaded constructor does not include power pin - LCD Vcc must be tied to +3V3 00024 // Best to use this with K64F as the GPIO hasn't sufficient output current to reliably 00025 // drive the LCD. 00026 N5110::N5110(PinName const scePin, 00027 PinName const rstPin, 00028 PinName const dcPin, 00029 PinName const mosiPin, 00030 PinName const sclkPin, 00031 PinName const ledPin) 00032 : 00033 _spi(new SPI(mosiPin,NC,sclkPin)), // create new SPI instance and initialise 00034 _led(new DigitalOut(ledPin)), 00035 _pwr(NULL), // pwr not needed so null it to be safe 00036 _sce(new DigitalOut(scePin)), 00037 _rst(new DigitalOut(rstPin)), 00038 _dc(new DigitalOut(dcPin)) 00039 {} 00040 // Second overload contructor uses the New Gamepad (Rev 2.1) pin mappings 00041 N5110::N5110() 00042 : 00043 _spi(new SPI(PTD2,NC,PTD1)), // create new SPI instance and initialise 00044 _led(new DigitalOut(PTB23)), 00045 _pwr(NULL), // pwr not needed so null it to be safe 00046 _sce(new DigitalOut(PTB19)), 00047 _rst(new DigitalOut(PTC1)), 00048 _dc(new DigitalOut(PTB18)) 00049 {} 00050 00051 N5110::~N5110() 00052 { 00053 delete _spi; 00054 00055 if(_pwr) { 00056 delete _pwr; 00057 } 00058 00059 delete _led; 00060 delete _sce; 00061 delete _rst; 00062 delete _dc; 00063 } 00064 00065 // initialise function - powers up and sends the initialisation commands 00066 void N5110::init() 00067 { 00068 turnOn(); // power up 00069 reset(); // reset LCD - must be done within 100 ms 00070 initSPI(); 00071 00072 backLightOn(); 00073 setContrast(0.55); // this may need tuning (say 0.4 to 0.6) 00074 setBias(3); // datasheet - 48:1 mux - don't mess with if you don't know what you're doing! (0 to 7) 00075 setTempCoefficient(0); // datasheet - may need increasing (range 0 to 3) at very low temperatures 00076 normalMode(); // normal video mode by default 00077 00078 clearRAM(); // RAM is undefined at power-up so clear to be sure 00079 clear(); // clear buffer 00080 } 00081 00082 // sets normal video mode (black on white) 00083 void N5110::normalMode() 00084 { 00085 sendCommand(0b00100000); // basic instruction 00086 sendCommand(0b00001100); // normal video mode- datasheet 00087 } 00088 00089 // sets normal video mode (white on black) 00090 void N5110::inverseMode() 00091 { 00092 sendCommand(0b00100000); // basic instruction 00093 sendCommand(0b00001101); // inverse video mode - datasheet 00094 } 00095 00096 // function to power up the LCD and backlight - only works when using GPIO to power 00097 void N5110::turnOn() 00098 { 00099 if (_pwr != NULL) { 00100 _pwr->write(1); // apply power 00101 } 00102 } 00103 00104 // function to power down LCD 00105 void N5110::turnOff() 00106 { 00107 clear(); // clear buffer 00108 refresh(); 00109 backLightOff(); // turn backlight off 00110 clearRAM(); // clear RAM to ensure specified current consumption 00111 // send command to ensure we are in basic mode 00112 00113 sendCommand(0b00100000); // basic mode 00114 sendCommand(0b00001000); // clear display 00115 sendCommand(0b00100001); // extended mode 00116 sendCommand(0b00100100); // power down 00117 00118 // if we are powering the LCD using the GPIO then make it low to turn off 00119 if (_pwr != NULL) { 00120 wait_ms(10); // small delay and then turn off the power pin 00121 _pwr->write(0); // turn off power 00122 } 00123 00124 } 00125 00126 // function to change LED backlight brightness 00127 void N5110::backLightOn() 00128 { 00129 _led->write(1); 00130 } 00131 00132 // function to change LED backlight brightness 00133 void N5110::backLightOff() 00134 { 00135 _led->write(0); 00136 } 00137 00138 void N5110::setContrast(float contrast) { 00139 00140 // enforce limits 00141 if (contrast > 1.0f) 00142 contrast = 1.0f; 00143 else if (contrast < 0.0f) 00144 contrast = 0.0; 00145 00146 // convert to char in range 0 to 127 (i.e. 6 bits) 00147 char ic = char(contrast*127.0f); 00148 00149 sendCommand(0b00100001); // extended instruction set 00150 sendCommand(0b10000000 | ic); // set Vop (which controls contrast) 00151 sendCommand(0b00100000); // back to basic instruction set 00152 } 00153 00154 void N5110::setTempCoefficient(char tc) { 00155 00156 // enforce limits 00157 if (tc>3) { 00158 tc=3; 00159 } 00160 00161 // temperature coefficient may need increasing at low temperatures 00162 00163 sendCommand(0b00100001); // extended instruction set 00164 sendCommand(0b00000100 | tc); 00165 sendCommand(0b00100000); // back to basic instruction set 00166 } 00167 00168 void N5110::setBias(char bias) { 00169 00170 // from data sheet 00171 // bias mux rate 00172 // 0 1:100 00173 // 1 1:80 00174 // 2 1:65 00175 // 3 1:48 (default) 00176 // 4 1:40/1:34 00177 // 5 1:24 00178 // 6 1:18/1:16 00179 // 7 1:10/1:9/1:8 00180 00181 // enforce limits 00182 if (bias>7) { 00183 bias=7; 00184 } 00185 00186 sendCommand(0b00100001); // extended mode instruction 00187 sendCommand(0b00010000 | bias); 00188 sendCommand(0b00100000); // end of extended mode instruction 00189 } 00190 00191 // pulse the active low reset line 00192 void N5110::reset() 00193 { 00194 _rst->write(0); // reset the LCD 00195 _rst->write(1); 00196 } 00197 00198 // function to initialise SPI peripheral 00199 void N5110::initSPI() 00200 { 00201 _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 00202 _spi->frequency(4000000); // maximum of screen is 4 MHz 00203 } 00204 00205 // send a command to the display 00206 void N5110::sendCommand(unsigned char command) 00207 { 00208 _dc->write(0); // set DC low for command 00209 _sce->write(0); // set CE low to begin frame 00210 _spi->write(command); // send command 00211 _dc->write(1); // turn back to data by default 00212 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00213 } 00214 00215 // send data to the display at the current XY address 00216 // dc is set to 1 (i.e. data) after sending a command and so should 00217 // be the default mode. 00218 void N5110::sendData(unsigned char data) 00219 { 00220 _sce->write(0); // set CE low to begin frame 00221 _spi->write(data); 00222 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00223 } 00224 00225 // this function writes 0 to the 504 bytes to clear the RAM 00226 void N5110::clearRAM() 00227 { 00228 _sce->write(0); //set CE low to begin frame 00229 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes 00230 _spi->write(0x00); // send 0's 00231 } 00232 _sce->write(1); // set CE high to end frame 00233 } 00234 00235 // function to set the XY address in RAM for subsequenct data write 00236 void N5110::setXYAddress(unsigned int const x, 00237 unsigned int const y) 00238 { 00239 if (x<WIDTH && y<HEIGHT) { // check within range 00240 sendCommand(0b00100000); // basic instruction 00241 sendCommand(0b10000000 | x); // send addresses to display with relevant mask 00242 sendCommand(0b01000000 | y); 00243 } 00244 } 00245 00246 // These functions are used to set, clear and get the value of pixels in the display 00247 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() 00248 // function must be called after set and clear in order to update the display 00249 void N5110::setPixel(unsigned int const x, 00250 unsigned int const y, 00251 bool const state) 00252 { 00253 if (x<WIDTH && y<HEIGHT) { // check within range 00254 // calculate bank and shift 1 to required position in the data byte 00255 if(state) buffer[x][y/8] |= (1 << y%8); 00256 else buffer[x][y/8] &= ~(1 << y%8); 00257 } 00258 } 00259 00260 void N5110::clearPixel(unsigned int const x, 00261 unsigned int const y) 00262 { 00263 if (x<WIDTH && y<HEIGHT) { // check within range 00264 // calculate bank and shift 1 to required position (using bit clear) 00265 buffer[x][y/8] &= ~(1 << y%8); 00266 } 00267 } 00268 00269 int N5110::getPixel(unsigned int const x, 00270 unsigned int const y) const 00271 { 00272 if (x<WIDTH && y<HEIGHT) { // check within range 00273 // return relevant bank and mask required bit 00274 00275 int pixel = (int) buffer[x][y/8] & (1 << y%8); 00276 00277 if (pixel) 00278 return 1; 00279 else 00280 return 0; 00281 } 00282 00283 return 0; 00284 00285 } 00286 00287 // function to refresh the display 00288 void N5110::refresh() 00289 { 00290 setXYAddress(0,0); // important to set address back to 0,0 before refreshing display 00291 // address auto increments after printing string, so buffer[0][0] will not coincide 00292 // with top-left pixel after priting string 00293 00294 _sce->write(0); //set CE low to begin frame 00295 00296 for(int j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00297 for(int i = 0; i < WIDTH; i++) { 00298 _spi->write(buffer[i][j]); // send buffer 00299 } 00300 } 00301 _sce->write(1); // set CE high to end frame 00302 00303 } 00304 00305 // fills the buffer with random bytes. Can be used to test the display. 00306 // The rand() function isn't seeded so it probably creates the same pattern everytime 00307 void N5110::randomiseBuffer() 00308 { 00309 int i,j; 00310 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00311 for(i = 0; i < WIDTH; i++) { 00312 buffer[i][j] = rand()%256; // generate random byte 00313 } 00314 } 00315 00316 } 00317 00318 // function to print 5x7 font 00319 void N5110::printChar(char const c, 00320 unsigned int const x, 00321 unsigned int const y) 00322 { 00323 if (y<BANKS) { // check if printing in range of y banks 00324 00325 for (int i = 0; i < 5 ; i++ ) { 00326 int pixel_x = x+i; 00327 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00328 break; 00329 buffer[pixel_x][y] = font5x7[(c - 32)*5 + i]; 00330 // array is offset by 32 relative to ASCII, each character is 5 pixels wide 00331 } 00332 00333 } 00334 } 00335 00336 // function to print string at specified position 00337 void N5110::printString(const char *str, 00338 unsigned int const x, 00339 unsigned int const y) 00340 { 00341 if (y<BANKS) { // check if printing in range of y banks 00342 00343 int n = 0 ; // counter for number of characters in string 00344 // loop through string and print character 00345 while(*str) { 00346 00347 // writes the character bitmap data to the buffer, so that 00348 // text and pixels can be displayed at the same time 00349 for (int i = 0; i < 5 ; i++ ) { 00350 int pixel_x = x+i+n*6; 00351 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00352 break; 00353 buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i]; 00354 } 00355 str++; // go to next character in string 00356 n++; // increment index 00357 } 00358 } 00359 } 00360 00361 // function to clear the screen buffer 00362 void N5110::clear() 00363 { 00364 memset(buffer,0,sizeof(buffer)); 00365 } 00366 00367 // function to plot array on display 00368 void N5110::plotArray(float const array[]) 00369 { 00370 for (int i=0; i<WIDTH; i++) { // loop through array 00371 // elements are normalised from 0.0 to 1.0, so multiply 00372 // by 47 to convert to pixel range, and subtract from 47 00373 // since top-left is 0,0 in the display geometry 00374 setPixel(i,47 - int(array[i]*47.0f),true); 00375 } 00376 00377 } 00378 00379 // function to draw circle 00380 void N5110:: drawCircle(unsigned int const x0, 00381 unsigned int const y0, 00382 unsigned int const radius, 00383 FillType const fill) 00384 { 00385 // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 00386 int x = radius; 00387 int y = 0; 00388 int radiusError = 1-x; 00389 00390 while(x >= y) { 00391 00392 // if transparent, just draw outline 00393 if (fill == FILL_TRANSPARENT) { 00394 setPixel( x + x0, y + y0,true); 00395 setPixel(-x + x0, y + y0,true); 00396 setPixel( y + x0, x + y0,true); 00397 setPixel(-y + x0, x + y0,true); 00398 setPixel(-y + x0, -x + y0,true); 00399 setPixel( y + x0, -x + y0,true); 00400 setPixel( x + x0, -y + y0,true); 00401 setPixel(-x + x0, -y + y0,true); 00402 } else { // drawing filled circle, so draw lines between points at same y value 00403 00404 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill 00405 00406 drawLine(x+x0,y+y0,-x+x0,y+y0,type); 00407 drawLine(y+x0,x+y0,-y+x0,x+y0,type); 00408 drawLine(y+x0,-x+y0,-y+x0,-x+y0,type); 00409 drawLine(x+x0,-y+y0,-x+x0,-y+y0,type); 00410 } 00411 00412 y++; 00413 if (radiusError<0) { 00414 radiusError += 2 * y + 1; 00415 } else { 00416 x--; 00417 radiusError += 2 * (y - x) + 1; 00418 } 00419 } 00420 00421 } 00422 00423 void N5110::drawLine(unsigned int const x0, 00424 unsigned int const y0, 00425 unsigned int const x1, 00426 unsigned int const y1, 00427 unsigned int const type) 00428 { 00429 // Note that the ranges can be negative so we have to turn the input values 00430 // into signed integers first 00431 int const y_range = static_cast<int>(y1) - static_cast<int>(y0); 00432 int const x_range = static_cast<int>(x1) - static_cast<int>(x0); 00433 00434 // if dotted line, set step to 2, else step is 1 00435 unsigned int const step = (type==2) ? 2:1; 00436 00437 // make sure we loop over the largest range to get the most pixels on the display 00438 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels 00439 // or else we'll only end up with 1 pixel in the x column 00440 if ( abs(x_range) > abs(y_range) ) { 00441 00442 // ensure we loop from smallest to largest or else for-loop won't run as expected 00443 unsigned int const start = x_range > 0 ? x0:x1; 00444 unsigned int const stop = x_range > 0 ? x1:x0; 00445 00446 // loop between x pixels 00447 for (unsigned int x = start; x<= stop ; x+=step) { 00448 // do linear interpolation 00449 int const dx = static_cast<int>(x)-static_cast<int>(x0); 00450 unsigned int const y = y0 + y_range * dx / x_range; 00451 00452 // If the line type is '0', this will clear the pixel 00453 // If it is '1' or '2', the pixel will be set 00454 setPixel(x,y, type); 00455 } 00456 } else { 00457 00458 // ensure we loop from smallest to largest or else for-loop won't run as expected 00459 unsigned int const start = y_range > 0 ? y0:y1; 00460 unsigned int const stop = y_range > 0 ? y1:y0; 00461 00462 for (unsigned int y = start; y<= stop ; y+=step) { 00463 // do linear interpolation 00464 int const dy = static_cast<int>(y)-static_cast<int>(y0); 00465 unsigned int const x = x0 + x_range * dy / y_range; 00466 00467 // If the line type is '0', this will clear the pixel 00468 // If it is '1' or '2', the pixel will be set 00469 setPixel(x,y, type); 00470 } 00471 } 00472 00473 } 00474 00475 void N5110::drawRect(unsigned int const x0, 00476 unsigned int const y0, 00477 unsigned int const width, 00478 unsigned int const height, 00479 FillType const fill) 00480 { 00481 if (fill == FILL_TRANSPARENT) { // transparent, just outline 00482 drawLine(x0,y0,x0+(width-1),y0,1); // top 00483 drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1); // bottom 00484 drawLine(x0,y0,x0,y0+(height-1),1); // left 00485 drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1); // right 00486 } else { // filled rectangle 00487 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill 00488 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle 00489 drawLine(x0,y,x0+(width-1),y,type); // draw line across screen 00490 } 00491 } 00492 } 00493 00494 void N5110::drawSprite(int x0, 00495 int y0, 00496 int nrows, 00497 int ncols, 00498 int *sprite) 00499 { 00500 for (int i = 0; i < nrows; i++) { 00501 for (int j = 0 ; j < ncols ; j++) { 00502 00503 int pixel = *((sprite+i*ncols)+j); 00504 setPixel(x0+j,y0+i, pixel); 00505 } 00506 } 00507 }
Generated on Sat Jul 16 2022 00:49:04 by
