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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DOGS102.cpp Source File

DOGS102.cpp

Go to the documentation of this file.
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