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