Challenges Integrating Teensy4.1 Audio, SD Card and LVGL - use SDIO?

Rich235

Member
First, thanks for the amazing work on Teensy and all its libraries - a truly wonderful achievement.

I have Teensy 4.1 and LVGL and dual 240x240 displays working great, taking images from the SD Card with animated GIFs and other animations on the screens.

I also have Teensy Audio playing sounds in the background from waveforms in .h files.

Finally, I have some 3-5 sec WAV files in the SD Card and it can play those on occasion also.

However, what I cannot achieve is showing a GIF animation or updating an image from SD Card at the same time as playing a WAV file. As long as they don't try to use the SD Card together, it seems to hang together. If they try to use it together, they stall each other, just about get through it stutteringly and after a few attempts crashes the SD card and graphics. Interestingly the waveform audio keeps on playing in the background despite everything else including Serial being unresponsive.

I'm trying to show a 3 second GIF animation with sound at the same time.

I'm using
Code:
SD.begin(BUILTIN_SDCARD);

Am I correct to assume that will always struggle with different libraries requesting SD Card access at the same time? (I can play multiple WAV files at the same time Audio only fine.)

Would moving to SDIO help?

I've tried Teensy 4.1 audio on its own with
Code:
SD.sdfs.begin(BUILTIN_SDCARD);
and that works great and seems smoother and removes a few artifacts on the first ~100ms of the WAV file playback. However, that is not compatible with my LVGL implementation.

If you think that will help, I'll look in to fixing the LVGL - on first attempts it looks challenging (memory allocation and freeing FsFile, seek and other differences).

I did wonder also if it was a shared timer conflict? How can I test for that?

Thanks for any advice. Happy to post my code but its just general advise I'm after first!

(I'm using Platformio, framework-arduinoteensy 1.155.0 (1.55) and LVGL 8.1.)
 
The T_4.1 PCB SD card is only accessed with SDIO.

TD 1.55 makes use of the SdFat library - though .sdfs. may offer improvement using better optimized access code.

There is benchmark code - give it a run against the SD card in use - maybe it isn't the best performer? There is a recently active thread showing best found cards for responsiveness.
 
Thanks for the tip! I'm assuming this is not a good result (after a fresh FAT32 format):
Code:
Type any character to start
Create files
Create micros: 5204191
Sequential Write: 3136.47 KB/sec
Begin Random Read Test
ns - read size sectors, nf - number of files, maxLat - latency micros
ns: 64 nf: 1 maxLat: 3451 total KB/sec: 15492.46 file KB/sec: 15492.46
ns: 64 nf: 2 maxLat: 3895 total KB/sec: 8592.67 file KB/sec: 4296.33
ns: 32 nf: 1 maxLat: 2444 total KB/sec: 15480.79 file KB/sec: 15480.79
ns: 32 nf: 2 maxLat: 2867 total KB/sec: 6640.21 file KB/sec: 3320.11
ns: 16 nf: 1 maxLat: 2085 total KB/sec: 15472.34 file KB/sec: 15472.34
ns: 16 nf: 2 maxLat: 2479 total KB/sec: 4606.13 file KB/sec: 2303.06
ns: 8 nf: 1 maxLat: 1366 total KB/sec: 15451.59 file KB/sec: 15451.59
ns: 8 nf: 2 maxLat: 1503 total KB/sec: 4367.96 file KB/sec: 2183.98
ns: 4 nf: 1 maxLat: 1276 total KB/sec: 15486.97 file KB/sec: 15486.97
ns: 4 nf: 2 maxLat: 1671 total KB/sec: 2155.83 file KB/sec: 1077.91
ns: 2 nf: 1 maxLat: 1231 total KB/sec: 15379.75 file KB/sec: 15379.75
ns: 2 nf: 2 maxLat: 1625 total KB/sec: 1116.66 file KB/sec: 558.33
ns: 1 nf: 1 maxLat: 1209 total KB/sec: 15338.36 file KB/sec: 15338.36
ns: 1 nf: 2 maxLat: 1602 total KB/sec: 568.02 file KB/sec: 284.01
End Random Read Test
Begin Random Write Test
ns - read size sectors, nf - number of files, maxLat - latency micros
ns: 64 nf: 1 maxLat: 10937 total KB/sec: 13864.55 file KB/sec: 13864.55
ns: 64 nf: 2 maxLat: 483069 total KB/sec: 2528.03 file KB/sec: 1264.02
ns: 32 nf: 1 maxLat: 9583 total KB/sec: 13928.64 file KB/sec: 13928.64
ns: 32 nf: 2 maxLat: 485845 total KB/sec: 1471.85 file KB/sec: 735.92
ns: 16 nf: 1 maxLat: 9293 total KB/sec: 13906.11 file KB/sec: 13906.11
ns: 16 nf: 2 maxLat: 479497 total KB/sec: 1094.28 file KB/sec: 547.14
ns: 8 nf: 1 maxLat: 2894 total KB/sec: 15634.52 file KB/sec: 15634.52
ns: 8 nf: 2 maxLat: 870274 total KB/sec: 262.71 file KB/sec: 131.36
ns: 4 nf: 1 maxLat: 15791 total KB/sec: 9624.29 file KB/sec: 9624.29
ns: 4 nf: 2 maxLat: 276176 total KB/sec: 234.66 file KB/sec: 117.33
ns: 2 nf: 1 maxLat: 15780 total KB/sec: 9511.76 file KB/sec: 9511.76
ns: 2 nf: 2 maxLat: 194296 total KB/sec: 159.03 file KB/sec: 79.51
ns: 1 nf: 1 maxLat: 15776 total KB/sec: 9643.94 file KB/sec: 9643.94
ns: 1 nf: 2 maxLat: 118855 total KB/sec: 98.78 file KB/sec: 49.39
End Random Write Test
Type any character to remove files
Remove micros: 4550974
Done
Do you advise FAT16 or FAT32 for Teensy multiple file reads or makes no difference?

Thanks again. I'll try another card.
 
OK, I've found a much newer card, closer to the results posted at the link you shared (thanks) but exactly the same response. (I've a few others to try also.) The two libraries, I think, don't like each other. I'll dig more deeply then come back with some more useful questions.
 
Thanks. OK, new SD Card. I can play 3 WAV files at the same time and, separately, I can display two massive animated GIFs at the same time at ~30fps, both for hours. So, I think multiple file access within one function type is fine and the speed of the card is fine and there is enough memory.

I can show a small GIF file from SD card but as soon as a WAV file plays the display gets stuck and the sound is just a buzz for ~1/3 sec. Sometimes it will recover and continue showing the GIF but most times it then crashes.

So, my hypothosis is it cannot access another file when WAV is playing.

Looking at the audio library play_sd_wav.cpp, I notice NVIC_DISABLE_IRQ(IRQ_SOFTWARE); and it uses AudioStartUsingSPI() which calls SPI.usingInterrupt(IRQ_SOFTWARE)

I'm wondering if the WAV use of interrupts is upsetting another file read?

Stripping out LVGL and just trying to read a small text file when playing a WAV, that crashes as soon as it trys to read the TXT file.

Here is my code for that test:

Code:
#include <Arduino.h>

// GUItool: begin automatically generated code
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioPlaySdWav           playSdWav1;     //xy=443.8888854980469,369.8888854980469
AudioMixer4              mixer1;         //xy=750.8888854980469,415.8888854980469
AudioOutputI2S           i2s1;           //xy=1314.0000076293945,452.00003695487976
AudioConnection          patchCord1(playSdWav1, 0, mixer1, 0);
AudioConnection          patchCord2(playSdWav1, 1, mixer1, 1);
AudioConnection          patchCord3(mixer1, 0, i2s1, 0);
AudioConnection          patchCord4(mixer1, 0, i2s1, 1);
// GUItool: end automatically generated code

// Audio: ******************************************
//Module Connections
//Pin 7
//Pin 20
//Pin 21

uint32_t timeNow2 = 0;
bool startedWAV = false;

void setup()
{
  //myLVGLtimer.begin(advanceLVGLtic, 15000); //  to run every 1ms

  SD.begin(BUILTIN_SDCARD);
  Serial.begin(115200);

  //Audio Setup: >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  // Audio connections require memory to work.  For more
  // detailed information, see the MemoryAndCpuUsage example
  AudioMemory(10);

  mixer1.gain(0, 0.2);
  mixer1.gain(1, 0.2);

  while (!Serial) {
    ; // wait for serial port to connect.
  }

  Serial.println("Sound and file reading - starting in 2 sec...");
  delay(2000);  //for me to get the terminal running
  
  timeNow2 = millis(); //start timing
}

void openCloseFile()
{
  File myManualFile;

  if (SD.exists("file.txt"))
  {
    Serial.println(">>>>>file.txt exists.");
    myManualFile = SD.open("file.txt", O_RDONLY);

    if (myManualFile)
    {
      Serial.print(">>>>>file.txt Opened! : ");
    }
    myManualFile.seek(3);
    Serial.print(">>>>> Contents from Position ");
    Serial.print(myManualFile.position());
    Serial.print(" = ");

    while (myManualFile.available())
    {
      Serial.write(myManualFile.read());
    }
    // close the file:
    myManualFile.close();
    Serial.println("");
    Serial.println(">>>>>File Closed");
  }
  //End direct file open and read
}

void loop()
{
  if ((millis() - timeNow2 > 1000) && (startedWAV == false))
  {
    playSdWav1.play("PandaOff.wav");
    startedWAV = true;
    Serial.println("Started playing WAV");
  }

  if ((millis() - timeNow2 > 2000) && (playSdWav1.isPlaying()))
  {
    Serial.println("Started trying to read tiny TXT file");
    openCloseFile();
    Serial.println("!!!!!  Finished reading tiny TXT file");
    Serial.println("");
  }

  if (millis() - timeNow2 > 6000)
  {
    timeNow2 = millis();
    startedWAV = false;
    Serial.println("Start again!");
  }
}

View attachment MultiFileTest.zip

This crashes as soon as it trys to read the TXT file:

Code:
Sound and file reading - starting in 2 sec...
Started playing WAV
Started trying to read tiny TXT file <<< crashes ;-(

I notice that if I change the time between the WAV starting and trying to open the TXT file, there is a point when it gets a bit further. Changing if ((millis() - timeNow2 > 2000) && (playSdWav1.isPlaying())) to 3000 it can open, read and close the file a few times before crashing.

I've attached the files I've been using. If you have a T4.1, an I2S sound chip and an SD Card, I'd be really grateful if you can give that a try please?

Is the Audio library written such that you can read a separate file whilst playing a WAV? It can definitely play multiple WAV files, but seems no other file outside the Audio library, unless I'm doing something wrong?

Thanks!
 
I've been testing this a bit more and looking for way around it, but I'm stuck. Fundamentally, does anyone know if it is possible to access files normally from the SD card outside the audio library whilst a WAV file is playing from the SD Card. I can't find a way to do that. Is it a fundamental limitation or is there a tip or setting that is needed? Thanks for your help.
 
Currently, there is no way. Teensyduino does not support anything like that.
Perhaps with SD in SPI mode..

What you can try: Stop the Audio library interrupts, then access the card. This *might* work...
 
That is it!! Thank you Frank B!

I've added, e.g.:
Code:
    AudioNoInterrupts();
    mySDfile = SD.open(buf, O_RDONLY);
    AudioInterrupts();
to all my file functions (open, close, read, seek, tell) and that works perfectly. I can now have Audio via a synth running in the background, play WAV files on top of that and display animated GIFs and other screen animations all at the same time - you have rescued my project! The Teensy 4.1 really is amazing. It is going to be driving triple CAN buses and many other automotive inputs for a dual screen Electric Vehicle control unit with synthetic sound generation for internal sound augmentation and external pedestrian warning sounds.

Thanks again and I hope this helps others.
 
Back
Top