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 {
|
namespace pimoroni {
|
||||||
|
|
||||||
|
PicoRGBKeypad::~PicoRGBKeypad() {
|
||||||
|
clear();
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void PicoRGBKeypad::init() {
|
void PicoRGBKeypad::init() {
|
||||||
memset(buffer, 0, sizeof(buffer));
|
memset(buffer, 0, sizeof(buffer));
|
||||||
led_data = buffer + 4;
|
led_data = buffer + 4;
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace pimoroni {
|
||||||
uint8_t *led_data;
|
uint8_t *led_data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
~PicoRGBKeypad();
|
||||||
void init();
|
void init();
|
||||||
void update();
|
void update();
|
||||||
void set_brightness(float brightness);
|
void set_brightness(float brightness);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import time
|
import time
|
||||||
import picokeypad as keypad
|
import picokeypad
|
||||||
|
|
||||||
keypad.init()
|
keypad = picokeypad.PicoKeypad()
|
||||||
keypad.set_brightness(1.0)
|
keypad.set_brightness(1.0)
|
||||||
|
|
||||||
lit = 0
|
lit = 0
|
||||||
|
|
|
@ -5,21 +5,20 @@
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/***** Module Functions *****/
|
/***** Module Functions *****/
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_init_obj, picokeypad_init);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad___del___obj, picokeypad___del__);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_width_obj, picokeypad_get_width);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(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_1(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_1(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_update_obj, picokeypad_update);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_set_brightness_obj, picokeypad_set_brightness);
|
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, 5, 5, picokeypad_illuminate_xy);
|
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, 4, 4, picokeypad_illuminate);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_obj, 5, 5, picokeypad_illuminate);
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_clear_obj, picokeypad_clear);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(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_get_button_states_obj, picokeypad_get_button_states);
|
||||||
|
|
||||||
/***** Globals Table *****/
|
/* Class Methods */
|
||||||
STATIC const mp_map_elem_t picokeypad_globals_table[] = {
|
STATIC const mp_rom_map_elem_t picokeypad_locals[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picokeypad) },
|
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picokeypad___del___obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picokeypad_init_obj) },
|
|
||||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picokeypad_get_width_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_height), MP_ROM_PTR(&picokeypad_get_height_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_get_num_pads), MP_ROM_PTR(&picokeypad_get_num_pads_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_clear), MP_ROM_PTR(&picokeypad_clear_obj) },
|
||||||
{ MP_ROM_QSTR(MP_QSTR_get_button_states), MP_ROM_PTR(&picokeypad_get_button_states_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 = {
|
const mp_obj_module_t picokeypad_user_cmodule = {
|
||||||
.base = { &mp_type_module },
|
.base = { &mp_type_module },
|
||||||
.globals = (mp_obj_dict_t*)&mp_module_picokeypad_globals,
|
.globals = (mp_obj_dict_t*)&mp_module_picokeypad_globals,
|
||||||
|
|
|
@ -7,130 +7,125 @@
|
||||||
|
|
||||||
using namespace pimoroni;
|
using namespace pimoroni;
|
||||||
|
|
||||||
PicoRGBKeypad *keypad = nullptr;
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "pico_rgb_keypad.h"
|
#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() {
|
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) {
|
||||||
if(keypad == nullptr) {
|
_PicoKeypad_obj_t *self = nullptr;
|
||||||
keypad = m_tracked_alloc_class(PicoRGBKeypad);
|
|
||||||
keypad->init();
|
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;
|
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);
|
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);
|
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);
|
return mp_obj_new_int(PicoRGBKeypad::NUM_PADS);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t picokeypad_update() {
|
mp_obj_t picokeypad_update(mp_obj_t self_in) {
|
||||||
if(keypad != nullptr)
|
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||||
keypad->update();
|
self->keypad->update();
|
||||||
else
|
|
||||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj) {
|
mp_obj_t picokeypad_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) {
|
||||||
if(keypad != nullptr) {
|
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||||
float brightness = mp_obj_get_float(brightness_obj);
|
|
||||||
|
|
||||||
if(brightness < 0 || brightness > 1.0f)
|
float brightness = mp_obj_get_float(brightness_obj);
|
||||||
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
|
||||||
else
|
if(brightness < 0 || brightness > 1.0f)
|
||||||
keypad->set_brightness(brightness);
|
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
||||||
}
|
|
||||||
else
|
self->keypad->set_brightness(brightness);
|
||||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t picokeypad_illuminate_xy(mp_uint_t n_args, const mp_obj_t *args) {
|
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[1]);
|
||||||
int x = mp_obj_get_int(args[0]);
|
int y = mp_obj_get_int(args[2]);
|
||||||
int y = mp_obj_get_int(args[1]);
|
int r = mp_obj_get_int(args[3]);
|
||||||
int r = mp_obj_get_int(args[2]);
|
int g = mp_obj_get_int(args[4]);
|
||||||
int g = mp_obj_get_int(args[3]);
|
int b = mp_obj_get_int(args[5]);
|
||||||
int b = mp_obj_get_int(args[4]);
|
|
||||||
|
|
||||||
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
||||||
mp_raise_ValueError("x or y out of range.");
|
mp_raise_ValueError("x or y out of range.");
|
||||||
else {
|
if(r < 0 || r > 255)
|
||||||
if(r < 0 || r > 255)
|
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
if(g < 0 || g > 255)
|
||||||
else if(g < 0 || g > 255)
|
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
if(b < 0 || b > 255)
|
||||||
else if(b < 0 || b > 255)
|
mp_raise_ValueError("b out of range. Expected 0 to 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);
|
|
||||||
|
|
||||||
|
self->keypad->illuminate(x, y, r, g, b);
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t picokeypad_illuminate(mp_uint_t n_args, const mp_obj_t *args) {
|
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[1]);
|
||||||
int i = mp_obj_get_int(args[0]);
|
int r = mp_obj_get_int(args[2]);
|
||||||
int r = mp_obj_get_int(args[1]);
|
int g = mp_obj_get_int(args[3]);
|
||||||
int g = mp_obj_get_int(args[2]);
|
int b = mp_obj_get_int(args[4]);
|
||||||
int b = mp_obj_get_int(args[3]);
|
|
||||||
|
|
||||||
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
||||||
mp_raise_ValueError("x or y out of range.");
|
mp_raise_ValueError("x or y out of range.");
|
||||||
else {
|
if(r < 0 || r > 255)
|
||||||
if(r < 0 || r > 255)
|
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
if(g < 0 || g > 255)
|
||||||
else if(g < 0 || g > 255)
|
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
if(b < 0 || b > 255)
|
||||||
else if(b < 0 || b > 255)
|
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
|
||||||
else
|
self->keypad->illuminate(i, r, g, b);
|
||||||
keypad->illuminate(i, r, g, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
|
||||||
|
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t picokeypad_clear() {
|
mp_obj_t picokeypad_clear(mp_obj_t self_in) {
|
||||||
if(keypad != nullptr)
|
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||||
keypad->clear();
|
self->keypad->clear();
|
||||||
else
|
|
||||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
|
||||||
|
|
||||||
return mp_const_none;
|
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;
|
uint16_t states = 0;
|
||||||
if(keypad != nullptr)
|
states = self->keypad->get_button_states();
|
||||||
states = keypad->get_button_states();
|
|
||||||
else
|
|
||||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
|
||||||
|
|
||||||
return mp_obj_new_int(states);
|
return mp_obj_new_int(states);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,17 @@
|
||||||
// Include MicroPython API.
|
// Include MicroPython API.
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
|
||||||
|
extern const mp_obj_type_t PicoKeypad_type;
|
||||||
|
|
||||||
// Declare the functions we'll make available in Python
|
// Declare the functions we'll make available in Python
|
||||||
extern mp_obj_t picokeypad_init();
|
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_get_width();
|
extern mp_obj_t picokeypad___del__(mp_obj_t self_in);
|
||||||
extern mp_obj_t picokeypad_get_height();
|
extern mp_obj_t picokeypad_get_width(mp_obj_t self_in);
|
||||||
extern mp_obj_t picokeypad_get_num_pads();
|
extern mp_obj_t picokeypad_get_height(mp_obj_t self_in);
|
||||||
extern mp_obj_t picokeypad_update();
|
extern mp_obj_t picokeypad_get_num_pads(mp_obj_t self_in);
|
||||||
extern mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj);
|
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_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_illuminate(mp_uint_t n_args, const mp_obj_t *args);
|
||||||
extern mp_obj_t picokeypad_clear();
|
extern mp_obj_t picokeypad_clear(mp_obj_t self_in);
|
||||||
extern mp_obj_t picokeypad_get_button_states();
|
extern mp_obj_t picokeypad_get_button_states(mp_obj_t self_in);
|
Ładowanie…
Reference in New Issue