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.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
Generated on Tue Jul 12 2022 18:00:34 by 1.7.2