Teensy 4.0 and TFT Touchscreen ILI9341

Status
Not open for further replies.

mika09

New member
Hello everyone,

I would like to know if the new Teensy 4.0 is compatible with the TFT Touchscreen ? I saw it retains compatibility with most of the pin functions on Teensy 3.2 but it's just to be sure.

If the answer is yes I guess the connections indication on the website (https://www.pjrc.com/store/display_ili9341_touch.html) will be the same for the 4.0.

Thanks
 
The answer is yes the PJRC display works great on the T4.

As for IO pins. It depends. If you are talking about using Audio board, than the T4 uses different Audio pins than T3.x so those will be different, likewise T4 does not have some of the same Alternate SPI pins the T3.x does so again with Audio boards this will be different.

And likewise with most of the Teensy boards, you are not limited to these pins.
That is, these connections break down to couple of things.

a)Display SPI pins (CS, DC, SDI/MOSI, SCK, SDO/MISO) - 10, 9, 11, 12, 13 - These are standard SPI pins on T3.x including both CS and DC are on hardware CS pins, so the fast library ili9341_t3 works great with it, likewise my derivative ili9341_t3n

These pins are also SPI pins on T4 (except pin 9 is not a hardware CS pin. But same libraries work with these as well. Also my library will work with both T3.x and T4 boards that use SPI pins of other SPI ports on many of these boards.

b) Touch SPI pins - again default pins work fine. And the t_CS and T_IRQ can be on any digital pins
 
Hi,

Thanks for your feedback, it was about the standard one because I don't need the audio board for my project so it will not be so much different.

I have a last question about the USB ports on T4.0, can I used the USB Host Cable as for the T3.6 ? or I can have an usb port by a different way.

After I will add a controller CAN (MCP2515-I/P) to communicate with my box.

Thanks
 
Hi,
...
I have a last question about the USB ports on T4.0, can I used the USB Host Cable as for the T3.6 ? or I can have an usb port by a different way.
...
Thanks

The only Device connect for T_4.0 USB is the micro USB adapter. Other USB signal pins are for use as a Host device. Those USB host pads if brought out act the same as on the T_3.6. But the onboard ESD power protect chip on the T_3.6 are not present. It works to powered hub or devices that won't over draw power on start.
 
Thank you for this! I just finished wiring this to my Teensy 4.0 (with audio board), and was just blindly following the alternate pins on the product page , and couldn't figure out why nothing was happening.

After re-wiring, the display works great. However, I have now lost contact with the SD drive. Is it because I'm now using the same pin for the TFT_CS that I am for the SDCARD_CS_PIN? If so, which pin should I switch it to? I confess, I'm a little in the dark about what exactly the CS even does...

Thanks in advance! I'll post my full code, but it's maybe a little long and confusing. Really, the key bit (I think) is the pin assignments in lines 80-92.
Code:
///////////////////////////////////
// copy the Design Tool code here
///////////////////////////////////
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=77,26
AudioPlaySdWav           playSdWav2;     //xy=79,67
AudioPlaySdRaw           playSdRaw1;     //xy=79,158
AudioSynthSimpleDrum     drum2;          //xy=81,355
AudioSynthSimpleDrum     drum4;          //xy=85,474
AudioSynthSimpleDrum     drum3;          //xy=87,401
AudioSynthSimpleDrum     drum1;          //xy=88,283
AudioPlaySdRaw           playSdRaw2;     //xy=95,220
AudioAmplifier           amp6;           //xy=235,413
AudioAmplifier           amp4;           //xy=252,371
AudioAmplifier           amp5;           //xy=255,471
AudioMixer4              mixer1;         //xy=258,35
AudioMixer4              mixer2;         //xy=263,99
AudioAmplifier           amp1;           //xy=264,168
AudioAmplifier           amp3;           //xy=270,281
AudioAmplifier           amp2;           //xy=293,219
AudioEffectFreeverb      freeverb3;      //xy=548,139
AudioEffectFreeverb      freeverb4;      //xy=558,210
AudioEffectFreeverb      freeverb2;      //xy=575,73
AudioEffectFreeverb      freeverb5;      //xy=576,267
AudioEffectFreeverb      freeverb1;      //xy=584,36
AudioEffectFreeverb      freeverb6;      //xy=591,352
AudioEffectFreeverb      freeverb7;      //xy=597,431
AudioEffectFreeverb      freeverb8;      //xy=599,506
AudioMixer4              mixer3;         //xy=757,178
AudioMixer4              mixer4;         //xy=788,272
AudioMixer4              masterMix;         //xy=954,203
AudioOutputI2S           i2s1;           //xy=994,343
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord3(playSdWav2, 0, mixer2, 0);
AudioConnection          patchCord4(playSdWav2, 1, mixer2, 1);
AudioConnection          patchCord5(playSdRaw1, amp1);
AudioConnection          patchCord6(drum2, amp4);
AudioConnection          patchCord7(drum4, amp5);
AudioConnection          patchCord8(drum3, amp6);
AudioConnection          patchCord9(drum1, amp3);
AudioConnection          patchCord10(playSdRaw2, amp2);
AudioConnection          patchCord11(amp6, freeverb7);
AudioConnection          patchCord12(amp4, freeverb6);
AudioConnection          patchCord13(amp5, freeverb8);
AudioConnection          patchCord14(mixer1, freeverb1);
AudioConnection          patchCord15(mixer2, freeverb2);
AudioConnection          patchCord16(amp1, freeverb3);
AudioConnection          patchCord17(amp3, freeverb5);
AudioConnection          patchCord18(amp2, freeverb4);
AudioConnection          patchCord19(freeverb3, 0, mixer3, 2);
AudioConnection          patchCord20(freeverb4, 0, mixer3, 3);
AudioConnection          patchCord21(freeverb2, 0, mixer3, 1);
AudioConnection          patchCord22(freeverb5, 0, mixer4, 0);
AudioConnection          patchCord23(freeverb1, 0, mixer3, 0);
AudioConnection          patchCord24(freeverb6, 0, mixer4, 1);
AudioConnection          patchCord25(freeverb7, 0, mixer4, 2);
AudioConnection          patchCord26(freeverb8, 0, mixer4, 3);
AudioConnection          patchCord27(mixer3, 0, masterMix, 0);
AudioConnection          patchCord28(mixer4, 0, masterMix, 3);
AudioConnection          patchCord29(masterMix, 0, i2s1, 0);
AudioConnection          patchCord30(masterMix, 0, i2s1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=836,584
// GUItool: end automatically generated code


AudioPlaySdWav *playSdWav[4]={&playSdWav1, &playSdWav2 };
AudioPlaySdRaw *playSdRaw[4]={&playSdRaw1, &playSdRaw2 };
AudioSynthSimpleDrum *drum[4]={&drum1,&drum2,&drum3,&drum4};

#include <ILI9341_t3.h>
#include <font_Arial.h> // from ILI9341_t3
#define TFT_DC      9
#define TFT_CS      10
#define TFT_RST    255  // 255 = unused, connect to 3.3V
#define TFT_MOSI    11
#define TFT_SCLK    13
#define TFT_MISO    12
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);


// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN    10
#define SDCARD_MOSI_PIN  7
#define SDCARD_SCK_PIN   14

int bpm=120;
int rawObjects=0;
int wavObjects=0;
int synthObjects=0;

#define WHOLENOTE 4
#define HALFNOTE  2
#define QUARTERNOTE 1
#define EIGHTHNOTE .5
#define SIXTEENTHNOTE .25

#ifdef __arm__
// should use uinstd.h to define sbrk but Due causes a conflict
extern "C" char* sbrk(int incr);
#else  // __ARM__
extern char *__brkval;
#endif  // __arm__
 
int freeMemory() {
  char top;
#ifdef __arm__
  return &top - reinterpret_cast<char*>(sbrk(0));
#elif defined(CORE_TEENSY) || (ARDUINO > 103 && ARDUINO != 151)
  return &top - __brkval;
#else  // __arm__
  return __brkval ? &top - __brkval : &top - __malloc_heap_start;
#endif  // __arm__
}

//*******************************************************************************************************************
//*******************************************************************************************************************
//*                                                                                             Sample Class
//*******************************************************************************************************************
//*******************************************************************************************************************
class Sample{
  protected:
  float noteType;       // i.e., what percentage of bpm is this note (e.g., a quarternote is 1 bpm, an eigthnote is .5)
  int pattern=0;
  int patternPosition=0;
  int patternLength=0;
  int isInverted=0;
  int id;
  elapsedMillis change;
  
  public:
    void setup(){
    }  
    void changePattern(int beats, int rests){
      patternLength=beats+rests;
      pattern=findBeats(beats,rests);
      printPattern(pattern,isInverted, patternLength);
    }

    //*******************************************************************************************************************
    //                                                                                               Main Sample Loop
    //*******************************************************************************************************************
    void loop(){    
       if(change>=(noteType*(60000/bpm))){
        // e.g., an eighthnote at 120 bpm should play every 250 milliseconds, which is 4 times a secon or 240 times a minute
        change=0;
        
        if(nowIsTheTimeToParty(patternPosition, pattern, patternLength, isInverted)){
          thenLetsParty();
        }
        patternPosition++;
        if(patternPosition>(patternLength-1)) patternPosition=0;
      }
    }
    int nowIsTheTimeToParty(int pos, int pattern, int len, int isInverted){
      /*    So, pattern 1101001, pos 0 = 1, pos 1=1, pos 2=0
       *    for pos 2, shift it left length-pos (5) = 11 and then just BITWISE AND 1       */
      int p=pattern>>((len-1)-pos);
     // Serial.println(p,BIN);
     int x=p&1;
     if(!isInverted) x=x^1; // Got confused with the inverting, so if it *isn't* inverted, we flip the bit here
     return x;
      // See, I'm told that bitwise AND return 0 if the rightmost digit is 0, and 1 if 1. I'm told.      
    }

    virtual void thenLetsParty(){}
    
    int findBeats(int beats, int rests){
      Serial.print(beats); Serial.print(" beats and "); Serial.print(rests); Serial.println(" rests.");
      Serial.print("This pattern is called '");
      Serial.print(findName(beats,rests));
      Serial.println("'.");
      isInverted=0;
      patternLength=beats+rests;
      int large=rests;
      int sm=beats;
      if(beats>rests){
        isInverted=1;
        large=beats;
        sm=rests;
      }
      int bigArray[large];
      int smallArray[sm];
      //Make two arrays, a big one and a little. Fill the big one with the specified number of beats or rests (1 or ) 
      //Depending on which one there is more of.
      int r=0;
      for(int i=0;i<large;i++){
          bigArray[i]=1;
        if(r<sm) smallArray[r]=0;
        r++;
      }
   // Serial.println("here we go");
      // The euclid function ultimately squeezes the two arrays together according to Euclids GCF algorhythm 
      // MaxRuns (starting at 20) prevents the recursive function from looping forever.
      int x=euclid(beats,rests,bigArray, smallArray, 20);
     // Serial.print(x,BIN);
     // Serial.println(" is what I get in findPattern");
      return x;
    }
    
    int euclid(int beats, int rests, int bigArray[], int smallArray[], int maxRuns){
      int big=beats;
      int small=rests;
      if(beats<rests){ 
        big=rests;
        small=beats;
      }  
      int remainder=big - small;
      // Ok, we have an array, bigArray, of arrays of 1s and 0s
      // And we have a smaller array, 
      int newBigArray[small];
      for(int i=0;i<small;i++){
        // Start with bigArray=[1][1][1] or whatever and smallArray=[0][0][0]
        // and end with newBigArray=[10][10][10] somehow
        newBigArray[i]=bigArray[i];
        int t=smallArray[i];
        while(t>1){
          newBigArray[i]=newBigArray[i]<<1;
          t=t>>1;
        }
        newBigArray[i]=newBigArray[i]<<1;
        newBigArray[i]=newBigArray[i] | smallArray[i];
      }    
      if(remainder==0 || maxRuns<=0) {
        for(int i=1;i<(small);i++){
          // Starting with the element in [1]
          int t=newBigArray[i];
          // We go through and count down the number of digits, shifting [i]
          while(t>1){
            newBigArray[0]=newBigArray[0]<<1;      
            t=t>>1;
          }
          newBigArray[0]=newBigArray[0]<<1;
          newBigArray[0]=newBigArray[0] | newBigArray[i];
        }
        return newBigArray[0];
      }
      else{
       int newSmallArray[remainder];
        for(int i=0;i<remainder;i++){    
          newSmallArray[i]=bigArray[small+i];
        }
        if(remainder>small){ //i.e., if small array is larger than bigArray
          return euclid(remainder, small, newSmallArray, newBigArray, maxRuns-1);
        }
        else{ 
          return euclid(small, remainder, newBigArray, newSmallArray, maxRuns-1);
        }
      }
    }
    
    void printPattern(int p, int inverted, int pl){
      const char* a=".";
      const char *b="X";
      if(inverted){
        a="X";
        b=".";
      }  
      int j=p;
      for(int i=pl-1;i>=0;i--){
          // Shift the pattern to the left by its length-1
          j=p>>i;
          if(j&1) Serial.print(a);
          else Serial.print(b);
      }
      Serial.println("     <------ Ta da!!!");
    }
    
    const char* findName(int a, int b){
      b=b+a;
      if(a==4 && b==12) return "Fandango";
      else if(a==2 && b==3) return "Swing Tumbao";
      else if(a==2 && b==5) return "Khafif-e-ramal";
      else if(a==3 && b==4) return "Cumbia";
      else if(a==3 && b==5) return "Khalif-e-ramal";
      else if(a==3 && b==7) return "Ruchenitza";
      else if(a==3 && b==8) return "Tresillo";
      else return "Something cool.";
    }
};


//*******************************************************************************************************************
//*******************************************************************************************************************
//                                                                                          SD SAMPLE!!!
//*******************************************************************************************************************
//*******************************************************************************************************************
class SDSample : public Sample{
    File currentDir;
  File currentSample;
  const char *sampleName;
  char fullSamplePath[50];
  int isItRaw;

  public:
    void setup(const char *dn,const char *sn,float n, int beats, int rests, int raw=0){
    sampleName=sn;
    noteType=n;
    changePattern(beats, rests);
    currentDir=loadDir(dn);
    currentSample=loadSample(sn);
    if(raw){
      isItRaw=1;
      id=rawObjects;
      rawObjects++;
    }
    else{
      wavObjects++;
      id=wavObjects;
    }      
  }  
  
  /************************************************************************************************************************************
   *                                                                                                                    loadDir()
  ************************************************************************************************************************************/
  File loadDir(const char* dir){
    Serial.println(dir);
    File myFile;
    myFile=SD.open(dir);
    Serial.print("Directory: ");Serial.println(myFile.name());
    return myFile;    
  }
  /************************************************************************************************************************************
   *                                                                                                                    loadSample()
  ************************************************************************************************************************************/
  File loadSample(const char* sampleName){
    File myFile;
    sprintf(fullSamplePath, "/%s/%s",currentDir.name(),sampleName);
        Serial.print("Name 1: ");Serial.println(fullSamplePath);          
    myFile=SD.open(fullSamplePath);
    if(! myFile){
      Serial.println("Can't open file");
      return myFile;
    }
    else{
      return myFile;
    }
  }
  //*******************************************************************************************************************
  //                                                                                               Play SDSample
  //*******************************************************************************************************************
  void thenLetsParty(){    
    if(isItRaw){
      delay(30);
      playSdRaw[id]->play(fullSamplePath);
    }
    else playSdWav[id]->play(fullSamplePath);
  }   
};



//*******************************************************************************************************************
//*******************************************************************************************************************
//                                                                                          Synth Drum!!!
//*******************************************************************************************************************
//*******************************************************************************************************************
class SynthDrum : public Sample{

  public:
    void setup(int f, int l, float m, float p, float n, int beats, int rests){
    noteType=n;
    changePattern(beats, rests);
    id=synthObjects;
    synthObjects++;

    drum[id]->frequency(f);
    drum[id]->length(l);
    drum[id]->secondMix(m);
    drum[id]->pitchMod(p);

  }  
    //*******************************************************************************************************************
  //                                                                                               Play synth drum
  //*******************************************************************************************************************
  void thenLetsParty(){    
    Serial.println("pARTY!");
    drum[id]->noteOn();
  }   
};

//*******************************************************************************************************************
//*******************************************************************************************************************
//*                                                                                           Main Program Space
//*******************************************************************************************************************
//*******************************************************************************************************************


SDSample sample1;
SDSample sample2;
SDSample sample3;
SDSample sample4;

SynthDrum synthD1;
SynthDrum synthD2;
SynthDrum synthD3;
SynthDrum synthD4;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);  
  delay(500);
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_YELLOW);
  tft.setFont(Arial_24);
  //tft.setTextSize(3);
  tft.setCursor(40, 8);
  tft.println("DEADBEEF");


  
  AudioMemory(20);
  sgtl5000_1.enable();
  sgtl5000_1.volume(0.8);
  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }
  delay(1000);
  float vol=.65;
  mixer1.gain(0, vol*.5);
  mixer1.gain(1, vol*.5);
  mixer2.gain(0, vol*.5);
  mixer2.gain(1, vol*.5);
  amp1.gain(vol);
  amp2.gain(vol);
  amp3.gain(vol);
  amp4.gain(vol);
  amp5.gain(vol);
  amp6.gain(vol);
  mixer3.gain(0, vol);
  mixer3.gain(1, vol);
  mixer3.gain(2, vol);
  mixer3.gain(3, vol);
  mixer4.gain(0, vol);
  mixer4.gain(1, vol);
  mixer3.gain(2, vol);
  mixer3.gain(3, vol);
  masterMix.gain(0, 1);
  masterMix.gain(3, 1);

  freeverb1.roomsize(.5);
  freeverb2.roomsize(0);
  freeverb3.roomsize(0);
  freeverb4.roomsize(0);
  freeverb5.roomsize(.5);
  freeverb6.roomsize(0);
  freeverb7.roomsize(0);
  freeverb8.roomsize(0);
  freeverb1.damping(.75);
  freeverb2.damping(0);
  freeverb3.damping(0);
  freeverb4.damping(0);
  freeverb5.damping(.75);
  freeverb6.damping(0);
  freeverb7.damping(0);
  freeverb8.damping(0);
  
  sample1.setup("D_808", "asia.wav", HALFNOTE,5,3);
 // sample2.setup("D_808", "damn.wav", EIGHTHNOTE,1,1);
  sample3.setup("D_808", "icehat.wav", SIXTEENTHNOTE,2,1);  
//  sample4.setup("D_808", "asia.wav", QUARTERNOTE,5,3);

  synthD1.setup(120, 500, 0.55, 1, QUARTERNOTE, 5,7);
  synthD2.setup(60, 250, 0.25, .5, QUARTERNOTE, 3,5);
  synthD3.setup(440, 500, 1, 1, EIGHTHNOTE, 3,2);
  synthD4.setup(440, 500, 1, 1, QUARTERNOTE, 1,7);
}
elapsedMillis msec;
void loop() {
// Mixer 1
  sample1.loop();
//  sample2.loop();
// Mixer 2
//sample3.loop();
 // sample4.loop();
// Mixer 3
// sample5.loop();
//  sample6.loop();
// Mixer 4
//  sample7.loop();  

  synthD1.loop();
//  synthD2.loop();
  synthD3.loop();
//  synthD4.loop();

  if(msec>500){
    msec=0;
    Serial.print("Memory: ");
    Serial.println(freeMemory());
  }
}
 
Got it! Must be obvious to most of the folks here, but I'm still so new at this. From this post:

On Teensy_4 the SPI doesn't have the ability to use hardware specific CS pins in the same special T_3.x way - so any available digital pin can be used for CS

So instead of using 10 for the screen, I just moved it to pin 14.

Thanks again!!
 
Status
Not open for further replies.
Back
Top