2022-04-13 20:13:27 +01:00
# include "drivers/encoder-pio/encoder.hpp"
# include <cstdio>
2022-04-17 16:16:59 +01:00
# include <cfloat>
2022-04-13 20:13:27 +01:00
# 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"
2022-04-17 16:16:59 +01:00
/********** Snapshot **********/
/***** Variables Struct *****/
typedef struct _Snapshot_obj_t {
mp_obj_base_t base ;
Encoder : : Snapshot * snapshot ;
} _Snapshot_obj_t ;
/***** Print *****/
void Snapshot_print ( const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
( void ) kind ; //Unused input parameter
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
Encoder : : Snapshot * snap = self - > snapshot ;
mp_print_str ( print , " Snapshot(count = " ) ;
mp_obj_print_helper ( print , mp_obj_new_int ( snap - > count ) , PRINT_REPR ) ;
mp_print_str ( print , " , delta = " ) ;
mp_obj_print_helper ( print , mp_obj_new_int ( snap - > delta ) , PRINT_REPR ) ;
mp_print_str ( print , " , freq = " ) ;
mp_obj_print_helper ( print , mp_obj_new_float ( snap - > frequency ) , PRINT_REPR ) ;
mp_print_str ( print , " ) " ) ;
}
/***** Constructor *****/
mp_obj_t Snapshot_make_new ( const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
mp_raise_TypeError ( " cannot create an instance of Snapshot. They can only be created by calling take_snapshot on an Encoder object " ) ;
return mp_const_none ;
}
/***** Destructor ******/
mp_obj_t Snapshot___del__ ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
delete self - > snapshot ;
return mp_const_none ;
}
/***** Methods *****/
mp_obj_t Snapshot_count ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > count ) ;
}
mp_obj_t Snapshot_delta ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > delta ) ;
}
mp_obj_t Snapshot_frequency ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_float ( self - > snapshot - > frequency ) ;
}
mp_obj_t Snapshot_revolutions ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > revolutions ( ) ) ;
}
mp_obj_t Snapshot_degrees ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > degrees ( ) ) ;
}
mp_obj_t Snapshot_radians ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > radians ( ) ) ;
}
mp_obj_t Snapshot_revolutions_delta ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > revolutions_delta ( ) ) ;
}
mp_obj_t Snapshot_degrees_delta ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > degrees_delta ( ) ) ;
}
mp_obj_t Snapshot_radians_delta ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_int ( self - > snapshot - > radians_delta ( ) ) ;
}
mp_obj_t Snapshot_revolutions_per_second ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_float ( self - > snapshot - > revolutions_per_second ( ) ) ;
}
mp_obj_t Snapshot_revolutions_per_minute ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_float ( self - > snapshot - > revolutions_per_minute ( ) ) ;
}
mp_obj_t Snapshot_degrees_per_second ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_float ( self - > snapshot - > degrees_per_second ( ) ) ;
}
mp_obj_t Snapshot_radians_per_second ( mp_obj_t self_in ) {
_Snapshot_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Snapshot_obj_t ) ;
return mp_obj_new_float ( self - > snapshot - > radians_per_second ( ) ) ;
}
2022-04-13 20:13:27 +01:00
/********** 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 ) ;
2022-04-17 16:16:59 +01:00
mp_print_str ( print , " , " ) ;
mp_obj_print_helper ( print , mp_obj_new_int ( self - > encoder - > common_pin ( ) ) , PRINT_REPR ) ;
mp_print_str ( print , " ) " ) ;
if ( self - > encoder - > direction ( ) = = NORMAL )
mp_print_str ( print , " , direction = NORMAL " ) ;
else
mp_print_str ( print , " , direction = REVERSED " ) ;
mp_print_str ( print , " , counts_per_rev = " ) ;
mp_obj_print_helper ( print , mp_obj_new_float ( self - > encoder - > counts_per_revolution ( ) ) , PRINT_REPR ) ;
2022-04-13 20:13:27 +01:00
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 ;
2022-04-17 16:16:59 +01:00
enum { ARG_pio , ARG_sm , ARG_pins , ARG_common_pin , ARG_count_microsteps , ARG_freq_divider } ;
2022-04-13 20:13:27 +01:00
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 } ,
2022-04-17 16:16:59 +01:00
{ MP_QSTR_common_pin , MP_ARG_INT , { . u_int = PIN_UNUSED } } ,
{ MP_QSTR_count_microsteps , MP_ARG_BOOL , { . u_bool = false } } ,
{ MP_QSTR_freq_divider , MP_ARG_OBJ , { . u_obj = mp_const_none } } ,
2022-04-13 20:13:27 +01:00
} ;
// 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 ;
}
2022-04-17 16:16:59 +01:00
float freq_divider = Encoder : : DEFAULT_FREQ_DIVIDER ;
if ( args [ ARG_freq_divider ] . u_obj ! = mp_const_none ) {
freq_divider = mp_obj_get_float ( args [ ARG_freq_divider ] . u_obj ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
bool count_microsteps = args [ ARG_count_microsteps ] . u_bool ;
Encoder * encoder = new Encoder ( pio , sm , pins , args [ ARG_common_pin ] . u_int , NORMAL , Encoder : : DEFAULT_COUNTS_PER_REV , count_microsteps , freq_divider ) ;
2022-04-13 20:13:27 +01:00
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 ) ;
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_common_pin ( 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 - > common_pin ( ) ) ;
}
2022-04-13 20:13:27 +01:00
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 ( ) ) ;
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_delta ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_int ( self - > encoder - > delta ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_zero ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
self - > encoder - > zero ( ) ;
return mp_const_none ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_step ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_int ( self - > encoder - > step ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_turn ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_int ( self - > encoder - > turn ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_revolutions ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_float ( self - > encoder - > revolutions ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_degrees ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_float ( self - > encoder - > degrees ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_radians ( mp_obj_t self_in ) {
2022-04-13 20:13:27 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
2022-04-17 16:16:59 +01:00
return mp_obj_new_float ( self - > encoder - > radians ( ) ) ;
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_direction ( size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
if ( n_args < = 1 ) {
enum { ARG_self } ;
static const mp_arg_t allowed_args [ ] = {
{ MP_QSTR_ , MP_ARG_REQUIRED | MP_ARG_OBJ } ,
} ;
// Parse args.
mp_arg_val_t args [ MP_ARRAY_SIZE ( allowed_args ) ] ;
mp_arg_parse_all ( n_args , pos_args , kw_args , MP_ARRAY_SIZE ( allowed_args ) , allowed_args , args ) ;
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( args [ ARG_self ] . u_obj , _Encoder_obj_t ) ;
return mp_obj_new_int ( self - > encoder - > direction ( ) ) ;
}
else {
enum { ARG_self , ARG_direction } ;
static const mp_arg_t allowed_args [ ] = {
{ MP_QSTR_ , MP_ARG_REQUIRED | MP_ARG_OBJ } ,
{ MP_QSTR_direction , MP_ARG_REQUIRED | MP_ARG_INT } ,
} ;
// Parse args.
mp_arg_val_t args [ MP_ARRAY_SIZE ( allowed_args ) ] ;
mp_arg_parse_all ( n_args , pos_args , kw_args , MP_ARRAY_SIZE ( allowed_args ) , allowed_args , args ) ;
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( args [ ARG_self ] . u_obj , _Encoder_obj_t ) ;
int direction = args [ ARG_direction ] . u_int ;
if ( direction < 0 | | direction > 1 ) {
mp_raise_ValueError ( " direction out of range. Expected NORMAL (0) or REVERSED (1) " ) ;
}
self - > encoder - > direction ( ( Direction ) direction ) ;
return mp_const_none ;
}
2022-04-13 20:13:27 +01:00
}
2022-04-17 16:16:59 +01:00
extern mp_obj_t Encoder_counts_per_revolution ( size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
if ( n_args < = 1 ) {
enum { ARG_self } ;
static const mp_arg_t allowed_args [ ] = {
{ MP_QSTR_ , MP_ARG_REQUIRED | MP_ARG_OBJ } ,
} ;
// Parse args.
mp_arg_val_t args [ MP_ARRAY_SIZE ( allowed_args ) ] ;
mp_arg_parse_all ( n_args , pos_args , kw_args , MP_ARRAY_SIZE ( allowed_args ) , allowed_args , args ) ;
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( args [ ARG_self ] . u_obj , _Encoder_obj_t ) ;
return mp_obj_new_float ( self - > encoder - > counts_per_revolution ( ) ) ;
}
else {
enum { ARG_self , ARG_counts_per_rev } ;
static const mp_arg_t allowed_args [ ] = {
{ MP_QSTR_ , MP_ARG_REQUIRED | MP_ARG_OBJ } ,
{ MP_QSTR_counts_per_rev , MP_ARG_REQUIRED | MP_ARG_OBJ } ,
} ;
// Parse args.
mp_arg_val_t args [ MP_ARRAY_SIZE ( allowed_args ) ] ;
mp_arg_parse_all ( n_args , pos_args , kw_args , MP_ARRAY_SIZE ( allowed_args ) , allowed_args , args ) ;
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( args [ ARG_self ] . u_obj , _Encoder_obj_t ) ;
float counts_per_rev = mp_obj_get_float ( args [ ARG_counts_per_rev ] . u_obj ) ;
if ( counts_per_rev < FLT_EPSILON ) {
mp_raise_ValueError ( " counts_per_rev out of range. Expected greater than 0.0 " ) ;
}
self - > encoder - > counts_per_revolution ( counts_per_rev ) ;
return mp_const_none ;
}
2022-04-13 20:13:27 +01:00
}
extern mp_obj_t Encoder_take_snapshot ( mp_obj_t self_in ) {
2022-04-17 16:16:59 +01:00
_Encoder_obj_t * self = MP_OBJ_TO_PTR2 ( self_in , _Encoder_obj_t ) ;
// Create a new MP Snapshot instance and assign a copy of the encoder's snapshot to it
_Snapshot_obj_t * snap = m_new_obj_with_finaliser ( _Snapshot_obj_t ) ;
snap - > base . type = & Snapshot_type ;
snap - > snapshot = new Encoder : : Snapshot ( self - > encoder - > take_snapshot ( ) ) ;
return MP_OBJ_FROM_PTR ( snap ) ;
2022-04-13 20:13:27 +01:00
}
}