221 lines
4.9 KiB
C
221 lines
4.9 KiB
C
/*
|
|
* (c) danielinux 2019
|
|
* GPLv.2
|
|
*
|
|
* See LICENSE for details
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#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();
|
|
}
|
|
|
|
|