Lib for the new LCD Display with ILI9341 controller Modified for huge fonts (>255 bytes/char). Needs modified font.h files with 2-byte size parameter. Window size is set on a per-character basis to minimise the number of pixels written (speed-up, plus better detection of whether one last character will fit on the current line). NUCLEO & NXP DMA-enabled versions are modified but untested.
Fork of SPI_TFT_ILI9341 by
SPI_TFT_ILI9341_NXP.cpp
00001 /* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller 00002 * Copyright (c) 2014 Peter Drescher - DC2PD 00003 * Special version for NXP LPC1768 00004 * 00005 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00006 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00007 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00008 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00009 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00010 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00011 * THE SOFTWARE. 00012 */ 00013 00014 // 25.06.14 initial version 00015 00016 // only include this file if target is LPC1768 00017 #if defined TARGET_LPC1768 00018 00019 #include "SPI_TFT_ILI9341.h" 00020 #include "mbed.h" 00021 00022 #if defined TARGET_LPC1768 00023 #define use_ram 00024 #endif 00025 00026 // some defines for the DMA use 00027 #define DMA_CHANNEL_ENABLE 1 00028 #define DMA_TRANSFER_TYPE_M2P (1UL << 11) 00029 #define DMA_CHANNEL_TCIE (1UL << 31) 00030 #define DMA_CHANNEL_SRC_INC (1UL << 26) 00031 #define DMA_MASK_IE (1UL << 14) 00032 #define DMA_MASK_ITC (1UL << 15) 00033 #define DMA_SSP1_TX (1UL << 2) 00034 #define DMA_SSP0_TX (0) 00035 #define DMA_DEST_SSP1_TX (2UL << 6) 00036 #define DMA_DEST_SSP0_TX (0UL << 6) 00037 00038 #define BPP 16 // Bits per pixel 00039 00040 //extern Serial pc; 00041 //extern DigitalOut xx; // debug !! 00042 00043 00044 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name) 00045 : GraphicsDisplay(name), SPI(mosi,miso,sclk), _cs(cs), _reset(reset), _dc(dc) 00046 { 00047 00048 format(8,3); // 8 bit spi mode 3 00049 frequency(10000000); // 10 Mhz SPI clock : result 2 / 4 = 8 00050 orientation = 0; 00051 char_x = 0; 00052 if((int)_spi.spi == SPI_0) { // test which SPI is in use 00053 spi_num = 0; 00054 } 00055 if((int)_spi.spi == SPI_1) { 00056 spi_num = 1; 00057 } 00058 tft_reset(); 00059 } 00060 00061 // we define a fast write to the SPI port 00062 void inline SPI_TFT_ILI9341::f_write(int data) 00063 { 00064 while(((_spi.spi->SR) & 0x02) == 0); 00065 _spi.spi->DR = data; 00066 } 00067 00068 // wait for SPI not busy 00069 // we have to wait for the last bit to switch the cs off 00070 void inline SPI_TFT_ILI9341::spi_bsy(void) 00071 { 00072 while ((_spi.spi->SR & 0x10) == 0x10); // SPI not idle 00073 } 00074 00075 00076 // switch fast between 8 and 16 bit mode 00077 void SPI_TFT_ILI9341::spi_16(bool s) 00078 { 00079 if(s) _spi.spi->CR0 |= 0x08; // switch to 16 bit Mode 00080 else _spi.spi->CR0 &= ~(0x08); // switch to 8 bit Mode 00081 00082 } 00083 00084 00085 int SPI_TFT_ILI9341::width() 00086 { 00087 if (orientation == 0 || orientation == 2) return 240; 00088 else return 320; 00089 } 00090 00091 00092 int SPI_TFT_ILI9341::height() 00093 { 00094 if (orientation == 0 || orientation == 2) return 320; 00095 else return 240; 00096 } 00097 00098 00099 void SPI_TFT_ILI9341::set_orientation(unsigned int o) 00100 { 00101 orientation = o; 00102 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL 00103 switch (orientation) { 00104 case 0: 00105 f_write(0x48); 00106 break; 00107 case 1: 00108 f_write(0x28); 00109 break; 00110 case 2: 00111 f_write(0x88); 00112 break; 00113 case 3: 00114 f_write(0xE8); 00115 break; 00116 } 00117 spi_bsy(); // wait for end of transfer 00118 _cs = 1; 00119 WindowMax(); 00120 } 00121 00122 00123 // write command to tft register 00124 // use fast command 00125 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd) 00126 { 00127 _dc = 0; 00128 _cs = 0; 00129 f_write(cmd); 00130 spi_bsy(); 00131 _dc = 1; 00132 } 00133 00134 void SPI_TFT_ILI9341::wr_dat(unsigned char dat) 00135 { 00136 f_write(dat); 00137 spi_bsy(); // wait for SPI send 00138 } 00139 00140 // the ILI9341 can read 00141 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd) 00142 { 00143 // has to change !! 00144 return(0); 00145 } 00146 00147 // read 32 bit 00148 int SPI_TFT_ILI9341::rd_32(unsigned char cmd) 00149 { 00150 // has to change !!! 00151 return(0); 00152 } 00153 00154 int SPI_TFT_ILI9341::Read_ID(void) 00155 { 00156 int r; 00157 r = rd_byte(0x0A); 00158 r = rd_byte(0x0A); 00159 r = rd_byte(0x0A); 00160 r = rd_byte(0x0A); 00161 return(r); 00162 } 00163 00164 00165 // Init code based on MI0283QT datasheet 00166 // this code is called only at start 00167 // no need to be optimized 00168 00169 void SPI_TFT_ILI9341::tft_reset() 00170 { 00171 _cs = 1; // cs high 00172 _dc = 1; // dc high 00173 _reset = 0; // display reset 00174 00175 wait_us(50); 00176 _reset = 1; // end hardware reset 00177 wait_ms(5); 00178 00179 wr_cmd(0x01); // SW reset 00180 wait_ms(5); 00181 wr_cmd(0x28); // display off 00182 00183 /* Start Initial Sequence ----------------------------------------------------*/ 00184 wr_cmd(0xCF); 00185 f_write(0x00); 00186 f_write(0x83); 00187 f_write(0x30); 00188 spi_bsy(); 00189 _cs = 1; 00190 00191 wr_cmd(0xED); 00192 f_write(0x64); 00193 f_write(0x03); 00194 f_write(0x12); 00195 f_write(0x81); 00196 spi_bsy(); 00197 _cs = 1; 00198 00199 wr_cmd(0xE8); 00200 f_write(0x85); 00201 f_write(0x01); 00202 f_write(0x79); 00203 spi_bsy(); 00204 _cs = 1; 00205 00206 wr_cmd(0xCB); 00207 f_write(0x39); 00208 f_write(0x2C); 00209 f_write(0x00); 00210 f_write(0x34); 00211 f_write(0x02); 00212 spi_bsy(); 00213 _cs = 1; 00214 00215 wr_cmd(0xF7); 00216 f_write(0x20); 00217 spi_bsy(); 00218 _cs = 1; 00219 00220 wr_cmd(0xEA); 00221 f_write(0x00); 00222 f_write(0x00); 00223 spi_bsy(); 00224 _cs = 1; 00225 00226 wr_cmd(0xC0); // POWER_CONTROL_1 00227 f_write(0x26); 00228 spi_bsy(); 00229 _cs = 1; 00230 00231 wr_cmd(0xC1); // POWER_CONTROL_2 00232 f_write(0x11); 00233 spi_bsy(); 00234 _cs = 1; 00235 00236 wr_cmd(0xC5); // VCOM_CONTROL_1 00237 f_write(0x35); 00238 f_write(0x3E); 00239 spi_bsy(); 00240 _cs = 1; 00241 00242 wr_cmd(0xC7); // VCOM_CONTROL_2 00243 f_write(0xBE); 00244 spi_bsy(); 00245 _cs = 1; 00246 00247 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL 00248 f_write(0x48); 00249 spi_bsy(); 00250 _cs = 1; 00251 00252 wr_cmd(0x3A); // COLMOD_PIXEL_FORMAT_SET 00253 f_write(0x55); // 16 bit pixel 00254 spi_bsy(); 00255 _cs = 1; 00256 00257 wr_cmd(0xB1); // Frame Rate 00258 f_write(0x00); 00259 f_write(0x1B); 00260 spi_bsy(); 00261 _cs = 1; 00262 00263 wr_cmd(0xF2); // Gamma Function Disable 00264 f_write(0x08); 00265 spi_bsy(); 00266 _cs = 1; 00267 00268 wr_cmd(0x26); 00269 f_write(0x01); // gamma set for curve 01/2/04/08 00270 spi_bsy(); 00271 _cs = 1; 00272 00273 wr_cmd(0xE0); // positive gamma correction 00274 f_write(0x1F); 00275 f_write(0x1A); 00276 f_write(0x18); 00277 f_write(0x0A); 00278 f_write(0x0F); 00279 f_write(0x06); 00280 f_write(0x45); 00281 f_write(0x87); 00282 f_write(0x32); 00283 f_write(0x0A); 00284 f_write(0x07); 00285 f_write(0x02); 00286 f_write(0x07); 00287 f_write(0x05); 00288 f_write(0x00); 00289 spi_bsy(); 00290 _cs = 1; 00291 00292 wr_cmd(0xE1); // negativ gamma correction 00293 f_write(0x00); 00294 f_write(0x25); 00295 f_write(0x27); 00296 f_write(0x05); 00297 f_write(0x10); 00298 f_write(0x09); 00299 f_write(0x3A); 00300 f_write(0x78); 00301 f_write(0x4D); 00302 f_write(0x05); 00303 f_write(0x18); 00304 f_write(0x0D); 00305 f_write(0x38); 00306 f_write(0x3A); 00307 f_write(0x1F); 00308 spi_bsy(); 00309 _cs = 1; 00310 00311 WindowMax (); 00312 00313 //wr_cmd(0x34); // tearing effect off 00314 //_cs = 1; 00315 00316 //wr_cmd(0x35); // tearing effect on 00317 //_cs = 1; 00318 00319 wr_cmd(0xB7); // entry mode 00320 f_write(0x07); 00321 spi_bsy(); 00322 _cs = 1; 00323 00324 wr_cmd(0xB6); // display function control 00325 f_write(0x0A); 00326 f_write(0x82); 00327 f_write(0x27); 00328 f_write(0x00); 00329 spi_bsy(); 00330 _cs = 1; 00331 00332 wr_cmd(0x11); // sleep out 00333 spi_bsy(); 00334 _cs = 1; 00335 00336 wait_ms(100); 00337 00338 wr_cmd(0x29); // display on 00339 spi_bsy(); 00340 _cs = 1; 00341 00342 wait_ms(100); 00343 00344 // setup DMA channel 0 00345 LPC_SC->PCONP |= (1UL << 29); // Power up the GPDMA. 00346 LPC_GPDMA->DMACConfig = 1; // enable DMA controller 00347 LPC_GPDMA->DMACIntTCClear = 0x1; // Reset the Interrupt status 00348 LPC_GPDMA->DMACIntErrClr = 0x1; 00349 LPC_GPDMACH0->DMACCLLI = 0; 00350 } 00351 00352 00353 // speed optimized 00354 // write direct to SPI1 register ! 00355 void SPI_TFT_ILI9341::pixel(int x, int y, int color) 00356 { 00357 wr_cmd(0x2A); 00358 spi_16(1); // switch to 8 bit Mode 00359 f_write(x); 00360 spi_bsy(); 00361 _cs = 1; 00362 00363 spi_16(0); // switch to 8 bit Mode 00364 wr_cmd(0x2B); 00365 spi_16(1); 00366 f_write(y); 00367 spi_bsy(); 00368 _cs = 1; 00369 spi_16(0); 00370 00371 wr_cmd(0x2C); // send pixel 00372 spi_16(1); 00373 f_write(color); 00374 spi_bsy(); 00375 _cs = 1; 00376 spi_16(0); 00377 } 00378 00379 // optimized 00380 // write direct to SPI1 register ! 00381 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) 00382 { 00383 wr_cmd(0x2A); 00384 spi_16(1); 00385 f_write(x); 00386 f_write(x+w-1); 00387 spi_bsy(); 00388 _cs = 1; 00389 spi_16(0); 00390 00391 wr_cmd(0x2B); 00392 spi_16(1); 00393 f_write(y) ; 00394 f_write(y+h-1); 00395 spi_bsy(); 00396 _cs = 1; 00397 spi_16(0); 00398 } 00399 00400 00401 void SPI_TFT_ILI9341::WindowMax (void) 00402 { 00403 window (0, 0, width(), height()); 00404 } 00405 00406 // optimized 00407 // use DMA to transfer pixel data to the screen 00408 void SPI_TFT_ILI9341::cls (void) 00409 { 00410 // we can use the fillrect function 00411 fillrect(0,0,width()-1,height()-1,_background); 00412 } 00413 00414 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color) 00415 { 00416 00417 int x = -r, y = 0, err = 2-2*r, e2; 00418 do { 00419 pixel(x0-x, y0+y,color); 00420 pixel(x0+x, y0+y,color); 00421 pixel(x0+x, y0-y,color); 00422 pixel(x0-x, y0-y,color); 00423 e2 = err; 00424 if (e2 <= y) { 00425 err += ++y*2+1; 00426 if (-x == y && e2 <= x) e2 = 0; 00427 } 00428 if (e2 > x) err += ++x*2+1; 00429 } while (x <= 0); 00430 } 00431 00432 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) 00433 { 00434 int x = -r, y = 0, err = 2-2*r, e2; 00435 do { 00436 vline(x0-x, y0-y, y0+y, color); 00437 vline(x0+x, y0-y, y0+y, color); 00438 e2 = err; 00439 if (e2 <= y) { 00440 err += ++y*2+1; 00441 if (-x == y && e2 <= x) e2 = 0; 00442 } 00443 if (e2 > x) err += ++x*2+1; 00444 } while (x <= 0); 00445 } 00446 00447 00448 // optimized for speed 00449 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color) 00450 { 00451 int w,j; 00452 w = x1 - x0 + 1; 00453 window(x0,y,w,1); 00454 _dc = 0; 00455 _cs = 0; 00456 f_write(0x2C); // send pixel 00457 spi_bsy(); 00458 _dc = 1; 00459 spi_16(1); 00460 00461 for (j=0; j<w; j++) { 00462 f_write(color); 00463 } 00464 spi_bsy(); 00465 spi_16(0); 00466 _cs = 1; 00467 WindowMax(); 00468 return; 00469 } 00470 00471 // optimized for speed 00472 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color) 00473 { 00474 int h,y; 00475 h = y1 - y0 + 1; 00476 window(x,y0,1,h); 00477 _dc = 0; 00478 _cs = 0; 00479 f_write(0x2C); // send pixel 00480 spi_bsy(); 00481 _dc = 1; 00482 spi_16(1); 00483 // switch to 16 bit Mode 3 00484 for (y=0; y<h; y++) { 00485 f_write(color); 00486 } 00487 spi_bsy(); 00488 spi_16(0); 00489 _cs = 1; 00490 WindowMax(); 00491 return; 00492 } 00493 00494 00495 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color) 00496 { 00497 //WindowMax(); 00498 int dx = 0, dy = 0; 00499 int dx_sym = 0, dy_sym = 0; 00500 int dx_x2 = 0, dy_x2 = 0; 00501 int di = 0; 00502 00503 dx = x1-x0; 00504 dy = y1-y0; 00505 00506 if (dx == 0) { /* vertical line */ 00507 if (y1 > y0) vline(x0,y0,y1,color); 00508 else vline(x0,y1,y0,color); 00509 return; 00510 } 00511 00512 if (dx > 0) { 00513 dx_sym = 1; 00514 } else { 00515 dx_sym = -1; 00516 } 00517 if (dy == 0) { /* horizontal line */ 00518 if (x1 > x0) hline(x0,x1,y0,color); 00519 else hline(x1,x0,y0,color); 00520 return; 00521 } 00522 00523 if (dy > 0) { 00524 dy_sym = 1; 00525 } else { 00526 dy_sym = -1; 00527 } 00528 00529 dx = dx_sym*dx; 00530 dy = dy_sym*dy; 00531 00532 dx_x2 = dx*2; 00533 dy_x2 = dy*2; 00534 00535 if (dx >= dy) { 00536 di = dy_x2 - dx; 00537 while (x0 != x1) { 00538 00539 pixel(x0, y0, color); 00540 x0 += dx_sym; 00541 if (di<0) { 00542 di += dy_x2; 00543 } else { 00544 di += dy_x2 - dx_x2; 00545 y0 += dy_sym; 00546 } 00547 } 00548 pixel(x0, y0, color); 00549 } else { 00550 di = dx_x2 - dy; 00551 while (y0 != y1) { 00552 pixel(x0, y0, color); 00553 y0 += dy_sym; 00554 if (di < 0) { 00555 di += dx_x2; 00556 } else { 00557 di += dx_x2 - dy_x2; 00558 x0 += dx_sym; 00559 } 00560 } 00561 pixel(x0, y0, color); 00562 } 00563 return; 00564 } 00565 00566 00567 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color) 00568 { 00569 00570 if (x1 > x0) hline(x0,x1,y0,color); 00571 else hline(x1,x0,y0,color); 00572 00573 if (y1 > y0) vline(x0,y0,y1,color); 00574 else vline(x0,y1,y0,color); 00575 00576 if (x1 > x0) hline(x0,x1,y1,color); 00577 else hline(x1,x0,y1,color); 00578 00579 if (y1 > y0) vline(x1,y0,y1,color); 00580 else vline(x1,y1,y0,color); 00581 00582 return; 00583 } 00584 00585 00586 00587 // optimized for speed 00588 // use DMA 00589 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color) 00590 { 00591 int h = y1 - y0 + 1; 00592 int w = x1 - x0 + 1; 00593 int pixel = h * w; 00594 unsigned int dma_count; 00595 window(x0,y0,w,h); 00596 00597 wr_cmd(0x2C); // send pixel 00598 spi_16(1); 00599 00600 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; 00601 00602 switch(spi_num) { // decide which SPI is to use 00603 case (0): 00604 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00605 LPC_SSP0->DMACR = 0x2; 00606 break; 00607 case (1): 00608 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00609 LPC_SSP1->DMACR = 0x2; 00610 break; 00611 } 00612 00613 // start DMA 00614 do { 00615 if (pixel > 4095) { 00616 dma_count = 4095; 00617 pixel = pixel - 4095; 00618 } else { 00619 dma_count = pixel; 00620 pixel = 0; 00621 } 00622 LPC_GPDMA->DMACIntTCClear = 0x1; 00623 LPC_GPDMA->DMACIntErrClr = 0x1; 00624 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt 00625 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_num ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00626 LPC_GPDMA->DMACSoftSReq = 0x1; // DMA request 00627 do { 00628 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00629 } while (pixel > 0); 00630 00631 spi_bsy(); // wait for end of transfer 00632 spi_16(0); 00633 _cs = 1; 00634 WindowMax(); 00635 return; 00636 } 00637 00638 void SPI_TFT_ILI9341::locate(int x, int y) 00639 { 00640 char_x = x; 00641 char_y = y; 00642 } 00643 00644 int SPI_TFT_ILI9341::columns() 00645 { 00646 return width() / font[1]; 00647 } 00648 00649 00650 int SPI_TFT_ILI9341::rows() 00651 { 00652 return height() / font[2]; 00653 } 00654 00655 00656 int SPI_TFT_ILI9341::_putc(int value) 00657 { 00658 if (value == '\n') { // new line 00659 char_x = 0; 00660 char_y = char_y + font[2]; 00661 if (char_y >= height() - font[2]) { 00662 char_y = 0; 00663 } 00664 } else { 00665 character(char_x, char_y, value); 00666 } 00667 return value; 00668 } 00669 00670 00671 // speed optimized 00672 // will use dma 00673 void SPI_TFT_ILI9341::character(int x, int y, int c) 00674 { 00675 unsigned int hor,vert,offset,bpl,j,i,b; 00676 unsigned char* zeichen; 00677 unsigned char z,w; 00678 #ifdef use_ram 00679 unsigned int pixel; 00680 unsigned int p; 00681 unsigned int dma_count,dma_off; 00682 uint16_t *buffer; 00683 #endif 00684 00685 if ((c < 31) || (c > 127)) return; // test char range 00686 00687 // read font parameter from start of array 00688 offset = (font[0]<<8) + font[1]; // bytes / char 00689 hor = font[2]; // get hor size of font 00690 vert = font[3]; // get vert size of font 00691 bpl = font[4]; // bytes per line 00692 00693 zeichen = &font[((c -32) * offset) + 5]; // start of char bitmap 00694 w = zeichen[0]; // width of actual char 00695 00696 if (char_x + (w+2) > width()) { 00697 char_x = 0; 00698 char_y = char_y + vert; 00699 if (char_y >= height() - vert) { 00700 char_y = 0; 00701 } 00702 } 00703 window(char_x, char_y,(w+2),vert); // setup char box 00704 wr_cmd(0x2C); 00705 spi_16(1); // switch to 16 bit Mode 00706 #ifdef use_ram 00707 pixel = (w+2) * vert; // calculate buffer size 00708 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the font 00709 if(buffer != NULL) { // there is memory space -> use dma 00710 p = 0; 00711 // construct the font into the buffer 00712 for (j=0; j<vert; j++) { // vert line 00713 for (i=0; i<(w+2); i++) { // horz line 00714 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00715 b = 1 << (j & 0x07); 00716 if (( z & b ) == 0x00) { 00717 buffer[p] = _background; 00718 } else { 00719 buffer[p] = _foreground; 00720 } 00721 p++; 00722 } 00723 } 00724 // copy the buffer with DMA SPI to display 00725 dma_off = 0; // offset for DMA transfer 00726 00727 switch(spi_num) { // decide which SPI is to use 00728 case (0): 00729 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00730 LPC_SSP0->DMACR = 0x2; 00731 break; 00732 case (1): 00733 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00734 LPC_SSP1->DMACR = 0x2; 00735 break; 00736 } 00737 // start DMA 00738 do { 00739 if (pixel > 4095) { // this is a giant font ! 00740 dma_count = 4095; 00741 pixel = pixel - 4095; 00742 } else { 00743 dma_count = pixel; 00744 pixel = 0; 00745 } 00746 LPC_GPDMA->DMACIntTCClear = 0x1; 00747 LPC_GPDMA->DMACIntErrClr = 0x1; 00748 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) (buffer + dma_off); 00749 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt 00750 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_num ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00751 LPC_GPDMA->DMACSoftSReq = 0x1; 00752 do { 00753 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00754 dma_off = dma_off + dma_count; 00755 } while (pixel > 0); 00756 00757 00758 spi_bsy(); 00759 free ((uint16_t *) buffer); 00760 spi_16(0); 00761 } 00762 00763 else { 00764 #endif 00765 for (j=0; j<vert; j++) { // vert line 00766 for (i=0; i<(w+2); i++) { // horz line 00767 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00768 b = 1 << (j & 0x07); 00769 if (( z & b ) == 0x00) { 00770 f_write(_background); 00771 } else { 00772 f_write(_foreground); 00773 } 00774 } 00775 } 00776 spi_bsy(); 00777 _cs = 1; 00778 spi_16(0); 00779 #ifdef use_ram 00780 } 00781 #endif 00782 _cs = 1; 00783 WindowMax(); 00784 if ((w + 2) < hor) { // x offset to next char 00785 char_x += w + 2; 00786 } else char_x += hor; 00787 } 00788 00789 00790 void SPI_TFT_ILI9341::set_font(unsigned char* f) 00791 { 00792 font = f; 00793 } 00794 00795 00796 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 00797 { 00798 unsigned int j; 00799 int padd; 00800 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 00801 00802 unsigned int i; 00803 00804 // the lines are padded to multiple of 4 bytes in a bitmap 00805 padd = -1; 00806 do { 00807 padd ++; 00808 } while (2*(w + padd)%4 != 0); 00809 window(x, y, w, h); 00810 bitmap_ptr += ((h - 1)* (w + padd)); 00811 wr_cmd(0x2C); // send pixel 00812 spi_16(1); 00813 for (j = 0; j < h; j++) { //Lines 00814 for (i = 0; i < w; i++) { // one line 00815 f_write(*bitmap_ptr); // one line 00816 bitmap_ptr++; 00817 } 00818 bitmap_ptr -= 2*w; 00819 bitmap_ptr -= padd; 00820 } 00821 spi_bsy(); 00822 _cs = 1; 00823 spi_16(0); 00824 WindowMax(); 00825 } 00826 00827 00828 // local filesystem is not implemented but you can add a SD card to a different SPI 00829 00830 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) 00831 { 00832 00833 #define OffsetPixelWidth 18 00834 #define OffsetPixelHeigh 22 00835 #define OffsetFileSize 34 00836 #define OffsetPixData 10 00837 #define OffsetBPP 28 00838 00839 char filename[50]; 00840 unsigned char BMP_Header[54]; 00841 unsigned short BPP_t; 00842 unsigned int PixelWidth,PixelHeigh,start_data; 00843 unsigned int i,off; 00844 int padd,j; 00845 unsigned short *line; 00846 00847 // get the filename 00848 i=0; 00849 while (*Name_BMP!='\0') { 00850 filename[i++]=*Name_BMP++; 00851 } 00852 filename[i] = 0; 00853 00854 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file 00855 if (!Image) { 00856 return(0); // error file not found ! 00857 } 00858 00859 fread(&BMP_Header[0],1,54,Image); // get the BMP Header 00860 00861 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 00862 fclose(Image); 00863 return(-1); // error no BMP file 00864 } 00865 00866 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 00867 if (BPP_t != 0x0010) { 00868 fclose(Image); 00869 return(-2); // error no 16 bit BMP 00870 } 00871 00872 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 00873 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 00874 if (PixelHeigh > height() + y || PixelWidth > width() + x) { 00875 fclose(Image); 00876 return(-3); // to big 00877 } 00878 00879 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 00880 00881 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line 00882 if (line == NULL) { 00883 return(-4); // error no memory 00884 } 00885 00886 // the bmp lines are padded to multiple of 4 bytes 00887 padd = -1; 00888 do { 00889 padd ++; 00890 } while ((PixelWidth * 2 + padd)%4 != 0); 00891 00892 window(x, y,PixelWidth ,PixelHeigh); 00893 wr_cmd(0x2C); // send pixel 00894 spi_16(1); 00895 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 00896 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 00897 fseek(Image, off ,SEEK_SET); 00898 fread(line,1,PixelWidth * 2,Image); // read a line - slow 00899 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 00900 f_write(line[i]); // one 16 bit pixel 00901 } 00902 } 00903 spi_bsy(); 00904 _cs = 1; 00905 spi_16(0); 00906 free (line); 00907 fclose(Image); 00908 WindowMax(); 00909 return(1); 00910 } 00911 00912 #endif 00913
Generated on Wed Jul 13 2022 12:41:39 by 1.7.2