143 lines
2.8 KiB
C
143 lines
2.8 KiB
C
|
/*
|
||
|
* Copyright (C) 2023 Daniele Lacamera <root@danielinux.net>
|
||
|
*
|
||
|
* 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 <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#include "task.h"
|
||
|
#include <stdint.h>
|
||
|
#include <stdlib.h>
|
||
|
#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);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|