diff --git a/Makefile b/Makefile index ffad3a8..e4ef6dd 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,7 @@ OBJS += $(STARTUP_SCRIPT:.s=.o) OBJS += utils/gpio.o OBJS += utils/usart.o OBJS += utils/timebase.o +OBJS += utils/debounce.o OBJS += init.o ################################################################ diff --git a/lib/common.h b/lib/common.h index 97c2c88..67b48f8 100644 --- a/lib/common.h +++ b/lib/common.h @@ -4,6 +4,7 @@ #include #include +#include typedef volatile uint8_t* io8_t; diff --git a/main.c b/main.c index 6310a63..2f4ed29 100644 --- a/main.c +++ b/main.c @@ -2,6 +2,7 @@ #include "utils/usart.h" #include "utils/timebase.h" +#include "utils/debounce.h" #include "init.h" @@ -10,23 +11,13 @@ void blink_green(void) GPIOC_ODR ^= BIT9; } - -// --- async delayed blue blink --- - -bool blue_blink_pending = false; - -void blue_off(void) -{ - GPIOC_ODR &= ~BIT8; - blue_blink_pending = false; -} - void blink_blue(void) { - GPIOC_ODR |= BIT8; - register_future_task(blue_off, 200); + GPIOC_ODR ^= BIT8; } +void blue_on(void) { GPIOC_ODR |= BIT8; } +void blue_off(void) { GPIOC_ODR &= ~BIT8; } // called every 1s @@ -44,25 +35,15 @@ void SystemInit(void) init_gpios(); init_usart(); - register_periodic_task(blink_green, 500); + register_periodic_task(blink_green, 1000); + //register_periodic_task(blink_blue, 1000); register_periodic_task(say_hello, 1000); + + register_debounced_pin(GPIOA, 0, blue_on, blue_off); } int main(void) { - int btn_c = 0; - while (1) { - bool btn = GPIOA_IDR & BIT0; - if (btn) { - if (btn_c++ > 20 && !blue_blink_pending) { - blue_blink_pending = true; - register_future_task(blink_blue, 1000); - } - } else { - btn_c = 0; - } - - delay_ms(1); - } + while (1); } diff --git a/proj.pro b/proj.pro index 86419c9..602fbb2 100644 --- a/proj.pro +++ b/proj.pro @@ -26,7 +26,8 @@ SOURCES += \ usart.c \ utils/gpio.c \ utils/timebase.c \ - utils/usart.c + utils/usart.c \ + utils/debounce.c HEADERS += \ lib/common.h \ @@ -43,5 +44,6 @@ HEADERS += \ usart.h \ utils/gpio.h \ utils/timebase.h \ - utils/usart.h + utils/usart.h \ + utils/debounce.h diff --git a/utils/debounce.c b/utils/debounce.c new file mode 100644 index 0000000..a502b03 --- /dev/null +++ b/utils/debounce.c @@ -0,0 +1,90 @@ +#include "debounce.h" +#include "timebase.h" + +static bool task_registered = false; +void debo_task(void); + +// ms debounce time +#define DEBO_TIME 20 +#define DEBO_PIN_COUNT 10 + +typedef struct { + uint32_t gpio; + uint32_t bit_n; + void (*falling_cb)(void); + void (*rising_cb)(void); + uint32_t counter_0; + uint32_t counter_1; + bool status; +} debo_entry_t; + +int debo_pin_n = 0; +debo_entry_t debo_pins[DEBO_PIN_COUNT]; + + + +bool register_debounced_pin(uint32_t gpio, uint8_t n, void (*rising_cb)(void), void (*falling_cb)(void)) +{ + if (!task_registered) { + register_periodic_task(debo_task, 1); + } + + if (debo_pin_n >= DEBO_PIN_COUNT) return false; + + // add the task + debo_entry_t *pin = &debo_pins[debo_pin_n++]; + pin->bit_n = n; + pin->gpio = gpio; + pin->falling_cb = falling_cb; + pin->rising_cb = rising_cb; + pin->counter_0 = 0; + pin->counter_1 = 0; + + io32_t IDR = P_REG(pin->gpio, GPIO_IDR_offs); + pin->status = *IDR & BIT(pin->bit_n); + + return true; +} + + + +void debo_task(void) +{ + io32_t IDR; + bool status; + + for (int i = 0; i < debo_pin_n; i++) { + debo_entry_t *pin = &debo_pins[i]; + + IDR = P_REG(pin->gpio, GPIO_IDR_offs); + + status = *IDR & BIT(pin->bit_n); + if (pin->status != status) { + if (status == 0) { + // falling + + if (pin->counter_0++ == DEBO_TIME) { + pin->status = 0; + + if (pin->falling_cb != NULL) { + pin->falling_cb(); + } + } + } else { + // rising + + if (pin->counter_1++ == DEBO_TIME) { + pin->status = 1; + + if (pin->rising_cb != NULL) { + pin->rising_cb(); + } + } + } + } else { + // rewind counters + pin->counter_0 = 0; + pin->counter_1 = 0; + } + } +} diff --git a/utils/debounce.h b/utils/debounce.h new file mode 100644 index 0000000..8e9397b --- /dev/null +++ b/utils/debounce.h @@ -0,0 +1,6 @@ +#pragma once +#include + +// Debouncer requires that you setup SysTick first. + +bool register_debounced_pin(uint32_t gpio, uint8_t n, void (*rising_cb)(void), void (*falling_cb)(void)); diff --git a/utils/timebase.c b/utils/timebase.c index 661b2e3..3f30d05 100644 --- a/utils/timebase.c +++ b/utils/timebase.c @@ -2,10 +2,11 @@ volatile uint32_t TIME_MS; + + +// --- time scheduler --- #define PERIODIC_TASK_COUNT 5 -#define FUTURE_TASK_COUNT 5 -// --- time scheduler system --- typedef struct { /** User callback */ void (*callback)(void); @@ -15,11 +16,13 @@ typedef struct { uint32_t countup; } periodic_task_t; -static uint8_t periodic_task_n = 0; +static int periodic_task_n = 0; static periodic_task_t periodic_tasks[PERIODIC_TASK_COUNT]; -// --- future call system --- + +// --- future calls --- +#define FUTURE_TASK_COUNT 5 typedef struct { /** 1 for active tasks */ bool active; @@ -48,7 +51,7 @@ bool register_periodic_task(void (*callback)(void), uint32_t interval_ms) -bool register_future_task(void (*callback)(void), uint32_t delay_ms) +bool schedule_task(void (*callback)(void), uint32_t delay_ms) { for (int i = 0; i < FUTURE_TASK_COUNT; i++) { future_task_t *task = &future_tasks[i]; @@ -91,6 +94,7 @@ void SysTick_Handler(void) } + void delay_ms(uint32_t ms) { uint32_t last_ms = TIME_MS; diff --git a/utils/timebase.h b/utils/timebase.h index 833e4e5..0ead8e6 100644 --- a/utils/timebase.h +++ b/utils/timebase.h @@ -1,13 +1,17 @@ #pragma once #include +/** Global millisecond time base */ extern volatile uint32_t TIME_MS; +/** Millisecond delay */ void delay_ms(uint32_t ms); + +/** Second delay */ void delay_s(uint32_t s); /** Schedule a periodic task (like a cron job). Returns success. */ bool register_periodic_task(void (*callback) (void), uint32_t interval_ms); /** Schedule a future one-off task. Returns success. */ -bool register_future_task(void (*callback)(void), uint32_t delay_ms); +bool schedule_task(void (*callback)(void), uint32_t delay_ms);