-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathesp32qep.cpp
94 lines (76 loc) · 2.23 KB
/
esp32qep.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/* ESP32QEP
*
* AUTHOR: Raphael Rätz
* EMAIL: raphael.raetz@hotmail.com
*/
// Includes
#include "esp32qep.h"
#include "freertos/task.h"
// Global (static) variable
static QEP qep;
// Initialization function, enable interrupts from core 1
bool QEP_initialize(uint8_t pinA, uint8_t pinB)
{
qep.pinA = pinA;
qep.pinB = pinB;
qep.counter = 0;
qep.queue = xQueueCreate(1, sizeof(int32_t));
if (qep.queue == NULL) {return false;}
else
{
pinMode(qep.pinA, INPUT_PULLUP);
pinMode(qep.pinB, INPUT_PULLUP);
xTaskCreatePinnedToCore(QEP_setupInterrupts, "qepTask", 1024, NULL, 0, NULL, 1);
return true;
}
}
// Enable the interrupts
void QEP_setupInterrupts(void* parameter)
{
attachInterrupt(qep.pinA, QEP_interruptA, CHANGE);
attachInterrupt(qep.pinB, QEP_interruptB, CHANGE);
vTaskDelete(NULL);
}
// Interrupt after change on pin A, on IRAM for speed
void IRAM_ATTR QEP_interruptA()
{
int pinA = (GPIO.in >> qep.pinA) & 0x1;
int pinB = (GPIO.in >> qep.pinB) & 0x1;
if (pinA == pinB) {qep.counter++;}
else {qep.counter--;}
xQueueOverwriteFromISR(qep.queue, (int32_t*)&qep.counter, pdFALSE);
}
// Interrupt after change on pin B, on IRAM for speed
void IRAM_ATTR QEP_interruptB()
{
int pinA = (GPIO.in >> qep.pinA) & 0x1;
int pinB = (GPIO.in >> qep.pinB) & 0x1;
if (pinA == pinB) {qep.counter--;}
else {qep.counter++;}
xQueueOverwriteFromISR(qep.queue, (int32_t*)&qep.counter, pdFALSE);
}
// Get the encoder tick count via queue, thread/interrupt safe
int32_t QEP_getCounter()
{
static int32_t counter = 0;
if (uxQueueMessagesWaiting(qep.queue) > 0)
{
xQueueReceive(qep.queue, &counter, portMAX_DELAY);
}
return counter;
}
// Run counter reset task on core 1
void QEP_resetCounter()
{
xTaskCreatePinnedToCore(QEP_resetCounterTask, "qepTask", 1024, NULL, 0, NULL, 1);
}
// Disable interrups, reset counter and re-enable interrupts
void QEP_resetCounterTask(void* parameter)
{
detachInterrupt(qep.pinA);
detachInterrupt(qep.pinA);
qep.counter = 0;
attachInterrupt(qep.pinA, QEP_interruptA, CHANGE);
attachInterrupt(qep.pinB, QEP_interruptB, CHANGE);
vTaskDelete(NULL);
}