Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plasma: Expose non-blocking update to MicroPython. #1053

Open
wants to merge 2 commits into
base: feature/picovector2-and-layers
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
8 changes: 8 additions & 0 deletions micropython/modules/plasma/plasma.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ 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(PlasmaAPA102_is_busy_obj, PlasmaAPA102_is_busy);

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 +20,8 @@ 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);
MP_DEFINE_CONST_FUN_OBJ_1(PlasmaWS2812_is_busy_obj, PlasmaWS2812_is_busy);

/***** Binding of Methods *****/
static const mp_rom_map_elem_t PlasmaAPA102_locals_dict_table[] = {
Expand All @@ -29,6 +33,8 @@ 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) },
{ MP_ROM_QSTR(MP_QSTR_is_busy), MP_ROM_PTR(&PlasmaAPA102_is_busy_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 +44,8 @@ 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) },
{ MP_ROM_QSTR(MP_QSTR_is_busy), MP_ROM_PTR(&PlasmaWS2812_is_busy_obj) },
};

static MP_DEFINE_CONST_DICT(PlasmaAPA102_locals_dict, PlasmaAPA102_locals_dict_table);
Expand Down
30 changes: 28 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,10 +114,21 @@ 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;
}

mp_obj_t PlasmaWS2812_is_busy(mp_obj_t self_in) {
_PlasmaWS2812_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaWS2812_obj_t);
return self->ws2812->is_busy() ? mp_const_true : mp_const_false;
}

mp_obj_t PlasmaWS2812_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_fps };
static const mp_arg_t allowed_args[] = {
Expand Down Expand Up @@ -230,6 +243,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 +322,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,10 +337,21 @@ 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;
}

mp_obj_t PlasmaAPA102_is_busy(mp_obj_t self_in) {
_PlasmaAPA102_obj_t *self = MP_OBJ_TO_PTR2(self_in, _PlasmaAPA102_obj_t);
return self->apa102->is_busy() ? mp_const_true : mp_const_false;
}

mp_obj_t PlasmaAPA102_start(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_self, ARG_fps };
static const mp_arg_t allowed_args[] = {
Expand Down
4 changes: 4 additions & 0 deletions micropython/modules/plasma/plasma.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ 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 mp_obj_t PlasmaAPA102_is_busy(mp_obj_t self_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 +28,7 @@ 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 mp_obj_t PlasmaWS2812_is_busy(mp_obj_t self_in);

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