Basically i glued Peter Drescher and Simon Ford libs in a GraphicsDisplay class, then derived TFT or LCD class (which inherits Protocols class), then the most derived ones (Inits), which are per-display and are the only part needed to be adapted to diff hw.

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, PinName* buspins, 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)
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==BUS_8)
00048     {
00049         PinName pins[16];
00050         for(int i=0; i<16; i++) pins[i]=NC;
00051         for(int i=0; i<8; i++) pins[i]=buspins[i];
00052         proto = new BUS8(pins, CS, reset, DC, WR, RD);
00053     }
00054     useNOP=false;
00055     buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
00056     buffer16 = (unsigned short*)buffer;
00057     draw_mode = NORMAL;
00058     set_orientation(1);
00059     foreground(White);
00060     background(Black);
00061     set_auto_up(true);
00062     tftID=0;
00063   //  cls();
00064   //  locate(0,0);
00065 }
00066 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)
00067     : 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)
00068 {
00069     if(displayproto==SPI_8)
00070     {
00071         proto = new SPI8(Hz, mosi, miso, sclk, CS, reset, DC);
00072         useNOP=false;
00073     }
00074     else if(displayproto==SPI_16)
00075     {
00076         proto = new SPI16(Hz, mosi, miso, sclk, CS, reset, DC);
00077         useNOP=true;
00078     }
00079     buffer = (unsigned char*) malloc (screensize_X*_LCDPAGES);
00080     buffer16 = (unsigned short*)buffer;
00081     draw_mode = NORMAL;
00082   //  cls();
00083     set_orientation(1);
00084     foreground(White);
00085     background(Black);
00086     set_auto_up(true);
00087     tftID=0;
00088   //  locate(0,0);
00089 
00090 }
00091 LCD::~LCD()
00092 {
00093     free(buffer);
00094 }
00095 
00096 void LCD::wr_cmd8(unsigned char cmd)
00097     {
00098         if(useNOP) proto->wr_cmd16(0xE300|cmd); // E3 is NOP cmd for LCD
00099         else proto->wr_cmd8(cmd);
00100     }
00101 void LCD::wr_data8(unsigned char data)
00102     {
00103         proto->wr_data8(data);
00104     }
00105 void LCD::wr_cmd16(unsigned short cmd)
00106     {
00107         proto->wr_cmd16(cmd);
00108     }
00109 void LCD::wr_gram(unsigned short data, unsigned int count)
00110     {
00111         proto->wr_gram(data, count);
00112     }
00113 void LCD::wr_grambuf(unsigned short* data, unsigned int lenght)
00114     {
00115         proto->wr_grambuf(data, lenght);
00116     }
00117 void LCD::hw_reset()
00118     {
00119         proto->hw_reset();
00120     }
00121 void LCD::BusEnable(bool enable)
00122     {
00123         proto->BusEnable(enable);
00124     }
00125 
00126 
00127 
00128 // monochrome LCD driver ICs does not have ram rotate in hw (swap raw<->columns) like TFT displays
00129 // for portrait views, XY swap will be done in sw in pixel() function
00130 void LCD::set_orientation(int o)
00131 {
00132     orientation = o;
00133     switch (o) {
00134         case (0):// portrait view -90°
00135             mirrorXY(Y);
00136             col_offset = 0;
00137             page_offset = _IC_PAGES-_LCDPAGES;
00138             set_width(screensize_Y);
00139             set_height(screensize_X);
00140         //    portrait = true;
00141             break;
00142         case (1): // default, landscape view 0°
00143             mirrorXY(NONE);
00144             col_offset = 0;
00145             page_offset = 0;
00146             set_width(screensize_X);
00147             set_height(screensize_Y);
00148        //     portrait = false;
00149             break;
00150         case (2):// portrait view +90°
00151             mirrorXY(X);
00152             col_offset = _IC_X_SEGS-screensize_X; // some displays have less pixels than IC ram
00153             page_offset = 0;
00154             set_width(screensize_Y);
00155             set_height(screensize_X);
00156        //     portrait = true;
00157             break;
00158         case (3):// landscape view +180°
00159             mirrorXY(XY);
00160             col_offset = _IC_X_SEGS-screensize_X;
00161             page_offset = _IC_PAGES-_LCDPAGES;
00162             set_width(screensize_X);
00163             set_height(screensize_Y);
00164        //     portrait = false;
00165             break;
00166     }
00167 }
00168 void LCD::mirrorXY(mirror_t mode)
00169 {
00170     switch (mode)
00171     {
00172         case(NONE):
00173          //   wr_cmd8(0xA0);
00174             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
00175             break;
00176         case(X):
00177         //    wr_cmd8(0xA1);
00178             wr_cmd16(0xA1C8);
00179             break;
00180         case(Y):
00181         //    wr_cmd8(0xA0);
00182             wr_cmd16(0xA0C0);
00183             break;
00184         case(XY):
00185         //    wr_cmd8(0xA1);
00186             wr_cmd16(0xA1C0);
00187             break;
00188     }
00189 }
00190 void LCD::invert(unsigned char o)
00191 {
00192     if(o == 0) wr_cmd8(0xA6);
00193     else wr_cmd8(0xA7);
00194 }
00195 
00196 void LCD::set_contrast(int o)
00197 {
00198     contrast = o;
00199  //   wr_cmd8(0x81);      //  set volume
00200     wr_cmd16(0x8100|(o&0x3F));
00201 }
00202 
00203 int LCD::get_contrast(void)
00204 {
00205     return(contrast);
00206 }
00207 void LCD::window(int x, int y, int w, int h) {
00208     // current pixel location
00209     cur_x = x;
00210     cur_y = y;
00211     // window settings
00212     win_x1 = x;
00213     win_x2 = x + w - 1;
00214     win_y1 = y;
00215     win_y2 = y + h - 1;
00216 }
00217 void LCD::window_pushpixel(unsigned short color) {
00218     pixel(cur_x, cur_y, color);
00219     cur_x++;
00220     if(cur_x > win_x2) {
00221         cur_x = win_x1;
00222         cur_y++;
00223         if(cur_y > win_y2) {
00224             cur_y = win_y1;
00225         }
00226     }
00227 }
00228 void LCD::window_pushpixel(unsigned short color, unsigned int count) {
00229     while(count)
00230     {
00231         pixel(cur_x, cur_y, color);
00232         cur_x++;
00233         if(cur_x > win_x2)
00234         {
00235             cur_x = win_x1;
00236             cur_y++;
00237             if(cur_y > win_y2)
00238             {
00239                 cur_y = win_y1;
00240             }
00241         }
00242         count--;
00243     }
00244 }
00245 void LCD::window_pushpixelbuf(unsigned short* color, unsigned int lenght) {
00246     while(lenght)
00247     {
00248         pixel(cur_x, cur_y, *color++);
00249         cur_x++;
00250         if(cur_x > win_x2)
00251         {
00252             cur_x = win_x1;
00253             cur_y++;
00254             if(cur_y > win_y2)
00255             {
00256                 cur_y = win_y1;
00257             }
00258         }
00259         lenght--;
00260     }
00261 }
00262 void LCD::pixel(int x, int y, unsigned short color)
00263 {
00264     if(!(orientation&1)) SWAP(x,y);
00265     // first check parameter
00266     if((x >= screensize_X) || (y >= screensize_Y)) return;
00267 
00268     if(color) buffer[(x + ((y>>3)*screensize_X))^1] &= ~(1 << (y&7));  // erase pixel
00269     else buffer[(x + ((y>>3)*screensize_X))^1] |= (1 << (y&7));   //Black=0000, set pixel
00270 }
00271 unsigned short LCD::pixelread(int x, int y)
00272 {
00273     if(!(orientation&1)) SWAP(x,y);
00274     // first check parameter
00275     if((x >= screensize_X) || (y >= screensize_Y)) return 0;
00276     
00277     if((buffer[(x + ((y>>3)*screensize_X))^1] & (1 << (y&7)))==0) return 0xFFFF ;  // pixel not set, White
00278     else return 0; // pixel set, Black
00279 }
00280 void LCD::copy_to_lcd(void)
00281 {
00282     unsigned short i=0;
00283     unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
00284     for(int page=0; page<_LCDPAGES; page++)
00285     {
00286       //  wr_cmd8(col_offset&0xF);              // set column low nibble
00287       //  wr_cmd8(0x10|(col_offset>>4));      // set column hi  nibble
00288         wr_cmd16(setcolcmd);
00289         wr_cmd8(0xB0|(page+page_offset));      // set page
00290         wr_grambuf(buffer16+i, screensize_X>>1);   // send whole page pixels
00291         i+=screensize_X>>1;
00292     }
00293 }
00294 void LCD::cls(void)
00295 {
00296     unsigned short tmp = _background^0xFFFF;
00297     memset(buffer,tmp,screensize_X*_LCDPAGES);  // clear display buffer
00298     unsigned short setcolcmd = 0x0010 | ((col_offset&0xF)<<8) | (col_offset>>4);
00299     for(int page=0; page<_LCDPAGES; page++)
00300     {
00301      //   wr_cmd8((unsigned char)col_offset&0xF);              // set column low nibble
00302      //   wr_cmd8(0x10|(col_offset>>4));      // set column hi  nibble
00303         wr_cmd16(setcolcmd);
00304         wr_cmd8(0xB0|(page+page_offset));      // set page
00305         wr_gram(tmp, screensize_X>>1);   // send whole page pixels = background
00306     }
00307 }
00308 int LCD::sizeX()
00309 {
00310     return screensize_X;
00311 }
00312 int LCD::sizeY()
00313 {
00314     return screensize_Y;
00315 }