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_NUCLEO.cpp
00001 /* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller 00002 * Copyright (c) 2013, 2014 Peter Drescher - DC2PD 00003 * Special version for STM Nucleo -L152 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 // 24.06.14 initial version 00015 // 25.06.14 add Nucleo F103RB 00016 00017 // only include this file if target is L152 or F103RB : 00018 #if defined TARGET_NUCLEO_L152RE || defined TARGET_NUCLEO_F103RB 00019 00020 #include "SPI_TFT_ILI9341.h" 00021 #include "mbed.h" 00022 00023 #if defined TARGET_NUCLEO_L152RE 00024 #include "stm32l1xx_dma.h" 00025 #define use_ram 00026 #endif 00027 00028 #if defined TARGET_NUCLEO_F103RB 00029 #include "stm32f10x_dma.h" 00030 #endif 00031 00032 #define BPP 16 // Bits per pixel 00033 00034 //extern Serial pc; 00035 //extern DigitalOut xx; // debug !! 00036 00037 DMA_InitTypeDef DMA_InitStructure; 00038 00039 00040 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name) 00041 : GraphicsDisplay(name), SPI(mosi,miso,sclk,NC), _cs(cs), _reset(reset), _dc(dc) 00042 { 00043 00044 format(8,3); // 8 bit spi mode 3 00045 frequency(10000000); // 10 Mhz SPI clock : result 2 / 4 = 8 00046 orientation = 0; 00047 char_x = 0; 00048 if(_spi.spi == SPI_1){ // test which SPI is in use 00049 spi_num = 1; 00050 } 00051 if(_spi.spi == SPI_2){ 00052 spi_num = 2; 00053 } 00054 #ifdef SPI_3 // there is no SPI 3 on all devices 00055 if(_spi.spi == SPI_3){ 00056 spi_num = 3; 00057 } 00058 #endif 00059 tft_reset(); 00060 } 00061 00062 // we define a fast write to the SPI port 00063 // we use the bit banding address to get the flag without masking 00064 00065 #define bit_SPI1_txe *((volatile unsigned int *)0x42260104) 00066 #define SPI1_DR *((volatile unsigned int *)0x4001300C) 00067 #define bit_SPI2_txe *((volatile unsigned int *)0x42070104) 00068 #define SPI2_DR *((volatile unsigned int *)0x4000380C) 00069 #define bit_SPI3_txe *((volatile unsigned int *)0x42078104) 00070 #define SPI3_DR *((volatile unsigned int *)0x40003C0C) 00071 00072 void SPI_TFT_ILI9341::f_write(int data){ 00073 00074 switch(spi_num){ // used SPI port 00075 case (1): 00076 while(bit_SPI1_txe == 0); // wait for SPI1->SR TXE flag 00077 SPI1_DR = data; 00078 break; 00079 00080 case (2): 00081 while( bit_SPI2_txe == 0); // wait for SPI2->SR TXE flag 00082 SPI2_DR = data; 00083 break; 00084 00085 case (3): 00086 while( bit_SPI3_txe == 0); // wait for SPI3->SR TXE flag 00087 SPI3_DR = data; 00088 break; 00089 00090 } 00091 } 00092 00093 // wait for SPI not busy 00094 // we have to wait for the last bit to switch the cs off 00095 // we use the bit banding address to get the flag without masking 00096 00097 #define bit_SPI1_bsy *((volatile unsigned int *)0x4226011C) 00098 #define bit_SPI2_bsy *((volatile unsigned int *)0x4207011C) 00099 #define bit_SPI3_bsy *((volatile unsigned int *)0x4207811C) 00100 00101 void inline SPI_TFT_ILI9341::spi_bsy(void){ 00102 switch(spi_num){ // decide which SPI is to use 00103 case (1): 00104 while(bit_SPI1_bsy == 1); // SPI1->SR bit 7 00105 break; 00106 00107 case (2): 00108 while(bit_SPI2_bsy == 1); // SPI2->SR bit 7 00109 break; 00110 00111 case (3): 00112 while(bit_SPI3_bsy == 1); // SPI2->SR bit 7 00113 break; 00114 } 00115 } 00116 00117 00118 // switch fast between 8 and 16 bit mode 00119 #define bit_SPI1_dff *((volatile unsigned int *)0x4226002C) 00120 #define bit_SPI2_dff *((volatile unsigned int *)0x4207002C) 00121 #define bit_SPI3_dff *((volatile unsigned int *)0x4207802C) 00122 void SPI_TFT_ILI9341::spi_16(bool s){ 00123 switch(spi_num){ // decide which SPI is to use 00124 case(1): 00125 if(s) bit_SPI1_dff = 1; // switch to 16 bit Mode 00126 else bit_SPI1_dff = 0; // switch to 8 bit Mode 00127 break; 00128 00129 case(2): 00130 if(s) bit_SPI2_dff = 1; // switch to 16 bit Mode 00131 else bit_SPI2_dff = 0; // switch to 8 bit Mode 00132 break; 00133 00134 case(3): 00135 if(s) bit_SPI3_dff = 1; // switch to 16 bit Mode 00136 else bit_SPI3_dff = 0; // switch to 8 bit Mode 00137 break; 00138 } 00139 } 00140 00141 00142 int SPI_TFT_ILI9341::width() 00143 { 00144 if (orientation == 0 || orientation == 2) return 240; 00145 else return 320; 00146 } 00147 00148 00149 int SPI_TFT_ILI9341::height() 00150 { 00151 if (orientation == 0 || orientation == 2) return 320; 00152 else return 240; 00153 } 00154 00155 00156 void SPI_TFT_ILI9341::set_orientation(unsigned int o) 00157 { 00158 orientation = o; 00159 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL 00160 switch (orientation) { 00161 case 0: 00162 f_write(0x48); 00163 break; 00164 case 1: 00165 f_write(0x28); 00166 break; 00167 case 2: 00168 f_write(0x88); 00169 break; 00170 case 3: 00171 f_write(0xE8); 00172 break; 00173 } 00174 spi_bsy(); // wait for end of transfer 00175 _cs = 1; 00176 WindowMax(); 00177 } 00178 00179 00180 // write command to tft register 00181 // use fast command 00182 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd) 00183 { 00184 _dc = 0; 00185 _cs = 0; 00186 f_write(cmd); 00187 spi_bsy(); 00188 _dc = 1; 00189 } 00190 00191 void SPI_TFT_ILI9341::wr_dat(unsigned char dat) 00192 { 00193 f_write(dat); 00194 spi_bsy(); // wait for SPI send 00195 } 00196 00197 // the ILI9341 can read 00198 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd) 00199 { 00200 // has to change !! 00201 return(0); 00202 } 00203 00204 // read 32 bit 00205 int SPI_TFT_ILI9341::rd_32(unsigned char cmd) 00206 { 00207 // has to change !!! 00208 return(0); 00209 } 00210 00211 int SPI_TFT_ILI9341::Read_ID(void){ 00212 int r; 00213 r = rd_byte(0x0A); 00214 r = rd_byte(0x0A); 00215 r = rd_byte(0x0A); 00216 r = rd_byte(0x0A); 00217 return(r); 00218 } 00219 00220 00221 // Init code based on MI0283QT datasheet 00222 // this code is called only at start 00223 // no need to be optimized 00224 00225 void SPI_TFT_ILI9341::tft_reset() 00226 { 00227 _cs = 1; // cs high 00228 _dc = 1; // dc high 00229 _reset = 0; // display reset 00230 00231 wait_us(50); 00232 _reset = 1; // end hardware reset 00233 wait_ms(5); 00234 00235 wr_cmd(0x01); // SW reset 00236 wait_ms(5); 00237 wr_cmd(0x28); // display off 00238 00239 /* Start Initial Sequence ----------------------------------------------------*/ 00240 wr_cmd(0xCF); 00241 f_write(0x00); 00242 f_write(0x83); 00243 f_write(0x30); 00244 spi_bsy(); 00245 _cs = 1; 00246 00247 wr_cmd(0xED); 00248 f_write(0x64); 00249 f_write(0x03); 00250 f_write(0x12); 00251 f_write(0x81); 00252 spi_bsy(); 00253 _cs = 1; 00254 00255 wr_cmd(0xE8); 00256 f_write(0x85); 00257 f_write(0x01); 00258 f_write(0x79); 00259 spi_bsy(); 00260 _cs = 1; 00261 00262 wr_cmd(0xCB); 00263 f_write(0x39); 00264 f_write(0x2C); 00265 f_write(0x00); 00266 f_write(0x34); 00267 f_write(0x02); 00268 spi_bsy(); 00269 _cs = 1; 00270 00271 wr_cmd(0xF7); 00272 f_write(0x20); 00273 spi_bsy(); 00274 _cs = 1; 00275 00276 wr_cmd(0xEA); 00277 f_write(0x00); 00278 f_write(0x00); 00279 spi_bsy(); 00280 _cs = 1; 00281 00282 wr_cmd(0xC0); // POWER_CONTROL_1 00283 f_write(0x26); 00284 spi_bsy(); 00285 _cs = 1; 00286 00287 wr_cmd(0xC1); // POWER_CONTROL_2 00288 f_write(0x11); 00289 spi_bsy(); 00290 _cs = 1; 00291 00292 wr_cmd(0xC5); // VCOM_CONTROL_1 00293 f_write(0x35); 00294 f_write(0x3E); 00295 spi_bsy(); 00296 _cs = 1; 00297 00298 wr_cmd(0xC7); // VCOM_CONTROL_2 00299 f_write(0xBE); 00300 spi_bsy(); 00301 _cs = 1; 00302 00303 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL 00304 f_write(0x48); 00305 spi_bsy(); 00306 _cs = 1; 00307 00308 wr_cmd(0x3A); // COLMOD_PIXEL_FORMAT_SET 00309 f_write(0x55); // 16 bit pixel 00310 spi_bsy(); 00311 _cs = 1; 00312 00313 wr_cmd(0xB1); // Frame Rate 00314 f_write(0x00); 00315 f_write(0x1B); 00316 spi_bsy(); 00317 _cs = 1; 00318 00319 wr_cmd(0xF2); // Gamma Function Disable 00320 f_write(0x08); 00321 spi_bsy(); 00322 _cs = 1; 00323 00324 wr_cmd(0x26); 00325 f_write(0x01); // gamma set for curve 01/2/04/08 00326 spi_bsy(); 00327 _cs = 1; 00328 00329 wr_cmd(0xE0); // positive gamma correction 00330 f_write(0x1F); 00331 f_write(0x1A); 00332 f_write(0x18); 00333 f_write(0x0A); 00334 f_write(0x0F); 00335 f_write(0x06); 00336 f_write(0x45); 00337 f_write(0x87); 00338 f_write(0x32); 00339 f_write(0x0A); 00340 f_write(0x07); 00341 f_write(0x02); 00342 f_write(0x07); 00343 f_write(0x05); 00344 f_write(0x00); 00345 spi_bsy(); 00346 _cs = 1; 00347 00348 wr_cmd(0xE1); // negativ gamma correction 00349 f_write(0x00); 00350 f_write(0x25); 00351 f_write(0x27); 00352 f_write(0x05); 00353 f_write(0x10); 00354 f_write(0x09); 00355 f_write(0x3A); 00356 f_write(0x78); 00357 f_write(0x4D); 00358 f_write(0x05); 00359 f_write(0x18); 00360 f_write(0x0D); 00361 f_write(0x38); 00362 f_write(0x3A); 00363 f_write(0x1F); 00364 spi_bsy(); 00365 _cs = 1; 00366 00367 WindowMax (); 00368 00369 //wr_cmd(0x34); // tearing effect off 00370 //_cs = 1; 00371 00372 //wr_cmd(0x35); // tearing effect on 00373 //_cs = 1; 00374 00375 wr_cmd(0xB7); // entry mode 00376 f_write(0x07); 00377 spi_bsy(); 00378 _cs = 1; 00379 00380 wr_cmd(0xB6); // display function control 00381 f_write(0x0A); 00382 f_write(0x82); 00383 f_write(0x27); 00384 f_write(0x00); 00385 spi_bsy(); 00386 _cs = 1; 00387 00388 wr_cmd(0x11); // sleep out 00389 spi_bsy(); 00390 _cs = 1; 00391 00392 wait_ms(100); 00393 00394 wr_cmd(0x29); // display on 00395 spi_bsy(); 00396 _cs = 1; 00397 00398 wait_ms(100); 00399 00400 // Configure the DMA controller init-structure 00401 DMA_StructInit(&DMA_InitStructure); 00402 switch(spi_num){ // decide which SPI is to use 00403 case (1): 00404 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // SPI1 and SPI2 are using DMA 1 00405 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1->DR); 00406 break; 00407 case (2): 00408 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // SPI1 and SPI2 are using DMA 1 00409 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI2->DR); 00410 break; 00411 case (3): 00412 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE); // SPI3 is using DMA 2 00413 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI3->DR); 00414 break; 00415 } 00416 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; 00417 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 00418 DMA_InitStructure.DMA_BufferSize = 0; 00419 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 00420 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 00421 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 00422 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; 00423 DMA_InitStructure.DMA_Priority = DMA_Priority_High; 00424 } 00425 00426 00427 // speed optimized 00428 // write direct to SPI1 register ! 00429 void SPI_TFT_ILI9341::pixel(int x, int y, int color) 00430 { 00431 wr_cmd(0x2A); 00432 spi_16(1); // switch to 8 bit Mode 00433 f_write(x); 00434 spi_bsy(); 00435 _cs = 1; 00436 00437 spi_16(0); // switch to 8 bit Mode 00438 wr_cmd(0x2B); 00439 spi_16(1); 00440 f_write(y); 00441 spi_bsy(); 00442 _cs = 1; 00443 spi_16(0); 00444 00445 wr_cmd(0x2C); // send pixel 00446 spi_16(1); 00447 f_write(color); 00448 spi_bsy(); 00449 _cs = 1; 00450 spi_16(0); 00451 } 00452 00453 // optimized 00454 // write direct to SPI1 register ! 00455 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) 00456 { 00457 wr_cmd(0x2A); 00458 spi_16(1); 00459 f_write(x); 00460 f_write(x+w-1); 00461 spi_bsy(); 00462 _cs = 1; 00463 spi_16(0); 00464 00465 wr_cmd(0x2B); 00466 spi_16(1); 00467 f_write(y) ; 00468 f_write(y+h-1); 00469 spi_bsy(); 00470 _cs = 1; 00471 spi_16(0); 00472 } 00473 00474 00475 void SPI_TFT_ILI9341::WindowMax (void) 00476 { 00477 window (0, 0, width(), height()); 00478 } 00479 00480 // optimized 00481 // use DMA to transfer pixel data to the screen 00482 void SPI_TFT_ILI9341::cls (void) 00483 { 00484 // we can use the fillrect function 00485 fillrect(0,0,width()-1,height()-1,_background); 00486 } 00487 00488 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color) 00489 { 00490 00491 int x = -r, y = 0, err = 2-2*r, e2; 00492 do { 00493 pixel(x0-x, y0+y,color); 00494 pixel(x0+x, y0+y,color); 00495 pixel(x0+x, y0-y,color); 00496 pixel(x0-x, y0-y,color); 00497 e2 = err; 00498 if (e2 <= y) { 00499 err += ++y*2+1; 00500 if (-x == y && e2 <= x) e2 = 0; 00501 } 00502 if (e2 > x) err += ++x*2+1; 00503 } while (x <= 0); 00504 } 00505 00506 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color) 00507 { 00508 int x = -r, y = 0, err = 2-2*r, e2; 00509 do { 00510 vline(x0-x, y0-y, y0+y, color); 00511 vline(x0+x, y0-y, y0+y, color); 00512 e2 = err; 00513 if (e2 <= y) { 00514 err += ++y*2+1; 00515 if (-x == y && e2 <= x) e2 = 0; 00516 } 00517 if (e2 > x) err += ++x*2+1; 00518 } while (x <= 0); 00519 } 00520 00521 00522 // optimized for speed 00523 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color) 00524 { 00525 int w,j; 00526 w = x1 - x0 + 1; 00527 window(x0,y,w,1); 00528 _dc = 0; 00529 _cs = 0; 00530 f_write(0x2C); // send pixel 00531 spi_bsy(); 00532 _dc = 1; 00533 spi_16(1); 00534 00535 for (j=0; j<w; j++) { 00536 f_write(color); 00537 } 00538 spi_bsy(); 00539 spi_16(0); 00540 _cs = 1; 00541 WindowMax(); 00542 return; 00543 } 00544 00545 // optimized for speed 00546 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color) 00547 { 00548 int h,y; 00549 h = y1 - y0 + 1; 00550 window(x,y0,1,h); 00551 _dc = 0; 00552 _cs = 0; 00553 f_write(0x2C); // send pixel 00554 spi_bsy(); 00555 _dc = 1; 00556 spi_16(1); 00557 // switch to 16 bit Mode 3 00558 for (y=0; y<h; y++) { 00559 f_write(color); 00560 } 00561 spi_bsy(); 00562 spi_16(0); 00563 _cs = 1; 00564 WindowMax(); 00565 return; 00566 } 00567 00568 00569 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color) 00570 { 00571 //WindowMax(); 00572 int dx = 0, dy = 0; 00573 int dx_sym = 0, dy_sym = 0; 00574 int dx_x2 = 0, dy_x2 = 0; 00575 int di = 0; 00576 00577 dx = x1-x0; 00578 dy = y1-y0; 00579 00580 if (dx == 0) { /* vertical line */ 00581 if (y1 > y0) vline(x0,y0,y1,color); 00582 else vline(x0,y1,y0,color); 00583 return; 00584 } 00585 00586 if (dx > 0) { 00587 dx_sym = 1; 00588 } else { 00589 dx_sym = -1; 00590 } 00591 if (dy == 0) { /* horizontal line */ 00592 if (x1 > x0) hline(x0,x1,y0,color); 00593 else hline(x1,x0,y0,color); 00594 return; 00595 } 00596 00597 if (dy > 0) { 00598 dy_sym = 1; 00599 } else { 00600 dy_sym = -1; 00601 } 00602 00603 dx = dx_sym*dx; 00604 dy = dy_sym*dy; 00605 00606 dx_x2 = dx*2; 00607 dy_x2 = dy*2; 00608 00609 if (dx >= dy) { 00610 di = dy_x2 - dx; 00611 while (x0 != x1) { 00612 00613 pixel(x0, y0, color); 00614 x0 += dx_sym; 00615 if (di<0) { 00616 di += dy_x2; 00617 } else { 00618 di += dy_x2 - dx_x2; 00619 y0 += dy_sym; 00620 } 00621 } 00622 pixel(x0, y0, color); 00623 } else { 00624 di = dx_x2 - dy; 00625 while (y0 != y1) { 00626 pixel(x0, y0, color); 00627 y0 += dy_sym; 00628 if (di < 0) { 00629 di += dx_x2; 00630 } else { 00631 di += dx_x2 - dy_x2; 00632 x0 += dx_sym; 00633 } 00634 } 00635 pixel(x0, y0, color); 00636 } 00637 return; 00638 } 00639 00640 00641 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color) 00642 { 00643 00644 if (x1 > x0) hline(x0,x1,y0,color); 00645 else hline(x1,x0,y0,color); 00646 00647 if (y1 > y0) vline(x0,y0,y1,color); 00648 else vline(x0,y1,y0,color); 00649 00650 if (x1 > x0) hline(x0,x1,y1,color); 00651 else hline(x1,x0,y1,color); 00652 00653 if (y1 > y0) vline(x1,y0,y1,color); 00654 else vline(x1,y1,y0,color); 00655 00656 return; 00657 } 00658 00659 00660 00661 // optimized for speed 00662 // use DMA 00663 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color) 00664 { 00665 00666 int h = y1 - y0 + 1; 00667 int w = x1 - x0 + 1; 00668 int pixel = h * w; 00669 unsigned int dma_transfer; 00670 window(x0,y0,w,h); 00671 00672 wr_cmd(0x2C); // send pixel 00673 spi_16(1); 00674 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &color; 00675 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; 00676 00677 switch(spi_num){ // decide which SPI is to use 00678 case (1): 00679 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA 00680 do{ 00681 if(pixel < 0x10000) { 00682 dma_transfer = pixel; 00683 pixel = 0; 00684 } 00685 else { 00686 dma_transfer = 0xffff; 00687 pixel = pixel - 0xffff; 00688 } 00689 DMA_SetCurrDataCounter(DMA1_Channel3, dma_transfer); 00690 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE); 00691 DMA_Cmd(DMA1_Channel3, ENABLE); 00692 while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer 00693 DMA_Cmd(DMA1_Channel3, DISABLE); 00694 }while(pixel > 0); 00695 break; 00696 00697 case (2): 00698 DMA_Init(DMA1_Channel5, &DMA_InitStructure); // init the DMA 00699 do{ 00700 if(pixel < 0x10000) { 00701 dma_transfer = pixel; 00702 pixel = 0; 00703 } 00704 else { 00705 dma_transfer = 0xffff; 00706 pixel = pixel - 0xffff; 00707 } 00708 DMA_SetCurrDataCounter(DMA1_Channel5, dma_transfer); 00709 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx,ENABLE); 00710 DMA_Cmd(DMA1_Channel5, ENABLE); 00711 while(DMA_GetCurrDataCounter(DMA1_Channel5) != 0); // wait for end of transfer 00712 DMA_Cmd(DMA1_Channel5, DISABLE); 00713 }while(pixel > 0); 00714 break; 00715 00716 case (3): 00717 DMA_Init(DMA2_Channel2, &DMA_InitStructure); // init the DMA 00718 do{ 00719 if(pixel < 0x10000) { 00720 dma_transfer = pixel; 00721 pixel = 0; 00722 } 00723 else { 00724 dma_transfer = 0xffff; 00725 pixel = pixel - 0xffff; 00726 } 00727 DMA_SetCurrDataCounter(DMA2_Channel2, dma_transfer); 00728 SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx,ENABLE); 00729 DMA_Cmd(DMA2_Channel2, ENABLE); 00730 while(DMA_GetCurrDataCounter(DMA2_Channel2) != 0); // wait for end of transfer 00731 DMA_Cmd(DMA2_Channel2, DISABLE); 00732 }while(pixel > 0); 00733 break; 00734 } 00735 spi_bsy(); 00736 spi_16(0); 00737 _cs = 1; 00738 WindowMax(); 00739 return; 00740 } 00741 00742 void SPI_TFT_ILI9341::locate(int x, int y) 00743 { 00744 char_x = x; 00745 char_y = y; 00746 } 00747 00748 int SPI_TFT_ILI9341::columns() 00749 { 00750 return width() / font[1]; 00751 } 00752 00753 00754 int SPI_TFT_ILI9341::rows() 00755 { 00756 return height() / font[2]; 00757 } 00758 00759 00760 int SPI_TFT_ILI9341::_putc(int value) 00761 { 00762 if (value == '\n') { // new line 00763 char_x = 0; 00764 char_y = char_y + font[2]; 00765 if (char_y >= height() - font[2]) { 00766 char_y = 0; 00767 } 00768 } else { 00769 character(char_x, char_y, value); 00770 } 00771 return value; 00772 } 00773 00774 00775 // speed optimized 00776 // will use dma 00777 void SPI_TFT_ILI9341::character(int x, int y, int c) 00778 { 00779 unsigned int hor,vert,offset,bpl,j,i,b; 00780 unsigned char* zeichen; 00781 unsigned char z,w; 00782 #ifdef use_ram 00783 unsigned int pixel; 00784 unsigned int p; 00785 unsigned int dma_count,dma_off; 00786 uint16_t *buffer; 00787 #endif 00788 00789 if ((c < 31) || (c > 127)) return; // test char range 00790 00791 // read font parameter from start of array 00792 offset = font[0]<<8+font[1]; // bytes / char 00793 hor = font[2]; // get hor size of font 00794 vert = font[3]; // get vert size of font 00795 bpl = font[4]; // bytes per line 00796 00797 zeichen = &font[((c -32) * offset) + 5]; // start of char bitmap 00798 w = zeichen[0]; // width of actual char 00799 00800 if (char_x + (w+2) > width()) { 00801 char_x = 0; 00802 char_y = char_y + vert; 00803 if (char_y >= height() - vert) { 00804 char_y = 0; 00805 } 00806 } 00807 window(char_x, char_y,(w+2),vert); // setup char box 00808 wr_cmd(0x2C); 00809 spi_16(1); // switch to 16 bit Mode 00810 #ifdef use_ram 00811 pixel = (w+2) * vert; // calculate buffer size 00812 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the font 00813 if(buffer != NULL) { // there is memory space -> use dma 00814 p = 0; 00815 // construct the font into the buffer 00816 for (j=0; j<vert; j++) { // vert line 00817 for (i=0; i<(w+2); i++) { // horz line 00818 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00819 b = 1 << (j & 0x07); 00820 if (( z & b ) == 0x00) { 00821 buffer[p] = _background; 00822 } else { 00823 buffer[p] = _foreground; 00824 } 00825 p++; 00826 } 00827 } 00828 // copy the buffer with DMA SPI to display 00829 dma_off = 0; // offset for DMA transfer 00830 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) (buffer + dma_off); 00831 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 00832 00833 switch(spi_num){ // decide which SPI is to use 00834 case (1): 00835 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA 00836 // start DMA 00837 do { 00838 if (pixel > 0X10000) { // this is a giant font ! 00839 dma_count = 0Xffff; 00840 pixel = pixel - 0Xffff; 00841 } else { 00842 dma_count = pixel; 00843 pixel = 0; 00844 } 00845 DMA_SetCurrDataCounter(DMA1_Channel3, dma_count); 00846 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE); 00847 DMA_Cmd(DMA1_Channel3, ENABLE); 00848 while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer 00849 DMA_Cmd(DMA1_Channel3, DISABLE); 00850 }while(pixel > 0); 00851 break; 00852 00853 case (2): 00854 DMA_Init(DMA1_Channel5, &DMA_InitStructure); // init the DMA 00855 // start DMA 00856 do { 00857 if (pixel > 0X10000) { // this is a giant font ! 00858 dma_count = 0Xffff; 00859 pixel = pixel - 0Xffff; 00860 } else { 00861 dma_count = pixel; 00862 pixel = 0; 00863 } 00864 DMA_SetCurrDataCounter(DMA1_Channel5, dma_count); 00865 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx,ENABLE); 00866 DMA_Cmd(DMA1_Channel5, ENABLE); 00867 while(DMA_GetCurrDataCounter(DMA1_Channel5) != 0); // wait for end of transfer 00868 DMA_Cmd(DMA1_Channel5, DISABLE); 00869 }while(pixel > 0); 00870 break; 00871 00872 case (3): 00873 DMA_Init(DMA2_Channel2, &DMA_InitStructure); // init the DMA 00874 // start DMA 00875 do { 00876 if (pixel > 0X10000) { // this is a giant font ! 00877 dma_count = 0Xffff; 00878 pixel = pixel - 0Xffff; 00879 } else { 00880 dma_count = pixel; 00881 pixel = 0; 00882 } 00883 DMA_SetCurrDataCounter(DMA2_Channel2, dma_count); 00884 SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx,ENABLE); 00885 DMA_Cmd(DMA2_Channel2, ENABLE); 00886 while(DMA_GetCurrDataCounter(DMA2_Channel2) != 0); // wait for end of transfer 00887 DMA_Cmd(DMA2_Channel2, DISABLE); 00888 }while(pixel > 0); 00889 break; 00890 00891 } 00892 spi_bsy(); 00893 free ((uint16_t *) buffer); 00894 spi_16(0); 00895 } 00896 00897 else{ 00898 #endif 00899 for (j=0; j<vert; j++) { // vert line 00900 for (i=0; i<(w+2); i++) { // horz line 00901 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00902 b = 1 << (j & 0x07); 00903 if (( z & b ) == 0x00) { 00904 f_write(_background); 00905 } else { 00906 f_write(_foreground); 00907 } 00908 } 00909 } 00910 spi_bsy(); 00911 _cs = 1; 00912 spi_16(0); 00913 #ifdef use_ram 00914 } 00915 #endif 00916 _cs = 1; 00917 WindowMax(); 00918 if ((w + 2) < hor) { // x offset to next char 00919 char_x += w + 2; 00920 } else char_x += hor; 00921 } 00922 00923 00924 void SPI_TFT_ILI9341::set_font(unsigned char* f) 00925 { 00926 font = f; 00927 } 00928 00929 00930 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 00931 { 00932 unsigned int j; 00933 int padd; 00934 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 00935 00936 unsigned int i; 00937 00938 // the lines are padded to multiple of 4 bytes in a bitmap 00939 padd = -1; 00940 do { 00941 padd ++; 00942 } while (2*(w + padd)%4 != 0); 00943 window(x, y, w, h); 00944 bitmap_ptr += ((h - 1)* (w + padd)); 00945 wr_cmd(0x2C); // send pixel 00946 spi_16(1); 00947 for (j = 0; j < h; j++) { //Lines 00948 for (i = 0; i < w; i++) { // one line 00949 f_write(*bitmap_ptr); // one line 00950 bitmap_ptr++; 00951 } 00952 bitmap_ptr -= 2*w; 00953 bitmap_ptr -= padd; 00954 } 00955 spi_bsy(); 00956 _cs = 1; 00957 spi_16(0); 00958 WindowMax(); 00959 } 00960 00961 00962 // local filesystem is not implemented but you can add a SD card to a different SPI 00963 00964 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) 00965 { 00966 00967 #define OffsetPixelWidth 18 00968 #define OffsetPixelHeigh 22 00969 #define OffsetFileSize 34 00970 #define OffsetPixData 10 00971 #define OffsetBPP 28 00972 00973 char filename[50]; 00974 unsigned char BMP_Header[54]; 00975 unsigned short BPP_t; 00976 unsigned int PixelWidth,PixelHeigh,start_data; 00977 unsigned int i,off; 00978 int padd,j; 00979 unsigned short *line; 00980 00981 // get the filename 00982 i=0; 00983 while (*Name_BMP!='\0') { 00984 filename[i++]=*Name_BMP++; 00985 } 00986 filename[i] = 0; 00987 00988 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file 00989 if (!Image) { 00990 return(0); // error file not found ! 00991 } 00992 00993 fread(&BMP_Header[0],1,54,Image); // get the BMP Header 00994 00995 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 00996 fclose(Image); 00997 return(-1); // error no BMP file 00998 } 00999 01000 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 01001 if (BPP_t != 0x0010) { 01002 fclose(Image); 01003 return(-2); // error no 16 bit BMP 01004 } 01005 01006 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 01007 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 01008 if (PixelHeigh > height() + y || PixelWidth > width() + x) { 01009 fclose(Image); 01010 return(-3); // to big 01011 } 01012 01013 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 01014 01015 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line 01016 if (line == NULL) { 01017 return(-4); // error no memory 01018 } 01019 01020 // the bmp lines are padded to multiple of 4 bytes 01021 padd = -1; 01022 do { 01023 padd ++; 01024 } while ((PixelWidth * 2 + padd)%4 != 0); 01025 01026 window(x, y,PixelWidth ,PixelHeigh); 01027 wr_cmd(0x2C); // send pixel 01028 spi_16(1); 01029 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 01030 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 01031 fseek(Image, off ,SEEK_SET); 01032 fread(line,1,PixelWidth * 2,Image); // read a line - slow 01033 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 01034 f_write(line[i]); // one 16 bit pixel 01035 } 01036 } 01037 spi_bsy(); 01038 _cs = 1; 01039 spi_16(0); 01040 free (line); 01041 fclose(Image); 01042 WindowMax(); 01043 return(1); 01044 } 01045 01046 #endif 01047
Generated on Wed Jul 13 2022 12:41:39 by 1.7.2