Port of the Adafruit PCD8544 Driver @ https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library for use in MBED Inital version only supports hardware SPI, and has been tested on a Nucleo test board. BSD license
Adafruit_PCD8544.cpp
00001 /********************************************************************* 00002 This is a library for our Monochrome Nokia 5110 LCD Displays 00003 00004 Pick one up today in the adafruit shop! 00005 ------> http://www.adafruit.com/products/338 00006 00007 These displays use SPI to communicate, 4 or 5 pins are required to 00008 interface 00009 00010 Adafruit invests time and resources providing this open source code, 00011 please support Adafruit and open-source hardware by purchasing 00012 products from Adafruit! 00013 00014 Written by Limor Fried/Ladyada for Adafruit Industries. 00015 BSD license, check license.txt for more information 00016 All text above, and the splash screen below must be included in any redistribution 00017 00018 00019 Modified for MBED usage and tested with STM32F411RE on a Nucleo board. 00020 Hardware SPI only, tested using default arduino pin out D11/D13 for MOSI/SCLK, Support provided for different pin layouts 00021 by James Kidd 2014 00022 *********************************************************************/ 00023 00024 #ifndef _BV 00025 #define _BV( bit ) ( 1<<(bit) ) 00026 #endif 00027 //#include <Wire.h> 00028 #include <stdint.h> 00029 #include <Adafruit_GFX.h> 00030 //#include "Adafruit_GFX.h" 00031 #include "Adafruit_PCD8544.h" 00032 00033 // the memory buffer for the LCD 00034 uint8_t pcd8544_buffer[LCDWIDTH * LCDHEIGHT / 8] = { 00035 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00037 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFC, 0xE0, 00038 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00039 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00040 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00041 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 00042 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x7F, 00043 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00046 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 00047 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x87, 0x8F, 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 00048 0xC1, 0xC0, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 00049 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00051 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00052 0x00, 0x80, 0xC0, 0xE0, 0xF1, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x0F, 0x87, 00053 0xE7, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x3F, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFD, 0xFF, 00054 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 00055 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00056 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00057 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 00058 0x7E, 0x3F, 0x3F, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xE0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 00059 0xFF, 0xFC, 0xF0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 00060 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 00063 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 00064 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00065 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00066 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 00067 }; 00068 00069 00070 // reduces how much is refreshed, which speeds it up! 00071 // originally derived from Steve Evans/JCW's mod but cleaned up and 00072 // optimized 00073 //#define enablePartialUpdate 00074 00075 #ifdef enablePartialUpdate 00076 static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax; 00077 #endif 00078 00079 00080 00081 static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) { 00082 #ifdef enablePartialUpdate 00083 if (xmin < xUpdateMin) xUpdateMin = xmin; 00084 if (xmax > xUpdateMax) xUpdateMax = xmax; 00085 if (ymin < yUpdateMin) yUpdateMin = ymin; 00086 if (ymax > yUpdateMax) yUpdateMax = ymax; 00087 #endif 00088 } 00089 00090 00091 /* 00092 * 3,4,5 by default with D13(sclk)/D11(mosi) used by default for SPI 00093 */ 00094 Adafruit_PCD8544::Adafruit_PCD8544(PinName RST, PinName CS,PinName DC,PinName MOSI,PinName SCLK ): Adafruit_GFX(LCDWIDTH,LCDHEIGHT) { 00095 _din = -1; 00096 _sclk = -1; 00097 _dc = 1; 00098 _rst = 1; 00099 _cs = 1; 00100 myPins.rst = RST; 00101 myPins.sce = CS; 00102 myPins.dc = DC; 00103 myPins.mosi = MOSI; 00104 myPins.miso = NC; 00105 myPins.sclk = SCLK; 00106 } 00107 /* 00108 * 3,4,5 by default with D13(sclk)/D11(mosi) used by default for SPI 00109 */ 00110 Adafruit_PCD8544::Adafruit_PCD8544(PinName RST, PinName CS,PinName DC ): Adafruit_GFX(LCDWIDTH,LCDHEIGHT) { 00111 _din = -1; 00112 _sclk = -1; 00113 _dc = 1; 00114 _rst = 1; 00115 _cs = 1; 00116 myPins.rst = RST; 00117 myPins.sce = CS; 00118 myPins.dc = DC; 00119 myPins.mosi = D11; 00120 myPins.miso = NC; 00121 myPins.sclk = D13; 00122 } 00123 00124 00125 // the most basic function, set a single pixel 00126 void Adafruit_PCD8544::drawPixel(int16_t x, int16_t y, uint16_t color) { 00127 if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) 00128 return; 00129 00130 int16_t t; 00131 switch(rotation){ 00132 case 1: 00133 t = x; 00134 x = y; 00135 y = LCDHEIGHT - 1 - t; 00136 break; 00137 case 2: 00138 x = LCDWIDTH - 1 - x; 00139 y = LCDHEIGHT - 1 - y; 00140 break; 00141 case 3: 00142 t = x; 00143 x = LCDWIDTH - 1 - y; 00144 y = t; 00145 break; 00146 } 00147 00148 if ((x < 0) || (x >= LCDWIDTH) || (y < 0) || (y >= LCDHEIGHT)) 00149 return; 00150 00151 // x is which column 00152 if (color) 00153 pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8); 00154 else 00155 pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8); 00156 00157 updateBoundingBox(x,y,x,y); 00158 } 00159 00160 00161 // the most basic function, get a single pixel 00162 uint8_t Adafruit_PCD8544::getPixel(int8_t x, int8_t y) { 00163 if ((x < 0) || (x >= LCDWIDTH) || (y < 0) || (y >= LCDHEIGHT)) 00164 return 0; 00165 00166 return (pcd8544_buffer[x+ (y/8)*LCDWIDTH] >> (y%8)) & 0x1; 00167 } 00168 00169 00170 void Adafruit_PCD8544::begin(uint8_t contrast, uint8_t bias) { 00171 00172 00173 if (isHardwareSPI()) { 00174 // Setup hardware SPI. 00175 LcdSPI = new SPI(myPins.mosi,NC,myPins.sclk); 00176 LcdSPI->format(LCD_SPI_BITS, LCD_SPI_MODE); 00177 LcdSPI->frequency(LCD_FREQ); 00178 } 00179 else { 00180 // Setup software SPI. 00181 00182 // Set software SPI specific pin outputs. 00183 /* pinMode(_din, OUTPUT); 00184 pinMode(_sclk, OUTPUT); 00185 00186 // Set software SPI ports and masks. 00187 clkport = portOutputRegister(digitalPinToPort(_sclk)); 00188 clkpinmask = digitalPinToBitMask(_sclk); 00189 mosiport = portOutputRegister(digitalPinToPort(_din)); 00190 mosipinmask = digitalPinToBitMask(_din);*/ 00191 } 00192 Pins = new DigitalOut*[3]; 00193 Pins[PIN_RST] = new DigitalOut(myPins.rst); 00194 Pins[PIN_SCE] = new DigitalOut(myPins.sce); 00195 Pins[PIN_DC] = new DigitalOut(myPins.dc); 00196 00197 00198 // Set common pin outputs. 00199 /*pinMode(_dc, OUTPUT); 00200 if (_rst > 0) 00201 pinMode(_rst, OUTPUT); 00202 if (_cs > 0) 00203 pinMode(_cs, OUTPUT);*/ 00204 00205 // toggle RST low to reset 00206 if (_rst > 0) { 00207 Pins[PIN_RST]->write(0); 00208 wait_ms(500); 00209 Pins[PIN_RST]->write(1); 00210 } 00211 00212 // get into the EXTENDED mode! 00213 command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 00214 00215 // LCD bias select (4 is optimal?) 00216 command(PCD8544_SETBIAS | bias); 00217 00218 // set VOP 00219 if (contrast > 0x7f) 00220 contrast = 0x7f; 00221 00222 command( PCD8544_SETVOP | contrast); // Experimentally determined 00223 00224 00225 // normal mode 00226 command(PCD8544_FUNCTIONSET); 00227 00228 // Set display to Normal 00229 command(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL); 00230 00231 // initial display line 00232 // set page address 00233 // set column address 00234 // write display data 00235 00236 // set up a bounding box for screen updates 00237 00238 updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 00239 // Push out pcd8544_buffer to the Display (will show the AFI logo) 00240 display(); 00241 } 00242 00243 00244 inline void Adafruit_PCD8544::spiWrite(uint8_t d) { 00245 if (isHardwareSPI()) { 00246 // Hardware SPI write. 00247 LcdSPI->write(d); 00248 //SPI.transfer(d); 00249 } 00250 else { 00251 // Software SPI write with bit banging. 00252 for(uint8_t bit = 0x80; bit; bit >>= 1) { 00253 *clkport &= ~clkpinmask; 00254 if(d & bit) *mosiport |= mosipinmask; 00255 else *mosiport &= ~mosipinmask; 00256 *clkport |= clkpinmask; 00257 } 00258 } 00259 } 00260 00261 bool Adafruit_PCD8544::isHardwareSPI() { 00262 return (_din == -1 && _sclk == -1); 00263 } 00264 00265 void Adafruit_PCD8544::command(uint8_t c) { 00266 Pins[PIN_DC]->write(0); 00267 //digitalWrite(_dc, LOW); 00268 if (_cs > 0) 00269 Pins[PIN_SCE]->write(0); 00270 //digitalWrite(_cs, LOW); 00271 spiWrite(c); 00272 if (_cs > 0) 00273 Pins[PIN_SCE]->write(1); 00274 //digitalWrite(_cs, HIGH); 00275 } 00276 00277 void Adafruit_PCD8544::data(uint8_t c) { 00278 Pins[PIN_DC]->write(1); 00279 //digitalWrite(_dc, HIGH); 00280 if (_cs > 0) 00281 Pins[PIN_SCE]->write(0);//digitalWrite(_cs, LOW); 00282 spiWrite(c); 00283 if (_cs > 0) 00284 Pins[PIN_SCE]->write(1);//digitalWrite(_cs, HIGH); 00285 } 00286 00287 void Adafruit_PCD8544::setContrast(uint8_t val) { 00288 if (val > 0x7f) { 00289 val = 0x7f; 00290 } 00291 command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 00292 command( PCD8544_SETVOP | val); 00293 command(PCD8544_FUNCTIONSET); 00294 00295 } 00296 00297 00298 00299 void Adafruit_PCD8544::display(void) { 00300 uint8_t col, maxcol, p; 00301 00302 for(p = 0; p < 6; p++) { 00303 #ifdef enablePartialUpdate 00304 // check if this page is part of update 00305 if ( yUpdateMin >= ((p+1)*8) ) { 00306 continue; // nope, skip it! 00307 } 00308 if (yUpdateMax < p*8) { 00309 break; 00310 } 00311 #endif 00312 00313 command(PCD8544_SETYADDR | p); 00314 00315 00316 #ifdef enablePartialUpdate 00317 col = xUpdateMin; 00318 maxcol = xUpdateMax; 00319 #else 00320 // start at the beginning of the row 00321 col = 0; 00322 maxcol = LCDWIDTH-1; 00323 #endif 00324 00325 command(PCD8544_SETXADDR | col); 00326 Pins[PIN_DC]->write(1); 00327 //digitalWrite(_dc, HIGH); 00328 if (_cs > 0) 00329 Pins[PIN_SCE]->write(0);//digitalWrite(_cs, LOW); 00330 for(; col <= maxcol; col++) { 00331 spiWrite(pcd8544_buffer[(LCDWIDTH*p)+col]); 00332 } 00333 if (_cs > 0) 00334 Pins[PIN_SCE]->write(1);//digitalWrite(_cs, HIGH); 00335 00336 } 00337 00338 command(PCD8544_SETYADDR ); // no idea why this is necessary but it is to finish the last byte? 00339 #ifdef enablePartialUpdate 00340 xUpdateMin = LCDWIDTH - 1; 00341 xUpdateMax = 0; 00342 yUpdateMin = LCDHEIGHT-1; 00343 yUpdateMax = 0; 00344 #endif 00345 00346 } 00347 00348 // clear everything 00349 void Adafruit_PCD8544::clearDisplay(void) { 00350 memset(pcd8544_buffer, 0, LCDWIDTH*LCDHEIGHT/8); 00351 updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 00352 cursor_y = cursor_x = 0; 00353 } 00354 00355 /* 00356 // this doesnt touch the buffer, just clears the display RAM - might be handy 00357 void Adafruit_PCD8544::clearDisplay(void) { 00358 00359 uint8_t p, c; 00360 00361 for(p = 0; p < 8; p++) { 00362 00363 st7565_command(CMD_SET_PAGE | p); 00364 for(c = 0; c < 129; c++) { 00365 //uart_putw_dec(c); 00366 //uart_putchar(' '); 00367 st7565_command(CMD_SET_COLUMN_LOWER | (c & 0xf)); 00368 st7565_command(CMD_SET_COLUMN_UPPER | ((c >> 4) & 0xf)); 00369 st7565_data(0x0); 00370 } 00371 } 00372 00373 } 00374 00375 */
Generated on Tue Jul 26 2022 01:34:34 by 1.7.2