You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
198 lines
5.5 KiB
C
198 lines
5.5 KiB
C
/** @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 <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#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;
|
|
}
|