Description
I know I'm kinda on my own with the panels of this size, but still - any advice on where to look at would be much appreciated.
Here's the deal: I have a lot of 32x32 px 1/8 panels (simple SHIFTREG driver), ESP32S3 with 8Mb PSRAM, and I'm trying to create a fairly big screen. I don't need much of a color depth, so I set that to 3.
It works great up to the size of 3x10 panels (30720 pixels). Any size bigger than that, such as 4x8 panels (32768 px) produces random garbage on the panels. The memory size should not be an issue: at 3 bpp color it only allocates about 96kB even with the double buffering enabled.
What worries me, is this weird 32768 px threshold. It is almost as if signed int is used somewhere instead of unsigned int. But where?...
UPD: "Single line" configurations up to 1 row of 31 panels (31744 pixels) work great, but 1 row of 32 panels (32768 pixels) breaks.
Activity
mrcodetastic commentedon Feb 17, 2025
It would be hard to know without looking at a logic level capture.
rigorka commentedon Feb 17, 2025
I can get that by connecting the HUB75 output to oscilloscope. Which of the HUB75 signals are you interested in?
Lukaswnd commentedon Feb 18, 2025
This is interesting, back in December 2023 I managed to run 45056 pixels, 22 Panels each 64x32.
Which version are you using? Latest Commit from Git, latest Git Release, latest from Pio registry or Arduino Registry.
One of the last commits changed the resolution in the Virtual Display from int16_t to uint16_t. Since the problem also occurs in single line configuration I doubt that is the issue.
Did you try to increase latch_blanking on some (cheap and poorly produced) boards it helps to keep long chains stable.
Can you make some pictures?
Edit: You are not using the external DMA buffer, right? This is not fast enough for such long chains even with low color depth?
board707 commentedon Feb 18, 2025
Changing the matrix dimensions from
int16
touint
should have increased the number of available points rather than decreased it :) However, I am more inclined to think that this has nothing to do with the problem.If you suspect this, you can always return to the previous type of numbers, one line was corrected
rigorka commentedon Feb 18, 2025
Thanks you for taking time to respond, here are some clarifications:
Latest Commit from Git
Yep, this does not change things much as this affects merely the X res, which was quite far from int16_t maximum anyway.
Yep, all the way up to four, with no changes.
This is what the end of the "healthy" 31-panel chain looks like (I don't have all the panels at home, so that's just the end of the chain):

And this are the examples of what "broken" 32-chain looks like (the shapes are fairly random at each reboot, sometimes the screen is just black. The chain responds to
setBrightness
call, but all other GFX calls such asdrawPixel
andclearScreen
do nothing:I'm not, but nothing changes if I do - the results are pretty much the same: chain of 31 panels work, chain of 32 does not
These are the library log output with 32 panels (when it does not work):
And this is the log with 31 panels, when things do work okay:
Lukaswnd commentedon Feb 19, 2025
Interesting, that the issues are with the Panels clsesed to the esp. This defently indictes a issuse with this library, probably numerical.
what I found so far it might be a problem with the DMA descriptors. Can someone please confirm or deny this:
This are 1/8 Panels 32 Pixels heigh and 32 pixel wide, so the Virtual display Maps it to a 16 pixel heigh and 64 pixel long Panel internally. So in a chain of 32 there would be 64*32 = 2048 Pixels in a row. Since the DMA Descriptor uses uint16_t as storage and output type there are 4096 bytes. for each color depth for each row.
In configureDMA the libraries tries to allocate one discriptor for all color depths seperated by row. This defenetly 'fails' (results in log [W][gdma_lcd_parallel16.cpp:369] create_dma_desc_link(): [S3] Creating DMA descriptor which links to payload with size greater than MAX_DMA_LEN!), because there is a max length for each descriptor on the s3 which is 4096-4. So it allocates one discriptor for each colordepth in each row, which also 'fails' because it would need 4 more bytes.
But this would only explain the last 4 pixels each row on the 32nd Panel, which are on the 1/8 Panels the following pixels. In lines 9-16 and 25-32 the pixels 29-32 (indexing starting at [1/1]). I marked them green. Judging by the logs start your panel count at 1, not 0, right? Otherwise it would explain the wrong panel 32 and onwards.
By 'fail' I mean that it just allocates 4092 bytes and ignores the rest of the data.
Allocation wise this would be managable to change. Maybe I find time to make a prototype on Friday.
Would changing the descriptors effect anything else but the DMA output? Like setting a pixel, color, oe and latch is all done to the datastructs, right?
And I guess we will see if changing the DMA Descriptor mid line would have any visual glitches
Lukaswnd commentedon Feb 19, 2025
Oh wait, the Image I edited is Panel 31, but you get which pixel should be wrong.
But I don't get why the ouput on Panel 31 would be wrong by my explanation.
rigorka commentedon Feb 19, 2025
Indeed, in my panel labeling debug code the panel count is 1..31.
What I also can not explain is why all GFX operations after the first one produce no effect at all in "faulty" case of 32 panels:
my application on S3 works normally, its network API responds fine, I can call
VirtualMatrixPanel->clearScreen()
,VirtualMatrixPanel->drawPixel()
etc without any memory-related errors, but these calls do not produce any result.This seems especially strange for
clearScreen()
which just callsupdateMatrixDMABuffer(0, 0, 0);
internally, and I see no reason at all for that to produce no effect.mrcodetastic commentedon Feb 22, 2025
It's times like this I realise this library really is a labour of love for me 😂.
You're on the money. The first data to get clocked out is the co-ordinates (0,0), the last data is the panel closest to the ESP.
With these ESP's getting ever more powerful, it seems with a long chain of 'four scan' (2xwidth, .5xheight) panels it's possible to easily blast the 4069-byte DMA descriptor payload limit with 32 panels 😂. As all each 'colour depth' loop is a long chain of output data, with each iteration of truncated data, the offset x will get worse I suspect.
Let me look and see what I can do.
mrcodetastic commentedon Feb 22, 2025
This I don't understand. I'm hoping there's some strange side-effect of the DMA payload limit being exceeded.
#755
mrcodetastic commentedon Feb 24, 2025
I made some changes which I think might fix the issue.
rigorka commentedon Feb 25, 2025
Thank you for your efforts, but unfortunately I'm out of luck trying to test the new version so far. The same config (one chain, 31 panels) which used to work before now spits the following log and dies (as in S3 becomes completely unresponsive, none of my app code is being executed after the library initialization). Furthermore, reducing the panel chain size to modest 4 panels changes nothing - S3 still hangs immediately after library init. Rolling the lib back to previous version fixes the issue immediately.
mrcodetastic commentedon Mar 2, 2025
Can you post a simple application with the code so I can repeat this issue on my end? I want to fix this issue.
rigorka commentedon Mar 5, 2025
Thank you for your willingness to pursue this further. I'm away on a trip from 1st to 21st march without (thankfully!) my panels and controllers, but will make sure to prepare a super simple app allowing to reproduce the problem and will send it to you late march as soon as I'm back and can test it on a real controller.
#755
#755
Fix double buffering #755
mrcodetastic commentedon Mar 16, 2025
No problems. I introduced new bugs trying to solve for this edge-case, but I think I've fixed everything now. Whilst I don't have a S3 connected to 32 panels, I can now at least get this output if I run a test sketch, which indicates to me all is now working fine.
Sketch:
airCoder2 commentedon Apr 1, 2025
Could you explain how you got the 96kB? According to my calculations, it should take about 24kB.
ashthespy commentedon Apr 7, 2025
Hi!
The refactoring of
getColourDepthSize
andgetDataPtr
missed the parts forSPIRAM_DMA_BUFFER
Will this (rather naive) diff be sufficient? I am not sure where
getColorDepthSize
needs the full row and where it doesn't.