use crate::serial_core::codec::Codec; use crate::serial_core::codecs::tactile_a::TactileACodec; use crate::serial_core::frame::TactileAFrame; use crate::serial_core::utils::elapsed_millis; use crossbeam_channel::{Receiver, Sender, TryRecvError}; use std::io::{Read, Write}; use std::time::{Duration, Instant}; const POLL_INTERVAL_MS: u64 = 10; /// Runs the serial polling loop on the calling (background) thread. /// Sends decoded pressure matrix data (Vec) to the output channel. pub fn run_serial_loop( port: &mut dyn ReadWrite, rows: usize, cols: usize, cancel_rx: &Receiver<()>, sample_tx: &Sender>, ) { let session_started_at = Instant::now(); let mut codec = TactileACodec::new(cols, rows); let req_frame = TactileACodec::build_req_frame(cols, rows); let mut buffer = [0u8; 1024]; let mut poll_interval = Duration::from_millis(POLL_INTERVAL_MS); loop { // Check cancel if cancel_rx.try_recv().is_ok() { break; } // Send poll request if let Ok(req_bytes) = codec.encode(&req_frame) { let _ = port.write_all(&req_bytes); } // Read response with poll interval let deadline = Instant::now() + poll_interval; loop { if Instant::now() >= deadline { break; } match port.read(&mut buffer) { Ok(n) if n > 0 => { if let Ok(frames) = codec.decode(&buffer[..n], session_started_at) { for frame in frames { if let TactileAFrame::Rep(rep) = frame { if let Ok(vals) = TactileACodec::parse_data_frame(&rep.payload) { let _ = sample_tx.try_send(vals); } } } } } Ok(_) => { std::thread::sleep(Duration::from_millis(1)); } Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => { continue; } Err(e) => { eprintln!("[serial] read error: {e}"); return; } } } } } /// Trait abstracting read+write for the serial port pub trait ReadWrite: Send { fn read(&mut self, buf: &mut [u8]) -> std::io::Result; fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()>; } /// Wrapper for serialport's Box pub struct SerialPortReadWrite { inner: Box, } impl SerialPortReadWrite { pub fn new(port: Box) -> Self { Self { inner: port } } } impl ReadWrite for SerialPortReadWrite { fn read(&mut self, buf: &mut [u8]) -> std::io::Result { self.inner.read(buf) } fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> { self.inner.write_all(buf) } }