Library to control a QVGA TFT connected to SPI. You can use printf to print text The lib can handle different fonts, draw lines, circles, rect and bmp
Dependents: TFT_Test1 SourceCodePro31-SB Mandelbrot Mindwave-screen ... more
SPI_TFT.cpp
00001 /* mbed library for 240*320 pixel display TFT based on HX8347D LCD Controller 00002 * Copyright (c) 2011 Peter Drescher - DC2PD 00003 * 00004 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00005 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00006 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00007 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00008 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00009 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00010 * THE SOFTWARE. 00011 */ 00012 00013 00014 // fix bmp padding for Bitmap function 00015 // speed up pixel 00016 // 30.12.11 fix cls 00017 // 11.03.12 use DMA to speed up 00018 // 15.03.12 use SSEL for TFT CS to enable DMA Register writes 00019 // 06.04.12 fix SSEL CS problem 00020 // 06.04.12 use direct access to the spi register to speed up the library. 00021 // 11.09.12 switch back to using io pin as cs to avoid problems with SSEL CS. 00022 // 21.09.12 fix Bug in BMP_16 00023 // 11.10.12 patch from Hans Bergles to get SPI1 working again 00024 // 03.02.13 add a switch to switch off DMA use for LPC11U24 00025 // 04.03.13 add support for new Kinetis board 00026 // 25.03.13 fix Bug in bitmap for Kinetis board 00027 // 18.10.13 Better Circle function from Michael Ammann 00028 00029 #include "SPI_TFT.h" 00030 #include "mbed.h" 00031 00032 #define BPP 16 // Bits per pixel 00033 00034 #if defined TARGET_LPC1768 00035 #define USE_DMA // we use dma to speed up 00036 #define NO_MBED_LIB // we write direct to the SPI register to speed up 00037 #endif 00038 00039 #if defined NO_DMA // if LPC1768 user want no DMA 00040 #undef USE_DMA 00041 #endif 00042 00043 00044 //extern Serial pc; 00045 //extern DigitalOut xx; // debug !! 00046 00047 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name) 00048 : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name) 00049 { 00050 orientation = 0; 00051 char_x = 0; 00052 #if defined TARGET_LPC1768 00053 if (mosi == p11 || mosi == P0_18){ 00054 spi_port = 0; // we must know the used SPI port to setup the DMA 00055 } 00056 else { 00057 spi_port = 1; 00058 } 00059 #endif 00060 tft_reset(); 00061 } 00062 00063 int SPI_TFT::width() 00064 { 00065 if (orientation == 0 || orientation == 2) return 240; 00066 else return 320; 00067 } 00068 00069 00070 int SPI_TFT::height() 00071 { 00072 if (orientation == 0 || orientation == 2) return 320; 00073 else return 240; 00074 } 00075 00076 00077 void SPI_TFT::set_orientation(unsigned int o) 00078 { 00079 orientation = o; 00080 switch (orientation) { 00081 case 0: 00082 wr_reg(0x16, 0x08); 00083 break; 00084 case 1: 00085 wr_reg(0x16, 0x68); 00086 break; 00087 case 2: 00088 wr_reg(0x16, 0xC8); 00089 break; 00090 case 3: 00091 wr_reg(0x16, 0xA8); 00092 break; 00093 } 00094 WindowMax(); 00095 } 00096 00097 00098 // write command to tft register 00099 00100 void SPI_TFT::wr_cmd(unsigned char cmd) 00101 { 00102 _cs = 0; 00103 #if defined NO_MBED_LIB 00104 unsigned short spi_d; 00105 spi_d = 0x7000 | cmd ; 00106 if (spi_port == 0) { // TFT on SSP0 00107 LPC_SSP0->DR = spi_d; 00108 // we have to wait for SPI IDLE to set CS back to high 00109 do { 00110 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle 00111 } else { 00112 LPC_SSP1->DR = spi_d; 00113 do { 00114 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle 00115 } 00116 #else // use mbed lib 00117 #if defined TARGET_KL25Z // 8 Bit SPI 00118 _spi.write(0x70); 00119 _spi.write(cmd); 00120 #else // 16 Bit SPI 00121 unsigned short spi_d; 00122 spi_d = 0x7000 | cmd ; 00123 _spi.write(spi_d); // mbed lib 00124 #endif 00125 #endif 00126 _cs = 1; 00127 } 00128 00129 00130 // write data to tft register 00131 void SPI_TFT::wr_dat(unsigned char dat) 00132 { 00133 _cs = 0; 00134 #if defined NO_MBED_LIB 00135 unsigned short spi_d; 00136 spi_d = 0x7200 | dat; 00137 if (spi_port == 0) { // TFT on SSP0 00138 LPC_SSP0->DR = spi_d; 00139 // we have to wait for SPI IDLE to set CS back to high 00140 do { 00141 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle 00142 } else { 00143 LPC_SSP1->DR = spi_d; 00144 do { 00145 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle 00146 } 00147 #else // use mbed lib 00148 #if defined TARGET_KL25Z // 8 Bit SPI 00149 _spi.write(0x72); 00150 _spi.write(dat); 00151 #else // 16 Bit SPI 00152 unsigned short spi_d; 00153 spi_d = 0x7200 | dat; 00154 _spi.write(spi_d); 00155 #endif 00156 #endif 00157 _cs = 1; 00158 } 00159 00160 00161 00162 // the HX8347-D controller do not use the MISO (SDO) Signal. 00163 // This is a bug - ? 00164 // A read will return 0 at the moment 00165 00166 unsigned short SPI_TFT::rd_dat (void) 00167 { 00168 unsigned short val = 0; 00169 00170 //val = _spi.write(0x73ff); /* Dummy read 1 */ 00171 //val = _spi.write(0x0000); /* Read D8..D15 */ 00172 return (val); 00173 } 00174 00175 // write to a TFT register 00176 void SPI_TFT::wr_reg (unsigned char reg, unsigned char val) 00177 { 00178 wr_cmd(reg); 00179 wr_dat(val); 00180 } 00181 00182 // read from a TFT register 00183 unsigned short SPI_TFT::rd_reg (unsigned char reg) 00184 { 00185 wr_cmd(reg); 00186 return(rd_dat()); 00187 } 00188 00189 // setup TFT controller - this is called by constructor 00190 void SPI_TFT::tft_reset() 00191 { 00192 #if defined TARGET_KL25Z // 8 Bit SPI 00193 _spi.format(8,3); 00194 #else // 16 Bit SPI 00195 _spi.format(16,3); // 16 bit spi mode 3 00196 #endif 00197 _spi.frequency(48000000); // 48 Mhz SPI clock 00198 _cs = 1; // cs high 00199 _reset = 0; // display reset 00200 00201 wait_us(50); 00202 _reset = 1; // end reset 00203 wait_ms(5); 00204 00205 /* Start Initial Sequence ----------------------------------------------------*/ 00206 wr_reg(0xEA, 0x00); /* Reset Power Control 1 */ 00207 wr_reg(0xEB, 0x20); /* Power Control 2 */ 00208 wr_reg(0xEC, 0x0C); /* Power Control 3 */ 00209 wr_reg(0xED, 0xC4); /* Power Control 4 */ 00210 wr_reg(0xE8, 0x40); /* Source OPON_N */ 00211 wr_reg(0xE9, 0x38); /* Source OPON_I */ 00212 wr_reg(0xF1, 0x01); /* */ 00213 wr_reg(0xF2, 0x10); /* */ 00214 wr_reg(0x27, 0xA3); /* Display Control 2 */ 00215 00216 /* Power On sequence ---------------------------------------------------------*/ 00217 wr_reg(0x1B, 0x1B); /* Power Control 2 */ 00218 wr_reg(0x1A, 0x01); /* Power Control 1 */ 00219 wr_reg(0x24, 0x2F); /* Vcom Control 2 */ 00220 wr_reg(0x25, 0x57); /* Vcom Control 3 */ 00221 wr_reg(0x23, 0x8D); /* Vcom Control 1 */ 00222 00223 /* Gamma settings -----------------------------------------------------------*/ 00224 wr_reg(0x40,0x00); // default setup 00225 wr_reg(0x41,0x00); // 00226 wr_reg(0x42,0x01); // 00227 wr_reg(0x43,0x13); // 00228 wr_reg(0x44,0x10); // 00229 wr_reg(0x45,0x26); // 00230 wr_reg(0x46,0x08); // 00231 wr_reg(0x47,0x51); // 00232 wr_reg(0x48,0x02); // 00233 wr_reg(0x49,0x12); // 00234 wr_reg(0x4A,0x18); // 00235 wr_reg(0x4B,0x19); // 00236 wr_reg(0x4C,0x14); // 00237 wr_reg(0x50,0x19); // 00238 wr_reg(0x51,0x2F); // 00239 wr_reg(0x52,0x2C); // 00240 wr_reg(0x53,0x3E); // 00241 wr_reg(0x54,0x3F); // 00242 wr_reg(0x55,0x3F); // 00243 wr_reg(0x56,0x2E); // 00244 wr_reg(0x57,0x77); // 00245 wr_reg(0x58,0x0B); // 00246 wr_reg(0x59,0x06); // 00247 wr_reg(0x5A,0x07); // 00248 wr_reg(0x5B,0x0D); // 00249 wr_reg(0x5C,0x1D); // 00250 wr_reg(0x5D,0xCC); // 00251 00252 /* Power + Osc ---------------------------------------------------------------*/ 00253 wr_reg(0x18, 0x36); /* OSC Control 1 */ 00254 wr_reg(0x19, 0x01); /* OSC Control 2 */ 00255 wr_reg(0x01, 0x00); /* Display Mode Control */ 00256 wr_reg(0x1F, 0x88); /* Power Control 6 */ 00257 wait_ms(5); /* Delay 5 ms */ 00258 wr_reg(0x1F, 0x80); /* Power Control 6 */ 00259 wait_ms(5); /* Delay 5 ms */ 00260 wr_reg(0x1F, 0x90); /* Power Control 6 */ 00261 wait_ms(5); /* Delay 5 ms */ 00262 wr_reg(0x1F, 0xD0); /* Power Control 6 */ 00263 wait_ms(5); /* Delay 5 ms */ 00264 00265 wr_reg(0x17, 0x05); /* Colmod 16Bit/Pixel */ 00266 00267 wr_reg(0x36, 0x00); /* Panel Characteristic */ 00268 wr_reg(0x28, 0x38); /* Display Control 3 */ 00269 wait_ms(40); 00270 wr_reg(0x28, 0x3C); /* Display Control 3 */ 00271 switch (orientation) { 00272 case 0: 00273 wr_reg(0x16, 0x08); 00274 break; 00275 case 2: 00276 wr_reg(0x16, 0xC8); 00277 break; 00278 case 3: 00279 wr_reg(0x16, 0xA8); 00280 break; 00281 case 1: 00282 default: 00283 wr_reg(0x16, 0x68); 00284 break; 00285 00286 } 00287 #if defined USE_DMA // setup DMA channel 0 00288 LPC_SC->PCONP |= (1UL << 29); // Power up the GPDMA. 00289 LPC_GPDMA->DMACConfig = 1; // enable DMA controller 00290 LPC_GPDMA->DMACIntTCClear = 0x1; // Reset the Interrupt status 00291 LPC_GPDMA->DMACIntErrClr = 0x1; 00292 LPC_GPDMACH0->DMACCLLI = 0; 00293 #endif 00294 WindowMax (); 00295 } 00296 00297 // Set one pixel 00298 void SPI_TFT::pixel(int x, int y, int color) 00299 { 00300 wr_reg(0x03, (x >> 0)); 00301 wr_reg(0x02, (x >> 8)); 00302 wr_reg(0x07, (y >> 0)); 00303 wr_reg(0x06, (y >> 8)); 00304 wr_cmd(0x22); 00305 _cs = 0; 00306 #if defined NO_MBED_LIB 00307 if (spi_port == 0) { // TFT on SSP0 00308 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00309 LPC_SSP0->DR = 0x72; // start Data 00310 LPC_SSP0->CR0 |= 0x08UL; // set back to 16 bit 00311 LPC_SSP0->DR = color; // Pixel 00312 // we have to wait for SPI IDLE to set CS back to high 00313 do { 00314 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle 00315 } else { // TFT on SSP1 00316 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00317 LPC_SSP1->DR = 0x72; // start Data 00318 LPC_SSP1->CR0 |= 0x08UL; // set back to 16 bit 00319 LPC_SSP1->DR = color; 00320 // we have to wait for SPI IDLE to set CS back to high 00321 do { 00322 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle 00323 } 00324 #else // use mbed lib 00325 00326 #if defined TARGET_KL25Z // 8 Bit SPI 00327 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00328 _spi.write(color >> 8); 00329 _spi.write(color & 0xff); 00330 #else 00331 _spi.format(8,3); // 8 bit Mode 3 00332 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00333 _spi.format(16,3); // switch to 16 bit Mode 3 00334 _spi.write(color); // Write D0..D15 00335 #endif 00336 #endif 00337 _cs = 1; 00338 } 00339 00340 // define draw area 00341 void SPI_TFT::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h) 00342 { 00343 wr_reg(0x03, x ); 00344 wr_reg(0x02, (x >> 8)); 00345 wr_reg(0x05, x+w-1 ); 00346 wr_reg(0x04, (x+w-1 >> 8)); 00347 wr_reg(0x07, y ); 00348 wr_reg(0x06, ( y >> 8)); 00349 wr_reg(0x09, ( y+h-1 )); 00350 wr_reg(0x08, ( y+h-1 >> 8)); 00351 } 00352 00353 // set draw area to max 00354 void SPI_TFT::WindowMax (void) 00355 { 00356 window (0, 0, width(), height()); 00357 } 00358 00359 00360 // clear screen 00361 void SPI_TFT::cls (void) 00362 { 00363 fprintf(stderr, "CLS \n\r"); 00364 int pixel = ( width() * height()); 00365 #if defined USE_DMA 00366 int dma_count; 00367 int color = _background; 00368 #endif 00369 WindowMax(); 00370 wr_cmd(0x22); 00371 00372 #if defined NO_MBED_LIB 00373 #if defined USE_DMA 00374 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; 00375 #endif 00376 _cs = 0; 00377 if (spi_port == 0) { // TFT on SSP0 00378 #if defined USE_DMA 00379 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00380 /* Enable SSP0 for DMA. */ 00381 LPC_SSP0->DMACR = 0x2; 00382 #endif 00383 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00384 LPC_SSP0->DR = 0x72; // start byte 00385 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00386 } else { // TFT on SSP1 00387 #if defined USE_DMA 00388 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00389 /* Enable SSP1 for DMA. */ 00390 LPC_SSP1->DMACR = 0x2; 00391 #endif 00392 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00393 LPC_SSP1->DR = 0x72; // start Data 00394 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00395 } 00396 00397 #if defined USE_DMA 00398 // start DMA 00399 do { 00400 if (pixel > 4095) { 00401 dma_count = 4095; 00402 pixel = pixel - 4095; 00403 } else { 00404 dma_count = pixel; 00405 pixel = 0; 00406 } 00407 LPC_GPDMA->DMACIntTCClear = 0x1; 00408 LPC_GPDMA->DMACIntErrClr = 0x1; 00409 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt 00410 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00411 LPC_GPDMA->DMACSoftSReq = 0x1; // DMA request 00412 do { 00413 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00414 } while (pixel > 0); 00415 if (spi_port == 0) { // TFT on SSP0 00416 do { 00417 } while ((0x0010 & LPC_SSP0->SR) == 0x10); // SPI FIFO not empty 00418 /* disable SSP0 for DMA. */ 00419 LPC_SSP0->DMACR = 0x0; 00420 } else { // TFT on SSP1 00421 do { 00422 } while ((0x0010 & LPC_SSP1->SR) == 0x10); // SPI FIFO not empty 00423 /* disable SSP1 for DMA. */ 00424 LPC_SSP1->DMACR = 0x0; 00425 } 00426 00427 #else // no DMA 00428 unsigned int i; 00429 for (i = 0; i < ( width() * height()); i++) 00430 _spi.write(_background); 00431 #endif 00432 00433 #else // use mbed lib 00434 _cs = 0; 00435 #if defined TARGET_KL25Z // 8 Bit SPI 00436 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00437 unsigned int i; 00438 for (i = 0; i < ( width() * height()); i++) { 00439 _spi.write(_background >> 8); 00440 _spi.write(_background & 0xff); 00441 } 00442 #else // 16 bit SPI 00443 _spi.format(8,3); // 8 bit Mode 3 00444 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00445 _spi.format(16,3); // switch back to 16 bit Mode 3 00446 unsigned int i; 00447 for (i = 0; i < ( width() * height()); i++) 00448 _spi.write(_background); 00449 #endif 00450 #endif 00451 _cs = 1; 00452 } 00453 00454 void SPI_TFT::circle(int x0, int y0, int r, int color) 00455 { 00456 int x = -r, y = 0, err = 2-2*r, e2; 00457 do { 00458 pixel(x0-x, y0+y,color); 00459 pixel(x0+x, y0+y,color); 00460 pixel(x0+x, y0-y,color); 00461 pixel(x0-x, y0-y,color); 00462 e2 = err; 00463 if (e2 <= y) { 00464 err += ++y*2+1; 00465 if (-x == y && e2 <= x) e2 = 0; 00466 } 00467 if (e2 > x) err += ++x*2+1; 00468 } while (x <= 0); 00469 00470 } 00471 00472 void SPI_TFT::fillcircle(int x0, int y0, int r, int color) 00473 { 00474 int x = -r, y = 0, err = 2-2*r, e2; 00475 do { 00476 vline(x0-x, y0-y, y0+y, color); 00477 vline(x0+x, y0-y, y0+y, color); 00478 e2 = err; 00479 if (e2 <= y) { 00480 err += ++y*2+1; 00481 if (-x == y && e2 <= x) e2 = 0; 00482 } 00483 if (e2 > x) err += ++x*2+1; 00484 } while (x <= 0); 00485 } 00486 00487 00488 // draw horizontal line 00489 void SPI_TFT::hline(int x0, int x1, int y, int color) 00490 { 00491 int w; 00492 w = x1 - x0 + 1; 00493 window(x0,y,w,1); 00494 wr_cmd(0x22); 00495 _cs = 0; 00496 #if defined NO_MBED_LIB 00497 if (spi_port == 0) { // TFT on SSP0 00498 #if defined USE_DMA 00499 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00500 /* Enable SSP0 for DMA. */ 00501 LPC_SSP0->DMACR = 0x2; 00502 #endif 00503 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00504 LPC_SSP0->DR = 0x72; // start Data 00505 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00506 } else { // TFT on SSP1 00507 #if defined USE_DMA 00508 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00509 /* Enable SSP1 for DMA. */ 00510 LPC_SSP1->DMACR = 0x2; 00511 #endif 00512 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00513 LPC_SSP1->DR = 0x72; // start Data 00514 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00515 } 00516 #if defined USE_DMA 00517 LPC_GPDMA->DMACIntTCClear = 0x1; 00518 LPC_GPDMA->DMACIntErrClr = 0x1; 00519 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; 00520 LPC_GPDMACH0->DMACCControl = w | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt 00521 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00522 LPC_GPDMA->DMACSoftSReq = 0x1; // start DMA 00523 do { 00524 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00525 if (spi_port == 0) { // TFT on SSP0 00526 do { 00527 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty 00528 } else { // TFT on SSP1 00529 do { 00530 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty 00531 } 00532 #else // no DMA 00533 int i; 00534 for (i=0; i<w; i++) { 00535 _spi.write(color); 00536 } 00537 #endif 00538 #else // use mbed lib 00539 #if defined TARGET_KL25Z // 8 Bit SPI 00540 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00541 for (int j=0; j<w; j++) { 00542 _spi.write(color >> 8); 00543 _spi.write(color & 0xff); 00544 } 00545 #else // 16 Bit SPI 00546 _spi.format(8,3); // 8 bit Mode 3 00547 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00548 _spi.format(16,3); // switch back to 16 bit Mode 3 00549 for (int j=0; j<w; j++) { 00550 _spi.write(color); 00551 } 00552 #endif 00553 #endif 00554 _cs = 1; 00555 WindowMax(); 00556 return; 00557 } 00558 00559 // draw vertical line 00560 void SPI_TFT::vline(int x, int y0, int y1, int color) 00561 { 00562 int h; 00563 h = y1 - y0 + 1; 00564 window(x,y0,1,h); 00565 wr_cmd(0x22); 00566 _cs = 0; 00567 #if defined NO_MBED_LIB 00568 if (spi_port == 0) { // TFT on SSP0 00569 #if defined USE_DMA 00570 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00571 /* Enable SSP0 for DMA. */ 00572 LPC_SSP0->DMACR = 0x2; 00573 #endif 00574 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00575 LPC_SSP0->DR = 0x72; // start Data 00576 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00577 } else { // TFT on SSP1 00578 #if defined USE_DMA 00579 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00580 /* Enable SSP1 for DMA. */ 00581 LPC_SSP1->DMACR = 0x2; 00582 #endif 00583 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00584 LPC_SSP1->DR = 0x72; // start Data 00585 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00586 } 00587 #if defined USE_DMA 00588 LPC_GPDMA->DMACIntTCClear = 0x1; 00589 LPC_GPDMA->DMACIntErrClr = 0x1; 00590 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; 00591 LPC_GPDMACH0->DMACCControl = h | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt 00592 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00593 LPC_GPDMA->DMACSoftSReq = 0x1; 00594 do { 00595 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00596 00597 if (spi_port == 0) { // TFT on SSP0 00598 do { 00599 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty 00600 } else { // TFT on SSP1 00601 do { 00602 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty 00603 } 00604 #else // no DMA 00605 for (int y=0; y<h; y++) { 00606 _spi.write(color); 00607 } 00608 #endif 00609 #else // use mbed lib 00610 #if defined TARGET_KL25Z // 8 Bit SPI 00611 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00612 for (int y=0; y<h; y++) { 00613 _spi.write(color >> 8); 00614 _spi.write(color & 0xff); 00615 } 00616 #else // 16 bit SPI 00617 _spi.format(8,3); // 8 bit Mode 3 00618 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00619 _spi.format(16,3); // switch to 16 bit Mode 3 00620 for (int y=0; y<h; y++) { 00621 _spi.write(color); 00622 } 00623 #endif 00624 #endif 00625 _cs = 1; 00626 WindowMax(); 00627 return; 00628 } 00629 00630 00631 // draw line 00632 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color) 00633 { 00634 //WindowMax(); 00635 int dx = 0, dy = 0; 00636 int dx_sym = 0, dy_sym = 0; 00637 int dx_x2 = 0, dy_x2 = 0; 00638 int di = 0; 00639 00640 dx = x1-x0; 00641 dy = y1-y0; 00642 00643 if (dx == 0) { /* vertical line */ 00644 if (y1 > y0) vline(x0,y0,y1,color); 00645 else vline(x0,y1,y0,color); 00646 return; 00647 } 00648 00649 if (dx > 0) { 00650 dx_sym = 1; 00651 } else { 00652 dx_sym = -1; 00653 } 00654 if (dy == 0) { /* horizontal line */ 00655 if (x1 > x0) hline(x0,x1,y0,color); 00656 else hline(x1,x0,y0,color); 00657 return; 00658 } 00659 00660 if (dy > 0) { 00661 dy_sym = 1; 00662 } else { 00663 dy_sym = -1; 00664 } 00665 00666 dx = dx_sym*dx; 00667 dy = dy_sym*dy; 00668 00669 dx_x2 = dx*2; 00670 dy_x2 = dy*2; 00671 00672 if (dx >= dy) { 00673 di = dy_x2 - dx; 00674 while (x0 != x1) { 00675 00676 pixel(x0, y0, color); 00677 x0 += dx_sym; 00678 if (di<0) { 00679 di += dy_x2; 00680 } else { 00681 di += dy_x2 - dx_x2; 00682 y0 += dy_sym; 00683 } 00684 } 00685 pixel(x0, y0, color); 00686 } else { 00687 di = dx_x2 - dy; 00688 while (y0 != y1) { 00689 pixel(x0, y0, color); 00690 y0 += dy_sym; 00691 if (di < 0) { 00692 di += dx_x2; 00693 } else { 00694 di += dx_x2 - dy_x2; 00695 x0 += dx_sym; 00696 } 00697 } 00698 pixel(x0, y0, color); 00699 } 00700 return; 00701 } 00702 00703 // draw rect 00704 void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color) 00705 { 00706 00707 if (x1 > x0) hline(x0,x1,y0,color); 00708 else hline(x1,x0,y0,color); 00709 00710 if (y1 > y0) vline(x0,y0,y1,color); 00711 else vline(x0,y1,y0,color); 00712 00713 if (x1 > x0) hline(x0,x1,y1,color); 00714 else hline(x1,x0,y1,color); 00715 00716 if (y1 > y0) vline(x1,y0,y1,color); 00717 else vline(x1,y1,y0,color); 00718 00719 return; 00720 } 00721 00722 00723 // fill rect 00724 void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color) 00725 { 00726 00727 int h = y1 - y0 + 1; 00728 int w = x1 - x0 + 1; 00729 int pixel = h * w; 00730 #if defined USE_DMA 00731 int dma_count; 00732 #endif 00733 window(x0,y0,w,h); 00734 wr_cmd(0x22); 00735 _cs = 0; 00736 #if defined NO_MBED_LIB 00737 if (spi_port == 0) { // TFT on SSP0 00738 #if defined USE_DMA 00739 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00740 /* Enable SSP0 for DMA. */ 00741 LPC_SSP0->DMACR = 0x2; 00742 #endif 00743 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00744 LPC_SSP0->DR = 0x72; // start Data 00745 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00746 } else { // TFT on SSP1 00747 #if defined USE_DMA 00748 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00749 /* Enable SSP1 for DMA. */ 00750 LPC_SSP1->DMACR = 0x2; 00751 #endif 00752 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00753 LPC_SSP1->DR = 0x72; // start Data 00754 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00755 } 00756 #if defined USE_DMA 00757 do { 00758 if (pixel > 4095) { 00759 dma_count = 4095; 00760 pixel = pixel - 4095; 00761 } else { 00762 dma_count = pixel; 00763 pixel = 0; 00764 } 00765 LPC_GPDMA->DMACIntTCClear = 0x1; 00766 LPC_GPDMA->DMACIntErrClr = 0x1; 00767 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)&color; 00768 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) ; // 16 bit transfer , no address increment, interrupt 00769 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00770 LPC_GPDMA->DMACSoftSReq = 0x1; 00771 do { 00772 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00773 00774 } while (pixel > 0); 00775 00776 if (spi_port == 0) { // TFT on SSP0 00777 do { 00778 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty 00779 } else { // TFT on SSP1 00780 do { 00781 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty 00782 } 00783 00784 #else // no DMA 00785 for (int p=0; p<pixel; p++) { 00786 _spi.write(color); 00787 } 00788 #endif 00789 00790 #else // use mbed lib 00791 #if defined TARGET_KL25Z // 8 Bit SPI 00792 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00793 for (int p=0; p<pixel; p++) { 00794 _spi.write(color >> 8); 00795 _spi.write(color & 0xff); 00796 } 00797 00798 #else // 16 bit SPI 00799 _spi.format(8,3); // 8 bit Mode 3 00800 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00801 _spi.format(16,3); // switch to 16 bit Mode 3 00802 for (int p=0; p<pixel; p++) { 00803 _spi.write(color); 00804 } 00805 #endif 00806 #endif 00807 _cs = 1; 00808 WindowMax(); 00809 return; 00810 } 00811 00812 // set cursor position 00813 void SPI_TFT::locate(int x, int y) 00814 { 00815 char_x = x; 00816 char_y = y; 00817 } 00818 00819 00820 // calculate num of chars in a row 00821 int SPI_TFT::columns() 00822 { 00823 return width() / font[1]; 00824 } 00825 00826 // calculate num of rows on the screen 00827 int SPI_TFT::rows() 00828 { 00829 return height() / font[2]; 00830 } 00831 00832 // print a char on the screen 00833 int SPI_TFT::_putc(int value) 00834 { 00835 if (value == '\n') { // new line 00836 char_x = 0; 00837 char_y = char_y + font[2]; 00838 if (char_y >= height() - font[2]) { 00839 char_y = 0; 00840 } 00841 } else { 00842 character(char_x, char_y, value); 00843 } 00844 return value; 00845 } 00846 00847 // consrtuct the char out of the font 00848 void SPI_TFT::character(int x, int y, int c) 00849 { 00850 unsigned int hor,vert,offset,bpl,j,i,b; 00851 unsigned char* zeichen; 00852 unsigned char z,w; 00853 #if defined USE_DMA 00854 unsigned int pixel; 00855 unsigned int p; 00856 unsigned int dma_count,dma_off; 00857 uint16_t *buffer; 00858 #endif 00859 00860 if ((c < 31) || (c > 127)) return; // test char range 00861 00862 // read font parameter from start of array 00863 offset = font[0]; // bytes / char 00864 hor = font[1]; // get hor size of font 00865 vert = font[2]; // get vert size of font 00866 bpl = font[3]; // bytes per line 00867 00868 if (char_x + hor > width()) { 00869 char_x = 0; 00870 char_y = char_y + vert; 00871 if (char_y >= height() - font[2]) { 00872 char_y = 0; 00873 } 00874 } 00875 window(char_x, char_y,hor,vert); // char box 00876 wr_cmd(0x22); 00877 00878 #if defined USE_DMA 00879 pixel = hor * vert; // calculate buffer size 00880 00881 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the 16 bit 00882 if (buffer == NULL) { 00883 //led = 1; 00884 //pc.printf("Malloc error !\n\r"); 00885 return; // error no memory 00886 } 00887 00888 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00889 w = zeichen[0]; // width of actual char 00890 p = 0; 00891 // construct the char into the buffer 00892 for (j=0; j<vert; j++) { // vert line 00893 for (i=0; i<hor; i++) { // horz line 00894 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00895 b = 1 << (j & 0x07); 00896 if (( z & b ) == 0x00) { 00897 buffer[p] = _background; 00898 } else { 00899 buffer[p] = _foreground; 00900 } 00901 p++; 00902 } 00903 } 00904 00905 // copy the buffer with DMA SPI to display 00906 dma_off = 0; // offset for DMA transfer 00907 _cs = 0; 00908 if (spi_port == 0) { // TFT on SSP0 00909 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 00910 /* Enable SSP0 for DMA. */ 00911 LPC_SSP0->DMACR = 0x2; 00912 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00913 LPC_SSP0->DR = 0x72; // start Data 00914 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00915 } else { // TFT on SSP1 00916 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 00917 /* Enable SSP1 for DMA. */ 00918 LPC_SSP1->DMACR = 0x2; 00919 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00920 LPC_SSP1->DR = 0x72; // start Data 00921 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00922 } 00923 00924 // start DMA 00925 do { 00926 if (pixel > 4095) { // this is a giant font ! 00927 dma_count = 4095; 00928 pixel = pixel - 4095; 00929 } else { 00930 dma_count = pixel; 00931 pixel = 0; 00932 } 00933 LPC_GPDMA->DMACIntTCClear = 0x1; 00934 LPC_GPDMA->DMACIntErrClr = 0x1; 00935 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t) (buffer + dma_off); 00936 LPC_GPDMACH0->DMACCControl = dma_count | (1UL << 18) | (1UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt 00937 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 00938 LPC_GPDMA->DMACSoftSReq = 0x1; 00939 do { 00940 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 00941 dma_off = dma_off + dma_count; 00942 } while (pixel > 0); 00943 00944 free ((uint16_t *) buffer); 00945 00946 if (spi_port == 0) { // TFT on SSP0 00947 do { 00948 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI0 not idle 00949 /* disable SSP0 for DMA. */ 00950 LPC_SSP0->DMACR = 0x0; 00951 } else { // TFT on SSP1 00952 do { 00953 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI1 not idle 00954 /* disable SSP1 for DMA. */ 00955 LPC_SSP1->DMACR = 0x0; 00956 } 00957 00958 #else // no dma 00959 _cs = 0; 00960 #if defined NO_MBED_LIB 00961 if (spi_port == 0) { // TFT on SSP0 00962 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 00963 LPC_SSP0->DR = 0x72; // start Data 00964 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 00965 } else { // TFT on SSP1 00966 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 00967 LPC_SSP1->DR = 0x72; // start Data 00968 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 00969 } 00970 #else // mbed lib 00971 #if defined TARGET_KL25Z // 8 Bit SPI 00972 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00973 #else // 16 bit SPI 00974 _spi.format(8,3); // 8 bit Mode 3 00975 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 00976 _spi.format(16,3); // switch back to 16 bit Mode 3 00977 #endif 00978 #endif 00979 00980 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap 00981 w = zeichen[0]; // width of actual char 00982 for (j=0; j<vert; j++) { // vert line 00983 for (i=0; i<hor; i++) { // horz line 00984 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1]; 00985 b = 1 << (j & 0x07); 00986 if (( z & b ) == 0x00) { 00987 #if defined TARGET_KL25Z // 8 Bit SPI 00988 _spi.write(_background >> 8); 00989 _spi.write(_background & 0xff); 00990 #else 00991 _spi.write(_background); 00992 #endif 00993 } else { 00994 #if defined TARGET_KL25Z // 8 Bit SPI 00995 _spi.write(_foreground >> 8); 00996 _spi.write(_foreground & 0xff); 00997 #else 00998 _spi.write(_foreground); 00999 #endif 01000 } 01001 } 01002 } 01003 #endif // no DMA 01004 _cs = 1; 01005 WindowMax(); 01006 if ((w + 2) < hor) { // x offset to next char 01007 char_x += w + 2; 01008 } else char_x += hor; 01009 } 01010 01011 01012 void SPI_TFT::set_font(unsigned char* f) 01013 { 01014 font = f; 01015 } 01016 01017 01018 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap) 01019 { 01020 unsigned int j; 01021 int padd; 01022 01023 unsigned short *bitmap_ptr = (unsigned short *)bitmap; 01024 #if defined TARGET_KL25Z // 8 Bit SPI 01025 unsigned short pix_temp; 01026 #endif 01027 01028 // the lines are padded to multiple of 4 bytes in a bitmap 01029 padd = -1; 01030 do { 01031 padd ++; 01032 } while (2*(w + padd)%4 != 0); 01033 window(x, y, w, h); 01034 wr_cmd(0x22); 01035 _cs = 0; 01036 #if defined NO_MBED_LIB 01037 if (spi_port == 0) { // TFT on SSP0 01038 #if defined USE_DMA 01039 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 01040 /* Enable SSP0 for DMA. */ 01041 LPC_SSP0->DMACR = 0x2; 01042 #endif 01043 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 01044 LPC_SSP0->DR = 0x72; // start Data 01045 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 01046 01047 } else { 01048 #if defined USE_DMA 01049 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 01050 /* Enable SSP1 for DMA. */ 01051 LPC_SSP1->DMACR = 0x2; 01052 #endif 01053 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 01054 LPC_SSP1->DR = 0x72; // start Data command 01055 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 01056 } 01057 01058 bitmap_ptr += ((h - 1)* (w + padd)); 01059 #if defined USE_DMA 01060 for (j = 0; j < h; j++) { //Lines 01061 LPC_GPDMA->DMACIntTCClear = 0x1; 01062 LPC_GPDMA->DMACIntErrClr = 0x1; 01063 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)bitmap_ptr; 01064 LPC_GPDMACH0->DMACCControl = w | (1UL << 18) | (1UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt 01065 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 01066 LPC_GPDMA->DMACSoftSReq = 0x1; 01067 do { 01068 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 01069 01070 bitmap_ptr -= w; 01071 bitmap_ptr -= padd; 01072 } 01073 #else 01074 unsigned int i; 01075 for (j = 0; j < h; j++) { //Lines 01076 for (i = 0; i < w; i++) { // copy pixel data to TFT 01077 _spi.write(*bitmap_ptr); // one line 01078 bitmap_ptr++; 01079 } 01080 bitmap_ptr -= 2*w; 01081 bitmap_ptr -= padd; 01082 } 01083 #endif 01084 if (spi_port == 0) { // TFT on SSP0 01085 do { 01086 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty 01087 } else { 01088 do { 01089 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty 01090 } 01091 #else // use mbed lib 01092 #if defined TARGET_KL25Z // 8 Bit SPI 01093 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 01094 #else 01095 _spi.format(8,3); // 8 bit Mode 3 01096 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 01097 _spi.format(16,3); // switch to 16 bit Mode 3 01098 #endif 01099 bitmap_ptr += ((h - 1)* (w + padd)); 01100 unsigned int i; 01101 for (j = 0; j < h; j++) { //Lines 01102 for (i = 0; i < w; i++) { // copy pixel data to TFT 01103 #if defined TARGET_KL25Z // 8 Bit SPI 01104 pix_temp = *bitmap_ptr; 01105 _spi.write(pix_temp >> 8); 01106 _spi.write(pix_temp); 01107 bitmap_ptr++; 01108 #else 01109 _spi.write(*bitmap_ptr); // one line 01110 bitmap_ptr++; 01111 #endif 01112 } 01113 bitmap_ptr -= 2*w; 01114 bitmap_ptr -= padd; 01115 } 01116 #endif // USE MBED LIB 01117 _cs = 1; 01118 WindowMax(); 01119 } 01120 01121 01122 // local filesystem is not implemented in kinetis board 01123 #if defined TARGET_LPC1768 || defined TARGET_LPC11U24 01124 01125 01126 int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP) 01127 { 01128 01129 #define OffsetPixelWidth 18 01130 #define OffsetPixelHeigh 22 01131 #define OffsetFileSize 34 01132 #define OffsetPixData 10 01133 #define OffsetBPP 28 01134 01135 char filename[50]; 01136 unsigned char BMP_Header[54]; 01137 unsigned short BPP_t; 01138 unsigned int PixelWidth,PixelHeigh,start_data; 01139 unsigned int i,off; 01140 int padd,j; 01141 unsigned short *line; 01142 01143 // get the filename 01144 LocalFileSystem local("local"); 01145 sprintf(&filename[0],"/local/"); 01146 i=7; 01147 while (*Name_BMP!='\0') { 01148 filename[i++]=*Name_BMP++; 01149 } 01150 01151 fprintf(stderr, "filename : %s \n\r",filename); 01152 01153 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file 01154 if (!Image) { 01155 return(0); // error file not found ! 01156 } 01157 01158 fread(&BMP_Header[0],1,54,Image); // get the BMP Header 01159 01160 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte 01161 fclose(Image); 01162 return(-1); // error no BMP file 01163 } 01164 01165 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8); 01166 if (BPP_t != 0x0010) { 01167 fclose(Image); 01168 return(-2); // error no 16 bit BMP 01169 } 01170 01171 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24); 01172 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24); 01173 if (PixelHeigh > height() + y || PixelWidth > width() + x) { 01174 fclose(Image); 01175 return(-3); // to big 01176 } 01177 01178 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24); 01179 01180 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line 01181 if (line == NULL) { 01182 return(-4); // error no memory 01183 } 01184 01185 // the bmp lines are padded to multiple of 4 bytes 01186 padd = -1; 01187 do { 01188 padd ++; 01189 } while ((PixelWidth * 2 + padd)%4 != 0); 01190 01191 01192 //fseek(Image, 70 ,SEEK_SET); 01193 window(x, y,PixelWidth ,PixelHeigh); 01194 wr_cmd(0x22); 01195 _cs = 0; 01196 #if defined NO_MBED_LIB 01197 if (spi_port == 0) { // TFT on SSP0 01198 #if defined USE_DMA 01199 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0 01200 /* Enable SSP0 for DMA. */ 01201 LPC_SSP0->DMACR = 0x2; 01202 #endif 01203 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit 01204 LPC_SSP0->DR = 0x72; // start Data 01205 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit 01206 01207 } else { 01208 #if defined USE_DMA 01209 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1 01210 /* Enable SSP1 for DMA. */ 01211 LPC_SSP1->DMACR = 0x2; 01212 #endif 01213 LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit 01214 LPC_SSP1->DR = 0x72; // start Data 01215 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit 01216 } 01217 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 01218 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 01219 fseek(Image, off ,SEEK_SET); 01220 fread(line,1,PixelWidth * 2,Image); // read a line - slow ! 01221 #if defined USE_DMA 01222 LPC_GPDMA->DMACIntTCClear = 0x1; 01223 LPC_GPDMA->DMACIntErrClr = 0x1; 01224 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)line; 01225 LPC_GPDMACH0->DMACCControl = PixelWidth | (1UL << 18) | (1UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 16 bit transfer , address increment, interrupt 01226 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX); 01227 LPC_GPDMA->DMACSoftSReq = 0x1; 01228 do { 01229 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running 01230 #else 01231 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 01232 _spi.write(line[i]); // one 16 bit pixel 01233 } 01234 #endif 01235 } 01236 if (spi_port == 0) { // TFT on SSP0 01237 do { 01238 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty 01239 } else { 01240 do { 01241 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty 01242 } 01243 01244 #else // use mbed lib 01245 _spi.format(8,3); // 8 bit Mode 3 01246 _spi.write(SPI_START | SPI_WR | SPI_DATA); // Write : RS = 1, RW = 0 01247 _spi.format(16,3); // switch to 16 bit Mode 3 01248 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up 01249 off = j * (PixelWidth * 2 + padd) + start_data; // start of line 01250 fseek(Image, off ,SEEK_SET); 01251 fread(line,1,PixelWidth * 2,Image); // read a line - slow ! 01252 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT 01253 _spi.write(line[i]); // one 16 bit pixel 01254 } 01255 } 01256 #endif 01257 _cs = 1; 01258 free (line); 01259 fclose(Image); 01260 WindowMax(); 01261 return(1); 01262 } 01263 01264 #endif
Generated on Tue Jul 12 2022 20:03:43 by 1.7.2