hal_sim/
io.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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?;
        }
    }
}