Old Skool Marquees I've been thinking about implementing some traditional style "marquee" lighting and

Old Skool Marquees

I’ve been thinking about implementing some traditional style “marquee” lighting and i’m wondering how best to store the bit mapping.

I want to be able to call the bit mapping (which led is on, when) and apply the colour over the top.

So a simple chase:

X 0 0 0
0 X 0 0
0 0 X 0
0 0 0 X
repeat

could be shown in any hue.

i’ve been stuffing bits like this:

sequence[32] = { {B000010000,B00000100,B000000010,B00000001,B000010000,B00000100,B000000010,B00000001}, // light chase
{B00000001,B00000010,B00000100,B00001000,B00000001,B00000010,B00000100,B00001000}, // light chase back

// etc etc…
}

but it gets ugly real quick.

I’ve tried this a few ways now, but none of them feel elegant (lots of loops, or that mess above etc), so i thought i’d throw it out here.

I’ve attached an image showing the sorts of bitmaps i want to use.

Any ideas?

note: i used to implement this on 4 channel “sequencers” i built back in the day, that stored the sequence in an EPROM, and it was a simple matter of incrementing the address on each clock, and 4 (or more) data lines would carry the pattern, hence my interest in trying this in software.

I’d define a palette with your pattern and just use fill_palette. Worth a glance, anyway!

yeah, it was your xmas twinkles example that you posted, where its using palettes, that gave me the idea of reworking the old marquees in the first place :wink:

How would i overlay the colour data though, doesn’t the palette imply the hue?

[edit: piss poor grammar - need more coffee]

Yes, palette implies hue. Exactly right.

So what I’d do is have a routine that takes a pattern, and two colors, as arguments, and makes a palette with that pattern in those colors.

Internally, palettes are just an array of CRGB’s, so you can just store values in them. I think the basic palette example code shows how to programmatically generate a palette.

you mean via currentPalette[i] ?

e.g

void SetupBlackAndWhiteStripedPalette()
{
// ‘black out’ all 16 palette entries…
fill_solid( currentPalette, 16, CRGB::Black);
// and set every fourth one to white.
currentPalette[0] = CRGB::White;
currentPalette[4] = CRGB::White;
currentPalette[8] = CRGB::White;
currentPalette[12] = CRGB::White;

}

Yep- like that!

@Stuart_Taylor , if you get something working I’d be interested to see how you tweaked things. I messed with the palette code some but wasn’t getting it to marquee. Didn’t get to trying the color tint part.

This is way cool. This what I’ve been thinking about as well. I thought I’d try to insert some of Andrew Tulane’s (sp?) code samples and call up the different routines after some time passes. I like this idea much better as I can create my own patterns! Thank you for your idea. Keep posting.

So, last night (I’m in the UK) I used the snippet above as a starting point, and lit every Nth led. The palette code scrolls this for you. Nice and easy.

Where I got to was wanting to light every Nth, Nth + 2, or Nth + Mth

A question for @Mark_Kriegsman ​​, where would I look to change the palette16 into a palette8? 16 sequence ‘steps’ can contain a lot of duplication.

The beauty of using palette, is it allows you to define “off” as CRGB::Black (or CRGB::Gray) and “on” as CRGB::White (or what ever colour you want). So as you create the palette, you write it out as:

on, off, off, on, off, off, on… etc etc

Which allows you the affordance to visualise the sequence in prose.

The BLEND and NOBLEND attributes make for some interesting “smearing”.

I want to experiment with more patterns, and changing colour, then I’ll post a video and gist.

I’m will complete the bitmap version, just so I can compare RAM usage and the readability and maintainability of the two implementations.

If for sure the code will be smaller if you leave out the palettes and write it by hand special for this application! I was just suggesting palettes because they’re already written!
And I wouldn’t try changing them to palette8; just use them as palette16 and fill them with repeats (or expansions) of your bit pattern.
Also, you only need one palette in SRAM, which you programmatically re-fill with new patterns every time. Total cost in memory should be 48 bytes SRAM (one palette), plus however many (16?) bit animation patterns, which presumably you’ll code in binary. So for example the pattern
O . . .
. O . .
. . O .
. . . O
would be coded as 0x08, 0x04, 0x02, 0x01, and stored in flash/PROGMEM as a total of just four bytes.

But really, use of palettes was just a convenient move. You can happily code this without them if you prefer to dig in and do so!

… or two bytes: 0x84, 0x21 !

But the code to decode the two byte version is probably several bytes longer than the four-byte version… ah programming.

hi @Mark_Kriegsman i’ve finally had time to upload this today, and the behaviour when using palettes wasn’t what i expected. Except once i thought about the palette demo, what i was seeing was a black swan.

i.e, if i set-up a palette with just one position of the 16 set to white, and the rest set to black, i would get 6 leds lit at any one time. This obviously affects the look of marquee.

I know it has to do with FillLEDsFromPaletteColors()

and within there

colorIndex += 3

If i mess with that i can get a single led lit, crawling the string (however the refresh is awful), but this is tied to

static uint8_t startIndex = 0;
startIndex = startIndex + 1; /* motion speed */

and this begins to make less sense.

How is this connected?

playing with this some more. I see that sometimes a single colour of a palette can be 5 or 6 pixels wide (for a say a 50 led strip, or even a strip that is a multiple of 16).
I guess for me to get old skool marquees working this way, a single colour in a given palette would need to be one pixel wide.

You can totally adjust how you want the palette mapped to pixels.

Where should I be looking? I don’t see it.

Sorry- that was like my least helpful comment of the year so far. That’s what I get for trying to make dinner and help code at the same time. I’ll post some more details this evening.

Lol, no its fine, I took the SO to see 50 shades, and I’m in no state to code after that 0.o

OK, so here’s the key, I think: when you stuff values INTO a CRGBPalette16 palette, you use pal[0]… pal[1]… pal[15]. A CRGBPalette16 actually physically has 16 slots, numbered internally 0…15. (I suspect you already are on top of this part).

BUT when you want to retrieve values OUT of the palette, using ColorFromPalette, the index values that correspond to the sixteen actual palette entries are NOT 0…15. Instead, they are 0, 16, 32, 64, …240. This is because ColorFromPalette takes an index in the range 0…255 (and does interpolation AS IF there really were 256 palette entries, even though there are only really 16).

So, lets consider the library routine fill_palette.

void fill_palette(
CRGB* L, uint16_t N, uint8_t startIndex, uint8_t incIndex,
const PALETTE& pal, uint8_t brightness, TBlendType blendType);

Normally, you’d call it something like this

static uint8_t startIndex = 0;
startIndex += 1;

uint8_t incIndex = 3;

fill_palette(
leds, NUM_LEDS, startIndex, incIndex,
myPalette, 255, BLEND);

Note that an index increment (incIndex) of three is used here. Let’s assume that this is the first pass, and that startIndex = 0. This means that:
the first pixel will be filled with whatever is in ColorFromPalette(myPal, 0…),
the second pixel will be filled with ColorFromPalette(myPal, 3…)
the third pixel will be filled with ColorFromPalette(myPal, 6…)
the fourth pixel will be filled with ColorFromPalette(myPal, 9…)
and so on. The ‘index’ (0…255) is going up by three for each pixel.

But remember: there aren’t 256 palette entries. There are really only 16, spread out across the range, and everything in between is interpolated.

So if you want to map EXACT palette entries onto individual LEDs, then “incIndex” needs to be exactly 16 (and startIndex might want to be a multiple of 16… but you can play with that and see if you like the effects).

SO. So this means, use fill_palette like this:
fill_palette( leds, NUM_LEDS, startIndex, 16, myPal, 255, BLEND);
That “16” there is important – it’ll keep the colors on the LEDs lined up with colors in the palette.

Play around with it a bit more, with “incIndex” set to 16, and see what you get, and if it starts to make more sense. Either way, let us know!

Hi @Mark_Kriegsman thank you for the very detail explanation. Because i was using a blendtype of NOBLEND i hadn’t considered how you would be achieving that, and the 0-255 positions of the palette is now glaringly obvious! very neat.

I had found this

https://gist.github.com/kriegsman/981cc6f501d30dfd82a7/revisions

and picked up on the changes and saw the helpful

/* higher = narrower stripes */

comment - who says comments are bad :wink:

So i was already working towards your suggestions, just very small iterations :slight_smile:

what did throw me for a while was

static uint8_t startIndex = 0;
startIndex = startIndex + 2; /* higher = faster motion */

i read it as, every-time through the loop. startIndex = 0, then we add 2 to it. therefore every-time through the loop, startIndex == 2, but of course for some reason i missed the static, and its preserved, so that threw me down a rabbit hole for a bit (one of those times where you begin to think its magic aka undocumented feature)

I’m still playing, but home to have something finished soon.