171 lines
4.9 KiB
C
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(")");
|
|
}
|
|
}
|
|
|
|
}
|