TKK_E32222388/ButtonRotaryHandler.h

171 lines
4.9 KiB
C

#define CLK_PIN 12 // BTN ENC1
#define DT_PIN 14 // BTN ENC2
#define SW_PIN 13 // BTN ENC
#define DIRECTION_NONE 0 // no change
#define DIRECTION_CCW 1 // counter-clockwise direction
#define DIRECTION_CW 2 // clockwise direction
#define BUTTON_PRESSED_EVENT 1
#define BUTTON_UNPRESSED_EVENT 2
#define BUTTON_NO_CHANGE_EVENT 0
volatile uint8_t rotaryDirection = DIRECTION_NONE;
volatile uint8_t rotaryDirectionPrev = DIRECTION_NONE;
volatile uint32_t rotaryLastTick;
volatile int rotaryCounter = 0;
volatile int rotaryCounterPrev = 0;
volatile int rotaryCounterPrevDebug = 0;
volatile bool buttonPressed = false;
volatile bool buttonPressedPrev = false;
volatile bool buttonPressedPrevDebug = false;
volatile uint32_t buttonLastTick = 0;
volatile int16_t rotaryPosition = 0;
volatile int16_t rotaryLastPosition = 0;
//volatile int16_t rotaryEncodedPrev = 0;
// Debounce time in milliseconds
const int debounceTime = 2;//2; //default is 2 (best)
volatile unsigned long lastInterruptTimeA = 0;
volatile unsigned long lastInterruptTimeB = 0;
volatile unsigned long lastInterruptTimeButton = 0;
// Variables to keep track of encoder state
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
long lastEncoderValue = 0;
// ISR for encoder A pin
void IRAM_ATTR handleEncoderA() {
unsigned long currentTime = millis();
if ((currentTime - lastInterruptTimeA) > debounceTime) {
int MSB = digitalRead(CLK_PIN);
int LSB = digitalRead(DT_PIN);
int encoded = (MSB << 1) | LSB;
int sum = (lastEncoded << 2) | encoded;
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011){
encoderValue--;
rotaryDirection = DIRECTION_CCW;
}
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000){
encoderValue++;
rotaryDirection = DIRECTION_CW;
}
lastEncoded = encoded;
lastInterruptTimeA = currentTime;
rotaryCounter=encoderValue; //copy to rotaryCounter
}
}
// ISR for encoder B pin
void IRAM_ATTR handleEncoderB() {
unsigned long currentTime = millis();
if ((currentTime - lastInterruptTimeB) > debounceTime) {
handleEncoderA(); // Call handleEncoderA to handle B changes in the same way
lastInterruptTimeB = currentTime;
}
}
void InitButtonRotaryHandler(){
Serial.print("Initializing Button and Rotary Encoder: ");
buttonPressedPrev = false;
buttonPressedPrevDebug = false;
rotaryCounter = 0;
rotaryCounterPrev = 0;
rotaryCounterPrevDebug = 0;
rotaryDirection = DIRECTION_NONE;
rotaryDirectionPrev = DIRECTION_NONE;
rotaryLastTick = millis();
buttonLastTick = millis();
pinMode(DT_PIN, INPUT_PULLUP);
pinMode(CLK_PIN, INPUT_PULLUP);
pinMode(SW_PIN, INPUT_PULLUP);
// button.setDebounceTime(5);
attachInterrupt(digitalPinToInterrupt(CLK_PIN), handleEncoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(DT_PIN), handleEncoderB, CHANGE);
// Initialize button pin
//pinMode(SW_PIN, INPUT_PULLUP); // Assuming the button is active low
//attachInterrupt(digitalPinToInterrupt(SW_PIN), ButtonInterrupt, CHANGE);
Serial.println("OK");
}
bool ButtonIsPressed(){
if (millis() - buttonLastTick < 10 ) return buttonPressed; //debounce
buttonPressed = digitalRead(SW_PIN) == LOW;
buttonLastTick = millis();
return buttonPressed;
}
//return 0 = no change, 1 = pressed, 2 = unpressed
uint8_t ButtonSwitchedEvent(){
//Serial.println("A");
if (millis() - buttonLastTick < 10 ) return BUTTON_NO_CHANGE_EVENT; //debounce
//Serial.println("B");
buttonPressed = digitalRead(SW_PIN) == LOW;
buttonLastTick = millis();
if (buttonPressed!=buttonPressedPrev){
buttonPressedPrev = buttonPressed;
if (buttonPressed) return BUTTON_PRESSED_EVENT;
return BUTTON_UNPRESSED_EVENT;
}else{
return BUTTON_NO_CHANGE_EVENT; //no change
}
}
//Reset Button flag for event
void ButtonResetEvent(){
buttonPressed = digitalRead(SW_PIN) == LOW;
buttonPressedPrev = buttonPressed;
buttonLastTick = millis();
}
//Reset Rotary flag for event
void RotaryResetEvent(){
rotaryCounter = 0;
rotaryCounterPrev = 0;
encoderValue = 0;
rotaryDirection = DIRECTION_NONE;
rotaryDirectionPrev = DIRECTION_NONE;
}
//Get rotary last direction then clear flag
uint8_t RotaryEvent(){
if (rotaryDirection!=DIRECTION_NONE) lastInterruptTimeB = millis(); //debounce it again from last consume
uint8_t v = rotaryDirection;
rotaryDirection = DIRECTION_NONE;
rotaryDirectionPrev = DIRECTION_NONE;
return v;
}
//for debug testing
void ButtonRotaryDebugRoutine(){
if (buttonPressedPrevDebug!=buttonPressed){
buttonPressedPrevDebug = buttonPressed;
Serial.print("Button: ");
Serial.println((buttonPressed?"1":"0"));
}
if (rotaryCounter!=rotaryCounterPrevDebug){
rotaryCounterPrevDebug = rotaryCounter;
if (rotaryDirection!=DIRECTION_NONE){
Serial.print("Rotary: ");
Serial.print((rotaryDirection==DIRECTION_CW?">":"<"));
Serial.print(" (");
Serial.print(rotaryCounterPrevDebug);
Serial.println(")");
}
}
}