From f2d84fa32137b727d62eb2f98e627d366b286c6c Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Thu, 24 Oct 2024 14:08:18 +0100 Subject: [PATCH] Plasma: Add support for GPIOs >=32. For both APA102 and WS2812 the pins used on the same PIO must be in the same range. The GPIO base offset applies to the whole PIO and not individual state machines. This means that for APA102 both data and clock must be in the same pin range, ie: either 16-48 inclusive or 0-31 inclusive. --- drivers/plasma/apa102.cpp | 20 ++++++++++++++++++-- drivers/plasma/ws2812.cpp | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/drivers/plasma/apa102.cpp b/drivers/plasma/apa102.cpp index 443a35ec3..87bdf3289 100644 --- a/drivers/plasma/apa102.cpp +++ b/drivers/plasma/apa102.cpp @@ -4,10 +4,26 @@ namespace plasma { APA102::APA102(uint num_leds, PIO pio, uint sm, uint pin_dat, uint pin_clk, uint freq, RGB* buffer) : buffer(buffer), num_leds(num_leds), pio(pio), sm(sm) { + // NOTE: This sets the gpio_base for *the entire PIO* not just this state machine + uint range_max = std::max(pin_dat, pin_clk); + uint range_min = std::min(pin_dat, pin_clk); + + // Both pins in 16-48 range + if(range_max >= 32 && range_min >= 16) { + pio_set_gpio_base(pio, 16); + // Both pins in 0-31 range + } else if(range_max <= 31) { + pio_set_gpio_base(pio, 0); + // Pins in different ranges: invalid combo! + } else { + // TODO: Need some means to notify the caller + pio_set_gpio_base(pio, 0); + } + pio_program_offset = pio_add_program(pio, &apa102_program); - pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_clk) | (1u << pin_dat)); - pio_sm_set_pindirs_with_mask(pio, sm, ~0u, (1u << pin_clk) | (1u << pin_dat)); + pio_sm_set_pins_with_mask(pio, sm, 0, (1u << (pin_clk - pio_get_gpio_base(pio))) | (1u << (pin_dat - pio_get_gpio_base(pio)))); + pio_sm_set_pindirs_with_mask(pio, sm, ~0u, (1u << (pin_clk - pio_get_gpio_base(pio))) | (1u << (pin_dat - pio_get_gpio_base(pio)))); pio_gpio_init(pio, pin_clk); pio_gpio_init(pio, pin_dat); diff --git a/drivers/plasma/ws2812.cpp b/drivers/plasma/ws2812.cpp index db6ae4b95..4da6d9329 100644 --- a/drivers/plasma/ws2812.cpp +++ b/drivers/plasma/ws2812.cpp @@ -4,6 +4,9 @@ namespace plasma { WS2812::WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq, bool rgbw, COLOR_ORDER color_order, RGB* buffer) : buffer(buffer), num_leds(num_leds), color_order(color_order), pio(pio), sm(sm) { + // NOTE: This sets the gpio_base for *the entire PIO* not just this state machine + pio_set_gpio_base(pio, pin >= 32 ? 16 : 0); + pio_program_offset = pio_add_program(pio, &ws2812_program); pio_gpio_init(pio, pin);