Code Design overview - sonyhome/FAB_LED GitHub Wiki
- The library provides predefined pixel types to support all the native byte orders, rgb, grb, rgbw, etc.
- The library consists of one main class with template constants, which implements all the code.
- The constants define properties of the LEDs such as timings, byte order etc.
- The main API routine is sendPixels with heavy polymorphism, used to support all the different ways of representing pixels, from the different pixel types, to raw 24bit and 32bit types, to compact 16bit type (r5g6b5), to palette types (1bit, 2bit, 4bit and 8bit). Note that if you use a pixel type with a LED strip protocol that uses a different type, the display will be correct as the method will convert the pixel, but it will be slower. For example you can send an rgbw pixel to a WS2812B LED strip that expects a grb pixel, it will be converted. This is not the case with raw types.
- The main class is instantiated into the different LED protocol types.
Unlike many other LED libraries, the classes are not pixel classes. They do not store any data. They are protocol classes, i.e. they define how you send the pixels to the LED strips.
To send pixels, a programmer...
- declares a LED protocol variable associated to a port via a template declaration
ws2812b<D,6> myLeds; // WS2812B LEDs on port D6
- declares a pixel array using one of the predefined types (rgb, grb, rgbw, etc.) or a native type uint8_t, uint32_t, etc.
grb myPixels[32] = {}; // Declare an array of 32 pixels
or
uint8_t myPixels[32*3] = {} // Declare a raw array of 32 pixels
- updates the pixels in the array to any desired pattern
myPixels[i].r = i; myPixels[i].r = 255-i; myPixels[i].b = 0;
- writes the pixels out to the LED strip
myLeds.sendPixels(32, myPixels);
That's it.
Now this paradigm is more powerful than embedding the pixel buffer in the class:
- It allows you to define very compact arrays with compact types
- use palettes for effects
- send multiple arrays in a row to the same LED strip (you must disable/restore interrupts),
- define multiple protocols on the same port to push an array on a port where multiple LED strips with different protocols have been soldered together,
- push the same array on multiple strips on different ports which can have the same or a different protocol, as pixels are converted to display correctly.
In general a basic LED protocol will be available you can instantiate, for example ws2812b or sk6812.
However you may have a special use case where you want to configure yourself the hardware parameters of the LED strip. If you look at example F, you will notice a custom type is declared:
template<avrLedStripPort dataPortId, uint8_t dataPortBit>
class custom : public avrBitbangLedStrip<
6, // 1 high, CPU cycles
2, // 1 low
2, // 0 high
2, // 0 low
50, // refresh msec
dataPortId, // data port
dataPortBit,
A,
0,
GRB, // byte order for each pixel
ONE_PORT_BITBANG> // protocol
{
public:
custom() : avrBitbangLedStrip<6,2,2,2,50,dataPortId,dataPortBit,A,0,GRB,ONE_PORT_BITBANG>() {};
~custom() {};
};
All you need to do is specialize the template for your needs:
- Set the 4 bitbanging durations (you can use CYCLES(ns) macro to compute cycles from nanoseconds from a spec sheet)
- set the refresh aka time to cause a led strip reset
- the port ID (letter) and bit offset (0 to 7) for the data, and if you use SPI, the clock.
- the pixel color order
- the method to push the pixels. Different methods will use differently the other parameters. For example the EIGHT_PORT_BITBANG uses the port ID (letter) and uses two port bit offsets to specify a range of pins used.
Once you declare your class, create a variable with it, and use it.
Be careful, C++ requires you pass the same fields twice. They must match!
class custom :: public avrBitbangLedStrip<a,b,c,d...>
{
...
custom() : avrBitbangLedStrip<a,b,c,d...>
...
}