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 GraphicsDisplay.cpp Source File

GraphicsDisplay.cpp

00001 /* mbed UniGraphic library - Graphics 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 GraphicsDisplay Display Library Base Class
00008  * Copyright (c) 2007-2009 sford
00009  * Released under the MIT License: http://mbed.org/license/mit
00010  *
00011  * mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00012  * Copyright (c) 2013 Peter Drescher - DC2PD
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022  
00023 
00024  
00025 #include "GraphicsDisplay.h"
00026 #define SWAP(a, b)  { a ^= b; b ^= a; a ^= b; }
00027 GraphicsDisplay::GraphicsDisplay(const char *name):TextDisplay(name) {
00028     set_font((unsigned char*)Terminal6x8,32,127,true);
00029  //   foreground(0xFFFF);
00030  //   background(0x0000);
00031     char_x = 0;
00032     char_y = 0;
00033     oriented_width=0;
00034     oriented_height=0;
00035     fontzoomver=1;
00036     fontzoomhor=1;
00037     auto_up = true;
00038 }
00039     
00040 void GraphicsDisplay::WindowMax (void)
00041 {
00042     window (0, 0, oriented_width,  oriented_height);
00043 }
00044 void GraphicsDisplay::set_width(int width)
00045 {
00046     oriented_width = width;
00047 }
00048 void GraphicsDisplay::set_height(int height)
00049 {
00050     oriented_height = height;
00051 }
00052 int GraphicsDisplay::width()
00053 {
00054     return oriented_width;
00055 }
00056 int GraphicsDisplay::height()
00057 {
00058     return oriented_height;
00059 }
00060 void GraphicsDisplay::circle(int x0, int y0, int r, unsigned short color)
00061 {
00062     int x = -r, y = 0, err = 2-2*r, e2;
00063     do {
00064         pixel(x0-x, y0+y,color);
00065         pixel(x0+x, y0+y,color);
00066         pixel(x0+x, y0-y,color);
00067         pixel(x0-x, y0-y,color);
00068         e2 = err;
00069         if (e2 <= y) {
00070             err += ++y*2+1;
00071             if (-x == y && e2 <= x) e2 = 0;
00072         }
00073         if (e2 > x) err += ++x*2+1;
00074     } while (x <= 0);
00075     if(auto_up) copy_to_lcd();
00076 }
00077 void GraphicsDisplay::fillcircle(int x0, int y0, int r, unsigned short color)
00078 {
00079     bool old_auto_up=auto_up;
00080     if(auto_up) auto_up=false;
00081     int x = -r, y = 0, err = 2-2*r, e2;
00082     do {
00083         vline(x0-x, y0-y, y0+y, color);
00084         vline(x0+x, y0-y, y0+y, color);
00085         e2 = err;
00086         if (e2 <= y) {
00087             err += ++y*2+1;
00088             if (-x == y && e2 <= x) e2 = 0;
00089         }
00090         if (e2 > x) err += ++x*2+1;
00091     } while (x <= 0);
00092     if(old_auto_up)
00093     {
00094         auto_up=true;
00095         copy_to_lcd();
00096     }
00097 }
00098 void GraphicsDisplay::hline(int x0, int x1, int y, unsigned short color)
00099 {
00100     int len = x1 - x0 + 1;
00101     window(x0,y,len,1);
00102  //   for (int j=0; j<len; j++) window_pushpixel(color);
00103     window_pushpixel(color, len);
00104     if(auto_up) copy_to_lcd();
00105     return;
00106 }
00107 void GraphicsDisplay::vline(int x, int y0, int y1, unsigned short color)
00108 {
00109     int len = y1 - y0 + 1;
00110     window(x,y0,1,len);
00111   //  for (int y=0; y<len; y++) window_pushpixel(color);
00112     window_pushpixel(color, len);
00113     if(auto_up) copy_to_lcd();
00114     return;
00115 }
00116 void GraphicsDisplay::line(int x0, int y0, int x1, int y1, unsigned short color)
00117 {
00118     //WindowMax();
00119     int   dx = 0, dy = 0;
00120     int   dx_sym = 0, dy_sym = 0;
00121     int   dx_x2 = 0, dy_x2 = 0;
00122     int   di = 0;
00123 
00124     dx = x1-x0;
00125     dy = y1-y0;
00126 
00127     if (dx == 0) {        /* vertical line */
00128         if (y1 < y0) SWAP(y0,y1);
00129         vline(x0,y0,y1,color);
00130         return;
00131     }
00132 
00133     if (dx > 0) {
00134         dx_sym = 1;
00135     } else {
00136         dx_sym = -1;
00137     }
00138     if (dy == 0) {        /* horizontal line */
00139         if (x1 < x0) SWAP(x1,x0);
00140         hline(x0,x1,y0,color);
00141         return;
00142     }
00143 
00144     if (dy > 0) {
00145         dy_sym = 1;
00146     } else {
00147         dy_sym = -1;
00148     }
00149 
00150     dx = dx_sym*dx;
00151     dy = dy_sym*dy;
00152 
00153     dx_x2 = dx*2;
00154     dy_x2 = dy*2;
00155 
00156     if (dx >= dy) {
00157         di = dy_x2 - dx;
00158         while (x0 != x1) {
00159 
00160             pixel(x0, y0, color);
00161             x0 += dx_sym;
00162             if (di<0) {
00163                 di += dy_x2;
00164             } else {
00165                 di += dy_x2 - dx_x2;
00166                 y0 += dy_sym;
00167             }
00168         }
00169         pixel(x0, y0, color);
00170     } else {
00171         di = dx_x2 - dy;
00172         while (y0 != y1) {
00173             pixel(x0, y0, color);
00174             y0 += dy_sym;
00175             if (di < 0) {
00176                 di += dx_x2;
00177             } else {
00178                 di += dx_x2 - dy_x2;
00179                 x0 += dx_sym;
00180             }
00181         }
00182         pixel(x0, y0, color);
00183     }
00184     if(auto_up) copy_to_lcd();
00185     return;
00186 }
00187 void GraphicsDisplay::rect(int x0, int y0, int x1, int y1, unsigned short color)
00188 {
00189     bool old_auto_up=auto_up;
00190     if(auto_up) auto_up=0;
00191     if (x1 > x0) hline(x0,x1,y0,color);
00192     else  hline(x1,x0,y0,color);
00193 
00194     if (y1 > y0) vline(x0,y0,y1,color);
00195     else vline(x0,y1,y0,color);
00196 
00197     if (x1 > x0) hline(x0,x1,y1,color);
00198     else  hline(x1,x0,y1,color);
00199 
00200     if (y1 > y0) vline(x1,y0,y1,color);
00201     else vline(x1,y1,y0,color);
00202     if(old_auto_up)
00203     {
00204         auto_up=true;
00205         copy_to_lcd();
00206     }
00207     return;
00208 }
00209 void GraphicsDisplay::fillrect(int x0, int y0, int x1, int y1, unsigned short color)
00210 {
00211     if(x0 > x1) SWAP(x0,x1);
00212     if(y0 > y1) SWAP(y0,y1);
00213      
00214     int h = y1 - y0 + 1;
00215     int w = x1 - x0 + 1;
00216     unsigned int pixels = h * w;
00217     window(x0,y0,w,h);
00218  //   for (unsigned int p=0; p<pixels; p++) window_pushpixel(color);
00219     window_pushpixel(color, pixels);
00220     if(auto_up) copy_to_lcd();
00221     return;
00222 }
00223 void GraphicsDisplay::locate(int x, int y)
00224 {
00225     char_x = x;
00226     char_y = y;
00227 }
00228 int GraphicsDisplay::columns()
00229 {
00230     return oriented_width / fonthor;
00231 }
00232 int GraphicsDisplay::rows()
00233 {
00234     return oriented_height / fontvert;
00235 }
00236 void GraphicsDisplay::set_font(unsigned char* f, unsigned char firstascii, unsigned char lastascii, bool proportional)
00237 {
00238     font = f;
00239     // read font parameter from start of array
00240     //fontoffset = font[0];                    // bytes / char
00241     fonthor = font[1];                       // get hor size of font
00242     fontvert = font[2];                      // get vert size of font
00243     //fontbpl = font[3];                       // bytes per line
00244     fontbpl = (fontvert+7)>>3; //bytes per line, rounded up to multiple of 8
00245     fontoffset = (fonthor*fontbpl)+1;
00246     firstch = firstascii;   // first ascii code present in font array (usually 32)
00247     lastch = lastascii;     // last ascii code present in font array (usually 127)
00248     fontprop=proportional;
00249     set_font_zoom(1,1);
00250 }
00251 void GraphicsDisplay::set_font_zoom(unsigned char x_mul, unsigned char y_mul)
00252 {
00253     fontzoomhor=((x_mul==0) ? 1:x_mul);
00254     fontzoomver=((y_mul==0) ? 1:y_mul);
00255 }
00256 int GraphicsDisplay::_putc(int value)
00257 {
00258     if (value == '\n') {    // new line
00259         char_x = 0;
00260         char_y = char_y + fontvert*fontzoomver;
00261         if (char_y >= oriented_height - fontvert*fontzoomver) {
00262             char_y = 0;
00263         }
00264     } else {
00265         character(char_x, char_y, value);
00266         if(auto_up) copy_to_lcd();
00267     }
00268     return value;
00269 }
00270 void GraphicsDisplay::character(int x, int y, int c)
00271 {
00272     char_x=x;
00273     char_y=y;
00274     int j,i,b;
00275     unsigned char* zeichen;
00276     unsigned char z,w,v;
00277 
00278  /*   // read font parameter from start of array
00279     offset = font[0];                    // bytes / char
00280     hor = font[1];                       // get hor size of font
00281     vert = font[2];                      // get vert size of font
00282     bpl = font[3];                       // bytes per line
00283 */
00284     if (char_x + fonthor*fontzoomhor > oriented_width) {
00285         char_x = 0;
00286         char_y = char_y + fontvert*fontzoomver;
00287         if (char_y > oriented_height - fontvert*fontzoomver) {
00288             char_y = 0;
00289         }
00290     }
00291     window(char_x, char_y,fonthor*fontzoomhor,fontvert*fontzoomver); // char box
00292     if ((c < firstch) || (c > lastch)) {   // test char range - if not exist fill with blank
00293          for (i = 0; i < fonthor*fontvert*fontzoomver;i++){
00294           window_pushpixel(_background, fontzoomhor); //(color, howmany) 
00295           }
00296     }
00297     else{
00298         zeichen = &font[((c-firstch) * fontoffset) + 4]; // start of char bitmap
00299         w = zeichen[0];                          // width of actual char
00300         // construct the char into the buffer
00301         for (j=0; j<fontvert; j++) {  //  vert line
00302             for (v=0; v<fontzoomver; v++) { // repeat horiz line for vertical zooming
00303               for (i=0; i<fonthor; i++) {   //  horz line
00304                 z =  zeichen[(fontbpl * i) + ((j & 0xF8) >> 3)+1];
00305                 b = 1 << (j & 0x07);
00306                 if (( z & b ) == 0x00) {
00307                 //   pixel(char_x+i,char_y+j,0);
00308                     window_pushpixel(_background, fontzoomhor); //(color, howmany)
00309                 } else {
00310                 //    pixel(char_x+i,char_y+j,1);
00311                     window_pushpixel(_foreground, fontzoomhor);
00312                 }
00313               }
00314             } //for each zoomed vert
00315          }
00316     }
00317     if(fontprop)
00318     {
00319         if((w+1)<fonthor) char_x += (w*fontzoomhor)+1; // put at least 1 blank after variable-width characters, except characters that occupy whole fonthor space like "_"
00320         else char_x += fonthor*fontzoomhor;
00321     }
00322     else char_x += fonthor*fontzoomhor; // fixed width
00323 }
00324 void GraphicsDisplay::Bitmap_BW(Bitmap_s bm, int x, int y)
00325 {
00326     int h,v,b;
00327  //   int cropX;
00328     char d;
00329     if(x<0) x=0;
00330     if(y<0) y=0;
00331     int cropX = (x+bm.xSize)-oriented_width;
00332     if(cropX<0) cropX=0; 
00333     window(x, y, bm.xSize-cropX, bm.ySize);
00334     for(v=0; v < bm.ySize; v++) {   // lines
00335         if((v + y) >= oriented_height) break; // no need to crop Y
00336         for(h=0; h < bm.xSize; h++) { // pixel
00337             if((h + x) >= oriented_width) break;
00338             d = bm.data[bm.Byte_in_Line * v + ((h & 0xF8) >> 3)];
00339             b = 0x80 >> (h & 0x07);
00340             if((d & b) == 0) {
00341                 window_pushpixel(_background);
00342             } else {
00343                 window_pushpixel(_foreground);
00344             }
00345         }
00346     }
00347     if(auto_up) copy_to_lcd();
00348 }
00349 void GraphicsDisplay::Bitmap(int x, int y, int w, int h,unsigned char *bitmap)
00350 {
00351     int  j;
00352     unsigned char  padd;
00353     unsigned short *bitmap_ptr = (unsigned short *)bitmap;    
00354 
00355     padd = w%2; // the lines are padded to multiple of 4 bytes in a bitmap
00356     if(x<0) x=0;
00357     else if(x>=oriented_width) return;
00358     if(y<0) y=0;
00359     else if(y>=oriented_height) return;
00360     int cropX = (x+w)-oriented_width;
00361     if(cropX<0) cropX=0;
00362     int cropY = (y+h)-oriented_height;
00363     if(cropY<0) cropY=0;
00364     window(x, y, w-cropX, h-cropY);
00365     bitmap_ptr += ((h - 1)* (w + padd)); // begin of last line in array (first line of image)(standard bmp scan direction is left->right bottom->top)
00366     for (j = 0; j < h-cropY; j++) {         //Lines
00367         window_pushpixelbuf(bitmap_ptr, w-cropX);
00368         bitmap_ptr -= w+padd;
00369     }
00370     if(auto_up) copy_to_lcd();
00371 }
00372 
00373 // local filesystem is not implemented in kinetis board , but you can add a SD card
00374 // fixme this whole functions needs testing and speedup
00375 int GraphicsDisplay::BMP_16(int x, int y, const char *Name_BMP)
00376 {
00377 
00378 #define OffsetPixelWidth    18
00379 #define OffsetPixelHeigh    22
00380 #define OffsetFileSize      34
00381 #define OffsetPixData       10
00382 #define OffsetBPP           28
00383 
00384     char filename[50];
00385     unsigned char BMP_Header[54];
00386     unsigned short BPP_t;
00387     unsigned int PixelWidth,PixelHeigh,start_data;
00388     unsigned int    i,off;
00389     int padd,j;
00390     unsigned short *line;
00391 
00392     // get the filename
00393     i=0;
00394     while (*Name_BMP!='\0') {
00395         filename[i++]=*Name_BMP++;
00396     }
00397     filename[i] = 0;  
00398     
00399     FILE *Image = fopen((const char *)&filename[0], "rb");  // open the bmp file
00400     if (!Image) {
00401         return(0);      // error file not found !
00402     }
00403 
00404     fread(&BMP_Header[0],1,54,Image);      // get the BMP Header
00405 
00406     if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) {  // check magic byte
00407         fclose(Image);
00408         return(-1);     // error no BMP file
00409     }
00410 
00411     BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
00412     if (BPP_t != 0x0010) {
00413         fclose(Image);
00414         return(-2);     // error no 16 bit BMP
00415     }
00416 
00417     PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
00418     PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
00419     if (PixelHeigh > oriented_height + y || PixelWidth > oriented_width + x) {
00420         fclose(Image);
00421         return(-3);      // to big
00422     }
00423 
00424     start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
00425 
00426     line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
00427     if (line == NULL) {
00428         return(-4);         // error no memory
00429     }
00430 
00431     // the bmp lines are padded to multiple of 4 bytes
00432     padd = -1;
00433     do {
00434         padd ++;
00435     } while ((PixelWidth * 2 + padd)%4 != 0);
00436 
00437     window(x, y,PixelWidth ,PixelHeigh);
00438 //    wr_cmd(0x2C);  // send pixel
00439     for (j = PixelHeigh - 1; j >= 0; j--) {               //Lines bottom up
00440         off = j * (PixelWidth  * 2 + padd) + start_data;   // start of line
00441         fseek(Image, off ,SEEK_SET);
00442         fread(line,1,PixelWidth * 2,Image);       // read a line - slow 
00443   /*      for (i = 0; i < PixelWidth; i++)
00444         {        // copy pixel data to TFT
00445      //       wr_16(line[i]);                  // one 16 bit pixel   
00446             window_pushpixel(line[i]);
00447             
00448         } */
00449         window_pushpixelbuf(line, PixelWidth);
00450      }
00451     free (line);
00452     fclose(Image);
00453     if(auto_up) copy_to_lcd();
00454     return(1);
00455 }
00456 
00457 void GraphicsDisplay::cls (void)
00458 {
00459     unsigned int pixels = ( oriented_width * oriented_height);
00460     WindowMax();
00461     for (unsigned int i = 0; i < pixels; i++)
00462     {
00463         window_pushpixel(_background);
00464     }
00465 }
00466 void GraphicsDisplay::set_auto_up(bool up)
00467 {
00468     if(up) {
00469         auto_up = true;
00470         copy_to_lcd();
00471         }
00472     else auto_up = false;
00473 }
00474 bool GraphicsDisplay::get_auto_up(void)
00475 {
00476     return (auto_up);
00477 }
00478 
00479