-
Notifications
You must be signed in to change notification settings - Fork 1
/
WS2812.hpp
72 lines (59 loc) · 2.06 KB
/
WS2812.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
#pragma once
#include "PulsedOutput.hpp"
#include <util/delay.h>
namespace AVR {
template <Ports port, u1 pin, bool StrictTiming = false, bool HandleInterrupts = true, unsigned ResetMicroseconds = 300,
bool InvertedOutput = false, bool LittleEndian = false>
class WS2812 : protected PulsedOutput<port, pin, 400, InvertedOutput, StrictTiming> {
using Parent = PulsedOutput<port, pin, 400, InvertedOutput, StrictTiming>;
using Parent::send;
protected:
/**
* @brief Shift an array of bytes out the specified pin using the WS2812 protocol.
*
* Does not include reset pulse.
*
* @param bytes the bytes to send
* @param length the number of bytes to send
*/
static void sendBytes(u1 const *const bytes, u2 length);
// naked, in our case, just removes the automatic "ret" which we do ourselves.
public:
using Parent::init;
struct RGB {
// This order matches the order of the WS2812 protocol
u1 g;
u1 r;
u1 b;
RGB() : g(0), r(0), b(0) {}
RGB(u1 w) : g(w), r(w), b(w) {}
RGB(u1 r, u1 g, u1 b) : g(g), r(r), b(b) {}
inline u1 const *data() const { return (u1 const *)this; }
inline operator u1 const *() const { return data(); }
static constexpr u1 size = sizeof(RGB);
};
struct RGBW {
// This order matches the order of the WS2812 protocol
u1 g;
u1 r;
u1 b;
u1 w;
RGBW() : g(0), r(0), b(0), w(0) {}
RGBW(u1 w) : g(0), r(0), b(0), w(w) {}
RGBW(u1 r, u1 g, u1 b, u1 w = 0) : g(g), r(r), b(b), w(w) {}
inline u1 const *data() const { return (u1 const *)this; }
inline operator u1 const *() const { return data(); }
static constexpr u1 size = sizeof(RGBW);
};
template <bool doLatchDelay = true>
inline static void setLEDs(RGB const *leds, u2 pixels) {
sendBytes(*leds, pixels * leds->size);
if (doLatchDelay) _delay_us(ResetMicroseconds);
}
template <bool doLatchDelay = true>
inline static void setLEDs(RGBW const *leds, u2 pixels) {
sendBytes(*leds, pixels * leds->size);
if (doLatchDelay) _delay_us(ResetMicroseconds);
}
};
}; // namespace AVR