Go Down

Topic: OctoWS2811 Library - for large LED display at video speed refresh (Read 3 times) previous topic - next topic

Skorn

Hi Paul,

If you like the program and want to it include it in your next library release contact me via an IM.  I have no problem with this and you have my approval to do so, I would just like to ensure that the code is bugfree and properly commented etc..

Thanks,

Paul Stoffregen

I ran the code.  A few minor edits were needed to make it run.

Here's a really quick video.  Each half of the display is run from a separate Teensy 3.0, with no coordination between them.  They're both running the code below.  Sorry about the shaky cam... I don't have time to set up the tripod and do a proper video.  But I wanted to at least get a quick capture so you can see it.

http://www.pjrc.com/teensy/beta/PlasmaDemo.mov

I added code to blink the LED as each update begins.  I measured 99.9 Hz.

Code: [Select]

//PlazINT  -  Fast Plasma Generator using Integer Math Only
//Edmund "Skorn" Horn
//March 4,2013
//Version 1.0 adapted for OctoWS2811Lib (tested, working...)


#include <OctoWS2811.h>

//OctoWS2811 Defn. Stuff
#define COLS_LEDs 60  // all of the following params need to be adjusted for screen size
#define ROWS_LEDs 16  // LED_LAYOUT assumed 0 if ROWS_LEDs > 8
#define LEDS_PER_STRIP (COLS_LEDs * (ROWS_LEDs / 6))

DMAMEM int displayMemory[LEDS_PER_STRIP*6];
int drawingMemory[LEDS_PER_STRIP*6];
const int config = WS2811_GRB | WS2811_800kHz;
OctoWS2811 leds(LEDS_PER_STRIP, displayMemory, drawingMemory, config);

//Byte val 2PI Cosine Wave, offset by 1 PI
//supports fast trig calcs and smooth LED fading/pulsing.
uint8_t const cos_wave[256] PROGMEM =
{0,0,0,0,1,1,1,2,2,3,4,5,6,6,8,9,10,11,12,14,15,17,18,20,22,23,25,27,29,31,33,35,38,40,42,
45,47,49,52,54,57,60,62,65,68,71,73,76,79,82,85,88,91,94,97,100,103,106,109,113,116,119,
122,125,128,131,135,138,141,144,147,150,153,156,159,162,165,168,171,174,177,180,183,186,
189,191,194,197,199,202,204,207,209,212,214,216,218,221,223,225,227,229,231,232,234,236,
238,239,241,242,243,245,246,247,248,249,250,251,252,252,253,253,254,254,255,255,255,255,
255,255,255,255,254,254,253,253,252,252,251,250,249,248,247,246,245,243,242,241,239,238,
236,234,232,231,229,227,225,223,221,218,216,214,212,209,207,204,202,199,197,194,191,189,
186,183,180,177,174,171,168,165,162,159,156,153,150,147,144,141,138,135,131,128,125,122,
119,116,113,109,106,103,100,97,94,91,88,85,82,79,76,73,71,68,65,62,60,57,54,52,49,47,45,
42,40,38,35,33,31,29,27,25,23,22,20,18,17,15,14,12,11,10,9,8,6,6,5,4,3,2,2,1,1,1,0,0,0,0
};


//Gamma Correction Curve
uint8_t const exp_gamma[256] PROGMEM =
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,
4,4,4,4,4,5,5,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,12,12,12,13,13,14,14,14,15,15,
16,16,17,17,18,18,19,19,20,20,21,21,22,23,23,24,24,25,26,26,27,28,28,29,30,30,31,32,32,33,
34,35,35,36,37,38,39,39,40,41,42,43,44,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,70,71,72,73,74,75,77,78,79,80,82,83,84,85,87,89,91,92,93,95,96,98,
99,100,101,102,105,106,108,109,111,112,114,115,117,118,120,121,123,125,126,128,130,131,133,
135,136,138,140,142,143,145,147,149,151,152,154,156,158,160,162,164,165,167,169,171,173,175,
177,179,181,183,185,187,190,192,194,196,198,200,202,204,207,209,211,213,216,218,220,222,225,
227,229,232,234,236,239,241,244,246,249,251,253,254,255
};


void setup()
{
  pinMode(13, OUTPUT);
  leds.begin();
  leds.show();
}

void loop()
{
  unsigned long frameCount=25500;  // arbitrary seed to calculate the three time displacement variables t,t2,t3
  while(1) {
    frameCount++ ;
    uint16_t t = fastCosineCalc((42 * frameCount)/100);  //time displacement - fiddle with these til it looks good...
    uint16_t t2 = fastCosineCalc((35 * frameCount)/100);
    uint16_t t3 = fastCosineCalc((38 * frameCount)/100);

    for (uint8_t y = 0; y < ROWS_LEDs; y++) {
      int left2Right, pixelIndex;
      if (((y % (ROWS_LEDs/8)) & 1) == 0) {
        left2Right = 1;
        pixelIndex = y * COLS_LEDs;
      } else {
        left2Right = -1;
        pixelIndex = (y + 1) * COLS_LEDs - 1;
      }
      for (uint8_t x = 0; x < COLS_LEDs ; x++) {
        //Calculate 3 seperate plasma waves, one for each color channel
        uint8_t r = fastCosineCalc(((x << 3) + (t >> 1) + fastCosineCalc((t2 + (y << 3)))));
        uint8_t g = fastCosineCalc(((y << 3) + t + fastCosineCalc(((t3 >> 2) + (x << 3)))));
        uint8_t b = fastCosineCalc(((y << 3) + t2 + fastCosineCalc((t + x + (g >> 2)))));
        //uncomment the following to enable gamma correction
        //r=pgm_read_byte_near(exp_gamma+r); 
        //g=pgm_read_byte_near(exp_gamma+g);
        //b=pgm_read_byte_near(exp_gamma+b);
        leds.setPixel(pixelIndex, ((r << 16) | (g << 8) | b));
        pixelIndex += left2Right;
      }
    }
    digitalWrite(13, HIGH);
    leds.show();  // not sure if this function is needed  to update each frame
    digitalWrite(13, LOW);
  }
}


inline uint8_t fastCosineCalc( uint16_t preWrapVal)
{
  uint8_t wrapVal = (preWrapVal % 255);
  if (wrapVal<0) wrapVal=255+wrapVal;
  return (pgm_read_byte_near(cos_wave+wrapVal));
}



Skorn

Hi Paul,

Thanks for the video and trying out the code.  One thing I didn't do in the code is to account for size of displays.  Personally I think the waveforms would look better if they were tweaked to suit your larger screen.  It looks good and fast though.  Almost 100fps realtime for that screen size is really good.  My Atmega 328p +TLC5940 based 16x8 matrix calculates pages at just over 30FPS, however,  the screen refreshed by the TLCs at 150Hz.

Anyway, thanks for the feedback.


Helmuth


ohararp

#9
Apr 01, 2013, 05:30 am Last Edit: Apr 01, 2013, 05:36 am by ohararp Reason: 1
Skorn,

I was playing with the Teensy 3.0 library and got your plasma program up and running on a small 16x16 matrix (see attached pic).  I am waiting to make a larger display but am testing out code in the meantime.  I was wondering how you generated the gamma correction table?  Did you use this link? http://neuroelec.com/2011/04/led-brightness-to-your-eye-gamma-correction-no/  I plotted the values you used for reference and compared them to the equation that was used as a reference http://www.poynton.com/PDFs/SMPTE93_Gamma.pdf. Based on the Matlab Plot (see attachment) using the equation:

Code: [Select]
res=0:255;
GammaE=255*(res/255).^(1/.45);


They are a bit different.  Nothing to be worried about, however I was just trying to track down where the gamma you used came from?

Code: [Select]
//Gamma Correction Curve
uint8_t const exp_gamma[256] PROGMEM =
{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,3,3,3,3,3,
4,4,4,4,4,5,5,5,5,5,6,6,6,7,7,7,7,8,8,8,9,9,9,10,10,10,11,11,12,12,12,13,13,14,14,14,15,15,
16,16,17,17,18,18,19,19,20,20,21,21,22,23,23,24,24,25,26,26,27,28,28,29,30,30,31,32,32,33,
34,35,35,36,37,38,39,39,40,41,42,43,44,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,
61,62,63,64,65,66,67,68,70,71,72,73,74,75,77,78,79,80,82,83,84,85,87,89,91,92,93,95,96,98,
99,100,101,102,105,106,108,109,111,112,114,115,117,118,120,121,123,125,126,128,130,131,133,
135,136,138,140,142,143,145,147,149,151,152,154,156,158,160,162,164,165,167,169,171,173,175,
177,179,181,183,185,187,190,192,194,196,198,200,202,204,207,209,211,213,216,218,220,222,225,
227,229,232,234,236,239,241,244,246,249,251,253,254,255


Edit:  Running the Plasma Example with the Gamma Correction provided a much more dramatic effect.  Great Job!
__________
Thanks Ryan
www.ohararp.com

Go Up