That one is usage error! Note: I am not necessarily saying there are no other bugs.
You are writing to the frame buffer while the DMA operation is reading from the frame buffer.
And if this is a T4.x and you did not set a frame buffer, it will malloc it, which comes from RAM2
Which adds other interesting wrinkles. That is, the operations write to memory, which goes through the cache
But DMA goes to the actual memory. So if you do nothing, about synchronizing the two, you end up with
holes and bleed through. The updateScreenAsync call has code that sees the buffer is in high memory and does the call to flush
the cache, before it starts the operation. But you then muck with some of the memory.
But the biggest issue is then when you get to the end of your loop, you fill screen to black, which on my screen is white because of your invert
and don't do another update screen, so some of the physical memory is updated and some is not...
So if you wish to see if the operations are working or not when going to the cache, you typically have two choices.
1) Don't use the Async call: For example this version works for me:
Code:
#define TFT_DC 9
#define TFT_CS 32
#define TFT_RST 31
#include <ST7789_t3.h>
#include <st7735_t3_font_Arial.h>
#define BLACK 0x0000
#define WHITE 0xFFFF
ST7789_t3 display = ST7789_t3(TFT_CS, TFT_DC, TFT_RST);
void setup() {
display.init(240, 320);
display.useFrameBuffer(true);
display.invertDisplay(false);
display.setRotation(1);
display.setTextWrap(false);
display.fillScreen(BLACK);
display.setTextColor(WHITE);
display.setFont(Arial_16);
}
void loop() {
char x;
int r = 0;
for (int i = 0; i < 200; i++) {
r++;
if (r == 20) {
display.print("\n");
r = 0;
}
x = i;
display.print(x);
display.updateScreen();
}
delay(1000);
display.fillRect(0, 0, 320, 240, BLACK);
display.updateScreen();
display.setCursor(0, 0);
}
2) Wait for the Aynch operation is complete before mucking with the memory.
Like at start of loop, call: display.waitUpdateAsyncComplete();
3) Sorry could not count - if you can allocate buffer in lower memory, the issue won't show up as much, as in this case you are not mucking with what the previous frame did:
Code:
uint16_t my_frame_buffer[320*240];
void setup() {
display.init(240, 320);
display.setFrameBuffer(my_frame_buffer);
display.useFrameBuffer(true);
...
4) Double buffer - Use two buffers (assuming you have enough memory), you fill one, and do the async update, while it is outputting it's frame, you fill up the second buffer... More complicated solution, requires knowing when you tell it to use a frame buffer, and when to do the next call to UpdteScreenAsync This was used in cases like movie frames, where while the screen is updating, you are loading in the next frame. There is no magic that synchronizes the two frames...
5) Sort of like 4) but with one buffer. You can turn on continuous async update: UpdteScreenAsync(true); Setup for callbacks on full and half screen: void setFrameCompleteCB(void (*pcb)(), bool fCallAlsoHalfDone = false);
You update the half screen that was just completed and know that you need to flush the cache if applicable, before the DMA operation gets back to the that portion of memory.
Hope that helps.