hal-sim 0.5.1

An embedded-hal and embedded-graphics Display simulator.
Documentation
use log::trace;

use embassy_futures::select::select;

use embassy_sync::blocking_mutex::raw::{NoopRawMutex, RawMutex};
use embassy_sync::mutex::Mutex as AsyncMutex;

use channel_bridge::asynch::{Receiver, Sender};
use channel_bridge::notification::Notification;

use crate::display::Change as DisplayChange;
use crate::gpio::Change as PinChange;
use crate::peripherals::Peripherals;

pub use crate::dto::*;

pub(crate) static NOTIFY: Notification = Notification::new();

pub fn peripherals_callback() {
    NOTIFY.notify();
}

pub async fn process<S, R>(sender: S, receiver: R)
where
    S: Sender<Data = UpdateEvent>,
    R: Receiver<Data = UpdateRequest, Error = S::Error>,
{
    handle(sender, receiver, &mut None, &mut None, &NOTIFY)
        .await
        .unwrap();
}

pub async fn handle<S, R>(
    sender: S,
    receiver: R,
    pins_changes: &mut Option<Vec<PinChange>>,
    displays_changes: &mut Option<Vec<DisplayChange>>,
    notification: &Notification,
) -> Result<(), S::Error>
where
    S: Sender<Data = UpdateEvent>,
    R: Receiver<Data = UpdateRequest, Error = S::Error>,
{
    let sender = AsyncMutex::<NoopRawMutex, _>::new(sender);

    select(
        receive(receiver),
        send(&sender, pins_changes, displays_changes, notification),
    )
    .await;

    Ok(())
}

async fn receive<R>(mut receiver: R) -> Result<(), R::Error>
where
    R: Receiver<Data = UpdateRequest>,
{
    loop {
        Peripherals::apply(receiver.recv().await?);
    }
}

async fn send<S>(
    sender: &AsyncMutex<impl RawMutex, S>,
    pins_changes: &mut Option<Vec<PinChange>>,
    displays_changes: &mut Option<Vec<DisplayChange>>,
    notification: &Notification,
) -> Result<(), S::Error>
where
    S: Sender<Data = UpdateEvent>,
{
    loop {
        notification.wait().await;

        let mut sender = sender.lock().await;

        while let Some(event) = Peripherals::fetch(pins_changes, displays_changes) {
            trace!("SENDING: {:?}", event);
            sender.send(event).await?;
        }
    }
}