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