Skip to content

Commit

Permalink
Plasma: Expose non-blocking update to MicroPython.
Browse files Browse the repository at this point in the history
  • Loading branch information
Gadgetoid committed Jan 22, 2025
1 parent a9a18c3 commit 0089e78
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 8 deletions.
10 changes: 7 additions & 3 deletions drivers/plasma/apa102.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,18 @@ bool APA102::dma_timer_callback(struct repeating_timer *t) {
return true;
}

bool APA102::is_busy() {
return dma_channel_is_busy(dma_channel);
}

void APA102::update(bool blocking) {
if(dma_channel_is_busy(dma_channel) && !blocking) return;
while(dma_channel_is_busy(dma_channel)) {}; // Block waiting for DMA finish
if(is_busy() && !blocking) return;
while(is_busy())) {}; // Block waiting for DMA finish
pio->txf[sm] = 0x00000000; // Output the APA102 start-of-frame bytes
dma_channel_set_trans_count(dma_channel, num_leds, false);
dma_channel_set_read_addr(dma_channel, buffer, true);
if (!blocking) return;
while(dma_channel_is_busy(dma_channel)) {}; // Block waiting for DMA finish
while(is_busy()) {}; // Block waiting for DMA finish
// This is necessary to prevent a single LED remaining lit when clearing and updating.
// This code will only run in *blocking* mode since it's assumed non-blocking will be continuously updating anyway.
// Yes this will slow down LED updates... don't use blocking mode unless you're clearing LEDs before shutdown,
Expand Down
1 change: 1 addition & 0 deletions drivers/plasma/apa102.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ namespace plasma {
bool start(uint fps=60);
bool stop();
void update(bool blocking=false);
bool is_busy();
void clear();
void set_hsv(uint32_t index, float h, float s, float v);
void set_rgb(uint32_t index, uint8_t r, uint8_t g, uint8_t b, bool gamma=true);
Expand Down
10 changes: 7 additions & 3 deletions drivers/plasma/ws2812.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,17 @@ bool WS2812::dma_timer_callback(struct repeating_timer *t) {
return true;
}

bool WS2812::is_busy() {
return dma_channel_is_busy(dma_channel);
}

void WS2812::update(bool blocking) {
if(dma_channel_is_busy(dma_channel) && !blocking) return;
while(dma_channel_is_busy(dma_channel)) {}; // Block waiting for DMA finish
if(is_busy() && !blocking) return;
while(is_busy()) {}; // Block waiting for DMA finish
dma_channel_set_trans_count(dma_channel, num_leds, false);
dma_channel_set_read_addr(dma_channel, buffer, true);
if (!blocking) return;
while(dma_channel_is_busy(dma_channel)) {}; // Block waiting for DMA finish
while(is_busy()) {}; // Block waiting for DMA finish
}

bool WS2812::start(uint fps) {
Expand Down
1 change: 1 addition & 0 deletions drivers/plasma/ws2812.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace plasma {
bool start(uint fps=60);
bool stop();
void update(bool blocking=false);
bool is_busy();
void clear();
void set_hsv(uint32_t index, float h, float s, float v, uint8_t w=0);
void set_rgb(uint32_t index, uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, bool gamma=true);
Expand Down
4 changes: 4 additions & 0 deletions micropython/modules/plasma/plasma.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(PlasmaAPA102_start_obj, 1, PlasmaAPA102_start);
MP_DEFINE_CONST_FUN_OBJ_KW(PlasmaAPA102_get_obj, 2, PlasmaAPA102_get);
MP_DEFINE_CONST_FUN_OBJ_1(PlasmaAPA102_clear_obj, PlasmaAPA102_clear);
MP_DEFINE_CONST_FUN_OBJ_1(PlasmaAPA102_update_obj, PlasmaAPA102_update);
MP_DEFINE_CONST_FUN_OBJ_2(PlasmaAPA102_set_blocking_obj, PlasmaAPA102_set_blocking);

MP_DEFINE_CONST_FUN_OBJ_1(PlasmaWS2812___del___obj, PlasmaWS2812___del__);
MP_DEFINE_CONST_FUN_OBJ_KW(PlasmaWS2812_set_rgb_obj, 5, PlasmaWS2812_set_rgb);
Expand All @@ -18,6 +19,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(PlasmaWS2812_start_obj, 1, PlasmaWS2812_start);
MP_DEFINE_CONST_FUN_OBJ_KW(PlasmaWS2812_get_obj, 2, PlasmaWS2812_get);
MP_DEFINE_CONST_FUN_OBJ_1(PlasmaWS2812_clear_obj, PlasmaWS2812_clear);
MP_DEFINE_CONST_FUN_OBJ_1(PlasmaWS2812_update_obj, PlasmaWS2812_update);
MP_DEFINE_CONST_FUN_OBJ_2(PlasmaWS2812_set_blocking_obj, PlasmaWS2812_set_blocking);

/***** Binding of Methods *****/
static const mp_rom_map_elem_t PlasmaAPA102_locals_dict_table[] = {
Expand All @@ -29,6 +31,7 @@ static const mp_rom_map_elem_t PlasmaAPA102_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&PlasmaAPA102_get_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&PlasmaAPA102_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&PlasmaAPA102_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_blocking), MP_ROM_PTR(&PlasmaAPA102_set_blocking_obj) },
};
static const mp_rom_map_elem_t PlasmaWS2812_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&PlasmaWS2812___del___obj) },
Expand All @@ -38,6 +41,7 @@ static const mp_rom_map_elem_t PlasmaWS2812_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&PlasmaWS2812_get_obj) },
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&PlasmaWS2812_clear_obj) },
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&PlasmaWS2812_update_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_blocking), MP_ROM_PTR(&PlasmaWS2812_set_blocking_obj) },
};

static MP_DEFINE_CONST_DICT(PlasmaAPA102_locals_dict, PlasmaAPA102_locals_dict_table);
Expand Down
20 changes: 18 additions & 2 deletions micropython/modules/plasma/plasma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ typedef struct _PlasmaWS2812_obj_t {
mp_obj_base_t base;
WS2812* ws2812;
void *buf;
bool blocking;
} _PlasmaWS2812_obj_t;


Expand Down Expand Up @@ -98,6 +99,7 @@ mp_obj_t PlasmaWS2812_make_new(const mp_obj_type_t *type, size_t n_args, size_t

self = mp_obj_malloc_with_finaliser(_PlasmaWS2812_obj_t, &PlasmaWS2812_type);
self->buf = buffer;
self->blocking = false;

self->ws2812 = m_new_class(WS2812, num_leds, pio, sm, dat, freq, rgbw, color_order, (WS2812::RGB *)buffer);

Expand All @@ -112,7 +114,13 @@ mp_obj_t PlasmaWS2812_clear(mp_obj_t self_in) {

mp_obj_t PlasmaWS2812_update(mp_obj_t self_in) {
_PlasmaWS2812_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaWS2812_obj_t);
self->ws2812->update(true);
self->ws2812->update(self->blocking);
return mp_const_none;
}

mp_obj_t PlasmaWS2812_set_blocking(mp_obj_t self_in, mp_obj_t blocking_in) {
_PlasmaWS2812_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaWS2812_obj_t);
self->blocking = blocking_in == mp_const_true;
return mp_const_none;
}

Expand Down Expand Up @@ -230,6 +238,7 @@ typedef struct _PlasmaAPA102_obj_t {
mp_obj_base_t base;
APA102* apa102;
void *buf;
bool blocking;
} _PlasmaAPA102_obj_t;


Expand Down Expand Up @@ -308,6 +317,7 @@ mp_obj_t PlasmaAPA102_make_new(const mp_obj_type_t *type, size_t n_args, size_t

self = mp_obj_malloc_with_finaliser(_PlasmaAPA102_obj_t, &PlasmaAPA102_type);
self->buf = buffer;
self->blocking = false;

self->apa102 = m_new_class(APA102, num_leds, pio, sm, dat, clk, freq, buffer);

Expand All @@ -322,7 +332,13 @@ mp_obj_t PlasmaAPA102_clear(mp_obj_t self_in) {

mp_obj_t PlasmaAPA102_update(mp_obj_t self_in) {
_PlasmaAPA102_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaAPA102_obj_t);
self->apa102->update(true);
self->apa102->update(self->blocking);
return mp_const_none;
}

mp_obj_t PlasmaAPA102_set_blocking(mp_obj_t self_in, mp_obj_t blocking_in) {
_PlasmaAPA102_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaAPA102_obj_t);
self->blocking = blocking_in == mp_const_true;
return mp_const_none;
}

Expand Down
2 changes: 2 additions & 0 deletions micropython/modules/plasma/plasma.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern mp_obj_t PlasmaAPA102_set_brightness(size_t n_args, const mp_obj_t *pos_a
extern mp_obj_t PlasmaAPA102_get(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t PlasmaAPA102_clear(mp_obj_t self_in);
extern mp_obj_t PlasmaAPA102_update(mp_obj_t self_in);
extern mp_obj_t PlasmaAPA102_set_blocking(mp_obj_t self_in, mp_obj_t blocking_in);

extern void PlasmaWS2812_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
extern mp_obj_t PlasmaWS2812_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
Expand All @@ -26,5 +27,6 @@ extern mp_obj_t PlasmaWS2812_set_hsv(size_t n_args, const mp_obj_t *pos_args, mp
extern mp_obj_t PlasmaWS2812_get(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
extern mp_obj_t PlasmaWS2812_clear(mp_obj_t self_in);
extern mp_obj_t PlasmaWS2812_update(mp_obj_t self_in);
extern mp_obj_t PlasmaWS2812_set_blocking(mp_obj_t self_in, mp_obj_t blocking_in);

extern bool Pimoroni_mp_obj_to_i2c(mp_obj_t in, void *out);

0 comments on commit 0089e78

Please sign in to comment.