task: move Scheduler into a trait, define static-sized scheduler implementation, expose as a system task runner in platform

This commit is contained in:
Victoria Fischer 2024-12-02 19:32:18 +01:00
parent 132d7c0a33
commit f789f6ded9
4 changed files with 41 additions and 31 deletions

View File

@ -10,7 +10,7 @@ mod mappings;
mod buffers; mod buffers;
use crate::platform::{DefaultBoard, Board}; use crate::platform::{DefaultBoard, Board};
use crate::task::{Task, Scheduler}; use crate::task::{FixedSizeScheduler, Scheduler};
use crate::render::{Surfaces, Renderer}; use crate::render::{Surfaces, Renderer};
use crate::geometry::Rectangle; use crate::geometry::Rectangle;
@ -26,20 +26,17 @@ fn main() {
log::info!("Surface implementation: {}", core::any::type_name_of_val(&output)); log::info!("Surface implementation: {}", core::any::type_name_of_val(&output));
log::info!("Creating animations"); log::info!("Creating animations");
let mut tasks: Vec<Box<dyn Task + 'static>> = vec![ let mut animations = FixedSizeScheduler::new([
Box::new(animations::IdleTask::new(&mut surfaces)), Box::new(animations::IdleTask::new(&mut surfaces)),
Box::new(animations::TestPattern::new(surfaces.new_surface(&Rectangle::everything()).unwrap())), Box::new(animations::TestPattern::new(surfaces.new_surface(&Rectangle::everything()).unwrap())),
]; ];
tasks.append(&mut board.system_tasks()); let mut renderer = FixedSizeScheduler::new([Box::new(Renderer::new(output, surfaces))]);
tasks.push(Box::new(Renderer::new(output, surfaces)));
let mut runner = Scheduler::new(tasks);
log::info!("Runner ready: {:?}", runner);
log::info!("Ready to rock and roll"); log::info!("Ready to rock and roll");
loop { loop {
runner.tick(); animations.tick();
system.tick();
renderer.tick();
} }
} }

View File

@ -18,6 +18,7 @@ use rgb::Rgb;
use super::Board; use super::Board;
use crate::task::FixedSizeScheduler;
use crate::task::Task; use crate::task::Task;
use crate::buffers::{Pixbuf, SurfacePool}; use crate::buffers::{Pixbuf, SurfacePool};
use crate::mappings::StrideMapping; use crate::mappings::StrideMapping;
@ -34,12 +35,14 @@ use crate::buffers::SimpleSurface as SurfaceType;
pub struct Esp32Board<'a> { pub struct Esp32Board<'a> {
output: Option<<Self as Board>::Output>, output: Option<<Self as Board>::Output>,
surfaces: Option<SurfacePool<SurfaceType>>, surfaces: Option<SurfacePool<SurfaceType>>,
tasks: Option<Vec<Box<dyn Task>>> sys_loop: EspSystemEventLoop,
modem: Option<Modem>,
} }
impl<'a> Board for Esp32Board<'a> { impl<'a> Board for Esp32Board<'a> {
type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'a>>; type Output = StrideOutput<[Rgb<u8>; 310], FastWs2812Esp32Rmt<'a>>;
type Surfaces = SurfacePool<SurfaceType>; type Surfaces = SurfacePool<SurfaceType>;
type Scheduler = FixedSizeScheduler<2>;
fn take() -> Self { fn take() -> Self {
// It is necessary to call this function once. Otherwise some patches to the runtime // It is necessary to call this function once. Otherwise some patches to the runtime
@ -51,7 +54,6 @@ impl<'a> Board for Esp32Board<'a> {
let peripherals = Peripherals::take().unwrap(); let peripherals = Peripherals::take().unwrap();
let sys_loop = EspSystemEventLoop::take().unwrap(); let sys_loop = EspSystemEventLoop::take().unwrap();
let nvs = EspDefaultNvsPartition::take().unwrap();
let channel = peripherals.rmt.channel0; let channel = peripherals.rmt.channel0;
let pins = peripherals.pins; let pins = peripherals.pins;
@ -74,10 +76,6 @@ impl<'a> Board for Esp32Board<'a> {
} }
}; };
let tasks: Vec<Box<dyn Task>> = vec![
Box::new(WifiTask::new(peripherals.modem, sys_loop.clone(), &nvs)),
];
const POWER_VOLTS : u32 = 5; const POWER_VOLTS : u32 = 5;
const POWER_MA : u32 = 500; const POWER_MA : u32 = 500;
const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA; const MAX_POWER_MW : u32 = POWER_VOLTS * POWER_MA;
@ -92,7 +90,8 @@ impl<'a> Board for Esp32Board<'a> {
Esp32Board { Esp32Board {
surfaces: Some(SurfacePool::new()), surfaces: Some(SurfacePool::new()),
output: Some(output), output: Some(output),
tasks: Some(tasks), modem: Some(peripherals.modem),
sys_loop: sys_loop.clone(),
} }
} }
@ -104,8 +103,11 @@ impl<'a> Board for Esp32Board<'a> {
self.surfaces.take().unwrap() self.surfaces.take().unwrap()
} }
fn system_tasks(&mut self) -> Vec<Box<dyn Task>> { fn system_tasks(&mut self) -> Self::Scheduler {
self.tasks.take().unwrap() let nvs = EspDefaultNvsPartition::take().unwrap();
FixedSizeScheduler::new([
Box::new(WifiTask::new(self.modem.take().unwrap(), self.sys_loop.clone(), &nvs)),
])
} }
} }

View File

@ -9,14 +9,15 @@ pub mod esp32;
pub type DefaultBoard = esp32::Esp32Board; pub type DefaultBoard = esp32::Esp32Board;
use crate::render::{Output, Surfaces}; use crate::render::{Output, Surfaces};
use crate::task::Task; use crate::task::Scheduler;
pub trait Board { pub trait Board {
type Output: Output; type Output: Output;
type Surfaces: Surfaces; type Surfaces: Surfaces;
type Scheduler: Scheduler;
fn take() -> Self; fn take() -> Self;
fn output(&mut self) -> Self::Output; fn output(&mut self) -> Self::Output;
fn surfaces(&mut self) -> Self::Surfaces; fn surfaces(&mut self) -> Self::Surfaces;
fn system_tasks(&mut self) -> Vec<Box<dyn Task>>; fn system_tasks(&mut self) -> Self::Scheduler;
} }

View File

@ -77,25 +77,35 @@ impl ScheduledTask {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Scheduler { pub struct FixedSizeScheduler<const TASK_COUNT: usize> {
tasks: Vec<ScheduledTask>, tasks: [Option<ScheduledTask>; TASK_COUNT],
} }
impl Scheduler { impl<const TASK_COUNT: usize> FixedSizeScheduler<TASK_COUNT> {
pub fn new(tasks: Vec<Box<dyn Task>>) -> Self { pub fn new(tasks: [Box<dyn Task>; TASK_COUNT]) -> Self {
let mut scheduled = Vec::new(); let mut scheduled = [const { None }; TASK_COUNT];
let mut idx = 0;
for task in tasks { for task in tasks {
log::info!("Scheduling task {} {:?}", task.name(), task); scheduled[idx] = Some(ScheduledTask::new(task));
scheduled.push(ScheduledTask::new(task)); idx += 1;
} }
Scheduler { FixedSizeScheduler {
tasks: scheduled tasks: scheduled
} }
} }
}
pub fn tick(&mut self) { impl<const TASK_COUNT: usize> Scheduler for FixedSizeScheduler<TASK_COUNT> {
for task in &mut self.tasks { fn tick(&mut self) {
task.tick(); for slot in &mut self.tasks {
match slot {
Some(task) => task.tick(),
_ => ()
}
} }
} }
} }
pub trait Scheduler {
fn tick(&mut self);
}