Is there any short of incompatibility between audioshield and XPT2046_Touchscreen???

Status
Not open for further replies.
teensy 3.6 + audioshield(i2s) + ILI9341_t3 + XPT2046_Touchscreen :(
Everything works perfect by its own... but when i merge code...

Hi, im playing around the teensy batdetector first coded by DD4WH.

I have the Screen working no problem with the audio shield but as soon as i try to include and initialice the touchscreen AUDIOSHIELD coms freeze.

Im using the alternative pinout described in Sin título.png.

Everything works nicely but when i put the command ts.begin(); in setup();
communication stops between audioshield and teensy 3.6
 
Last edited:
My code:
Code:
/***********************************************************************
 * 
 * first version ultrasound detector 
 * using higher sample rate code by Frank Boesing 
 * 
 * https://forum.pjrc.com/threads/38988-Bat-detector
 * 
 * Frank DD4WH 2016_10_31
 * 
 *  first experiment 
 */

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <Metro.h>
#include "font_Arial.h"
#include <ILI9341_t3.h>

#include <XPT2046_Touchscreen.h>

#define BACKLIGHT_PIN 0

#define TFT_DC      20
#define TFT_CS      21
#define TFT_RST     32  // 255 = unused. connect to 3.3V
#define TFT_MOSI     7
#define TFT_SCLK    14
#define TFT_MISO    12

#define CS_PIN  8
#define TIRQ_PIN  2
XPT2046_Touchscreen ts(CS_PIN);

ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

Metro five_sec=Metro(2000); // Set up a 0.5 second Metro

// this audio comes from the codec by I2S2

AudioInputI2S            i2s_in; 
           
AudioRecordQueue         Q_in_L;    
AudioRecordQueue         Q_in_R;    

AudioPlayQueue           Q_out_L; 
AudioPlayQueue           Q_out_R; 
AudioAnalyzeFFT256  myFFT;
AudioOutputI2S           i2s_out;           
AudioConnection          patchCord1(i2s_in, 0, Q_in_L, 0);
AudioConnection          patchCord2(i2s_in, 1, Q_in_R, 0);
AudioConnection      patchCord5(Q_out_R,0,myFFT,0); 
AudioConnection          patchCord3(Q_out_L, 0, i2s_out, 1);
AudioConnection          patchCord4(Q_out_R, 0, i2s_out, 0);
AudioControlSGTL5000     sgtl5000_1;     //xy=265.212

int idx_t = 0;
int idx = 0;
int64_t sum;
float32_t mean;
int n_L;
int n_R;
long int n_clear;
int8_t mic_gain = 0; // start detecting with this MIC_GAIN in dB 1MIN TO 7MAX
int peak[512];
int barm[512];

ulong samp_ptr = 0;
bool FFT_state = false;

//const int myInput = AUDIO_INPUT_LINEIN;
const int myInput = AUDIO_INPUT_MIC;

// We're only processing one buffer at a time so the
// number of samples is fixed at 128
#define BUFFER_SIZE 128

float32_t float_buffer_L [BUFFER_SIZE];
float32_t float_buffer_R [BUFFER_SIZE];
float32_t float_buffer_L_3 [BUFFER_SIZE];
float32_t float_buffer_R_3 [BUFFER_SIZE];

void setup() {
  Serial.begin(115200);
  delay(1000);
  ts.begin();


  // Audio connections require memory. and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(100);

  // Enable the audio shield. select input. and enable output
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(myInput);
  sgtl5000_1.volume(0.5);
  sgtl5000_1.adcHighPassFilterDisable(); // does not help too much!
  setI2SFreq (96000); // this works perfectly
//  setI2SFreq (192000); this sucks with a Teensy 3.5 (because of the slow display driver)
  AudioNoInterrupts();
  sgtl5000_1.micGain (mic_gain);
  AudioInterrupts();
  pinMode( BACKLIGHT_PIN, OUTPUT );
  analogWrite( BACKLIGHT_PIN, 1023 );

  tft.begin();
  tft.setRotation( 3 );
  tft.fillScreen(ILI9341_BLACK);
  tft.setCursor(10, 1);
  tft.setTextSize(2);
  tft.setTextColor(ILI9341_WHITE);
  tft.setFont(Arial_14);
  tft.print("Floating point audio processing");


 /****************************************************************************************
 *  begin to queue the audio from the audio library
 ****************************************************************************************/
    delay(100);
    Q_in_L.begin();
    Q_in_R.begin();    
} // END SETUP


int16_t *sp_L;
int16_t *sp_R;

void loop() {
 if(ts.touched()){
    tft.fillScreen(ILI9341_BLUE);
 }
 elapsedMicros usec = 0;
/**********************************************************************************
 *  Get samples from queue buffers
 **********************************************************************************/

    // this is supposed to prevent overfilled queue buffers
    if (Q_in_L.available() > 3 || Q_in_R.available() > 3) {
      Q_in_L.clear();
      Q_in_R.clear();
      n_clear ++; // just for debugging to check how often this occurs
    }
    // is there at least one buffer in each channel available ?
    if (Q_in_L.available() >= 1 && Q_in_R.available() >= 1)
    {   
    sp_L = Q_in_L.readBuffer();
    sp_R = Q_in_R.readBuffer();

      // convert to float
     arm_q15_to_float (sp_L, float_buffer_L, BUFFER_SIZE); // convert int_buffer to float 32bit
     arm_q15_to_float (sp_L, float_buffer_R, BUFFER_SIZE); // convert int_buffer to float 32bit
     Q_in_L.freeBuffer();
     Q_in_R.freeBuffer();

/**************************************************************************
 * From here, all the 32 bit float audio processing can start
 * ************************************************************************/

      
/**************************************************************************
 * END of 32 bit float audio processing
 * ************************************************************************
 */
    sp_L = Q_out_L.getBuffer();
    sp_R = Q_out_R.getBuffer();
    arm_float_to_q15 (float_buffer_L, sp_L, BUFFER_SIZE); 
    arm_float_to_q15 (float_buffer_R, sp_R, BUFFER_SIZE); 
      Q_out_L.playBuffer(); // play it !
      Q_out_R.playBuffer(); // play it !

/**********************************************************************************
 *  PRINT ROUTINE FOR ELAPSED MICROSECONDS
 **********************************************************************************/
 
      sum = sum + usec;
      idx_t++;
      if (idx_t > 1000) {
          tft.fillRect(240,50,90,20,ILI9341_BLACK);   
          tft.setCursor(240, 50);
          mean = sum / idx_t;
          tft.print (mean);
          Serial.print (mean);
          Serial.print (" microsec for 2 stereo blocks    ");
          Serial.println();
          idx_t = 0;
          sum = 0;
         
      }

     }
/**********************************************************************************
 *  PRINT ROUTINE FOR AUDIO LIBRARY PROCESSOR AND MEMORY USAGE
 **********************************************************************************/
          if (five_sec.check() == 1)
    {
      Serial.print("Proc = ");
      Serial.print(AudioProcessorUsage());
      Serial.print(" (");    
      Serial.print(AudioProcessorUsageMax());
      Serial.print("),  Mem = ");
      Serial.print(AudioMemoryUsage());
      Serial.print(" (");    
      Serial.print(AudioMemoryUsageMax());
      Serial.println(")");
      Serial.print("Cleared the audio buffer ");    
      Serial.print(n_clear); Serial.println (" times. ");

/*      tft.fillRect(100,120,200,80,ILI9341_BLACK);
      tft.setCursor(10, 120);
      tft.setTextSize(2);
      tft.setTextColor(ILI9341_WHITE);
      tft.setFont(Arial_14);
      tft.print ("Proc = ");
      tft.setCursor(100, 120);
      tft.print (AudioProcessorUsage());
      tft.setCursor(180, 120);
      tft.print (AudioProcessorUsageMax());
      tft.setCursor(10, 150);
      tft.print ("Mem  = ");
      tft.setCursor(100, 150);
      tft.print (AudioMemoryUsage());
      tft.setCursor(180, 150);
      tft.print (AudioMemoryUsageMax());
     */ 
      AudioProcessorUsageMaxReset();
      AudioMemoryUsageMaxReset();
    }
   spectrum();
}


 void spectrum() { // spectrum analyser code by rheslip - modified
     if (myFFT.available()) {
    int scale;
    scale = 2;
  for (int16_t x=2; x < 100; x+=1) {

     int bar = (abs(myFFT.output[x]) * scale);
     if (bar >180) bar=180;
     // this is a very simple IIR filter to smooth the reaction of the bars
     bar = 0.05 * bar + 0.95 * barm[x]; 
//     if (bar > peak[x]) peak[x]=bar;
//     tft.drawFastVLine(x, 210-bar,bar, ILI9341_PURPLE);
//     tft.drawFastVLine(x*2+10, 210-bar,bar, ILI9341_PINK);

     tft.drawPixel(x*2+10, 210-barm[x], ILI9341_BLACK);
     tft.drawPixel(x*2+10, 210-bar, ILI9341_WHITE);

//     tft.drawFastVLine(x*2+10, 20, 210-bar-20, ILI9341_BLACK);    

//     tft.drawPixel(x*2+10,209-peak[x], ILI9341_YELLOW);

     if(peak[x]>0) peak[x]-=1;
     barm[x] = bar;
  }
  } //end if

   } // end void spectrum

// sample rate routine by Frank Boesing
void setI2SFreq(int freq) {
  typedef struct {
    uint8_t mult;
    uint16_t div;
  } tmclk;

  const int numfreqs = 14;
  const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, (int)44117.64706 , 48000, 88200, (int)44117.64706 * 2, 96000, 176400, (int)44117.64706 * 4, 192000};

#if (F_PLL==16000000)
  const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
#elif (F_PLL==72000000)
  const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
#elif (F_PLL==96000000)
  const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
#elif (F_PLL==120000000)
  const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
#elif (F_PLL==144000000)
  const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
#elif (F_PLL==180000000)
  const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
#elif (F_PLL==192000000)
  const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
#elif (F_PLL==216000000)
  const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
#elif (F_PLL==240000000)
  const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
#endif

  for (int f = 0; f < numfreqs; f++) {
    if ( freq == samplefreqs[f] ) {
      while (I2S0_MCR & I2S_MCR_DUF) ;
      I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
      return;
    }
  }
}

its just Frank code but adding touchscreen capabilities, as a example i just made it turn everything blue when touched.
As soon as i do ts.begin() audioshield stops working, the screen remains working perfect on its own
 
Is there any way to tell the touch screen controller that SPI clock is on pin 14? Or is it overriding things back to pin 13?

Having a look in the library init section may give you a lead on either commenting out setup line or the format to use a longer begin string like the LCD uses.
 
Look at use of this when the interrupt pin is to be specified:: XPT2046_Touchscreen ts(CS_PIN);

Odd it isn't shown here display_ili9341_touch.html

But if you look here 'github.com/PaulStoffregen/XPT2046_Touchscreen' ( or at library examples ) you'll find:
Code:
The use of the Touch interrupt pin can be optionally specified. If the Teensy pin specified is actively connected to the T_IRQ display pin then the normal touch calls will respond, but can be called more often as each call returns without hardware access when no interrupt was recorded.
#define TIRQ_PIN  2
[B]XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);[/B]

Offhand I'm not sure why this might be affecting your code as I only got that far. But when the IRQ pin is given and connected the Touch Library can be less intrusive to the SPI. One of the examples should show how to use this for no SPI transfer until actual touch happens.

The real problem may be in this from the github :: "The digital pin used for chip select is required. The normal MISO, MOSI and SCK pins will be used automatically."

Where the Display has selectors for SPI pins as used:: ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

I've worked with the XPT2046_Touchscreen - and offered the INT detection code - but I've never used it anywhere but default SPI? I'm not sure if it 'piggybacks' on the ILI9341 SPI settings? If not it will be messing with pins 11 and 13?

If the Pin13_LED blinks on Touch checks like 'ts.getPoint' then the pins have not moved for Touch data. [ may need to disable audio to confirm this if it is already blinking? ]

Paul/KurtE? In the Touch code I don't see explicit MOSI/MISO/SCLK pins called out like in the display driver.

Does changing the above code as follows do anything?
Code:
[B]ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);[/B]
#define CS_PIN  8
#define TIRQ_PIN  2
[U]XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);[/U]
 
Look at use of this when the interrupt pin is to be specified:: XPT2046_Touchscreen ts(CS_PIN);

Odd it isn't shown here display_ili9341_touch.html

But if you look here 'github.com/PaulStoffregen/XPT2046_Touchscreen' ( or at library examples ) you'll find:
Code:
The use of the Touch interrupt pin can be optionally specified. If the Teensy pin specified is actively connected to the T_IRQ display pin then the normal touch calls will respond, but can be called more often as each call returns without hardware access when no interrupt was recorded.
#define TIRQ_PIN  2
[B]XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);[/B]

Offhand I'm not sure why this might be affecting your code as I only got that far. But when the IRQ pin is given and connected the Touch Library can be less intrusive to the SPI. One of the examples should show how to use this for no SPI transfer until actual touch happens.

The real problem may be in this from the github :: "The digital pin used for chip select is required. The normal MISO, MOSI and SCK pins will be used automatically."

Where the Display has selectors for SPI pins as used:: ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);

I've worked with the XPT2046_Touchscreen - and offered the INT detection code - but I've never used it anywhere but default SPI? I'm not sure if it 'piggybacks' on the ILI9341 SPI settings? If not it will be messing with pins 11 and 13?

If the Pin13_LED blinks on Touch checks like 'ts.getPoint' then the pins have not moved for Touch data. [ may need to disable audio to confirm this if it is already blinking? ]

Paul/KurtE? In the Touch code I don't see explicit MOSI/MISO/SCLK pins called out like in the display driver.

Does changing the above code as follows do anything?
Code:
[B]ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RST, TFT_MOSI, TFT_SCLK, TFT_MISO);[/B]
#define CS_PIN  8
#define TIRQ_PIN  2
[U]XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);[/U]

I tried XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);, same result

I managed to simply digitalRead(TIRQ_PIN) each loop because i just need to know when the touchscreen is pressed, i dont need the specific position.

After some testing you were right:
XPT2046_Touchscreen ts(CS_PIN); uses defaut SPI PINS killing audioshield spi coms,

if i have time i will work in a <XPT2046_Touchscreen.h> library
that uses the constructor like this
Code:
XPT2046_Touchscreen  ts = XPT2046_Touchscreen (ts_CS, ts_IRQ, ts_RST, ts_MOSI, ts_SCLK,ts_MISO);
 
Perhaps a quick test with code like this from ILI9341_t [ ...\hardware\teensy\avr\libraries\ILI9341_t3\ILI9341_t3.cpp ]- with hardcoded values for the two changed pins would give quick feedback:
Code:
void ILI9341_t3::begin(void)
{
    // verify SPI pins are valid;
    #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
    if ((_mosi == 11 || _mosi == 7 || _mosi == 28) && (_miso == 12 || _miso == 8 || _miso == 39) 
    		&& (_sclk == 13 || _sclk == 14 || _sclk == 27)) {
	#else
    if ((_mosi == 11 || _mosi == 7) && (_miso == 12 || _miso == 8) && (_sclk == 13 || _sclk == 14)) {
    #endif	
[B]        SPI.setMOSI(_mosi);
        SPI.setMISO(_miso);
        SPI.setSCK(_sclk);[/B]
	} else
        return; // not valid pins...
	[U]SPI.begin();[/U]

You can copy the [ …\hardware\teensy\avr\libraries\XPT2046_Touchscreen ] to sketchbook libraries to make local changes and see it used in Verbose Console.
Code:
bool XPT2046_Touchscreen::begin()
{
 // insert proper SPI.set's here
	[U]SPI.begin();[/U]

Once working maybe this from XPT...Touch:: #define SPI_SETTING SPISettings(2000000, MSBFIRST, SPI_MODE0)

could run faster like in the ILI9341_t3 ::
Code:
// Teensy 3.1 can only generate 30 MHz SPI when running at 120 MHz (overclock)
// At all other speeds, SPI.beginTransaction() will use the fastest available clock
#define SPICLOCK 30000000

// ...
SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE0));
 
Status
Not open for further replies.
Back
Top