Can I remove one extra FB?


#1

Right now I have 3 copies of my FB:
backgroundBuffers[currentRefreshBuffer]
backgroundBuffers[currentDrawBuffer]
CRGB matrixleds[w*h]; (in SmartMatrix_GFX)

Currently, I need to do this:

CRGB matrixleds[w*h]
void show_callback() {
    memcpy(backgroundLayer.backBuffer(), matrixleds, kMatrixHeight*kMatrixWidth*3);
    backgroundLayer.swapBuffers(false);
}

I’m not entirely sure how the 2 FBs in backgroundBuffers work.
I can see they get swapped, and I can see that
backgroundLayer.swapBuffers(true) allows keeping the 2 frames in sync

I tried to do 2 things
First I tried to add this code to Layer_Background_Impl.h

template<typename RGB, unsigned int optionFlags>
void SMLayerBackground<RGB, optionFlags>::ResetBackBuffer(RGB* newbuffer) {
  RGB *old = backgroundBuffers[currentDrawBuffer];
  backgroundBuffers[currentDrawBuffer] = newbuffer;
  free(old);
}

Then, I was kind of hoping that I could just draw in it directly, but that didn’t take care of my swapping problem, so that’s likely a dead end.

Instead, the solution was apparently do go the other way, let SmartMatrix manage its 2 buffers and repoint my CRGB FastLED buffer to the SM backbuffer.
CRGB and rgb24 are not equivalent due to the methods added to the CRGB object, but the underlying storage should be the same, no? (afterall I can memcpy from one to the other and that works fine).

//CRGB matrixleds[width*height];
CRGB *matrixleds;  // don't malloc, have a pointer I can repoint

// and then after each swap, point it to the bg buffer
void show_callback() {
    //memcpy(backgroundLayer.backBuffer(), matrixleds, kMatrixHeight*kMatrixWidth*3);
    backgroundLayer.swapBuffers(false); // maybe true instead
    //matrixleds = (CRGB *) backgroundLayer.getRealBackBuffer();
    matrixleds = (CRGB *) backgroundLayer.backBuffer();
}

    matrixLayer.addLayer(&backgroundLayer); 
    matrixLayer.begin();
    //matrixleds = (CRGB *) backgroundLayer.getRealBackBuffer();
    matrixleds = (CRGB *) backgroundLayer.backBuffer();

I wasn’t too clear on which one was correct between getRealBackBuffer and backBuffer.
Sadly, either way, I get a crash as soon as I write in matrixleds. I haven’t quite figured out why, yet.

Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.
0x400d5399: SmartMatrix_GFX::drawPixel(short, short, CRGB) at /home/merlin/Arduino/libraries/FastLED/pixeltypes.h line 178

So, is my hope to remove my GFX buffer mostly doomed?
Thanks


#2

true will make sure the buffers have the same data after the swap. false saves CPU cycles if you don’t care what’s in the buffer, e.g. if you fill it from scratch each time.

Take a look at the FastLED_Functions example. It shows when to call backBuffer (after waiting for isSwapPending() == false). You will want to ignore it’s use of swapBuffers(false), and change to true for your application


#3

Thanks, yeah, that was my basic understanding although I didn’t get that far given that I can’t get SmartMatrix to use an external FastLED buffer without crashing, or FastLED methods to work on a SmartMatrix buffer without crashing either.

For starters, would you agree that my ResetBackBuffer idea is flawed and indeed won’t work?
Then, could SmartMatrix work with a single buffer where the draw buffer is outside of its control and swapBuffers is replaced by a memcpy from the outside buffer to the SmartMatrix one?
I realize that you may end up with a refresh that runs half way through a memcpy, but somehow I’m thinking it will be fast enough not to matter so much.

Otherwise if you have suggestions on whether it’s possible to use a SmartMatrix buffer with FastLED primitives, what’s I’m doing with
matrixleds = (CRGB *) backgroundLayer.backBuffer();
this would work for me too (but indeed I tried, and I get a crash aspasted above)


#4

Can you paste the code that actually does the CRGB write into matrixleds?


#5

Sure

Sigh, of course I screwed this up and I see the problem now:

leds is set at begin() time. So, if I change it at runtime to point to the right backbuffer, _leds will be pointing to the wrong place.
I need to add some method that allows resetting the _leds pointer at runtime after begin()
Will look at doing that.

The problem of course is that the drawPixel method is not attached to a CRGB object, but to the NeoMatrix lib I wrote (so I should have known)


#6

Ok, I got it working now. I modified SmartMatrix::GFX to accept a new CRGB pointer. I then cast from rgb24 to CRGB and there are no problems (as expected).

@Louis , one question though: should I be using backBuffer or getRealBackBuffer? They both seem to work

void show_callback() {
    backgroundLayer.swapBuffers(true);
    matrix->newLedsPtr((CRGB *) backgroundLayer.backBuffer());
    //matrix->newLedsPtr((CRGB *) backgroundLayer.getRealBackBuffer());
}

#7

Done. 18KB of precious memory saved.

SmartMatrix::GFX is now “free” to use, no more duplicate framebuffer or extra copies (and you get access to FastLED / NeoMatrix and LEDMatrix code without having to rewrite anything).


#8

I think someone else contributed getRealBackBuffer(), and I don’t recall why you’d want to use it. Use backBuffer() unless something’s not working.


#9

Thanks. I’ll stick to backBuffer which seems to work fine.