You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
3.0 KiB

/* interrupt routine for Rotary Encoders
7 years ago
idea from: https://github.com/marcmerlin/IoTuz/blob/95f53be6569c68f7fbef491bb36082870f82d629/IoTuz.cpp
*/
#include "rotary.h"
7 years ago
#include "freertos/task.h"
//using namespace std;
7 years ago
Rotary* Rotary::instance = NULL;
Rotary::Rotary() {
instance = this;
}
bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) {
this->pinA = pinA;
this->pinB = pinB;
this->pinButton = pinButton;
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(pinButton, INPUT_PULLUP);
xTaskCreate(
&cTaskWrapper, /* Task function. */
"encoderTask", /* String with name of task. */
1024, /* Stack size in words. */
this, /* Parameter passed as input of the task */
tskIDLE_PRIORITY+2, /* Priority of the task. */
&taskHandle); /* Task handle. */
7 years ago
attachInterrupt(digitalPinToInterrupt(pinA), doEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(pinB), doEncoder, CHANGE);
return true;
}
void Rotary::cTaskWrapper(void* parameters) {
static_cast<Rotary*>(parameters)->task(NULL);
}
void Rotary::task(void *pvParameters) {
7 years ago
xTaskToNotify = xTaskGetCurrentTaskHandle();
uint32_t ulNotificationValue;
while(true) {
7 years ago
ulNotificationValue = ulTaskNotifyTake( pdTRUE, portMAX_DELAY );
delay(2); // wait until bounce settled
static uint8_t old_AB = 0;
// grey code
// http://hades.mech.northwestern.edu/index.php/Rotary_Encoder
// also read up on 'Understanding Quadrature Encoded Signals'
// https://www.pjrc.com/teensy/td_libs_Encoder.html
// another interesting lib: https://github.com/0xPIT/encoder/blob/arduino/ClickEncoder.cpp
static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
old_AB <<= 2;
old_AB |= ((digitalRead(pinB))?(1<<1):0) | ((digitalRead(pinA))?(1<<0):0);
encoderPos += ( enc_states[( old_AB & 0x0f )]);
ulNotificationValue = ulTaskNotifyTake( pdTRUE, 0 ); // clear pending notifications
debouncePulses++;
7 years ago
if (debouncePulses > 3) { // update every 4 pulses
debouncePulses = 0;
7 years ago
if (encoderPos > encoderPosOld+1) {
value++; // if the value has at least changed for 2
if (callback) callback(value, 1);
} else if (encoderPos < encoderPosOld-1) {
value--;
if (callback) callback(value, -1);
}
// otherwise skip
7 years ago
encoderPosOld = encoderPos;
}
7 years ago
}
vTaskDelete(NULL);
}
7 years ago
bool Rotary::registerCallback(std::function<void(int, int)> callback) {
this->callback = callback;
return true;
}
7 years ago
// Interrupt on changing state
void Rotary::doEncoder() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
configASSERT( instance->xTaskToNotify != NULL );
vTaskNotifyGiveFromISR( instance->xTaskToNotify, &xHigherPriorityTaskWoken );
portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}