added a debouncer

master
Ondřej Hruška 9 years ago
parent 6dd9ceb94e
commit 6eb62a809f
  1. 1
      Makefile
  2. 1
      lib/common.h
  3. 37
      main.c
  4. 6
      proj.pro
  5. 90
      utils/debounce.c
  6. 6
      utils/debounce.h
  7. 14
      utils/timebase.c
  8. 6
      utils/timebase.h

@ -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
################################################################

@ -4,6 +4,7 @@
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
typedef volatile uint8_t* io8_t;

@ -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);
}

@ -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

@ -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;
}
}
}

@ -0,0 +1,6 @@
#pragma once
#include <common.h>
// 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));

@ -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;

@ -1,13 +1,17 @@
#pragma once
#include <common.h>
/** 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);

Loading…
Cancel
Save