/** @file encoder.c * @date 2014-12-04 * @author Frank Klee * @brief Drehencoder Library * * Basisroutinen zum Abfragen eines Drehencoders mittels Polling. * Quelle: https://www.mikrocontroller.net/articles/Drehgeber * * @brief Formatierungen und Umbenennungen der Funktionen * @author Tom, DL7BJ * @date 2023-03-23 */ #include #include #include "encoder.h" int8_t DrehgeberPosition; ///< akt. Drehencoderposition int8_t DrehgeberMax = 127; ///< maximaler Wert des Drehgebers int8_t DrehgeberMin = -127; ///< minimaler Wert des Drehgebers volatile int16_t iButtonPressedCounter = 0; ///< Zähler für kurzen Tastendruck volatile int16_t iButtonDebounceCycles = 0; ///< Zähler für Entprellung volatile int16_t iButtonPressedLongCycles = 0; ///< Zähler für langen Tastendruck volatile int8_t enc_delta; ///< Delta des Encoders bei Betätigung static int8_t last; ///< letzter Wert des Encoders typedef enum EButtonState { ButtonState_Unpressed, ///< Taster nicht gedrückt ButtonState_Pressed, ///< Taster gedrückt ButtonState_Hold, ///< Taster gehalten ButtonState_Released ///< Taster geöffnet }tEButtonState; volatile tEButtonState buttonState = ButtonState_Unpressed; volatile tEButtonPressedState buttonPressed = ButtonPressed_Unpressed; /** @fn void EncoderInit(void) * @brief Initialisierung des Drehencoders und der Startwerte * @param none * @retval none */ void EncoderInit(void) { int8_t new; new = 0; if(PHASE_A) new = 3; if(PHASE_B) new ^= 1; last = new; enc_delta = 0; iButtonDebounceCycles = BUTTON_DEBOUNCETIME_MS; iButtonPressedLongCycles = BUTTON_PRESSEDLONG_MS; } /** @fn void EncoderPolling(void) * @brief EncoderPolling * * Abfrage des Drehencoders und des Tasters * Wird vom Timer 0 aufgerufen * * @param none * @retval none */ void EncoderPolling(void) { int8_t new, diff; new = 0; if(PHASE_A) new = 3; if(PHASE_B) new ^= 1; diff = last - new; if(diff & 1) { last = new; enc_delta += (diff & 2) - 1; } switch(buttonState) { case ButtonState_Unpressed: if(BUTTONPRESSED) buttonState = ButtonState_Pressed; break; case ButtonState_Pressed: buttonState = ButtonState_Hold; break; case ButtonState_Hold: iButtonPressedCounter++; if(iButtonPressedCounter >= iButtonDebounceCycles && (! BUTTONPRESSED)) { buttonState = ButtonState_Released; if(buttonPressed != ButtonPressed_Long) buttonPressed = ButtonPressed_Short; } if(iButtonPressedCounter >= iButtonPressedLongCycles) { buttonState = ButtonState_Released; buttonPressed = ButtonPressed_Long; } break; case ButtonState_Released: iButtonPressedCounter = 0; if(!BUTTONPRESSED) buttonState = ButtonState_Unpressed; break; } } #if defined (SingleStep) int8_t EncodeRead(void) { int8_t val; cli(); val = enc_delta; enc_delta = 0; sei(); return val; } #elif defined (TwoStep) int8_t EncodeRead(void) { int8_t val; cli(); val = enc_delta; enc_delta = val & 1; sei(); return val >> 1; } #elif defined (FourStep) int8_t EncodeRead(void) { int8_t val; cli(); val = enc_delta; enc_delta = val & 3; sei(); return val >> 2; } #endif /** @fn int8_t EncoderRead(char Ueberlauf) * @brief Liest die akt. Position des Drehencoders * * @param Ueberlauf größer +127, -127 * @retval Aktuelle Position des Drehencoders */ int8_t EncoderRead(char Ueberlauf) { DrehgeberPosition += EncodeRead(); if(DrehgeberPosition > DrehgeberMax) { if(Ueberlauf) DrehgeberPosition = DrehgeberPosition - DrehgeberMax + DrehgeberMin - 1; else DrehgeberPosition = DrehgeberMax; } if(DrehgeberPosition < DrehgeberMin) { if(Ueberlauf) DrehgeberPosition = DrehgeberPosition + DrehgeberMax - DrehgeberMin + 1; else DrehgeberPosition = DrehgeberMin; } return(DrehgeberPosition); } /** @fn void EncoderWrite(int8_t EncoderPos) * @brief Setzt die aktuelle Position des Drehencoders * * @param EncoderPos - die Position des Drehencoders * @retval none */ void EncoderWrite(int8_t EncoderPos) { DrehgeberPosition = EncoderPos; } /** @fn void EncoderMinMax(int8_t EncoderMin, int8_t EncoderMax) * @brief Setzt den minimalen und maximalen Bereich des Drehencoders * * @param EncoderMin minimaler Wert des Drehencoders * @param EncoderMax maximaler Wert des Drehencoders * @retval none */ void EncoderMinMax(int8_t EncoderMin, int8_t EncoderMax) { DrehgeberMin = EncoderMin; DrehgeberMax = EncoderMax; if(DrehgeberPosition > DrehgeberMax) DrehgeberPosition = DrehgeberMax; if(DrehgeberPosition < DrehgeberMin) DrehgeberPosition = DrehgeberMin; } /** @fn tEButtonPressedState EncoderGetButtonState(void) * @brief Liefert den Status des Tasters vom Drehencoder * * @param none * @retval tEButtonPressedState */ tEButtonPressedState EncoderGetButtonState(void) { tEButtonPressedState retVal = buttonPressed; buttonPressed = ButtonPressed_Unpressed; return retVal; }