diff --git a/platformio.ini b/platformio.ini index f8861ae..7a0ed3a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -28,4 +28,5 @@ lib_deps = https://github.com/Gianbacchio/ESP8266_Spiram.git Adafruit Unified Sensor Adafruit BME280 Library + ClickEncoder lib_ignore = ESPAsyncTCP diff --git a/src/rotary.cpp b/src/rotary.cpp index b4291c5..61d78b9 100644 --- a/src/rotary.cpp +++ b/src/rotary.cpp @@ -15,12 +15,7 @@ //using namespace std; -TaskHandle_t Rotary::xTaskToNotify = NULL; -Rotary* Rotary::instance = NULL; - -Rotary::Rotary() { - instance = this; -} +Rotary::Rotary() {} bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { this->pinA = pinA; @@ -30,112 +25,37 @@ bool Rotary::begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton) { pinMode(pinB, INPUT_PULLUP); pinMode(pinButton, INPUT_PULLUP); + encoder = new ClickEncoder(pinA, pinB, pinButton, 4); + //encoder->setButtonOnPinZeroEnabled(true); + xTaskCreate( &cTaskWrapper, /* Task function. */ - "buttonTask", /* String with name of task. */ - 2048, /* Stack size in words. */ + "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. */ - &buttonTaskHandle); /* Task handle. */ + &taskHandle); /* Task handle. */ return true; } void Rotary::cTaskWrapper(void* parameters) { - static_cast(parameters)->button_task(NULL); + static_cast(parameters)->task(NULL); } -void Rotary::button_task(void *pvParameters) { - xTaskToNotify = xTaskGetCurrentTaskHandle(); - - attachInterrupt(digitalPinToInterrupt(pinA), doEncoderA, RISING); - attachInterrupt(digitalPinToInterrupt(pinB), doEncoderB, RISING); -// attachInterrupt(digitalPinToInterrupt(pinButton), doButton, FALLING); - - uint32_t ulNotificationValue; - uint32_t ulStatusValue; - +void Rotary::task(void *pvParameters) { while(true) { - rotating = true; // reset the debouncer - - ulNotificationValue = xTaskNotifyWait(0x00, ULONG_MAX, &ulStatusValue, portMAX_DELAY ); - -// if ( rotating ) delay (1); // wait a little until the bouncing is done - - if( ulStatusValue == 1 ) { - // adjust counter + if A leads B - encoderPos += 1; - changed(); - rotating = false; // no more debouncing until loop() hits again - } else if ( ulStatusValue == 2 ) { - // adjust counter -1 if B leads A - encoderPos -= 1; - changed(); - rotating = false; // no more debouncing until loop() hits again - } else if ( ulStatusValue == 4 ) { - Button_set = digitalRead(pinButton); - - if (! Button_set ) { - encoderPos = 0; - } + encoder->service(); + value += encoder->getValue(); + if (value != last) { + last = value; + if (callback) callback(value); } - - } -} - -void Rotary::changed() { - if (lastReportedPos != encoderPos) { - if (callback) callback(encoderPos); - lastReportedPos = encoderPos; + vTaskDelay(1 / portTICK_PERIOD_MS); } + vTaskDelete(NULL); } bool Rotary::registerCallback(std::function callback) { this->callback = callback; return true; } - -void Rotary::doButton() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - - configASSERT( xTaskToNotify != NULL ); - uint32_t intrBits = 4; - xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); -} - -// Interrupt on A changing state -void Rotary::doEncoderA() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (instance->skipA) { - instance->skipA = false; - instance->debounceA = millis(); - return; - } - if (!digitalRead(instance->pinB) && ((millis() - instance->debounceA) > instance->debounceDelay)) { - instance->debounceA = millis(); - instance->skipB = true; - configASSERT( xTaskToNotify != NULL ); - uint32_t intrBits = 1; - xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } -} - -// Interrupt on B changing state, same as A above -void Rotary::doEncoderB() { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (instance->skipB) { - instance->skipB = false; - instance->debounceB = millis(); - return; - } - if (!digitalRead(instance->pinA) && ((millis() - instance->debounceB) > instance->debounceDelay)) { - instance->debounceB = millis(); - instance->skipA = true; - configASSERT( xTaskToNotify != NULL ); - uint32_t intrBits = 2; - xTaskNotifyFromISR( xTaskToNotify, intrBits, eSetValueWithoutOverwrite, &xHigherPriorityTaskWoken ); - portYIELD_FROM_ISR(); //portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); - } -} - diff --git a/src/rotary.h b/src/rotary.h index 081fb46..209b58f 100644 --- a/src/rotary.h +++ b/src/rotary.h @@ -3,6 +3,7 @@ #include #include +#include // usually the rotary encoders three pins have the ground pin in the middle enum PinAssignments { @@ -16,31 +17,15 @@ class Rotary { Rotary(); bool begin(uint8_t pinA, uint8_t pinB, uint8_t pinButton); bool registerCallback(std::function callback); - static void IRAM_ATTR doEncoderA(void); - static void IRAM_ATTR doEncoderB(void); - static void IRAM_ATTR doButton(void); - static Rotary* instance; - static TaskHandle_t xTaskToNotify; - uint32_t debounceA; - uint32_t debounceB; - uint32_t debounceDelay = 50; + ClickEncoder *encoder; + int16_t last, value; private: - volatile int encoderPos = 0; // a counter for the dial - unsigned int lastReportedPos = 1; // change management - boolean rotating = false; // debounce management - // interrupt service routine vars - boolean A_set = false; - boolean B_set = false; - boolean Button_set = false; - boolean skipA = false; - boolean skipB = false; uint8_t pinA; uint8_t pinB; uint8_t pinButton; - void changed(void); std::function callback = nullptr; - TaskHandle_t buttonTaskHandle; - void button_task(void*); + TaskHandle_t taskHandle; + void task(void*); static void cTaskWrapper(void*); };