kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Pico RGB Keypad: Refactor to class.
Because `mp_tracked_calloc` does not survive a soft reset but the memory region will, resulting in half-initialised frankenclasses that behave unpredictably. Using the class pattern fixes this since it's always guaranteed to be initialised when a user instantiates it, and __del__ can handle cleanup.pull/711/head
rodzic
9964ed716b
commit
bd3651d97d
|
@ -17,6 +17,11 @@ enum pin {
|
|||
|
||||
namespace pimoroni {
|
||||
|
||||
PicoRGBKeypad::~PicoRGBKeypad() {
|
||||
clear();
|
||||
update();
|
||||
}
|
||||
|
||||
void PicoRGBKeypad::init() {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
led_data = buffer + 4;
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace pimoroni {
|
|||
uint8_t *led_data;
|
||||
|
||||
public:
|
||||
~PicoRGBKeypad();
|
||||
void init();
|
||||
void update();
|
||||
void set_brightness(float brightness);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import time
|
||||
import picokeypad as keypad
|
||||
import picokeypad
|
||||
|
||||
keypad.init()
|
||||
keypad = picokeypad.PicoKeypad()
|
||||
keypad.set_brightness(1.0)
|
||||
|
||||
lit = 0
|
||||
|
|
|
@ -5,21 +5,20 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/***** Module Functions *****/
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_init_obj, picokeypad_init);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_width_obj, picokeypad_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_height_obj, picokeypad_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_num_pads_obj, picokeypad_get_num_pads);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_update_obj, picokeypad_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_set_brightness_obj, picokeypad_set_brightness);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_xy_obj, 5, 5, picokeypad_illuminate_xy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_obj, 4, 4, picokeypad_illuminate);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_clear_obj, picokeypad_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_button_states_obj, picokeypad_get_button_states);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad___del___obj, picokeypad___del__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_width_obj, picokeypad_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_height_obj, picokeypad_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_num_pads_obj, picokeypad_get_num_pads);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_update_obj, picokeypad_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picokeypad_set_brightness_obj, picokeypad_set_brightness);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_xy_obj, 6, 6, picokeypad_illuminate_xy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_obj, 5, 5, picokeypad_illuminate);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_clear_obj, picokeypad_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_button_states_obj, picokeypad_get_button_states);
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_map_elem_t picokeypad_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picokeypad) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picokeypad_init_obj) },
|
||||
/* Class Methods */
|
||||
STATIC const mp_rom_map_elem_t picokeypad_locals[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picokeypad___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picokeypad_get_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picokeypad_get_height_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_num_pads), MP_ROM_PTR(&picokeypad_get_num_pads_obj) },
|
||||
|
@ -30,9 +29,34 @@ STATIC const mp_map_elem_t picokeypad_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picokeypad_clear_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_button_states), MP_ROM_PTR(&picokeypad_get_button_states_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_globals, picokeypad_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_locals, picokeypad_locals);
|
||||
|
||||
#ifdef MP_DEFINE_CONST_OBJ_TYPE
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
PicoKeypad_type,
|
||||
MP_QSTR_PicoKeypad,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, picokeypad_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&mp_module_picokeypad_locals
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t PicoKeypad_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PicoKeypad,
|
||||
.make_new = picokeypad_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_module_picokeypad_locals,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Module Globals */
|
||||
STATIC const mp_map_elem_t picokeypad_globals[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_picokeypad) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PicoKeypad), (mp_obj_t)&PicoKeypad_type },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(4) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_globals, picokeypad_globals);
|
||||
|
||||
/***** Module Definition *****/
|
||||
const mp_obj_module_t picokeypad_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_picokeypad_globals,
|
||||
|
|
|
@ -7,130 +7,125 @@
|
|||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoRGBKeypad *keypad = nullptr;
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "pico_rgb_keypad.h"
|
||||
|
||||
#define NOT_INITIALISED_MSG "Cannot call this function, as picokeypad is not initialised. Call picokeypad.init() first."
|
||||
typedef struct _PicoKeypad_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoRGBKeypad* keypad;
|
||||
} PicoKeypad_obj_t;
|
||||
|
||||
mp_obj_t picokeypad_init() {
|
||||
if(keypad == nullptr) {
|
||||
keypad = m_tracked_alloc_class(PicoRGBKeypad);
|
||||
keypad->init();
|
||||
}
|
||||
mp_obj_t picokeypad_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_PicoKeypad_obj_t *self = nullptr;
|
||||
|
||||
self = m_new_obj_with_finaliser(PicoKeypad_obj_t);
|
||||
self->base.type = &PicoKeypad_type;
|
||||
|
||||
self->keypad = m_new_class(PicoRGBKeypad);
|
||||
self->keypad->init();
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad___del__(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
m_del_class(PicoRGBKeypad, self->keypad);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_width() {
|
||||
mp_obj_t picokeypad_get_width(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::WIDTH);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_height() {
|
||||
mp_obj_t picokeypad_get_height(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::HEIGHT);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_num_pads() {
|
||||
mp_obj_t picokeypad_get_num_pads(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::NUM_PADS);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_update() {
|
||||
if(keypad != nullptr)
|
||||
keypad->update();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
mp_obj_t picokeypad_update(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
self->keypad->update();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj) {
|
||||
if(keypad != nullptr) {
|
||||
float brightness = mp_obj_get_float(brightness_obj);
|
||||
mp_obj_t picokeypad_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
|
||||
if(brightness < 0 || brightness > 1.0f)
|
||||
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
||||
else
|
||||
keypad->set_brightness(brightness);
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
float brightness = mp_obj_get_float(brightness_obj);
|
||||
|
||||
if(brightness < 0 || brightness > 1.0f)
|
||||
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
||||
|
||||
self->keypad->set_brightness(brightness);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_illuminate_xy(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's 5
|
||||
(void)n_args; //Unused input parameter, we know it's self + 5
|
||||
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoKeypad_obj_t);
|
||||
|
||||
if(keypad != nullptr) {
|
||||
int x = mp_obj_get_int(args[0]);
|
||||
int y = mp_obj_get_int(args[1]);
|
||||
int r = mp_obj_get_int(args[2]);
|
||||
int g = mp_obj_get_int(args[3]);
|
||||
int b = mp_obj_get_int(args[4]);
|
||||
int x = mp_obj_get_int(args[1]);
|
||||
int y = mp_obj_get_int(args[2]);
|
||||
int r = mp_obj_get_int(args[3]);
|
||||
int g = mp_obj_get_int(args[4]);
|
||||
int b = mp_obj_get_int(args[5]);
|
||||
|
||||
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
else if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
else if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
else
|
||||
keypad->illuminate(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
|
||||
self->keypad->illuminate(x, y, r, g, b);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_illuminate(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's 5
|
||||
(void)n_args; //Unused input parameter, we know it's self + 5
|
||||
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoKeypad_obj_t);
|
||||
|
||||
if(keypad != nullptr) {
|
||||
int i = mp_obj_get_int(args[0]);
|
||||
int r = mp_obj_get_int(args[1]);
|
||||
int g = mp_obj_get_int(args[2]);
|
||||
int b = mp_obj_get_int(args[3]);
|
||||
int i = mp_obj_get_int(args[1]);
|
||||
int r = mp_obj_get_int(args[2]);
|
||||
int g = mp_obj_get_int(args[3]);
|
||||
int b = mp_obj_get_int(args[4]);
|
||||
|
||||
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
else if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
else if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
else
|
||||
keypad->illuminate(i, r, g, b);
|
||||
}
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
|
||||
self->keypad->illuminate(i, r, g, b);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_clear() {
|
||||
if(keypad != nullptr)
|
||||
keypad->clear();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
mp_obj_t picokeypad_clear(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
self->keypad->clear();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_button_states() {
|
||||
mp_obj_t picokeypad_get_button_states(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
uint16_t states = 0;
|
||||
if(keypad != nullptr)
|
||||
states = keypad->get_button_states();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
states = self->keypad->get_button_states();
|
||||
return mp_obj_new_int(states);
|
||||
}
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
extern const mp_obj_type_t PicoKeypad_type;
|
||||
|
||||
// Declare the functions we'll make available in Python
|
||||
extern mp_obj_t picokeypad_init();
|
||||
extern mp_obj_t picokeypad_get_width();
|
||||
extern mp_obj_t picokeypad_get_height();
|
||||
extern mp_obj_t picokeypad_get_num_pads();
|
||||
extern mp_obj_t picokeypad_update();
|
||||
extern mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj);
|
||||
extern mp_obj_t picokeypad_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t picokeypad___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_width(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_height(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_num_pads(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_update(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj);
|
||||
extern mp_obj_t picokeypad_illuminate_xy(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picokeypad_illuminate(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picokeypad_clear();
|
||||
extern mp_obj_t picokeypad_get_button_states();
|
||||
extern mp_obj_t picokeypad_clear(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_button_states(mp_obj_t self_in);
|
Ładowanie…
Reference in New Issue