6
6
*/
7
7
8
8
#include < ESP32Encoder.h>
9
+ #include < soc/pcnt_struct.h>
10
+ #include " esp_log.h"
11
+
12
+ static const char * TAG = " ESP32Encoder" ;
13
+
9
14
10
15
// static ESP32Encoder *gpio2enc[48];
11
16
//
12
17
//
13
18
enum puType ESP32Encoder::useInternalWeakPullResistors=DOWN;
14
- ESP32Encoder *ESP32Encoder::encoders[MAX_ESP32_ENCODERS] = { NULL , NULL , NULL ,
15
- NULL ,
16
- NULL , NULL , NULL , NULL };
19
+ ESP32Encoder *ESP32Encoder::encoders[MAX_ESP32_ENCODERS] = { NULL , };
17
20
18
21
bool ESP32Encoder::attachedInterrupt=false ;
19
22
pcnt_isr_handle_t ESP32Encoder::user_isr_handle = NULL ;
20
23
21
- ESP32Encoder::ESP32Encoder () {
22
- attached = false ;
23
- aPinNumber = (gpio_num_t ) 0 ;
24
- bPinNumber = (gpio_num_t ) 0 ;
25
- working = false ;
26
- direction = false ;
27
- unit = (pcnt_unit_t ) -1 ;
24
+ ESP32Encoder::ESP32Encoder (bool always_interrupt_, enc_isr_cb_t enc_isr_cb, void * enc_isr_cb_data):
25
+ always_interrupt{always_interrupt_},
26
+ aPinNumber{(gpio_num_t ) 0 },
27
+ bPinNumber{(gpio_num_t ) 0 },
28
+ unit{(pcnt_unit_t ) -1 },
29
+ fullQuad{false },
30
+ countsMode{2 },
31
+ count{0 },
32
+ r_enc_config{},
33
+ _enc_isr_cb (enc_isr_cb),
34
+ _enc_isr_cb_data(enc_isr_cb_data),
35
+ attached{false },
36
+ direction{false },
37
+ working{false }
38
+ {
28
39
}
29
40
30
- ESP32Encoder::~ESP32Encoder () {
31
- // TODO Auto-generated destructor stub
32
- }
41
+ ESP32Encoder::~ESP32Encoder () {}
33
42
34
43
/* Decode what PCNT's unit originated an interrupt
35
44
* and pass this information together with the event type
36
45
* the main program using a queue.
37
46
*/
38
- static void IRAM_ATTR pcnt_example_intr_handler (void *arg) {
39
- ESP32Encoder * ptr;
40
-
47
+ #ifdef CONFIG_IDF_TARGET_ESP32S2
48
+ #define COUNTER_H_LIM cnt_thr_h_lim_lat_un
49
+ #define COUNTER_L_LIM cnt_thr_l_lim_lat_un
50
+ #define thres0_lat cnt_thr_thres0_lat_un
51
+ #define thres1_lat cnt_thr_thres1_lat_un
52
+
53
+ #elif CONFIG_IDF_TARGET_ESP32S3
54
+ #define COUNTER_H_LIM cnt_thr_h_lim_lat_un
55
+ #define COUNTER_L_LIM cnt_thr_l_lim_lat_un
56
+ #define thres0_lat cnt_thr_thres0_lat_un
57
+ #define thres1_lat cnt_thr_thres1_lat_un
58
+ #else
59
+ #define COUNTER_H_LIM h_lim_lat
60
+ #define COUNTER_L_LIM l_lim_lat
61
+ #endif
62
+
63
+
64
+
65
+ static void IRAM_ATTR esp32encoder_pcnt_intr_handler (void *arg) {
66
+ ESP32Encoder * esp32enc = {};
41
67
uint32_t intr_status = PCNT.int_st .val ;
42
- int i;
43
-
44
- for (i = 0 ; i < PCNT_UNIT_MAX; i++) {
68
+ for (uint8_t i = 0 ; i < PCNT_UNIT_MAX; i++) {
45
69
if (intr_status & (BIT (i))) {
46
- ptr = ESP32Encoder::encoders[i];
47
- /* Save the PCNT event type that caused an interrupt
48
- to pass it to the main program */
49
-
50
- int64_t status=0 ;
51
- if (PCNT.status_unit [i].h_lim_lat ){
52
- status=ptr->r_enc_config .counter_h_lim ;
53
- }
54
- if (PCNT.status_unit [i].l_lim_lat ){
55
- status=ptr->r_enc_config .counter_l_lim ;
70
+ pcnt_unit_t unit = static_cast <pcnt_unit_t >(i);
71
+ esp32enc = ESP32Encoder::encoders[i];
72
+ if (PCNT.status_unit [i].COUNTER_H_LIM ){
73
+ esp32enc->count += esp32enc->r_enc_config .counter_h_lim ;
74
+ pcnt_counter_clear (unit);
75
+ } else if (PCNT.status_unit [i].COUNTER_L_LIM ){
76
+ esp32enc->count += esp32enc->r_enc_config .counter_l_lim ;
77
+ pcnt_counter_clear (unit);
78
+ } else if (esp32enc->always_interrupt && (PCNT.status_unit [i].thres0_lat || PCNT.status_unit [i].thres1_lat )) {
79
+ int16_t c;
80
+ pcnt_get_counter_value (unit, &c);
81
+ esp32enc->count += c;
82
+ pcnt_set_event_value (unit, PCNT_EVT_THRES_0, -1 );
83
+ pcnt_set_event_value (unit, PCNT_EVT_THRES_1, 1 );
84
+ pcnt_event_enable (unit, PCNT_EVT_THRES_0);
85
+ pcnt_event_enable (unit, PCNT_EVT_THRES_1);
86
+ pcnt_counter_clear (unit);
87
+ if (esp32enc->_enc_isr_cb ) {
88
+ esp32enc->_enc_isr_cb (esp32enc->_enc_isr_cb_data );
89
+ }
56
90
}
57
- // pcnt_counter_clear(ptr->unit);
58
91
PCNT.int_clr .val = BIT (i); // clear the interrupt
59
- ptr->count = status + ptr->count ;
60
92
}
61
93
}
62
94
}
63
95
96
+
97
+
98
+
99
+
100
+ void ESP32Encoder::detatch (){
101
+ pcnt_counter_pause (unit);
102
+ ESP32Encoder::encoders[unit]=NULL ;
103
+
104
+ }
64
105
void ESP32Encoder::attach (int a, int b, enum encType et) {
65
106
if (attached) {
66
- Serial. println ( " All ready attached, FAIL! " );
107
+ ESP_LOGE (TAG, " attach: already attached" );
67
108
return ;
68
109
}
69
110
int index = 0 ;
@@ -74,7 +115,7 @@ void ESP32Encoder::attach(int a, int b, enum encType et) {
74
115
}
75
116
}
76
117
if (index == MAX_ESP32_ENCODERS) {
77
- Serial. println ( " Too many encoders, FAIL!" );
118
+ ESP_LOGE (TAG, " Too many encoders, FAIL!" );
78
119
return ;
79
120
}
80
121
@@ -149,30 +190,32 @@ void ESP32Encoder::attach(int a, int b, enum encType et) {
149
190
r_enc_config .counter_h_lim = _INT16_MAX;
150
191
r_enc_config .counter_l_lim = _INT16_MIN ;
151
192
152
- pcnt_unit_config (&r_enc_config);
193
+ pcnt_unit_config (&r_enc_config);
153
194
}
154
195
155
-
156
196
// Filter out bounces and noise
157
- pcnt_set_filter_value (unit, 250 ); // Filter Runt Pulses
158
- pcnt_filter_enable (unit);
159
-
197
+ setFilter (250 ); // Filter Runt Pulses
160
198
161
- /* Enable events on maximum and minimum limit values */
199
+ /* Enable events on maximum and minimum limit values */
162
200
pcnt_event_enable (unit, PCNT_EVT_H_LIM);
163
201
pcnt_event_enable (unit, PCNT_EVT_L_LIM);
164
-
165
202
pcnt_counter_pause (unit); // Initial PCNT init
166
- pcnt_counter_clear (unit);
167
203
/* Register ISR handler and enable interrupts for PCNT unit */
168
- if (attachedInterrupt==false ){
169
- attachedInterrupt=true ;
170
- esp_err_t er = pcnt_isr_register (pcnt_example_intr_handler,(void *) NULL , (int )0 ,
204
+ if (! attachedInterrupt){
205
+ esp_err_t er = pcnt_isr_register (esp32encoder_pcnt_intr_handler,(void *) NULL , (int )0 ,
171
206
(pcnt_isr_handle_t *)&ESP32Encoder::user_isr_handle);
172
207
if (er != ESP_OK){
173
- Serial. println ( " Encoder wrap interupt failed" );
208
+ ESP_LOGE (TAG, " Encoder wrap interrupt failed" );
174
209
}
210
+ attachedInterrupt=true ;
211
+ }
212
+ if (always_interrupt){
213
+ pcnt_set_event_value (unit, PCNT_EVT_THRES_0, -1 );
214
+ pcnt_set_event_value (unit, PCNT_EVT_THRES_1, 1 );
215
+ pcnt_event_enable (unit, PCNT_EVT_THRES_0);
216
+ pcnt_event_enable (unit, PCNT_EVT_THRES_1);
175
217
}
218
+ pcnt_counter_clear (unit);
176
219
pcnt_intr_enable (unit);
177
220
pcnt_counter_resume (unit);
178
221
@@ -198,7 +241,7 @@ int64_t ESP32Encoder::getCountRaw() {
198
241
return c;
199
242
}
200
243
int64_t ESP32Encoder::getCount () {
201
- return getCountRaw () + count ;
244
+ return count + getCountRaw () ;
202
245
}
203
246
204
247
int64_t ESP32Encoder::clearCount () {
@@ -214,3 +257,13 @@ int64_t ESP32Encoder::resumeCount() {
214
257
return pcnt_counter_resume (unit);
215
258
}
216
259
260
+ void ESP32Encoder::setFilter (uint16_t value) {
261
+ if (value>1023 )value=1023 ;
262
+ if (value==0 ) {
263
+ pcnt_filter_disable (unit);
264
+ } else {
265
+ pcnt_set_filter_value (unit, value);
266
+ pcnt_filter_enable (unit);
267
+ }
268
+
269
+ }
0 commit comments