Skip to content

Commit 18e463c

Browse files
committed
add pcnt overflow handler & clean-up
1 parent f2824f6 commit 18e463c

File tree

2 files changed

+57
-37
lines changed

2 files changed

+57
-37
lines changed

ports/esp32s2/common-hal/frequencyio/FrequencyIn.c

Lines changed: 55 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,21 @@
2626

2727
#include "shared-bindings/frequencyio/FrequencyIn.h"
2828

29-
#include <stdint.h>
30-
3129
#include "py/runtime.h"
3230

33-
#include "supervisor/shared/tick.h"
34-
#include "shared-bindings/time/__init__.h"
31+
static void IRAM_ATTR pcnt_overflow_handler(void *self_in) {
32+
frequencyio_frequencyin_obj_t* self = self_in;
33+
// reset counter
34+
pcnt_counter_clear(self->unit);
3535

36-
#include "common-hal/microcontroller/Pin.h"
36+
// increase multiplier
37+
self->multiplier++;
38+
39+
// reset interrupt
40+
PCNT.int_clr.val = BIT(self->unit);
41+
}
3742

38-
static void IRAM_ATTR frequencyin_interrupt_handler(void *self_in) {
43+
static void IRAM_ATTR timer_interrupt_handler(void *self_in) {
3944
frequencyio_frequencyin_obj_t* self = self_in;
4045
// get counter value
4146
int16_t count;
@@ -50,9 +55,41 @@ static void IRAM_ATTR frequencyin_interrupt_handler(void *self_in) {
5055
TIMERG0.hw_timer[0].config.alarm_en = 1;
5156
}
5257

53-
static void init_timer(frequencyio_frequencyin_obj_t* self, uint16_t capture_period) {
58+
static void init_pcnt(frequencyio_frequencyin_obj_t* self) {
59+
// Prepare configuration for the PCNT unit
60+
const pcnt_config_t pcnt_config = {
61+
// Set PCNT input signal and control GPIOs
62+
.pulse_gpio_num = self->pin,
63+
.ctrl_gpio_num = PCNT_PIN_NOT_USED,
64+
.channel = PCNT_CHANNEL_0,
65+
// What to do on the positive / negative edge of pulse input?
66+
.pos_mode = PCNT_COUNT_INC, // count both rising and falling edges
67+
.neg_mode = PCNT_COUNT_INC,
68+
// Set counter limit
69+
.counter_h_lim = INT16_MAX,
70+
.counter_l_lim = 0,
71+
};
72+
73+
// Initialize PCNT unit
74+
const int8_t unit = peripherals_pcnt_init(pcnt_config);
75+
if (unit == -1) {
76+
mp_raise_RuntimeError(translate("All PCNT units in use"));
77+
}
78+
79+
// set the GPIO back to high-impedance, as pcnt_unit_config sets it as pull-up
80+
gpio_set_pull_mode(self->pin, GPIO_FLOATING);
81+
82+
self->unit = (pcnt_unit_t)unit;
83+
84+
// enable pcnt interrupt
85+
pcnt_event_enable(self->unit, PCNT_EVT_H_LIM);
86+
pcnt_isr_register(pcnt_overflow_handler, (void *)self, ESP_INTR_FLAG_IRAM, &self->handle);
87+
pcnt_intr_enable(self->unit);
88+
}
89+
90+
static void init_timer(frequencyio_frequencyin_obj_t* self) {
5491
// Prepare configuration for the timer module
55-
timer_config_t config = {
92+
const timer_config_t config = {
5693
.alarm_en = true,
5794
.counter_en = false,
5895
.intr_type = TIMER_INTR_LEVEL,
@@ -64,9 +101,9 @@ static void init_timer(frequencyio_frequencyin_obj_t* self, uint16_t capture_per
64101
// Initialize timer module
65102
timer_init(TIMER_GROUP_0, TIMER_0, &config);
66103
timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0);
67-
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, capture_period * 1000000);
104+
timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, self->capture_period * 1000000);
105+
timer_isr_register(TIMER_GROUP_0, TIMER_0, timer_interrupt_handler, (void *)self, ESP_INTR_FLAG_IRAM, &self->handle);
68106
timer_enable_intr(TIMER_GROUP_0, TIMER_0);
69-
timer_isr_register(TIMER_GROUP_0, TIMER_0, frequencyin_interrupt_handler, (void *)self, ESP_INTR_FLAG_IRAM, &self->handle);
70107

71108
// Start timer
72109
timer_start(TIMER_GROUP_0, TIMER_0);
@@ -78,33 +115,15 @@ void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t*
78115
mp_raise_ValueError(translate("Invalid capture period. Valid range: 1 - 500"));
79116
}
80117

81-
// Prepare configuration for the PCNT unit
82-
const pcnt_config_t pcnt_config = {
83-
// Set PCNT input signal and control GPIOs
84-
.pulse_gpio_num = pin->number,
85-
.ctrl_gpio_num = PCNT_PIN_NOT_USED,
86-
.channel = PCNT_CHANNEL_0,
87-
// What to do on the positive / negative edge of pulse input?
88-
.pos_mode = PCNT_COUNT_INC, // count both rising and falling edges
89-
.neg_mode = PCNT_COUNT_INC,
90-
};
91-
92-
// Initialize PCNT unit
93-
const int8_t unit = peripherals_pcnt_init(pcnt_config);
94-
if (unit == -1) {
95-
mp_raise_RuntimeError(translate("All PCNT units in use"));
96-
}
97-
98-
// set the GPIO back to high-impedance, as pcnt_unit_config sets it as pull-up
99-
gpio_set_pull_mode(pin->number, GPIO_FLOATING);
100-
101-
// initialize timer
102-
init_timer(self, capture_period);
103-
104118
self->pin = pin->number;
105-
self->unit = (pcnt_unit_t)unit;
119+
self->handle = NULL;
120+
self->multiplier = 0;
106121
self->capture_period = capture_period;
107122

123+
// initialize pcnt and timer
124+
init_pcnt(self);
125+
init_timer(self);
126+
108127
claim_pin(pin);
109128
}
110129

@@ -118,15 +137,15 @@ void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* se
118137
}
119138
reset_pin_number(self->pin);
120139
peripherals_pcnt_deinit(&self->unit);
140+
timer_deinit(TIMER_GROUP_0, TIMER_0);
121141
if (self->handle) {
122-
timer_deinit(TIMER_GROUP_0, TIMER_0);
123142
esp_intr_free(self->handle);
124143
self->handle = NULL;
125144
}
126145
}
127146

128147
uint32_t common_hal_frequencyio_frequencyin_get_item(frequencyio_frequencyin_obj_t* self) {
129-
return self->frequency;
148+
return (self->frequency + (self->multiplier * INT16_MAX));
130149
}
131150

132151
void common_hal_frequencyio_frequencyin_pause(frequencyio_frequencyin_obj_t* self) {

ports/esp32s2/common-hal/frequencyio/FrequencyIn.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ typedef struct {
3636
pcnt_unit_t unit;
3737
intr_handle_t handle;
3838
uint8_t pin;
39-
uint32_t frequency;
39+
uint8_t multiplier;
40+
uint16_t frequency;
4041
uint16_t capture_period;
4142
} frequencyio_frequencyin_obj_t;
4243

0 commit comments

Comments
 (0)