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:
Tue Jun 24 15:37:52 2014 +0000
Revision:
11:59eca2723ec5
Add fast Version for NUCLEO L152RE

Who changed what in which revision?

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