/* * Rotary_Encoder.c * * Created: Mon Nov 29 2021 11:27:29 * Author Chris */ // ============================================================================================ // Includes #include "Rotary_Encoder.h" #include "pico/time.h" #include "pico/types.h" #include "pico/stdlib.h" #include "hardware/gpio.h" // ============================================================================================ // Defines #define ENCODER_PIN_A_GPIO 25 #define ENCODER_PIN_B_GPIO 24 #define ENCODER_SWITCH_GPIO 27 #define GPIO_IRQ_LEVEL_LOW 1 #define GPIO_IRQ_LEVEL_HIGH 2 #define GPIO_IRQ_EDGE_FALL 4 #define GPIO_IRQ_EDGE_RISE 8 #define SWITCH_IDLE 1 #define SWITCH_PRESSED 0 #define DEBOUNCE_TIME_ENCODER_MS 50 #define DEBOUNCE_TIME_SWITCH_MS 300 // Separate Switch Define #define SWITCH_GPIO 23 // ============================================================================================ // Variables static volatile uint32_t _Debounce_Time_Encoder_ms = 0; static volatile uint32_t _Debounce_Time_Switch_ms = 0; static volatile bool _Rotation_CW_Occurred; static volatile bool _Rotation_CCW_Occurred; static volatile bool _Rotary_Encoder_Switch_Press_Occurred; extern volatile uint32_t _Debounce_Time_Switch_ms; extern volatile bool _Switch_Press_Occurred; // Other switch - not from the Rotary Encoder static volatile uint8_t _Rotary_Encoder_Previous_NextCode = 0; static volatile uint16_t _Rotary_Encoder_Store_State = 0; static volatile int8_t _Rotary_Encoder_Table[] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; // ============================================================================================ // Function Declarations /******************************************************************* Interrupt Service Routines *******************************************************************/ void ISR_Rotary_Encoder(uint gpio, uint32_t events) { if(gpio == ENCODER_PIN_A_GPIO || gpio == ENCODER_PIN_B_GPIO) { _Rotary_Encoder_Previous_NextCode <<= 2; if(gpio_get(ENCODER_PIN_A_GPIO)) { _Rotary_Encoder_Previous_NextCode |= 0x02; } if(gpio_get(ENCODER_PIN_B_GPIO)) { _Rotary_Encoder_Previous_NextCode |= 0x01; } _Rotary_Encoder_Previous_NextCode &= 0x0f; // If valid then _Rotary_Encoder_Store_State as 16 bit data. if(_Rotary_Encoder_Table[_Rotary_Encoder_Previous_NextCode]) { _Rotary_Encoder_Store_State <<= 4; _Rotary_Encoder_Store_State |= _Rotary_Encoder_Previous_NextCode; if((_Rotary_Encoder_Store_State & 0xFF)==0x2B) { _Rotation_CCW_Occurred = true; } if((_Rotary_Encoder_Store_State & 0xFF)==0x17) { _Rotation_CW_Occurred = true; } } } else if(gpio == ENCODER_SWITCH_GPIO) { uint32_t Current_Time_ms = to_ms_since_boot(get_absolute_time()); if(Current_Time_ms < _Debounce_Time_Switch_ms) { return; } _Rotary_Encoder_Switch_Press_Occurred = true; _Debounce_Time_Switch_ms = Current_Time_ms + DEBOUNCE_TIME_SWITCH_MS; } else if(gpio == SWITCH_GPIO) { uint32_t Current_Time_ms = to_ms_since_boot(get_absolute_time()); if(Current_Time_ms < _Debounce_Time_Switch_ms) { return; } _Switch_Press_Occurred = true; _Debounce_Time_Switch_ms = Current_Time_ms + DEBOUNCE_TIME_SWITCH_MS; } } /******************************************************************* Functions *******************************************************************/ void Rotary_Encoder_Init(void) { _Rotation_CW_Occurred = false; _Rotation_CCW_Occurred = false; _Rotary_Encoder_Switch_Press_Occurred = false; gpio_init(ENCODER_PIN_A_GPIO); gpio_set_dir(ENCODER_PIN_A_GPIO, false); gpio_init(ENCODER_PIN_B_GPIO); gpio_set_dir(ENCODER_PIN_B_GPIO, false); gpio_init(ENCODER_SWITCH_GPIO); gpio_set_dir(ENCODER_SWITCH_GPIO, false); gpio_set_irq_enabled_with_callback(ENCODER_PIN_A_GPIO, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &ISR_Rotary_Encoder); gpio_set_irq_enabled(ENCODER_PIN_B_GPIO, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); gpio_set_irq_enabled(ENCODER_SWITCH_GPIO, GPIO_IRQ_EDGE_FALL , true); } bool Rotary_Encoder_Rotation_CW_Occurred(void) { bool Return_Value = _Rotation_CW_Occurred; _Rotation_CW_Occurred = false; return Return_Value; } bool Rotary_Encoder_Rotation_CCW_Occurred(void) { bool Return_Value = _Rotation_CCW_Occurred; _Rotation_CCW_Occurred = false; return Return_Value; } bool Rotary_Encoder_Switch_Press_Occurred(void) { bool Return_Value = _Rotary_Encoder_Switch_Press_Occurred; _Rotary_Encoder_Switch_Press_Occurred = false; return Return_Value; } /******************************************************************* Internal Functions *******************************************************************/