From 259593e6082b9d949d7cd4b971e0145f100a7fd1 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Mon, 23 Aug 2021 23:59:22 +0200 Subject: [PATCH] ws2812: add support for 168MHz (e.g. Adafruit Feather STM32F405) --- ws2812/gen-ws2812-arm.go | 2 +- ws2812/ws2812-asm_cortexm.go | 394 +++++++++++++++++++++++++++++++++++ ws2812/ws2812_cortexm.go | 3 + 3 files changed, 398 insertions(+), 1 deletion(-) diff --git a/ws2812/gen-ws2812-arm.go b/ws2812/gen-ws2812-arm.go index 8f9b14e..9c5abf1 100644 --- a/ws2812/gen-ws2812-arm.go +++ b/ws2812/gen-ws2812-arm.go @@ -35,7 +35,7 @@ import ( // from wp.josh.com seem to be fine for the ws2812. // Clock frequencies to support, in MHz. -var clockFrequencies = []int{16, 48, 64, 120} +var clockFrequencies = []int{16, 48, 64, 120, 168} func writeImplementation(f *os.File, megahertz int) error { cycleTimeNS := 1 / float64(megahertz) diff --git a/ws2812/ws2812-asm_cortexm.go b/ws2812/ws2812-asm_cortexm.go index de32ee9..fe36f60 100644 --- a/ws2812/ws2812-asm_cortexm.go +++ b/ws2812/ws2812-asm_cortexm.go @@ -651,3 +651,397 @@ func (d Device) writeByte120(c byte) { }) interrupt.Restore(mask) } + +func (d Device) writeByte168(c byte) { + portSet, maskSet := d.Pin.PortMaskSet() + portClear, maskClear := d.Pin.PortMaskClear() + + // Timings: + // T0H: 59 - 61 cycles or 351.2ns - 363.1ns + // T1H: 177 - 179 cycles or 1053.6ns - 1065.5ns + // TLD: 194 - cycles or 1154.8ns - + mask := interrupt.Disable() + value := uint32(c) << 24 + device.AsmFull(` + 1: @ send_bit + str {maskSet}, {portSet} @ [2] T0H and T0L start here + 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 + 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 + 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 + str {maskClear}, {portClear} @ [2] T1H -> T1L transition + 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 + 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 + 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{}{ + "value": value, + "i": 8, + "maskSet": maskSet, + "portSet": portSet, + "maskClear": maskClear, + "portClear": portClear, + }) + interrupt.Restore(mask) +} diff --git a/ws2812/ws2812_cortexm.go b/ws2812/ws2812_cortexm.go index 3e7e2d9..fb153b9 100644 --- a/ws2812/ws2812_cortexm.go +++ b/ws2812/ws2812_cortexm.go @@ -29,6 +29,9 @@ func (d Device) WriteByte(c byte) error { case 120_000_000: // 120MHz d.writeByte120(c) return nil + case 168_000_000: // 168MHz, e.g. stm32f405 + d.writeByte168(c) + return nil default: return errUnknownClockSpeed }