There's no hardware documentation as such, but the Blinkt! is just a chain of 8 APA102 LED pixels, albeit ones with a particularly quirky implementation of the protocol, which can be driven by just toggling a couple of GPIO pins (data and clock).
It would be easy to, for example, create a C library you could bind into. I started with C for Blinkt!, intending to bind against it with Python, until I realized that it was simply overkill for most uses.
Anyway. The Blinkt! protocol is relatively straight forward. It's just like driving a shift register, toggling the clock line and setting data bits in turn.
It comprises 8 APA102 pixels, the protocol of which is explored here: https://cpldcpu.com/2014/08/27/apa102/
The data line is connected to BCM
23 and the clock line to BCM
The pixels are 24bits, 8bits per colour and include an 8bit "start frame" that has a 5bit brightness value for a total of 32bits per pixel:
start blue green red
111 00000 00000000 00000000 00000000
5-bit brightness value
All of the important stuff happens here: https://github.com/pimoroni/blinkt/blob/master/library/blinkt.py#L62-L79
Here's that chunk with just the interesting bits of code:
"""Output the buffer to Blinkt!"""
for pixel in pixels:
r, g, b, brightness = pixel
_write_byte(0b11100000 | brightness)
For each pixel, you need to clock out the pixel start frame which is
0b11100000 plus a brightness value from 0 to 31.
Then the b, g and r values are clocked out in the same way.
_write_byte() does simply that, it outputs each bit of a byte to the data line and pulses the clock: https://github.com/pimoroni/blinkt/blob/master/library/blinkt.py#L41-L46
It does this by clocking out the most significant bit of the byte and shifting that byte left once for each bit.
for x in range(8):
GPIO.output(DAT, byte & 0b10000000)
byte <<= 1
_eof() stand for Start Of Frame and End Of Frame, these are the data bits that reset and latch the APA102 pixels: https://github.com/pimoroni/blinkt/blob/master/library/blinkt.py#L50-L60
for x in range(36):
for x in range(32):
In this case, they're just setting the data line and pulsing the clock.
_eof() pulses the clock 36 times, clocking out 36 zeros.
_sof() pulses the clock 32 times, clocking out 32 zeros.
So to summarize, in order to drive Blintk! you should:
- Clock out 36 zeros
- Clock out 8 pixels, for each pixel:
- Clock out start frame with brightness from 0 to 31:
0b11100000 | brightness
- Bytes are clocked out most-significant-bit (the left-most bit) first
- Clock out blue byte
- Clock out red byte
- Clock out green byte
- Clock out 32 zeros