Files
tangentbord1/src/uart.rs

89 lines
2.8 KiB
Rust

use core::mem::{size_of, transmute};
use embassy_executor::Spawner;
use embassy_rp::interrupt;
use embassy_rp::peripherals::{PIN_0, PIN_1, UART0};
use embassy_rp::uart::{self, BufferedUart, DataBits, Parity, StopBits};
use embassy_time::{with_timeout, Duration, TimeoutError};
use embedded_io::asynch::{Read, Write};
use futures::{select_biased, FutureExt};
use log::{error, info};
use static_cell::StaticCell;
use crate::keyboard::{self, Half, KbEvents};
#[derive(Clone, Debug)]
enum Message {
KeyboardEvent(keyboard::Event),
}
pub async fn start(tx: PIN_0, rx: PIN_1, uart: UART0, board: Half, events: KbEvents) {
static TX_BUF: StaticCell<[u8; 1024]> = StaticCell::new();
static RX_BUF: StaticCell<[u8; 1024]> = StaticCell::new();
let mut config = uart::Config::default();
config.baudrate = 115200;
config.data_bits = DataBits::DataBits8;
config.stop_bits = StopBits::STOP1;
config.parity = Parity::ParityNone;
let uart = embassy_rp::uart::BufferedUart::new(
uart,
interrupt::take!(UART0_IRQ),
tx,
rx,
TX_BUF.init_with(|| [0u8; 1024]),
RX_BUF.init_with(|| [0u8; 1024]),
config,
);
Spawner::for_current_executor()
.await
.must_spawn(uart_task(uart, board, events))
}
#[embassy_executor::task]
async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut events: KbEvents) {
let (mut rx, mut tx) = uart.split();
let (mut events_rx, mut events_tx) = events.split();
let rx_task = async {
loop {
let mut buf = [0u8; size_of::<Message>()];
// TODO: this timout thing seems sketchy
match with_timeout(Duration::from_millis(5), rx.read_exact(&mut buf)).await {
Ok(Ok(_)) => {}
Ok(Err(e)) => {
error!("uart error: {:?}", e);
continue;
}
Err(TimeoutError) => continue,
};
let message: Message = unsafe { transmute(buf) }; // crimes :)
info!("got msg: {:?}", message);
match message {
Message::KeyboardEvent(event) => events_tx.send(event),
}
}
};
let tx_task = async {
loop {
// forward messages to the other keyboard half
let event = events_rx.recv().await;
if event.source != this_half {
continue; // do not forward messages from the other half back to it
}
let message = Message::KeyboardEvent(event);
let message: [u8; size_of::<Message>()] = unsafe { transmute(message) }; // crimes :)
tx.write_all(&message).await.ok();
}
};
select_biased! {
_ = tx_task.fuse() => error!("uart tx_task exited"),
_ = rx_task.fuse() => error!("eart rx_task exited"),
}
}