From 448df55335c7a68c6e409c7abe94fcf8bdbc3ca6 Mon Sep 17 00:00:00 2001 From: Karsten Fleischer Date: Sat, 26 Oct 2024 18:09:58 +0200 Subject: [PATCH] Protect ISRs, getter and setters with mutex --- src/ESP32RotaryEncoder.cpp | 27 ++++++++++++++++++++++++++- src/ESP32RotaryEncoder.h | 1 + 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/ESP32RotaryEncoder.cpp b/src/ESP32RotaryEncoder.cpp index 013ab91..f6b403f 100644 --- a/src/ESP32RotaryEncoder.cpp +++ b/src/ESP32RotaryEncoder.cpp @@ -48,43 +48,53 @@ void RotaryEncoder::setEncoderType( EncoderType type ) void RotaryEncoder::setBoundaries( long minValue, long maxValue, bool circleValues ) { + portENTER_CRITICAL(&mux); if( minValue > maxValue ) ESP_LOGW( LOG_TAG, "Minimum value (%ld) is greater than maximum value (%ld); behavior is undefined.", minValue, maxValue ); setMinValue( minValue ); setMaxValue( maxValue ); setCircular( circleValues ); + portEXIT_CRITICAL(&mux); } void RotaryEncoder::setMinValue( long minValue ) { + portENTER_CRITICAL(&mux); ESP_LOGD( LOG_TAG, "minValue = %ld", minValue ); this->minEncoderValue = minValue; + portEXIT_CRITICAL(&mux); } void RotaryEncoder::setMaxValue( long maxValue ) { + portENTER_CRITICAL(&mux); ESP_LOGD( LOG_TAG, "maxValue = %ld", maxValue ); this->maxEncoderValue = maxValue; + portEXIT_CRITICAL(&mux); } void RotaryEncoder::setCircular( bool circleValues ) { + portENTER_CRITICAL(&mux); ESP_LOGD( LOG_TAG, "Boundaries %s circular", ( circleValues ? "are" : "are not" ) ); this->circleValues = circleValues; + portEXIT_CRITICAL(&mux); } void RotaryEncoder::setStepValue( long stepValue ) { + portENTER_CRITICAL(&mux); ESP_LOGD( LOG_TAG, "stepValue = %ld", stepValue ); if( stepValue > maxEncoderValue || stepValue < minEncoderValue ) ESP_LOGW( LOG_TAG, "Step value (%ld) is outside the bounds (%ld...%ld); behavior is undefined.", stepValue, minEncoderValue, maxEncoderValue ); this->stepValue = stepValue; + portEXIT_CRITICAL(&mux); } void RotaryEncoder::onTurned( EncoderCallback f ) @@ -216,6 +226,7 @@ void RotaryEncoder::disable() bool RotaryEncoder::buttonPressed() { + portENTER_CRITICAL(&mux); if( !_isEnabled ) return false; @@ -225,12 +236,14 @@ bool RotaryEncoder::buttonPressed() bool wasPressed = buttonPressedFlag; buttonPressedFlag = false; + portEXIT_CRITICAL(&mux); return wasPressed; } bool RotaryEncoder::encoderChanged() { + portENTER_CRITICAL(&mux); if( !_isEnabled ) return false; @@ -240,15 +253,21 @@ bool RotaryEncoder::encoderChanged() bool hasChanged = encoderChangedFlag; encoderChangedFlag = false; + portEXIT_CRITICAL(&mux); return hasChanged; } long RotaryEncoder::getEncoderValue() { + portENTER_CRITICAL(&mux); constrainValue(); - return currentValue; + long value = currentValue; + + portEXIT_CRITICAL(&mux); + + return value; } void RotaryEncoder::constrainValue() @@ -267,12 +286,14 @@ void RotaryEncoder::constrainValue() void RotaryEncoder::setEncoderValue( long newValue ) { + portENTER_CRITICAL(&mux); if( newValue != currentValue ) ESP_LOGD( LOG_TAG, "Overriding encoder value from '%ld' to '%ld'", currentValue, newValue ); currentValue = newValue; constrainValue(); + portEXIT_CRITICAL(&mux); } void ARDUINO_ISR_ATTR RotaryEncoder::loop() @@ -286,6 +307,7 @@ void ARDUINO_ISR_ATTR RotaryEncoder::loop() void ARDUINO_ISR_ATTR RotaryEncoder::_button_ISR() { + portENTER_CRITICAL_ISR(&mux); static unsigned long _lastInterruptTime = 0; // Simple software de-bounce @@ -312,10 +334,12 @@ void ARDUINO_ISR_ATTR RotaryEncoder::_button_ISR() } _lastInterruptTime = millis(); + portEXIT_CRITICAL_ISR(&mux); } void ARDUINO_ISR_ATTR RotaryEncoder::_encoder_ISR() { + portENTER_CRITICAL_ISR(&mux); /** * Almost all of this came from a blog post by Garry on GarrysBlog.com: * https://garrysblog.com/2021/03/20/reliably-debouncing-rotary-encoders-with-arduino-and-esp32/ @@ -386,4 +410,5 @@ void ARDUINO_ISR_ATTR RotaryEncoder::_encoder_ISR() // Remember current time so we can calculate speed _lastInterruptTime = millis(); } + portEXIT_CRITICAL_ISR(&mux); } diff --git a/src/ESP32RotaryEncoder.h b/src/ESP32RotaryEncoder.h index 7c538ba..d964997 100644 --- a/src/ESP32RotaryEncoder.h +++ b/src/ESP32RotaryEncoder.h @@ -49,6 +49,7 @@ typedef enum { class RotaryEncoder { protected: + mutable portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; #if defined( ESP32 ) typedef std::function EncoderCallback;