LVGL compatible DMA enabled LCD drivers for Teensy 4.x

I understand your point of view, and I totally agree that your style makes sense given a more professional approach to product development. For myself, I had the need to support a half dozen or so devices running the same codebase on very different hardware and found the flexibility of lovyangfx made that trivial. Sure, I'm not using most of its functionality but that compiles away without burden because the performance was outstanding compared to the more basic drivers available for the platform.

I know it looks ugly, I thought so too at first but it works so much better for me in practice having that detailed definition available all in one place for reference and tweaking. It also supports an impressive list of devices, all my varied and hacked up hardware worked out of the box.

Still, horses for courses. I do like your library and look forward to trying it, it looks very neat and clever and should make for a good tight coupling with lvgl.
 
oh interesting. yeah i could make one, but i can't test it. instead, I'll leave an open offer to help should one of you decide to implement this driver using the code I provided, but i'll need your help to actually test it. I'm loath to order another screen, just because I've ordered so many that I only ever use once, it's getting ridiculous.
I completely hear you on this! You don't know how many cameras, displays, joysticks, mice, keyboards, etc. I have sitting around here, mostly stuck in boxes in cabinet. And I only do this for the fun of it! And I now have 4 of the ST7796 displays (2 of each I mentioned).

Edit: At least these are reasonably cheap, as compared to ones like RA8875/RA8876.
 
I have a couple of RA8875s because we involved them with an initial prototype of a device we were building for work, so I didn't pay for them fortunately. Can't say I'm a fan of the slow speed of the chip, even with the "graphics acceleration" which is almost useless if you need something that looks modern and anti-aliased. About the only thing it really helps with, if you work at it, is displaying pngs, because of the way they decompress, it just happens to fit with the way their "graphics acceleration" works, at least for the drawing, not the decompression ofc.
 
Here's a first draft of a driver for st7796. Seems to work, I have done some limited testing over the last week. I put it on my github because I don't know how to submit a whole repository. @honey_the_codewitch feel free to take ownership.

st7796_t4

Performance is outstanding, from an average 15fps using ST7735_T3 and chugging hard at 90%+ usage to about 25fps with a much more relaxed ~80% usage when animating a fullscreen scrolling chart. Very nice!
 
What's curious to me is the 80% usage and if there's a way to get that higher. 320x240@16bpp over 1 bit SPI should net you up to about 31FPS before saturating the bus so you're close to maximum speed already if not there already. But where's that other 20% of usage getting lost? You got me curious. I'll need to get an ST7796
 
I could probably get higher, the code is still in system testing and verification phase, not yet optimized and I have delays where they probably dont belong (like the main loop). There is other stuff happening too, the sampling interrupt fires every 1100us and lasts 320us reading all the i2c registers of both shunt amplifiers at 1mhz and while recording also prepares the arrays for the real-time chart display so a fair bit of cpu is being tied up there.

Mind you the screen is running 480x320 at 80mhz (or whatever the actual frequency is you get when you use that value for SPI?) to get the quoted performance and is perfectly stable without any issue. This is in a lashup prototype without much care for the wiring.

However it was interesting to see that because the SPI is running during sampling, I was getting some slight interference in my readings corresponding to screen activity. RF noise from SPI was leaking into the shunt amplifiers. Shielding didn't help, the grounding was already good, turns out a simple snap-on balun on the i2c wires was the answer and it is only a bit above the noise floor now which seems to be about 100nA. More than sensitive enough for any practical use I will have for it.

I'm very happy. Everything is working as intended and looks great! I will end up with a very functional and stylish new bench power supply, soon I can finish this side project and finally use it to slim down my battery hungry lightning detector.
 
I'm very happy. Everything is working as intended and looks great! I will end up with a very functional and stylish new bench power supply, soon I can finish this side project and finally use it to slim down my battery hungry lightning detector.
That's great to hear, and I'm glad the code is working out for you. Thanks for your contribution. At some point I need to go back and shore up these libs and officially release them. When I do i'll add your code to the array of supported libs and credit you. I may make small changes for naming consistency. (I know camelCase is all the rage in arduino, but most of my stuff is not limited to arduino, and my C and C++ projects tend to prefer snake casing) wars have been fought over less, I know. =) plus i may end up adding additional features such as formalizing the offset/gap spacing for X and Y positions because that's so common with displays.
 
Go for it, please take ownership and change it to suit your vision. My cut'n'paste style is simply too lazy to be consistent. Cheers!
 
Hallo
I'm using a 3.5-inch Waveshare touchscreen display with an ST7796S chip on my Teensy 4.1. Is there a good library with DMA functionality?

20260304_211443.jpg
 
I did a tweaked version of the standard Teensy ST7735/7789/7796 library, which you can find here. The main motivation was to allow use of the 480x320 ST7796 using DMA, and add some changes so that long-running screen updates over SPI didn’t clobber SPI SD card reads by the Audio library.

I ended up also adding in partial screen updates using DMA, and the ability for multiple displays of different types to coexist on one SPI bus.

This may well be entirely irrelevant to LVGL, of course; I’ve never used that, so I don’t know how the library dependencies stack up…
 
Well, it looks like PlatformIO isn't finding the one you downloaded, and / or you haven't selected the /dev/big-screen-t4 branch.
  • ST7796_t3.h is definitely in there
  • the /dev/big-screen-t4 version number is set to 1.2.0 - PlatformIO is showing 1.0.0
(I know most people, including Paul, prefer not to bother with such distractions as version numbering, but I happen to think it's quite helpful. Call me old-fashioned...)

I know next to nothing of PlatformIO, so can't be of much help there.
 
One more question. Can I move the frame buffer to the second RAM area of the Teensy 4.1 or to the 16MB PSRAM expansion?
 
tft.updateScreenAsync() doesn't work. updateScreen() is work :rolleyes:


C:
void redraw_Display(void)
{
  uint16_t color = rand();
  tft.fillScreen(color);
}


void loop() {

  if (Timer_1 >= 2000)
  {
    redraw_Display();
    Timer_1 = 0;
  }
 
  if (updateScreen_Timer >= 500)
  {
    tft.updateScreenAsync();
    updateScreen_Timer = 0;
  }
 
That looks like your code. You can allocate the framebuffer in PSRAM, and pass its address as a parameter to the setFrameBuffer() method. See the ReadMe.md.

tft.updateScreenAsync() doesn't work
Yes it does. But no-one can tell what you've done wrong (or if there's a bug) from that fragment of code - complete sketch which can be dropped into the Arduino IDE, please...
 
My ST7796S Touchdisplay Test. tft.updateScreenAsync() doesn't work.
tft.updateScreen() work fine.

C:
// ST7796S Test

#define TFT_MISO  12
#define TFT_MOSI  11  //a12
#define TFT_SCK   13  //a13
#define TFT_DC   8
#define TFT_CS   10
#define TFT_RST  9
#define TFT_BL 28 // TFT Backlight

#include <ST7735_t3.h> // Hardware-specific library
#include <ST7789_t3.h> // Hardware-specific library
#include <ST7796_t3.h> // Hardware-specific library
#include <SPI.h>

// For 3.5" or 4.0" TFT with ST7796
ST7796_t3 tft = ST7796_t3(TFT_CS, TFT_DC, TFT_RST);

// FrameBuffer is located in Teensy4.1 Ram2
DMAMEM uint16_t FrameBuffer[320 * 480];

elapsedMillis updateScreen_Timer = 0;
elapsedMillis Timer_1 = 0;


void setup(void) {
  Serial.begin(9600);
  tft.setFrameBuffer(FrameBuffer); // Initialize Frame Buffer
  tft.init(320, 480);
  pinMode(TFT_BL, OUTPUT); // TFT Backligth
  digitalWrite(TFT_BL, HIGH);
  tft.setRotation(1);
  tft.invertDisplay(true);
  tft.useFrameBuffer(true);
 
}

void redraw_Display(void)
{
  uint16_t color = rand();
  tft.fillScreen(color);
}

void loop() {

  if (Timer_1 >= 2000)
  {
    tft.waitUpdateAsyncComplete();
    redraw_Display();
    Timer_1 = 0;
  }
 
  if (updateScreen_Timer >= 500)
  {
    tft.updateScreenAsync();   // tft.updateScreen() doesn't work and tft.updateScreen() work fine.
    updateScreen_Timer = 0;
  }
 
}
 

Attachments

  • FrameBuf_dma.ino
    1.2 KB · Views: 1
Last edited:
Well that's very odd. I've tried your code, with pins amended to suit my hardware (just my pins here, for clarity), and it works absolutely fine:
C++:
#define TFT_DC    9
#define TFT_SCK  13
#define TFT_MISO 12
#define TFT_MOSI 11
#define TFT_CS   29

#define TFT_RST  33
#define TFT_BL   34
But I can't believe that makes any significant difference, especially if synchronous updates are working for you - that says to me that SPI is working properly, so there's no weird "you can't use that pin" dependency.

Clutching at straws here, but do you have any other SPI devices on that bus? If so, your test code obviously doesn't set their /CS pins high ... but even if they were interfering, that still shouldn't show up as a difference between synchronous and ansynchronous updates.

I've pushed an update to the branch, which fixes a minor issue with spurious debug output on the serial port. It does also include a change Paul made to set dot_a_linkage=false in library.properties - maybe that's it? Worth a try.
 
I'm getting an error message with PlatformIO and VS code.
Arduino IDE reporting no errors. But PlatformIO is reporting an error in ST7735_t3.h, line 4970.
I don't know where the error is.

Screenshot 2026-03-08 200855.png
 
@Rolfdegen: I don't have any displays that use the ST7735_t3 library, but I thought I'd take an independent look. Have you downloaded & installed the latest version (after the update mentioned in post #45) ?? Are you sure that you don't have multiple copies of the ST7735_t3 library and/or sure which copy of the ST7735 library is being used by your PlatformIO/VSCode build ?? Looking in the @h4yn0nnym0u5e repository for the referenced ST7735_t3 library, the source for ST7735_t3.cpp currently only goes to line 4782.

Hope that helps . . .

Mark J Culross
KD5RXT
 
Back
Top