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 initSPI(); 00061 00062 setContrast(0.55); // this may need tuning (say 0.4 to 0.6) 00063 setBias(3); // datasheet - 48:1 mux - don't mess with if you don't know what you're doing! (0 to 7) 00064 setTempCoefficient(0); // datasheet - may need increasing (range 0 to 3) at very low temperatures 00065 normalMode(); // normal video mode by default 00066 00067 clearRAM(); // RAM is undefined at power-up so clear to be sure 00068 clear(); // clear buffer 00069 setBrightness(0.5); 00070 } 00071 00072 // sets normal video mode (black on white) 00073 void N5110::normalMode() 00074 { 00075 sendCommand(0b00100000); // basic instruction 00076 sendCommand(0b00001100); // normal video mode- datasheet 00077 } 00078 00079 // sets normal video mode (white on black) 00080 void N5110::inverseMode() 00081 { 00082 sendCommand(0b00100000); // basic instruction 00083 sendCommand(0b00001101); // inverse video mode - datasheet 00084 } 00085 00086 // function to power up the LCD and backlight - only works when using GPIO to power 00087 void N5110::turnOn() 00088 { 00089 if (_pwr != NULL) { 00090 _pwr->write(1); // apply power 00091 } 00092 } 00093 00094 // function to power down LCD 00095 void N5110::turnOff() 00096 { 00097 clear(); // clear buffer 00098 refresh(); 00099 setBrightness(0.0); // turn backlight off 00100 clearRAM(); // clear RAM to ensure specified current consumption 00101 // send command to ensure we are in basic mode 00102 00103 sendCommand(0b00100000); // basic mode 00104 sendCommand(0b00001000); // clear display 00105 sendCommand(0b00100001); // extended mode 00106 sendCommand(0b00100100); // power down 00107 00108 // if we are powering the LCD using the GPIO then make it low to turn off 00109 if (_pwr != NULL) { 00110 wait_ms(10); // small delay and then turn off the power pin 00111 _pwr->write(0); // turn off power 00112 } 00113 00114 } 00115 00116 // function to change LED backlight brightness 00117 void N5110::setBrightness(float brightness) 00118 { 00119 // check whether brightness is within range 00120 if (brightness < 0.0f) 00121 brightness = 0.0f; 00122 if (brightness > 1.0f) 00123 brightness = 1.0f; 00124 // set PWM duty cycle 00125 _led->write(brightness); 00126 } 00127 00128 void N5110::setContrast(float contrast) { 00129 00130 // enforce limits 00131 if (contrast > 1.0f) 00132 contrast = 1.0f; 00133 else if (contrast < 0.0f) 00134 contrast = 0.0; 00135 00136 // convert to char in range 0 to 127 (i.e. 6 bits) 00137 char ic = char(contrast*127.0f); 00138 00139 sendCommand(0b00100001); // extended instruction set 00140 sendCommand(0b10000000 | ic); // set Vop (which controls contrast) 00141 sendCommand(0b00100000); // back to basic instruction set 00142 } 00143 00144 void N5110::setTempCoefficient(char tc) { 00145 00146 // enforce limits 00147 if (tc>3) { 00148 tc=3; 00149 } 00150 00151 // temperature coefficient may need increasing at low temperatures 00152 00153 sendCommand(0b00100001); // extended instruction set 00154 sendCommand(0b00000100 | tc); 00155 sendCommand(0b00100000); // back to basic instruction set 00156 } 00157 00158 void N5110::setBias(char bias) { 00159 00160 // from data sheet 00161 // bias mux rate 00162 // 0 1:100 00163 // 1 1:80 00164 // 2 1:65 00165 // 3 1:48 (default) 00166 // 4 1:40/1:34 00167 // 5 1:24 00168 // 6 1:18/1:16 00169 // 7 1:10/1:9/1:8 00170 00171 // enforce limits 00172 if (bias>7) { 00173 bias=7; 00174 } 00175 00176 sendCommand(0b00100001); // extended mode instruction 00177 sendCommand(0b00010000 | bias); 00178 sendCommand(0b00100000); // end of extended mode instruction 00179 } 00180 00181 // pulse the active low reset line 00182 void N5110::reset() 00183 { 00184 _rst->write(0); // reset the LCD 00185 _rst->write(1); 00186 } 00187 00188 // function to initialise SPI peripheral 00189 void N5110::initSPI() 00190 { 00191 _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 00192 _spi->frequency(4000000); // maximum of screen is 4 MHz 00193 } 00194 00195 // send a command to the display 00196 void N5110::sendCommand(unsigned char command) 00197 { 00198 _dc->write(0); // set DC low for command 00199 _sce->write(0); // set CE low to begin frame 00200 _spi->write(command); // send command 00201 _dc->write(1); // turn back to data by default 00202 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00203 } 00204 00205 // send data to the display at the current XY address 00206 // dc is set to 1 (i.e. data) after sending a command and so should 00207 // be the default mode. 00208 void N5110::sendData(unsigned char data) 00209 { 00210 _sce->write(0); // set CE low to begin frame 00211 _spi->write(data); 00212 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00213 } 00214 00215 // this function writes 0 to the 504 bytes to clear the RAM 00216 void N5110::clearRAM() 00217 { 00218 _sce->write(0); //set CE low to begin frame 00219 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes 00220 _spi->write(0x00); // send 0's 00221 } 00222 _sce->write(1); // set CE high to end frame 00223 } 00224 00225 // function to set the XY address in RAM for subsequenct data write 00226 void N5110::setXYAddress(unsigned int const x, 00227 unsigned int const y) 00228 { 00229 if (x<WIDTH && y<HEIGHT) { // check within range 00230 sendCommand(0b00100000); // basic instruction 00231 sendCommand(0b10000000 | x); // send addresses to display with relevant mask 00232 sendCommand(0b01000000 | y); 00233 } 00234 } 00235 00236 // These functions are used to set, clear and get the value of pixels in the display 00237 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() 00238 // function must be called after set and clear in order to update the display 00239 void N5110::setPixel(unsigned int const x, 00240 unsigned int const y, 00241 bool const state) 00242 { 00243 if (x<WIDTH && y<HEIGHT) { // check within range 00244 // calculate bank and shift 1 to required position in the data byte 00245 if(state) buffer[x][y/8] |= (1 << y%8); 00246 else buffer[x][y/8] &= ~(1 << y%8); 00247 00248 } 00249 } 00250 00251 void N5110::setScreen(unsigned char data[84][6]){ 00252 for(int i=0; i<84; i++){ 00253 for(int j=0; j<6; j++){ 00254 buffer[i][j] &= (unsigned char)data[i][j]; 00255 buffer[i][j] |= (unsigned char)data[i][j]; 00256 } 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 Mon Jul 18 2022 01:51:48 by
1.7.2