UniGraphic-Fork for ST7920-LCD-controller and SH1106. Tested with 128x64 LCD with SPI and 128x64-OLED with IIC

Dependents:   UniGraphic-St7920-Test AfficheurUTILECO

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