use embedded_hal_async::delay::DelayNs;
use crate::DisplayBus;
#[derive(Clone, Copy)]
pub enum InitStep<'a> {
SingleCommand(u8),
CommandWithParams(u8, &'a [u8]),
DelayMs(u8),
Nop,
Nested(&'a [InitStep<'a>]),
}
impl InitStep<'static> {
pub const fn maybe_cmd(cmd: Option<u8>) -> Self {
match cmd {
Some(cmd) => Self::SingleCommand(cmd),
None => Self::Nop,
}
}
pub const fn cmd_if(cond: bool, cmd: u8) -> Self {
Self::SingleCommand(if cond { cmd } else { 0 })
}
pub const fn cmd_if_with<const N: usize>(
cond: bool,
cmd: u8,
params: &'static [u8; N],
) -> Self {
Self::CommandWithParams(if cond { cmd } else { 0 }, params)
}
pub const fn maybe_cmd_with<const N: usize>(cmd: u8, params: Option<&'static [u8; N]>) -> Self {
match params {
Some(p) => Self::CommandWithParams(cmd, p),
None => Self::Nop,
}
}
pub const fn select_cmd(cond: bool, cmd_true: u8, cmd_false: u8) -> Self {
Self::SingleCommand(if cond { cmd_true } else { cmd_false })
}
}
pub struct SequencedInit<'a, D: DelayNs, B: DisplayBus, I: Iterator<Item = InitStep<'a>>> {
steps: I,
delay: &'a mut D,
display_bus: &'a mut B,
}
impl<'a, D: DelayNs, B: DisplayBus, I: Iterator<Item = InitStep<'a>>> SequencedInit<'a, D, B, I> {
pub fn new(steps: I, delay: &'a mut D, display_bus: &'a mut B) -> Self {
Self {
steps,
delay,
display_bus,
}
}
async fn exec_atomic_step(&mut self, step: InitStep<'a>) -> Result<(), B::Error> {
match step {
InitStep::SingleCommand(cmd) => self.display_bus.write_cmd(&[cmd]).await,
InitStep::CommandWithParams(cmd, data) => {
self.display_bus.write_cmd_with_params(&[cmd], data).await
}
InitStep::DelayMs(ms) => {
self.delay.delay_ms(ms as u32).await;
Ok(())
}
InitStep::Nop => Ok(()),
InitStep::Nested(_) => {
panic!("We only support 1 level in InitStep.");
}
}
}
pub async fn sequenced_init(&mut self) -> Result<(), B::Error> {
while let Some(step) = self.steps.next() {
match step {
InitStep::Nested(sub_steps) => {
for sub_step in sub_steps.iter() {
self.exec_atomic_step(*sub_step).await?;
}
}
_ => self.exec_atomic_step(step).await?,
}
}
Ok(())
}
}
pub async fn sequenced_init<'a, D: DelayNs, B: DisplayBus, I: Iterator<Item = InitStep<'a>>>(
steps: I,
delay: &'a mut D,
display_bus: &'a mut B,
) -> Result<(), B::Error> {
SequencedInit::new(steps, delay, display_bus)
.sequenced_init()
.await
}