J_Sanders
Active member
Hello,
I'm seeing audio DAC output glitches when reading from Teensy 4.1's onboard microSD card using SDIO.
I'm using Teensyduino 1.54 beta#6.
Here's a sketch that reproduces the issue:
The sketch first writes a file to the card. Then, it reads 64kB from that file into a buffer every 100ms. The data read back from the card is not used.
Meanwhile, the audio buffers are filled with 0's from a dedicated array, unrelated to the card readout. The DAC output should remain at its midpoint, but instead it does this:

And zooming into each spike at 100ms:

My best guess is that the SD DMA channel priority is greater than the audio ISR, and samples are being dropped or misread.
I tried setting the audio ISR priority to maximum in output_i2s.cpp by adding a priority argument:
This didn't help.
Is there a way to make microSD reads from T4's onboard card interruptible? Or is something else at fault here?
Thanks!
-J
I'm seeing audio DAC output glitches when reading from Teensy 4.1's onboard microSD card using SDIO.
I'm using Teensyduino 1.54 beta#6.
Here's a sketch that reproduces the issue:
Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include "SdFat.h"
#define FILE_TRANSFER_BUFFER_SIZE 64000
#define N_BUFFERS_IN_FILE 100
AudioPlayQueue queue1;
AudioPlayQueue queue2;
AudioOutputI2S i2s1;
AudioConnection patchCord1(queue1, 0, i2s1, 0);
AudioConnection patchCord2(queue2, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1;
// MicroSD vars
SdFs SDcard;
FsFile Wave0; // File on microSD card
byte fileTransferBuffer[FILE_TRANSFER_BUFFER_SIZE] = {0};
uint32_t playbackFilePos = 0;
bool ready = false; // SD busy flag
int16_t Zeros[256] = {0}; // An empty audio waveform
uint32_t startTime = 0;
uint32_t currentTime = 0;
void setup() {
AudioMemory(2);
sgtl5000_1.enable();
sgtl5000_1.volume(0.5);
SDcard.begin(SdioConfig(FIFO_SDIO));
writeTestFile();
Wave0 = SDcard.open("Wave0.wfm", O_RDWR | O_CREAT);
Wave0.seek(0);
startTime = micros();
}
void loop() {
//------ Fill audio buffers-------
int16_t *p1 = queue1.getBuffer();
int16_t *p2 = queue2.getBuffer();
memcpy(p1, Zeros, 256);
memcpy(p2, Zeros, 256);
queue1.playBuffer();
queue2.playBuffer();
//------ Read a buffer of data from microSD card every 100ms (disrupts playback!) -----
currentTime = micros();
if (currentTime - startTime > 100000) {
startTime = currentTime;
Wave0.read(fileTransferBuffer, FILE_TRANSFER_BUFFER_SIZE);
playbackFilePos += FILE_TRANSFER_BUFFER_SIZE;
if (playbackFilePos > N_BUFFERS_IN_FILE*FILE_TRANSFER_BUFFER_SIZE) {
Wave0.seek(0);
}
}
}
void writeTestFile() {
SDcard.remove("Wave0.wfm");
Wave0 = SDcard.open("Wave0.wfm", O_RDWR | O_CREAT);
Wave0.seek(0);
for (uint32_t i = 0; i < N_BUFFERS_IN_FILE; i++) {
Wave0.write(fileTransferBuffer, FILE_TRANSFER_BUFFER_SIZE);
while (sdBusy()) {}
}
delayMicroseconds(100000);
Wave0.close();
}
bool sdBusy() {
return ready ? SDcard.card()->isBusy() : false;
}
The sketch first writes a file to the card. Then, it reads 64kB from that file into a buffer every 100ms. The data read back from the card is not used.
Meanwhile, the audio buffers are filled with 0's from a dedicated array, unrelated to the card readout. The DAC output should remain at its midpoint, but instead it does this:

And zooming into each spike at 100ms:

My best guess is that the SD DMA channel priority is greater than the audio ISR, and samples are being dropped or misread.
I tried setting the audio ISR priority to maximum in output_i2s.cpp by adding a priority argument:
Code:
dma.attachInterrupt(isr, 0);
This didn't help.
Is there a way to make microSD reads from T4's onboard card interruptible? Or is something else at fault here?
Thanks!
-J