diff --git a/libraries/plasma2040/apa102.cpp b/libraries/plasma2040/apa102.cpp index dec84c2f..7f877c5d 100644 --- a/libraries/plasma2040/apa102.cpp +++ b/libraries/plasma2040/apa102.cpp @@ -2,7 +2,7 @@ namespace plasma { -APA102::APA102(uint num_leds, PIO pio, uint sm, uint pin_dat, uint pin_clk, uint freq) : num_leds(num_leds), pio(pio), sm(sm) { +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) { uint offset = pio_add_program(pio, &apa102_program); pio_sm_set_pins_with_mask(pio, sm, 0, (1u << pin_clk) | (1u << pin_dat)); @@ -32,7 +32,9 @@ APA102::APA102(uint num_leds, PIO pio, uint sm, uint pin_dat, uint pin_clk, uint channel_config_set_read_increment(&config, true); dma_channel_configure(dma_channel, &config, &pio->txf[sm], NULL, 0, false); - buffer = new RGB[num_leds]; + if(this->buffer == nullptr) { + this->buffer = new RGB[num_leds]; + } } bool APA102::dma_timer_callback(struct repeating_timer *t) { diff --git a/libraries/plasma2040/apa102.hpp b/libraries/plasma2040/apa102.hpp index db60e234..b59e0536 100644 --- a/libraries/plasma2040/apa102.hpp +++ b/libraries/plasma2040/apa102.hpp @@ -54,7 +54,7 @@ namespace plasma { RGB *buffer; uint32_t num_leds; - APA102(uint num_leds, PIO pio, uint sm, uint pin_dat, uint pin_clk, uint freq=DEFAULT_SERIAL_FREQ); + APA102(uint num_leds, PIO pio, uint sm, uint pin_dat, uint pin_clk, uint freq=DEFAULT_SERIAL_FREQ, RGB* buffer=nullptr); ~APA102() { stop(); clear(); diff --git a/libraries/plasma2040/ws2812.cpp b/libraries/plasma2040/ws2812.cpp index fdf12099..73c69b9f 100644 --- a/libraries/plasma2040/ws2812.cpp +++ b/libraries/plasma2040/ws2812.cpp @@ -2,7 +2,7 @@ namespace plasma { -WS2812::WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq) : num_leds(num_leds), pio(pio), sm(sm) { +WS2812::WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq, RGB* buffer) : buffer(buffer), num_leds(num_leds), pio(pio), sm(sm) { uint offset = pio_add_program(pio, &ws2812_program); pio_gpio_init(pio, pin); @@ -31,7 +31,9 @@ WS2812::WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq) : num_leds( dma_channel_set_read_addr(dma_channel, (uint32_t *)buffer, false); dma_channel_configure(dma_channel, &config, &pio->txf[sm], NULL, 0, false); - buffer = new RGB[num_leds]; + if(!this->buffer) { + this->buffer = new RGB[num_leds]; + } } bool WS2812::dma_timer_callback(struct repeating_timer *t) { diff --git a/libraries/plasma2040/ws2812.hpp b/libraries/plasma2040/ws2812.hpp index 63485571..6c4c3bee 100644 --- a/libraries/plasma2040/ws2812.hpp +++ b/libraries/plasma2040/ws2812.hpp @@ -54,7 +54,7 @@ namespace plasma { RGB *buffer; uint32_t num_leds; - WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq=DEFAULT_SERIAL_FREQ); + WS2812(uint num_leds, PIO pio, uint sm, uint pin, uint freq=DEFAULT_SERIAL_FREQ, RGB* buffer=nullptr); ~WS2812() { stop(); clear(); diff --git a/micropython/modules/plasma_2040/plasma_2040.cpp b/micropython/modules/plasma_2040/plasma_2040.cpp index 20f7fe52..9c056840 100644 --- a/micropython/modules/plasma_2040/plasma_2040.cpp +++ b/micropython/modules/plasma_2040/plasma_2040.cpp @@ -27,6 +27,7 @@ const mp_obj_float_t const_float_1 = {{&mp_type_float}, 1.0f}; typedef struct _PlasmaWS2812_obj_t { mp_obj_base_t base; WS2812* ws2812; + void *buf; } _PlasmaWS2812_obj_t; @@ -58,7 +59,8 @@ mp_obj_t PlasmaWS2812_make_new(const mp_obj_type_t *type, size_t n_args, size_t ARG_pio, ARG_sm, ARG_dat, - ARG_freq + ARG_freq, + ARG_buffer }; static const mp_arg_t allowed_args[] = { { MP_QSTR_num_leds, MP_ARG_REQUIRED | MP_ARG_INT }, @@ -66,6 +68,7 @@ mp_obj_t PlasmaWS2812_make_new(const mp_obj_type_t *type, size_t n_args, size_t { MP_QSTR_sm, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_dat, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_freq, MP_ARG_INT, {.u_int = WS2812::DEFAULT_SERIAL_FREQ} }, + { MP_QSTR_buffer, MP_ARG_OBJ, {.u_obj = nullptr} }, }; // Parse args. @@ -78,10 +81,22 @@ mp_obj_t PlasmaWS2812_make_new(const mp_obj_type_t *type, size_t n_args, size_t int dat = args[ARG_dat].u_int; int freq = args[ARG_freq].u_int; + void *buffer = nullptr; + + if (args[ARG_buffer].u_obj) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_RW); + buffer = bufinfo.buf; + if(bufinfo.len < (size_t)(num_leds * 4)) { + mp_raise_ValueError("Supplied buffer is too small for LED count!"); + } + } + self = m_new_obj_with_finaliser(_PlasmaWS2812_obj_t); self->base.type = &PlasmaWS2812_type; + self->buf = buffer; - self->ws2812 = new WS2812(num_leds, pio, sm, dat, freq); + self->ws2812 = new WS2812(num_leds, pio, sm, dat, freq, (WS2812::RGB *)buffer); return MP_OBJ_FROM_PTR(self); } @@ -166,6 +181,7 @@ mp_obj_t PlasmaWS2812_set_hsv(size_t n_args, const mp_obj_t *pos_args, mp_map_t typedef struct _PlasmaAPA102_obj_t { mp_obj_base_t base; APA102* apa102; + void *buf; } _PlasmaAPA102_obj_t; @@ -198,7 +214,8 @@ mp_obj_t PlasmaAPA102_make_new(const mp_obj_type_t *type, size_t n_args, size_t ARG_sm, ARG_dat, ARG_clk, - ARG_freq + ARG_freq, + ARG_buffer }; static const mp_arg_t allowed_args[] = { { MP_QSTR_num_leds, MP_ARG_REQUIRED | MP_ARG_INT }, @@ -207,6 +224,7 @@ mp_obj_t PlasmaAPA102_make_new(const mp_obj_type_t *type, size_t n_args, size_t { MP_QSTR_dat, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_clk, MP_ARG_REQUIRED | MP_ARG_INT }, { MP_QSTR_freq, MP_ARG_INT, {.u_int = APA102::DEFAULT_SERIAL_FREQ} }, + { MP_QSTR_buffer, MP_ARG_OBJ, {.u_obj = nullptr} }, }; // Parse args. @@ -220,10 +238,22 @@ mp_obj_t PlasmaAPA102_make_new(const mp_obj_type_t *type, size_t n_args, size_t int clk = args[ARG_clk].u_int; int freq = args[ARG_freq].u_int; + void *buffer = nullptr; + + if (args[ARG_buffer].u_obj) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_RW); + buffer = bufinfo.buf; + if(bufinfo.len < (size_t)(num_leds * 4)) { + mp_raise_ValueError("Supplied buffer is too small for LED count!"); + } + } + self = m_new_obj_with_finaliser(_PlasmaAPA102_obj_t); self->base.type = &PlasmaAPA102_type; + self->buf = buffer; - self->apa102 = new APA102(num_leds, pio, sm, dat, clk, freq); + self->apa102 = new APA102(num_leds, pio, sm, dat, clk, freq, (APA102::RGB *)buffer); return MP_OBJ_FROM_PTR(self); }