/* * Copyright (C) 2023 Daniele Lacamera * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include "task.h" #include #include #include "system.h" static struct screen *focus = NULL; static int refresh = 0, redraw = 0; static struct task *tasklist; static struct screen *screenlist; static uint32_t trigger = 0U; static volatile uint32_t pending_events = 0; static uint8_t current_screen = 0; void screen_set_focus(struct screen *s) { if (s) { focus = s; if (s->draw) s->draw(); } } struct screen *screen_get_focus(void) { return focus; } void screen_refresh(void) { refresh = 1; } void screen_draw(void) { redraw = 1; } struct screen *screens(void) { return screenlist; } int screen_n_screens(void) { int n = 0; struct screen *s = screenlist; while (s) { n++; s = s->next; } return n; } void register_task(struct task *t) { t->screen = NULL; t->next = tasklist; tasklist = t; if (t->init) t->init(); } static int screen_id = 0; void register_screen(struct task *t, struct screen *s) { t->screen = s; s->task = t; s->next = screenlist; s->id = screen_id++; screenlist = s; if (!focus) { focus = screenlist; focus->draw(); } } void task_add_events(struct task *t, uint32_t ev) { t->events |= ev; } void task_del_events(struct task *t, uint32_t ev) { t->events &= ~ev; } void trigger_event(uint32_t ev) { pending_events |= ev; } void clear_event(uint32_t ev) { pending_events &= ~ev; } void main_loop(void) { struct task *t = tasklist; struct screen *s; int prio; uint32_t processing_events; while(1) { WFI(); if (!pending_events) continue; for (prio = 0; prio < 32; prio++) { processing_events = pending_events&(1 << prio); if (processing_events == 0) continue; t = tasklist; while(t) { if (processing_events & t->events) t->run(processing_events & t->events, NULL); t = t->next; } } clear_event(EV_SYSTICK); } }