light_ws2812
Contribution description
Adding 3rd party lib reference of light_ws2812, and example that leverages it
Testing procedure
if you hook up a ws2811 or ws2812 LED array to the pin specified with the arguments
CFLAGS += -DLIGHT_WS2812_GPIO_PIN=7
CFLAGS += -DLIGHT_WS2812_GPIO_PORT=GPIOA
you should see a random pattern being played across them when you flash the included example.
I think this PKG could be integrated into the existing ws281x driver as an alternative backend. See https://api.riot-os.org/group__drivers__ws281x.html
I think this PKG could be integrated into the existing ws281x driver as an alternative backend. See https://api.riot-os.org/group__drivers__ws281x.html
@maribu to be clear, are you thinking keep the package, and also add a reference to it in the ws281x driver? or eliminate adding it as a standalone package and ONLY update the driver?
The current ws281x driver requires a you to select a backend (e.g. ws281x_atmega for an AVR ASM implementation). There are currently not many backends upstream yet, see e.g. https://forum.riot-os.org/t/about-how-to-interface-ws2812s-rgb-leds-with-nrf-based-board for some discussion about WIP backends. The benefit of that approach is that you can develop your RIOT application for board A, but later switch to board B for some unrelated reasons and still be able to use the same code unmodified. Even if you previously used e.g. the I2S peripheral to perform the bitbanging, or ATmega CPU cycle counting, or the SPI MOSI pin and later switch to the RP2040 PIO state machine and DMA for bitbanging.
If this package gets added as a backend, it would benefit from the existing test application and existing users could directly make use of it. If it is added with a different API, users will have a hard time switching between different modes of generating the ws281x signal.
That makes sense. So I think I will leave it in as a pkg, but then add the needful references to that package to the ws281x driver. That way if a developer wants to go as-slim-as-possible they can just use the package directly, or they can use the driver as you detailed. Does that sound good?
@maribu please see the most recent commit. I verified it builds via the following operation:
cd tests/driver_ws281x
CFLAGS="-DLIGHT_WS2812_UC_STM32G0XX -DLIGHT_WS2812_GPIO_PIN=7 -DLIGHT_WS2812_GPIO_PORT=GPIOA -DCONFIG_USE_CLOCK_HSI=1" make BOARD=nucleo-g070rb
Cool. GitHub swallowed my comment regarding the features required :frowning_face:
My point was that the package has some requirements, namely:
ws2812_port_setandws2812_port_clrneeds to be defined for the MCU family used- The CPU architecture has to be ARM Cortex-M (or AVR, but that would require some work on the package that IMO could still be done later on, if somebody wants to use
light_ws2812on AVR) - The timing behavior of the CPU needs to match the assumptions the inline assembly is making
Some background regarding the timing behavior: The AVR backend that I implemented uses CPU cycle counting in very much the same way the light_ws2812 package does. I tried the same on my STM32F767ZI MCU (but rather using a delay loop than nops) and figured out that the CPU occasionally took 1 CPU cycle for each two-instruction loop iteration, but sometimes a dozen cycles or so. The CPU has a dual-issue feature that allows it to perform two CPU instructions in a single CPU cycle under some conditions, and a long pipeline that needs to be flushed on unexpected branches. So while the dynamic branch predictor incorrectly predicted the branch as not being taken, the two instruction loop took ages per iteration. But once the predictor got it right, it went down to a single cycle. Even though the delay code in light_ws2812 doesn't use a delay loop, I'm still almost certain that the dual-issue feature can run two nops in a single CPU cycle and that whether or not the instruction cache is hot will have a huge impact on the timing. So, I would be extremely surprised if the package would work with any Cortex-M7 CPU.
My suggestion is to introduce a new feature, e.g. named light_ws2812, that will be provided by the Cortex-M MCU families that match the timing assumptions and for which ws2812_port_set and ws2812_port_clr are defined.
This seems to need rebase now. Please ping me, when I should take another look.
@david-vankampen ping :)