marekburiak / ILI9341_due

Arduino Due and AVR (Uno, Mega, Nano, Pro Mini,...) library for interfacing with ILI9341 SPI TFTs
http://marekburiak.github.io/ILI9341_due
99 stars 36 forks source link

program blocks if running a SD card on the SPI bus additionally to ILI9341_due #4

Closed shiftleftplusone closed 8 years ago

shiftleftplusone commented 9 years ago

I just encountered the reason why my further test programs didn't show correct display outputs: it happened when a SD card was plugged to the SPI bus additionally.

this is the SD init function:


int16_t initSD() {
   char sbuf[128];
   uint32_t  tstamp;
   int16_t   ior=0;

   tstamp = clock();
   ior=SD.begin(sd_cs);  // true on sucess; else false
   while( !ior) {      
      sprintf(sbuf, "#: ...SD not found... ");  
      curlf(); lcdprint("#: ...SD not found... "); 
      Serial.println(sbuf);
      delay(1000);   
      ior=SD.begin(sd_cs);
      if (clock()-tstamp>20000) {Serial.println("#: ...break!"); break; }
   } 
  if(!ior) return -16;     // SD ioresult==0 => error = -16 
  return 1 ;                     // SD ioresult==1 => ok = 1
} 

this is the call in setup():

// SD card
   sprintf(sbuf, "SD init... ");   Serial.println(sbuf);
   i = initSD();
   if(i==-16) sprintf(sbuf, "SD failed! ERROR ! ");  
   else sprintf(sbuf, "SD OK ! ");   
   Serial.println(sbuf);   
   curlf(); 
   lcdprint(sbuf);

lcdprint() is a macro which is basically { dtft.cursorToXY(x,y); dtft.printAt(str, x, y); }

it works fine with Adafruit ILI9340, but with ILI9341_due the program blocks then. (not only lcd print is blocked, but also Serial hangs up and the program stops running prematurely).

Instead if I outcomment the SD init line // i = initSD();

then again the display works also fine with ILI9341_due.

What do I have to change to make the SPI bus work with both the ILI9341_due and the SD ?

marekburiak commented 9 years ago

Try to uncomment this line in ILI9341_due_config.h:

//#define ILI_USE_SPI_TRANSACTION

If that won't work then SD library must be overriding something that ILI9341_due uses. I had no problems using SDFat library together with my lib (sdFatTftBitmap example uses it to render images from SD card): https://github.com/greiman/SdFat Btw. SdFat can use DMA on Due to read/write faster from/to SD card. That's where I got my initial DMA code for my lib from.

shiftleftplusone commented 9 years ago

is already uncommente by default! // uncomment if you want to use SPI transactions. Uncomment it if the library does not work when used with other libraries. //#define ILI_USE_SPI_TRANSACTION

marekburiak commented 9 years ago

By default it's like this (commented out):

//#define ILI_USE_SPI_TRANSACTION

So try to uncomment it:

#define ILI_USE_SPI_TRANSACTION
shiftleftplusone commented 9 years ago

actually I don't want to change the SD lib because I need a lot of SD.h features for my program and I invested lot of time to have stdio.h compatible commands to access it (which I wrote by my own), like

long     fprintf_( File * stream, const char fmtstr[], ... );       // see ANSI C: fprintf()
long     fscanf_ ( File * stream, const char fmtstr[], ... ) ;      // see ANSI C: fscanf()
char   * fgets_  ( char * str, int32_t num, File * stream );        // see ANSI C: fgets()
File     fopen_  ( char * filename, const char * mode );            // see ANSI C: fopen()
int16_t  fclose_ ( File   file_);                                   // see ANSI C: fclose()   
int16_t  remove_ ( char * filename );                               // see ANSI C: remove()

http://www.mindstormsforum.de/viewtopic.php?f=78&t=8491#p66429

shiftleftplusone commented 9 years ago

aah, yes, I will do !

shiftleftplusone commented 9 years ago

if uncommented: SD seems to work but then display text blocks instead.

marekburiak commented 9 years ago

I am sure SDFat has those or similar functions too. If you don't want to switch SD library then I guess you'll have to find out why it's not working ;) Try to change the order in which you initialize tft and sd. If I remember you are initializing tft first and sd after that so try to initialize sd first and then tft.

shiftleftplusone commented 9 years ago

I had a look at this SDfat lib but that's really weird to me - no chance. standard SD.h is fine, I will have to keep it.

update:

no, faulty, too: no correct display output any more after initianlizing the SD card. LCD initialization is faulty. with the Adafruit ILI9340 driver it works though.

shiftleftplusone commented 9 years ago

this is the complete test code, you can choose display type either

_ILI9341_ // Adafruit
// or
_ILI9341due_ // your lib
#include <SPI.h>
#include <SD.h>
//#include <ardustdio.h>

//=====================================================================================
// misc.  
//=====================================================================================

#define  _DUEMISO_    74  // Arduino Due SPI Header
#define  _DUEMOSI_    75
#define  _DUESCK_     76

#define  _MEGAMISO_   50  // Arduino MegaSPI Header
#define  _MEGAMOSI_   51
#define  _MEGASCK_    52

#define  clock()      millis()  
#define  LRAND_MAX    32767
#define  srand(seed)  randomSeed(seed)
#define  rand()       random(LRAND_MAX)
#define  rando()      ((float)rand()/(LRAND_MAX+1))

//=====================================================================================
// TFT LCD
//=====================================================================================

#define   UTFT_SmallFont     8 // UTFT 8x10
#define   UTFT_MediumFont   12 // UTFT ++ 
#define   UTFT_BigFont      18 // UTFT +++ 
#define   _SmallFont_        1 // 9341 6x9
#define   _MediumFont_       2 // 9341 12x16
#define   _BigFont_          3 // 9341 18x23

int16_t  LCDmaxX , LCDmaxY ;                // display size
int16_t  _curx_, _cury_,                    // last x,y cursor pos on TFT screen
         _maxx_, _maxy_;                    // max. x,y cursor pos on TFT screen       

// set LCD TFT type
int16_t  LCDTYPE   =   -1;

#define  _LCD1602_    1  // LCD1602  Hitachi HD44780 driver <LiquidCrystal.h> 
                           // http://www.arduino.cc/en/Tutorial/LiquidCrystal   //
#define  _SERLCD_     2  // Sparkfun serLCD 16x2  
                           // http://playground.arduino.cc/Code/SerLCD   //
#define  _UTFT_       4  // Henning Karlsen UTFT 2.2-2.4" 220x176 - 320x240 lib
                           // http://henningkarlsen.com/electronics/library.php?id=51   //
#define _ILI9341_     8  // https://github.com/adafruit/Adafruit_ILI9340
                           // https://github.com/adafruit/Adafruit-GFX-Library //
#define _ILI9341due_  9  // ILI9341_due NEW lib by Marek Buriak
                           // http://marekburiak.github.io/ILI9341_due/ //

//--------------------------------------------------------------------------------------------------
#define    tft_cs     49
#define    tft_dc     48
#define    tft_rst     0                        

//=====================================================================================
// UTFT Henning Karlsen
//=====================================================================================
#include <UTFTQD.h>

//UTFT   qdUTFT(Model,  SDA=MOSI,   SCL,      CS,     RESET,  RS)    // Due: 3 exposed SS pins: 4,10,52
//UTFT   qdUTFT(QD220A,   A2,       A1,       A5,     A4,     A3);   // adjust model parameter and pins!
  UTFT   qdUTFT(QD220A, _MEGAMOSI_,_MEGASCK_,tft_cs , 0,      49);   // A0->Vc (LED), A4->BoardReset
 extern  uint8_t SmallFont[];

//=====================================================================================
// TFT Adafruit LIL9340/ILI9341
//=====================================================================================
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9340.h>

Adafruit_ILI9340  tft = Adafruit_ILI9340(tft_cs, tft_dc, tft_rst);

//=====================================================================================
// TFT ILI9341_due // http://marekburiak.github.io/ILI9341_due/ //
//=====================================================================================
#include <ILI9341_due_config.h>
#include <ILI9341_due.h>
#include <SystemFont5x7.h>

ILI9341_due      dtft = ILI9341_due(tft_cs, tft_dc);

// Color set
#define  BLACK           0x0000
#define RED             0xF800
#define GREEN           0x07E0
//#define BLUE            0x001F
#define BLUE            0x102E
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0 
#define ORANGE          0xFD20
#define GREENYELLOW     0xAFE5 
#define DARKGREEN       0x03E0
#define WHITE           0xFFFF

uint16_t  color;

//--------------------------------------------------------------------------------------------------

#define  lcdWhiteBlack()  {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_WHITE, ILI9340_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, BLACK) ;} \
}

#define  lcdNormal()      {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_WHITE, ILI9340_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, BLACK) ;} \
}

#define  lcdInvers()      {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(  0,  0,  0); qdUTFT.setBackColor(255,255,255);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_BLACK, ILI9340_WHITE) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(BLACK, WHITE) ;} \
}

#define  lcdWhiteRed()    {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(255,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_WHITE, ILI9340_RED) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, RED) ;} \
}

#define  lcdRedBlack()    {                                                                 \   
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,  0,  0); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_RED, ILI9340_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(RED, BLACK) ;} \
}

#define  lcdYellowBlue()  {                                                                 \     
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,  0); qdUTFT.setBackColor( 64, 64, 64);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9340_YELLOW, ILI9340_BLUE);} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(YELLOW, BLUE);} \
}

int16_t  fontwi= 8;  // default
int16_t  fonthi=10;  // default

void putfonttype(uint8_t fsize) {
  if(LCDTYPE==_UTFT_)  { fontwi= qdUTFT.getFontXsize(); fonthi=qdUTFT.getFontYsize(); }
  else
  if(LCDTYPE==_ILI9341_) {
     if(fsize==_SmallFont_)     { fontwi= 6; fonthi=9; }  // 5x7 + overhead 
     else
     if(fsize==_MediumFont_)    { fontwi=12; fonthi=16; } // ?
     else
     if(fsize==_BigFont_)       { fontwi=18; fonthi=23; } // ?
  }
  else
  if(LCDTYPE==_ILI9341due_) {
     if(fsize==_SmallFont_)     { fontwi= 6; fonthi=9; }  // 5x7 + overhead 
  }
  _maxx_ = LCDmaxX / fontwi;    // max number of letters x>>
  _maxy_ = LCDmaxY / fonthi;    // max number of letters y^^ 
}

void setlcdorient(int16_t orient) {

  if(LCDTYPE==_ILI9341_) {
      tft.setRotation(orient);
      LCDmaxX=tft.width();
      LCDmaxY=tft.height();        
   }
   else
   if(LCDTYPE==_ILI9341due_) {
      if(orient==0) dtft.setRotation(iliRotation0);
      else
      if(orient==1) dtft.setRotation(iliRotation90);
      else
      if(orient==2) dtft.setRotation(iliRotation180);
      else
      if(orient==3) dtft.setRotation(iliRotation270); 
      LCDmaxX=dtft.width();
      LCDmaxY=dtft.height();   
   }

}

void lcdcls()  {                                                         
   if(LCDTYPE==_UTFT_)       { qdUTFT.clrScr();                }  
   else
   if(LCDTYPE==_ILI9341_)    { tft.fillScreen(ILI9340_BLACK);  }
   else
   if(LCDTYPE==_ILI9341due_) { dtft.fillScreen(BLACK);  }
   _curx_ =0;  _cury_ =0;
}

void curlf()   {                                                        
   _curx_=0; 
   if( _cury_ <=(LCDmaxY-10) ) _cury_+=fonthi; 
   else _cury_=0; 

   if(LCDTYPE==_ILI9341_)    { tft.setCursor(0, _cury_); }  
   else
   if(LCDTYPE==_ILI9341due_) { dtft.cursorToXY(0, _cury_); }  
}

void curxy(int16_t  x,  int16_t  y) {
   _curx_ = x;
   _cury_ = y; 
   if(LCDTYPE==_ILI9341_)      {tft.setCursor(x, y); }
   else
   if(LCDTYPE==_ILI9341due_)   {dtft.cursorToXY(x, y); }
}

void lcdprintxy(int16_t x, int16_t y, char * str) {
   if(LCDTYPE==_UTFT_)          { 
     qdUTFT.print(str,x,y); 
     _curx_=x+strlen(str)*fontwi; 
     _cury_=y; 
   }
   else if(LCDTYPE==_ILI9341_)  { 
      tft.setCursor(x,y);     
      tft.print(str); 
      _curx_=tft.getCursorX(); 
      _cury_=tft.getCursorY(); 
   }
   else if(LCDTYPE==_ILI9341due_)  { 
      dtft.cursorToXY(x,y);     
      dtft.printAt(str, x, y); 
      _curx_=x+strlen(str)*fontwi; 
      _cury_=y; 
   }
}

void lcdprint(char * str) {
    if(LCDTYPE==_UTFT_)     { 
      qdUTFT.print(str, _curx_, _cury_); 
      _curx_=_curx_+strlen(str)*fontwi; 
    }
    else if(LCDTYPE==_ILI9341_)  { 
       tft.setCursor(_curx_, _cury_); 
       tft.print(str); 
       _curx_=tft.getCursorX(); 
       _cury_=tft.getCursorY(); 
    }
    else if(LCDTYPE==_ILI9341due_)  { 
       dtft.cursorToXY(_curx_, _cury_); 
       dtft.printAt(str, _curx_, _cury_ ); 
      _curx_=_curx_+strlen(str)*fontwi;
    }
}

void initLCD(uint8_t orientation) { // 0,2==Portrait  1,3==Landscape
   if(LCDTYPE==_UTFT_) {
      qdUTFT.InitLCD(orientation%2);
      LCDmaxX=qdUTFT.getDisplayXSize();
      LCDmaxY=qdUTFT.getDisplayYSize();
      qdUTFT.setFont(SmallFont);
      putfonttype(UTFT_SmallFont);
      fontwi=qdUTFT.getFontXsize();
      fonthi=qdUTFT.getFontYsize();
   }
   else
   if(LCDTYPE==_ILI9341_) {
      tft.begin();
      setlcdorient(orientation);       
      tft.setTextSize(_SmallFont_);
      putfonttype(_SmallFont_);
   } 
   else
   if(LCDTYPE==_ILI9341due_) {
      dtft.begin();
      dtft.setRotation((iliRotation)orientation);
      //setlcdorient(orientation);  
      dtft.fillScreen(BLACK);
      dtft.setFont(SystemFont5x7); 
      dtft.setTextColor(WHITE);
      dtft.print("ILI9341due"); 
      putfonttype(_SmallFont_);
   }  
}  

//=====================================================================================
// SD Card
//=====================================================================================
#define  sd_cs        38     // <<<<<<<< adjust!
File     myFile; 
char     _fname_[64];

#define fileIO_OK            +1
#define fileIO_NO_ERR         0
#define fileIO_ERR_CREATE    -1
#define fileIO_ERR_OPEN      -2
#define fileIO_ERR_REMOVE    -3
#define fileIO_ERR_WRITE     -4
#define fileIO_ERR_READ      -5
#define fileIO_ERR_IMPLAUS   -6
#define fileIO_ERR_NAME      -8
#define fileIO_ERR_SDCARD   -16

//=====================================================================================
// SD init
//=====================================================================================

int16_t initSD() {
   char sbuf[128];
   uint32_t  tstamp;
   int16_t   ior=0;

   tstamp = clock();
   ior=SD.begin(sd_cs);  // true on sucess; else false
   while( !ior) {      
      sprintf(sbuf, "#: ...SD not found... ");  
      //curlf(); lcdprint("#: ...SD not found... "); 
      Serial.println(sbuf);
      delay(1000);   
      ior=SD.begin(sd_cs);
      if (clock()-tstamp>20000) {Serial.println("#: ...break!"); break; }
   } 
  if(!ior) return fileIO_ERR_SDCARD;     // SD ioresult==0 => error = -16 
  return fileIO_OK ;                     // SD ioresult==1 => ok = 1
} 

//=====================================================================================
// user interface:  button pad control pins
//=====================================================================================

#define  PIN_ESC    13
#define  PIN_UP     12
#define  PIN_OK     11
#define  PIN_DN      4 // instead opt.: 6
#define  PIN_LE      3 // instead opt.: 5
#define  PIN_RI      2

//=====================================================================================
// Digital Pins
//=====================================================================================

#define  SensorPTouch(pin) (!digitalRead(pin))    // btn press for _PULLUP Touch Pin (intern. pullup resistor)
#define  SensorTouch(pin)  ( digitalRead(pin))    // btn press for _PULLDOWN Touch Pin (ext. pulldown resistor)
#define  pbtn(pin)         (!digitalRead(pin))    // alias (_PULLUP Touch Pin)

//=====================================================================================

int16_t  btnpressed() {
   return ( pbtn(PIN_ESC)||pbtn(PIN_UP)||pbtn(PIN_OK)||pbtn(PIN_DN)||pbtn(PIN_LE)||pbtn(PIN_RI) );
}

//=====================================================================================

int16_t   getbtn() {
   int16_t  choice= -1;

   while (!  btnpressed() );  // wait until button pad pressed
   if( pbtn(PIN_ESC) ) choice = PIN_ESC;
   if( pbtn(PIN_UP) )  choice = PIN_UP;
   if( pbtn(PIN_OK) )  choice = PIN_OK;
   if( pbtn(PIN_DN) )  choice = PIN_DN;
   if( pbtn(PIN_LE) )  choice = PIN_LE;
   if( pbtn(PIN_RI) )  choice = PIN_RI;     
   while (  btnpressed() );   // wait until button pad released

   return choice;   
}

//=====================================================================================
//=====================================================================================
void setup() {
   char sbuf[128], sbuf2[128];   
   int32_t  i=0;

   // Serial terminal window
   i=115200;
   Serial.begin(i);  
   Serial.print("Serial started, baud="); Serial.println(i);

   // GPIO pins default = INPUT_PULLUP, 13 for LED13
   Serial.println();
   Serial.println("GPIO pin mode default: INPUT_PULLUP");
   for ( i= 2; (i<=13); ++i)  pinMode(i, INPUT_PULLUP); 
   pinMode(13, OUTPUT);
   for ( i=22; (i<=53); ++i)  pinMode(i, INPUT_PULLUP); 

      // SD card
   sprintf(sbuf2, "SD init... ");   Serial.println(sbuf2);
   i = initSD();
   if(i==fileIO_ERR_SDCARD) sprintf(sbuf2, "SD failed! ERROR ! ");  
   else sprintf(sbuf2, "SD OK ! ");   
   Serial.println(sbuf2);   

   // TFT LCD
   Serial.println();
   LCDTYPE = _ILI9341due_;
   Serial.print("init LCD..."); 
   initLCD(1);   
   Serial.println(" done.");   lcdcls();
   sprintf(sbuf, "LCD=%d wi%dxhi%d Font %dx%d",LCDTYPE,LCDmaxX,LCDmaxY,fontwi,fonthi);
   Serial.println(sbuf); 
   Serial.println();
   lcdcls(); lcdprint(sbuf);  // LCD runstate

   curlf(); lcdprint(sbuf2);  // SD runstate

   sprintf(sbuf, "setup(): done.");
   Serial.println(); Serial.println(sbuf);   
   curlf(); curlf(); lcdprint(sbuf);

}

//=====================================================================================
//=====================================================================================
void loop(){
   char     sbuf[128];

}
//=====================================================================================
//=====================================================================================
marekburiak commented 9 years ago

Just FYI, I won't have time to look into SD library and why it conflicts with my lib so I suggest you either switch SD library to SDFat or try to figure out why those two libs don't work together. Sorry but I have really no time at the moment (or any time soon).

shiftleftplusone commented 9 years ago

ok, don't mind, but I will use the Adafruit lib then if I need to have SD card access. Thanks for your reply!

shiftleftplusone commented 9 years ago

the test program also blocks using SdFat with your ILI9341_due lib, but nevertheless, Adafruit ILI9340 and UTFT are also fine with SdFat instead!

So there must be issues in your ILI9341_due lib which conflits with SD card backpanes in general running on the same SPi bus simultaneously!

#include <SPI.h>
#include <SdFat.h>
SdFat SD;

//#include <ardustdio.h>

//=====================================================================================
// misc.  
//=====================================================================================

// **SNIP**
marekburiak commented 9 years ago

I am using SDFat to load images from SD card and that happens in an interleaving fashion so read a few bytes from SD card, send it to TFT, read next a few bytes from SD, send it to TFT...and it works fine. Maybe you can compare how I initialize TFT and SD card in sdFatTftBitmap example because it is definitely not blocking there.

shiftleftplusone commented 9 years ago

perhaps the issue was partially a syntax error related to Adafruit syntax. (Anyway, this different function syntax for each single lib is really confusing.)

So now it's almost always fine with SdFat.h, but still issues about SD.h.