mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-19 14:14:00 +00:00
ws2812: add support for ESP8266
This patch adds support for the ESP8266 chip by adding support for 80MHz operation. This should also work when the ESP32 is changed to 80MHz, but I didn't test it (as there is not currently a way to do that). Verified on a NodeMCU dev board with an ESP8266.
This commit is contained in:
committed by
Ron Evans
parent
a689aef543
commit
65f8299153
+117
-1
@@ -16,7 +16,7 @@ func (d Device) WriteByte(c byte) error {
|
|||||||
portClear, maskClear := d.Pin.PortMaskClear()
|
portClear, maskClear := d.Pin.PortMaskClear()
|
||||||
|
|
||||||
switch machine.CPUFrequency() {
|
switch machine.CPUFrequency() {
|
||||||
case 160e6:
|
case 160e6: // 160MHz
|
||||||
// See:
|
// See:
|
||||||
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
|
||||||
// Because I do not know the exact instruction timings, I'm going to
|
// Because I do not know the exact instruction timings, I'm going to
|
||||||
@@ -224,6 +224,122 @@ func (d Device) WriteByte(c byte) error {
|
|||||||
"portClear": uintptr(unsafe.Pointer(portClear)),
|
"portClear": uintptr(unsafe.Pointer(portClear)),
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
|
case 80e6: // 80MHz
|
||||||
|
// See docs for 160MHz.
|
||||||
|
// T0H: 21 cycles or 262.5ns
|
||||||
|
// T0L: 67 cycles or 837.5ns
|
||||||
|
// +: 88 cycles or 1100.0ns
|
||||||
|
// T1H: 47 cycles or 587.5ns
|
||||||
|
// T1L: 39 cycles or 487.5ns
|
||||||
|
// +: 86 cycles or 1075.0ns
|
||||||
|
device.AsmFull(`
|
||||||
|
1: // send_bit
|
||||||
|
s32i {maskSet}, {portSet}, 0 // [1] T0H and T1H start here
|
||||||
|
nop // [18]
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
nop
|
||||||
|
slli {value}, {value}, 1 // [1] shift {value} to the left by 1
|
||||||
|
bbsi {value}, 8, 2f // [1] branch to skip_store if bit 8 is set
|
||||||
|
s32i {maskClear}, {portClear}, 0 // [1] T0H -> T0L transition
|
||||||
|
2: // skip_store
|
||||||
|
nop // [27]
|
||||||
|
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
|
||||||
|
s32i {maskClear}, {portClear}, 0 // [1] T1H -> T1L transition
|
||||||
|
nop // [36]
|
||||||
|
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
|
||||||
|
addi {i}, {i}, -1 // [1]
|
||||||
|
bnez {i}, 1b // [1] send_bit, T1H and T1L end here
|
||||||
|
|
||||||
|
// Restore original values after modifying them in the inline
|
||||||
|
// assembly. Not doing that would result in undefined behavior as
|
||||||
|
// the compiler doesn't know we're modifying these values.
|
||||||
|
movi.n {i}, 8
|
||||||
|
slli {value}, {value}, 8
|
||||||
|
`, map[string]interface{}{
|
||||||
|
// Note: casting pointers to uintptr here because of what might be
|
||||||
|
// an Xtensa backend bug with inline assembly.
|
||||||
|
"value": uint32(c),
|
||||||
|
"i": 8,
|
||||||
|
"maskSet": maskSet,
|
||||||
|
"portSet": uintptr(unsafe.Pointer(portSet)),
|
||||||
|
"maskClear": maskClear,
|
||||||
|
"portClear": uintptr(unsafe.Pointer(portClear)),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
default:
|
default:
|
||||||
return errUnknownClockSpeed
|
return errUnknownClockSpeed
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user