SPI Library for 240x320 TFT LCD with ILI9320, ILI9325 and ILI9328 chip
Dependents: KL25Z_ILI9320_Demo Mini-DK
SPI_TFT_ILI9320.cpp
00001 /************************************************************************************************** 00002 ***** ***** 00003 ***** Name: SPI_TFT.cpp ***** 00004 ***** Ver.: 1.0 ***** 00005 ***** Date: 04/01/2013 ***** 00006 ***** Auth: Frank Vannieuwkerke ***** 00007 ***** Erik Olieman ***** 00008 ***** Func: library for 240*320 pixel TFT with ILI9320 LCD Controller ***** 00009 ***** ***** 00010 ***** Rewrite from Peter Drescher code - http://mbed.org/cookbook/SPI-driven-QVGA-TFT ***** 00011 ***** ***** 00012 **************************************************************************************************/ 00013 00014 #include "SPI_TFT_ILI9320.h" 00015 #include "mbed.h" 00016 00017 00018 #define BPP 16 // Bits per pixel 00019 00020 00021 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, const char *name) 00022 : GraphicsDisplay(name), _spi(mosi, miso, sclk), _cs(cs) 00023 { 00024 char_x = 0; 00025 tft_reset(); 00026 set_orientation(0); 00027 backgroundimage = false; 00028 #ifndef NO_FLASH_BUFFER 00029 backgroundOrientation = 0; 00030 #endif 00031 } 00032 00033 int SPI_TFT::width() 00034 { 00035 if (orientation == 0 || orientation == 2) return 240; 00036 else return 320; 00037 } 00038 00039 int SPI_TFT::height() 00040 { 00041 if (orientation == 0 || orientation == 2) return 320; 00042 else return 240; 00043 } 00044 00045 void SPI_TFT::set_orientation(unsigned int o) 00046 { 00047 orientation = o; 00048 WindowMax(); 00049 } 00050 00051 void SPI_TFT::mod_orientation(void) 00052 { 00053 switch (orientation) { 00054 case 0: 00055 wr_reg(0x03, 0x10b0); // ID1 = 1, ID0 = 1, AM = 0 - Portrait 00056 break; 00057 case 1: 00058 wr_reg(0x03, 0x10a8); // ID1 = 1, ID0 = 0, AM = 0 - Landscape 00059 break; 00060 case 2: 00061 wr_reg(0x03, 0x1080); // ID1 = 0, ID0 = 0, AM = 1 - Portrait upside down 00062 break; 00063 case 3: 00064 wr_reg(0x03, 0x1098); // ID1 = 0, ID0 = 1, AM = 1 - Landscape upside down 00065 break; 00066 } 00067 } 00068 00069 void SPI_TFT::wr_cmd(unsigned char cmd) 00070 { 00071 _cs = 0; 00072 _spi.write(0x70); 00073 _spi.write(0x00); 00074 _spi.write(cmd); 00075 _cs = 1; 00076 } 00077 00078 void SPI_TFT::wr_dat(unsigned short dat) 00079 { 00080 unsigned char u,l; 00081 u = (dat >> 0x08); 00082 l = (dat & 0xff); 00083 _cs = 0; 00084 _spi.write(0x72); 00085 _spi.write(u); 00086 _spi.write(l); 00087 _cs = 1; 00088 } 00089 00090 void SPI_TFT::wr_dat_start(void) 00091 { 00092 _spi.write(0x72); 00093 } 00094 00095 unsigned short SPI_TFT::rd_dat(void) // IMPORTANT : SPI frequency needs to be lowered when reading 00096 { 00097 unsigned short val = 0; 00098 _cs = 0; 00099 _spi.frequency(SPI_F_LO); 00100 _spi.write(0x73); 00101 _spi.write(0x00); 00102 val = _spi.write(0x00); // Dummy read 00103 val = _spi.write(0x00); // Read D8..D15 00104 val <<= 8; 00105 val |= _spi.write(0x00); // Read D0..D7 00106 _cs = 1; 00107 _spi.frequency(SPI_F_HI); 00108 return (val); 00109 } 00110 00111 void SPI_TFT::wr_reg(unsigned char reg, unsigned short val) 00112 { 00113 wr_cmd(reg); 00114 wr_dat(val); 00115 } 00116 00117 unsigned short SPI_TFT::rd_reg(unsigned char reg) 00118 { 00119 wr_cmd(reg); 00120 return(rd_dat()); 00121 } 00122 00123 unsigned short SPI_TFT::Read_ID(void) // IMPORTANT : SPI frequency needs to be lowered when reading 00124 { 00125 unsigned short val = 0; 00126 _cs = 0; 00127 _spi.write(0x70); 00128 _spi.write(0x00); 00129 _spi.write(0x00); 00130 _cs = 1; 00131 _spi.frequency(SPI_F_LO); 00132 _cs = 0; 00133 _spi.write(0x73); 00134 val = _spi.write(0x00); // Dummy read 00135 val = _spi.write(0x00); // Read D8..D15 00136 val <<= 8; 00137 val |= _spi.write(0x00); // Read D0..D7 00138 _cs = 1; 00139 _spi.frequency(SPI_F_HI); 00140 return (val); 00141 } 00142 00143 void SPI_TFT::SetCursor( unsigned short Xpos, unsigned short Ypos ) 00144 { 00145 wr_reg(0x20, Xpos ); 00146 wr_reg(0x21, Ypos ); 00147 } 00148 00149 void SPI_TFT::tft_reset() 00150 { 00151 uint16_t DeviceID; 00152 _spi.format(8,3); // 8 bit spi mode 3 00153 DeviceID = Read_ID(); 00154 _spi.frequency(SPI_F_HI); // 48 Mhz SPI clock 00155 if(DeviceID == 0x9320 || DeviceID == 0x9300) 00156 { 00157 wr_reg(0x00,0x0000); 00158 wr_reg(0x01,0x0100); // Driver Output Control 00159 wr_reg(0x02,0x0700); // LCD Driver Waveform Control 00160 wr_reg(0x03,0x1030); // Set the scan mode 00161 wr_reg(0x04,0x0000); // Scaling Control 00162 wr_reg(0x08,0x0202); // Display Control 2 00163 wr_reg(0x09,0x0000); // Display Control 3 00164 wr_reg(0x0a,0x0000); // Frame Cycle Contal 00165 wr_reg(0x0c,(1<<0)); // Extern Display Interface Control 1 00166 wr_reg(0x0d,0x0000); // Frame Maker Position 00167 wr_reg(0x0f,0x0000); // Extern Display Interface Control 2 00168 00169 wait_ms(50); 00170 00171 wr_reg(0x07,0x0101); // Display Control 00172 00173 wait_ms(50); 00174 00175 wr_reg(0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4)); // Power Control 1 00176 wr_reg(0x11,0x0007); // Power Control 2 00177 wr_reg(0x12,(1<<8)|(1<<4)|(0<<0)); // Power Control 3 00178 wr_reg(0x13,0x0b00); // Power Control 4 00179 wr_reg(0x29,0x0000); // Power Control 7 00180 wr_reg(0x2b,(1<<14)|(1<<4)); 00181 00182 wr_reg(0x50,0); // Set X Start 00183 wr_reg(0x51,239); // Set X End 00184 wr_reg(0x52,0); // Set Y Start 00185 wr_reg(0x53,319); // Set Y End 00186 00187 wait_ms(50); 00188 00189 wr_reg(0x60,0x2700); // Driver Output Control 00190 wr_reg(0x61,0x0001); // Driver Output Control 00191 wr_reg(0x6a,0x0000); // Vertical Srcoll Control 00192 00193 wr_reg(0x80,0x0000); // Display Position Partial Display 1 00194 wr_reg(0x81,0x0000); // RAM Address Start Partial Display 1 00195 wr_reg(0x82,0x0000); // RAM Address End-Partial Display 1 00196 wr_reg(0x83,0x0000); // Displsy Position Partial Display 2 00197 wr_reg(0x84,0x0000); // RAM Address Start Partial Display 2 00198 wr_reg(0x85,0x0000); // RAM Address End Partial Display 2 00199 00200 wr_reg(0x90,(0<<7)|(16<<0)); // Frame Cycle Control 00201 wr_reg(0x92,0x0000); // Panel Interface Control 2 00202 wr_reg(0x93,0x0001); // Panel Interface Control 3 00203 wr_reg(0x95,0x0110); // Frame Cycle Control 00204 wr_reg(0x97,(0<<8)); 00205 wr_reg(0x98,0x0000); // Frame Cycle Control 00206 wr_reg(0x07,0x0133); 00207 } 00208 if(DeviceID == 0x9325 || DeviceID == 0x9328) 00209 { 00210 wr_reg(0xe7,0x0010); 00211 wr_reg(0x00,0x0001); // start internal osc 00212 wr_reg(0x01,0x0100); 00213 wr_reg(0x02,0x0700); // power on sequence 00214 wr_reg(0x03,(1<<12)|(1<<5)|(1<<4)|(0<<3) ); // importance 00215 wr_reg(0x04,0x0000); 00216 wr_reg(0x08,0x0207); 00217 wr_reg(0x09,0x0000); 00218 wr_reg(0x0a,0x0000); // display setting 00219 wr_reg(0x0c,0x0001); // display setting 00220 wr_reg(0x0d,0x0000); 00221 wr_reg(0x0f,0x0000); 00222 wr_reg(0x10,0x0000); // Power On sequence 00223 wr_reg(0x11,0x0007); 00224 wr_reg(0x12,0x0000); 00225 wr_reg(0x13,0x0000); 00226 00227 wait_ms(50); 00228 00229 wr_reg(0x10,0x1590); 00230 wr_reg(0x11,0x0227); 00231 00232 wait_ms(50); 00233 00234 wr_reg(0x12,0x009c); 00235 00236 wait_ms(50); 00237 00238 wr_reg(0x13,0x1900); 00239 wr_reg(0x29,0x0023); 00240 wr_reg(0x2b,0x000e); 00241 00242 wait_ms(50); 00243 00244 wr_reg(0x20,0x0000); 00245 wr_reg(0x21,0x0000); 00246 00247 wait_ms(50); 00248 00249 wr_reg(0x30,0x0007); 00250 wr_reg(0x31,0x0707); 00251 wr_reg(0x32,0x0006); 00252 wr_reg(0x35,0x0704); 00253 wr_reg(0x36,0x1f04); 00254 wr_reg(0x37,0x0004); 00255 wr_reg(0x38,0x0000); 00256 wr_reg(0x39,0x0706); 00257 wr_reg(0x3c,0x0701); 00258 wr_reg(0x3d,0x000f); 00259 00260 wait_ms(50); 00261 00262 wr_reg(0x50,0x0000); 00263 wr_reg(0x51,0x00ef); 00264 wr_reg(0x52,0x0000); 00265 wr_reg(0x53,0x013f); 00266 wr_reg(0x60,0xa700); 00267 wr_reg(0x61,0x0001); 00268 wr_reg(0x6a,0x0000); 00269 wr_reg(0x80,0x0000); 00270 wr_reg(0x81,0x0000); 00271 wr_reg(0x82,0x0000); 00272 wr_reg(0x83,0x0000); 00273 wr_reg(0x84,0x0000); 00274 wr_reg(0x85,0x0000); 00275 00276 wr_reg(0x90,0x0010); 00277 wr_reg(0x92,0x0000); 00278 wr_reg(0x93,0x0003); 00279 wr_reg(0x95,0x0110); 00280 wr_reg(0x97,0x0000); 00281 wr_reg(0x98,0x0000); 00282 00283 wr_reg(0x07,0x0133); // display on sequence 00284 00285 wr_reg(0x20,0x0000); 00286 wr_reg(0x21,0x0000); 00287 } 00288 wait_ms(100); 00289 WindowMax(); 00290 } 00291 00292 00293 void SPI_TFT::pixel(int x, int y, int color) 00294 { 00295 switch (orientation) { 00296 case 0: 00297 wr_reg(0x20, x); 00298 wr_reg(0x21, y); 00299 break; 00300 case 1: 00301 wr_reg(0x20, 239-y); 00302 wr_reg(0x21, x); 00303 break; 00304 case 2: 00305 wr_reg(0x20, 239-x); 00306 wr_reg(0x21, 319-y); 00307 break; 00308 case 3: 00309 wr_reg(0x20, y); 00310 wr_reg(0x21, 319-x); 00311 break; 00312 } 00313 wr_cmd(0x22); 00314 wr_dat(color); 00315 } 00316 00317 00318 void SPI_TFT::window(int x, int y, int w, int h) 00319 { 00320 unsigned int xw1, yh1; 00321 xw1 = x + w - 1; 00322 yh1 = y + h - 1; 00323 wr_reg(0x20, x); 00324 wr_reg(0x21, y); 00325 switch (orientation) { 00326 case 0: 00327 wr_reg(0x50, x); 00328 wr_reg(0x51, xw1); 00329 wr_reg(0x52, y); 00330 wr_reg(0x53, yh1); 00331 break; 00332 case 1: 00333 wr_reg(0x50, 239 - yh1); 00334 wr_reg(0x51, 239 - y); 00335 wr_reg(0x52, x); 00336 wr_reg(0x53, xw1); 00337 break; 00338 case 2: 00339 wr_reg(0x50, 239 - xw1); 00340 wr_reg(0x51, 239 - x); 00341 wr_reg(0x52, 319 - yh1); 00342 wr_reg(0x53, 319 - y); 00343 break; 00344 case 3: 00345 wr_reg(0x50, y); 00346 wr_reg(0x51, yh1); 00347 wr_reg(0x52, 319 - xw1); 00348 wr_reg(0x53, 319 - x); 00349 break; 00350 } 00351 } 00352 00353 00354 void SPI_TFT::WindowMax(void) 00355 { 00356 window(0, 0, width(), height()); 00357 } 00358 00359 00360 void SPI_TFT::cls (void) 00361 { 00362 if (backgroundimage == false) { 00363 unsigned long int index=0; 00364 wr_reg(0x03, 0x1030); 00365 WindowMax(); 00366 SetCursor(0,0); 00367 wr_cmd(0x22); 00368 _cs = 0; 00369 wr_dat_start(); 00370 #ifndef SPI_8BIT 00371 _spi.format(16,3); 00372 #endif 00373 int num = width()*height(); 00374 00375 for( index = 0; index<num; index++ ) { 00376 #ifndef SPI_8BIT 00377 _spi.fastWrite(_background); 00378 #else 00379 _spi.fastWrite(_background >> 8); 00380 _spi.fastWrite(_background & 0xFF); 00381 #endif 00382 } 00383 _spi.clearRX(); 00384 00385 #ifndef SPI_8BIT 00386 _spi.format(8,3); 00387 #endif 00388 _cs = 1; 00389 } 00390 #ifndef NO_FLASH_BUFFER 00391 else { 00392 int _orientation=orientation; 00393 set_orientation(backgroundOrientation); 00394 Bitmap(0,0,width(),height(),(unsigned char*) sector_start_adress[ 25 ]); 00395 set_orientation(_orientation); 00396 } 00397 #endif 00398 } 00399 00400 void SPI_TFT::hline(int x0, int x1, int y, int color) 00401 { 00402 unsigned int index=0; 00403 int w; 00404 w = x1 - x0 + 1; 00405 mod_orientation(); 00406 window(x0,y,w,1); 00407 wr_cmd(0x22); 00408 _cs = 0; 00409 wr_dat_start(); 00410 00411 #ifndef SPI_8BIT 00412 _spi.format(16,3); 00413 #endif 00414 int num = x1-x0; 00415 for( index = 0; index<num; index++ ) { 00416 #ifndef SPI_8BIT 00417 _spi.fastWrite(color); 00418 #else 00419 _spi.fastWrite(color >> 8); 00420 _spi.fastWrite(color & 0xFF); 00421 #endif 00422 } 00423 _spi.clearRX(); 00424 00425 #ifndef SPI_8BIT 00426 _spi.format(8,3); 00427 #endif 00428 _cs = 1; 00429 return; 00430 } 00431 00432 void SPI_TFT::vline(int x, int y0, int y1, int color) 00433 { 00434 unsigned int index=0; 00435 int h; 00436 h = y1 - y0 + 1; 00437 mod_orientation(); 00438 window(x,y0,1,h); 00439 wr_cmd(0x22); 00440 _cs = 0; 00441 wr_dat_start(); 00442 #ifndef SPI_8BIT 00443 _spi.format(16,3); 00444 #endif 00445 int num = y1-y0; 00446 for( index = 0; index<num; index++ ) { 00447 #ifndef SPI_8BIT 00448 _spi.fastWrite(color); 00449 #else 00450 _spi.fastWrite(color >> 8); 00451 _spi.fastWrite(color & 0xFF); 00452 #endif 00453 } 00454 _spi.clearRX(); 00455 #ifndef SPI_8BIT 00456 _spi.format(8,3); 00457 #endif 00458 _cs = 1; 00459 return; 00460 } 00461 00462 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color) 00463 { 00464 wr_reg(0x03, 0x1030); 00465 WindowMax(); 00466 int dx = 0, dy = 0; 00467 int dx_sym = 0, dy_sym = 0; 00468 int dx_x2 = 0, dy_x2 = 0; 00469 int di = 0; 00470 00471 dx = x1-x0; 00472 dy = y1-y0; 00473 00474 if (dx == 0) { // vertical line 00475 if (y1 > y0) vline(x0,y0,y1,color); 00476 else vline(x0,y1,y0,color); 00477 return; 00478 } 00479 00480 if (dx > 0) { 00481 dx_sym = 1; 00482 } else { 00483 dx_sym = -1; 00484 } 00485 if (dy == 0) { // horizontal line 00486 if (x1 > x0) hline(x0,x1,y0,color); 00487 else hline(x1,x0,y0,color); 00488 return; 00489 } 00490 00491 if (dy > 0) { 00492 dy_sym = 1; 00493 } else { 00494 dy_sym = -1; 00495 } 00496 00497 dx = dx_sym*dx; 00498 dy = dy_sym*dy; 00499 00500 dx_x2 = dx*2; 00501 dy_x2 = dy*2; 00502 00503 if (dx >= dy) { 00504 di = dy_x2 - dx; 00505 while (x0 != x1) { 00506 00507 pixel(x0, y0, color); 00508 x0 += dx_sym; 00509 if (di<0) { 00510 di += dy_x2; 00511 } else { 00512 di += dy_x2 - dx_x2; 00513 y0 += dy_sym; 00514 } 00515 } 00516 pixel(x0, y0, color); 00517 } else { 00518 di = dx_x2 - dy; 00519 while (y0 != y1) { 00520 pixel(x0, y0, color); 00521 y0 += dy_sym; 00522 if (di < 0) { 00523 di += dx_x2; 00524 } else { 00525 di += dx_x2 - dy_x2; 00526 x0 += dx_sym; 00527 } 00528 } 00529 pixel(x0, y0, color); 00530 } 00531 return; 00532 } 00533 00534 00535 void SPI_TFT::rect(int x0, int y0, int w, int h, int color) 00536 { 00537 hline(x0,x0+w,y0,color); 00538 vline(x0,y0,y0+h,color); 00539 hline(x0,x0+w,y0+h,color); 00540 vline(x0+w,y0,y0+h,color); 00541 00542 return; 00543 } 00544 00545 void SPI_TFT::fillrect(int x0, int y0, int w, int h, int color) 00546 { 00547 unsigned long int index=0; 00548 if (w < 0) { 00549 x0 = x0 + w; 00550 w = -w; 00551 } 00552 if (h < 0) { 00553 y0 = y0 + h; 00554 h = -h; 00555 } 00556 mod_orientation(); 00557 window(x0,y0,w,h); 00558 wr_cmd(0x22); 00559 _cs = 0; 00560 wr_dat_start(); 00561 #ifndef SPI_8BIT 00562 _spi.format(16,3); 00563 #endif 00564 int num = h*w; 00565 for( index = 0; index<num; index++ ) { 00566 #ifndef SPI_8BIT 00567 _spi.fastWrite(color); 00568 #else 00569 _spi.fastWrite(color >> 8); 00570 _spi.fastWrite(color & 0xFF); 00571 #endif 00572 } 00573 _spi.clearRX(); 00574 #ifndef SPI_8BIT 00575 _spi.format(8,3); 00576 #endif 00577 _cs = 1; 00578 return; 00579 } 00580 00581 void SPI_TFT::draw_ellipse(int xc, int yc, int a, int b, unsigned int color) 00582 { 00583 /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */ 00584 wr_reg(0x03, 0x1030); 00585 WindowMax(); 00586 int x = 0, y = b; 00587 long a2 = (long)a*a, b2 = (long)b*b; 00588 long crit1 = -(a2/4 + a%2 + b2); 00589 long crit2 = -(b2/4 + b%2 + a2); 00590 long crit3 = -(b2/4 + b%2); 00591 long t = -a2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4 00592 long dxt = 2*b2*x, dyt = -2*a2*y; 00593 long d2xt = 2*b2, d2yt = 2*a2; 00594 00595 while (y>=0 && x<=a) { 00596 pixel(xc+x, yc+y, color); 00597 if (x!=0 || y!=0) 00598 pixel(xc-x, yc-y, color); 00599 if (x!=0 && y!=0) { 00600 pixel(xc+x, yc-y, color); 00601 pixel(xc-x, yc+y, color); 00602 } 00603 if (t + b2*x <= crit1 || // e(x+1,y-1/2) <= 0 00604 t + a2*y <= crit3) // e(x+1/2,y) <= 0 00605 incx(); 00606 else if (t - a2*y > crit2) // e(x+1/2,y-1) > 0 00607 incy(); 00608 else { 00609 incx(); 00610 incy(); 00611 } 00612 } 00613 } 00614 00615 void SPI_TFT::fill_ellipse(int xc, int yc, int a, int b, unsigned int color) 00616 { 00617 /* e(x,y) = b^2*x^2 + a^2*y^2 - a^2*b^2 */ 00618 int x = 0, y = b; 00619 int rx = x, ry = y; 00620 unsigned int width = 1; 00621 unsigned int height = 1; 00622 long a2 = (long)a*a, b2 = (long)b*b; 00623 long crit1 = -(a2/4 + a%2 + b2); 00624 long crit2 = -(b2/4 + b%2 + a2); 00625 long crit3 = -(b2/4 + b%2); 00626 long t = -a2*y; // e(x+1/2,y-1/2) - (a^2+b^2)/4 00627 long dxt = 2*b2*x, dyt = -2*a2*y; 00628 long d2xt = 2*b2, d2yt = 2*a2; 00629 00630 if (b == 0) { 00631 fillrect(xc-a, yc, 2*a+1, 1, color); 00632 return; 00633 } 00634 00635 while (y>=0 && x<=a) { 00636 if (t + b2*x <= crit1 || // e(x+1,y-1/2) <= 0 00637 t + a2*y <= crit3) { // e(x+1/2,y) <= 0 00638 if (height == 1) 00639 ; // draw nothing 00640 else if (ry*2+1 > (height-1)*2) { 00641 fillrect(xc-rx, yc-ry, width, height-1, color); 00642 fillrect(xc-rx, yc+ry+1, width, 1-height, color); 00643 ry -= height-1; 00644 height = 1; 00645 } else { 00646 fillrect(xc-rx, yc-ry, width, ry*2+1, color); 00647 ry -= ry; 00648 height = 1; 00649 } 00650 incx(); 00651 rx++; 00652 width += 2; 00653 } else if (t - a2*y > crit2) { // e(x+1/2,y-1) > 0 00654 incy(); 00655 height++; 00656 } else { 00657 if (ry*2+1 > height*2) { 00658 fillrect(xc-rx, yc-ry, width, height, color); 00659 fillrect(xc-rx, yc+ry+1, width, -height, color); 00660 } else { 00661 fillrect(xc-rx, yc-ry, width, ry*2+1, color); 00662 } 00663 incx(); 00664 incy(); 00665 rx++; 00666 width += 2; 00667 ry -= height; 00668 height = 1; 00669 } 00670 } 00671 00672 if (ry > height) { 00673 fillrect(xc-rx, yc-ry, width, height, color); 00674 fillrect(xc-rx, yc+ry+1, width, -height, color); 00675 } else { 00676 fillrect(xc-rx, yc-ry, width, ry*2+1, color); 00677 } 00678 } 00679 00680 00681 void SPI_TFT::locate(int x, int y) 00682 { 00683 char_x = x; 00684 char_y = y; 00685 } 00686 00687 int SPI_TFT::columns() 00688 { 00689 return width() / font[1]; 00690 } 00691 00692 int SPI_TFT::rows() 00693 { 00694 return height() / font[2]; 00695 } 00696 00697 int SPI_TFT::_putc(int value) 00698 { 00699 if (value == '\n') { // new line 00700 char_x = 0; 00701 char_y = char_y + font[2]; 00702 if (char_y >= height() - font[2]) { 00703 char_y = 0; 00704 } 00705 } else { 00706 character(char_x, char_y, value); 00707 } 00708 return value; 00709 } 00710 00711 void SPI_TFT::character(int x, int y, int c) 00712 { 00713 unsigned int hor,vert,offset,bpl,j,i,b; 00714 unsigned char* bitmap_char; 00715 unsigned char z,w; 00716 00717 if ((c < 31) || (c > 127)) return; // test char range 00718 00719 // read font parameter from start of array 00720 offset = font[0]; // bytes / char 00721 hor = font[1]; // get hor size of font 00722 vert = font[2]; // get vert size of font 00723 bpl = font[3]; // bytes per line 00724 00725 if (char_x + hor > width()) { 00726 char_x = 0; 00727 char_y = char_y + vert; 00728 if (char_y >= height() - font[2]) { 00729 char_y = 0; 00730 } 00731 } 00732 mod_orientation(); 00733 00734 bitmap_char = &font[((c -32) * offset) + 4]; // start of char bitmap 00735 w = bitmap_char[0]; // width of actual char 00736 window(char_x, char_y,hor,vert); // char box 00737 wr_cmd(0x22); 00738 _cs = 0; 00739 wr_dat_start(); 00740 #ifndef SPI_8BIT 00741 _spi.format(16,3); 00742 #endif 00743 for (j=0; j<vert; j++) { // vert line 00744 for (i=0; i<hor; i++) { // horz line 00745 z = bitmap_char[bpl * i + ((j & 0xF8) >> 3)+1]; 00746 b = 1 << (j & 0x07); 00747 if (( z & b ) == 0x00) { 00748 #ifndef NO_FLASH_BUFFER 00749 if (backgroundimage==false) 00750 { 00751 #endif 00752 #ifndef SPI_8BIT 00753 _spi.fastWrite(_background); 00754 #else 00755 _spi.fastWrite(_background >> 8); 00756 _spi.fastWrite(_background & 0xFF); 00757 #endif 00758 #ifndef NO_FLASH_BUFFER 00759 } 00760 else 00761 { 00762 unsigned short *bitmap_ptr = (unsigned short *)sector_start_adress[ 25 ]; 00763 int angle = (orientation - backgroundOrientation)%4; //Get the difference in orientation between background and current 00764 switch (angle) { 00765 case 0: //Same orientation 00766 bitmap_ptr += width() * (height()-(y+j+1))+x+i; 00767 break; 00768 case 1: //Rotated 1 (don't ask me which direction) 00769 bitmap_ptr += height() * (width()-(x+i+1))+height()-(y+j + 1); 00770 break; 00771 case 2: //Upside down 00772 bitmap_ptr += width() * (y+j)+width() - (x+i + 1); 00773 break; 00774 case 3: //Rotated 3 00775 bitmap_ptr += height() * (x+i)+y+j; 00776 break; 00777 default: 00778 break; 00779 } 00780 00781 #ifndef SPI_8BIT 00782 _spi.fastWrite(*bitmap_ptr); 00783 #else 00784 _spi.fastWrite((*bitmap_ptr) >> 8); 00785 _spi.fastWrite((*bitmap_ptr) & 0xFF); 00786 #endif 00787 } 00788 #endif 00789 } else { 00790 #ifndef SPI_8BIT 00791 _spi.fastWrite(_foreground); 00792 #else 00793 _spi.fastWrite(_foreground >> 8); 00794 _spi.fastWrite(_foreground & 0xFF); 00795 #endif 00796 } 00797 } 00798 } 00799 _spi.clearRX(); 00800 #ifndef SPI_8BIT 00801 _spi.format(8,3); 00802 #endif 00803 _cs = 1; 00804 if ((w + 2) < hor) { // x offset to next char 00805 char_x += w + 2; 00806 } else char_x += hor; 00807 } 00808 00809 void SPI_TFT::set_font(unsigned char* f) 00810 { 00811 font = f; 00812 } 00813 00814 00815 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 00816 { 00817 unsigned int i,j; 00818 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 00819 mod_orientation(); 00820 window(x, y, w, h); 00821 wr_cmd(0x22); 00822 _cs = 0; 00823 wr_dat_start(); 00824 #ifndef SPI_8BIT 00825 _spi.format(16,3); 00826 #endif 00827 bitmap_ptr += ((h - 1)*w); 00828 for (j = 0; j < h; j++) { //Lines 00829 for (i = 0; i < w; i++) { // copy pixel data to TFT 00830 #ifndef SPI_8BIT 00831 _spi.fastWrite(*bitmap_ptr); // one line 00832 #else 00833 _spi.fastWrite((*bitmap_ptr) >> 8); 00834 _spi.fastWrite((*bitmap_ptr) & 0xFF); 00835 #endif 00836 bitmap_ptr++; 00837 } 00838 bitmap_ptr -= 2*w; 00839 } 00840 _spi.clearRX(); 00841 #ifndef SPI_8BIT 00842 _spi.format(8,3); 00843 #endif 00844 _cs = 1; 00845 } 00846 00847 int SPI_TFT::Bitmap(unsigned int x, unsigned int y, const char *Name_BMP) 00848 { 00849 #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red >> 3 ) << 11 ) | (( green >> 2 ) << 5 ) | ( blue >> 3 )) 00850 mod_orientation(); 00851 00852 bitmapData bmp = getBitmapData(Name_BMP); 00853 if (bmp.return_code != 1) 00854 return bmp.return_code; 00855 00856 00857 unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width); // we need a buffer for a line 00858 unsigned short *line_short = (unsigned short*) (line); // Same one, addressed as short 00859 00860 00861 if ((bmp.height > height()+y) || (bmp.width > width()+x)) 00862 return -3; //Size mismatch 00863 00864 if (line == NULL) 00865 return(-4); // error no memory 00866 00867 00868 for (int j = bmp.height-1; j >= 0; j--) { //Lines bottom up 00869 int off = j * (bmp.width * bmp.bits/8 + bmp.pad) + bmp.start_data; // start of line 00870 fseek(bmp.file, off ,SEEK_SET); 00871 fread(line,1,bmp.width * bmp.bits/8,bmp.file); // read a line - slow ! 00872 00873 //If 24 bit format, convert to 565 00874 if (bmp.bits == 24) { 00875 for (int i = 0; i<bmp.width; i++) { 00876 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]); 00877 } 00878 } 00879 00880 window(x, y+bmp.height - 1 - j,bmp.width ,1); 00881 wr_cmd(0x22); 00882 00883 _cs = 0; 00884 wr_dat_start(); 00885 #ifndef SPI_8BIT 00886 _spi.format(16,3); 00887 #endif 00888 _spi.setFormat(); 00889 00890 for (int i = 0; i < bmp.width; i++) { // copy pixel data to TFT 00891 #ifndef SPI_8BIT 00892 _spi.fastWrite(line_short[i]); // one line 00893 #else 00894 _spi.fastWrite(line_short[i] >> 8); 00895 _spi.fastWrite(line_short[i] & 0xFF); 00896 #endif 00897 } 00898 00899 _spi.clearRX(); 00900 #ifndef SPI_8BIT 00901 _spi.format(8,3); 00902 #endif 00903 _cs = 1; 00904 00905 } 00906 00907 00908 free (line); 00909 fclose(bmp.file); 00910 WindowMax(); 00911 00912 return(1); 00913 } 00914 00915 #ifndef NO_FLASH_BUFFER 00916 00917 int SPI_TFT::fileToFlash(const char *Name_BMP) 00918 { 00919 #define RGB565CONVERT(red, green, blue) (uint16_t)( (( red >> 3 ) << 11 ) | (( green >> 2 ) << 5 ) | ( blue >> 3 )) 00920 00921 mod_orientation(); 00922 00923 bitmapData bmp = getBitmapData(Name_BMP); 00924 if (bmp.return_code != 1) 00925 return bmp.return_code; 00926 00927 00928 unsigned char *line = (unsigned char *) malloc (bmp.bits/8 * bmp.width); // we need a buffer for a line 00929 unsigned short *line_short = (unsigned short*) (line); // Same one, addressed as short 00930 00931 unsigned short *flashSector = (unsigned short *) malloc (256); //And one to send to flash 00932 00933 if ((bmp.height != height()) || (bmp.width != width())) 00934 return -3; //Size mismatch 00935 00936 if ((line == NULL) || (flashSector == NULL)) 00937 return(-4); // error no memory 00938 00939 00940 int flashPointer = 0, flashWrites = 0; 00941 00942 //Erase Flash that will be used: 00943 if ( iap.blank_check( 25, 29 ) == SECTOR_NOT_BLANK ) { 00944 iap.prepare( 25, 29 ); 00945 iap.erase( 25, 29 ); 00946 } 00947 00948 for (int j = 0; j < bmp.height; j++) { //Lines bottom up 00949 int off = j * (bmp.width * bmp.bits/8 + bmp.pad) + bmp.start_data; // start of line 00950 fseek(bmp.file, off ,SEEK_SET); 00951 fread(line,1,bmp.width * bmp.bits/8,bmp.file); // read a line - slow ! 00952 00953 //If 24 bit format, do some processing 00954 if (bmp.bits == 24) { 00955 for (int i = 0; i<bmp.width; i++) { 00956 line_short[i] = RGB565CONVERT(line[3*i+2], line[3*i+1], line[3*i]); 00957 } 00958 } 00959 00960 00961 for (int i = 0; i < bmp.width; i++) { // copy pixel data to TFT 00962 flashSector[flashPointer] = line_short[i]; // one line 00963 flashPointer++; 00964 00965 //If flashpointer reached the end, write to flash 00966 if (flashPointer == 128) { 00967 iap.prepare( 25, 29 ); 00968 iap.write((char *)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256); 00969 flashPointer = 0; 00970 flashWrites++; 00971 if (flashWrites == 1000) 00972 error("Too many flashwrites"); 00973 } 00974 } 00975 } 00976 //write remaining data 00977 if (flashPointer!=0) { 00978 iap.prepare( 25, 29 ); 00979 iap.write((char*)flashSector, sector_start_adress[ 25 ] + 256 * flashWrites, 256); 00980 flashPointer = 0; 00981 flashWrites++; 00982 if (flashWrites == 1000) 00983 error("Too many flashwrites"); 00984 } 00985 00986 00987 00988 free (line); 00989 fclose(bmp.file); 00990 backgroundImage(true); 00991 backgroundOrientation = orientation; 00992 return(1); 00993 } 00994 00995 void SPI_TFT::backgroundImage( bool active) { 00996 backgroundimage = active; 00997 } 00998 #endif 00999 01000 01001 SPI_TFT::bitmapData SPI_TFT::getBitmapData(const char *Name_BMP){ 01002 #define OffsetPixelWidth 18 01003 #define OffsetPixelHeigh 22 01004 #define OffsetFileSize 34 01005 #define OffsetPixData 10 01006 #define OffsetBPP 28 01007 01008 01009 bitmapData retval; 01010 retval.return_code = 1; 01011 unsigned char BMP_Header[54]; 01012 01013 retval.file = fopen(Name_BMP, "rb"); // open the bmp file 01014 if (!retval.file) { 01015 retval.return_code = 0; 01016 return(retval); // error file not found ! 01017 } 01018 01019 fread(&BMP_Header[0],1,54,retval.file); // get the BMP Header 01020 01021 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 01022 fclose(retval.file); 01023 retval.return_code = -1; 01024 return(retval); // error not a BMP file 01025 } 01026 01027 int BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 01028 if (BPP_t == 0x0010) 01029 retval.bits = 16; 01030 else if (BPP_t == 0x0018) 01031 retval.bits = 24; 01032 else { 01033 fclose(retval.file); 01034 retval.return_code = -2; 01035 return(retval); // error no 16/24 bit BMP 01036 } 01037 01038 retval.height = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 01039 retval.width = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 01040 if (retval.height > height()|| retval.width > width()) { 01041 fclose(retval.file); 01042 retval.return_code = -3; 01043 return(retval); // too big 01044 } 01045 01046 01047 retval.start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 01048 01049 // the bmp lines are padded to multiple of 4 bytes 01050 retval.pad = -1; 01051 do { 01052 retval.pad ++; 01053 } while ((retval.width * retval.bits/8 + retval.pad)%4 != 0); 01054 return retval; 01055 01056 }
Generated on Wed Jul 13 2022 08:41:16 by 1.7.2