/*
* Test for Audio DMA underrun recovery when
* starved by display updates.
*
* Tested on Teensy 4.1, default settings
*/
#include <ST7735_t3.h>
#include <Audio.h>
//=========================================================
// GUItool: begin automatically generated code
AudioSynthWaveform wav1; //xy=201,155
AudioSynthWaveform wav2; //xy=227,195
AudioRecordQueue queue; //xy=417,91
AudioOutputI2S i2sOut; //xy=479,167
AudioConnection patchCord1(wav1, 0, i2sOut, 0);
AudioConnection patchCord2(wav1, queue);
AudioConnection patchCord3(wav2, 0, i2sOut, 1);
AudioControlSGTL5000 audioShield; //xy=472,250
// GUItool: end automatically generated code
//---------------------------------------------------------
void randomWav(AudioSynthWaveform& wav)
{
wav.begin(0.5f,110.0f*random(1,7),WAVEFORM_SINE);
}
//=========================================================
// Change pin numbers to suit your hardware!
// CS DC RST
ST7735_t3 tft = ST7735_t3{ 9,10,22};
#define TFT_BL 4 // backlight pin
//---------------------------------------------------------
static elapsedMicros euTFT;
uint32_t lastTFT;
void randomRect(void)
{
static elapsedMillis em = 0; // allow a gap between screen updates
static bool updating = false;
if (!tft.asyncUpdateActive())
{
if (updating)
{
updating = false;
lastTFT = euTFT;
}
// stock library takes 21.3ms to update
// 128x160 at 16MHz SPI speed, so...
if (em > 30) // ...leave a gap for audio to recover
{
em = 0;
euTFT = 0;
updating = true;
// choose new rectangle dimensions
int16_t x=999,y=999,w,h;
w = random(tft.width() / 2);
h = random(tft.height() / 2);
while (x+w >= tft.width())
x = random(tft.width());
while (y+h >= tft.height())
y = random(tft.height());
// write to frame buffer
tft.fillRect(x,y,w,h,random(65536));
// update screen
tft.updateScreenAsync();
}
}
}
//=========================================================
void setup()
{
AudioMemory(20);
audioShield.enable();
audioShield.volume(0.05f); // low volume
queue.begin(); // start check of audio stalling
// standard TFT display setup
tft.initR(INITR_BLACKTAB); // ST7735
//tft.init(); // ST7789
pinMode(TFT_BL,OUTPUT);
digitalWriteFast(TFT_BL,HIGH);
tft.fillScreen(0);
tft.setRotation(1);
tft.print("Hello world");
// now prepare to use async updates
tft.useFrameBuffer(true);
}
//=========================================================
elapsedMillis audioTimer;
int count, audioCount;
void loop()
{
if (audioTimer >= 290) // roughly 100 audio updates
{
audioTimer = 0;
if (random(2))
randomWav(wav2);
else
randomWav(wav1);
Serial.printf("Count: %d; audio updates: %d; last TFT update took %uus\n", count, audioCount, lastTFT);
count = 0;
audioCount = 0;
}
// count audio updates
if (queue.available())
{
audioCount++;
queue.clear();
}
randomRect();
count++;
}