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 00135 00136 // pulse the active low reset line 00137 void N5110::reset() 00138 { 00139 _rst->write(0); // reset the LCD 00140 _rst->write(1); 00141 } 00142 00143 // function to initialise SPI peripheral 00144 void N5110::initSPI() 00145 { 00146 _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 00147 _spi->frequency(4000000); // maximum of screen is 4 MHz 00148 } 00149 00150 // send a command to the display 00151 void N5110::sendCommand(unsigned char command) 00152 { 00153 _dc->write(0); // set DC low for command 00154 _sce->write(0); // set CE low to begin frame 00155 _spi->write(command); // send command 00156 _dc->write(1); // turn back to data by default 00157 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00158 } 00159 00160 // send data to the display at the current XY address 00161 // dc is set to 1 (i.e. data) after sending a command and so should 00162 // be the default mode. 00163 void N5110::sendData(unsigned char data) 00164 { 00165 _sce->write(0); // set CE low to begin frame 00166 _spi->write(data); 00167 _sce->write(1); // set CE high to end frame (expected for transmission of single byte) 00168 } 00169 00170 // this function writes 0 to the 504 bytes to clear the RAM 00171 void N5110::clearRAM() 00172 { 00173 _sce->write(0); //set CE low to begin frame 00174 for(int i = 0; i < WIDTH * HEIGHT; i++) { // 48 x 84 bits = 504 bytes 00175 _spi->write(0x00); // send 0's 00176 } 00177 _sce->write(1); // set CE high to end frame 00178 } 00179 00180 // function to set the XY address in RAM for subsequenct data write 00181 void N5110::setXYAddress(unsigned int const x, 00182 unsigned int const y) 00183 { 00184 if (x<WIDTH && y<HEIGHT) { // check within range 00185 sendCommand(0x80 | x); // send addresses to display with relevant mask 00186 sendCommand(0x40 | y); 00187 } 00188 } 00189 00190 // These functions are used to set, clear and get the value of pixels in the display 00191 // Pixels are addressed in the range of 0 to 47 (y) and 0 to 83 (x). The refresh() 00192 // function must be called after set and clear in order to update the display 00193 void N5110::setPixel(unsigned int const x, 00194 unsigned int const y) 00195 { 00196 if (x<WIDTH && y<HEIGHT) { // check within range 00197 // calculate bank and shift 1 to required position in the data byte 00198 buffer[x][y/8] |= (1 << y%8); 00199 } 00200 } 00201 00202 void N5110::clearPixel(unsigned int const x, 00203 unsigned int const y) 00204 { 00205 if (x<WIDTH && y<HEIGHT) { // check within range 00206 // calculate bank and shift 1 to required position (using bit clear) 00207 buffer[x][y/8] &= ~(1 << y%8); 00208 } 00209 } 00210 00211 int N5110::getPixel(unsigned int const x, 00212 unsigned int const y) const 00213 { 00214 if (x<WIDTH && y<HEIGHT) { // check within range 00215 // return relevant bank and mask required bit 00216 00217 int pixel = (int) buffer[x][y/8] & (1 << y%8); 00218 00219 if (pixel) 00220 return 1; 00221 else 00222 return 0; 00223 } 00224 00225 return 0; 00226 00227 } 00228 00229 // function to refresh the display 00230 void N5110::refresh() 00231 { 00232 setXYAddress(0,0); // important to set address back to 0,0 before refreshing display 00233 // address auto increments after printing string, so buffer[0][0] will not coincide 00234 // with top-left pixel after priting string 00235 00236 _sce->write(0); //set CE low to begin frame 00237 00238 for(int j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00239 for(int i = 0; i < WIDTH; i++) { 00240 _spi->write(buffer[i][j]); // send buffer 00241 } 00242 } 00243 _sce->write(1); // set CE high to end frame 00244 00245 } 00246 00247 // fills the buffer with random bytes. Can be used to test the display. 00248 // The rand() function isn't seeded so it probably creates the same pattern everytime 00249 void N5110::randomiseBuffer() 00250 { 00251 int i,j; 00252 for(j = 0; j < BANKS; j++) { // be careful to use correct order (j,i) for horizontal addressing 00253 for(i = 0; i < WIDTH; i++) { 00254 buffer[i][j] = rand()%256; // generate random byte 00255 } 00256 } 00257 00258 } 00259 00260 // function to print 5x7 font 00261 void N5110::printChar(char const c, 00262 unsigned int const x, 00263 unsigned int const y) 00264 { 00265 if (y<BANKS) { // check if printing in range of y banks 00266 00267 for (int i = 0; i < 5 ; i++ ) { 00268 int pixel_x = x+i; 00269 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00270 break; 00271 buffer[pixel_x][y] = font5x7[(c - 32)*5 + i]; 00272 // array is offset by 32 relative to ASCII, each character is 5 pixels wide 00273 } 00274 00275 } 00276 } 00277 00278 // function to print string at specified position 00279 void N5110::printString(const char *str, 00280 unsigned int const x, 00281 unsigned int const y) 00282 { 00283 if (y<BANKS) { // check if printing in range of y banks 00284 00285 int n = 0 ; // counter for number of characters in string 00286 // loop through string and print character 00287 while(*str) { 00288 00289 // writes the character bitmap data to the buffer, so that 00290 // text and pixels can be displayed at the same time 00291 for (int i = 0; i < 5 ; i++ ) { 00292 int pixel_x = x+i+n*6; 00293 if (pixel_x > WIDTH-1) // ensure pixel isn't outside the buffer size (0 - 83) 00294 break; 00295 buffer[pixel_x][y] = font5x7[(*str - 32)*5 + i]; 00296 } 00297 str++; // go to next character in string 00298 n++; // increment index 00299 } 00300 } 00301 } 00302 00303 // function to clear the screen buffer 00304 void N5110::clear() 00305 { 00306 memset(buffer,0,sizeof(buffer)); 00307 } 00308 00309 // function to plot array on display 00310 void N5110::plotArray(float const array[]) 00311 { 00312 for (int i=0; i<WIDTH; i++) { // loop through array 00313 // elements are normalised from 0.0 to 1.0, so multiply 00314 // by 47 to convert to pixel range, and subtract from 47 00315 // since top-left is 0,0 in the display geometry 00316 setPixel(i,47 - int(array[i]*47.0f)); 00317 } 00318 00319 } 00320 00321 // function to draw circle 00322 void N5110:: drawCircle(unsigned int const x0, 00323 unsigned int const y0, 00324 unsigned int const radius, 00325 FillType const fill) 00326 { 00327 // from http://en.wikipedia.org/wiki/Midpoint_circle_algorithm 00328 int x = radius; 00329 int y = 0; 00330 int radiusError = 1-x; 00331 00332 while(x >= y) { 00333 00334 // if transparent, just draw outline 00335 if (fill == FILL_TRANSPARENT) { 00336 setPixel( x + x0, y + y0); 00337 setPixel(-x + x0, y + y0); 00338 setPixel( y + x0, x + y0); 00339 setPixel(-y + x0, x + y0); 00340 setPixel(-y + x0, -x + y0); 00341 setPixel( y + x0, -x + y0); 00342 setPixel( x + x0, -y + y0); 00343 setPixel(-x + x0, -y + y0); 00344 } else { // drawing filled circle, so draw lines between points at same y value 00345 00346 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill 00347 00348 drawLine(x+x0,y+y0,-x+x0,y+y0,type); 00349 drawLine(y+x0,x+y0,-y+x0,x+y0,type); 00350 drawLine(y+x0,-x+y0,-y+x0,-x+y0,type); 00351 drawLine(x+x0,-y+y0,-x+x0,-y+y0,type); 00352 } 00353 00354 y++; 00355 if (radiusError<0) { 00356 radiusError += 2 * y + 1; 00357 } else { 00358 x--; 00359 radiusError += 2 * (y - x) + 1; 00360 } 00361 } 00362 00363 } 00364 00365 void N5110::drawLine(unsigned int const x0, 00366 unsigned int const y0, 00367 unsigned int const x1, 00368 unsigned int const y1, 00369 unsigned int const type) 00370 { 00371 int y_range = y1-y0; // calc range of y and x 00372 int x_range = x1-x0; 00373 int start,stop,step; 00374 00375 // if dotted line, set step to 2, else step is 1 00376 step = (type==2) ? 2:1; 00377 00378 // make sure we loop over the largest range to get the most pixels on the display 00379 // for instance, if drawing a vertical line (x_range = 0), we need to loop down the y pixels 00380 // or else we'll only end up with 1 pixel in the x column 00381 if ( abs(x_range) > abs(y_range) ) { 00382 00383 // ensure we loop from smallest to largest or else for-loop won't run as expected 00384 start = x1>x0 ? x0:x1; 00385 stop = x1>x0 ? x1:x0; 00386 00387 // loop between x pixels 00388 for (int x = start; x<= stop ; x+=step) { 00389 // do linear interpolation 00390 int y = y0 + (y1-y0)*(x-x0)/(x1-x0); 00391 00392 if (type == 0) // if 'white' line, turn off pixel 00393 clearPixel(x,y); 00394 else 00395 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel 00396 } 00397 } else { 00398 00399 // ensure we loop from smallest to largest or else for-loop won't run as expected 00400 start = y1>y0 ? y0:y1; 00401 stop = y1>y0 ? y1:y0; 00402 00403 for (int y = start; y<= stop ; y+=step) { 00404 // do linear interpolation 00405 int x = x0 + (x1-x0)*(y-y0)/(y1-y0); 00406 00407 if (type == 0) // if 'white' line, turn off pixel 00408 clearPixel(x,y); 00409 else 00410 setPixel(x,y); // else if 'black' or 'dotted' turn on pixel 00411 00412 } 00413 } 00414 00415 } 00416 00417 void N5110::drawRect(unsigned int const x0, 00418 unsigned int const y0, 00419 unsigned int const width, 00420 unsigned int const height, 00421 FillType const fill) 00422 { 00423 if (fill == FILL_TRANSPARENT) { // transparent, just outline 00424 drawLine(x0,y0,x0+(width-1),y0,1); // top 00425 drawLine(x0,y0+(height-1),x0+(width-1),y0+(height-1),1); // bottom 00426 drawLine(x0,y0,x0,y0+(height-1),1); // left 00427 drawLine(x0+(width-1),y0,x0+(width-1),y0+(height-1),1); // right 00428 } else { // filled rectangle 00429 int type = (fill==FILL_BLACK) ? 1:0; // black or white fill 00430 for (int y = y0; y<y0+height; y++) { // loop through rows of rectangle 00431 drawLine(x0,y,x0+(width-1),y,type); // draw line across screen 00432 } 00433 } 00434 } 00435 00436 void N5110::drawSprite(int x0, 00437 int y0, 00438 int nrows, 00439 int ncols, 00440 int *sprite) 00441 { 00442 for (int i = 0; i < nrows; i++) { 00443 for (int j = 0 ; j < ncols ; j++) { 00444 00445 int pixel = *((sprite+i*ncols)+j); 00446 00447 if (pixel) { 00448 setPixel(x0+j,y0+i); 00449 } 00450 else { 00451 clearPixel(x0+j,y0+i); 00452 } 00453 00454 } 00455 } 00456 }
Generated on Mon Jul 18 2022 14:19:10 by
