mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-07-26 10:38:41 +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()
|
||||
|
||||
switch machine.CPUFrequency() {
|
||||
case 160e6:
|
||||
case 160e6: // 160MHz
|
||||
// See:
|
||||
// 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
|
||||
@@ -224,6 +224,122 @@ func (d Device) WriteByte(c byte) error {
|
||||
"portClear": uintptr(unsafe.Pointer(portClear)),
|
||||
})
|
||||
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:
|
||||
return errUnknownClockSpeed
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user