Skip to content

Commit d115ab6

Browse files
committed
mimxrt/machine_encoder: Emulate the phases argument.
By dividing the internal counter by 1, 2 or 4. The default is 4, matching the hardware. Signed-off-by: robert-hh <robert@hammelrath.com>
1 parent 5e8bac1 commit d115ab6

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

docs/library/mimxrt.Encoder.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Example usage::
2727
Constructors
2828
------------
2929

30-
.. class:: Encoder(id, phase_a, phase_b, *, home, match_pin, filter_ns, cpc, signed, index)
30+
.. class:: Encoder(id, phase_a, phase_b, *, home, match_pin, filter_ns, cpc, signed, index, phases)
3131
:no-index:
3232

3333
Construct and return a new quadrature encoder object using the following parameters:
@@ -72,6 +72,10 @@ Constructors
7272
- *index*\=value. A Pin specifier telling to which pin the index pulse is connected.
7373
At a rising slope of the index pulse the position counter is set to the init value
7474
and the cycles counter is increased by one. A *value* of *None* disables the index input.
75+
- *phases* specifies the number of signal edges to count and thus the
76+
granularity of the decoding. e.g. 4 phases corresponds to "4x quadrature
77+
decoding", and will result in four counts per pulse. Ports may support
78+
either 1, 2, or 4 phases and the default is 4 phase. *(Supported on MIMXRT)*
7579

7680
The arguments phase_a, phase_b and filter_ns are generic across ports, all other arguments are port-specific.
7781

ports/mimxrt/machine_encoder.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ typedef struct _machine_encoder_obj_t {
4949
uint8_t mode;
5050
bool is_signed;
5151
uint8_t match_pin;
52+
uint8_t phases_inv;
5253
uint32_t cpc;
5354
uint32_t filter;
5455
uint16_t status;
@@ -403,7 +404,7 @@ static void mp_machine_encoder_init_helper_common(machine_encoder_obj_t *self,
403404
static void mp_machine_encoder_init_helper(machine_encoder_obj_t *self,
404405
size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
405406
enum { ARG_phase_a, ARG_phase_b, ARG_home,
406-
ARG_match_pin, ARG_filter_ns, ARG_cpc, ARG_signed, ARG_index};
407+
ARG_match_pin, ARG_filter_ns, ARG_cpc, ARG_signed, ARG_index, ARG_phases};
407408

408409
static const mp_arg_t allowed_args[] = {
409410
{ MP_QSTR_phase_a, MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
@@ -414,6 +415,7 @@ static void mp_machine_encoder_init_helper(machine_encoder_obj_t *self,
414415
{ MP_QSTR_cpc, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} },
415416
{ MP_QSTR_signed, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
416417
{ MP_QSTR_index, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_INT(-1)} },
418+
{ MP_QSTR_phases, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 4} },
417419
};
418420
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
419421
mp_arg_parse_all(n_args, pos_args, kw_args,
@@ -442,6 +444,12 @@ static void mp_machine_encoder_init_helper(machine_encoder_obj_t *self,
442444
}
443445
}
444446

447+
// Get the Phases argument
448+
if ((args[ARG_phases].u_int != 1) && (args[ARG_phases].u_int != 2) && (args[ARG_phases].u_int != 4)) {
449+
mp_raise_ValueError(MP_ERROR_TEXT("invalid value for phases"));
450+
}
451+
self->phases_inv = 4 / args[ARG_phases].u_int;
452+
445453
// Set the common options
446454
mp_machine_encoder_init_helper_common(self, args + ARG_match_pin, &self->enc_config);
447455

@@ -552,7 +560,7 @@ static mp_obj_t machine_encoder_value(size_t n_args, const mp_obj_t *args) {
552560
uint32_t actual_value = ENC_GetPositionValue(self->instance);
553561
if (n_args > 1) {
554562
// Set the encoder position value and clear the rev counter.
555-
uint32_t value = mp_obj_int_get_truncated(args[1]);
563+
uint32_t value = mp_obj_int_get_truncated(args[1]) * self->phases_inv;
556564
clear_encoder_registers(self);
557565
// Set the position and rev register
558566
ENC_SetInitialPositionValue(self->instance, value);
@@ -562,9 +570,13 @@ static mp_obj_t machine_encoder_value(size_t n_args, const mp_obj_t *args) {
562570
}
563571
// Get the position as signed or unsigned 32 bit value.
564572
if (self->is_signed) {
565-
return mp_obj_new_int((int32_t)actual_value);
573+
int32_t value = (int32_t)actual_value;
574+
if (value < 0) {
575+
value -= (self->phases_inv - 1);
576+
}
577+
return mp_obj_new_int(value / self->phases_inv);
566578
} else {
567-
return mp_obj_new_int_from_uint(actual_value);
579+
return mp_obj_new_int_from_uint(actual_value / self->phases_inv);
568580
}
569581
}
570582
static MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_encoder_value_obj, 1, 2, machine_encoder_value);
@@ -751,6 +763,7 @@ static mp_obj_t mp_machine_counter_make_new(const mp_obj_type_t *type, size_t n_
751763
self->irq = NULL;
752764
self->match_pin = 0;
753765
self->is_signed = true;
766+
self->phases_inv = 1;
754767
self->mode = MODE_COUNTER;
755768

756769
// Set defaults for ENC Config

tests/extmod_hardware/machine_encoder.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ def setUp(self):
4545
out0_pin(0)
4646
out1_pin(0)
4747
self.enc = Encoder(id, in0_pin, in1_pin, phases=1)
48-
self.pulses = 0 # track the expected encoder position in software
4948
self.pulses = start_value # track the expected encoder position in software
5049

5150
def tearDown(self):

0 commit comments

Comments
 (0)