diff --git a/init.c b/init.c index 3e0c078..613bf58 100644 --- a/init.c +++ b/init.c @@ -11,6 +11,7 @@ void init_gpios(void) gpio_enable(GPIOC); gpio_set_mode(GPIOC, BIT8 | BIT9 | BIT7, MODER_OUTPUT); + gpio_set_mode(GPIOA, BIT0, MODER_INPUT); } diff --git a/main.c b/main.c index ce248ed..6310a63 100644 --- a/main.c +++ b/main.c @@ -5,12 +5,36 @@ #include "init.h" - -void blink(void) { +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); +} + + +// called every 1s + +void say_hello(void) +{ + usart_tx_string(USART3, "HELLO\r\n"); +} + /** Called before main() */ void SystemInit(void) @@ -20,16 +44,25 @@ void SystemInit(void) init_gpios(); init_usart(); - schedule_timed_task(blink, 500); + register_periodic_task(blink_green, 500); + register_periodic_task(say_hello, 1000); } int main(void) { + int btn_c = 0; while (1) { - delay_ms(1000); - GPIOC_ODR ^= BIT8; + 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; + } - usart_tx_string(USART3, "HELLO\r\n"); + delay_ms(1); } } diff --git a/utils/timebase.c b/utils/timebase.c index 5aa100a..661b2e3 100644 --- a/utils/timebase.c +++ b/utils/timebase.c @@ -2,28 +2,43 @@ volatile uint32_t TIME_MS; -#define TASK_COUNT 10 +#define PERIODIC_TASK_COUNT 5 +#define FUTURE_TASK_COUNT 5 // --- time scheduler system --- typedef struct { /** User callback */ - void (*callback) (void); + void (*callback)(void); /** Callback interval */ uint32_t interval_ms; /** Counter, when reaches interval_ms, is cleared and callback is called. */ uint32_t countup; -} timebase_cb_t; +} periodic_task_t; -static uint8_t scheduled_task_n = 0; -static timebase_cb_t scheduled_tasks[TASK_COUNT]; +static uint8_t periodic_task_n = 0; +static periodic_task_t periodic_tasks[PERIODIC_TASK_COUNT]; -bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms) +// --- future call system --- +typedef struct { + /** 1 for active tasks */ + bool active; + /** User callback */ + void (*callback)(void); + /** Counter, when reaches 0ms, callback is called and the task is removed */ + uint32_t countdown_ms; +} future_task_t; + +static future_task_t future_tasks[FUTURE_TASK_COUNT]; + + + +bool register_periodic_task(void (*callback)(void), uint32_t interval_ms) { - if (scheduled_task_n >= TASK_COUNT) return false; + if (periodic_task_n >= PERIODIC_TASK_COUNT) return false; // add the task - timebase_cb_t *task = &scheduled_tasks[scheduled_task_n++]; + periodic_task_t *task = &periodic_tasks[periodic_task_n++]; task->callback = callback; task->countup = 0; task->interval_ms = interval_ms; @@ -32,19 +47,47 @@ bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms) } + +bool register_future_task(void (*callback)(void), uint32_t delay_ms) +{ + for (int i = 0; i < FUTURE_TASK_COUNT; i++) { + future_task_t *task = &future_tasks[i]; + if (task->active) continue; + + task->callback = callback; + task->countdown_ms = delay_ms; + task->active = true; + } + + return false; +} + + + /** IRQ */ void SysTick_Handler(void) { TIME_MS++; // run scheduled tasks - for (int i = 0; i < scheduled_task_n; i++) { - timebase_cb_t *task = &scheduled_tasks[i]; + for (int i = 0; i < periodic_task_n; i++) { + periodic_task_t *task = &periodic_tasks[i]; if (task->countup++ >= task->interval_ms) { task->callback(); task->countup = 0; } } + + // run future tasks + for (int i = 0; i < FUTURE_TASK_COUNT; i++) { + future_task_t *task = &future_tasks[i]; + if (!task->active) continue; + + if (task->countdown_ms-- == 0) { + task->callback(); + task->active = 0; + } + } } diff --git a/utils/timebase.h b/utils/timebase.h index 4a2fee5..833e4e5 100644 --- a/utils/timebase.h +++ b/utils/timebase.h @@ -6,5 +6,8 @@ extern volatile uint32_t TIME_MS; void delay_ms(uint32_t ms); void delay_s(uint32_t s); -/** Schedule a timed task (like a cron job) */ -bool schedule_timed_task(void (*callback) (void), uint32_t interval_ms); +/** 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);