mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-22 07:29:01 +00:00
ws2812: improve timings to be compatible with the WS2811
The WS2811 has a slightly slower data rate, but it is close enough that a single library can support both LEDs at the same time. In my testing, this package was already compatible with WS2811 LEDs before this change when running at 4-5V, but when the voltage dropped to 3V or so the LEDs started misbehaving. With these improved timings, the LEDs remained of the correct color even at very low voltages (although blue was starting to fade due to lack of voltage - that's not a software/protocol issue).
This commit is contained in:
committed by
Ron Evans
parent
cad03a7d4e
commit
7a2b1b8c90
+310
-12
@@ -16,18 +16,26 @@ func (d Device) writeByte16(c byte) {
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
|
||||
// Timings:
|
||||
// T0H: 4 - 6 cycles or 250.0ns - 375.0ns
|
||||
// T1H: 9 - 11 cycles or 562.5ns - 687.5ns
|
||||
// TLD: 8 - cycles or 500.0ns -
|
||||
// T0H: 6 - 8 cycles or 375.0ns - 500.0ns
|
||||
// T1H: 17 - 19 cycles or 1062.5ns - 1187.5ns
|
||||
// TLD: 19 - cycles or 1187.5ns -
|
||||
mask := interrupt.Disable()
|
||||
value := uint32(c) << 24
|
||||
device.AsmFull(`
|
||||
1: @ send_bit
|
||||
str {maskSet}, {portSet} @ [2] T0H and T0L start here
|
||||
nop
|
||||
nop
|
||||
lsls {value}, #1 @ [1]
|
||||
bcs.n 2f @ [1/3] skip_store
|
||||
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
|
||||
2: @ skip_store
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
@@ -38,6 +46,17 @@ func (d Device) writeByte16(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
subs {i}, #1 @ [1]
|
||||
bne.n 1b @ [1/3] send_bit
|
||||
`, map[string]interface{}{
|
||||
@@ -56,9 +75,9 @@ func (d Device) writeByte48(c byte) {
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
|
||||
// Timings:
|
||||
// T0H: 10 - 12 cycles or 208.3ns - 250.0ns
|
||||
// T1H: 27 - 29 cycles or 562.5ns - 604.2ns
|
||||
// TLD: 22 - cycles or 458.3ns -
|
||||
// T0H: 17 - 19 cycles or 354.2ns - 395.8ns
|
||||
// T1H: 51 - 53 cycles or 1062.5ns - 1104.2ns
|
||||
// TLD: 56 - cycles or 1166.7ns -
|
||||
mask := interrupt.Disable()
|
||||
value := uint32(c) << 24
|
||||
device.AsmFull(`
|
||||
@@ -70,10 +89,34 @@ func (d Device) writeByte48(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
lsls {value}, #1 @ [1]
|
||||
bcs.n 2f @ [1/3] skip_store
|
||||
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
|
||||
2: @ skip_store
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
@@ -110,6 +153,40 @@ func (d Device) writeByte48(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
subs {i}, #1 @ [1]
|
||||
bne.n 1b @ [1/3] send_bit
|
||||
`, map[string]interface{}{
|
||||
@@ -128,9 +205,9 @@ func (d Device) writeByte64(c byte) {
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
|
||||
// Timings:
|
||||
// T0H: 13 - 15 cycles or 203.1ns - 234.4ns
|
||||
// T1H: 36 - 38 cycles or 562.5ns - 593.8ns
|
||||
// TLD: 29 - cycles or 453.1ns -
|
||||
// T0H: 23 - 25 cycles or 359.4ns - 390.6ns
|
||||
// T1H: 68 - 70 cycles or 1062.5ns - 1093.8ns
|
||||
// TLD: 74 - cycles or 1156.2ns -
|
||||
mask := interrupt.Disable()
|
||||
value := uint32(c) << 24
|
||||
device.AsmFull(`
|
||||
@@ -145,10 +222,42 @@ func (d Device) writeByte64(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
lsls {value}, #1 @ [1]
|
||||
bcs.n 2f @ [1/3] skip_store
|
||||
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
|
||||
2: @ skip_store
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
@@ -198,6 +307,51 @@ func (d Device) writeByte64(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
subs {i}, #1 @ [1]
|
||||
bne.n 1b @ [1/3] send_bit
|
||||
`, map[string]interface{}{
|
||||
@@ -216,9 +370,9 @@ func (d Device) writeByte120(c byte) {
|
||||
portClear, maskClear := d.Pin.PortMaskClear()
|
||||
|
||||
// Timings:
|
||||
// T0H: 24 - 26 cycles or 200.0ns - 216.7ns
|
||||
// T1H: 66 - 68 cycles or 550.0ns - 566.7ns
|
||||
// TLD: 54 - cycles or 450.0ns -
|
||||
// T0H: 42 - 44 cycles or 350.0ns - 366.7ns
|
||||
// T1H: 126 - 128 cycles or 1050.0ns - 1066.7ns
|
||||
// TLD: 138 - cycles or 1150.0ns -
|
||||
mask := interrupt.Disable()
|
||||
value := uint32(c) << 24
|
||||
device.AsmFull(`
|
||||
@@ -244,10 +398,70 @@ func (d Device) writeByte120(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
lsls {value}, #1 @ [1]
|
||||
bcs.n 2f @ [1/3] skip_store
|
||||
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
|
||||
2: @ skip_store
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
@@ -341,6 +555,90 @@ func (d Device) writeByte120(c byte) {
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
subs {i}, #1 @ [1]
|
||||
bne.n 1b @ [1/3] send_bit
|
||||
`, map[string]interface{}{
|
||||
|
||||
Reference in New Issue
Block a user