Replies: 3 comments 10 replies
-
Hi @twinotter, There have been a couple of discussions about this behaviour over the year(s). I actually made a change to the library similar to you and removed the 'showDmabuffer' call and merged everything into the one flipDMABuffer call, that certainly helped. My theory is that the DMA calls (this library) and Arduino sketch run independently/asynchronously, and therefore, it could be plausible that the DMA changes to the end of list pointer occur before actual graphics drawing / updates to the DMA buffer haven't finished - only a theory though. As a hack, I notice that if I put a delay between the end of my graphics logic (i.e. doing updates to the DMA buffer), and then the 'flip', then any flicker largely disappears. Alternatively, I just create my own in-sketch graphics buffer (i.e. uint16_6 buffer[64][32];), and then iterate through the whole thing and update the DMA buffer (no dma library double buffering required). |
Beta Was this translation helpful? Give feedback.
-
Interesting theory. I think the library, isr, and arduino code are all running on the same core, so there wouldn't be a race condition there. But the DMA is in some ways like a separate core - with separate timing to the memory bus. My theory (also unsubstantiated) is that the DMA is preloading the next frame pointer from the DMA linked list. Some percentage of the time (based on number of elements in the linked list), it preloads the one that is about to be changed, so has one extra circuit through that buffer before switching. And that's when the flicker changed. I found adding a 3ms delay right after the flip eliminated my flicker.. without affecting my framerate. (that wait for the end of buffer ISR to trigger is what affects frame rate most) BUT when I added some more debug serial port messaging, more flicker reappeared. So there is more to it than just this. In short order I'm going to try out using that layer buffer approach - it has the advantage also of being able to read back the true color... and should allow me to go back to single-buffering the DMA... so the memory hit should be somewhat minimal. But I'm also interested in trying out stopping and restarting the DMA. In this approach, I'd have two DMA buffers that never point to each other (the way page flips are done now). Instead, I'd just reinitialize the DMA with the other DMA buffer's address... hopefully that would clear any pipe-lined DMA memory accesses and eliminate flicker. It's hard to say which approach is better... (sorry for my slow response time.) |
Beta Was this translation helpful? Give feedback.
-
one question regarding this, in theory do i have to change the codes flow on flipping buffer or i can use the same flow for using dma buffer or memory buffer? i guess, in easy words. whats happen now is double dma is not working as expected per codes completion but the memory buffer guarantee that. thanks! |
Beta Was this translation helpful? Give feedback.
-
I'm trying to figure out why I'm getting some flicker. The options in the Common Issues issue don't seem to apply...
Flickering happens somewhat rarely. (Maybe a couple times a second with a frame rate of about 140ish fps.)
I'm double buffering. Drawing to the non-displayed buffer. Then flipping. There is a "fillRect" being used to erase part of the buffer... and is what's leading directly to the flickering. If I remove it, pixels are persistent of course, but the flicker disappears completely. This means the draw buffer, which shouldn't be on display or even in the presently output DMA linked list, is being displayed....
The code is oriented like this:
Originally this had quite a bit of flickering (maybe 3 or 4 times per second with a frame rate of about 70). When I combined them together into a single swap command below there was less flickering and frame rate jumped to 140ish. In ESP32_HUB75_LED_MATRIX_PANEL_DMA_Display.h:
This has the advantage of having only a single wait for the previous_buffer_free(). That gives the improved frame rate.
I've got it configured with double buffering. I've tried a number of different configurations
I've found I can eliminate flickering entirely if I run three swap commands in a row, but frame rate drops to about 30fps:
I'm thinking of moving the code that changes the DMA end-of-list pointer and putting it inside the isr... I believe that will likely cause the DMA to output one more complete frame before its switch happens. This is on the theory that the DMA is close to done with a complete frame when the pointer at the end of the linked list changes. thus, perhaps the DMA is moving on to the new buffer before the code gets stopped in the while loop waiting for the dma to finish... this is a stretch both because the timing seems really unlikely and because the isr/main loop are running on the same processor - there is no race condition on that end of things... only potentially between the DMA and the code.
Am I missing something obvious? Has anyone seen this behavior in double buffered setups?
Rudy
Beta Was this translation helpful? Give feedback.
All reactions