Keeping a TFT display refreshed while doing other things asynchronously...

I have a Teensy 4.1, audio board, and ILI9341 TFT display. There's some graphics & text, FFT, and eventually additional functions like reading various digital IO & sensors.

How does one keep the TFT updated on time without interruptions or flicker, while attending to the asynchronous things like button presses, and waiting for WAV files to play & stop..? Does everything have to be in the main Loop{} with branches to handle them, or do I need to learn interrupts, or what exactly..? I'm assuming there's no multi-tasking...or is there..?

I was thinking a series of If{} blocks for each activity, followed by a screen update, and finally a nested loop to wait for a timer value to decrement to zero before looping again. And then hope the combined duration of all activities doesn't exceed the length of the timer and cause a screen refresh to be delayed or skipped.

Not sure which way to go...

Thanks.
 
Use one elapsedMillis or elapsedMicros for every activity that happens with regular intervals, and then check for events like USB inputs or file play status changes. Dont stop in a delay loop waiting for a timer value, that loop is actually the loop() function and several timer values are checked inside that loop(). For instance if buttons are read every 5 milliseconds and screen is refreshed every 20 milliseconds (50Hz) I would do something like this

Code:
elapsedMillis buttonTimer, screenTimer;
bool audioPlaying;

loop() {
    /* Handle periodic events */
    if (buttonTimer >= 5) {
        buttonTimer -= 5;
        /* Read and check buttons here */
    }

    if (screenTimer >= 20) {
        screenTimer -= 20;
        /* Update screen here */
    }

.
.
.

    /* Now check for asynchronous events */
    if (Serial.available()) {
         /* Read and handle incoming serial data */
    } 

    if (audioPlaying && !playWav1.isPlaying()) {
        /* Wave file should be playing but has stopped, handle that */
    }
}

This can be done in several ways, but this general structure works well for me.
 
Note: with the ILI9341_t3n library you can also setup a logical frame buffer for the display, and do quick updates, which simply write to memory and then you can tell the screen to update
asynchronous using DMA: tft.updateScreenAsync()

Which then does not cause things to wait around for the pixels to update on the screen. There are also other games you can play to speed up display updates as well with the frame buffer. In that if you know only a small portion of the screen updated, you can set a clipping rectangle and use the synchronous version of the update which will then only output those bits.
 
Use one elapsedMillis or elapsedMicros for every activity that happens with regular intervals, and then check for events like USB inputs or file play status changes.
Great. It seems I was kind of on the right track already, just didn't know about the Millis and Micros. Thanks.
 
Note: with the ILI9341_t3n library you can also setup a logical frame buffer for the display, and do quick updates, which simply write to memory and then you can tell the screen to update
asynchronous using DMA: tft.updateScreenAsync()
Thank you! That was going to be my next question. This display is so darn fast that the FFT lines are barely visible. I was pondering ways to use page buffer arrays or something, and have them layered on screen so they stick around longer.
 
Back
Top