Skip to content

Commit 6b55548

Browse files
committed
mimxrt: Support Encoder/Counter for the MIMXRT117x family.
Signed-off-by: robert-hh <robert@hammelrath.com>
1 parent f53a2bd commit 6b55548

File tree

3 files changed

+118
-21
lines changed

3 files changed

+118
-21
lines changed

docs/mimxrt/quickref.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ Example usage::
566566

567567
qe # show the Encoder object properties
568568

569-
The Quadrature Encoder is hardware based. It available on all MIMXRT devices exept the ones
569+
The Quadrature Encoder is hardware based. It available on all MIMXRT devices except the ones
570570
based on the i.MX RT 1010 MCU. For details about using the Encoder with a MIMXRT board
571571
see :ref:`machine.Encoder <mimxrt_machine.Encoder>`:
572572

@@ -593,7 +593,7 @@ Example usage::
593593

594594
counter # show the Counter object properties
595595

596-
The Quadrature Encoder is hardware based. It available on all MIMXRT devices exept the ones
596+
The Quadrature Encoder is hardware based. It available on all MIMXRT devices except the ones
597597
based on the i.MX RT 1010 MCU. For details about using the Counter with a MIMXRT board
598598
see :ref:`machine.Counter <mimxrt_machine.Counter>`:
599599

ports/mimxrt/boards/make-pins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ def module_instance_factory(pins, output_file, name):
362362
if name == "FLEXPWM":
363363
output_file.write(f"#define {k} {k[-4:]}\n")
364364
if name == "XBAR":
365-
output_file.write(f"#define {k} {k}A1\n")
365+
output_file.write(f"#define {k} {k[:4]}A1\n")
366366
for i in v:
367367
output_file.write(i + "\n")
368368

ports/mimxrt/machine_encoder.c

Lines changed: 115 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ typedef struct _machine_encoder_obj_t {
4242
mp_obj_base_t base;
4343
ENC_Type *instance;
4444
int8_t id;
45+
bool active;
4546
uint8_t input_a;
4647
uint8_t input_b;
4748
uint8_t mode;
@@ -69,13 +70,6 @@ typedef struct _encoder_xbar_signal_t {
6970
#define ENCODER_TRIGGER_ROLL_UNDER (kENC_PositionRollUnderFlag)
7071
#define ENCODER_ALL_INTERRUPTS (0x7f)
7172

72-
#if !defined(XBAR_ENC_DIR_OFFSET)
73-
#define XBAR_ENC_DIR_OFFSET (12)
74-
#define XBAR_ENC_DIR_REGISTER GPR6
75-
#define XBAR_OUT_MIN (4)
76-
#define XBAR_OUT_MAX (19)
77-
#endif
78-
7973
#define XBAR_IN (1)
8074
#define XBAR_OUT (0)
8175

@@ -86,6 +80,58 @@ typedef struct _encoder_xbar_signal_t {
8680

8781
STATIC void encoder_deinit_single(machine_encoder_obj_t *self);
8882

83+
#if defined MIMXRT117x_SERIES
84+
85+
#define XBAR_ENC_DIR_OFFSET_1 (4)
86+
#define XBAR_ENC_DIR_REGISTER_1 GPR20
87+
#define XBAR_ENC_DIR_OFFSET_2 (32)
88+
#define XBAR_ENC_DIR_REGISTER_2 GPR21
89+
#define XBAR_OUT_MIN (4)
90+
#define XBAR_OUT_MAX (42)
91+
#define XBAR_STRING "XBAR1_INOUT"
92+
#define XBAR_STRING_LEN strlen(XBAR_STRING)
93+
94+
static encoder_xbar_signal_t xbar_signal_table[FSL_FEATURE_SOC_ENC_COUNT] = {
95+
{ kXBARA1_OutputDec1Phasea,
96+
kXBARA1_OutputDec1Phaseb,
97+
kXBARA1_OutputDec1Index,
98+
kXBARA1_OutputDec1Home,
99+
kXBARA1_OutputDec1Trigger,
100+
kXBARA1_InputDec1PosMatch },
101+
102+
{ kXBARA1_OutputDec2Phasea,
103+
kXBARA1_OutputDec2Phaseb,
104+
kXBARA1_OutputDec2Index,
105+
kXBARA1_OutputDec2Home,
106+
kXBARA1_OutputDec2Trigger,
107+
kXBARA1_InputDec2PosMatch },
108+
109+
{ kXBARA1_OutputDec3Phasea,
110+
kXBARA1_OutputDec3Phaseb,
111+
kXBARA1_OutputDec3Index,
112+
kXBARA1_OutputDec3Home,
113+
kXBARA1_OutputDec3Trigger,
114+
kXBARA1_InputDec3PosMatch },
115+
116+
{ kXBARA1_OutputDec4Phasea,
117+
kXBARA1_OutputDec4Phaseb,
118+
kXBARA1_OutputDec4Index,
119+
kXBARA1_OutputDec4Home,
120+
kXBARA1_OutputDec4Trigger,
121+
kXBARA1_InputDec4PosMatch },
122+
};
123+
124+
#else // defined MIMXRT117x_SERIES
125+
126+
#if !defined(XBAR_ENC_DIR_OFFSET)
127+
#define XBAR_ENC_DIR_OFFSET (12)
128+
#define XBAR_ENC_DIR_REGISTER GPR6
129+
#define XBAR_OUT_MIN (4)
130+
#define XBAR_OUT_MAX (19)
131+
#endif
132+
#define XBAR_STRING "XBAR_INOUT"
133+
#define XBAR_STRING_LEN strlen(XBAR_STRING)
134+
89135
static encoder_xbar_signal_t xbar_signal_table[FSL_FEATURE_SOC_ENC_COUNT] = {
90136
{ kXBARA1_OutputEnc1PhaseAInput,
91137
kXBARA1_OutputEnc1PhaseBInput,
@@ -122,6 +168,7 @@ static encoder_xbar_signal_t xbar_signal_table[FSL_FEATURE_SOC_ENC_COUNT] = {
122168
#endif
123169
#endif
124170
};
171+
#endif // defined MIMXRT117x_SERIES
125172

126173
static machine_encoder_obj_t *encoder_table[FSL_FEATURE_SOC_ENC_COUNT];
127174
static ENC_Type *enc_instances[] = ENC_BASE_PTRS;
@@ -185,13 +232,14 @@ STATIC const machine_pin_af_obj_t *af_name_decode_xbar(const machine_pin_af_obj_
185232
xbar_input_signal_t *io_number) {
186233
const char *str;
187234
size_t len;
235+
size_t xlen = XBAR_STRING_LEN;
188236
str = (char *)qstr_data(af_obj->name, &len);
189-
// test for the name starting with XBAR_INOUT
190-
if (len < 12 || strncmp(str, "XBAR_INOUT", 10) != 0) {
237+
// test for the name starting with XBAR
238+
if (len < (xlen + 2) || strncmp(str, XBAR_STRING, xlen) != 0) {
191239
return NULL;
192240
}
193241
// Get I/O number, e.g. XBAR_INOUT03
194-
*io_number = (str[10] - '0') * 10 + (str[11] - '0');
242+
*io_number = (str[xlen] - '0') * 10 + (str[xlen + 1] - '0');
195243
return af_obj;
196244
}
197245

@@ -215,12 +263,26 @@ STATIC uint8_t connect_pin_to_encoder(mp_obj_t desc, xbar_output_signal_t encode
215263
XBARA_SetSignalsConnection(XBARA1, xbar_pin, encoder_signal);
216264
} else {
217265
// No API here, so do basic Register access.
266+
#if defined MIMXRT117x_SERIES
267+
if (xbar_pin >= XBAR_OUT_MIN && xbar_pin <= XBAR_OUT_MAX) {
268+
if (xbar_pin < XBAR_ENC_DIR_OFFSET_2) {
269+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_1 |= 1 << (xbar_pin - XBAR_ENC_DIR_OFFSET_1);
270+
XBARA_SetSignalsConnection(XBARA1, encoder_signal, xbar_pin);
271+
} else {
272+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_2 |= 1 << (xbar_pin - XBAR_ENC_DIR_OFFSET_2);
273+
XBARA_SetSignalsConnection(XBARA1, encoder_signal, xbar_pin);
274+
}
275+
} else {
276+
mp_raise_ValueError(MP_ERROR_TEXT("invalid match Pin"));
277+
}
278+
#else
218279
if (xbar_pin >= XBAR_OUT_MIN && xbar_pin <= XBAR_OUT_MAX) {
219280
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER |= 1 << (xbar_pin + XBAR_ENC_DIR_OFFSET); // Compare the offset 12 with other MCU
220281
XBARA_SetSignalsConnection(XBARA1, encoder_signal, xbar_pin);
221282
} else {
222283
mp_raise_ValueError(MP_ERROR_TEXT("invalid match Pin"));
223284
}
285+
#endif // defined MIMXRT117x_SERIES
224286
}
225287
return xbar_pin;
226288
}
@@ -239,7 +301,12 @@ STATIC void clear_encoder_registers(machine_encoder_obj_t *self) {
239301
//
240302
STATIC uint32_t calc_filter(uint32_t filter_ns, uint16_t *count, uint16_t *period) {
241303

304+
#if defined MIMXRT117x_SERIES
305+
uint32_t freq_khz = CLOCK_GetRootClockFreq(kCLOCK_Root_Bus) / 1000;
306+
#else
242307
uint32_t freq_khz = CLOCK_GetIpgFreq() / 1000;
308+
#endif
309+
243310
uint32_t cycles = (filter_ns * (freq_khz / 1000)) / 1000;
244311
if (cycles == 0) {
245312
// Set filter off
@@ -277,7 +344,15 @@ STATIC void mp_machine_encoder_init_helper_common(machine_encoder_obj_t *self,
277344
self->match_pin = connect_pin_to_encoder(args[ARG_match_pin].u_obj, xbar_signal_table[self->id].enc_match, XBAR_OUT);
278345
} else {
279346
// Disconnect the XBAR from the output by switching it to an input.
347+
#if defined MIMXRT117x_SERIES
348+
if (self->match_pin < XBAR_ENC_DIR_OFFSET_2) {
349+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_1 &= ~(1 << (self->match_pin - XBAR_ENC_DIR_OFFSET_1));
350+
} else {
351+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_2 &= ~(1 << (self->match_pin - XBAR_ENC_DIR_OFFSET_2));
352+
}
353+
#else
280354
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER &= ~(1 << (self->match_pin + XBAR_ENC_DIR_OFFSET));
355+
#endif
281356
}
282357
}
283358

@@ -321,6 +396,7 @@ STATIC void mp_machine_encoder_init_helper_common(machine_encoder_obj_t *self,
321396
ENC_Init(self->instance, enc_config);
322397
clear_encoder_registers(self);
323398
ENC_ClearStatusFlags(self->instance, 0xff); // Clear all status flags
399+
self->active = true;
324400
}
325401

326402
STATIC void mp_machine_encoder_init_helper(machine_encoder_obj_t *self,
@@ -420,15 +496,26 @@ STATIC mp_obj_t mp_machine_encoder_make_new(const mp_obj_type_t *type, size_t n_
420496
}
421497

422498
STATIC void encoder_deinit_single(machine_encoder_obj_t *self) {
423-
if (self->irq->handler) {
424-
DisableIRQ(enc_irqn[self->id + 1]);
425-
ENC_DisableInterrupts(self->instance, ENCODER_ALL_INTERRUPTS);
426-
}
427-
if (self->match_pin != 0) {
428-
// Disconnect the XBAR from the output by switching it to an input.
429-
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER &= ~(1 << (self->match_pin + XBAR_ENC_DIR_OFFSET));
499+
if (self->active) {
500+
if (self->irq && self->irq->handler) {
501+
DisableIRQ(enc_irqn[self->id + 1]);
502+
ENC_DisableInterrupts(self->instance, ENCODER_ALL_INTERRUPTS);
503+
}
504+
if (self->match_pin != 0) {
505+
// Disconnect the XBAR from the output by switching it to an input.
506+
#if defined MIMXRT117x_SERIES
507+
if (self->match_pin < XBAR_ENC_DIR_OFFSET_2) {
508+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_1 &= ~(1 << (self->match_pin - XBAR_ENC_DIR_OFFSET_1));
509+
} else {
510+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER_2 &= ~(1 << (self->match_pin - XBAR_ENC_DIR_OFFSET_2));
511+
}
512+
#else
513+
IOMUXC_GPR->XBAR_ENC_DIR_REGISTER &= ~(1 << (self->match_pin + XBAR_ENC_DIR_OFFSET));
514+
#endif
515+
}
516+
ENC_Deinit(self->instance);
430517
}
431-
ENC_Deinit(self->instance);
518+
self->active = false;
432519
}
433520

434521
// encoder_deinit_all()
@@ -458,6 +545,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_encoder_status_obj, machine_encoder_sta
458545
// encoder.value([value])
459546
STATIC mp_obj_t machine_encoder_value(size_t n_args, const mp_obj_t *args) {
460547
machine_encoder_obj_t *self = MP_OBJ_TO_PTR(args[0]);
548+
if (!self->active) {
549+
mp_raise_ValueError(MP_ERROR_TEXT("device stopped"));
550+
}
461551
uint32_t actual_value = ENC_GetPositionValue(self->instance);
462552
if (n_args > 1) {
463553
// Set the encoder position value and clear the rev counter.
@@ -481,6 +571,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_encoder_value_obj, 1, 2, mach
481571
// encoder.cycles([value])
482572
STATIC mp_obj_t machine_encoder_cycles(size_t n_args, const mp_obj_t *args) {
483573
machine_encoder_obj_t *self = MP_OBJ_TO_PTR(args[0]);
574+
if (!self->active) {
575+
mp_raise_ValueError(MP_ERROR_TEXT("device stopped"));
576+
}
577+
484578
int16_t cycles = (int16_t)ENC_GetRevolutionValue(self->instance);
485579
if (n_args > 1) {
486580
// Set the revolution value
@@ -502,6 +596,9 @@ STATIC mp_obj_t machine_encoder_irq(size_t n_args, const mp_obj_t *pos_args, mp_
502596
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
503597
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
504598
machine_encoder_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
599+
if (!self->active) {
600+
mp_raise_ValueError(MP_ERROR_TEXT("device stopped"));
601+
}
505602

506603
if (self->irq == NULL) {
507604
self->irq = m_new_obj(mp_irq_obj_t);

0 commit comments

Comments
 (0)