Adafruit_GFX Compatible Layers - Modern Font Support coming to SmartMatrix Library 4.0

Adding support for larger fonts has been a popular feature request for years, and I never took on the project as I thought it might be a difficult project. Turns out I was right, but now at least most of the work is done, and you can now run sketches like this using the “teensy4” branch, and this will be coming in the upcoming SmartMatrix Library 4.0 release.

There is now a new SMLayerBackgroundGFX layer (equivalent to SMLayerBackground) and new SMLayerGFXMono layer (equivalent to SMLayerIndexed and SMLayerScrolling combined). Both layers inherit from Adafruit_GFX, so you can use any of the Adafruit_GFX library functions with the new layers. I made both layers backward compatible with the SmartMatrix Library main layer functions, so you should be able to use existing sketches and the new layers with little or no changes. Adafruit_GFX uses uint16_t (equivalent to rgb16 or rgb565) to store colors, which is a downgrade if you’re using rgb24 or rgb48 in SmartMatrix Library to store your colors, so there are wrapper functions in the layers that take the rgb24/48 color, store it while Adafruit_GFX is doing the drawing, and pass it through to the actual drawPixel(rgb24)/drawPixel(rgb48) functions. The layers themselves are overhauled especially the SMLayerGFXMono layer which was rewritten to be much more efficient during refresh.

The examples were updated to show how to use the new layers:

  • Updated example MultipleTextLayers: optionally use Adafruit_GFX layers, improving refresh rate
  • Updated FeatureDemo: add “GFX” layer support option
  • Updated FastLED_Functions: add explicit cast from CRGB to rgb24. With new uint16_t conversions for Adafruit_GFX, the compiler gets confused as to which type we want, even though this sketch doesn’t use the new layers
  • New example Adafruit_GFX: shows how to use Adafruit_GFX functions with the new layers
  • New example MultipleTextLayersGFX: Improved version of MultipleTextLayers, includes Adafruit_GFX fonts (featured in video above)

Backwards Compatibility:

The only change that needs to be made (as of now) is adding explicit casts between FastLED’s CRGB type and rgb24. I’m not sure why this is needed. I merged in some really helpful code from @mrwastl to convert between different rgb types, and this was a side effect. It’s beyond my level of C++ understanding to fix this, but the explicit cast seems to work. See FastLED_Functions for an example.

Testing:

I tested the new code with the above examples on a Teensy 4. I didn’t test Teensy 3 (which I expect to work no problem), and I didn’t test with ESP32. ESP32 could have issues as it uses malloc instead of static allocation of buffers, and I may have made a mistake in the malloc calls. I’d appreciate if you’re using ESP32 if you’d let me know if your sketches are running fine with the latest from teensy4, or if you see any errors.

I tested Adafruit_GFX functions that are included in the Adafruit_GFX sketch (adapted from Adafruit’s own examples), but I don’t think this tests Adafruit_GFX functions 100%. There’s probably some things to fix, please let me know if you run into errors, and include a sample sketch to reproduce it and I’ll try to get a fix done ASAP.

If yo’u’re trying to replace SmartMatrix::GFX by integrating its FastLED+GFX functionality, by all means. I’ll have no problem turning down my code and pointing to yours.
If you were worried about breaking SmartMatrix::GFX, I don’t think it’s much of a worry. I really only use the pointer to your 2 copies of the framebuffer and poke into them directly as they happen to be compatible between SmartMatrix in 24bit mode, and FastLED.

The cast has not been a problem, all I do is this:

Even shorter, it’s really only
matrixleds = (CRGB *)backgroundLayer.backBuffer();

The direct cast works fine since the arrays are compatible.
Once I have a pointer on your array, I take my FastLED CRGB array and point it to that
matrix->newLedsPtr(matrixleds);
which goes there:

I didn’t have to do all the work you did, by defining _fb as an array of CRGB, I get all the FastLED goodness without having to re-write any of it :slight_smile:

Am I missing something?

Ok, if you are trying to do the same thing than me, but have it work with other bit depth than 24bit, then you have to do a fair amount of work. Is that what you’re doing?
If so, I didn’t bother because my existing solution involves so little code, fully reuses the existing code in FastLED and GFX (and updates to it I don’t have to worry about), and 24bpp is the only thing I’ll ever need (at least for storage).
Framebuffer::GFX totally supports downgrading the 24bit framebuffer to a 16bpp display like an LCD, but obviously it can’t go up to 32bits. That said, I have no need for 32bpp on any display. I grew up with 2-4bpp, I was extactic when I got 8bpp, and 24bpp is more than I thought I’d ever need. I feel it’s still true today :slight_smile:

Sure enough, your MatrixGFXDemo sketch works with the new layer with just two lines changed.

There’s really no need for that now, but if I do update the new GFX layers to support rgb8 and rgb16, then I think the best way to integrate Framebuffer::GFX with the GFX layers using non-24 bit color is probably to make the GFX layers compatible with Framebuffer::GFX. I’m not working on that now, so I’m satisfied with the fact that SmartMatrix::GFX still works.

  // Because SmartMatrix uses templates so heavily, its object cannot be passed to us
  // However the main function can create a show function that copies our data from _fb
  // into the SmartMatrix object, and pass that function to us by pointer.
  void (* _show)();

From your comments it seemed like you weren’t happy with the _show() call in SmartMatrix:GFX. I did have to figure out how pass a Layer object to a function to add a randomization feature in the MultipleTextLayersGFX sketch, and it seems like that might work for SmartMatrix:GFX. Here’s that code in case it helps you:

Great to hear the sketch “just works” (after changing the top config bit).

I didn’t love it, I’m not a fan of all the limitations that templates introduce, but I got over it :slight_smile:

interesting, I thought it wasn’t actually possible. I’m not sure if I want to change the interface in an incompatible way, now, Still, worth having a look.

Thanks