diff --git a/Cargo.toml b/Cargo.toml index 94b41a2..0dd5c3b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,4 @@ name = "b15f" path = "src/lib.rs" [dependencies] - +serialport = "4.2.0" diff --git a/src/b15f.rs b/src/b15f.rs index b9410a5..ed72cb6 100644 --- a/src/b15f.rs +++ b/src/b15f.rs @@ -2,7 +2,10 @@ //! interacting with the B15 on a high level. If you are writing code //! for the B15, this is the module you want to use. -use std::process::Command; +use std::{process::Command, time::Duration, fmt::{Debug, Display}, thread::sleep, error::Error}; +use serialport::SerialPort; + +use crate::request::Request; /// Hardcoded commit hash of the most recent firmware static COMMIT_HASH: &'static str = "bc459c80cec755d7df2c11a807d74e085cbed332"; @@ -23,9 +26,8 @@ macro_rules! log_end { } /// Structure representing the driver for the board 15 -#[derive(Debug)] pub struct B15F { - + usart: Box } impl B15F { @@ -42,39 +44,50 @@ impl B15F { /// /// let drv = B15F::new().unwrap(); /// ``` - pub fn new() -> Result { - let drv = B15F {}; - drv.init() - } + pub fn new() -> Result { + let port = B15F::init_connection()?; - fn init(self) -> Result { - let devices = B15F::get_devices(); - - let device = match devices.first() { - Some(item) => item, - None => return Err("Failed to find adapter") + let mut drv =B15F { + usart: port }; - log!("Using adapter: {}", device); - - log_start!("Establish connection with adapter"); - todo!("Implement USART"); - log_end!("Ok!"); - log_start!("Testing connection"); - todo!("Test connection"); + for tries in 0..3 { + drv.discard(); + } log_end!("Ok!"); - let info = self.get_board_info(); + let info = drv.get_board_info(); log!("AVR firmware version: {} built at {} ({})", info[0], info[1], info[2]); let avr_commit_hash = info[3]; if avr_commit_hash != COMMIT_HASH { log!("Different commit hashes: {} vs {}", avr_commit_hash, COMMIT_HASH); - return Err("Versions incompatible. Please update the software!"); + return Err("Versions incompatible. Please update the software!".into()); } - Ok(self) + Ok(drv) + } + + fn init_connection() -> Result, String> { + let devices = B15F::get_devices(); + + let device = match devices.first() { + Some(item) => item, + None => return Err("Failed to find adapter".into()) + }; + + log!("Using adapter: {}", device); + + log_start!("Establish connection with adapter"); + + let port = serialport::new(device, 57_600) + .timeout(Duration::from_millis(1000)) + .open() + .map_err(|err| err.to_string())?; + log_end!("Ok!"); + + Ok(port) } /// Yields information about the installed firmware on the B15 @@ -97,6 +110,18 @@ impl B15F { todo!(); } + /// Clears data in the USART buffers on this device and on the B15 + pub fn discard(&mut self) { + self.usart.clear(serialport::ClearBuffer::Output).unwrap(); + + for i in 0..16 { + self.usart.write(&Request::new().discard().done()[..]).unwrap(); + sleep(Duration::from_millis(4)); + } + + self.usart.clear(serialport::ClearBuffer::Input).unwrap() + } + #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] fn get_devices() -> Vec { let output = Command::new("bash") @@ -127,4 +152,12 @@ impl B15F { .map(|item| item.into()) .collect() } +} + +impl Debug for B15F { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "Baudrate: {}", self.usart.baud_rate().unwrap())?; + writeln!(f, "Data bits: {:?}", self.usart.data_bits().unwrap())?; + writeln!(f, "Parity: {:?}", self.usart.parity().unwrap()) + } } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 558002d..53e291b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,4 +14,6 @@ //! [`original`]: https://github.com/devfix/b15f pub mod b15f; +mod request; + pub use crate::b15f::B15F; \ No newline at end of file diff --git a/src/request.rs b/src/request.rs new file mode 100644 index 0000000..8af5ed4 --- /dev/null +++ b/src/request.rs @@ -0,0 +1,30 @@ +//! This module contains the request data used to communicate +//! with the B15 via USART. +//! +//! Using a direct USART connection to the B15 is discouraged, +//! if you are trying to interact with the B15 consider using +//! the `b15f::B15F` structure instead. + +#[repr(u8)] +enum RequestType { + Discard = 0 +} + +pub struct Request { + req: Vec +} + +impl Request { + pub fn new() -> Request { + Request { req: vec![] } + } + + pub fn discard(mut self) -> Self { + self.req.push(RequestType::Discard as u8); + self + } + + pub fn done(self) -> Vec { + self.req + } +} \ No newline at end of file