Skip to content

Commit 6d025a2

Browse files
committed
Add espressif rotaryio divisor support.
1 parent 8ebab76 commit 6d025a2

File tree

5 files changed

+60
-10
lines changed

5 files changed

+60
-10
lines changed

ports/espressif/common-hal/rotaryio/IncrementalEncoder.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@
2929
#include "common-hal/microcontroller/Pin.h"
3030

3131
#include "py/runtime.h"
32-
#include "supervisor/shared/translate.h"
3332

3433
void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
3534
const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) {
3635
claim_pin(pin_a);
3736
claim_pin(pin_b);
3837

3938
// Prepare configuration for the PCNT unit
40-
const pcnt_config_t pcnt_config = {
39+
pcnt_config_t pcnt_config = {
4140
// Set PCNT input signal and control GPIOs
4241
.pulse_gpio_num = pin_a->number,
4342
.ctrl_gpio_num = pin_b->number,
@@ -51,11 +50,46 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
5150
};
5251

5352
// Initialize PCNT unit
54-
const int8_t unit = peripherals_pcnt_init(pcnt_config);
53+
const int8_t unit = peripherals_pcnt_get_unit(pcnt_config);
5554
if (unit == -1) {
5655
mp_raise_RuntimeError(translate("All PCNT units in use"));
5756
}
5857

58+
pcnt_unit_config(&pcnt_config);
59+
60+
if ((self->divisor == 2) || (self->divisor == 1)) {
61+
// Setup channel 1 for divisor=2 or divisor=1
62+
pcnt_config.pulse_gpio_num = pin_b->number; // What was control is now signal
63+
pcnt_config.ctrl_gpio_num = pin_a->number; // What was signal is now control
64+
pcnt_config.channel = PCNT_CHANNEL_1;
65+
// What to do on the positive / negative edge of pulse input?
66+
pcnt_config.pos_mode = PCNT_COUNT_DEC; // Count up on the positive edge
67+
pcnt_config.neg_mode = PCNT_COUNT_INC; // Keep the counter value on the negative edge
68+
// What to do when control input is low or high?
69+
pcnt_config.lctrl_mode = PCNT_MODE_KEEP; // Keep the primary counter mode if low
70+
pcnt_config.hctrl_mode = PCNT_MODE_REVERSE; // Reverse counting direction if high
71+
} else {
72+
// Ensure channel 1 is disabled for divisor=4
73+
pcnt_config.pulse_gpio_num = pin_b->number; // What was control is now signal
74+
pcnt_config.ctrl_gpio_num = pin_a->number; // What was signal is now control
75+
pcnt_config.channel = PCNT_CHANNEL_1;
76+
// What to do on the positive / negative edge of pulse input?
77+
pcnt_config.pos_mode = PCNT_COUNT_DIS; // Disabled
78+
pcnt_config.neg_mode = PCNT_COUNT_DIS; // Disabled
79+
// What to do when control input is low or high?
80+
pcnt_config.lctrl_mode = PCNT_MODE_DISABLE; // Disabled
81+
pcnt_config.hctrl_mode = PCNT_MODE_DISABLE; // Disabled
82+
}
83+
84+
pcnt_unit_config(&pcnt_config);
85+
86+
// Initialize PCNT's counter
87+
pcnt_counter_pause(pcnt_config.unit);
88+
pcnt_counter_clear(pcnt_config.unit);
89+
90+
// Everything is set up, now go to counting
91+
pcnt_counter_resume(pcnt_config.unit);
92+
5993
self->pin_a = pin_a->number;
6094
self->pin_b = pin_b->number;
6195
self->unit = (pcnt_unit_t)unit;
@@ -77,7 +111,12 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o
77111
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self) {
78112
int16_t count;
79113
pcnt_get_counter_value(self->unit, &count);
80-
return (count / 2) + self->position;
114+
115+
if ((self->divisor == 4) || (self->divisor == 2)) {
116+
return (count / 2) + self->position;
117+
} else {
118+
return (count) + self->position;
119+
}
81120
}
82121

83122
void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self,
@@ -87,11 +126,9 @@ void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalenc
87126
}
88127

89128
mp_int_t common_hal_rotaryio_incrementalencoder_get_divisor(rotaryio_incrementalencoder_obj_t *self) {
90-
return 4;
129+
return self->divisor;
91130
}
92131

93132
void common_hal_rotaryio_incrementalencoder_set_divisor(rotaryio_incrementalencoder_obj_t *self, mp_int_t divisor) {
94-
if (divisor != 4) {
95-
mp_raise_ValueError(translate("divisor must be 4"));
96-
}
133+
self->divisor = divisor;
97134
}

ports/espressif/common-hal/rotaryio/IncrementalEncoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ typedef struct {
3535
uint8_t pin_a, pin_b;
3636
mp_int_t position;
3737
pcnt_unit_t unit;
38+
int8_t divisor; // Number of quadrature edges required per count
3839
} rotaryio_incrementalencoder_obj_t;
3940

4041
#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H

ports/espressif/peripherals/pcnt.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void peripherals_pcnt_reset(void) {
3737
}
3838
}
3939

40-
int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
40+
int peripherals_pcnt_get_unit(pcnt_config_t pcnt_config) {
4141
// Look for available pcnt unit
4242
for (uint8_t i = 0; i <= 3; i++) {
4343
if (pcnt_unit_state[i] == PCNT_UNIT_INACTIVE) {
@@ -49,6 +49,17 @@ int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
4949
}
5050
}
5151

52+
return pcnt_config.unit;
53+
}
54+
55+
int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
56+
// Look for available pcnt unit
57+
58+
const int8_t unit = peripherals_pcnt_get_unit(pcnt_config);
59+
if (unit == -1) {
60+
return -1;
61+
}
62+
5263
// Initialize PCNT unit
5364
pcnt_unit_config(&pcnt_config);
5465

ports/espressif/peripherals/pcnt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "soc/pcnt_struct.h"
3232

3333
extern int peripherals_pcnt_init(pcnt_config_t pcnt_config);
34+
extern int peripherals_pcnt_get_unit(pcnt_config_t pcnt_config);
3435
extern void peripherals_pcnt_deinit(pcnt_unit_t *unit);
3536
extern void peripherals_pcnt_reset(void);
3637

shared-bindings/rotaryio/IncrementalEncoder.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type,
7777
rotaryio_incrementalencoder_obj_t *self = m_new_obj(rotaryio_incrementalencoder_obj_t);
7878
self->base.type = &rotaryio_incrementalencoder_type;
7979

80+
common_hal_rotaryio_incrementalencoder_set_divisor(self, args[ARG_divisor].u_int);
8081
common_hal_rotaryio_incrementalencoder_construct(self, pin_a, pin_b);
8182

82-
common_hal_rotaryio_incrementalencoder_set_divisor(self, args[ARG_divisor].u_int);
8383
return MP_OBJ_FROM_PTR(self);
8484
}
8585

0 commit comments

Comments
 (0)