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_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]; // bytes / char 00793 hor = font[1]; // get hor size of font 00794 vert = font[2]; // get vert size of font 00795 bpl = font[3]; // bytes per line 00796 00797 if (char_x + hor > width()) { 00798 char_x = 0; 00799 char_y = char_y + vert; 00800 if (char_y >= height() - font[2]) { 00801 char_y = 0; 00802 } 00803 } 00804 window(char_x, char_y,hor,vert); // setup char box 00805 wr_cmd(0x2C); 00806 spi_16(1); // switch to 16 bit Mode 00807 #ifdef use_ram 00808 pixel = hor * vert; // calculate buffer size 00809 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the font 00810 if(buffer != NULL) { // there is memory space -> use dma 00811 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00812 w = zeichen[0]; // width of actual char 00813 p = 0; 00814 // construct the font into the buffer 00815 for (j=0; j<vert; j++) { // vert line 00816 for (i=0; i<hor; i++) { // horz line 00817 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00818 b = 1 << (j & 0x07); 00819 if (( z & b ) == 0x00) { 00820 buffer[p] = _background; 00821 } else { 00822 buffer[p] = _foreground; 00823 } 00824 p++; 00825 } 00826 } 00827 // copy the buffer with DMA SPI to display 00828 dma_off = 0; // offset for DMA transfer 00829 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) (buffer + dma_off); 00830 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 00831 00832 switch(spi_num){ // decide which SPI is to use 00833 case (1): 00834 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA 00835 // start DMA 00836 do { 00837 if (pixel > 0X10000) { // this is a giant font ! 00838 dma_count = 0Xffff; 00839 pixel = pixel - 0Xffff; 00840 } else { 00841 dma_count = pixel; 00842 pixel = 0; 00843 } 00844 DMA_SetCurrDataCounter(DMA1_Channel3, dma_count); 00845 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE); 00846 DMA_Cmd(DMA1_Channel3, ENABLE); 00847 while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer 00848 DMA_Cmd(DMA1_Channel3, DISABLE); 00849 }while(pixel > 0); 00850 break; 00851 00852 case (2): 00853 DMA_Init(DMA1_Channel5, &DMA_InitStructure); // init the DMA 00854 // start DMA 00855 do { 00856 if (pixel > 0X10000) { // this is a giant font ! 00857 dma_count = 0Xffff; 00858 pixel = pixel - 0Xffff; 00859 } else { 00860 dma_count = pixel; 00861 pixel = 0; 00862 } 00863 DMA_SetCurrDataCounter(DMA1_Channel5, dma_count); 00864 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx,ENABLE); 00865 DMA_Cmd(DMA1_Channel5, ENABLE); 00866 while(DMA_GetCurrDataCounter(DMA1_Channel5) != 0); // wait for end of transfer 00867 DMA_Cmd(DMA1_Channel5, DISABLE); 00868 }while(pixel > 0); 00869 break; 00870 00871 case (3): 00872 DMA_Init(DMA2_Channel2, &DMA_InitStructure); // init the DMA 00873 // start DMA 00874 do { 00875 if (pixel > 0X10000) { // this is a giant font ! 00876 dma_count = 0Xffff; 00877 pixel = pixel - 0Xffff; 00878 } else { 00879 dma_count = pixel; 00880 pixel = 0; 00881 } 00882 DMA_SetCurrDataCounter(DMA2_Channel2, dma_count); 00883 SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx,ENABLE); 00884 DMA_Cmd(DMA2_Channel2, ENABLE); 00885 while(DMA_GetCurrDataCounter(DMA2_Channel2) != 0); // wait for end of transfer 00886 DMA_Cmd(DMA2_Channel2, DISABLE); 00887 }while(pixel > 0); 00888 break; 00889 00890 } 00891 spi_bsy(); 00892 free ((uint16_t *) buffer); 00893 spi_16(0); 00894 } 00895 00896 else{ 00897 #endif 00898 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00899 w = zeichen[0]; // width of actual char 00900 for (j=0; j<vert; j++) { // vert line 00901 for (i=0; i<hor; i++) { // horz line 00902 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00903 b = 1 << (j & 0x07); 00904 if (( z & b ) == 0x00) { 00905 f_write(_background); 00906 } else { 00907 f_write(_foreground); 00908 } 00909 } 00910 } 00911 spi_bsy(); 00912 _cs = 1; 00913 spi_16(0); 00914 #ifdef use_ram 00915 } 00916 #endif 00917 _cs = 1; 00918 WindowMax(); 00919 if ((w + 2) < hor) { // x offset to next char 00920 char_x += w + 2; 00921 } else char_x += hor; 00922 } 00923 00924 00925 void SPI_TFT_ILI9341::set_font(unsigned char* f) 00926 { 00927 font = f; 00928 } 00929 00930 00931 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 00932 { 00933 unsigned int j; 00934 int padd; 00935 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 00936 00937 unsigned int i; 00938 00939 // the lines are padded to multiple of 4 bytes in a bitmap 00940 padd = -1; 00941 do { 00942 padd ++; 00943 } while (2*(w + padd)%4 != 0); 00944 window(x, y, w, h); 00945 bitmap_ptr += ((h - 1)* (w + padd)); 00946 wr_cmd(0x2C); // send pixel 00947 spi_16(1); 00948 for (j = 0; j < h; j++) { //Lines 00949 for (i = 0; i < w; i++) { // one line 00950 f_write(*bitmap_ptr); // one line 00951 bitmap_ptr++; 00952 } 00953 bitmap_ptr -= 2*w; 00954 bitmap_ptr -= padd; 00955 } 00956 spi_bsy(); 00957 _cs = 1; 00958 spi_16(0); 00959 WindowMax(); 00960 } 00961 00962 00963 // local filesystem is not implemented but you can add a SD card to a different SPI 00964 00965 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) 00966 { 00967 00968 #define OffsetPixelWidth 18 00969 #define OffsetPixelHeigh 22 00970 #define OffsetFileSize 34 00971 #define OffsetPixData 10 00972 #define OffsetBPP 28 00973 00974 char filename[50]; 00975 unsigned char BMP_Header[54]; 00976 unsigned short BPP_t; 00977 unsigned int PixelWidth,PixelHeigh,start_data; 00978 unsigned int i,off; 00979 int padd,j; 00980 unsigned short *line; 00981 00982 // get the filename 00983 i=0; 00984 while (*Name_BMP!='\0') { 00985 filename[i++]=*Name_BMP++; 00986 } 00987 filename[i] = 0; 00988 00989 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file 00990 if (!Image) { 00991 return(0); // error file not found ! 00992 } 00993 00994 fread(&BMP_Header[0],1,54,Image); // get the BMP Header 00995 00996 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 00997 fclose(Image); 00998 return(-1); // error no BMP file 00999 } 01000 01001 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 01002 if (BPP_t != 0x0010) { 01003 fclose(Image); 01004 return(-2); // error no 16 bit BMP 01005 } 01006 01007 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 01008 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 01009 if (PixelHeigh > height() + y || PixelWidth > width() + x) { 01010 fclose(Image); 01011 return(-3); // to big 01012 } 01013 01014 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 01015 01016 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line 01017 if (line == NULL) { 01018 return(-4); // error no memory 01019 } 01020 01021 // the bmp lines are padded to multiple of 4 bytes 01022 padd = -1; 01023 do { 01024 padd ++; 01025 } while ((PixelWidth * 2 + padd)%4 != 0); 01026 01027 window(x, y,PixelWidth ,PixelHeigh); 01028 wr_cmd(0x2C); // send pixel 01029 spi_16(1); 01030 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 01031 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 01032 fseek(Image, off ,SEEK_SET); 01033 fread(line,1,PixelWidth * 2,Image); // read a line - slow 01034 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 01035 f_write(line[i]); // one 16 bit pixel 01036 } 01037 } 01038 spi_bsy(); 01039 _cs = 1; 01040 spi_16(0); 01041 free (line); 01042 fclose(Image); 01043 WindowMax(); 01044 return(1); 01045 } 01046 01047 #endif 01048 01049
Generated on Wed Jul 13 2022 13:26:36 by
