Trouble wrapping my head around some parts of movie2serial PDE

Status
Not open for further replies.

visualSound

Well-known member
Hey everyone. So I've been breaking my brain over a very small bit of code in the movie2serial PDE that comes with the octo library.

Let me start off with my original issue:

I have been using a for loop and .setPixel() and ints for red, green, and blue in my teensy's code and sending values ranging from 0-255 from my video application over serial. However I noticed that the videoDisplay sketch does things in a more optimal way, where it reads the incoming serial byte array directly into the drawingMemory array.

So, I tried replicated this in my own teensy serial receiver code, however I get strange results with the colors. The pattern is there... but the hue and saturation and brightness is jumbled.

So I dove into the movie2serial PDE and discovered that the bytes are ranging from -128 to 127, while the video application I use sends values from 0-255, which is using python by the way.
The values them selves even when I add 128, don't make sense to me, and on top of that I'm having a hard time understanding what the bit wise operators and stuff are doing to the data. I want to replicate what movie2serial is doing in python, but I just don't have a clue what I'm doing :confused:

1) so the video's pixel in processing (which up to this point I understand) is getting passed into "colorWiring", this converts the hex color value to 3 ints, applies gamma, then converts it back to hex but with a new order...
After that I'm confused as to how the values are going negative, and how they produce correct colors on the arduino side:

Code:
    for (x = xbegin; x != xend; x += xinc) {
      for (int i=0; i < 8; i++) {
        // fetch 8 pixels from the image, 1 for each pin
        pixel[i] = image.pixels[x + (y + linesPerPin * i) * image.width];
        pixel[i] = colorWiring(pixel[i]);
      }
      // convert 8 pixels to 24 bytes
      for (mask = 0x800000; mask != 0; mask >>= 1) {
        byte b = 0;
        for (int i=0; i < 8; i++) {
          if ((pixel[i] & mask) != 0) b |= (1 << i);
        }
        println(b);
        data[offset++] = b;
        //data[offset++] = 124;
      }
    }

Why are the values not staying from 0-255?

Why does sending values of 0-255 from another application generate weird results?
 
My first thought is variable size and type. It looks like a BYTE is treated as signed and can't hold numbers over 127. And if you shift a one out the left it can be carried as a sign.

My second is that that incomplete code does not show how pixel and data arrays are defined so I couldn't say for sure. Or as Paul and the masthead say:

Forum Rule: Always post complete source code & details to reproduce any issue!

<edit> byte is treated as unsigned
 
Last edited:
No luck,

I tried adding this line just to see what it prints out:
Code:
println(b << 1);
It seemed to double the values, so larger negative and positive numbers.

I'm still trying to understand how a signed byte value in Processing going from -128 to 127 can be sent over serial to an arduino which works in unsigned bytes from 0-255 ... I'm sure this is obvious to experienced programmers, I just haven't stumbled across any explanations of this thus far.

Why is it that the same arduino code, when receiving byte values from 0-255 from python, over serial, comes in all mucked up?
 
Actually what I said isn't entirely true:

in the arduino code, drawingMemory is not a byte array at declaration, but an int array.
Code:
int drawingMemory[ledsPerStrip*6];

and later it's populated using serial.readBytes and "(char* )" which I'm not totally clear on what that's doing either:
Code:
count = Serial.readBytes((char *)drawingMemory, sizeof(drawingMemory));




For reference, here's the full code from processing:
Code:
/*  OctoWS2811 movie2serial.pde - Transmit video data to 1 or more
 Teensy 3.0 boards running OctoWS2811 VideoDisplay.ino
 http://www.pjrc.com/teensy/td_libs_OctoWS2811.html
 Copyright (c) 2013 Paul Stoffregen, PJRC.COM, LLC
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:
 
 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 */

// To configure this program, edit the following sections:
//
//  1: change myMovie to open a video file of your choice    ;-)
//
//  2: edit the serialConfigure() lines in setup() for your
//     serial device names (Mac, Linux) or COM ports (Windows)
//
//  3: if your LED strips have unusual color configuration,
//     edit colorWiring().  Nearly all strips have GRB wiring,
//     so normally you can leave this as-is.
//
//  4: if playing 50 or 60 Hz progressive video (or faster),
//     edit framerate in movieEvent().

import processing.video.*;
import processing.serial.*;
import java.awt.Rectangle;

Movie myMovie = new Movie(this, "D:/AV/1080p/3d-freebies/free-loops_Lightrays_2_live.mov");

float gamma = 1.7;

int numPorts=0;  // the number of serial ports in use
int maxPorts=24; // maximum number of serial ports

Serial[] ledSerial = new Serial[maxPorts];     // each port's actual Serial port
Rectangle[] ledArea = new Rectangle[maxPorts]; // the area of the movie each port gets, in % (0-100)
boolean[] ledLayout = new boolean[maxPorts];   // layout of rows, true = even is left->right
PImage[] ledImage = new PImage[maxPorts];      // image sent to each port
int[] gammatable = new int[256];
int errorCount=0;
float framerate=0;

void setup() {
  String[] list = Serial.list();
  delay(20);
  println("Serial Ports List:");
  println(list);
  serialConfigure("COM3");  // change these to your port names
  //serialConfigure("/dev/ttyACM1");
  if (errorCount > 0) exit();
  for (int i=0; i < 256; i++) {
    gammatable[i] = (int)(pow((float)i / 255.0, gamma) * 255.0 + 0.5);
  }
  size(480, 400);  // create the window
  myMovie.loop();  // start the movie :-)
}


// movieEvent runs for each new frame of movie data
void movieEvent(Movie m) {
  // read the movie's next frame
  m.read();

  //if (framerate == 0) framerate = m.getSourceFrameRate();
  framerate = 30.0; // TODO, how to read the frame rate???

  for (int i=0; i < numPorts; i++) {    
    // copy a portion of the movie's image to the LED image
    int xoffset = percentage(m.width, ledArea[i].x);
    int yoffset = percentage(m.height, ledArea[i].y);
    int xwidth =  percentage(m.width, ledArea[i].width);
    int yheight = percentage(m.height, ledArea[i].height);
    ledImage[i].copy(m, xoffset, yoffset, xwidth, yheight, 
    0, 0, ledImage[i].width, ledImage[i].height);
    // convert the LED image to raw data
    byte[] ledData =  new byte[(ledImage[i].width * ledImage[i].height * 3) + 3];
    image2data(ledImage[i], ledData, ledLayout[i]);
    if (i == 0) {
      ledData[0] = '*';  // first Teensy is the frame sync master
      int usec = (int)((1000000.0 / framerate) * 0.75);
      ledData[1] = (byte)(usec);   // request the frame sync pulse
      ledData[2] = (byte)(usec >> 8); // at 75% of the frame time
    } else {
      ledData[0] = '%';  // others sync to the master board
      ledData[1] = 0;
      ledData[2] = 0;
    }
    // send the raw data to the LEDs  :-)
    println(ledData.length);
    ledSerial[i].write(ledData);
  }
}

// image2data converts an image to OctoWS2811's raw data format.
// The number of vertical pixels in the image must be a multiple
// of 8.  The data array must be the proper size for the image.
void image2data(PImage image, byte[] data, boolean layout) {
  int offset = 3;
  int x, y, xbegin, xend, xinc, mask;
  int linesPerPin = image.height / 8;
  int pixel[] = new int[8];

  for (y = 0; y < linesPerPin; y++) {
    if ((y & 1) == (layout ? 0 : 1)) {
      // even numbered rows are left to right
      xbegin = 0;
      xend = image.width;
      xinc = 1;
    } else {
      // odd numbered rows are right to left
      xbegin = image.width - 1;
      xend = -1;
      xinc = -1;
    }
    for (x = xbegin; x != xend; x += xinc) {
      for (int i=0; i < 8; i++) {
        // fetch 8 pixels from the image, 1 for each pin
        pixel[i] = image.pixels[x + (y + linesPerPin * i) * image.width];
        pixel[i] = colorWiring(pixel[i]);
      }
      // convert 8 pixels to 24 bytes
      for (mask = 0x800000; mask != 0; mask >>= 1) {
        byte b = 0;
        for (int i=0; i < 8; i++) {
          if ((pixel[i] & mask) != 0) b |= (1 << i);
        }
        println(b << 1);
        data[offset++] = b;
      }
    }
  }
}

// translate the 24 bit color from RGB to the actual
// order used by the LED wiring.  GRB is the most common.
int colorWiring(int c) {
  int red = (c & 0xFF0000) >> 16;
  int green = (c & 0x00FF00) >> 8;
  int blue = (c & 0x0000FF);
  red = gammatable[red];
  green = gammatable[green];
  blue = gammatable[blue];
  return (green << 16) | (red << 8) | (blue); // GRB - most common wiring
}

// ask a Teensy board for its LED configuration, and set up the info for it.
void serialConfigure(String portName) {
  if (numPorts >= maxPorts) {
    println("too many serial ports, please increase maxPorts");
    errorCount++;
    return;
  }
  try {
    ledSerial[numPorts] = new Serial(this, portName);
    if (ledSerial[numPorts] == null) throw new NullPointerException();
    ledSerial[numPorts].write('?');
  } 
  catch (Throwable e) {
    println("Serial port " + portName + " does not exist or is non-functional");
    errorCount++;
    return;
  }
  delay(50);
  String line = ledSerial[numPorts].readStringUntil(10);
  if (line == null) {
    println("Serial port " + portName + " is not responding.");
    println("Is it really a Teensy 3.0 running VideoDisplay?");
    errorCount++;
    return;
  }
  String param[] = line.split(",");
  if (param.length != 12) {
    println("Error: port " + portName + " did not respond to LED config query");
    errorCount++;
    return;
  }
  // only store the info and increase numPorts if Teensy responds properly
  ledImage[numPorts] = new PImage(Integer.parseInt(param[0]), Integer.parseInt(param[1]), RGB);
  ledArea[numPorts] = new Rectangle(Integer.parseInt(param[5]), Integer.parseInt(param[6]), 
  Integer.parseInt(param[7]), Integer.parseInt(param[8]));
  ledLayout[numPorts] = (Integer.parseInt(param[5]) == 0);
  numPorts++;
}

// draw runs every time the screen is redrawn - show the movie...
void draw() {
  // show the original video
  image(myMovie, 0, 80);

  // then try to show what was most recently sent to the LEDs
  // by displaying all the images for each port.
  for (int i=0; i < numPorts; i++) {
    // compute the intended size of the entire LED array
    int xsize = percentageInverse(ledImage[i].width, ledArea[i].width);
    int ysize = percentageInverse(ledImage[i].height, ledArea[i].height);
    // computer this image's position within it
    int xloc =  percentage(xsize, ledArea[i].x);
    int yloc =  percentage(ysize, ledArea[i].y);
    // show what should appear on the LEDs
    image(ledImage[i], 240 - xsize / 2 + xloc, 10 + yloc);
  }
}

// respond to mouse clicks as pause/play
boolean isPlaying = true;
void mousePressed() {
  if (isPlaying) {
    myMovie.pause();
    isPlaying = false;
  } else {
    myMovie.play();
    isPlaying = true;
  }
}

// scale a number by a percentage, from 0 to 100
int percentage(int num, int percent) {
  double mult = percentageFloat(percent);
  double output = num * mult;
  return (int)output;
}

// scale a number by the inverse of a percentage, from 0 to 100
int percentageInverse(int num, int percent) {
  double div = percentageFloat(percent);
  double output = num / div;
  return (int)output;
}

// convert an integer from 0 to 100 to a float percentage
// from 0.0 to 1.0.  Special cases for 1/3, 1/6, 1/7, etc
// are handled automatically to fix integer rounding.
double percentageFloat(int percent) {
  if (percent == 33) return 1.0 / 3.0;
  if (percent == 17) return 1.0 / 6.0;
  if (percent == 14) return 1.0 / 7.0;
  if (percent == 13) return 1.0 / 8.0;
  if (percent == 11) return 1.0 / 9.0;
  if (percent ==  9) return 1.0 / 11.0;
  if (percent ==  8) return 1.0 / 12.0;
  return (double)percent / 100.0;
}


My arduino code:
Code:
// ------------------- Variables - These need to be set -------------------- //
//#define PIN 2
const int ledsPerStrip = 500;
const int dataChunkSize = 3;

int maxBright = 255;

// ------------------- Variables - These just need to be declared -------------------- //
#include <OctoWS2811.h>
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

const int numOfBytes = ledsPerStrip * 8 * dataChunkSize;
int byteReturnLen = 0;
int byteReturnCounter = 0;
byte inputBuffer[numOfBytes];
int led = 0;
int led_r = 0;
int led_g = 0;
int led_b = 0;

// ------------------- Setup -------------------- //
void setup() {
  leds.begin();
  delay(500);
  Serial.begin(115200);
  Serial.setTimeout(500);
  leds.show();
}
// ------------------- Main Loop -------------------- //
void loop() {
  if(Serial.available() > 0) {
    byteReturnCounter = Serial.readBytes((char *)drawingMemory, numOfBytes);
  }

      leds.show();
}
 
drawingMemory is just a big buffer in memory used to hold the pixels.

It's defined with "int" to cause the compiler to automatically align it to a 32 bit boundary. Being aligned to the physical memory bus inside the chip allows some parts inside the library to work more optimally. If it were defined as "char" or "byte", the compiler wouldn't automatically align it. A special syntax for forcing alignment is available, but it's messy. Just using "int" is much simpler, though it does hide this subtle point.

The memory is actually used as an array of bytes in most places.
 
Interesting use!
Well that definitely clears things up a bit more, but I'm still having trouble getting 0-255 byte values of the appropriate length to show correctly on the leds/teensy.

I'm using the above stripped down arduino code, which works, but incorrectly. I tried printing the values that are going out to the led's and they are huge numbers, all over the place which is where I think the noisy colors are coming from:

ledImg.jpg

If it's treating the int array as a byte array in terms of led RGB values, and I'm sending out values from 0-255 over serial why would this be happening?

If I load the serial buffer into:
Code:
char inputBuffer[numOfBytes];


then use:
Code:
      for (int j = 0; j < (ledsPerStrip * 8); j++) {
        led_r = inputBuffer[(j*dataChunkSize)];
        led_g = inputBuffer[(j*dataChunkSize)+1];
        led_b = inputBuffer[(j*dataChunkSize)+2];
        leds.setPixel(j, led_r, led_g, led_b);
      }

where led_r, led_g, and led_b are ints.. it works as expected. The values are correct and the colors on the strip right.

What is the setPixel() function doing that the raw data coming in is not?
 
I wanted to bump this thread as I've still been 100% stumped on this one:
In order to simplify my question :

Here's my stripped down teensy receiving code:

Code:
#include <OctoWS2811.h>
const int ledsPerStrip = 8;

DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int numOfBytes = ledsPerStrip * 8 * 3;

const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);


void setup() {
  leds.begin();
  delay(500);
  Serial.begin(115200);
  Serial.setTimeout(500);
  leds.show();
}


void loop() {
  if(Serial.available() > 0) {
    Serial.readBytes((char *)drawingMemory, numOfBytes);
  }
  leds.show();
}



Here's my stripped down sender code in processing:

Code:
import processing.serial.*;
Serial port;

int numPix = 64;
int dataChunkSize = 3;
byte[] vals = new byte[numPix * dataChunkSize];

float sinVal = 0;
float time = 0;
float timeSpeed = .05;


void setup() {
  size(64, 1, P2D);
  String[] portNames = Serial.list();
  println(portNames);
  port = new Serial(this, portNames[1], 115200); //115200
}


void draw() {
  background(0);
  loadPixels();
  sinVal = sin(time);
  sinVal = sinVal *.5 + .5;
  
  // Simple sin wave / lfo like animation across all pixels.
  for (int z = 0; z < pixels.length; z ++) {
    pixels[z] = color(sinVal*255, 0, 0);
  }

  // getting pixels - not neccesary here but want it in the workflow for later.
  updatePixels();
  for (int z = 0; z < pixels.length; z ++) {
    color c = pixels[z];
    byte r = (byte) (((c >> 16) & 0xFF));
    byte g = (byte) (((c >> 8) & 0xFF));
    byte b = (byte) ((c & 0xFF));

    vals[z*dataChunkSize] = r;
    vals[z*dataChunkSize+1] = g;
    vals[z*dataChunkSize+2] = b;
  }

  port.write(vals);
  time += timeSpeed;
}

This doesn't work - and I'm sure it's something simple that's just not obvious to me.
Results on strip are highly erratic and random looking with a hint of the intended pattern sometimes visible.
 
Serial.readBytes() returns the actual number of bytes read, you might check that value. you might need to do multiple reads.
 
Hey thanks manitou -

When I use the octo library and use a for loop and setPixel() to transfer values 1 at a time from source array > to "drawingMemory" array - no problem. It's when I try to read the serial buffer directly into "drawingMemory" that results in the above.
 
Bumping this thread!
Any one have any input on how to get this working properly?

Post # 10 shows the most simplified version of my problem, where Processing is sending serial over to Teensy 3.1 using the above code.


- Why does reading serial data directly into the drawingMemory array/buffer not work correctly? (the led's display an extremely flickery version of what the animation is supposed to look like)
 
Just scanning on my phone so not reading all before. .. can you memcopy or similar in place of serial read?
 
- Why does reading serial data directly into the drawingMemory array/buffer not work correctly? (the led's display an extremely flickery version of what the animation is supposed to look like)

Probably because the pixel data is arranged differently in that buffer than the arrangement in the source data you're trying to directly copy.
 
Paul,

In my simplified processing sketch, I'm building an array that contains 3 bytes for every pixel.
r1,g1,b1,r2,g2,b2,r3,g3,b3 etc..

Is this not how the "drawingMemory" array is structured on the receiving end?
Are there extra bytes that i'm missing?
How should I structure my byte data in processing?
 
In my simplified processing sketch, I'm building an array that contains 3 bytes for every pixel.
r1,g1,b1,r2,g2,b2,r3,g3,b3 etc..

Is this not how the "drawingMemory" array is structured on the receiving end?

Indeed, that is NOT how OctoWS2811 stores its data.

I've been considering switching the drawing buffer (but not the display buffer) to this common format. Someone recently submitted a patch on github to rapidly convert formats. The display buffer MUST be in a rather unusual format which OctoWS2811 requires.

How should I structure my byte data in processing?

There's a function in the movie2serial.pde sketch which converts from the common RGB format to OctoWS2811's special format.

The format is groups of 24 bytes, where the first byte is 8 LSB, the next byte is 8 bit1, etc. Each group of 24 bytes are 8 pixels. Yes, I know that's "strange", but think of how OctoWS2811 sends out 8 parallel schemes. The display buffer MUST be in this special format with 8 copies of the same bit within 8 different pixels, because that's how it actually transmits out 8 streams of pixels in parallel.

If you want to write directly into the OctoWS2811 buffers, you must use its special format. If you simply write the common RGB packed byte format, you'll end up with your bits in mostly the wrong places, not even going to the same LEDs.
 
Got ya, That's super helpful thank you Paul.

Is it possible to format that 24 byte segment with out diving into the lower level stuff you're talking about? Or is it not as simple as "put the rgb bytes here and the other bytes there"..
Meantime I will revisit the bit of code that converts 8 pixels to 24 bytes and see report back with my results.

Thanks for the explanation!
 
Any chance I could get a link to that conversion patch? Would love to take a look at it and see how it works / try to integrate it.
 
Are you looking for this from the installed libraries.: I:\Teensy163\hardware\teensy\avr\libraries\OctoWS2811\examples\VideoDisplay\Processing
 
Someone recently submitted a patch on github to rapidly convert formats.
defragster, no I have the videoDisplay\processing file and I've been picking it apart - I was referring to what Paul said in the above quote.

Basically I'm trying to make a simplified version of the method named image2data that's in that processing sketch... something that works with out needing to conform to the structure of the rest of the code that can take 8 r/g/b values and convert them into the integer format.

from that I ultimately need a similar version in python that way I can communicate to the teensy (trying to avoid .setPixel() for performance reasons) from Touch Designer.
For loops in Python are quite a bit different from java / c so it seems like I'll have to do a bit more hacking to get that working - but that's my goal !
 
Paul,
So I've been doing some more reading on binary / bytes / ints etc and have a bit clearer of an idea on how that works if only slightly.
Some of this might be common sense but I want to make sure I am on the right track here..

I checked the size of an int on the teensy3.1 using sizeof() which told me it's 4 bytes wide

So does that mean the data is structured somewhat like this?:
Code:
{  1      2       3       4      5       6       7      8       9      10      11      12     13     14      15     16      17      18      19     20     21     22     23     24   }
{  1      2       3       4      1       2       3      4       1      2       3       4       1      2       3      4       1       2       3      4      1      2      3      4   }
{ int1 | int1 | int1 | int1 ,   int2 | int2 | int2 | int2 ,    int3 | int3 | int3 | int3 ,   int4 | int4 | int4 | int4 ,   int5 | int5 | int5 | int5 ,   int6 | int6 | int6 | int6  }
{  r1  ,  g1  ,  b1  ,  r2  ,    g2  ,  b2  ,  r3  ,  g3  ,     b3  ,  r4  ,  g4  ,  b4  ,    r5  ,  g5  ,  b5  ,  r6  ,    g6  ,  b6  ,  r7  ,  g7  ,    b7  ,  r8  ,  g8  ,  b8   }

Where the r/g/b triplets need to be shifted into integer form at their respective locations?
 
Last edited:
Okay - I wasn't sure what reference you were making to Paul's comment, but that file does have some RGB manipulation code in it so I thought it might be the piece.
 
So a bit of a follow up on my last post - I still had that data structure wrong.

The library is setup to simplify addressing the led's by making them led 0-n however the int array "drawingMemory" is setup to have the pixel1 of strips 1-8, then pixel2 of strips 1-8, so on, I didn't catch on to this until now so hopefully I didn't confuse anyone out there :)

Also, bitwise operators and such are new to me and had me pretty confused. I have a better idea of how they work now but it's not as simple as "this byte here and this byte there".

----------

Anyways that being said - I tracked down the person who made a patch the octows2811 library Paul mentioned:
https://github.com/bitogre/OctoWS2811/commit/18e3c93fac3aa7546c152969c9f9485c153a6ad7

that link above shows the changes made in relation to the optimization, I downloaded the library and compared it side by side with the standard one and noticed some pretty huge speed increases. Here's what I found

Standard octo library : 2,320 pixels total at 60 fps (290 per pin)
Modified octo library : 3,360 pixels total at 60 fps (420 per pin)


That's a difference of 1,040 led's total !

Just to be clear this is when using .setPixel() to set per pixel colors - if you can tap into writing directly to the drawing buffer array obviously it will be faster than the modified libraries figures but as this thread has shown, for an artist who knows some programming that's pretty tough ;)

Here was my final teensy's code:

Code:
// ------------------- Variables - These need to be set -------------------- //

const int ledsPerStrip = 400;

// ------------------- Variables - These just need to be declared -------------------- //
#include <OctoWS2811.h>
DMAMEM int displayMemory[ledsPerStrip*6];
int drawingMemory[ledsPerStrip*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(ledsPerStrip, displayMemory, drawingMemory, config);

const int numOfBytes = ledsPerStrip * 8 * 3;
char inputBuffer[numOfBytes];
int led_r = 0;
int led_g = 0;
int led_b = 0;

// ------------------- Setup -------------------- //
void setup() {
  leds.begin();
  delay(500);
  Serial.begin(115200);
  Serial.setTimeout(500);
  leds.show();
}

// ------------------- Main Loop -------------------- //
void loop() {
  if(Serial.available() > 0) {
    Serial.readBytes(inputBuffer, numOfBytes);
  }
  
      for (int j = 0; j < (ledsPerStrip * 8); j++) {
        led_r = inputBuffer[(j*3)];
        led_g = inputBuffer[(j*3)+1];
        led_b = inputBuffer[(j*3)+2];
        leds.setPixel(j, led_r, led_g, led_b);
      }
      leds.show();
}

----------

Big thanks to bitOgre and Paul for the help here - I hope this optimization or an easier way to access the drawingBuffer get's added to the main branch when there's time - it's quite a big improvement !
 
Standard octo library : 2,320 pixels total at 60 fps (290 per pin)
Modified octo library : 3,360 pixels total at 60 fps (420 per pin)


That's a difference of 1,040 led's total !

Looks like I ought to get onto integrating that patch. ;)

The sad reality is I was about half-way through fiddling with OctoWS2811 and getting it sort-of working on Teensy-LC when Arduino 1.6.0 hit. Then 1.6.1, 1.6.2 & 1.6.3 came out, while getting LC released, and then I started digging into long-neglected issues with Lidar, SD, SPI flash. Somehow I haven't gotten back onto OctoWS2811, even though my 1920 LED test board is still sitting here in my tiny workspace, covering most of the window, this whole time!

There a regional Burning Man event next month wanting to use the LEDs, then they're going to go live at a local hackerspace... so the good news for OctoWS2811 is I have a fairly hard deadline coming up to get a new OctoWS2811 release wrapped up. I definitely want to get this patch integrated.
 
Status
Not open for further replies.
Back
Top