Files
RP2350_MIDI_Lighter/Firmware/Rotary_Encoder.c
Chris 89c875e38f - First complete version of firmware. Currently being tested in the rehearsal room
- Added bunch of screens, fonts and images
 - Added script to read out frame buffer (function currently disabled in Firmware)
2025-10-26 20:57:58 +01:00

161 lines
4.6 KiB
C

/*
* 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
*******************************************************************/