Darren Ulrich / UniGraphic

Dependents:   Bicycl_Computer_NUCLEO-F411RE Bicycl_Computer_NUCLEO-L476RG

Fork of UniGraphic by GraphicsDisplay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LCD.cpp Source File

LCD.cpp

00001 /* mbed UniGraphic library - universal LCD driver class
00002  * Copyright (c) 2015 Giuliano Dianda
00003  * Released under the MIT License: http://mbed.org/license/mit
00004  *
00005  * Derived work of:
00006  *
00007  * mbed library for the mbed Lab Board  128*32 pixel LCD
00008  * use C12832 controller
00009  * Copyright (c) 2012 Peter Drescher - DC2PD
00010  * Released under the MIT License: http://mbed.org/license/mit
00011  *
00012  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00013  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00014  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00015  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00016  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00017  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00018  * THE SOFTWARE.
00019  */
00020 
00021 #include "LCD.h"
00022 
00023 //#include "mbed_debug.h"
00024 
00025 #define SWAP(a, b)  { a ^= b; b ^= a; a ^= b; }
00026 
00027 
00028 LCD::LCD(proto_t displayproto, PortName port, PinName CS, PinName reset, PinName DC, PinName WR, PinName RD, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name)
00029     : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y), _LCDPAGES(lcdsize_y>>3), _IC_X_SEGS(ic_x_segs), _IC_Y_COMS(ic_y_coms), _IC_PAGES(ic_y_coms>>3)
00030 {
00031     if(displayproto==PAR_8) proto = new PAR8(port, CS, reset, DC, WR, RD);
00032     useNOP=false;
00033     buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
00034     buffer16 = (unsigned short*)buffer;
00035     draw_mode = NORMAL;
00036     set_orientation(1);
00037     foreground(White);
00038     background(Black);
00039     set_auto_up(true);
00040     tftID=0;
00041   //  cls();
00042   //  locate(0,0);
00043 }
00044 LCD::LCD(proto_t displayproto, int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC, const int lcdsize_x, const int lcdsize_y, const int ic_x_segs, const int ic_y_coms, const char *name)
00045     : GraphicsDisplay(name), screensize_X(lcdsize_x), screensize_Y(lcdsize_y), _LCDPAGES(lcdsize_y>>3), _IC_X_SEGS(ic_x_segs), _IC_Y_COMS(ic_y_coms), _IC_PAGES(ic_y_coms>>3)
00046 {
00047     if(displayproto==SPI_8)
00048     {
00049         proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC);
00050         useNOP=false;
00051     }
00052     else if(displayproto==SPI_16)
00053     {
00054         proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC);
00055         useNOP=true;
00056     }
00057     buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
00058     buffer16 = (unsigned short*)buffer;
00059     draw_mode = NORMAL;
00060   //  cls();
00061     set_orientation(1);
00062     foreground(White);
00063     background(Black);
00064     set_auto_up(true);
00065     tftID=0;
00066   //  locate(0,0);
00067 
00068 }
00069 LCD::~LCD()
00070 {
00071     free(buffer);
00072 }
00073 
00074 void LCD::wr_cmd8(unsigned char cmd)
00075     {
00076         if(useNOP) proto->wr_cmd16(0xE300|cmd); // E3 is NOP cmd for LCD
00077         else proto->wr_cmd8(cmd);
00078     }
00079 void LCD::wr_data8(unsigned char data)
00080     {
00081         proto->wr_data8(data);
00082     }
00083 void LCD::wr_cmd16(unsigned short cmd)
00084     {
00085         proto->wr_cmd16(cmd);
00086     }
00087 void LCD::wr_gram(unsigned short data, unsigned int count)
00088     {
00089         proto->wr_gram(data, count);
00090     }
00091 void LCD::wr_grambuf(unsigned short* data, unsigned int lenght)
00092     {
00093         proto->wr_grambuf(data, lenght);
00094     }
00095 void LCD::hw_reset()
00096     {
00097         proto->hw_reset();
00098     }
00099 void LCD::BusEnable(bool enable)
00100     {
00101         proto->BusEnable(enable);
00102     }
00103 
00104 
00105 
00106 // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays
00107 // for portrait views, XY swap will be done in sw in pixel() function
00108 void LCD::set_orientation(int o)
00109 {
00110     orientation = o;
00111     switch (o) {
00112         case (0):// portrait view -90°
00113             mirrorXY(Y);
00114             col_offset = 0;
00115             page_offset = _IC_PAGES-_LCDPAGES;
00116             set_width(screensize_Y);
00117             set_height(screensize_X);
00118         //    portrait = true;
00119             break;
00120         case (1): // default, landscape view 0°
00121             mirrorXY(NONE);
00122             col_offset = 0;
00123             page_offset = 0;
00124             set_width(screensize_X);
00125             set_height(screensize_Y);
00126        //     portrait = false;
00127             break;
00128         case (2):// portrait view +90°
00129             mirrorXY(X);
00130             col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram
00131             page_offset = 0;
00132             set_width(screensize_Y);
00133             set_height(screensize_X);
00134        //     portrait = true;
00135             break;
00136         case (3):// landscape view +180°
00137             mirrorXY(XY);
00138             col_offset = _IC_X_SEGS-screensize_X;
00139             page_offset = _IC_PAGES-_LCDPAGES;
00140             set_width(screensize_X);
00141             set_height(screensize_Y);
00142        //     portrait = false;
00143             break;
00144     }
00145 }
00146 void LCD::mirrorXY(mirror_t mode)
00147 {
00148     switch (mode)
00149     {
00150         case(NONE):
00151          //   wr_cmd8(0xA0);
00152             wr_cmd16(0xA0C8); // this is in real Y mirror command, but seems most displays have COMs wired inverted, so assume this is the default no-y-mirror
00153             break;
00154         case(X):
00155         //    wr_cmd8(0xA1);
00156             wr_cmd16(0xA1C8);
00157             break;
00158         case(Y):
00159         //    wr_cmd8(0xA0);
00160             wr_cmd16(0xA0C0);
00161             break;
00162         case(XY):
00163         //    wr_cmd8(0xA1);
00164             wr_cmd16(0xA1C0);
00165             break;
00166     }
00167 }
00168 void LCD::invert(unsigned char o)
00169 {
00170     if(o == 0) wr_cmd8(0xA6);
00171     else wr_cmd8(0xA7);
00172 }
00173 
00174 void LCD::set_contrast(int o)
00175 {
00176     contrast = o;
00177  //   wr_cmd8(0x81);      //  set volume
00178     wr_cmd16(0x8100|(o&0x3F));
00179 }
00180 
00181 int LCD::get_contrast(void)
00182 {
00183     return(contrast);
00184 }
00185 void LCD::window(int x, int y, int w, int h) {
00186     // current pixel location
00187     cur_x = x;
00188     cur_y = y;
00189     // window settings
00190     win_x1 = x;
00191     win_x2 = x + w - 1;
00192     win_y1 = y;
00193     win_y2 = y + h - 1;
00194 }
00195 void LCD::window_pushpixel(unsigned short color) {
00196     pixel(cur_x, cur_y, color);
00197     cur_x++;
00198     if(cur_x > win_x2) {
00199         cur_x = win_x1;
00200         cur_y++;
00201         if(cur_y > win_y2) {
00202             cur_y = win_y1;
00203         }
00204     }
00205 }
00206 void LCD::window_pushpixel(unsigned short color, unsigned int count) {
00207     while(count)
00208     {
00209         pixel(cur_x, cur_y, color);
00210         cur_x++;
00211         if(cur_x > win_x2)
00212         {
00213             cur_x = win_x1;
00214             cur_y++;
00215             if(cur_y > win_y2)
00216             {
00217                 cur_y = win_y1;
00218             }
00219         }
00220         count--;
00221     }
00222 }
00223 void LCD::window_pushpixelbuf(unsigned short* color, unsigned int lenght) {
00224     while(lenght)
00225     {
00226         pixel(cur_x, cur_y, *color++);
00227         cur_x++;
00228         if(cur_x > win_x2)
00229         {
00230             cur_x = win_x1;
00231             cur_y++;
00232             if(cur_y > win_y2)
00233             {
00234                 cur_y = win_y1;
00235             }
00236         }
00237         lenght--;
00238     }
00239 }
00240 void LCD::pixel(int x, int y, unsigned short color)
00241 {
00242     if(!(orientation&1)) SWAP(x,y);
00243     // first check parameter
00244     if((x >= screensize_X) || (y >= screensize_Y)) return;
00245 
00246 //    if(draw_mode == NORMAL)
00247 //    {
00248         if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7));  // erase pixel
00249         else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7));   //Black=0000, set pixel
00250 //    }
00251 //    else
00252 //    { // XOR mode
00253 //        if(color == 1) buffer[x + ((y>>3) * screensize_X)] ^= (1 << (y&7));   // xor pixel
00254 //    }
00255 }
00256 void LCD::copy_to_lcd(void)
00257 {
00258     unsigned short i=0;
00259     unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
00260     for(int page=0; page<_LCDPAGES; page++)
00261     {
00262       //  wr_cmd8(col_offset&0xF);              // set column low nibble
00263       //  wr_cmd8(0x10|(col_offset>>4));      // set column hi  nibble
00264         wr_cmd16(setcolcmd);
00265         wr_cmd8(0xB0|(page+page_offset));      // set page
00266         wr_grambuf(buffer16+i, screensize_X>>1);   // send whole page pixels
00267         i+=screensize_X>>1;
00268     }
00269 }
00270 void LCD::cls(void)
00271 {
00272     unsigned short tmp = _background^0xFFFF;
00273     memset(buffer,tmp,screensize_X*_LCDPAGES);  // clear display buffer
00274     unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
00275     for(int page=0; page<_LCDPAGES; page++)
00276     {
00277      //   wr_cmd8((unsigned char)col_offset&0xF);              // set column low nibble
00278      //   wr_cmd8(0x10|(col_offset>>4));      // set column hi  nibble
00279         wr_cmd16(setcolcmd);
00280         wr_cmd8(0xB0|(page+page_offset));      // set page
00281         wr_gram(tmp, screensize_X>>1);   // send whole page pixels = background
00282     }
00283 }
00284 int LCD::sizeX()
00285 {
00286     return screensize_X;
00287 }
00288 int LCD::sizeY()
00289 {
00290     return screensize_Y;
00291 }