Skip to content

Add espressif rotaryio divisor support. #6207

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -3126,10 +3126,6 @@ msgstr ""
msgid "division by zero"
msgstr ""

#: ports/espressif/common-hal/rotaryio/IncrementalEncoder.c
msgid "divisor must be 4"
msgstr ""

#: extmod/ulab/code/numpy/vector.c
msgid "dtype must be float, or complex"
msgstr ""
Expand Down
37 changes: 28 additions & 9 deletions ports/espressif/common-hal/rotaryio/IncrementalEncoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,14 @@
#include "common-hal/microcontroller/Pin.h"

#include "py/runtime.h"
#include "supervisor/shared/translate.h"

void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencoder_obj_t *self,
const mcu_pin_obj_t *pin_a, const mcu_pin_obj_t *pin_b) {
claim_pin(pin_a);
claim_pin(pin_b);

// Prepare configuration for the PCNT unit
const pcnt_config_t pcnt_config = {
pcnt_config_t pcnt_config = {
// Set PCNT input signal and control GPIOs
.pulse_gpio_num = pin_a->number,
.ctrl_gpio_num = pin_b->number,
Expand All @@ -51,11 +50,32 @@ void common_hal_rotaryio_incrementalencoder_construct(rotaryio_incrementalencode
};

// Initialize PCNT unit
const int8_t unit = peripherals_pcnt_init(pcnt_config);
const int8_t unit = peripherals_pcnt_get_unit(pcnt_config);
if (unit == -1) {
mp_raise_RuntimeError(translate("All PCNT units in use"));
}

pcnt_unit_config(&pcnt_config);

pcnt_config.pulse_gpio_num = pin_b->number; // What was control is now signal
pcnt_config.ctrl_gpio_num = pin_a->number; // What was signal is now control
pcnt_config.channel = PCNT_CHANNEL_1;
// What to do on the positive / negative edge of pulse input?
pcnt_config.pos_mode = PCNT_COUNT_DEC; // Count up on the positive edge
pcnt_config.neg_mode = PCNT_COUNT_INC; // Keep the counter value on the negative edge
// What to do when control input is low or high?
pcnt_config.lctrl_mode = PCNT_MODE_KEEP; // Keep the primary counter mode if low
pcnt_config.hctrl_mode = PCNT_MODE_REVERSE; // Reverse counting direction if high

pcnt_unit_config(&pcnt_config);

// Initialize PCNT's counter
pcnt_counter_pause(pcnt_config.unit);
pcnt_counter_clear(pcnt_config.unit);

// Everything is set up, now go to counting
pcnt_counter_resume(pcnt_config.unit);

self->pin_a = pin_a->number;
self->pin_b = pin_b->number;
self->unit = (pcnt_unit_t)unit;
Expand All @@ -77,21 +97,20 @@ void common_hal_rotaryio_incrementalencoder_deinit(rotaryio_incrementalencoder_o
mp_int_t common_hal_rotaryio_incrementalencoder_get_position(rotaryio_incrementalencoder_obj_t *self) {
int16_t count;
pcnt_get_counter_value(self->unit, &count);
return (count / 2) + self->position;

return (count + self->position) / self->divisor;
}

void common_hal_rotaryio_incrementalencoder_set_position(rotaryio_incrementalencoder_obj_t *self,
mp_int_t new_position) {
self->position = new_position;
self->position = new_position * self->divisor;
pcnt_counter_clear(self->unit);
}

mp_int_t common_hal_rotaryio_incrementalencoder_get_divisor(rotaryio_incrementalencoder_obj_t *self) {
return 4;
return self->divisor;
}

void common_hal_rotaryio_incrementalencoder_set_divisor(rotaryio_incrementalencoder_obj_t *self, mp_int_t divisor) {
if (divisor != 4) {
mp_raise_ValueError(translate("divisor must be 4"));
}
self->divisor = divisor;
}
1 change: 1 addition & 0 deletions ports/espressif/common-hal/rotaryio/IncrementalEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ typedef struct {
uint8_t pin_a, pin_b;
mp_int_t position;
pcnt_unit_t unit;
int8_t divisor; // Number of quadrature edges required per count
} rotaryio_incrementalencoder_obj_t;

#endif // MICROPY_INCLUDED_ESPRESSIF_COMMON_HAL_ROTARYIO_INCREMENTALENCODER_H
13 changes: 12 additions & 1 deletion ports/espressif/peripherals/pcnt.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ void peripherals_pcnt_reset(void) {
}
}

int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
int peripherals_pcnt_get_unit(pcnt_config_t pcnt_config) {
// Look for available pcnt unit
for (uint8_t i = 0; i <= 3; i++) {
if (pcnt_unit_state[i] == PCNT_UNIT_INACTIVE) {
Expand All @@ -49,6 +49,17 @@ int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
}
}

return pcnt_config.unit;
}

int peripherals_pcnt_init(pcnt_config_t pcnt_config) {
// Look for available pcnt unit

const int8_t unit = peripherals_pcnt_get_unit(pcnt_config);
if (unit == -1) {
return -1;
}

// Initialize PCNT unit
pcnt_unit_config(&pcnt_config);

Expand Down
1 change: 1 addition & 0 deletions ports/espressif/peripherals/pcnt.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "soc/pcnt_struct.h"

extern int peripherals_pcnt_init(pcnt_config_t pcnt_config);
extern int peripherals_pcnt_get_unit(pcnt_config_t pcnt_config);
extern void peripherals_pcnt_deinit(pcnt_unit_t *unit);
extern void peripherals_pcnt_reset(void);

Expand Down
2 changes: 1 addition & 1 deletion shared-bindings/rotaryio/IncrementalEncoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ STATIC mp_obj_t rotaryio_incrementalencoder_make_new(const mp_obj_type_t *type,
self->base.type = &rotaryio_incrementalencoder_type;

common_hal_rotaryio_incrementalencoder_construct(self, pin_a, pin_b);

common_hal_rotaryio_incrementalencoder_set_divisor(self, args[ARG_divisor].u_int);

return MP_OBJ_FROM_PTR(self);
}

Expand Down