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