Lib for the new LCD Display with ILI9341 controller

Dependents:   TFT_Test_ILI9341 touch_piirto TFT_banggood TFT_Test_ILI9341-a-fish ... more

Lib for 320*240 Pixel Color LCD with ILI9341 controller. Based on MI0283QT-9 datasheet. The lib is based on the http://mbed.org/cookbook/SPI-driven-QVGA-TFT code for the older LCD board.

The lib is using the 4 line serial data interface. The IM pins have to be set to 1110 (IM3-IM0) to use this mode. It use the SPI hardware.

I have started to speed up the lib with using DMA and direct SPI programming. To do this I have to split the code for the different platforms. To prevent unreadable code with a lot of #ifdef... I have create a new file. The #ifdef definition around is switching between the platforms. I will add the other Nucleo platforms. If you want to support others - see ..._NUCLEO.cpp , port and send me the code to add.

Display 1

If you use the TFT Proto from MikroElektronika http://www.mikroe.com/eng/products/view/474/tft-proto-board/ you have to connect : /media/uploads/dreschpe/tft_proto.png

MBEDDisplay
+ 3,3V3,3V
GNDGND
mosiSDI
misoSDO
sckRS
csCS
resetRST
dcWR/SCL
GNDIM0
+3,3VIM1 IM2 IM3
GNDDB0 - DB17
GNDRD

The backlite LED need a resistor to limit the current. You can use two 10R resistors parallel to get 5R driven by 3.3V.

Display 2

Watterott is also selling a ILI9341 based QVGA TFT : http://www.watterott.com/de/MI0283QT-2-Adapter

Unfortunately this adapter is set to 9 bit SPI mode via the mode pins IM0-IM3. If you want to patch this - like I have done - you have to desolder the TFT from the pcb to cut some traces. This is a flexible print. Only for people with soldering skills ! You also have to get access to pin 36 for the dc signal. Cut the GND connection. You can use the level converter used for the LCD_LED signal. Mosfet Q1 can be driven with a logic signal without converter. Watterott will change this in a future revision.

/media/uploads/dreschpe/mi0283qt_v12_patch.pdf

Display 3

There are inexpensive displays from china. You can get them at: http://www.banggood.com/2_2-Inch-Serial-TFT-SPI-LCD-Screen-Module-HD-240-X-320-5110-Compatible-p-912854.html The board has also a SD card connector at the backside, but no touch.

/media/uploads/dreschpe/tft3_1.jpg /media/uploads/dreschpe/tft3_2.jpg

The board can be used without modification. Connect VCC with 5V USB out. There is a voltage regulator on board. To use the SD card simply import the SDFileSystem and connect it to the second SPI.

Fonts

How to get nice looking fonts ?

To print characters to a graphic screen we need a font. To code a font by paper is ok for a small lcd, but for a 320*240 pixel display we need bigger fonts. A 12*12 pixel font is readable, but a lot of work to construct.

Fonts can be made with the GLCD Font Creator also from http://www.mikroe.com .

With this program you can load a window font and convert it into a c-array. To use this Font with my lib you have to add 4 parameter at the beginning of the font array. - the number of byte / char - the vertial size in pixel - the horizontal size in pixel - the number of byte per vertical line (it is vertical size / 8 ) You also have to change the array to char[]. After that you can switch between different fonts with set_font(unsigned char* font); The horizontal size of each character is also stored in the font. It look better if you use bigger fonts or italic. The letter M is wider than a l.

Here are some Fonts from me : http://mbed.org/users/dreschpe/code/TFT_fonts/

The small made for the mbed lab board : http://mbed.org/users/dreschpe/code/LCD_fonts/

And from Peter Holzleitner : http://mbed.org/users/pholzleitner/code/SourceCodePro31-SB/

Text commands :

You can use the claim() function to redirect the output to stdout or stderr to the TFT. After claim(stdout) you can simply use the printf function to print to the TFT.

  • locate(x,y); function is used to setup the cursor position. x,y are the pixel position. This was changed from row,column in older lib !

There are two parameter to setup the color of the text :

  • background(color);
  • foreground(color); All color are 16bit: R5 G6 B5.
  • set_orientation(); This command select one of the 4 directions to use the display. This command is also working on the graphical commands.

Graphics

Graphic commands :

  • cls(); Fill the screen with background color
  • pixel(x,y,color); set a single pixel at x,y with color
  • line(x0,y0,x1,y1,color); draw a line from x0,y0 to x1,y1 with color
  • rect(x0,y0,x1,y1,color); draw a rectangle x0,y0 to x1,y1 with color
  • fillrect(x0,y0,x1,y1,color); draw a filled rectangle
  • circle( x0,y0,radius ,color); draw a circle around x0,y0 with radius
  • fillcircle(x0,y0,radius ,color); draw a filled circle around x0,y0 with radius
  • Bitmap(x0,y0,w,h,*bitmap); paint a bitmap with width w and high h starting at x0,y0 (upper left corner)
  • BMP_16(x0,y0,*bmp); paint a bmp file out of the internal drive or a SD-card

How to transfer a grafic to the mbed ?

The hard way - but fast to load :

Load from mbed flash. It consume a lot of flash memory. To construct a bitmap array we can use gimp. http://www.gimp.org/ Load a image (edit and resize) and export it as BMP. You have to select the option 16 bit R5 G6 B5 !

To convert this file into a c-array you can use the hex-editor winhex. (http://www.x-ways.net/winhex/index-m.html) The eval version can handle the small files. We don`t need the bmp header. Mark the data starting at offset 0x46 to the end of file. Use "edit -> copy block -> C Source" to export this data as C array. Paste the data into a C file into the mbed compiler. The editor will generate a array of char[]. To use 16 bit DMA on this we have to put a __align(2) in front of the definition. To put it into Flash we change it to static const unsigned char bmp[]{...}

__align(2)
static const unsigned char bmp[]{
      0xCB, 0x5A, 0x5C, 0xE7,....

};

The easy way - but slower to load:

With the BMP_16 command we can load a picture out of the internal drive or a SD-card to the display.

  • BMP_16(x0,y0,"/local/test.bmp"); paint test.bmp out of the internal drive to x0, y0
  • BMP_16(x0,y0,"/sd/test.bmp"); paint test.bmp out of a external SD-card to x0, y0

simply copy test.bmp to the mbed usb drive or the SD-card. The bmp has to be saved with the options 16 bit R5 G6 B5 ! You can use the program gimp to convert pictures into the 16 bit bmp format.

sample code

http://mbed.org/users/dreschpe/code/TFT_Test_ILI9341/

// example to test the TFT Display
// Thanks to the GraphicsDisplay and TextDisplay classes
// test2.bmp has to be on the mbed file system

#include "stdio.h"
#include "mbed.h"
#include "SPI_TFT_ILI9341.h"
#include "string"
#include "Arial12x12.h"
#include "Arial24x23.h"
#include "Arial28x28.h"
#include "font_big.h"

extern unsigned char p1[];  // the mbed logo

DigitalOut LCD_LED(p21); // the Watterott display has a backlight switch
DigitalOut CS_Touch(p15); // disable the touch controller on the Watterott display

// the TFT is connected to SPI pin 5-7
SPI_TFT_ILI9341 TFT(p5, p6, p7, p8, p9, p10,"TFT"); // mosi, miso, sclk, cs, reset, dc

int main()
{
    int i;
    LCD_LED = 1;  // backlight on
    CS_Touch = 1; 
   
    TFT.claim(stdout);      // send stdout to the TFT display
    //TFT.claim(stderr);      // send stderr to the TFT display
    TFT.set_orientation(1);
    TFT.background(Black);    // set background to black
    TFT.foreground(White);    // set chars to white
    TFT.cls();                // clear the screen

    //first show the 4 directions
    TFT.set_orientation(0);
    TFT.background(Black);
    TFT.cls();

    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(0,0);
    printf("  Hello Mbed 0");

    TFT.set_orientation(1);
    TFT.locate(0,0);
    printf("  Hello Mbed 1");
    TFT.set_orientation(2);
    TFT.locate(0,0);
    printf("  Hello Mbed 2");
    TFT.set_orientation(3);
    TFT.locate(0,0);
    printf("  Hello Mbed 3");
    TFT.set_orientation(1);
    TFT.set_font((unsigned char*) Arial24x23);
    TFT.locate(50,100);
    TFT.printf("TFT orientation");

/media/uploads/dreschpe/orient.jpg

// draw some graphics
    TFT.cls();
    TFT.set_font((unsigned char*) Arial24x23);
    TFT.locate(100,100);
    TFT.printf("Graphic");

    TFT.line(0,0,100,0,Green);
    TFT.line(0,0,0,200,Green);
    TFT.line(0,0,100,200,Green);

    TFT.rect(100,50,150,100,Red);
    TFT.fillrect(180,25,220,70,Blue);

    TFT.circle(80,150,33,White);
    TFT.fillcircle(160,190,20,Yellow);

    double s;

    for (i=0; i<320; i++) {
        s =20 * sin((long double) i / 10 );
        TFT.pixel(i,100 + (int)s ,Red);
    }

/media/uploads/dreschpe/grafik.jpg

   // bigger text
    TFT.foreground(White);
    TFT.background(Blue);
    TFT.cls();
    TFT.set_font((unsigned char*) Arial24x23);
    TFT.locate(0,0);
    TFT.printf("Different Fonts :");

    TFT.set_font((unsigned char*) Neu42x35);
    TFT.locate(0,30);
    TFT.printf("Hello Mbed 1");
    TFT.set_font((unsigned char*) Arial24x23);
    TFT.locate(20,80);
    TFT.printf("Hello Mbed 2");
    TFT.set_font((unsigned char*) Arial12x12);
    TFT.locate(35,120);
    TFT.printf("Hello Mbed 3");

/media/uploads/dreschpe/fonts2.jpg

    // mbed logo from flash
    // defined in graphics.c
    //__align(4)
    //unsigned char p1[18920] = {
    //0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ....
    // 
    TFT.background(Black);
    TFT.cls();

    TFT.locate(10,10);
    TFT.printf("Graphic from Flash");

    TFT.Bitmap(90,90,172,55,p1);

/media/uploads/dreschpe/mbed.jpg

  
  #include "SDFileSystem.h"
  // connect a sd-card to the second spi or use the local filesystem of the LPC   
  SDFileSystem sd(p11, p12, p13, p14, "sd"); // mosi,miso,sck,cs
  TFT.cls();
  TFT.locate(10,110);
  TFT.printf("Graphic from external SD-card");
  int err = TFT.BMP_16(1,140,"/sd/test.bmp");  // load test.bmp from external SD-card
  TFT.locate(10,120);
  if (err != 1) TFT.printf(" - Err: %d",err);

/media/uploads/dreschpe/bmp16.jpg

Committer:
dreschpe
Date:
Sun Jun 22 21:44:00 2014 +0000
Revision:
8:07ad6a48a85d
Parent:
7:4c30bea883bc
Special Nucleo L152 version of TFT Lib

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dreschpe 0:da1bf437cbc1 1 /* mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
dreschpe 8:07ad6a48a85d 2 * Copyright (c) 2013, 2014 Peter Drescher - DC2PD
dreschpe 8:07ad6a48a85d 3 * special version for STM Nucleo -L152 and SPI1 !
dreschpe 0:da1bf437cbc1 4 *
dreschpe 0:da1bf437cbc1 5 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
dreschpe 0:da1bf437cbc1 6 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
dreschpe 0:da1bf437cbc1 7 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
dreschpe 0:da1bf437cbc1 8 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
dreschpe 0:da1bf437cbc1 9 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
dreschpe 0:da1bf437cbc1 10 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
dreschpe 0:da1bf437cbc1 11 * THE SOFTWARE.
dreschpe 0:da1bf437cbc1 12 */
dreschpe 0:da1bf437cbc1 13
dreschpe 0:da1bf437cbc1 14 #include "SPI_TFT_ILI9341.h"
dreschpe 0:da1bf437cbc1 15 #include "mbed.h"
dreschpe 8:07ad6a48a85d 16 #include "stm32l1xx_dma.h"
dreschpe 8:07ad6a48a85d 17 #include "stm32l1xx_rcc.h"
dreschpe 8:07ad6a48a85d 18 #include "stm32l1xx_spi.h"
dreschpe 0:da1bf437cbc1 19
dreschpe 8:07ad6a48a85d 20 #define BPP 16 // Bits per pixel
dreschpe 8:07ad6a48a85d 21
dreschpe 0:da1bf437cbc1 22 //extern Serial pc;
dreschpe 0:da1bf437cbc1 23 //extern DigitalOut xx; // debug !!
dreschpe 0:da1bf437cbc1 24
dreschpe 8:07ad6a48a85d 25
dreschpe 0:da1bf437cbc1 26 SPI_TFT_ILI9341::SPI_TFT_ILI9341(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, PinName dc, const char *name)
dreschpe 0:da1bf437cbc1 27 : _spi(mosi, miso, sclk), _cs(cs), _reset(reset), _dc(dc), GraphicsDisplay(name)
dreschpe 0:da1bf437cbc1 28 {
dreschpe 6:fe07ae8329f7 29 clk = sclk;
dreschpe 0:da1bf437cbc1 30 orientation = 0;
dreschpe 0:da1bf437cbc1 31 char_x = 0;
dreschpe 0:da1bf437cbc1 32 tft_reset();
dreschpe 0:da1bf437cbc1 33 }
dreschpe 0:da1bf437cbc1 34
dreschpe 0:da1bf437cbc1 35 int SPI_TFT_ILI9341::width()
dreschpe 0:da1bf437cbc1 36 {
dreschpe 0:da1bf437cbc1 37 if (orientation == 0 || orientation == 2) return 240;
dreschpe 0:da1bf437cbc1 38 else return 320;
dreschpe 0:da1bf437cbc1 39 }
dreschpe 0:da1bf437cbc1 40
dreschpe 0:da1bf437cbc1 41
dreschpe 0:da1bf437cbc1 42 int SPI_TFT_ILI9341::height()
dreschpe 0:da1bf437cbc1 43 {
dreschpe 0:da1bf437cbc1 44 if (orientation == 0 || orientation == 2) return 320;
dreschpe 0:da1bf437cbc1 45 else return 240;
dreschpe 0:da1bf437cbc1 46 }
dreschpe 0:da1bf437cbc1 47
dreschpe 0:da1bf437cbc1 48
dreschpe 2:0a16083193a4 49 void SPI_TFT_ILI9341::set_orientation(unsigned int o)
dreschpe 0:da1bf437cbc1 50 {
dreschpe 0:da1bf437cbc1 51 orientation = o;
dreschpe 2:0a16083193a4 52 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL
dreschpe 0:da1bf437cbc1 53 switch (orientation) {
dreschpe 0:da1bf437cbc1 54 case 0:
dreschpe 2:0a16083193a4 55 _spi.write(0x48);
dreschpe 0:da1bf437cbc1 56 break;
dreschpe 0:da1bf437cbc1 57 case 1:
dreschpe 2:0a16083193a4 58 _spi.write(0x28);
dreschpe 0:da1bf437cbc1 59 break;
dreschpe 0:da1bf437cbc1 60 case 2:
dreschpe 2:0a16083193a4 61 _spi.write(0x88);
dreschpe 0:da1bf437cbc1 62 break;
dreschpe 0:da1bf437cbc1 63 case 3:
dreschpe 2:0a16083193a4 64 _spi.write(0xE8);
dreschpe 0:da1bf437cbc1 65 break;
dreschpe 0:da1bf437cbc1 66 }
dreschpe 8:07ad6a48a85d 67 _cs = 1;
dreschpe 0:da1bf437cbc1 68 WindowMax();
dreschpe 8:07ad6a48a85d 69 }
dreschpe 0:da1bf437cbc1 70
dreschpe 0:da1bf437cbc1 71
dreschpe 0:da1bf437cbc1 72 // write command to tft register
dreschpe 0:da1bf437cbc1 73
dreschpe 0:da1bf437cbc1 74 void SPI_TFT_ILI9341::wr_cmd(unsigned char cmd)
dreschpe 0:da1bf437cbc1 75 {
dreschpe 0:da1bf437cbc1 76 _dc = 0;
dreschpe 0:da1bf437cbc1 77 _cs = 0;
dreschpe 8:07ad6a48a85d 78 SPI1->DR = cmd;
dreschpe 8:07ad6a48a85d 79 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 0:da1bf437cbc1 80 _dc = 1;
dreschpe 0:da1bf437cbc1 81 }
dreschpe 0:da1bf437cbc1 82
dreschpe 0:da1bf437cbc1 83
dreschpe 0:da1bf437cbc1 84
dreschpe 0:da1bf437cbc1 85 void SPI_TFT_ILI9341::wr_dat(unsigned char dat)
dreschpe 0:da1bf437cbc1 86 {
dreschpe 8:07ad6a48a85d 87 SPI1->DR = dat;
dreschpe 8:07ad6a48a85d 88 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 0:da1bf437cbc1 89 }
dreschpe 0:da1bf437cbc1 90
dreschpe 8:07ad6a48a85d 91 // the ILI9341 can read
dreschpe 6:fe07ae8329f7 92
dreschpe 6:fe07ae8329f7 93 char SPI_TFT_ILI9341::rd_byte(unsigned char cmd)
dreschpe 6:fe07ae8329f7 94 {
dreschpe 6:fe07ae8329f7 95 char r;
dreschpe 6:fe07ae8329f7 96 _dc = 0;
dreschpe 6:fe07ae8329f7 97 _cs = 0;
dreschpe 8:07ad6a48a85d 98 SPI1->DR = cmd;
dreschpe 8:07ad6a48a85d 99 do{}while(SPI1->SR & 0x02 == 0); // wait for SPI send
dreschpe 8:07ad6a48a85d 100 SPI1->DR = 0xFF;
dreschpe 8:07ad6a48a85d 101 do{}while(SPI1->SR & 0x02 == 0); // wait for SPI send
dreschpe 8:07ad6a48a85d 102 r = SPI1->DR;
dreschpe 6:fe07ae8329f7 103 _cs = 1;
dreschpe 6:fe07ae8329f7 104 return(r);
dreschpe 6:fe07ae8329f7 105 }
dreschpe 0:da1bf437cbc1 106
dreschpe 6:fe07ae8329f7 107 // read 32 bit
dreschpe 6:fe07ae8329f7 108 int SPI_TFT_ILI9341::rd_32(unsigned char cmd)
dreschpe 6:fe07ae8329f7 109 {
dreschpe 6:fe07ae8329f7 110 int d;
dreschpe 6:fe07ae8329f7 111 char r;
dreschpe 6:fe07ae8329f7 112 _dc = 0;
dreschpe 6:fe07ae8329f7 113 _cs = 0;
dreschpe 6:fe07ae8329f7 114 d = cmd;
dreschpe 6:fe07ae8329f7 115 d = d << 1;
dreschpe 6:fe07ae8329f7 116 _spi.format(9,3); // we have to add a dummy clock cycle
dreschpe 6:fe07ae8329f7 117 _spi.write(d);
dreschpe 8:07ad6a48a85d 118 _spi.format(8,3);
dreschpe 6:fe07ae8329f7 119 _dc = 1;
dreschpe 6:fe07ae8329f7 120 r = _spi.write(0xff);
dreschpe 6:fe07ae8329f7 121 d = r;
dreschpe 6:fe07ae8329f7 122 r = _spi.write(0xff);
dreschpe 6:fe07ae8329f7 123 d = (d << 8) | r;
dreschpe 6:fe07ae8329f7 124 r = _spi.write(0xff);
dreschpe 6:fe07ae8329f7 125 d = (d << 8) | r;
dreschpe 6:fe07ae8329f7 126 r = _spi.write(0xff);
dreschpe 6:fe07ae8329f7 127 d = (d << 8) | r;
dreschpe 8:07ad6a48a85d 128 _cs = 1;
dreschpe 6:fe07ae8329f7 129 return(d);
dreschpe 6:fe07ae8329f7 130 }
dreschpe 0:da1bf437cbc1 131
dreschpe 6:fe07ae8329f7 132 int SPI_TFT_ILI9341::Read_ID(void){
dreschpe 6:fe07ae8329f7 133 int r;
dreschpe 6:fe07ae8329f7 134 r = rd_byte(0x0A);
dreschpe 6:fe07ae8329f7 135 r = rd_byte(0x0A);
dreschpe 6:fe07ae8329f7 136 r = rd_byte(0x0A);
dreschpe 6:fe07ae8329f7 137 r = rd_byte(0x0A);
dreschpe 6:fe07ae8329f7 138 return(r);
dreschpe 6:fe07ae8329f7 139 }
dreschpe 0:da1bf437cbc1 140
dreschpe 0:da1bf437cbc1 141
dreschpe 1:6d6125e88de7 142 // Init code based on MI0283QT datasheet
dreschpe 8:07ad6a48a85d 143 // this code is called only at start
dreschpe 8:07ad6a48a85d 144 // no need to be optimized
dreschpe 1:6d6125e88de7 145
dreschpe 0:da1bf437cbc1 146 void SPI_TFT_ILI9341::tft_reset()
dreschpe 0:da1bf437cbc1 147 {
dreschpe 2:0a16083193a4 148 _spi.format(8,3); // 8 bit spi mode 3
dreschpe 8:07ad6a48a85d 149 _spi.frequency(8000000); // 8 Mhz SPI clock - 32 / 4
dreschpe 0:da1bf437cbc1 150 _cs = 1; // cs high
dreschpe 8:07ad6a48a85d 151 _dc = 1; // dc high
dreschpe 0:da1bf437cbc1 152 _reset = 0; // display reset
dreschpe 0:da1bf437cbc1 153
dreschpe 0:da1bf437cbc1 154 wait_us(50);
dreschpe 1:6d6125e88de7 155 _reset = 1; // end hardware reset
dreschpe 0:da1bf437cbc1 156 wait_ms(5);
dreschpe 8:07ad6a48a85d 157
dreschpe 8:07ad6a48a85d 158 wr_cmd(0x01); // SW reset
dreschpe 1:6d6125e88de7 159 wait_ms(5);
dreschpe 8:07ad6a48a85d 160 wr_cmd(0x28); // display off
dreschpe 0:da1bf437cbc1 161
dreschpe 0:da1bf437cbc1 162 /* Start Initial Sequence ----------------------------------------------------*/
dreschpe 8:07ad6a48a85d 163 wr_cmd(0xCF);
dreschpe 1:6d6125e88de7 164 _spi.write(0x00);
dreschpe 1:6d6125e88de7 165 _spi.write(0x83);
dreschpe 1:6d6125e88de7 166 _spi.write(0x30);
dreschpe 1:6d6125e88de7 167 _cs = 1;
dreschpe 8:07ad6a48a85d 168
dreschpe 8:07ad6a48a85d 169 wr_cmd(0xED);
dreschpe 1:6d6125e88de7 170 _spi.write(0x64);
dreschpe 1:6d6125e88de7 171 _spi.write(0x03);
dreschpe 1:6d6125e88de7 172 _spi.write(0x12);
dreschpe 1:6d6125e88de7 173 _spi.write(0x81);
dreschpe 1:6d6125e88de7 174 _cs = 1;
dreschpe 8:07ad6a48a85d 175
dreschpe 8:07ad6a48a85d 176 wr_cmd(0xE8);
dreschpe 1:6d6125e88de7 177 _spi.write(0x85);
dreschpe 1:6d6125e88de7 178 _spi.write(0x01);
dreschpe 1:6d6125e88de7 179 _spi.write(0x79);
dreschpe 1:6d6125e88de7 180 _cs = 1;
dreschpe 8:07ad6a48a85d 181
dreschpe 8:07ad6a48a85d 182 wr_cmd(0xCB);
dreschpe 0:da1bf437cbc1 183 _spi.write(0x39);
dreschpe 0:da1bf437cbc1 184 _spi.write(0x2C);
dreschpe 0:da1bf437cbc1 185 _spi.write(0x00);
dreschpe 0:da1bf437cbc1 186 _spi.write(0x34);
dreschpe 0:da1bf437cbc1 187 _spi.write(0x02);
dreschpe 0:da1bf437cbc1 188 _cs = 1;
dreschpe 8:07ad6a48a85d 189
dreschpe 8:07ad6a48a85d 190 wr_cmd(0xF7);
dreschpe 1:6d6125e88de7 191 _spi.write(0x20);
dreschpe 0:da1bf437cbc1 192 _cs = 1;
dreschpe 8:07ad6a48a85d 193
dreschpe 8:07ad6a48a85d 194 wr_cmd(0xEA);
dreschpe 1:6d6125e88de7 195 _spi.write(0x00);
dreschpe 1:6d6125e88de7 196 _spi.write(0x00);
dreschpe 0:da1bf437cbc1 197 _cs = 1;
dreschpe 8:07ad6a48a85d 198
dreschpe 0:da1bf437cbc1 199 wr_cmd(0xC0); // POWER_CONTROL_1
dreschpe 1:6d6125e88de7 200 _spi.write(0x26);
dreschpe 0:da1bf437cbc1 201 _cs = 1;
dreschpe 8:07ad6a48a85d 202
dreschpe 0:da1bf437cbc1 203 wr_cmd(0xC1); // POWER_CONTROL_2
dreschpe 0:da1bf437cbc1 204 _spi.write(0x11);
dreschpe 0:da1bf437cbc1 205 _cs = 1;
dreschpe 8:07ad6a48a85d 206
dreschpe 0:da1bf437cbc1 207 wr_cmd(0xC5); // VCOM_CONTROL_1
dreschpe 1:6d6125e88de7 208 _spi.write(0x35);
dreschpe 1:6d6125e88de7 209 _spi.write(0x3E);
dreschpe 0:da1bf437cbc1 210 _cs = 1;
dreschpe 8:07ad6a48a85d 211
dreschpe 0:da1bf437cbc1 212 wr_cmd(0xC7); // VCOM_CONTROL_2
dreschpe 1:6d6125e88de7 213 _spi.write(0xBE);
dreschpe 8:07ad6a48a85d 214 _cs = 1;
dreschpe 8:07ad6a48a85d 215
dreschpe 0:da1bf437cbc1 216 wr_cmd(0x36); // MEMORY_ACCESS_CONTROL
dreschpe 0:da1bf437cbc1 217 _spi.write(0x48);
dreschpe 8:07ad6a48a85d 218 _cs = 1;
dreschpe 8:07ad6a48a85d 219
dreschpe 1:6d6125e88de7 220 wr_cmd(0x3A); // COLMOD_PIXEL_FORMAT_SET
dreschpe 8:07ad6a48a85d 221 _spi.write(0x55); // 16 bit pixel
dreschpe 1:6d6125e88de7 222 _cs = 1;
dreschpe 8:07ad6a48a85d 223
dreschpe 1:6d6125e88de7 224 wr_cmd(0xB1); // Frame Rate
dreschpe 1:6d6125e88de7 225 _spi.write(0x00);
dreschpe 8:07ad6a48a85d 226 _spi.write(0x1B);
dreschpe 1:6d6125e88de7 227 _cs = 1;
dreschpe 8:07ad6a48a85d 228
dreschpe 1:6d6125e88de7 229 wr_cmd(0xF2); // Gamma Function Disable
dreschpe 1:6d6125e88de7 230 _spi.write(0x08);
dreschpe 8:07ad6a48a85d 231 _cs = 1;
dreschpe 8:07ad6a48a85d 232
dreschpe 8:07ad6a48a85d 233 wr_cmd(0x26);
dreschpe 1:6d6125e88de7 234 _spi.write(0x01); // gamma set for curve 01/2/04/08
dreschpe 8:07ad6a48a85d 235 _cs = 1;
dreschpe 8:07ad6a48a85d 236
dreschpe 1:6d6125e88de7 237 wr_cmd(0xE0); // positive gamma correction
dreschpe 8:07ad6a48a85d 238 _spi.write(0x1F);
dreschpe 8:07ad6a48a85d 239 _spi.write(0x1A);
dreschpe 8:07ad6a48a85d 240 _spi.write(0x18);
dreschpe 8:07ad6a48a85d 241 _spi.write(0x0A);
dreschpe 8:07ad6a48a85d 242 _spi.write(0x0F);
dreschpe 8:07ad6a48a85d 243 _spi.write(0x06);
dreschpe 8:07ad6a48a85d 244 _spi.write(0x45);
dreschpe 8:07ad6a48a85d 245 _spi.write(0x87);
dreschpe 8:07ad6a48a85d 246 _spi.write(0x32);
dreschpe 8:07ad6a48a85d 247 _spi.write(0x0A);
dreschpe 1:6d6125e88de7 248 _spi.write(0x07);
dreschpe 8:07ad6a48a85d 249 _spi.write(0x02);
dreschpe 8:07ad6a48a85d 250 _spi.write(0x07);
dreschpe 8:07ad6a48a85d 251 _spi.write(0x05);
dreschpe 1:6d6125e88de7 252 _spi.write(0x00);
dreschpe 1:6d6125e88de7 253 _cs = 1;
dreschpe 8:07ad6a48a85d 254
dreschpe 1:6d6125e88de7 255 wr_cmd(0xE1); // negativ gamma correction
dreschpe 8:07ad6a48a85d 256 _spi.write(0x00);
dreschpe 8:07ad6a48a85d 257 _spi.write(0x25);
dreschpe 8:07ad6a48a85d 258 _spi.write(0x27);
dreschpe 8:07ad6a48a85d 259 _spi.write(0x05);
dreschpe 8:07ad6a48a85d 260 _spi.write(0x10);
dreschpe 8:07ad6a48a85d 261 _spi.write(0x09);
dreschpe 8:07ad6a48a85d 262 _spi.write(0x3A);
dreschpe 8:07ad6a48a85d 263 _spi.write(0x78);
dreschpe 8:07ad6a48a85d 264 _spi.write(0x4D);
dreschpe 8:07ad6a48a85d 265 _spi.write(0x05);
dreschpe 8:07ad6a48a85d 266 _spi.write(0x18);
dreschpe 8:07ad6a48a85d 267 _spi.write(0x0D);
dreschpe 1:6d6125e88de7 268 _spi.write(0x38);
dreschpe 8:07ad6a48a85d 269 _spi.write(0x3A);
dreschpe 1:6d6125e88de7 270 _spi.write(0x1F);
dreschpe 1:6d6125e88de7 271 _cs = 1;
dreschpe 8:07ad6a48a85d 272
dreschpe 1:6d6125e88de7 273 WindowMax ();
dreschpe 8:07ad6a48a85d 274
dreschpe 1:6d6125e88de7 275 //wr_cmd(0x34); // tearing effect off
dreschpe 1:6d6125e88de7 276 //_cs = 1;
dreschpe 8:07ad6a48a85d 277
dreschpe 1:6d6125e88de7 278 //wr_cmd(0x35); // tearing effect on
dreschpe 1:6d6125e88de7 279 //_cs = 1;
dreschpe 8:07ad6a48a85d 280
dreschpe 1:6d6125e88de7 281 wr_cmd(0xB7); // entry mode
dreschpe 1:6d6125e88de7 282 _spi.write(0x07);
dreschpe 1:6d6125e88de7 283 _cs = 1;
dreschpe 8:07ad6a48a85d 284
dreschpe 1:6d6125e88de7 285 wr_cmd(0xB6); // display function control
dreschpe 1:6d6125e88de7 286 _spi.write(0x0A);
dreschpe 1:6d6125e88de7 287 _spi.write(0x82);
dreschpe 1:6d6125e88de7 288 _spi.write(0x27);
dreschpe 1:6d6125e88de7 289 _spi.write(0x00);
dreschpe 1:6d6125e88de7 290 _cs = 1;
dreschpe 8:07ad6a48a85d 291
dreschpe 1:6d6125e88de7 292 wr_cmd(0x11); // sleep out
dreschpe 1:6d6125e88de7 293 _cs = 1;
dreschpe 8:07ad6a48a85d 294
dreschpe 1:6d6125e88de7 295 wait_ms(100);
dreschpe 8:07ad6a48a85d 296
dreschpe 1:6d6125e88de7 297 wr_cmd(0x29); // display on
dreschpe 1:6d6125e88de7 298 _cs = 1;
dreschpe 8:07ad6a48a85d 299
dreschpe 1:6d6125e88de7 300 wait_ms(100);
dreschpe 8:07ad6a48a85d 301
dreschpe 8:07ad6a48a85d 302 // Configure the DMA controller init-structure
dreschpe 8:07ad6a48a85d 303 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // SPI1 is using DMA 1
dreschpe 8:07ad6a48a85d 304 DMA_StructInit(&DMA_InitStructure);
dreschpe 8:07ad6a48a85d 305 DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &(SPI1->DR);
dreschpe 8:07ad6a48a85d 306 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
dreschpe 8:07ad6a48a85d 307 DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
dreschpe 8:07ad6a48a85d 308 DMA_InitStructure.DMA_BufferSize = 0;
dreschpe 8:07ad6a48a85d 309 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
dreschpe 8:07ad6a48a85d 310 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
dreschpe 8:07ad6a48a85d 311 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dreschpe 8:07ad6a48a85d 312 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
dreschpe 8:07ad6a48a85d 313 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
dreschpe 1:6d6125e88de7 314 }
dreschpe 0:da1bf437cbc1 315
dreschpe 0:da1bf437cbc1 316
dreschpe 8:07ad6a48a85d 317 // speed optimized
dreschpe 8:07ad6a48a85d 318 // write direct to SPI1 register !
dreschpe 0:da1bf437cbc1 319 void SPI_TFT_ILI9341::pixel(int x, int y, int color)
dreschpe 0:da1bf437cbc1 320 {
dreschpe 8:07ad6a48a85d 321 _dc = 0;
dreschpe 8:07ad6a48a85d 322 _cs = 0;
dreschpe 8:07ad6a48a85d 323 SPI1->DR = 0x2A;
dreschpe 8:07ad6a48a85d 324 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 325 _dc = 1;
dreschpe 8:07ad6a48a85d 326 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 327 SPI1->DR = x;
dreschpe 8:07ad6a48a85d 328 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 329
dreschpe 0:da1bf437cbc1 330 _cs = 1;
dreschpe 8:07ad6a48a85d 331 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 8:07ad6a48a85d 332 _dc = 0;
dreschpe 8:07ad6a48a85d 333 _cs = 0;
dreschpe 8:07ad6a48a85d 334 SPI1->DR = 0x2B;
dreschpe 8:07ad6a48a85d 335 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 336 _dc = 1;
dreschpe 8:07ad6a48a85d 337 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 338 SPI1->DR = y;
dreschpe 8:07ad6a48a85d 339 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 0:da1bf437cbc1 340 _cs = 1;
dreschpe 8:07ad6a48a85d 341 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 8:07ad6a48a85d 342 _dc = 0;
dreschpe 8:07ad6a48a85d 343 _cs = 0;
dreschpe 8:07ad6a48a85d 344 SPI1->DR = 0x2C; // send pixel
dreschpe 8:07ad6a48a85d 345 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 346 _dc = 1;
dreschpe 8:07ad6a48a85d 347 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 348 SPI1->DR = color;
dreschpe 8:07ad6a48a85d 349 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 350
dreschpe 8:07ad6a48a85d 351 _cs = 1;
dreschpe 8:07ad6a48a85d 352 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 353 }
dreschpe 0:da1bf437cbc1 354
dreschpe 8:07ad6a48a85d 355 // optimized
dreschpe 8:07ad6a48a85d 356 // write direct to SPI1 register !
dreschpe 0:da1bf437cbc1 357 void SPI_TFT_ILI9341::window (unsigned int x, unsigned int y, unsigned int w, unsigned int h)
dreschpe 0:da1bf437cbc1 358 {
dreschpe 8:07ad6a48a85d 359 _dc = 0;
dreschpe 8:07ad6a48a85d 360 _cs = 0;
dreschpe 8:07ad6a48a85d 361 SPI1->DR = 0x2A;
dreschpe 8:07ad6a48a85d 362 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 363 _dc = 1;
dreschpe 8:07ad6a48a85d 364 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 365 SPI1->DR = x ;
dreschpe 8:07ad6a48a85d 366 do{}while((SPI1->SR & 0x02) == 0); // wait for SPI TX buffer free
dreschpe 8:07ad6a48a85d 367 SPI1->DR = (x+w-1);
dreschpe 8:07ad6a48a85d 368 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 0:da1bf437cbc1 369 _cs = 1;
dreschpe 8:07ad6a48a85d 370 _dc = 0;
dreschpe 8:07ad6a48a85d 371 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 8:07ad6a48a85d 372 _cs = 0;
dreschpe 8:07ad6a48a85d 373 SPI1->DR = 0x2B;
dreschpe 8:07ad6a48a85d 374 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 375 _dc = 1;
dreschpe 8:07ad6a48a85d 376 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 377 SPI1->DR = y ;
dreschpe 8:07ad6a48a85d 378 do{}while((SPI1->SR & 0x02) == 0); // wait for SPI TX buffer free
dreschpe 8:07ad6a48a85d 379 SPI1->DR = (y+h-1);
dreschpe 8:07ad6a48a85d 380 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 0:da1bf437cbc1 381 _cs = 1;
dreschpe 8:07ad6a48a85d 382 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 383 }
dreschpe 0:da1bf437cbc1 384
dreschpe 0:da1bf437cbc1 385
dreschpe 0:da1bf437cbc1 386 void SPI_TFT_ILI9341::WindowMax (void)
dreschpe 0:da1bf437cbc1 387 {
dreschpe 0:da1bf437cbc1 388 window (0, 0, width(), height());
dreschpe 0:da1bf437cbc1 389 }
dreschpe 0:da1bf437cbc1 390
dreschpe 8:07ad6a48a85d 391 // optimized
dreschpe 8:07ad6a48a85d 392 // use DMA to transfer pixel data to the screen
dreschpe 0:da1bf437cbc1 393 void SPI_TFT_ILI9341::cls (void)
dreschpe 0:da1bf437cbc1 394 {
dreschpe 0:da1bf437cbc1 395 int pixel = ( width() * height());
dreschpe 0:da1bf437cbc1 396 WindowMax();
dreschpe 8:07ad6a48a85d 397 _dc = 0;
dreschpe 8:07ad6a48a85d 398 _cs = 0;
dreschpe 8:07ad6a48a85d 399 SPI1->DR = 0x2C; // send pixel
dreschpe 8:07ad6a48a85d 400 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 401 _dc = 1;
dreschpe 8:07ad6a48a85d 402 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 403
dreschpe 8:07ad6a48a85d 404 // set up the DMA structure for single byte
dreschpe 8:07ad6a48a85d 405 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &_background;
dreschpe 8:07ad6a48a85d 406 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
dreschpe 8:07ad6a48a85d 407 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA
dreschpe 8:07ad6a48a85d 408 // we have to send 2 blocks of pixel date, because the DMA counter can only transfer 64k
dreschpe 8:07ad6a48a85d 409 DMA_SetCurrDataCounter(DMA1_Channel3, 38400); // 1.half of screen
dreschpe 8:07ad6a48a85d 410 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE);
dreschpe 8:07ad6a48a85d 411 DMA_Cmd(DMA1_Channel3, ENABLE);
dreschpe 8:07ad6a48a85d 412 do{
dreschpe 8:07ad6a48a85d 413 }while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer
dreschpe 8:07ad6a48a85d 414 DMA_Cmd(DMA1_Channel3, DISABLE);
dreschpe 8:07ad6a48a85d 415 DMA_SetCurrDataCounter(DMA1_Channel3, 38400); // 2.half of screen
dreschpe 8:07ad6a48a85d 416 DMA_Cmd(DMA1_Channel3, ENABLE);
dreschpe 8:07ad6a48a85d 417 do{
dreschpe 8:07ad6a48a85d 418 }while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer
dreschpe 8:07ad6a48a85d 419 DMA_Cmd(DMA1_Channel3, DISABLE);
dreschpe 8:07ad6a48a85d 420 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 421 _cs = 1;
dreschpe 8:07ad6a48a85d 422 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 423 }
dreschpe 0:da1bf437cbc1 424
dreschpe 0:da1bf437cbc1 425
dreschpe 0:da1bf437cbc1 426 void SPI_TFT_ILI9341::circle(int x0, int y0, int r, int color)
dreschpe 0:da1bf437cbc1 427 {
dreschpe 0:da1bf437cbc1 428
mazgch 3:3d7298360e45 429 int x = -r, y = 0, err = 2-2*r, e2;
mazgch 3:3d7298360e45 430 do {
mazgch 3:3d7298360e45 431 pixel(x0-x, y0+y,color);
mazgch 3:3d7298360e45 432 pixel(x0+x, y0+y,color);
mazgch 3:3d7298360e45 433 pixel(x0+x, y0-y,color);
mazgch 3:3d7298360e45 434 pixel(x0-x, y0-y,color);
mazgch 3:3d7298360e45 435 e2 = err;
mazgch 3:3d7298360e45 436 if (e2 <= y) {
mazgch 3:3d7298360e45 437 err += ++y*2+1;
mazgch 3:3d7298360e45 438 if (-x == y && e2 <= x) e2 = 0;
mazgch 3:3d7298360e45 439 }
mazgch 3:3d7298360e45 440 if (e2 > x) err += ++x*2+1;
mazgch 3:3d7298360e45 441 } while (x <= 0);
dreschpe 4:f018e272220b 442
dreschpe 0:da1bf437cbc1 443 }
dreschpe 0:da1bf437cbc1 444
mazgch 3:3d7298360e45 445 void SPI_TFT_ILI9341::fillcircle(int x0, int y0, int r, int color)
dreschpe 0:da1bf437cbc1 446 {
mazgch 3:3d7298360e45 447 int x = -r, y = 0, err = 2-2*r, e2;
mazgch 3:3d7298360e45 448 do {
mazgch 3:3d7298360e45 449 vline(x0-x, y0-y, y0+y, color);
mazgch 3:3d7298360e45 450 vline(x0+x, y0-y, y0+y, color);
mazgch 3:3d7298360e45 451 e2 = err;
mazgch 3:3d7298360e45 452 if (e2 <= y) {
mazgch 3:3d7298360e45 453 err += ++y*2+1;
mazgch 3:3d7298360e45 454 if (-x == y && e2 <= x) e2 = 0;
mazgch 3:3d7298360e45 455 }
mazgch 3:3d7298360e45 456 if (e2 > x) err += ++x*2+1;
mazgch 3:3d7298360e45 457 } while (x <= 0);
dreschpe 0:da1bf437cbc1 458 }
dreschpe 0:da1bf437cbc1 459
dreschpe 0:da1bf437cbc1 460
dreschpe 8:07ad6a48a85d 461 // optimized for speed
dreschpe 8:07ad6a48a85d 462 // use SPI1 register access !!
dreschpe 0:da1bf437cbc1 463 void SPI_TFT_ILI9341::hline(int x0, int x1, int y, int color)
dreschpe 0:da1bf437cbc1 464 {
dreschpe 0:da1bf437cbc1 465 int w;
dreschpe 0:da1bf437cbc1 466 w = x1 - x0 + 1;
dreschpe 0:da1bf437cbc1 467 window(x0,y,w,1);
dreschpe 5:55aed13f2630 468 wr_cmd(0x2C); // send pixel
dreschpe 8:07ad6a48a85d 469
dreschpe 8:07ad6a48a85d 470 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 471
dreschpe 5:55aed13f2630 472 int j;
dreschpe 5:55aed13f2630 473 for (j=0; j<w; j++) {
dreschpe 8:07ad6a48a85d 474 SPI1->DR = color;
dreschpe 8:07ad6a48a85d 475 do{}while((SPI1->SR & 0x02) == 0); // wait for SPI TX buffer free
dreschpe 0:da1bf437cbc1 476 }
dreschpe 8:07ad6a48a85d 477 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 478 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 479 _cs = 1;
dreschpe 0:da1bf437cbc1 480 WindowMax();
dreschpe 0:da1bf437cbc1 481 return;
dreschpe 0:da1bf437cbc1 482 }
dreschpe 0:da1bf437cbc1 483
dreschpe 0:da1bf437cbc1 484 void SPI_TFT_ILI9341::vline(int x, int y0, int y1, int color)
dreschpe 0:da1bf437cbc1 485 {
dreschpe 0:da1bf437cbc1 486 int h;
dreschpe 0:da1bf437cbc1 487 h = y1 - y0 + 1;
dreschpe 0:da1bf437cbc1 488 window(x,y0,1,h);
dreschpe 5:55aed13f2630 489 wr_cmd(0x2C); // send pixel
dreschpe 8:07ad6a48a85d 490
dreschpe 0:da1bf437cbc1 491 _spi.format(16,3); // switch to 16 bit Mode 3
dreschpe 0:da1bf437cbc1 492 for (int y=0; y<h; y++) {
dreschpe 0:da1bf437cbc1 493 _spi.write(color);
dreschpe 0:da1bf437cbc1 494 }
dreschpe 8:07ad6a48a85d 495 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 496 _cs = 1;
dreschpe 0:da1bf437cbc1 497 WindowMax();
dreschpe 0:da1bf437cbc1 498 return;
dreschpe 0:da1bf437cbc1 499 }
dreschpe 0:da1bf437cbc1 500
dreschpe 0:da1bf437cbc1 501
dreschpe 0:da1bf437cbc1 502
dreschpe 0:da1bf437cbc1 503 void SPI_TFT_ILI9341::line(int x0, int y0, int x1, int y1, int color)
dreschpe 0:da1bf437cbc1 504 {
dreschpe 0:da1bf437cbc1 505 //WindowMax();
dreschpe 0:da1bf437cbc1 506 int dx = 0, dy = 0;
dreschpe 0:da1bf437cbc1 507 int dx_sym = 0, dy_sym = 0;
dreschpe 0:da1bf437cbc1 508 int dx_x2 = 0, dy_x2 = 0;
dreschpe 0:da1bf437cbc1 509 int di = 0;
dreschpe 0:da1bf437cbc1 510
dreschpe 0:da1bf437cbc1 511 dx = x1-x0;
dreschpe 0:da1bf437cbc1 512 dy = y1-y0;
dreschpe 0:da1bf437cbc1 513
dreschpe 0:da1bf437cbc1 514 if (dx == 0) { /* vertical line */
dreschpe 0:da1bf437cbc1 515 if (y1 > y0) vline(x0,y0,y1,color);
dreschpe 0:da1bf437cbc1 516 else vline(x0,y1,y0,color);
dreschpe 0:da1bf437cbc1 517 return;
dreschpe 0:da1bf437cbc1 518 }
dreschpe 0:da1bf437cbc1 519
dreschpe 0:da1bf437cbc1 520 if (dx > 0) {
dreschpe 0:da1bf437cbc1 521 dx_sym = 1;
dreschpe 0:da1bf437cbc1 522 } else {
dreschpe 0:da1bf437cbc1 523 dx_sym = -1;
dreschpe 0:da1bf437cbc1 524 }
dreschpe 0:da1bf437cbc1 525 if (dy == 0) { /* horizontal line */
dreschpe 0:da1bf437cbc1 526 if (x1 > x0) hline(x0,x1,y0,color);
dreschpe 0:da1bf437cbc1 527 else hline(x1,x0,y0,color);
dreschpe 0:da1bf437cbc1 528 return;
dreschpe 0:da1bf437cbc1 529 }
dreschpe 0:da1bf437cbc1 530
dreschpe 0:da1bf437cbc1 531 if (dy > 0) {
dreschpe 0:da1bf437cbc1 532 dy_sym = 1;
dreschpe 0:da1bf437cbc1 533 } else {
dreschpe 0:da1bf437cbc1 534 dy_sym = -1;
dreschpe 0:da1bf437cbc1 535 }
dreschpe 0:da1bf437cbc1 536
dreschpe 0:da1bf437cbc1 537 dx = dx_sym*dx;
dreschpe 0:da1bf437cbc1 538 dy = dy_sym*dy;
dreschpe 0:da1bf437cbc1 539
dreschpe 0:da1bf437cbc1 540 dx_x2 = dx*2;
dreschpe 0:da1bf437cbc1 541 dy_x2 = dy*2;
dreschpe 0:da1bf437cbc1 542
dreschpe 0:da1bf437cbc1 543 if (dx >= dy) {
dreschpe 0:da1bf437cbc1 544 di = dy_x2 - dx;
dreschpe 0:da1bf437cbc1 545 while (x0 != x1) {
dreschpe 0:da1bf437cbc1 546
dreschpe 0:da1bf437cbc1 547 pixel(x0, y0, color);
dreschpe 0:da1bf437cbc1 548 x0 += dx_sym;
dreschpe 0:da1bf437cbc1 549 if (di<0) {
dreschpe 0:da1bf437cbc1 550 di += dy_x2;
dreschpe 0:da1bf437cbc1 551 } else {
dreschpe 0:da1bf437cbc1 552 di += dy_x2 - dx_x2;
dreschpe 0:da1bf437cbc1 553 y0 += dy_sym;
dreschpe 0:da1bf437cbc1 554 }
dreschpe 0:da1bf437cbc1 555 }
dreschpe 0:da1bf437cbc1 556 pixel(x0, y0, color);
dreschpe 0:da1bf437cbc1 557 } else {
dreschpe 0:da1bf437cbc1 558 di = dx_x2 - dy;
dreschpe 0:da1bf437cbc1 559 while (y0 != y1) {
dreschpe 0:da1bf437cbc1 560 pixel(x0, y0, color);
dreschpe 0:da1bf437cbc1 561 y0 += dy_sym;
dreschpe 0:da1bf437cbc1 562 if (di < 0) {
dreschpe 0:da1bf437cbc1 563 di += dx_x2;
dreschpe 0:da1bf437cbc1 564 } else {
dreschpe 0:da1bf437cbc1 565 di += dx_x2 - dy_x2;
dreschpe 0:da1bf437cbc1 566 x0 += dx_sym;
dreschpe 0:da1bf437cbc1 567 }
dreschpe 0:da1bf437cbc1 568 }
dreschpe 0:da1bf437cbc1 569 pixel(x0, y0, color);
dreschpe 0:da1bf437cbc1 570 }
dreschpe 0:da1bf437cbc1 571 return;
dreschpe 0:da1bf437cbc1 572 }
dreschpe 0:da1bf437cbc1 573
dreschpe 0:da1bf437cbc1 574
dreschpe 0:da1bf437cbc1 575 void SPI_TFT_ILI9341::rect(int x0, int y0, int x1, int y1, int color)
dreschpe 0:da1bf437cbc1 576 {
dreschpe 0:da1bf437cbc1 577
dreschpe 0:da1bf437cbc1 578 if (x1 > x0) hline(x0,x1,y0,color);
dreschpe 0:da1bf437cbc1 579 else hline(x1,x0,y0,color);
dreschpe 0:da1bf437cbc1 580
dreschpe 0:da1bf437cbc1 581 if (y1 > y0) vline(x0,y0,y1,color);
dreschpe 0:da1bf437cbc1 582 else vline(x0,y1,y0,color);
dreschpe 0:da1bf437cbc1 583
dreschpe 0:da1bf437cbc1 584 if (x1 > x0) hline(x0,x1,y1,color);
dreschpe 0:da1bf437cbc1 585 else hline(x1,x0,y1,color);
dreschpe 0:da1bf437cbc1 586
dreschpe 0:da1bf437cbc1 587 if (y1 > y0) vline(x1,y0,y1,color);
dreschpe 0:da1bf437cbc1 588 else vline(x1,y1,y0,color);
dreschpe 0:da1bf437cbc1 589
dreschpe 0:da1bf437cbc1 590 return;
dreschpe 0:da1bf437cbc1 591 }
dreschpe 0:da1bf437cbc1 592
dreschpe 0:da1bf437cbc1 593
dreschpe 0:da1bf437cbc1 594
dreschpe 8:07ad6a48a85d 595 // optimized for speed
dreschpe 8:07ad6a48a85d 596 // use DMA
dreschpe 0:da1bf437cbc1 597 void SPI_TFT_ILI9341::fillrect(int x0, int y0, int x1, int y1, int color)
dreschpe 0:da1bf437cbc1 598 {
dreschpe 0:da1bf437cbc1 599
dreschpe 0:da1bf437cbc1 600 int h = y1 - y0 + 1;
dreschpe 0:da1bf437cbc1 601 int w = x1 - x0 + 1;
dreschpe 0:da1bf437cbc1 602 int pixel = h * w;
dreschpe 8:07ad6a48a85d 603 unsigned int dma_transfer;
dreschpe 0:da1bf437cbc1 604 window(x0,y0,w,h);
dreschpe 8:07ad6a48a85d 605 wr_cmd(0x2C); // send pixel
dreschpe 8:07ad6a48a85d 606 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 607 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &color;
dreschpe 8:07ad6a48a85d 608 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
dreschpe 8:07ad6a48a85d 609 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA
dreschpe 8:07ad6a48a85d 610 do{
dreschpe 8:07ad6a48a85d 611 if(pixel < 0x10000) {
dreschpe 8:07ad6a48a85d 612 dma_transfer = pixel;
dreschpe 8:07ad6a48a85d 613 pixel = 0;
dreschpe 8:07ad6a48a85d 614 }
dreschpe 8:07ad6a48a85d 615 else {
dreschpe 8:07ad6a48a85d 616 dma_transfer = 0xffff;
dreschpe 8:07ad6a48a85d 617 pixel = pixel - 0xffff;
dreschpe 8:07ad6a48a85d 618 }
dreschpe 8:07ad6a48a85d 619 DMA_SetCurrDataCounter(DMA1_Channel3, dma_transfer);
dreschpe 8:07ad6a48a85d 620 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE);
dreschpe 8:07ad6a48a85d 621 DMA_Cmd(DMA1_Channel3, ENABLE);
dreschpe 8:07ad6a48a85d 622 do{
dreschpe 8:07ad6a48a85d 623 }while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer
dreschpe 8:07ad6a48a85d 624 DMA_Cmd(DMA1_Channel3, DISABLE);
dreschpe 8:07ad6a48a85d 625 }while(pixel > 0);
dreschpe 8:07ad6a48a85d 626 do{}while((SPI1->SR & 0x80) == 0x80); // wait for SPI send
dreschpe 8:07ad6a48a85d 627 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 628 _cs = 1;
dreschpe 0:da1bf437cbc1 629 WindowMax();
dreschpe 0:da1bf437cbc1 630 return;
dreschpe 0:da1bf437cbc1 631 }
dreschpe 0:da1bf437cbc1 632
dreschpe 0:da1bf437cbc1 633
dreschpe 0:da1bf437cbc1 634 void SPI_TFT_ILI9341::locate(int x, int y)
dreschpe 0:da1bf437cbc1 635 {
dreschpe 0:da1bf437cbc1 636 char_x = x;
dreschpe 0:da1bf437cbc1 637 char_y = y;
dreschpe 0:da1bf437cbc1 638 }
dreschpe 0:da1bf437cbc1 639
dreschpe 0:da1bf437cbc1 640
dreschpe 0:da1bf437cbc1 641
dreschpe 0:da1bf437cbc1 642 int SPI_TFT_ILI9341::columns()
dreschpe 0:da1bf437cbc1 643 {
dreschpe 0:da1bf437cbc1 644 return width() / font[1];
dreschpe 0:da1bf437cbc1 645 }
dreschpe 0:da1bf437cbc1 646
dreschpe 0:da1bf437cbc1 647
dreschpe 0:da1bf437cbc1 648
dreschpe 0:da1bf437cbc1 649 int SPI_TFT_ILI9341::rows()
dreschpe 0:da1bf437cbc1 650 {
dreschpe 0:da1bf437cbc1 651 return height() / font[2];
dreschpe 0:da1bf437cbc1 652 }
dreschpe 0:da1bf437cbc1 653
dreschpe 0:da1bf437cbc1 654
dreschpe 0:da1bf437cbc1 655
dreschpe 0:da1bf437cbc1 656 int SPI_TFT_ILI9341::_putc(int value)
dreschpe 0:da1bf437cbc1 657 {
dreschpe 0:da1bf437cbc1 658 if (value == '\n') { // new line
dreschpe 0:da1bf437cbc1 659 char_x = 0;
dreschpe 0:da1bf437cbc1 660 char_y = char_y + font[2];
dreschpe 0:da1bf437cbc1 661 if (char_y >= height() - font[2]) {
dreschpe 0:da1bf437cbc1 662 char_y = 0;
dreschpe 0:da1bf437cbc1 663 }
dreschpe 0:da1bf437cbc1 664 } else {
dreschpe 0:da1bf437cbc1 665 character(char_x, char_y, value);
dreschpe 0:da1bf437cbc1 666 }
dreschpe 0:da1bf437cbc1 667 return value;
dreschpe 0:da1bf437cbc1 668 }
dreschpe 0:da1bf437cbc1 669
dreschpe 0:da1bf437cbc1 670
dreschpe 8:07ad6a48a85d 671
dreschpe 0:da1bf437cbc1 672 void SPI_TFT_ILI9341::character(int x, int y, int c)
dreschpe 0:da1bf437cbc1 673 {
dreschpe 0:da1bf437cbc1 674 unsigned int hor,vert,offset,bpl,j,i,b;
dreschpe 0:da1bf437cbc1 675 unsigned char* zeichen;
dreschpe 0:da1bf437cbc1 676 unsigned char z,w;
dreschpe 8:07ad6a48a85d 677 unsigned int pixel;
dreschpe 8:07ad6a48a85d 678 unsigned int p;
dreschpe 8:07ad6a48a85d 679 unsigned int dma_count,dma_off;
dreschpe 8:07ad6a48a85d 680 uint16_t *buffer;
dreschpe 0:da1bf437cbc1 681
dreschpe 0:da1bf437cbc1 682 if ((c < 31) || (c > 127)) return; // test char range
dreschpe 0:da1bf437cbc1 683
dreschpe 0:da1bf437cbc1 684 // read font parameter from start of array
dreschpe 0:da1bf437cbc1 685 offset = font[0]; // bytes / char
dreschpe 0:da1bf437cbc1 686 hor = font[1]; // get hor size of font
dreschpe 0:da1bf437cbc1 687 vert = font[2]; // get vert size of font
dreschpe 0:da1bf437cbc1 688 bpl = font[3]; // bytes per line
dreschpe 0:da1bf437cbc1 689
dreschpe 0:da1bf437cbc1 690 if (char_x + hor > width()) {
dreschpe 0:da1bf437cbc1 691 char_x = 0;
dreschpe 0:da1bf437cbc1 692 char_y = char_y + vert;
dreschpe 0:da1bf437cbc1 693 if (char_y >= height() - font[2]) {
dreschpe 0:da1bf437cbc1 694 char_y = 0;
dreschpe 0:da1bf437cbc1 695 }
dreschpe 0:da1bf437cbc1 696 }
dreschpe 0:da1bf437cbc1 697 window(char_x, char_y,hor,vert); // char box
dreschpe 5:55aed13f2630 698 wr_cmd(0x2C); // send pixel
dreschpe 8:07ad6a48a85d 699 pixel = hor * vert; // calculate buffer size
dreschpe 8:07ad6a48a85d 700 SPI1->CR1 |= 1 << 11; // switch to 16 bit Mode
dreschpe 8:07ad6a48a85d 701 buffer = (uint16_t *) malloc (2*pixel); // we need a buffer for the 16 bit
dreschpe 8:07ad6a48a85d 702 if (buffer == NULL) { // there is no space
dreschpe 8:07ad6a48a85d 703 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
dreschpe 8:07ad6a48a85d 704 w = zeichen[0]; // width of actual char
dreschpe 8:07ad6a48a85d 705 for (j=0; j<vert; j++) { // vert line
dreschpe 8:07ad6a48a85d 706 for (i=0; i<hor; i++) { // horz line
dreschpe 8:07ad6a48a85d 707 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
dreschpe 8:07ad6a48a85d 708 b = 1 << (j & 0x07);
dreschpe 8:07ad6a48a85d 709 if (( z & b ) == 0x00) {
dreschpe 8:07ad6a48a85d 710 _spi.write(_background);
dreschpe 8:07ad6a48a85d 711 } else {
dreschpe 8:07ad6a48a85d 712 _spi.write(_foreground);
dreschpe 8:07ad6a48a85d 713 }
dreschpe 0:da1bf437cbc1 714 }
dreschpe 0:da1bf437cbc1 715 }
dreschpe 8:07ad6a48a85d 716 _cs = 1;
dreschpe 8:07ad6a48a85d 717 _spi.format(8,3);
dreschpe 8:07ad6a48a85d 718 }
dreschpe 8:07ad6a48a85d 719 else{ // malloc ok, we can use DMA
dreschpe 8:07ad6a48a85d 720 zeichen = &font[((c -32) * offset) + 4]; // start of char bitmap
dreschpe 8:07ad6a48a85d 721 w = zeichen[0]; // width of actual char
dreschpe 8:07ad6a48a85d 722 p = 0;
dreschpe 8:07ad6a48a85d 723 // construct the char into the buffer
dreschpe 8:07ad6a48a85d 724 for (j=0; j<vert; j++) { // vert line
dreschpe 8:07ad6a48a85d 725 for (i=0; i<hor; i++) { // horz line
dreschpe 8:07ad6a48a85d 726 z = zeichen[bpl * i + ((j & 0xF8) >> 3)+1];
dreschpe 8:07ad6a48a85d 727 b = 1 << (j & 0x07);
dreschpe 8:07ad6a48a85d 728 if (( z & b ) == 0x00) {
dreschpe 8:07ad6a48a85d 729 buffer[p] = _background;
dreschpe 8:07ad6a48a85d 730 } else {
dreschpe 8:07ad6a48a85d 731 buffer[p] = _foreground;
dreschpe 8:07ad6a48a85d 732 }
dreschpe 8:07ad6a48a85d 733 p++;
dreschpe 8:07ad6a48a85d 734 }
dreschpe 8:07ad6a48a85d 735 }
dreschpe 8:07ad6a48a85d 736 // copy the buffer with DMA SPI to display
dreschpe 8:07ad6a48a85d 737 dma_off = 0; // offset for DMA transfer
dreschpe 8:07ad6a48a85d 738 DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) (buffer + dma_off);
dreschpe 8:07ad6a48a85d 739 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
dreschpe 8:07ad6a48a85d 740 DMA_Init(DMA1_Channel3, &DMA_InitStructure); // init the DMA
dreschpe 8:07ad6a48a85d 741 // start DMA
dreschpe 8:07ad6a48a85d 742 do {
dreschpe 8:07ad6a48a85d 743 if (pixel > 0X10000) { // this is a giant font !
dreschpe 8:07ad6a48a85d 744 dma_count = 0Xffff;
dreschpe 8:07ad6a48a85d 745 pixel = pixel - 0Xffff;
dreschpe 8:07ad6a48a85d 746 } else {
dreschpe 8:07ad6a48a85d 747 dma_count = pixel;
dreschpe 8:07ad6a48a85d 748 pixel = 0;
dreschpe 8:07ad6a48a85d 749 }
dreschpe 8:07ad6a48a85d 750 DMA_SetCurrDataCounter(DMA1_Channel3, dma_count);
dreschpe 8:07ad6a48a85d 751 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx,ENABLE);
dreschpe 8:07ad6a48a85d 752 DMA_Cmd(DMA1_Channel3, ENABLE);
dreschpe 8:07ad6a48a85d 753 do{
dreschpe 8:07ad6a48a85d 754 }while(DMA_GetCurrDataCounter(DMA1_Channel3) != 0); // wait for end of transfer
dreschpe 8:07ad6a48a85d 755 DMA_Cmd(DMA1_Channel3, DISABLE);
dreschpe 8:07ad6a48a85d 756 }while(pixel > 0);
dreschpe 8:07ad6a48a85d 757 do{}while(SPI1->SR & 0x80 == 1); // wait for SPI send
dreschpe 8:07ad6a48a85d 758 free ((uint16_t *) buffer);
dreschpe 8:07ad6a48a85d 759 SPI1->CR1 &= ~(1 << 11); // switch to 8 bit Mode
dreschpe 0:da1bf437cbc1 760 }
dreschpe 0:da1bf437cbc1 761 _cs = 1;
dreschpe 0:da1bf437cbc1 762 WindowMax();
dreschpe 0:da1bf437cbc1 763 if ((w + 2) < hor) { // x offset to next char
dreschpe 0:da1bf437cbc1 764 char_x += w + 2;
dreschpe 0:da1bf437cbc1 765 } else char_x += hor;
dreschpe 0:da1bf437cbc1 766 }
dreschpe 0:da1bf437cbc1 767
dreschpe 0:da1bf437cbc1 768
dreschpe 0:da1bf437cbc1 769 void SPI_TFT_ILI9341::set_font(unsigned char* f)
dreschpe 0:da1bf437cbc1 770 {
dreschpe 0:da1bf437cbc1 771 font = f;
dreschpe 0:da1bf437cbc1 772 }
dreschpe 0:da1bf437cbc1 773
dreschpe 0:da1bf437cbc1 774
dreschpe 0:da1bf437cbc1 775
dreschpe 0:da1bf437cbc1 776 void SPI_TFT_ILI9341::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
dreschpe 0:da1bf437cbc1 777 {
dreschpe 0:da1bf437cbc1 778 unsigned int j;
dreschpe 0:da1bf437cbc1 779 int padd;
dreschpe 0:da1bf437cbc1 780 unsigned short *bitmap_ptr = (unsigned short *)bitmap;
dreschpe 8:07ad6a48a85d 781
dreschpe 2:0a16083193a4 782 unsigned int i;
dreschpe 8:07ad6a48a85d 783
dreschpe 0:da1bf437cbc1 784 // the lines are padded to multiple of 4 bytes in a bitmap
dreschpe 0:da1bf437cbc1 785 padd = -1;
dreschpe 0:da1bf437cbc1 786 do {
dreschpe 0:da1bf437cbc1 787 padd ++;
dreschpe 0:da1bf437cbc1 788 } while (2*(w + padd)%4 != 0);
dreschpe 0:da1bf437cbc1 789 window(x, y, w, h);
dreschpe 2:0a16083193a4 790 bitmap_ptr += ((h - 1)* (w + padd));
dreschpe 5:55aed13f2630 791 wr_cmd(0x2C); // send pixel
dreschpe 5:55aed13f2630 792 _spi.format(16,3);
dreschpe 2:0a16083193a4 793 for (j = 0; j < h; j++) { //Lines
dreschpe 2:0a16083193a4 794 for (i = 0; i < w; i++) { // one line
dreschpe 5:55aed13f2630 795 _spi.write(*bitmap_ptr); // one line
dreschpe 5:55aed13f2630 796 bitmap_ptr++;
dreschpe 0:da1bf437cbc1 797 }
dreschpe 0:da1bf437cbc1 798 bitmap_ptr -= 2*w;
dreschpe 0:da1bf437cbc1 799 bitmap_ptr -= padd;
dreschpe 0:da1bf437cbc1 800 }
dreschpe 0:da1bf437cbc1 801 _cs = 1;
dreschpe 0:da1bf437cbc1 802 _spi.format(8,3);
dreschpe 0:da1bf437cbc1 803 WindowMax();
dreschpe 0:da1bf437cbc1 804 }
dreschpe 0:da1bf437cbc1 805
dreschpe 0:da1bf437cbc1 806
dreschpe 6:fe07ae8329f7 807 // local filesystem is not implemented in kinetis board , but you can add a SD card
dreschpe 5:55aed13f2630 808
dreschpe 0:da1bf437cbc1 809 int SPI_TFT_ILI9341::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
dreschpe 0:da1bf437cbc1 810 {
dreschpe 0:da1bf437cbc1 811
dreschpe 0:da1bf437cbc1 812 #define OffsetPixelWidth 18
dreschpe 0:da1bf437cbc1 813 #define OffsetPixelHeigh 22
dreschpe 0:da1bf437cbc1 814 #define OffsetFileSize 34
dreschpe 0:da1bf437cbc1 815 #define OffsetPixData 10
dreschpe 0:da1bf437cbc1 816 #define OffsetBPP 28
dreschpe 0:da1bf437cbc1 817
dreschpe 0:da1bf437cbc1 818 char filename[50];
dreschpe 0:da1bf437cbc1 819 unsigned char BMP_Header[54];
dreschpe 0:da1bf437cbc1 820 unsigned short BPP_t;
dreschpe 0:da1bf437cbc1 821 unsigned int PixelWidth,PixelHeigh,start_data;
dreschpe 0:da1bf437cbc1 822 unsigned int i,off;
dreschpe 0:da1bf437cbc1 823 int padd,j;
dreschpe 0:da1bf437cbc1 824 unsigned short *line;
dreschpe 0:da1bf437cbc1 825
dreschpe 0:da1bf437cbc1 826 // get the filename
dreschpe 6:fe07ae8329f7 827 i=0;
dreschpe 0:da1bf437cbc1 828 while (*Name_BMP!='\0') {
dreschpe 0:da1bf437cbc1 829 filename[i++]=*Name_BMP++;
dreschpe 0:da1bf437cbc1 830 }
dreschpe 8:07ad6a48a85d 831 filename[i] = 0;
dreschpe 8:07ad6a48a85d 832
dreschpe 0:da1bf437cbc1 833 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file
dreschpe 0:da1bf437cbc1 834 if (!Image) {
dreschpe 0:da1bf437cbc1 835 return(0); // error file not found !
dreschpe 0:da1bf437cbc1 836 }
dreschpe 0:da1bf437cbc1 837
dreschpe 0:da1bf437cbc1 838 fread(&BMP_Header[0],1,54,Image); // get the BMP Header
dreschpe 0:da1bf437cbc1 839
dreschpe 0:da1bf437cbc1 840 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte
dreschpe 0:da1bf437cbc1 841 fclose(Image);
dreschpe 0:da1bf437cbc1 842 return(-1); // error no BMP file
dreschpe 0:da1bf437cbc1 843 }
dreschpe 0:da1bf437cbc1 844
dreschpe 0:da1bf437cbc1 845 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
dreschpe 0:da1bf437cbc1 846 if (BPP_t != 0x0010) {
dreschpe 0:da1bf437cbc1 847 fclose(Image);
dreschpe 0:da1bf437cbc1 848 return(-2); // error no 16 bit BMP
dreschpe 0:da1bf437cbc1 849 }
dreschpe 0:da1bf437cbc1 850
dreschpe 0:da1bf437cbc1 851 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
dreschpe 0:da1bf437cbc1 852 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
dreschpe 0:da1bf437cbc1 853 if (PixelHeigh > height() + y || PixelWidth > width() + x) {
dreschpe 0:da1bf437cbc1 854 fclose(Image);
dreschpe 0:da1bf437cbc1 855 return(-3); // to big
dreschpe 0:da1bf437cbc1 856 }
dreschpe 0:da1bf437cbc1 857
dreschpe 0:da1bf437cbc1 858 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
dreschpe 0:da1bf437cbc1 859
dreschpe 0:da1bf437cbc1 860 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
dreschpe 0:da1bf437cbc1 861 if (line == NULL) {
dreschpe 0:da1bf437cbc1 862 return(-4); // error no memory
dreschpe 0:da1bf437cbc1 863 }
dreschpe 0:da1bf437cbc1 864
dreschpe 0:da1bf437cbc1 865 // the bmp lines are padded to multiple of 4 bytes
dreschpe 0:da1bf437cbc1 866 padd = -1;
dreschpe 0:da1bf437cbc1 867 do {
dreschpe 0:da1bf437cbc1 868 padd ++;
dreschpe 0:da1bf437cbc1 869 } while ((PixelWidth * 2 + padd)%4 != 0);
dreschpe 0:da1bf437cbc1 870
dreschpe 0:da1bf437cbc1 871 window(x, y,PixelWidth ,PixelHeigh);
dreschpe 6:fe07ae8329f7 872 wr_cmd(0x2C); // send pixel
dreschpe 8:07ad6a48a85d 873 _spi.format(16,3);
dreschpe 0:da1bf437cbc1 874 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up
dreschpe 0:da1bf437cbc1 875 off = j * (PixelWidth * 2 + padd) + start_data; // start of line
dreschpe 0:da1bf437cbc1 876 fseek(Image, off ,SEEK_SET);
dreschpe 8:07ad6a48a85d 877 fread(line,1,PixelWidth * 2,Image); // read a line - slow
dreschpe 0:da1bf437cbc1 878 for (i = 0; i < PixelWidth; i++) { // copy pixel data to TFT
dreschpe 0:da1bf437cbc1 879 _spi.write(line[i]); // one 16 bit pixel
dreschpe 8:07ad6a48a85d 880 }
dreschpe 0:da1bf437cbc1 881 }
dreschpe 0:da1bf437cbc1 882 _cs = 1;
dreschpe 0:da1bf437cbc1 883 _spi.format(8,3);
dreschpe 0:da1bf437cbc1 884 free (line);
dreschpe 0:da1bf437cbc1 885 fclose(Image);
dreschpe 0:da1bf437cbc1 886 WindowMax();
dreschpe 0:da1bf437cbc1 887 return(1);
dreschpe 5:55aed13f2630 888 }