Add support for Cortex-M4 120MHz

This adjusts the timing for 120MHz as seen on atsamd51 boards. The
timing was kept as close as possible to the Cortex-M4 64MHz logic in
ws2812_m4_64m.go.

Tested: This works on ItsyBitsy-M4
This commit is contained in:
Jonathan Basseri
2019-12-04 00:38:38 -08:00
committed by Ayke
parent c62d7db35d
commit f822da51fe
+173
View File
@@ -0,0 +1,173 @@
// +build atsamd51
package ws2812
// This file implements the WS2812 protocol for 120MHz Cortex-M4
// microcontrollers.
// Note: This implementation does not work with tinygo 0.9.0 or older.
import (
"device/arm"
)
// Send a single byte using the WS2812 protocol.
func (d Device) WriteByte(c byte) error {
// For the Cortex-M4 at 120MHz
portSet, maskSet := d.Pin.PortMaskSet()
portClear, maskClear := d.Pin.PortMaskClear()
// See:
// https://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
// T0H: 32-34 cycles or 266.67ns - 283.33ns
// T0L: 101-103 cycles or 841.67ns - 858.33ns
// +: 133-137 cycles or 1108.33ns - 1141.67ns
// T1H: 73-75 cycles or 608.33ns - 625.00ns
// T1L: 58-60 cycles or 483.33ns - 500.00ns
// +: 131-135 cycles or 1091.67ns - 1125.00ns
// A branch is treated here as 1-3 cycles, because apparently it might get
// speculated. This is more of a guess than hard fact, because the only docs
// by ARM that state this are now considered superseded (by what?).
value := uint32(c) << 24
arm.AsmFull(`
send_bit:
str {maskSet}, {portSet} @ [2] T0H and T0L start here
lsls {value}, #1 @ [1]
nop @ [28]
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
bcs.n skip_store @ [1-3]
str {maskClear}, {portClear} @ [2] T0H -> T0L transition
skip_store:
nop @ [41]
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
str {maskClear}, {portClear} @ [2] T1H -> T1L transition
nop @ [54]
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 send_bit @ [1-3]
`, map[string]interface{}{
"value": value,
"i": 8,
"maskSet": maskSet,
"portSet": portSet,
"maskClear": maskClear,
"portClear": portClear,
})
return nil
}