mrcodetastic / ESP32-HUB75-MatrixPanel-DMA

An Adafruit GFX Compatible Library for the ESP32, ESP32-S2, ESP32-S3 to drive HUB75 LED matrix panels using DMA for high refresh rates. Supports panel chaining.
MIT License
898 stars 201 forks source link

Please help review RGBPanel library comparison #7

Closed marcmerlin closed 3 years ago

marcmerlin commented 5 years ago

If you have a bit of time, could I ask you to review this writeup I just did?

The choice of APIs and backend drivers can be a bit confusing, so I've tried to write a summary. https://github.com/marcmerlin/SmartMatrix_GFX/blob/master/README.md

Could you look it over and send me edits if applicable you can click edit in github and it'll send me a pull request. Once it looks ok, I'll share it with Adafruit, Louis and you so that each lib can summarize the ecosystem out there and help users make the right choice for their needs.

marcmerlin commented 5 years ago

Just corrected the lack of 24bpp support https://github.com/marcmerlin/SmartMatrix_GFX/commit/e0ea86a0f9259770245fb4bde102a0a1618995a3#diff-04c6e90faac2675aa89e2176d2eec7d8

mrcodetastic commented 3 years ago

Hi. I never responded to this directly, but your summary seems in-line. I don't think there's a great deal between SmartMatrix and this library other than the fact that this was originally built as a drop-in replacement for people familiar with Adafruit GFX.

Thanks to Covid though I’ve had some time in the past few weeks to work on the library that I never had in the past two years, so have fixed a bunch of memory issues and Brian Lough’s fantastic contribution helped resolve chaining support.

The difference between this library really is that it doesn't provide any fancy stuff like layers etc. It's really a raw pixel co-ordinate to DMA interface, to keep memory usage to the bare minimum. In any case, your GFX library provides this higher level pixel-persistence stuff, which I'll look at building a bridge to.

marcmerlin commented 3 years ago

Thanks for the update, and good job with the progress. So, what follows is an observation and not a critcism :)

I've been working with OSS for close to 30 years, and I've seen so many examples of several project that solve 90% of the problem, but not the same 90% :) which in turn makes it difficult for users to pick what's the best code for them to use.

I'm not blaming you for writing this, it's a really cool learning project (I did a simpler version for RGB Matrices http://marc.merlins.org/perso/arduino/post_2015-01-06_Driver-for-direct-driving-single-to-3-color-LED-Matrices-with-software-PWM.html and just got lucky that no one else had, before me).

I also agree with you that I don't need the extra layers and everything in the SmartMatrix API. My SmartMatrix::GFX glue library ignores all of it and uses the library as a framebuffer :) Are you able to drive 128x128 on ESP32? SmartMatrix stops around 128x100 or so if you have PSRAM If you can do, 128x128, then your lib is a clear win over SmartMatrix. If not, it's a different lib with a different 90% support :)

As for the last 10% which sadly is becoming more than 10%: There is the issue that panels are getting more of a mess. Between FM6126A (now FM6127) chips that are incompatible, and Louis who barely got it working for one panel he had but it never really worked for me, and the many more ways those panels can be messed up (ABCDE vs ABC for 128x64, or the AB panels, and all the different ways of doing row mapping to save a tiny bit of copper traces, it's a terrible mess). I'm sure you're aware of https://github.com/hzeller/rpi-rgb-led-matrix which is currently the best lib for supporting as many of those panels as possible (and yet, people still end up getting new weird ones at random), but it's only for rPi.

Ths is kind of where I wish that the two libs could join effort/code to help solve that 10%, but that's just my wish, and I totally understand that you get to work on what's interesting and worthwhile to you :)

marcmerlin commented 3 years ago

In the meantime, because I've grown beyond 128x64, I've switched to rPi and wrote glue code/library to run arduino code on rPi: image

http://marc.merlins.org/perso/arduino/post_2020-03-13_RGB-Panels_-from-192x80_-to-384x192_-to-384x256-and-maybe-not-much-beyond.html

While you can't use the rpi code as is, if you encounter weird panels, you may be able to re-use the support that's already been written in that lib. Have fun with your project, and thanks for the update.

mrcodetastic commented 3 years ago

Totally agree with you on the missing 10% issue, but agree that's open source since well since open source began... "Will XXXX be the year for Linux on the Desktop" is a classic example.

RPi/SBC for any serious projects (like yours) should be the go-to choice anyway I think (or even better an FPGA) so a vastly more capable library makes sense. I'll look to see if there's portable code of use to this Arduino library, but for now nobody has raised any issues or a pull request for the FMXXXX chips. Perhaps it's more of an issue for non-32x64 panels.

To be honest though, if the Chinese start pumping out piles of crap panels to save a dollarh, then I'll probably just design a PCB myself that will always work with the library, or provide a list of 'working panels'. Rather support the panels that don’t have shortcuts.

Greater than 128x128 should be easily doable.

marcmerlin commented 3 years ago

Eheh, I'm not surprised to read we've had the same experiences :) Few comments:

What is the highest res you can do right now even if you don't have the panels? Can you blind output 128x128 at 100Hz or so? If so, that makes your library more capable than SmartMatrix on ESP32.

mrcodetastic commented 3 years ago

The library, like SmartMatrix drops the colour gradients / PWM depth silently if there's going to be memory constraints, or refresh issues. Also, how things are chained, what GPIO bus speed is set and what other junk is running in the sketch influences this. Quick compile and run on a ESP32 floating around:

128x128 works 256x128 works, but I think it's dropped to about 5-6bit colour.

Raised lsbMsbTransitionBit to 0/4 to fit in remaining RAM
lsbMsbTransitionBit of 0 gives 19 Hz refresh: 
lsbMsbTransitionBit of 1 gives 38 Hz refresh: 
lsbMsbTransitionBit of 2 gives 67 Hz refresh: 
lsbMsbTransitionBit of 3 gives 101 Hz refresh: 
Raised lsbMsbTransitionBit to 3 to meet minimum refresh rate

But in the end, it depends on how it looks to the naked eye.

marcmerlin commented 3 years ago

256x128 for an ESP32 is really great. The way SmartMatrix manages memory and bitplanes, it cannot reach 128x128 (runs out of RAM). So, congratulations, your lib and how you manage memory, is 3-4x more efficient than SmartMatrix.

You definitely should advertise this on your main page, something like "Support for up to 128x256 at reduced color depth on ESP32 when SmartMatrix tops out a bit after 128x64"

Without having looked at the SmartMatrix code in details, it still uses more bitplanes than you do, or uses them in a way that is less memory efficient than you. Well done!

marcmerlin commented 3 years ago

I posted your update in https://community.pixelmatix.com/t/up-to-256x128-on-esp32-with-esp32-rgb64x32matrixpanel-i2s-dma/733 . This will hopefully help people looking for 128x128 or above on ESP32.

mrcodetastic commented 3 years ago

Thank you!

embedded-creations commented 3 years ago

Cool to see that there's another library option for people wanting to drive HUB75 panels with an ESP32. It looks like we're going after different goals with just a little bit of overlap. SmartMatrix Library supports minimum 24-bit refresh, ESP32-RGB64x32MatrixPanel-I2S-DMA supports maximum 24-bit refresh. I'm focusing on visual quality over max pixel count, so my library is optimized for that. I do plan on making this more clear in my documentation (which really needs a refresh, I'm just starting to move it to a GitHub Wiki from an unmaintained website), and I'll steer people to this library and the RPi library for those that need higher pixel count than SmartMatrix Library can handle, or need RAM for other purposes, or just want to try a different library.

I took a quick look under the hood here to see how memory is being used more efficiently. Here's some of the differences I spotted, and please correct me if I got any of this wrong:

So, compared to SmartMatrix Library, I believe the big savings are: half the I2S DMA Buffer and linked list descriptors, and either no intermediate drawing buffers, or if there are buffers, they're 2/3 the size.

I don't think it would hurt to have an option in SmartMatrix Library to disable the double buffering, but I'd leave double buffering on by default. Drawing directly to the I2S buffers is a fundamental change that breaks how SmartMatrix Library is designed, with independent layers that have their own buffers, and a separation between the drawing and refresh memory.

I do like the idea of using Adafruit_GFX as a layer in SmartMatrix Library for those that want to use the Adafruit_GFX drawing routines to save RAM or for sketch compatibility. I wish they had up to 24-bit color support. Their font support has improved dramatically since I last looked at it (SmartMatrix Library used to be better), so it would be nice for people that need better fonts to have access to them.

I also like your idea of taking some patterns from Aurora and turning them into an easy to understand sketch. I'm going to have to add that to a SmartMatrix Library example.

Quick compile and run on a ESP32 floating around:

128x128 works 256x128 works, but I think it's dropped to about 5-6bit colour.

Did you actually test this displaying on a panel? I'm curious if this result actually results in a working display, and if so, if the quality is acceptable.

mrcodetastic commented 3 years ago

Hi Louis,

Honoured to have you here... You're the legend that got me interested in esp32 DMA. There's nothing your library can't do that this does, I based this library partly off your code I think when I hacked this first together two years ago (and didn't do anything else with it until recently.

The original aim of this library was educational, but I did want a graphics library that struck a balance between a) memory usage (as my projects use Bluetooth and other resource hogs). b) good enough colour depth; and c) used DMA (not timers like neocats p3 matrix library).

So this was created. There is no silver bullet for such a resource constrained device really.

In haven't tested it on a physical display as I don't have the hardware. But it runs it seems.

On Fri., 21 Aug. 2020, 9:58 pm Louis Beaudoin, notifications@github.com wrote:

Cool to see that there's another library option for people wanting to drive HUB75 panels with an ESP32. It looks like we're going after different goals with just a little bit of overlap. SmartMatrix Library supports minimum 24-bit refresh, ESP32-RGB64x32MatrixPanel-I2S-DMA supports maximum 24-bit refresh. I'm focusing on visual quality over max pixel count, so my library is optimized for that. I do plan on making this more clear in my documentation (which really needs a refresh, I'm just starting to move it to a GitHub Wiki from an unmaintained website), and I'll steer people to this library and the RPi library for those that need higher pixel count than SmartMatrix Library can handle.

I took a quick look under the hood here to see how memory is being used more efficiently. Here's some of the differences I spotted, and please correct me if I got any of this wrong:

  • Double buffering in the I2S buffer is disabled by default, and it looks like most of your examples don't use it, saving a bunch of DMA RAM. Are you doing anything to avoid visible tearing or glitching when the I2S buffer gets updated with new content at the same time it's being refreshed to the panel?
    • You'll also save half the DMA Linked List Descriptors which can be large
    • (You could save even more RAM by using an external latch to store the address like SmartMatrix Library optionally does)
  • When drawing a pixel, you can draw directly to the I2S buffer, avoiding any intermediate buffers.
    • What happens if drawing graphics is slower than the refresh rate, doesn't it result in tearing as some of the new pixels are refreshed on one frame, and some on the next?
    • You also can't currently read the color of a pixel you've drawn to the buffer, but a lot of time that functionality isn't used.
    • I think a good test case for this is to sweep a vertical line (or scroll text) horizontally quickly across the screen, so there's pixels on each row. I tried to save RAM in a project I was working on using SmartMatrix Library and removed the double buffering and the tearing showed up with scrolling text and I had to save RAM another way.
  • You do use Adafruit_GFX which uses uint16_t to store pixels, and has double buffering. That saves 1/3 of the RAM compared to SmartMatrix Library's minimum 24-bit drawing buffer. I believe the Adafruit_GFX buffers are optional, so you can save a ton of RAM if a sketch like AuroraDemo is only drawing directly to the I2S Buffer and not using Adafruit_GFX.

So, compared to SmartMatrix Library, I believe the big savings are: half the I2S DMA Buffer and linked list descriptors, and either no intermediate drawing buffers, or if there are buffers, they're 2/3 the size.

I don't think it would hurt to have an option in SmartMatrix Library to disable the double buffering, but I'd leave double buffering on by default. Drawing directly to the I2S buffers is a fundamental change that breaks how SmartMatrix Library is designed, with independent layers that have their own buffers, and a separation between the drawing and refresh memory.

I do like the idea of using Adafruit_GFX as a layer in SmartMatrix Library for those that want to use the Adafruit_GFX drawing routines to save RAM or for sketch compatibility. I wish they had up to 24-bit color support. Their font support has improved dramatically since I last looked at it (SmartMatrix Library used to be better), so it would be nice for people that need better fonts to have access to them.

I also like your idea of taking some patterns from Aurora and turning them into an easy to understand sketch. I'm going to have to add that to a SmartMatrix Library example.

Quick compile and run on a ESP32 floating around:

128x128 works 256x128 works, but I think it's dropped to about 5-6bit colour.

Did you actually test this displaying on a panel? I'm curious if this result actually results in a working display, and if so, if the quality is acceptable.

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/mrfaptastic/ESP32-RGB64x32MatrixPanel-I2S-DMA/issues/7#issuecomment-678489850, or unsubscribe https://github.com/notifications/unsubscribe-auth/AC3TMKPUOA7PWAYMAUVKG5DSB3NW3ANCNFSM4GMVNBTA .

marcmerlin commented 3 years ago

@embedded-creations thanks for having a look, and the details of the differences between the libs. As a user, I always hate it when I look on the net , find 3 solutions and don't know which one is better for me, or not , so your explanation is very helpful. Some details:

For 128x256, I'd offer to run it on my panels, but they are all FM6126A, so they won't work with this lib. I could cheat and init them with rPi and then hot swap them to see what happens. Maybe a bit later when I have spare time after my current project :)

I think supporting GFX is important, because so much code uses it across so many kinds of displays, but actually the lesser known LEDMatrix API is a 24bit native implementation and supports extra things like mirroring and other fun stuff that is extensively used by Mark Estes' excellent demo collection: https://github.com/marcmerlin/FastLED_NeoMatrix_SmartMatrix_LEDMatrix_GFX_Demos/tree/master/LEDMatrix/Table_Mark_Estes
You can see a demo here: https://www.youtube.com/watch?v=PbuB-QE-WjQ (ok, in 6mn after I post this that is, it's still uploading)

@mrfaptastic porting your lib to a driver for Framebuffer::GFX should be a very simple port (I can help if you're interested, but looking at SmartMatrix::GFX and FastLED::NeoMatrix should give you an easy to copy example to get things working within hours). I have lovely ASCII art (haha) that explains how the pieces fit: http://marc.merlins.org/perso/arduino/post_2020-03-16_Framebuffer_GFX_-Choosing-between-its-3-2D-APIs_-FastLED-XY_-NeoMatrix_-and-LEDMatrix_-and-detail-of-its-many-supported-hardware-backends.html

If you get them to work together, then you automatically support all demos written against LEDMatrix and FastLED, (in addition to just GFX). Once you have that, you can run any demo code in https://github.com/marcmerlin/FastLED_NeoMatrix_SmartMatrix_LEDMatrix_GFX_Demos/

embedded-creations commented 3 years ago

Hi Stuart, glad my code (really built on top of Sprite_TMs code) got you interested in DMA.

There's nothing your library can't do that this does

Not true, it has options to be way more memory efficient than SmartMatrix Library :-)

good enough colour depth

memory usage (as my projects use Bluetooth and other resource hogs)

My solution to that is going to be to move the HUB75 refreshing to a separate ESP32. That also allows for driving HUB75 panels using pretty much any microcontroller, not limited to Teensy/ESP32. I have a product in the alpha stage, able to receive APA102 data, and drive a 128x64 panel at 36-bit color 240Hz refresh. That will be the next product I launch after the SmartLED Shield for Teensy 4 campaign is complete.

I agree that 24-bit is probably good enough for a lot of people. I tried your library a week or so ago, and I was surprised how good it looked, and didn't notice tearing or anything in the Aurora and Bitmap examples. I like that you added gamma correction by default, and control brightness with the OE signal, not dimming the source data.

I put away my ESP32 setup, but if I get it out again I'll try 128x256 and see how it looks.

"Honoured", "legend", "colour", are you in the UK? I'm American but have been living in Cambridge for the past three years.

Galaxy-Man commented 3 years ago

mrfaptastic, thanks for the updated library. All works no issues, not got a SD card so running in memory. Waiting for ribbon cables to test 2x2.

If you are thinking of going bigger let me know and Ill get you some more panels sent over. Im currently using FM6124/FM6126 and seems to be fine.

mrcodetastic commented 3 years ago

If you are thinking of going bigger let me know and Ill get you some more panels sent over. Im currently using FM6124/FM6126 and seems to be fine.

As always, you're more than kind. A FM6124/FM6126 panel(s) would be of use to test with. @atc1441 seemed to imply that the FMXXXX example doesn't work and he had to do additional stuff. https://github.com/mrfaptastic/ESP32-RGB64x32MatrixPanel-I2S-DMA/issues/23#issuecomment-677929742

Interested to know what happens when chaining non-FM with FM models of panels together... this will no doubt be the next problem as people chain whatever they have laying around in the basement, together.

Galaxy-Man commented 3 years ago

Before I sent you the panels I tried FM6126 + one of the icnd2038s panels. I loaded the reset routine and the icnd2038s panel ignored it but the FM accepted and both work together. I'll try and get two icnd2038s panels and built 2x2, it's like roulette when preodering even from Amzon. Watch this space.

embedded-creations commented 3 years ago

Copyright (c) 2015 Pixelmatix

You might want to update your license file :-)

Galaxy-Man commented 3 years ago

Hi Louis

I am being stupid here, which licence file?

mrcodetastic commented 3 years ago

@Galaxy-Man I think that's a message to me. @embedded-creations - I'm all for giving credit where credit is due ha!