@@ -14,9 +14,51 @@ type WS2812 struct {
1414 offset uint8
1515}
1616
17- func NewWS2812 (sm pio.StateMachine , pin machine.Pin , baud uint32 ) (* WS2812 , error ) {
17+ func NewWS2812 (sm pio.StateMachine , pin machine.Pin ) (* WS2812 , error ) {
18+ // These timings are taken from the table "Updated simplified timing
19+ // constraints for NeoPixel strings" at:
20+ // https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
21+ // Here is a copy:
22+ // Symbol Parameter Min Typical Max Units
23+ // T0H 0 code, high voltage time 200 350 500 ns
24+ // T1H 1 code, high voltage time 550 700 5500 ns
25+ // TLD data, low voltage time 450 600 5000 ns
26+ // TLL latch, low voltage time 6000 ns
27+ // The equivalent table for WS2811 LEDs would be the following:
28+ // Symbol Parameter Min Typical Max Units
29+ // T0H 0 code, high voltage time 350 500 650 ns
30+ // T1H 1 code, high voltage time 1050 1200 5500 ns
31+ // TLD data, low voltage time 1150 1300 5000 ns
32+ // TLL latch, low voltage time 6000 ns
33+ // Combining the two (min and max) leads to the following table:
34+ // Symbol Parameter Min Typical Max Units
35+ // T0H 0 code, high voltage time 350 - 500 ns
36+ // T1H 1 code, high voltage time 1050 - 5500 ns
37+ // TLD data, low voltage time 1150 - 5000 ns
38+ // TLL latch, low voltage time 6000 ns
39+ // These comined timings are used so that the ws2812 package is compatible
40+ // with both WS2812 and with WS2811 chips.
41+ // T0H is the time the pin should be high to send a "0" bit.
42+ // T1H is the time the pin should be high to send a "1" bit.
43+ // TLD is the time the pin should be low between bits.
44+ // TLL is the time the pin should be low to apply (latch) the new colors.
45+ //
46+ // These constants are for the most part not used but serve as
47+ // a notebook of documentation. When in a IDE such as VSCode one
48+ // can mouse over constants to observe their value.
49+ const (
50+ t0h = 352 // augment it slightly to compensate for PIO clock instability.
51+ t0h_cycles = 3 // Taken from PIO program by observing instructions used.
52+ freq = 1_000_000_000 * t0h_cycles / t0h
53+ t1h_t0 = 1050. / t0h // =3
54+ tld_t0 = 1150. / t0h // ~3.8
55+ tll_t0 = 6000. / t0h // ~18
56+ t1h_cycles = t1h_t0 * t0h_cycles // =9
57+ tld_cycles = tld_t0 * t0h_cycles // ~9.8
58+ tll_cycles = tll_t0 * t0h_cycles // ~51.42
59+ )
1860 sm .TryClaim () // SM should be claimed beforehand, we just guarantee it's claimed.
19- whole , frac , err := pio .ClkDivFromFrequency (baud , machine .CPUFrequency ())
61+ whole , frac , err := pio .ClkDivFromFrequency (freq , machine .CPUFrequency ())
2062 if err != nil {
2163 return nil , err
2264 }
@@ -40,8 +82,9 @@ func NewWS2812(sm pio.StateMachine, pin machine.Pin, baud uint32) (*WS2812, erro
4082}
4183
4284func (ws * WS2812 ) SetRGB (r , g , b uint8 ) {
43- color := uint32 (r )<< 16 | uint32 (g )<< 8 | uint32 (b )
44- println ("r" , r , "g" , g , "b" , b )
85+ // Has little endian encoding over wire, last bits are most significant.
86+ // So green comes first, followed by red and lastly blue.
87+ color := uint32 (g ) | uint32 (r )<< 8 | uint32 (b )<< 16
4588 ws .sm .TxPut (color )
4689}
4790
0 commit comments