Newer
Older
Fadecandy is firmware for the [Teensy 3.0](http://www.pjrc.com/store/teensy3.html), a tiny and inexpensive ARM microcontroller board.
Fadecandy drives addressable LED strips with the WS2811 and WS2812 controllers. These LED strips are common and inexpensive, available from [many suppliers](http://www.aliexpress.com/item/5M-WS2811-LED-digital-strip-60leds-m-with-60pcs-WS2811-built-in-tthe-5050-smd-rgb/635563383.html?tracelog=back_to_detail_a) for around $0.25 per pixel.
This firmware is based on Stoffregen's excellent [OctoWS2811](http://www.pjrc.com/teensy/td_libs_OctoWS2811.html) library, which pumps out serial data for these LED strips entirely using DMA. This firmware builds on Paul's work by adding:
* A high performance USB protocol
* Zero copy architecture with triple-buffering
* Interpolation between keyframes
* Gamma and color correction with per-channel 256-entry lookup tables
* Temporal dithering
These features add up to give *very smooth* fades and high dynamic range. Ever notice that annoying stair-stepping effect when fading LEDs from off to dim? Fadecandy avoids that using a form of [delta-sigma modulation](http://en.wikipedia.org/wiki/Delta-sigma_modulation). It rapidly wiggles each pixel's value up or down by one 8-bit step, in order to achieve 16-bit resolution for fades.
* 512 pixels supported per Teensy board (8 strings, 64 pixels per string)
* Constant hardware frame rate of 520 FPS, to support temporal dithering
* Full-speed (12 Mbps) USB
Prerequisites
-------------
* The recommended ARM toolchain, from <https://code.launchpad.net/gcc-arm-embedded>
* The Teensy Loader: <http://www.pjrc.com/teensy/loader.html>
Pin Assignment
--------------
The pin assignment is the same as the original [OctoWS2811](http://www.pjrc.com/teensy/td_libs_OctoWS2811.html) pinout:
Teensy 3.0 Pin | Function
-------------- | --------------
2 | Led strip #1
14 | Led strip #2
7 | Led strip #3
8 | Led strip #4
6 | Led strip #5
20 | Led strip #6
21 | Led strip #7
5 | Led strip #8
15 & 16 | Connect together
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
Color Processing
----------------
The Fadecandy firmware maintains a color lookup table with 256 8-bit entries for each of the three color channels. The input values to this LUT are the 8-bit colorspace as used in the framebuffer's 24-bit pixel values. The outputs are a 48-bit color which acts as the input for Fadecandy's dithering algorithm.
Why 48-bit color? In combination with our dithering algorithm, this gives a lot more color resolution, especially near the low end of the brightness range where stair-stepping and color shift can be most apparent.
Each pixel goes through the following processing steps in Fadecandy:
* 8 bit per channel framebuffer values are expanded to 16 bits per channel
* We interpolate smoothly from the old framebuffer values to the new framebuffer values
* This interpolated 16-bit value goes through the color LUT, which itself is linearly interpolated
* The final 16-bit value is fed into our temporal dithering algorithm, which results in an 8-bit color
* These 8-bit colors are converted to the format needed by OctoWS2811's DMA engine
* In hardware, the converted colors are streamed out to eight LED strings in parallel
USB Protocol
------------
To achieve the best CPU efficiency, Fadecandy uses a custom packet-oriented USB protocol rather than emulating a USB serial device. This simple USB protocol is easy to speak using cross-platform libraries like [libusb](http://www.libusb.org) and [PyUSB](http://pyusb.sourceforge.net/). Examples are included. If you use the included [Open Pixel Control](http://openpixelcontrol.org/) bridge, you need not worry about the USB protocol at all.
Attribute | Value
--------------- | -----
Vendor ID | 0x1d50
Product ID | 0x607a
Manufacturer | "scanlime"
Product | "Fadecandy"
Serial | Unique for each Teensy 3.0 board
Device Class | Vendor-specific
Configurations | 1
Endpoints | 1
Endpoint 1 | Bulk OUT (Host to Device), 64-byte packets
The device has a single Bulk OUT endpoint which expects packets of up to 64 bytes. Multiple packets may be transmitted in one LibUSB "write" operation, as long as the buffer you provide is a multiple of 64 bytes in length.
Each packet begins with an 8-bit control byte, which is divided into three bit-fields:
Bits 7..6 | Bit 5 | Bits 4..0
---------- | ----------- | ------------
Type code | 'Final' bit | Packet index
* The 'type' code indicates what kind of packet this is.
* The 'final' bit, if set, causes the most recent group of packets to take effect
* The packet index is used to sequence packets within a particular type code
The following packet types are recognized:
Type code | Meaning of 'final' bit | Index range | Packet contents
--------- | ------------------------------- | ----------- | -------------------------------------
0 | Interpolate to new video frame | 0 … 24 | Up to 21 pixels, 24-bit RGB
1 | Instantly apply new color LUT | 0 … 24 | Up to 31 16-bit lookup table entries
2 | | | (reserved)
3 | | | (reserved)
In a type 0 packet, the USB packet contains up to 21 pixels of 24-bit RGB color data. The last packet (index 24) only needs to contain 8 valid pixels. Pixels 9-20 in these packets are ignored.
Byte Offset | Description
------------- | ------------
0 | Control byte
1 | Pixel 0, Red
2 | Pixel 0, Green
3 | Pixel 0, Blue
4 | Pixel 1, Red
5 | Pixel 1, Green
6 | Pixel 1, Blue
… | …
61 | Pixel 20, Red
62 | Pixel 20, Green
63 | Pixel 20, Blue
In a type 1 packet, the USB packet contains up to 31 lookup-table entries. The lookup table is structured as three arrays of 256 entries, starting with the entire red-channel LUT, then the green-channel LUT, then the blue-channel LUT. Each packet is structured as follows:
Byte Offset | Description
------------- | ------------
0 | Control byte
1 | Reserved (0)
2 | LUT entry #0, low byte
3 | LUT entry #0, high byte
4 | LUT entry #1, low byte
5 | LUT entry #1, high byte
… | …
62 | LUT entry #30, low byte
63 | LUT entry #30, high byte
Contact
-------
Micah Elizabeth Scott <<micah@scanlime.org>>