8000 mimxrt: Support Encoder/Counter for the MIMXRT117x family. · micropython/micropython@4111eb0 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4111eb0

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

File tree

2 files changed

+127
-30
lines changed

2 files changed

+127
-30
lines changed

docs/mimxrt/quickref.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -554,17 +554,17 @@ Example usage::
554554

555555
qe = Encoder(0, Pin(0), Pin(1)) # create Quadrature Encoder object
556556
qe.value() # get current counter values
557-
qe.value(0) # Set value and cycles to 0
558-
qe.init(cpc=128) # Specify 128 counts/cycle
559-
qe.init(index=Pin(3)) # Specify Pin 3 as Index pulse input
557+
qe.value(0) # set value and cycles to 0
558+
qe.init(cpc=128) # specify 128 counts/cycle
559+
qe.init(index=Pin(3)) # specify Pin 3 as Index pulse input
560560
qe.deinit() # turn off the Quadrature Encoder
561-
qe.init(match=64) # Set a match event at count 64
561+
qe.init(match=64) # set a match event at count 64
562562
qe.irq(qe.IRQ_MATCH, value=100, handler=handler)
563-
# Call the function handler at a match event
563+
# call the function handler at a match event
564564

565565
qe # show the Encoder object properties
566566

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

@@ -583,15 +583,15 @@ Example usage::
583583

584584
counter = Counter(0, Pin(0)) # create Counter object
585585
counter.value() # get current counter value
586-
counter.value(0) # Set the counter to 0
587-
counter.init(cpc=128) # Specify 128 counts/cycle
586+
counter.value(0) # set the counter to 0
587+
counter.init(cpc=128) # specify 128 counts/cycle
588588
counter.deinit() # turn off the Counter
589-
counter.init(match=1000) # Create a match event at count 1000
590-
counter.irq(Counter.IRQ_MATCH, handler) # Call the function handler at a counter match
589+
counter.init(match=1000) # create a match event at count 1000
590+
counter.irq(Counter.IRQ_MATCH, handler) # call the function handler at a counter match
591591

592592
counter # show the Counter object properties
593593

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

ports/mimxrt/machine_encoder.c

Lines changed: 116 additions & 19 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;
@@ -172,7 +219,7 @@ STATIC void mp_machine_encoder_print(const mp_print_t *print, mp_obj_t self_in,
172219
self->id, self->cpc, self->enc_config.positionCompareValue, self->filter);
173220
}
174221

175-
// Utililty functions
222+
// Utility functions
176223
//
177224

178225
STATIC void encoder_set_iomux(const machine_pin_obj_t *pin, const machine_pin_af_obj_t *af) {
@@ -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_kh F438 z = 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)
0