Class Module for EA DOGS102 Graphic LCD display SPI Interface
Dependents: mDotEVBM2X MTDOT-EVB-LinkCheck-AL MTDOT-EVBDemo-DRH MTDOT_BOX_EVB_LCD_Helloworld ... more
DOGS102.cpp
00001 /** 00002 * @file DOGS102.cpp 00003 * @brief Device driver - DOGS102 102x64 pixel Graphic LCD display W/RTOS Support 00004 * @author Tim Barr 00005 * @version 1.01 00006 * @see http://www.lcd-module.com/eng/pdf/grafik/dogs102-6e.pdf 00007 * @see http://www.lcd-module.com/eng/pdf/zubehoer/uc1701.pdf 00008 * 00009 * Copyright (c) 2015 00010 * 00011 * Licensed under the Apache License, Version 2.0 (the "License"); 00012 * you may not use this file except in compliance with the License. 00013 * You may obtain a copy of the License at 00014 * 00015 * http://www.apache.org/licenses/LICENSE-2.0 00016 * 00017 * Unless required by applicable law or agreed to in writing, software 00018 * distributed under the License is distributed on an "AS IS" BASIS, 00019 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00020 * See the License for the specific language governing permissions and 00021 * limitations under the License. 00022 * 00023 * 07/08/15 TAB Fixed error boundary check error in endUpdate 00024 */ 00025 00026 #include "DOGS102.h" 00027 #include "mbed_debug.h" 00028 #include "rtos.h" 00029 00030 // macro to make sure x falls into range from low to high (inclusive) 00031 #define CLIP(x, low, high) { if ( (x) < (low) ) x = (low); if ( (x) > (high) ) x = (high); } while (0); 00032 00033 DOGS102::DOGS102(SPI &spi, DigitalOut &lcd_cs, DigitalOut &cmnd_data) 00034 { 00035 _spi = &spi; 00036 _lcd_cs = &lcd_cs; 00037 _cmnd_data = &cmnd_data; 00038 00039 DOGS102::init(); 00040 00041 return; 00042 } 00043 uint8_t DOGS102::setCursor(uint8_t xcur, uint8_t ycur) 00044 { 00045 uint8_t ypage; 00046 uint8_t y_shift; 00047 00048 CLIP(xcur, 0, LCDWIDTH-1); 00049 ypage = ycur/8; 00050 CLIP(ypage, 0, LCDPAGES-1); 00051 y_shift = ycur % 8; 00052 DOGS102::writeCommand(SETPGADDR,ypage); 00053 DOGS102::writeCommand(SETCOLADDRMSB,xcur>>4); 00054 DOGS102::writeCommand(SETCOLADDRLSB,xcur); 00055 return y_shift; 00056 } 00057 00058 void DOGS102::clearBuffer(void) 00059 { 00060 memset(_lcdbuffer, 0, sizeof(_lcdbuffer)); 00061 00062 if (!_update_flag) 00063 { 00064 DOGS102::sendBuffer(_lcdbuffer); 00065 } 00066 00067 } 00068 00069 void DOGS102::writeText(uint8_t column, uint8_t page, const uint8_t *font_address, const char *text, const uint8_t size) 00070 { 00071 // Position of character data in memory array 00072 uint16_t pos_array; 00073 // temporary column, page address, and column_cnt are used 00074 // to stay inside display area 00075 uint8_t i,y, column_cnt = 0; 00076 00077 // font information, needed for calculation 00078 uint8_t start_code, last_code, width, page_height, bytes_p_char; 00079 00080 uint8_t *txtbuffer; 00081 00082 start_code = font_address[2]; // get first defined character 00083 last_code = font_address[3]; // get last defined character 00084 width = font_address[4]; // width in pixel of one char 00085 page_height = font_address[6]; // page count per char 00086 bytes_p_char = font_address[7]; // bytes per char 00087 00088 if(page_height + page > LCDPAGES) //stay inside display area 00089 page_height = LCDPAGES - page; 00090 00091 // The string is displayed character after character. If the font has more then one page, 00092 // the top page is printed first, then the next page and so on 00093 for(y = 0; y < page_height; y++) 00094 { 00095 txtbuffer = &_lcdbuffer[page*LCDWIDTH + column]; 00096 column_cnt = 0; // clear column_cnt start point 00097 i = 0; 00098 while(( i < size) && ((column_cnt + column) < LCDWIDTH)) 00099 { 00100 if(text[i] < start_code || (uint8_t)text[i] > last_code) //make sure data is valid 00101 i++; 00102 else 00103 { 00104 // calculate position of ASCII character in font array 00105 // bytes for header + (ASCII - startcode) * bytes per char) 00106 pos_array = 8 + (uint8_t)(text[i++] - start_code) * bytes_p_char; 00107 00108 // get the dot pattern for the part of the char to print 00109 pos_array += y*width; 00110 00111 // stay inside display area 00112 if((column_cnt + width + column) > LCDWIDTH) 00113 column_cnt = LCDWIDTH-width; 00114 00115 // copy character data to buffer 00116 memcpy (txtbuffer+column_cnt,font_address+pos_array,width); 00117 } 00118 00119 column_cnt += width; 00120 } 00121 if (!_update_flag) 00122 { 00123 setCursor(column,(page+y)*8); // set start position x and y 00124 DOGS102::writeData(txtbuffer,column_cnt); 00125 } 00126 } 00127 } 00128 00129 void DOGS102::writeBitmap(uint8_t column, uint8_t page, const uint8_t *bm_address) 00130 { 00131 uint8_t width, page_cnt, bm_pntr; 00132 00133 width = bm_address[0]; 00134 page_cnt = (bm_address[1] + 7) / 8; //height in pages, add 7 and divide by 8 for getting the used pages (byte boundaries) 00135 00136 if(width + column > LCDWIDTH) //stay inside display area 00137 width = LCDWIDTH - column; 00138 if(page_cnt + page > LCDPAGES) 00139 page_cnt = LCDPAGES - page; 00140 00141 for (uint8_t i=0;i < page_cnt;i++ ) 00142 { 00143 bm_pntr = 2+i*width; 00144 memcpy(_lcdbuffer+column+((i+page)*LCDWIDTH),bm_address+bm_pntr, width); 00145 } 00146 00147 if (_update_flag == 0) 00148 { 00149 DOGS102::sendBuffer(_lcdbuffer); 00150 } 00151 } 00152 00153 void DOGS102::startUpdate(void) 00154 { 00155 _update_flag++; 00156 } 00157 00158 void DOGS102::endUpdate(void) 00159 { 00160 if (_update_flag != 0) 00161 _update_flag--; 00162 00163 if (_update_flag == 0) 00164 { 00165 DOGS102::sendBuffer(_lcdbuffer); 00166 } 00167 } 00168 00169 uint8_t DOGS102::getUpdateState(void) 00170 { 00171 return _update_flag; 00172 } 00173 00174 uint8_t DOGS102::init(void) 00175 { 00176 uint8_t result = 0; 00177 00178 _spi->frequency(4000000); 00179 _spi->format(8,3); // 8bit transfers, SPI mode 3 00180 _lcd_cs->write(1); // initialize chip select pin 00181 _cmnd_data->write(1); // initialize command/data pin 00182 _update_flag = 0; // initialize update semaphore 00183 00184 // Reset all registers to POR values 00185 // result = DOGS102::writeCommand(SOFTRESET); 00186 osDelay(50); 00187 00188 // send initial setup commands to power up the display 00189 result |= DOGS102::writeCommand(SETSCROLLLINE,0x00); // set scroll line to 0 00190 result |= DOGS102::writeCommand(SETSEGDIR,0x01); // set reverse seg direction 00191 result |= DOGS102::writeCommand(SETCOMDIR,0x00); // set normal com direction 00192 result |= DOGS102::writeCommand(SETALLPIXELON,0x00); // disable all pixel on mode 00193 result |= DOGS102::writeCommand(SETINVDISP,0x00); // Turn display inverse off 00194 result |= DOGS102::writeCommand(SETLCDBIAS,0x00); // set bias ratio to 1/9 00195 result |= DOGS102::writeCommand(SETPWRCTRL,0x07); // turn on booster,regulator and follower 00196 result |= DOGS102::writeCommand(SETVLCDRESRATIO,0x07); // Set resistor ratio tomax 00197 result |= DOGS102::writeCommand(SETELECVOL,0x10); // set contrast to 32 out of 63 00198 result |= DOGS102::writeCommand(SETAPROGCTRL,0x83); // enable wrap around bits 00199 result |= DOGS102::writeCommand(SETDISPEN,0x01); // set display enable bit 00200 00201 DOGS102::clearBuffer(); 00202 00203 if(result != 0) 00204 { 00205 debug("%s %d: ILS29011:init failed\n\r", __FILE__, __LINE__); 00206 } 00207 00208 return result; 00209 } 00210 00211 uint8_t DOGS102::writeCommand(uint8_t const reg, uint8_t const data) const 00212 { 00213 uint8_t buf; 00214 uint8_t result = 0; 00215 00216 switch (reg) // setup data byte for specific command register write 00217 { 00218 case SETCOLADDRLSB : 00219 // use COLMASK for data 00220 buf = SETCOLADDRLSB | (data & COLMASK); 00221 break; 00222 case SETCOLADDRMSB : 00223 // use COLMASK for data 00224 buf = SETCOLADDRMSB | (data & COLMASK); 00225 break; 00226 case SETPWRCTRL : 00227 // use PCMASK for data 00228 buf = SETPWRCTRL | (data & PCMASK); 00229 break; 00230 case SETSCROLLLINE : 00231 // use SLMASK for data 00232 buf = SETSCROLLLINE | (data & SLMASK); 00233 break; 00234 case SETPGADDR : 00235 // use COLMASK for data 00236 buf = SETPGADDR | (data & COLMASK); 00237 break; 00238 case SETVLCDRESRATIO : 00239 // use PCMASK for data 00240 buf = SETVLCDRESRATIO | (data & PCMASK); 00241 break; 00242 case SETELECVOL : 00243 // double byte command use SLMASK for data 00244 buf = data & SLMASK; 00245 break; 00246 case SETALLPIXELON : 00247 // use LSBMASK for data 00248 buf = SETALLPIXELON | (data & LSBMASK); 00249 break; 00250 case SETINVDISP : 00251 // use LSBMASK for data 00252 buf = SETINVDISP | (data & LSBMASK); 00253 break; 00254 case SETDISPEN : 00255 // use LSBMASK for data 00256 buf = SETDISPEN | (data & LSBMASK); 00257 break; 00258 case SETSEGDIR : 00259 // use LSBMASK for data 00260 buf = SETSEGDIR | (data & LSBMASK); 00261 break; 00262 case SETLCDBIAS : 00263 // use LSBMASK for data 00264 buf = SETLCDBIAS | (data & LSBMASK); 00265 break; 00266 case SETCOMDIR : 00267 // use LC1MASK for data 00268 buf = SETCOMDIR | ((data << 3) & COLMASK); 00269 break; 00270 case SOFTRESET : 00271 // no data mask needed 00272 buf = SOFTRESET; 00273 break; 00274 case SETAPROGCTRL : 00275 // Double byte command use WAMASK and TCMASK for data 00276 buf = data & (COLMASK | TCMASK); 00277 break; 00278 default : 00279 debug("Command Register not valid\n\r"); 00280 result = 1; 00281 } 00282 00283 if (result == 0) 00284 { 00285 _spi->frequency(4000000); 00286 _spi->format(8,3); // 8bit transfers, SPI mode 3 00287 00288 _lcd_cs->write (0); // enable LCD SPI interface 00289 _cmnd_data->write(0); // set to command mode 00290 00291 switch (reg) // send first byte of double byte command for these register 00292 { 00293 case SETELECVOL : 00294 case SETAPROGCTRL : 00295 _spi->write(reg); 00296 break; 00297 } 00298 00299 _spi->write(buf); // send command register 00300 00301 _cmnd_data->write(1); // set back to data mode 00302 _lcd_cs->write(1); // disable LCD SPI Interface 00303 00304 } 00305 00306 if(result != 0) 00307 { 00308 debug("DOGS102:writeCommand failed\n\r"); 00309 } 00310 00311 return result; 00312 } 00313 00314 void DOGS102::writeData(const uint8_t* data, uint8_t count) const 00315 { 00316 uint8_t result = 0; 00317 uint8_t i; 00318 00319 _spi->frequency(4000000); 00320 _spi->format(8,3); // 8bit transfers, SPI mode 3 00321 00322 _lcd_cs->write(0); // enable LCD SPI interface 00323 i = 0; // initialize transfer counter 00324 00325 do 00326 { 00327 _spi->write(data[i]); 00328 i++; 00329 } while ((result == 0) && (i <= count)) ; 00330 00331 _lcd_cs->write(1); // disable LCD SPI interface 00332 00333 return; 00334 } 00335 00336 void DOGS102::sendBuffer(const uint8_t* buffer) 00337 { 00338 //debug("Sending LCD Buffer\n"); 00339 for (int i=0; i<LCDPAGES; i++) 00340 { 00341 DOGS102::setCursor(0,i*8); 00342 DOGS102::writeData(buffer + i*LCDWIDTH, LCDWIDTH); 00343 } 00344 } 00345
Generated on Sat Jul 16 2022 10:59:31 by
1.7.2