Sparkfun's Nokia Color LCD Arduino Shield library for FRDM boards
Dependents: ColorLCDShield_Conway
ColorLCDShield.cpp
00001 // ==================================================== Nov 08 2013, kayeks == 00002 // ColorLCDShield.cpp 00003 // =========================================================================== 00004 // Sparkfun's Color LCD Shield (LCD-09363) library for mbed FRDM-KL25Z boards. 00005 // - https://www.sparkfun.com/products/9363 00006 // This library has modified from Sparkfun's Arduino library code 00007 // - Command/data transmissions are implemented as software SPI communication 00008 // because the FRDM board's MCUs are not 9-bit SPI capable :( 00009 // - License is `CC BY-SA 3.0' 00010 // - Original descriptions are below 00011 00012 /* 00013 LCDShield.cpp - Arduino Library to control a Nokia 6100 LCD, 00014 specifically that found on SparkFun's Color LCD Shield. 00015 This code should work for both Epson and Phillips display drivers 00016 normally found on the Color LCD Shield. 00017 00018 License: CC BY-SA 3.0: Creative Commons Share-alike 3.0. Feel free 00019 to use and abuse this code however you'd like. If you find it useful 00020 please attribute, and SHARE-ALIKE! 00021 00022 This is based on code by Mark Sproul, and Peter Davenport. 00023 Thanks to Coleman Sellers and Harold Timmis for help getting it to work with the Phillips Driver 7-31-2011 00024 */ 00025 00026 #include "ColorLCDShield.h" 00027 00028 /*extern "C" { 00029 #include "wiring.h" 00030 }*/ 00031 00032 #include "mbed.h" 00033 // #include "Arduino.h" 00034 00035 // static char x_offset = 0; 00036 // static char y_offset = 0; 00037 00038 DigitalOut res(D8); // Arduino D8 00039 DigitalOut cs(D9); // Arduino D9 00040 DigitalOut dio(D11); // Arduino D11 00041 DigitalOut sck(D13); // Arduino D13 00042 00043 LCDShield::LCDShield() 00044 { 00045 } 00046 00047 void LCDShield::LCDCommand(unsigned char data) 00048 { 00049 char jj; 00050 00051 cs = 0; // enable chip 00052 dio = 0; // output low on data out (9th bit low = command) 00053 00054 sck = 0; // send clock pulse 00055 // wait_us(1); 00056 sck = 1; 00057 00058 for (jj = 0; jj < 8; jj++) 00059 { 00060 if ((data & 0x80) == 0x80) 00061 dio = 1; 00062 else 00063 dio = 0; 00064 00065 sck = 0; // send clock pulse 00066 // wait_us(1); 00067 sck = 1; 00068 00069 data <<= 1; 00070 } 00071 00072 cs = 1; // disable 00073 } 00074 00075 void LCDShield::LCDData(unsigned char data) 00076 { 00077 char j; 00078 00079 cs = 0; // enable chip 00080 dio = 1; // output high on data out (9th bit high = data) 00081 00082 sck = 0; // send clock pulse 00083 // wait_us(1); 00084 sck = 1; // send clock pulse 00085 00086 for (j = 0; j < 8; j++) 00087 { 00088 if ((data & 0x80) == 0x80) 00089 dio = 1; 00090 else 00091 dio = 0; 00092 00093 sck = 0; // send clock pulse 00094 // wait_us(1); 00095 sck = 1; 00096 00097 data <<= 1; 00098 } 00099 00100 cs = 1; // disable 00101 } 00102 00103 void LCDShield::init(int type, bool colorSwap) 00104 { 00105 driver = type; 00106 00107 // Initialize the control pins, and reset display: 00108 sck = 0; // CLK = LOW 00109 dio = 0; // DIO = LOW 00110 wait_us(10); // 10us delay 00111 cs = 1; // CS = HIGH 00112 wait_us(10); // 10uS Delay 00113 res = 0; // RESET = LOW 00114 wait_ms(200); // 200ms delay 00115 res = 1; // RESET = HIGH 00116 wait_ms(200); // 200ms delay 00117 sck = 1; // SCK_PIN = HIGH 00118 dio = 1; // DIO = HIGH 00119 wait_us(10); // 10us delay 00120 00121 if (driver == EPSON) 00122 { 00123 LCDCommand(DISCTL); // Display control (0xCA) 00124 LCDData(0x0C); // 12 = 1100 - CL dividing ratio [don't divide] switching period 8H (default) 00125 LCDData(0x20); // nlines/4 - 1 = 132/4 - 1 = 32 duty 00126 LCDData(0x00); // No inversely highlighted lines 00127 00128 LCDCommand(COMSCN); // common scanning direction (0xBB) 00129 LCDData(0x01); // 1->68, 132<-69 scan direction 00130 00131 LCDCommand(OSCON); // internal oscialltor ON (0xD1) 00132 LCDCommand(SLPOUT); // sleep out (0x94) 00133 00134 LCDCommand(PWRCTR); // power ctrl (0x20) 00135 LCDData(0x0F); // everything on, no external reference resistors 00136 00137 LCDCommand(DISINV); // invert display mode (0xA7) 00138 00139 LCDCommand(DATCTL); // data control (0xBC) 00140 LCDData(0x03); // Inverse page address, reverse rotation column address, column scan-direction !!! try 0x01 00141 LCDData(0x00); // normal RGB arrangement 00142 LCDData(0x02); // 16-bit Grayscale Type A (12-bit color) 00143 00144 LCDCommand(VOLCTR); // electronic volume, this is the contrast/brightness (0x81) 00145 LCDData(32); // volume (contrast) setting - fine tuning, original (0-63) 00146 LCDData(3); // internal resistor ratio - coarse adjustment (0-7) 00147 00148 LCDCommand(NOP); // nop (0x25) 00149 00150 wait_ms(100); 00151 00152 LCDCommand(DISON); // display on (0xAF) 00153 } 00154 else if (driver == PHILIPS) 00155 { 00156 LCDCommand(SLEEPOUT); // Sleep Out (0x11) 00157 LCDCommand(BSTRON); // Booster voltage on (0x03) 00158 LCDCommand(DISPON); // Display on (0x29) 00159 00160 //LCDCommand(INVON); // Inversion on (0x20) 00161 00162 // 12-bit color pixel format: 00163 LCDCommand(COLMOD); // Color interface format (0x3A) 00164 LCDData(0x03); // 0b011 is 12-bit/pixel mode 00165 00166 LCDCommand(MADCTL); // Memory Access Control(PHILLIPS) 00167 if (colorSwap) 00168 LCDData(0x08); 00169 else 00170 LCDData(0x00); 00171 00172 LCDCommand(SETCON); // Set Contrast(PHILLIPS) 00173 LCDData(0x30); 00174 00175 LCDCommand(NOPP); // nop(PHILLIPS) 00176 } 00177 } 00178 00179 void LCDShield::clear(int color) 00180 { 00181 if (driver) // if it's an Epson 00182 { 00183 LCDCommand(PASET); 00184 LCDData(0); 00185 LCDData(131); 00186 00187 LCDCommand(CASET); 00188 LCDData(0); 00189 LCDData(131); 00190 00191 LCDCommand(RAMWR); 00192 } 00193 else // otherwise it's a phillips 00194 { 00195 LCDCommand(PASETP); 00196 LCDData(0); 00197 LCDData(131); 00198 00199 LCDCommand(CASETP); 00200 LCDData(0); 00201 LCDData(131); 00202 00203 LCDCommand(RAMWRP); 00204 } 00205 00206 for(unsigned int i=0; i < (131*131)/2; i++) 00207 { 00208 LCDData((color>>4)&0x00FF); 00209 LCDData(((color&0x0F)<<4)|(color>>8)); 00210 LCDData(color&0x0FF); 00211 } 00212 00213 // x_offset = 0; 00214 // y_offset = 0; 00215 } 00216 00217 void LCDShield::contrast(char setting) 00218 { 00219 if (driver == EPSON) 00220 { 00221 setting &= 0x3F; // 2 msb's not used, mask out 00222 LCDCommand(VOLCTR); // electronic volume, this is the contrast/brightness(EPSON) 00223 LCDData(setting); // volume (contrast) setting - course adjustment, -- original was 24 00224 LCDData(3); // TODO: Make this coarse adjustment variable, 3's a good place to stay 00225 } 00226 else if (driver == PHILIPS) 00227 { 00228 setting &= 0x7F; // msb is not used, mask it out 00229 LCDCommand(SETCON); // contrast command (PHILLIPS) 00230 LCDData(setting); // volume (contrast) setting - course adjustment, -- original was 24 00231 } 00232 } 00233 00234 // Added by Steve Sparks @ Big Nerd Ranch. 00235 // This swaps the Epson RGB order into the Philips RGB order. (Or, vice versa, I suppose.) 00236 uint16_t LCDShield::swapColors(uint16_t in) { 00237 return ((in & 0x000F)<<8)|(in & 0x00F0)|((in & 0x0F00)>>8); 00238 } 00239 00240 void LCDShield::setPixel(int color, unsigned char x, unsigned char y) 00241 { 00242 y = (COL_HEIGHT - 1) - y; 00243 x = (ROW_LENGTH - 1) - x; 00244 00245 if (driver == EPSON) // if it's an epson 00246 { 00247 LCDCommand(PASET); // page start/end ram 00248 LCDData(x); 00249 LCDData(ENDPAGE); 00250 00251 LCDCommand(CASET); // column start/end ram 00252 LCDData(y); 00253 LCDData(ENDCOL); 00254 00255 LCDCommand(RAMWR); // write 00256 LCDData((color>>4)&0x00FF); 00257 LCDData(((color&0x0F)<<4)|(color>>8)); 00258 LCDData(color&0x0FF); 00259 } 00260 else if (driver == PHILIPS) // otherwise it's a phillips 00261 { 00262 LCDCommand(PASETP); // page start/end ram 00263 LCDData(x); 00264 LCDData(x); 00265 00266 LCDCommand(CASETP); // column start/end ram 00267 LCDData(y); 00268 LCDData(y); 00269 00270 LCDCommand(RAMWRP); // write 00271 00272 LCDData((unsigned char)((color>>4)&0x00FF)); 00273 LCDData((unsigned char)(((color&0x0F)<<4)|0x00)); 00274 } 00275 } 00276 // 2/18/2013 This Methos added by Tony Contrada in order to create arc segments in varied line thickness, or Filled 00277 void LCDShield::setArc(int x0, int y0, int radius, int arcSegments[], int numSegments, int lineThickness, int color) 00278 { 00279 //Line Thickness (Num Pixels) 00280 if(lineThickness == FILL) lineThickness = radius; 00281 for(int i = 0; i < lineThickness; i++) 00282 { 00283 int f = 1 - radius; 00284 int ddF_x = 0; 00285 int ddF_y = -2 * radius; 00286 int x = 0; 00287 int y = radius; 00288 while(x < y) 00289 { 00290 if(f >= 0) 00291 { 00292 y--; 00293 ddF_y += 2; 00294 f += ddF_y; 00295 } 00296 x++; 00297 ddF_x += 2; 00298 f += ddF_x + 1; 00299 00300 for(int i = 0; i < numSegments; i++) 00301 { 00302 if(arcSegments[i] == NNE) setPixel(color, x0 - y, y0 + x); //SHOW NNE 00303 if(arcSegments[i] == ENE) setPixel(color, x0 - x, y0 + y); //SHOW ENE 00304 if(arcSegments[i] == ESE) setPixel(color, x0 + x, y0 + y); //SHOW ESE 00305 if(arcSegments[i] == SSE) setPixel(color, x0 + y, y0 + x); //SHOW SSE 00306 if(arcSegments[i] == SSW) setPixel(color, x0 + y, y0 - x); //SHOW SSW 00307 if(arcSegments[i] == WSW) setPixel(color, x0 + x, y0 - y); //SHOW WSW 00308 if(arcSegments[i] == WNW) setPixel(color, x0 - x, y0 - y); //SHOW WNW 00309 if(arcSegments[i] == NNW) setPixel(color, x0 - y, y0 - x); //SHOW NNW 00310 } 00311 00312 } 00313 radius--; 00314 } 00315 00316 } 00317 00318 // 2/22/2013 - Modified by Tony Contrada to include Line Thickness (in pixels) or a Filled Circle 00319 void LCDShield::setCircle (int x0, int y0, int radius, int color, int lineThickness) 00320 { 00321 if(lineThickness == FILL) lineThickness = radius; 00322 00323 for(int r = 0; r < lineThickness; r++) 00324 { 00325 int f = 1 - radius; 00326 int ddF_x = 0; 00327 int ddF_y = -2 * radius; 00328 int x = 0; 00329 int y = radius; 00330 00331 setPixel(color, x0, y0 + radius); 00332 setPixel(color, x0, y0 - radius); 00333 setPixel(color, x0 + radius, y0); 00334 setPixel(color, x0 - radius, y0); 00335 00336 while(x < y) 00337 { 00338 if(f >= 0) 00339 { 00340 y--; 00341 ddF_y += 2; 00342 f += ddF_y; 00343 } 00344 x++; 00345 ddF_x += 2; 00346 f += ddF_x + 1; 00347 00348 setPixel(color, x0 + x, y0 + y); 00349 setPixel(color, x0 - x, y0 + y); 00350 setPixel(color, x0 + x, y0 - y); 00351 setPixel(color, x0 - x, y0 - y); 00352 setPixel(color, x0 + y, y0 + x); 00353 setPixel(color, x0 - y, y0 + x); 00354 setPixel(color, x0 + y, y0 - x); 00355 setPixel(color, x0 - y, y0 - x); 00356 } 00357 radius--; 00358 } 00359 00360 } 00361 00362 void LCDShield::setChar(char c, int x, int y, int fColor, int bColor) 00363 { 00364 y = (COL_HEIGHT - 1) - y; // make display "right" side up 00365 x = (ROW_LENGTH - 2) - x; 00366 00367 int i,j; 00368 unsigned int nCols; 00369 unsigned int nRows; 00370 unsigned int nBytes; 00371 unsigned char PixelRow; 00372 unsigned char Mask; 00373 unsigned int Word0; 00374 unsigned int Word1; 00375 const unsigned char *pFont; 00376 const unsigned char *pChar; 00377 00378 // get pointer to the beginning of the selected font table 00379 pFont = *FONT8x16; 00380 // get the nColumns, nRows and nBytes 00381 nCols = *pFont; 00382 nRows = *(pFont + 1); 00383 nBytes = *(pFont + 2); 00384 // get pointer to the last byte of the desired character 00385 pChar = pFont + (nBytes * (c - 0x1F)) + nBytes - 1; 00386 00387 if (driver) // if it's an epson 00388 { 00389 // Row address set (command 0x2B) 00390 LCDCommand(PASET); 00391 LCDData(x); 00392 LCDData(x + nRows - 1); 00393 // Column address set (command 0x2A) 00394 LCDCommand(CASET); 00395 LCDData(y); 00396 LCDData(y + nCols - 1); 00397 00398 // WRITE MEMORY 00399 LCDCommand(RAMWR); 00400 // loop on each row, working backwards from the bottom to the top 00401 for (i = nRows - 1; i >= 0; i--) { 00402 // copy pixel row from font table and then decrement row 00403 PixelRow = *(pChar++); 00404 // loop on each pixel in the row (left to right) 00405 // Note: we do two pixels each loop 00406 Mask = 0x80; 00407 for (j = 0; j < nCols; j += 2) 00408 { 00409 // if pixel bit set, use foreground color; else use the background color 00410 // now get the pixel color for two successive pixels 00411 if ((PixelRow & Mask) == 0) 00412 Word0 = bColor; 00413 else 00414 Word0 = fColor; 00415 Mask = Mask >> 1; 00416 if ((PixelRow & Mask) == 0) 00417 Word1 = bColor; 00418 else 00419 Word1 = fColor; 00420 Mask = Mask >> 1; 00421 // use this information to output three data bytes 00422 LCDData((Word0 >> 4) & 0xFF); 00423 LCDData(((Word0 & 0xF) << 4) | ((Word1 >> 8) & 0xF)); 00424 LCDData(Word1 & 0xFF); 00425 } 00426 } 00427 } 00428 else 00429 { 00430 fColor = swapColors(fColor); 00431 bColor = swapColors(bColor); 00432 00433 // Row address set (command 0x2B) 00434 LCDCommand(PASETP); 00435 LCDData(x); 00436 LCDData(x + nRows - 1); 00437 // Column address set (command 0x2A) 00438 LCDCommand(CASETP); 00439 LCDData(y); 00440 LCDData(y + nCols - 1); 00441 00442 // WRITE MEMORY 00443 LCDCommand(RAMWRP); 00444 // loop on each row, working backwards from the bottom to the top 00445 pChar+=nBytes-1; // stick pChar at the end of the row - gonna reverse print on phillips 00446 for (i = nRows - 1; i >= 0; i--) { 00447 // copy pixel row from font table and then decrement row 00448 PixelRow = *(pChar--); 00449 // loop on each pixel in the row (left to right) 00450 // Note: we do two pixels each loop 00451 Mask = 0x01; // <- opposite of epson 00452 for (j = 0; j < nCols; j += 2) 00453 { 00454 // if pixel bit set, use foreground color; else use the background color 00455 // now get the pixel color for two successive pixels 00456 if ((PixelRow & Mask) == 0) 00457 Word0 = bColor; 00458 else 00459 Word0 = fColor; 00460 Mask = Mask << 1; // <- opposite of epson 00461 if ((PixelRow & Mask) == 0) 00462 Word1 = bColor; 00463 else 00464 Word1 = fColor; 00465 Mask = Mask << 1; // <- opposite of epson 00466 // use this information to output three data bytes 00467 LCDData((Word0 >> 4) & 0xFF); 00468 LCDData(((Word0 & 0xF) << 4) | ((Word1 >> 8) & 0xF)); 00469 LCDData(Word1 & 0xFF); 00470 } 00471 } 00472 } 00473 } 00474 00475 00476 void LCDShield::setStr(char *pString, int x, int y, int fColor, int bColor) 00477 { 00478 x = x + 16; 00479 y = y + 8; 00480 int originalY = y; 00481 00482 // loop until null-terminator is seen 00483 while (*pString != 0x00) { 00484 // draw the character 00485 setChar(*pString++, x, y, fColor, bColor); 00486 // advance the y position 00487 y = y + 8; 00488 // bail out if y exceeds 131 00489 if (y > 131) { 00490 x = x + 16; 00491 y = originalY; 00492 } 00493 if (x > 123) break; 00494 } 00495 } 00496 00497 void LCDShield::setLine(int x0, int y0, int x1, int y1, int color) 00498 { 00499 int dy = y1 - y0; // Difference between y0 and y1 00500 int dx = x1 - x0; // Difference between x0 and x1 00501 int stepx, stepy; 00502 00503 if (dy < 0) 00504 { 00505 dy = -dy; 00506 stepy = -1; 00507 } 00508 else 00509 stepy = 1; 00510 00511 if (dx < 0) 00512 { 00513 dx = -dx; 00514 stepx = -1; 00515 } 00516 else 00517 stepx = 1; 00518 00519 dy <<= 1; // dy is now 2*dy 00520 dx <<= 1; // dx is now 2*dx 00521 setPixel(color, x0, y0); 00522 00523 if (dx > dy) 00524 { 00525 int fraction = dy - (dx >> 1); 00526 while (x0 != x1) 00527 { 00528 if (fraction >= 0) 00529 { 00530 y0 += stepy; 00531 fraction -= dx; 00532 } 00533 x0 += stepx; 00534 fraction += dy; 00535 setPixel(color, x0, y0); 00536 } 00537 } 00538 else 00539 { 00540 int fraction = dx - (dy >> 1); 00541 while (y0 != y1) 00542 { 00543 if (fraction >= 0) 00544 { 00545 x0 += stepx; 00546 fraction -= dy; 00547 } 00548 y0 += stepy; 00549 fraction += dx; 00550 setPixel(color, x0, y0); 00551 } 00552 } 00553 } 00554 00555 void LCDShield::setRect(int x0, int y0, int x1, int y1, unsigned char fill, int color) 00556 { 00557 // check if the rectangle is to be filled 00558 if (fill == 1) 00559 { 00560 int xDiff; 00561 00562 if(x0 > x1) 00563 xDiff = x0 - x1; //Find the difference between the x vars 00564 else 00565 xDiff = x1 - x0; 00566 00567 while(xDiff > 0) 00568 { 00569 setLine(x0, y0, x0, y1, color); 00570 00571 if(x0 > x1) 00572 x0--; 00573 else 00574 x0++; 00575 00576 xDiff--; 00577 } 00578 00579 } 00580 else 00581 { 00582 // best way to draw an unfilled rectangle is to draw four lines 00583 setLine(x0, y0, x1, y0, color); 00584 setLine(x0, y1, x1, y1, color); 00585 setLine(x0, y0, x0, y1, color); 00586 setLine(x1, y0, x1, y1, color); 00587 } 00588 } 00589 00590 void LCDShield::printLogo(void) 00591 { 00592 int x = 4, y = 25, logo_ix = 0, z; 00593 char logo; 00594 00595 for (logo_ix = 0; logo_ix < 1120; logo_ix++) 00596 { 00597 logo = logo_spark[logo_ix]; 00598 for (z = 0; z < 8; z++) 00599 { 00600 if ((logo & 0x80) == 0x80) setPixel(RED, y, x); 00601 x++; 00602 if (x == 132) 00603 { 00604 x = 4; 00605 y++; 00606 } 00607 logo <<= 1; 00608 } 00609 } 00610 } 00611 00612 void LCDShield::off(void) 00613 { 00614 if (driver) // If it's an epson 00615 LCDCommand(DISOFF); 00616 else // otherwise it's a phillips 00617 LCDCommand(DISPOFF); 00618 } 00619 00620 void LCDShield::on(void) 00621 { 00622 if (driver) // If it's an epson 00623 LCDCommand(DISON); 00624 else // otherwise it's a phillips 00625 LCDCommand(DISPON); 00626 }
Generated on Tue Jul 12 2022 18:28:11 by 1.7.2