VideoDisplay: How are pixels set?

Status
Not open for further replies.

dirkblaze

Member
Q1: In the VideoDisplay sketch found on the Arduino OctoWS2811 Examples menu, when the Teensy receives a frame of data, it puts it into the “drawingMemory” then shows the LEDs. How is that supposed to work? When does the data just sent get pushed onto the LEDs?

I am running one Teensy / octo and one data wire, btw so the frame sync stuff isn’t getting used.

From VideoDisplay sketch:

if (startChar == '*') {
// receive a "master" frame - we send the frame sync to other boards
// the sender is controlling the video pace. The 16 bit number is
// how far into this frame to send the sync to other boards.
unsigned int startAt = micros();
unsigned int usecUntilFrameSync = 0;
int count = Serial.readBytes((char *)&usecUntilFrameSync, 2);
if (count != 2) return;
count = Serial.readBytes((char *)drawingMemory, sizeof(drawingMemory));

if (count == sizeof(drawingMemory)) { //<<<< So we have the image date from Processing sketch


// image data is in the "drawingMemory" buffer

unsigned int endAt = micros();
unsigned int usToWaitBeforeSyncOutput = 100;
if (endAt - startAt < usecUntilFrameSync) {
usToWaitBeforeSyncOutput = usecUntilFrameSync - (endAt - startAt);
}
digitalWrite(12, HIGH);
pinMode(12, OUTPUT);
delayMicroseconds(usToWaitBeforeSyncOutput);
digitalWrite(12, LOW);
// WS2811 update begins immediately after falling edge of frame sync
digitalWrite(13, HIGH);

leds.show(); // <<<<< "Showing" the LEDs here doesn't seem to do anything!!

digitalWrite(13, LOW);
}



Q2: Is there more detailed documentation on these "drawing operations" and the reason for setting aside memory here? If this is being used by the OctoWS2811 LED library, why are we using it for an I/O buffer?

Quoting from the brief documentation on https://www.pjrc.com/teensy/td_libs_OctoWS2811.html, "drawingMemory: The memory used for drawing operations. Use either an array of "int" 6 times ledsPerStrip, or NULL to perform all drawing directly to the display memory. "


Thanks Paul!
 
leds.show(); // <<<<< "Showing" the LEDs here doesn't seem to do anything!!

Actually, it does quite a lot.

First, if the hardware is still busy updating the LEDs from your prior show(), it waits for the hardware to finish.

Then it copies the drawing buffer to the display buffer, and starts the hardware working on the LED update using the display buffer.

Is there more detailed documentation on these "drawing operations" and the reason for setting aside memory here?

Maybe you're thinking show() does all the update work and returns only after the LEDs are all updated. That's how FastLED and NeoPixel work. It's simple and easy to understand, but not very efficient. You can't even begin working on next frame until show() is done.

OctoWS2811 uses DMA hardware to update the LEDs, while your code continues to run and has full access to the CPU. Unless it's still working on the prior update, show() returns almost instantly. The LEDs update automatically while your code runs. This gives you a huge performance advantage, since you can start working on the next frame while the LEDs are updating.

The drawing buffer is used so your changes don't interfere with the last frame you just gave to show(). Remeber, the hardware is still working to slowly send all the data out the pins, while you get to draw a new frame. This is a pretty standard graphics technique called double buffering. It avoids strange flicking bugs, which vary depending on the speed of your code and what order it writes the pixels.
 
Thanks, but where, exactly, does the sketch "copies the drawing buffer to the display buffer, and starts the hardwar working on the LED update using the display buffer?"

As you just said, "Show" doesn't do that. Also, how are you telling the HW that the first three bytes of drawingMemory are not display data?
Also, why are we read "sizeof(drawingMemory)" which is "int drawingMemory[ledsPerStrip*6]" when the data sent from Movie2Serial is this:
"byte[(ledImage.width * ledImage.height * 3) + 3]" => not the same as the much larger drawingMemory??

When I ran this code, my display did not update!! I had to write a routine to set the pixels from the inbound buffer. I'm sure what you're describing is faster. But I don't see how it works!!
 
I guess toggling pin 13 tells Octo to map colors from drawingMemory into the display memory and there to the pixels? Where is this documented? What, exactly is the format of the drawingMemory supposed to be? Where can I find that?

Yep, I'm familiar with double buffering, btw. Was righting DB code for the Amiga in 1988!

Thanks!
 
but where, exactly, does the sketch "copies the drawing buffer to the display buffer

Line 257 within the show() function!

https://github.com/PaulStoffregen/OctoWS2811/blob/master/OctoWS2811.cpp#L257

When I ran this code, my display did not update!!

This library has been used by many thousands of people over the last 4 years. It is very mature code that works well.

Perhaps your efforts would be better directed at troubleshooting your hardware?
 
Status
Not open for further replies.
Back
Top