I have a bit of a problem:

I have a bit of a problem: I want to use an attiny167 to drive about 120 pixels but I only have enough SRAM for 60-70. I figured I’d try to output a 60 pixel buffer twice – but I’m not sure about the easiest way to do this.

I basically want to change CLEDController to accept the length of the CRGB buffer and the number of pixels to output as two separate parameters. If number of pixels to output > pixel buffer size then I simply want to reset the pointer into the pixel buffer every time we reach the end.

I started digging around showRGBInternal for the clockless controller but it’s a bit over my head. I’ll play around with it a bit but if anyone can help it would be greatly appreciated!

Thanks

Why not split the pixels into two strips and put them on separate pins (and then give the two addLeds calls the same led array)? The asm code for avr output is pretty dense, and there’s no more registers slots available to track count vs size of the buffer.

This is for a jacket that already has the LEDs in it, it’ll be a challenge to wire it that way. If I wire it that way I can even have both strips on the same pin. Unfortunately I don’t think it’ll be possible for this project :confused:

Would disabling dithering (or any other hack) free up those registers?

It might - but it took a lot to get all the timing and such working right in there, and I’m not sure how ugly the changes would be to make it do what you want.

And you’re hard locked to the attiny167?

(But hey, at least it isn’t a pic12 :slight_smile:

This specific controller has a custom PCB with the tiny167 and a plastic enclosure from http://polycase.com, so no flexibility there. I’ve used an off the shelf arduino mini or micro in the jacket before, so thats what I’ll end up using.

I was hoping to use the custom controller since it is tailor made for wearables with LEDs: on/off switch, rotary encoder for brightness and changing modes, etc.

Naively I thought 512 bytes of SRAM would be enough for 120 pixels but I didn’t take into account overhead of arduino / fastled / call stack / globals / rotary encoder state. If I am super aggressive with my code I can get 100 pixels going at the expense of some of the nicer animations, so I still prefer somehow outputting 60 pixels twice.

Here’s an idea… in clockless_trinket.h on FastLED3.1 (latest pull) - change line 133 to read:

showRGBInternal(pixels);
#if defined(FASTLED_DOUBLE_OUTPUT)
showRGBInternal(pixels);
nLeds *= 2; // so that the clock adjustment happens correctly
#endif

and then, before you include FastLED.h put:

#define FASTLED_DOUBLE_OUTPUT 1
#include <FastLED.h>

and then, when you do the addLeds, just do it for your 60 pixels.

Thanks, I’ll try that now

My hope is that it can cycle out and back into that function quickly enough to not trigger the 2812’s reset/latching.

So, did it work, it’s been a whole 10 minutes! :slight_smile:

It’s only outputting the buffer once. Maybe I need to reset something in PixelController?

Heh, I wish :slight_smile:

Ok - simplify the code in clockless_trinket.h - just make it:

showRGBInternal(pixels);
showRGBInternal(pixels);
nLeds *= 2;

if that doesn’t work, you can (more drastically) try this:

void showAdjTime(const uint8_t *data, int nLeds, CRGB & scale, bool advance, int skip) {
	PixelController<RGB_ORDER> pixels(data, nLeds, scale, getDither(), advance, skip);

PixelController<RGB_ORDER> pixels2(data, nLeds, scale, getDither(), advance, skip);

	mWait.wait();
	cli();

	showRGBInternal(pixels);

showRGBInternal(pixels2);
nLeds *= 2;

Still no bueno. I played with it a bit and it seems the second showRGBInternal overwrites the first instead of continuing it

(Also for the pixels2 version)

Also, it is possible that the gap between writing out the last pixel of the first showRGBInternal call and the start of writing out the first pixel of the second showRGBInternal call is long enough that the 2812’s are latching, and so it is effectively just re-writing the first 60 leds a second time.

In fact, this may be exactly what is happening. Are you running at 8 or 16Mhz?

I’ve realized that you only have a window of between 5-10µs between the end of one led and the start of another, that’s only 40-80 clock cycles (80-160 if running at 16Mhz). Because the attiny167 doesn’t have a hardware multiply, we have to do an unrolled multiplication for the scaling - and that’s 41 cycles just on its own, that doesn’t include any of the other work that happens at the beginning of showRGBInternal.

I’m running at 16Mhz

Try this - https://gist.github.com/focalintent/f2225596fd6e1c58e027

I’m getting len * 2 pixels lit up white and the first pixel flickering. I also have a new appreciation for the work you & mark put in. You weren’t kidding about that dense asm :wink:

(note that it will need the #define FASTLED_DOUBLE_OUTPUT before you do the #include “FastLED.h” to enable writing the output twice)

ok - that means the changes to add the extra loop inside of showRGBInternal are fucking with the asm enough that it’s killing the timing for writing data out - times like this I want to set gcc on fire.