kopia lustrzana https://github.com/pimoroni/pimoroni-pico
First pass at MP support
rodzic
70b589d431
commit
564fecf1de
|
@ -0,0 +1,65 @@
|
|||
#include "encoder.h"
|
||||
|
||||
|
||||
/***** Methods *****/
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder___del___obj, Encoder___del__);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_pins_obj, Encoder_pins);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_state_obj, Encoder_state);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_count_obj, Encoder_count);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_obj, Encoder_revolutions);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_degrees_obj, Encoder_angle_degrees);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_radians_obj, Encoder_angle_radians);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_frequency_obj, Encoder_frequency);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_second_obj, Encoder_revolutions_per_second);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_minute_obj, Encoder_revolutions_per_minute);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_per_second_obj, Encoder_degrees_per_second);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_per_second_obj, Encoder_radians_per_second);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_zero_count_obj, Encoder_zero_count);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Encoder_take_snapshot_obj, Encoder_take_snapshot);
|
||||
|
||||
/***** Binding of Methods *****/
|
||||
STATIC const mp_rom_map_elem_t Encoder_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Encoder___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&Encoder_pins_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&Encoder_state_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Encoder_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_revolutions), MP_ROM_PTR(&Encoder_revolutions_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_angle_degrees), MP_ROM_PTR(&Encoder_angle_degrees_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_angle_radians), MP_ROM_PTR(&Encoder_angle_radians_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Encoder_frequency_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Encoder_revolutions_per_second_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_revolutions_per_minute), MP_ROM_PTR(&Encoder_revolutions_per_minute_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_degrees_per_second), MP_ROM_PTR(&Encoder_degrees_per_second_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_radians_per_second), MP_ROM_PTR(&Encoder_radians_per_second_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_zero_count), MP_ROM_PTR(&Encoder_zero_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_take_snapshot), MP_ROM_PTR(&Encoder_take_snapshot_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(Encoder_locals_dict, Encoder_locals_dict_table);
|
||||
|
||||
/***** Class Definition *****/
|
||||
const mp_obj_type_t Encoder_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_encoder,
|
||||
.print = Encoder_print,
|
||||
.make_new = Encoder_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&Encoder_locals_dict,
|
||||
};
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_map_elem_t encoder_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_encoder) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Encoder), (mp_obj_t)&Encoder_type },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_ANGULAR), MP_ROM_INT(0x00) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_LINEAR), MP_ROM_INT(0x01) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CONTINUOUS), MP_ROM_INT(0x02) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_encoder_globals, encoder_globals_table);
|
||||
|
||||
/***** Module Definition *****/
|
||||
const mp_obj_module_t encoder_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_encoder_globals,
|
||||
};
|
||||
MP_REGISTER_MODULE(MP_QSTR_encoder, encoder_user_cmodule, MODULE_ENCODER_ENABLED);
|
|
@ -0,0 +1,229 @@
|
|||
#include "drivers/encoder-pio/capture.hpp"
|
||||
#include "drivers/encoder-pio/encoder.hpp"
|
||||
#include <cstdio>
|
||||
|
||||
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
|
||||
|
||||
using namespace pimoroni;
|
||||
//using namespace encoder;
|
||||
|
||||
extern "C" {
|
||||
#include "encoder.h"
|
||||
#include "py/builtin.h"
|
||||
|
||||
|
||||
/********** Encoder **********/
|
||||
|
||||
/***** Variables Struct *****/
|
||||
typedef struct _Encoder_obj_t {
|
||||
mp_obj_base_t base;
|
||||
Encoder* encoder;
|
||||
} _Encoder_obj_t;
|
||||
|
||||
|
||||
/***** Print *****/
|
||||
void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind; //Unused input parameter
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
mp_print_str(print, "Encoder(");
|
||||
|
||||
mp_print_str(print, "pins = (");
|
||||
pin_pair pins = self->encoder->pins();
|
||||
mp_obj_print_helper(print, mp_obj_new_int(pins.a), PRINT_REPR);
|
||||
mp_print_str(print, ", ");
|
||||
mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR);
|
||||
mp_print_str(print, "), enabled = ");
|
||||
/*mp_obj_print_helper(print, self->encoder->is_enabled() ? mp_const_true : mp_const_false, PRINT_REPR);
|
||||
mp_print_str(print, ", pulse = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->pulse()), PRINT_REPR);
|
||||
mp_print_str(print, ", value = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->value()), PRINT_REPR);
|
||||
mp_print_str(print, ", freq = ");
|
||||
mp_obj_print_helper(print, mp_obj_new_float(self->encoder->frequency()), PRINT_REPR);
|
||||
*/
|
||||
mp_print_str(print, ")");
|
||||
}
|
||||
|
||||
|
||||
/***** Constructor *****/
|
||||
mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_Encoder_obj_t *self = nullptr;
|
||||
|
||||
enum { ARG_pio, ARG_sm, ARG_pins, ARG_pin_c, ARG_calibration, ARG_freq };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_pio, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_sm, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_pin_c, MP_ARG_INT, {.u_int = PIN_UNUSED} },
|
||||
{ MP_QSTR_calibration, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_freq, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
PIO pio = args[ARG_pio].u_int == 0 ? pio0 : pio1;
|
||||
int sm = args[ARG_sm].u_int;
|
||||
|
||||
size_t pin_count = 0;
|
||||
pin_pair pins;
|
||||
|
||||
// Determine what pair of pins this encoder will use
|
||||
const mp_obj_t object = args[ARG_pins].u_obj;
|
||||
mp_obj_t *items = nullptr;
|
||||
if(mp_obj_is_type(object, &mp_type_list)) {
|
||||
mp_obj_list_t *list = MP_OBJ_TO_PTR2(object, mp_obj_list_t);
|
||||
pin_count = list->len;
|
||||
items = list->items;
|
||||
}
|
||||
else if(mp_obj_is_type(object, &mp_type_tuple)) {
|
||||
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(object, mp_obj_tuple_t);
|
||||
pin_count = tuple->len;
|
||||
items = tuple->items;
|
||||
}
|
||||
|
||||
if(items == nullptr)
|
||||
mp_raise_TypeError("cannot convert object to a list or tuple of pins");
|
||||
else if(pin_count != 2)
|
||||
mp_raise_TypeError("list or tuple must only contain two integers");
|
||||
else {
|
||||
int a = mp_obj_get_int(items[0]);
|
||||
int b = mp_obj_get_int(items[1]);
|
||||
if((a < 0 || a >= (int)NUM_BANK0_GPIOS) ||
|
||||
(b < 0 || b >= (int)NUM_BANK0_GPIOS)) {
|
||||
mp_raise_ValueError("a pin in the list or tuple is out of range. Expected 0 to 29");
|
||||
}
|
||||
else if(a == b) {
|
||||
mp_raise_ValueError("cannot use the same pin for encoder A and B");
|
||||
}
|
||||
|
||||
pins.a = (uint8_t)a;
|
||||
pins.b = (uint8_t)b;
|
||||
}
|
||||
/*
|
||||
encoder::Calibration *calib = nullptr;
|
||||
encoder::CalibrationType calibration_type = encoder::CalibrationType::ANGULAR;
|
||||
const mp_obj_t calib_object = args[ARG_calibration].u_obj;
|
||||
if(calib_object != mp_const_none) {
|
||||
if(mp_obj_is_int(calib_object)) {
|
||||
int type = mp_obj_get_int(calib_object);
|
||||
if(type < 0 || type >= 3) {
|
||||
mp_raise_ValueError("type out of range. Expected ANGULAR (0), LINEAR (1) or CONTINUOUS (2)");
|
||||
}
|
||||
calibration_type = (encoder::CalibrationType)type;
|
||||
}
|
||||
else if(mp_obj_is_type(calib_object, &Calibration_type)) {
|
||||
calib = (MP_OBJ_TO_PTR2(calib_object, _Calibration_obj_t)->calibration);
|
||||
}
|
||||
else {
|
||||
mp_raise_TypeError("cannot convert object to an integer or a Calibration class instance");
|
||||
}
|
||||
}
|
||||
|
||||
float freq = encoder::EncoderState::DEFAULT_FREQUENCY;
|
||||
if(args[ARG_freq].u_obj != mp_const_none) {
|
||||
freq = mp_obj_get_float(args[ARG_freq].u_obj);
|
||||
}
|
||||
*/
|
||||
|
||||
Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_pin_c].u_int);
|
||||
if(!encoder->init()) {
|
||||
delete encoder;
|
||||
mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this Encoder. Try running `import gc` followed by `gc.collect()` before creating it");
|
||||
}
|
||||
|
||||
self = m_new_obj_with_finaliser(_Encoder_obj_t);
|
||||
self->base.type = &Encoder_type;
|
||||
self->encoder = encoder;
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
|
||||
/***** Destructor ******/
|
||||
mp_obj_t Encoder___del__(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
delete self->encoder;
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
|
||||
/***** Methods *****/
|
||||
extern mp_obj_t Encoder_pins(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
pin_pair pins = self->encoder->pins();
|
||||
|
||||
mp_obj_t tuple[2];
|
||||
tuple[0] = mp_obj_new_int(pins.a);
|
||||
tuple[1] = mp_obj_new_int(pins.b);
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_state(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
bool_pair state = self->encoder->state();
|
||||
|
||||
mp_obj_t tuple[2];
|
||||
tuple[0] = state.a ? mp_const_true : mp_const_false;
|
||||
tuple[1] = state.b ? mp_const_true : mp_const_false;
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_count(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_int(self->encoder->count());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_revolutions(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->revolutions());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->angle_degrees());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->angle_radians());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_frequency(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->frequency());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->revolutions_per_second());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->revolutions_per_minute());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->degrees_per_second());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
return mp_obj_new_float(self->encoder->radians_per_second());
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_zero_count(mp_obj_t self_in) {
|
||||
_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
self->encoder->zero_count();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in) {
|
||||
//_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
|
||||
//Capture capture = self->encoder->perform_capture();
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
/***** Extern of Class Definition *****/
|
||||
extern const mp_obj_type_t Encoder_type;
|
||||
|
||||
/***** Extern of Class Methods *****/
|
||||
extern void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
extern mp_obj_t Encoder_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 Encoder___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_pins(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_state(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_count(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_revolutions(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_frequency(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_zero_count(mp_obj_t self_in);
|
||||
extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in);
|
|
@ -0,0 +1,22 @@
|
|||
set(MOD_NAME encoder)
|
||||
string(TOUPPER ${MOD_NAME} MOD_NAME_UPPER)
|
||||
add_library(usermod_${MOD_NAME} INTERFACE)
|
||||
|
||||
target_sources(usermod_${MOD_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/capture.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.cpp
|
||||
)
|
||||
pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.pio)
|
||||
|
||||
target_include_directories(usermod_${MOD_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/
|
||||
)
|
||||
|
||||
target_compile_definitions(usermod_${MOD_NAME} INTERFACE
|
||||
MODULE_ENCODER_ENABLED=1
|
||||
)
|
||||
|
||||
target_link_libraries(usermod INTERFACE usermod_${MOD_NAME})
|
|
@ -43,6 +43,7 @@ include(bitmap_fonts/micropython)
|
|||
include(plasma/micropython)
|
||||
include(hub75/micropython)
|
||||
include(servo/micropython)
|
||||
include(encoder/micropython)
|
||||
include(ulab/code/micropython)
|
||||
include(qrcode/micropython/micropython)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue