Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 2 of 2

Thread: T4.0 ILI9341_t3. DemoSauce WavFilePlayer mashup causes crashes

  1. #1
    Senior Member
    Join Date
    Dec 2015
    Location
    LA
    Posts
    202

    T4.0 ILI9341_t3. DemoSauce WavFilePlayer mashup causes crashes

    As title suggests playing wave files while displaying DemoSauce causes a crash when the '_twistyText' animation runs.
    On Mac, I'm using Arduino 1.8.13, TL1.54-beta7 with PJRC T4, 320x240 display and a T3 audio board painfully converted some year ago to work on T4.

    The example program 'DemoSauce' for the T4.0 has had only the .ino file modified as below to match my setup and merge WavFilePlayer so it will play the animations with music except, skipping the first occurrence of twistyText to avoid an immediate crash. The interesting spot is at //mdr309 where if you un-comment the line, sound playing is turned off for twisty and the animations will run for many minutes to hours depending on who knows what. It will eventually crash in the '_checkerboard' animation however. Longer run times with no arduino serial monitor and longer still if wall wort.

    The changes from the original are commented with //mdr You should start with the T4, example DemoSauce. Then substitute the below for the DemoSauce.ino

    Removed the microphone stuff and random animation selection to simplify and help debug.
    Added the XPT2046_Touchscreen stuff because if I don't have its .begin() I get noise in the audio. (I don't want to unhook the touchscreen)

    Code:
    /***************************************************
                     **  DemoSauce!  **
      State-of-the-art graphics for your beautiful TFT display.
    
      Greetz to the Portland Dorkbot Crew!!!!
    
             Programmed by Zach Archer (@zkarcher)  ::  http://controlzinc.com/
      Using hardware by Thomas Hudson (@hydronics)  ::  http://thomashudson.org/
    
      Usage:
        * Connect a microphone to MIC_PIN.
        * Connect TFT backlight to BACKLIGHT_PIN.
    
      MIT license, all text above must be included in any redistribution
     ****************************************************/
    
    // https://github.com/zkarcher/demosauce
    
    #include "SPI.h"
    #include "ILI9341_t3.h"
    #include "font_Arial.h"
    #include <XPT2046_Touchscreen.h>    //mdr
    #include <Audio.h>    //mdr
    
    #include "FrameParams.h"
    
    // Animations
    #include "Checkerboard.h"
    #include "Cube3D.h"
    #include "Leaves.h"
    #include "MagentaSquares.h"
    //#include "MicCheck.h"
    #include "PlasmaCloud.h"
    #include "PlasmaYellow.h"
    #include "Sphere3D.h"
    #include "TriangleWeb.h"
    #include "TwistyText.h"
    #include "Waveform.h"
    
    // Transitions
    #include "TransitionDither.h"
    #include "TransitionHalftone.h"
    #include "TransitionScroll.h"
    #include "TransitionSquares.h"
    
    const boolean DO_BENCHMARKS = true;
    const uint32_t SERIAL_BAUD_RATE = 9600;
    
    const boolean DEBUG_ANIM = false; // dev: for hacking on one animation.
    const uint_fast8_t DEBUG_ANIM_INDEX = 0;
    
    const boolean DEBUG_TRANSITION = false;  // dev: set to true for short animation durations
    const int_fast8_t DEBUG_TRANSITION_INDEX = -1;  // Supports -1: chooses a transition at random
    
    const int_fast16_t DEFAULT_ANIM_TIME = 7.0f * 1000.0f;  // ms mdr changed to 7 seconds from 20
    
    // TFT pins
    const uint8_t TFT_DC = 5;    //mdr yours might be different
    const uint8_t TFT_CS = 9;    //mdr yours might be different
    const uint8_t MIC_PIN = 14;
    const uint8_t BACKLIGHT_PIN = 23;
    
    // Use these with the Teensy Audio Shield and Teesny 4.0  mdr20190823
    #define SDCARD_CS_PIN    10    //mdr yours might be different
    
    // Pin assignment for T4 XPT2046_Touchscreen
    #define T_CS_PIN  4    //mdr yours might be different
    #define TIRQ_PIN  3    //mdr yours might be different
    
    // Use hardware SPI (#13, #12, #11) and the above for CS/DC
    ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
    XPT2046_Touchscreen ts(T_CS_PIN, TIRQ_PIN);  // mdr get buzzing if connected and not inialized
    AudioPlaySdWav           playWav1;    //mdr
    // Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC
    AudioOutputI2S           audioOutput;    //mdr
    AudioConnection          patchCord1(playWav1, 0, audioOutput, 0);    //mdr
    AudioConnection          patchCord2(playWav1, 1, audioOutput, 1);    //mdr
    AudioControlSGTL5000     sgtl5000_1;    //mdr
    
    FrameParams frameParams;
    long previousMillis = 0;
    
    Checkerboard * _checkerboard       = new Checkerboard();
    Cube3D * _cube3D                   = new Cube3D();
    Leaves * _leaves                   = new Leaves();
    MagentaSquares * _magentaSquares   = new MagentaSquares();
    PlasmaCloud * _plasmaCloud         = new PlasmaCloud();
    PlasmaYellow * _plasmaYellow       = new PlasmaYellow();
    Sphere3D * _sphere3D               = new Sphere3D();
    TriangleWeb * _triangleWeb         = new TriangleWeb();
    TwistyText * _twistyText           = new TwistyText();
    Waveform * _waveform               = new Waveform();
    
    TransitionDither * _transDither  = new TransitionDither();
    TransitionHalftone * _transHalftone  = new TransitionHalftone();
    TransitionScroll * _transScroll  = new TransitionScroll();
    TransitionSquares * _transSquares  = new TransitionSquares();
    
    BaseAnimation **anims; // Array of pointers to BaseAnimation's. Initialized in setup() below.
    int_fast8_t animCount;
    
    BaseAnimation *activeAnim = 0;
    int_fast16_t animTimeLeft = 0;
    BaseAnimation *nextAnim;
    
    BaseTransition **transitions;
    int_fast8_t transCount;
    boolean isTransition = true;
    BaseTransition *activeTransition = 0;
    
    // Benchmarks
    uint32_t frameCount;
    
    // Search the anims[] aray for the activeAnim pointer. If found, return the array index.
    int_fast8_t getActiveAnimIndex() {
      for( int_fast8_t i=0; i<animCount; i++ ) {
        if( anims[i] == activeAnim ) return i;
      }
      return -1;  // not found
    }
    
    void setup() {
      // Backlight
      //pinMode( BACKLIGHT_PIN, OUTPUT );    //mdr not using
      //analogWrite( BACKLIGHT_PIN, 1023 );
    
      // Audio connections require memory to work.  For more
      // detailed information, see the MemoryAndCpuUsage example
      AudioMemory(5);    //mdr  max seems to be 4
    
      // Comment these out if not using the audio adaptor board.
      // This may wait forever if the SDA & SCL pins lack
      // pullup resistors
      sgtl5000_1.enable();    //mdr
      sgtl5000_1.volume(0.25);    //mdr
    
      // Microphone
      pinMode( MIC_PIN, INPUT );    //mdr not using
    
      tft.begin();
      tft.setRotation( 1 );
      tft.fillScreen(ILI9341_BLACK);
    
      ts.begin();  // mdr get buzzing if connected and not inialized
      ts.setRotation(2);    //mdr
      
      Serial.begin( SERIAL_BAUD_RATE );
      while (!Serial && millis() < 2000)
        ;
    
      // Serial
      if( DO_BENCHMARKS ) {
        tft.setTextColor(ILI9341_YELLOW);
        tft.setFont(Arial_18);
        tft.setCursor(10, 30);
        tft.print("myT4_demoSauce_Audio");    //mdr changed displayed text on no serial
        tft.setCursor(80, 90);
        tft.print("waiting for");
        tft.setCursor(60, 120);
        tft.print("Serial Monitor");
        tft.setTextColor(ILI9341_GREEN);
        tft.setFont(Arial_18);
        while (!Serial && millis() < 8000) { // wait for Arduino Serial Monitor
          tft.fillRect(118, 182, 42, 18, ILI9341_BLACK);
          tft.setCursor(118, 182);
          tft.print((8000.0 - (float)millis()) / 1000.0, 1);
          tft.print(" sec");
          delay(100);
        }
      }
      previousMillis = millis();
    
      // Clear
      uint16_t w = tft.width();
      uint16_t h = tft.height();
      tft.fillRect( 0, 0, w, h, 0x0 );
    
      tft.setScroll( 0 );
    
      // Populate anims in the order you want them to display.
      BaseAnimation* ANIMS_TEMP[] = {
        _twistyText,
        _plasmaCloud,
        _waveform,
        _magentaSquares,
        _sphere3D,
        _checkerboard,
        _leaves,
        _cube3D,
        _plasmaYellow,
        _triangleWeb
      };
      animCount = sizeof( ANIMS_TEMP ) / sizeof( BaseAnimation* );
    
      // Retain ANIMS_TEMP objects permanently
      anims = (BaseAnimation**)malloc( animCount * sizeof(BaseAnimation*) );
      for( int_fast8_t i=0; i<animCount; i++ ) {
        anims[i] = ANIMS_TEMP[i];
        anims[i]->init( tft );      // Initalize all animations
      }
    
      BaseTransition* TRANS_TEMP[] = {
        _transDither,
        _transHalftone,
        _transScroll,
        _transSquares
      };
      transCount = sizeof( TRANS_TEMP ) / sizeof( BaseTransition* );
    
      // Retain TRANS_TEMP objects permanently
      transitions = (BaseTransition**)malloc( transCount * sizeof(BaseTransition*) );
      for( int_fast8_t i=0; i<transCount; i++ ) {
        transitions[i] = TRANS_TEMP[i];
        transitions[i]->init( tft );
      }
    
      // Start!
      if( !activeAnim ) {
        if( DEBUG_ANIM ) {
          startAnimation( anims[DEBUG_ANIM_INDEX] );
        } else {
          startAnimation( anims[0] );
        }
      }
    
      if (!(SD.begin(SDCARD_CS_PIN))) {    //mdr
        // stop here, but print a message repetitively
        while (1) {
          Serial.println("Unable to access the SD card");
          delay(500);
        }
      }
    }
    
    void startAnimation( BaseAnimation *newAnim ) {
      isTransition = false;
    
      activeAnim = newAnim;
      tft.fillScreen( activeAnim->bgColor() );
      tft.setScroll( 0 );
      activeAnim->reset( tft );
    
      animTimeLeft = DEFAULT_ANIM_TIME;
    
      if( DEBUG_TRANSITION ) animTimeLeft = 2000;
    
      if( DO_BENCHMARKS ) {
        Serial.println("---");
        Serial.print( activeAnim->title() );
    
        if( activeAnim->willForceTransition() ) {
          // TwistyText does not obey DEFAULT_ANIM_TIME
          Serial.println("");
    
        } else {
          Serial.print("  [");
          Serial.print( (uint8_t)(animTimeLeft / 1000.0f) );
          Serial.print(" secs]  AudioMemoryUsageMax ");    //mdr added
          Serial.println(AudioMemoryUsageMax());
        }
    
        frameCount = 0;
      }
    }
    
    void loop() {
      // Frame multiplier
      long newMillis = millis();
      uint_fast8_t elapsed = newMillis - previousMillis;
      previousMillis = newMillis;
      frameParams.timeMult = elapsed * (60.0f / 1000);  // 1.0==exactly 60fps. 4.0==15fps, 4x slower
    
      // Get some audio input
      const uint_fast8_t SAMPLES_PER_FRAME = 1;
      frameParams.audioPeak = 0;
      uint_fast16_t sum = 0;
    
      for( uint_fast8_t s=0; s<SAMPLES_PER_FRAME; s++ ) {
        uint_fast16_t sample = abs( random(0,511) );    //mdr nice effects with no mic
        frameParams.audioPeak = max( frameParams.audioPeak, sample );
        sum += sample;
      }
      frameParams.audioMean = sum * (1.0 / (512*SAMPLES_PER_FRAME));  // Range: 0..1
    
      frameParams.audioPeak = min( (uint_fast16_t)frameParams.audioPeak, (uint_fast16_t)511 );
    
      if( !isTransition ) {
        activeAnim->perFrame( tft, frameParams );
        animTimeLeft -= elapsed;
    
        if( DO_BENCHMARKS ) frameCount++;
      }
    
      // Has this animation expired?
      boolean willForceTransition = activeAnim->willForceTransition();
      boolean forceTransitionNow = activeAnim->forceTransitionNow();
    
      // Debugging transitions: Ignore animations hogging the screen
      if( DEBUG_TRANSITION ) willForceTransition = false;
    
      if( !DEBUG_ANIM ) {
        if( (!willForceTransition && (animTimeLeft <= 0)) || forceTransitionNow ) {
    
          // If the transition has not started yet, then start it.
          if( !isTransition ) {
            isTransition = true;
    
            nextAnim = anims[ (getActiveAnimIndex() + 1) % animCount ];
            if(_twistyText==nextAnim){    //mdr309 don't play if twistyText or crash
                //playWav1.stop();    //mdr un-comment this to prevent crash on twistyText
            }else if(!playWav1.isPlaying()){
                playWav1.play("SDTEST1.WAV"); //start playing
            }
    
            // Choose a random transition
            activeTransition = transitions[ random(transCount) ];
            if( DEBUG_TRANSITION && (DEBUG_TRANSITION_INDEX >= 0) ) {
              activeTransition = transitions[ DEBUG_TRANSITION_INDEX ];
            }
    
            activeTransition->restart( tft, nextAnim->bgColor() );
    
            // Benchmark: show how many frames the animation completed while alive.
            if( DO_BENCHMARKS ) {
              Serial.print("Frame count (more is better):  ");
              Serial.print( frameCount );
    
              if( !activeAnim->willForceTransition() ) {
                Serial.print( "  (" );
                Serial.print( (float)frameCount / (DEFAULT_ANIM_TIME / 1000.0f) );
                Serial.println(" FPS)");
              } else {
                Serial.println("");
              }
            }
          }
    
          // After the transition ends, advance to the next animation
          activeTransition->perFrame( tft, frameParams );
          if( activeTransition->isComplete() ) {
            startAnimation( nextAnim );
          }
    
        }
      }
    
    }
    I'm hoping someone can try this on an T4 version(Rev D) audio board to confirm the issue.
    Last edited by bicycleguy; 04-08-2021 at 11:55 PM. Reason: added

  2. #2
    Senior Member
    Join Date
    Dec 2015
    Location
    LA
    Posts
    202
    Forgot to mention, you don't need to be attached to a display to see the problem, although it's not very interesting. You can hear the music in headphones. It will crash when it gets to twistyText as shown in the terminal. If you un-comment the line after //mdr309 when it gets there the sound will stop and then start again in ~20sec when the next animation starts.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •