First pass at MP support

encoder-pio
ZodiusInfuser 2022-04-13 20:13:27 +01:00
rodzic 70b589d431
commit 564fecf1de
5 zmienionych plików z 340 dodań i 0 usunięć

Wyświetl plik

@ -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);

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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);

Wyświetl plik

@ -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})

Wyświetl plik

@ -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)