Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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]; // bytes / char 00689 hor = font[1]; // get hor size of font 00690 vert = font[2]; // get vert size of font 00691 bpl = font[3]; // bytes per line 00692 00693 if (char_x + hor > width()) { 00694 char_x = 0; 00695 char_y = char_y + vert; 00696 if (char_y >= height() - font[2]) { 00697 char_y = 0; 00698 } 00699 } 00700 window(char_x, char_y,hor,vert); // setup char box 00701 wr_cmd(0x2C); 00702 spi_16(1); // switch to 16 bit Mode 00703 #ifdef use_ram 00704 pixel = hor * vert; // calculate buffer size 00705 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the font 00706 if(buffer != NULL) { // there is memory space -> use dma 00707 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00708 w = zeichen[0]; // width of actual char 00709 p = 0; 00710 // construct the font into the buffer 00711 for (j=0; j<vert; j++) { // vert line 00712 for (i=0; i<hor; i++) { // horz line 00713 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00714 b = 1 << (j & 0x07); 00715 if (( z & b ) == 0x00) { 00716 buffer[p] = _background; 00717 } else { 00718 buffer[p] = _foreground; 00719 } 00720 p++; 00721 } 00722 } 00723 // copy the buffer with DMA SPI to display 00724 dma_off = 0; // offset for DMA transfer 00725 00726 switch(spi_num) { // decide which SPI is to use 00727 case (0): 00728 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00729 LPC_SSP0->DMACR = 0x2; 00730 break; 00731 case (1): 00732 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00733 LPC_SSP1->DMACR = 0x2; 00734 break; 00735 } 00736 // start DMA 00737 do { 00738 if (pixel > 4095) { // this is a giant font ! 00739 dma_count = 4095; 00740 pixel = pixel - 4095; 00741 } else { 00742 dma_count = pixel; 00743 pixel = 0; 00744 } 00745 LPC_GPDMA->DMACIntTCClear = 0x1; 00746 LPC_GPDMA->DMACIntErrClr = 0x1; 00747 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) (buffer + dma_off); 00748 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt 00749 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_num ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00750 LPC_GPDMA->DMACSoftSReq = 0x1; 00751 do { 00752 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00753 dma_off = dma_off + dma_count; 00754 } while (pixel > 0); 00755 00756 00757 spi_bsy(); 00758 free ((uint16_t *) buffer); 00759 spi_16(0); 00760 } 00761 00762 else { 00763 #endif 00764 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00765 w = zeichen[0]; // width of actual char 00766 for (j=0; j<vert; j++) { // vert line 00767 for (i=0; i<hor; i++) { // horz line 00768 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00769 b = 1 << (j & 0x07); 00770 if (( z & b ) == 0x00) { 00771 f_write(_background); 00772 } else { 00773 f_write(_foreground); 00774 } 00775 } 00776 } 00777 spi_bsy(); 00778 _cs = 1; 00779 spi_16(0); 00780 #ifdef use_ram 00781 } 00782 #endif 00783 _cs = 1; 00784 WindowMax(); 00785 if ((w + 2) < hor) { // x offset to next char 00786 char_x += w + 2; 00787 } else char_x += hor; 00788 } 00789 00790 00791 void SPI_TFT_ILI9341::set_font(unsigned char* f) 00792 { 00793 font = f; 00794 } 00795 00796 00797 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 00798 { 00799 unsigned int j; 00800 int padd; 00801 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 00802 00803 unsigned int i; 00804 00805 // the lines are padded to multiple of 4 bytes in a bitmap 00806 padd = -1; 00807 do { 00808 padd ++; 00809 } while (2*(w + padd)%4 != 0); 00810 window(x, y, w, h); 00811 bitmap_ptr += ((h - 1)* (w + padd)); 00812 wr_cmd(0x2C); // send pixel 00813 spi_16(1); 00814 for (j = 0; j < h; j++) { //Lines 00815 for (i = 0; i < w; i++) { // one line 00816 f_write(*bitmap_ptr); // one line 00817 bitmap_ptr++; 00818 } 00819 bitmap_ptr -= 2*w; 00820 bitmap_ptr -= padd; 00821 } 00822 spi_bsy(); 00823 _cs = 1; 00824 spi_16(0); 00825 WindowMax(); 00826 } 00827 00828 00829 // local filesystem is not implemented but you can add a SD card to a different SPI 00830 00831 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) 00832 { 00833 00834 #define OffsetPixelWidth 18 00835 #define OffsetPixelHeigh 22 00836 #define OffsetFileSize 34 00837 #define OffsetPixData 10 00838 #define OffsetBPP 28 00839 00840 char filename[50]; 00841 unsigned char BMP_Header[54]; 00842 unsigned short BPP_t; 00843 unsigned int PixelWidth,PixelHeigh,start_data; 00844 unsigned int i,off; 00845 int padd,j; 00846 unsigned short *line; 00847 00848 // get the filename 00849 i=0; 00850 while (*Name_BMP!='\0') { 00851 filename[i++]=*Name_BMP++; 00852 } 00853 filename[i] = 0; 00854 00855 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file 00856 if (!Image) { 00857 return(0); // error file not found ! 00858 } 00859 00860 fread(&BMP_Header[0],1,54,Image); // get the BMP Header 00861 00862 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 00863 fclose(Image); 00864 return(-1); // error no BMP file 00865 } 00866 00867 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 00868 if (BPP_t != 0x0010) { 00869 fclose(Image); 00870 return(-2); // error no 16 bit BMP 00871 } 00872 00873 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 00874 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 00875 if (PixelHeigh > height() + y || PixelWidth > width() + x) { 00876 fclose(Image); 00877 return(-3); // to big 00878 } 00879 00880 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 00881 00882 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line 00883 if (line == NULL) { 00884 return(-4); // error no memory 00885 } 00886 00887 // the bmp lines are padded to multiple of 4 bytes 00888 padd = -1; 00889 do { 00890 padd ++; 00891 } while ((PixelWidth * 2 + padd)%4 != 0); 00892 00893 window(x, y,PixelWidth ,PixelHeigh); 00894 wr_cmd(0x2C); // send pixel 00895 spi_16(1); 00896 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 00897 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 00898 fseek(Image, off ,SEEK_SET); 00899 fread(line,1,PixelWidth * 2,Image); // read a line - slow 00900 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 00901 f_write(line[i]); // one 16 bit pixel 00902 } 00903 } 00904 spi_bsy(); 00905 _cs = 1; 00906 spi_16(0); 00907 free (line); 00908 fclose(Image); 00909 WindowMax(); 00910 return(1); 00911 } 00912 00913 #endif 00914 00915
Generated on Wed Jul 13 2022 13:26:36 by
