I really like the new DemoReel100 example in FastLED3.1,

I really like the new DemoReel100 example in FastLED3.1, but I’m wondering what the best way to pass parameters to the various routines is (in order to make them more generic). For instance, we could generalize several parameters in the sinelon or bpm routines, thus giving us a much wider range of output. The poor hack I did was in the nextPattern() routine with:

if (gCurrentPatternNumber != (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns) ) {

switch(gCurrentPatternNumber) {             // The very first pattern MUST be pre-defined

  case 0: thisdelay=20; thisrot=1; thatrot=1; break;                                 // for my two_sin routine
  case 1: thisdelay=15; thisrot=0; break;
  case 2: thisdelay=20; thatrot=0; thishue=255; thathue=255; break;
  case 3: thisdelay=30; thiscutoff=128; thatcutoff=128; wavebright=64; break;
  case 4: thisdelay=20; wavebright=128; thisspeed=3; break;
}

}
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}

Would love to see it done elegantly though.

Here’s a modified DemoReel100 (called DemoReel2Arg) showing how you could pass two (hardcoded, not variable) arguments to each pattern function. It lets you do something similar to the code you posted here, but it’s more ‘declarative’, for what that’s worth.

And again the warning: we’re in the land of function pointers here, so this is not a good sketch to start with if you’re new to Arduino and/or C.

It could be done differently using C++ classes and inheritance and virtual functions, and that might be cleaner … or not. Keeping it simple is sometimes good.

Also, I have to say I sort of like the “Timecode Performance” model of how to do this.https://plus.google.com/112916219338292742137/posts/TVzTPbnJNE7

Awesome! I guess in the latter case, I could feed the arguments prior to calling the routine. Err, no I can’t. Not and have it change each time it’s called. Will sort that out.

Don’t underestimate the power and usefulness of global variables here, too, FWIW. I know we’re taught that they’re objectively and universally bad, but we’re not writing million-line deep-computer-science enterprise-class applications with a projected twenty-five year active lifespan here[1].

Also, as I said before, I sort of like the “Performance” (timecode) programming model, where you can put arbitrary code in each block. And if you want the whole ‘performance’ to repeat, you just set the last step in the performance to be “RestartPerformance()”, and presto- it’s a loop.


[1] Some of us might do that sort of thing at our day jobs.This != that. :slight_smile:

Also, you could define each ‘PatternWithArguments’ structure to be a pointer to the function, and a void* pointer to a structure that’s different for each different pattern. E.g., rainbow might take just one argument, but juggle might take three. The PatternWithArgument in each case would be a function pointer to the pattern function, and a (void*) pointer to a parameter block for that particular pattern function. Each pattern function would then cast that pointer to a pointer to the right kind of function block and if you’re still following along then I don’t have to say any more and if it’s all seeming like an overcomplicated mess, you’re probably right about that, too.

My brain just broke. Have recorded the various demos and this conversation for further study.

@Mark_Kriegsman

(raising hand) “Mr. Kriegsman, may I be excused? My brain is full.”