Add uart Header struct

This commit is contained in:
2023-05-29 17:14:30 +02:00
parent fa3b1502d7
commit 59f91e2f6b
4 changed files with 52 additions and 13 deletions

15
Cargo.lock generated
View File

@ -103,6 +103,20 @@ name = "bytemuck"
version = "1.13.1" version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.16",
]
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -1331,6 +1345,7 @@ name = "tangentbord1"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"atomic-polyfill 1.0.2", "atomic-polyfill 1.0.2",
"bytemuck",
"cortex-m", "cortex-m",
"cortex-m-rt", "cortex-m-rt",
"crc-any", "crc-any",

View File

@ -37,6 +37,7 @@ atomic-polyfill = "1.0.2"
critical-section = "1.1.1" critical-section = "1.1.1"
crc-any = "2.4.3" crc-any = "2.4.3"
serde = { version = "1.0.163", default-features = false, features = ["derive"] } serde = { version = "1.0.163", default-features = false, features = ["derive"] }
bytemuck = { version = "1.13.1", features = ["derive"] }
#[patch."https://git.nubo.sh/hulthe/tgnt.git"] #[patch."https://git.nubo.sh/hulthe/tgnt.git"]
#tgnt = { path = "../tgnt" } #tgnt = { path = "../tgnt" }

View File

@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
#![feature(split_array)]
use embassy_rp::{ use embassy_rp::{
bind_interrupts, bind_interrupts,

View File

@ -1,3 +1,6 @@
use core::mem::size_of;
use bytemuck::{cast, AnyBitPattern, NoUninit};
use crc_any::CRCu16; use crc_any::CRCu16;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::peripherals::{PIN_0, PIN_1, UART0}; use embassy_rp::peripherals::{PIN_0, PIN_1, UART0};
@ -46,26 +49,41 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
let (mut rx, mut tx) = uart.split(); let (mut rx, mut tx) = uart.split();
let (mut events_rx, mut events_tx) = events.split(); let (mut events_rx, mut events_tx) = events.split();
const HEADER_LEN: usize = 4; #[repr(C)]
#[derive(Clone, Copy, Debug, NoUninit, AnyBitPattern)]
struct Header {
/// The length of the payload.
len: u8,
/// An arbitrary value to feed the crc, should be different for each message.
random: u8,
/// A little-endian crc16.
crc: [u8; 2],
}
const HEADER_LEN: usize = size_of::<Header>();
let rx_task = async { let rx_task = async {
let mut buf: heapless::Vec<u8, 1024> = Vec::new(); let mut buf: heapless::Vec<u8, 1024> = Vec::new();
loop { loop {
if let &[len, random, crc1, crc2, ref rest @ ..] = buf.as_slice() { if buf.len() >= HEADER_LEN {
let crc = u16::from_le_bytes([crc1, crc2]); let (&header, rest) = buf.split_array_ref::<HEADER_LEN>();
let header: Header = cast(header);
let crc = u16::from_le_bytes(header.crc);
let mut calculated_crc = CRCu16::crc16(); let mut calculated_crc = CRCu16::crc16();
calculated_crc.digest(&[len, random]); calculated_crc.digest(&[header.len, header.random]);
let calculated_crc = calculated_crc.get_crc(); let calculated_crc = calculated_crc.get_crc();
if calculated_crc != crc { if calculated_crc != crc {
log::error!("invalid uart package crc: {:x?}", &buf[..HEADER_LEN]); log::error!("invalid uart header crc: {header:x?}");
buf.remove(0); // pop the first byte and hope we find a good packet header buf.remove(0); // pop the first byte and hope we find a good packet header
continue; continue;
} }
log::debug!("got uart header {:x?}", &buf[..HEADER_LEN]); log::debug!("got uart header {header:x?}");
let len = usize::from(len); let len = usize::from(header.len);
if rest.len() >= len { if rest.len() >= len {
let r = postcard::from_bytes(&rest[..len]); let r = postcard::from_bytes(&rest[..len]);
@ -106,7 +124,7 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
let tx_task = async { let tx_task = async {
let mut buf = [0u8; 256 + HEADER_LEN]; let mut buf = [0u8; 256 + HEADER_LEN];
let mut counter = 1u8; let mut counter = 0u8;
loop { loop {
// forward messages to the other keyboard half // forward messages to the other keyboard half
let event = events_rx.recv().await; let event = events_rx.recv().await;
@ -115,7 +133,7 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
} }
let message = Message::KeyboardEvent(event); let message = Message::KeyboardEvent(event);
let (header, body) = buf.split_at_mut(HEADER_LEN); let (buf_header, body) = buf.split_array_mut();
let serialized = match postcard::to_slice(&message, body) { let serialized = match postcard::to_slice(&message, body) {
Ok(s) => s, Ok(s) => s,
Err(e) => { Err(e) => {
@ -125,16 +143,20 @@ async fn uart_task(uart: BufferedUart<'static, UART0>, this_half: Half, mut even
}; };
// add a "random" value to feed the crc // add a "random" value to feed the crc
let random = counter;
counter = counter.wrapping_add(1); counter = counter.wrapping_add(1);
let random = counter;
let len = serialized.len() as u8; let len = serialized.len() as u8;
let mut crc = CRCu16::crc16(); let mut crc = CRCu16::crc16();
crc.digest(&[len, random]); crc.digest(&[len, random]);
let [crc1, crc2] = crc.get_crc().to_le_bytes(); let header = Header {
len: serialized.len() as u8,
header.copy_from_slice(&[len, random, crc1, crc2]); random,
crc: crc.get_crc().to_le_bytes(),
};
let header: [u8; HEADER_LEN] = cast(header);
*buf_header = header;
let package = &buf[..HEADER_LEN + usize::from(len)]; let package = &buf[..HEADER_LEN + usize::from(len)];
tx.write_all(package).await.ok(); tx.write_all(package).await.ok();