/* * (c) danielinux 2019 * GPLv.2 * * See LICENSE for details */ #include #include #include #include #include "system.h" #include "button.h" #include "systick.h" #include "unicore-mx/stm32/gpio.h" #include "unicore-mx/stm32/exti.h" #include "unicore-mx/stm32/rcc.h" #include "unicore-mx/stm32/f4/rcc.h" #include "unicore-mx/stm32/adc.h" #include "unicore-mx/stm32/f4/adc.h" #include "unicore-mx/stm32/f4/nvic.h" // Uncomment to enable debug //#define BUTTON_DEBUG enum button_state { IDLE = 0, PRESSING, PRESSED, HOLD, RELEASING, }; #ifdef BUTTON_DEBUG # define DBG printf #else # define DBG(...) do {} while (0) #endif #define BUTTON_DEBOUNCE_TIME 50 #define BUTTON_HOLD_TIME 200 static volatile int button_press_pending = 0; #define BUTTON_PLUS '+' #define BUTTON_MINUS '-' static void input_run(uint32_t ev, void *arg); static void input_init(void); const char button_task_name[] = "Input"; // PA8 + PA9 // ROTARY encoder // PC0 // BUTTON // // TODO: // C4 + C5 rotary // B0 + B1 + C3 Buttons (- + RotSW) // void pin_exti_init(void) { } void pin_exti_start_read(void) { exti_set_trigger(GPIO0|GPIO1|GPIO3|GPIO4|GPIO5, EXTI_TRIGGER_BOTH); exti_enable_request(GPIO0); exti_enable_request(GPIO1); exti_enable_request(GPIO3); exti_enable_request(GPIO4); exti_enable_request(GPIO5); } static void button_setup(void) { rcc_periph_clock_enable(RCC_SYSCFG); rcc_periph_clock_enable(RCC_GPIOB); rcc_periph_clock_enable(RCC_GPIOC); gpio_mode_setup(GPIOC, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO3 | GPIO4 | GPIO5); gpio_mode_setup(GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLDOWN, GPIO0 | GPIO1); nvic_enable_irq(NVIC_EXTI9_5_IRQ); nvic_enable_irq(NVIC_EXTI0_IRQ); nvic_enable_irq(NVIC_EXTI1_IRQ); nvic_enable_irq(NVIC_EXTI3_IRQ); nvic_enable_irq(NVIC_EXTI4_IRQ); nvic_set_priority(NVIC_EXTI9_5_IRQ, 1); nvic_set_priority(NVIC_EXTI0_IRQ, 1); nvic_set_priority(NVIC_EXTI1_IRQ, 1); nvic_set_priority(NVIC_EXTI3_IRQ, 1); nvic_set_priority(NVIC_EXTI4_IRQ, 1); exti_select_source(GPIO0, GPIOB); exti_select_source(GPIO1, GPIOB); exti_select_source(GPIO3, GPIOC); exti_select_source(GPIO4, GPIOC); exti_select_source(GPIO5, GPIOC); } static volatile uint32_t rot_up = 0; static volatile uint32_t rot_down = 0; static void button_start_read(void) { exti_set_trigger(GPIO0|GPIO1|GPIO3, EXTI_TRIGGER_RISING); exti_set_trigger(GPIO4, EXTI_TRIGGER_FALLING); exti_enable_request(GPIO0); exti_enable_request(GPIO1); exti_enable_request(GPIO3); exti_enable_request(GPIO4); } static volatile uint32_t last_rot_ev = 0; void isr_exti_rot0(void) { uint32_t rot_val = gpio_get(GPIOC, GPIO4 | GPIO5); if ((jiffies - last_rot_ev) > 100) { if ((rot_val & GPIO4) == 0) { if ((rot_val & GPIO5) == 0) rot_down++; else rot_up++; } } exti_reset_request(GPIO4); exti_reset_request(GPIO5); } void isr_exti_button(void) { uint32_t pending; pending = (gpio_get(GPIOB, GPIO0|GPIO1)); if ((pending & GPIO0) != 0) { button_press_pending = '-'; } if ((pending & GPIO1) != 0) { button_press_pending = '+'; } if (!pending) { pending = (gpio_get(GPIOC, GPIO3)); if ((pending & GPIO3) != 0) { button_press_pending = '*'; } } exti_reset_request(GPIO0); exti_reset_request(GPIO1); exti_reset_request(GPIO3); } static uint32_t t0s, t0us; static uint32_t t1s, t1us; static uint32_t time_diff_ms(uint32_t s_a, uint32_t us_a, uint32_t s_b, uint32_t us_b) { uint32_t res = 0; res = (s_a - s_b) * 1000; if (us_b > us_a) { us_a += 1000000; res -= 1000; } res += (us_a - us_b) / 1000; return res; } /* Button interface */ struct user_button { enum button_state state; uint32_t transition_start_timestamp; }; static struct user_button Buttons[N_BUTTONS]; int button_poll(void (*callback)(uint8_t press, int hold)) { int b = 0; int st; static uint32_t last_event = 0; static uint32_t pressed_start = 0; while(rot_down > 0) { callback('D',0); rot_down--; } while(rot_up > 0) { callback('U',0); rot_up--; } if (jiffies - last_event < BUTTON_DEBOUNCE_TIME) return; last_event = jiffies; st = !!(gpio_get(GPIOB, GPIO0 | GPIO1) | gpio_get(GPIOC, GPIO3)); if (!st) { pressed_start = 0; } if ((button_press_pending) && st) { if ((pressed_start == 0) || ((jiffies - pressed_start) > BUTTON_HOLD_TIME)) { pressed_start = jiffies; callback(button_press_pending, 0); return 1; } } button_press_pending = 0; return 0; } void button_init(void) { memset(Buttons, 0, sizeof(struct user_button) * N_BUTTONS); button_setup(); button_start_read(); }