add simple request building macros

This commit is contained in:
Robert 2022-12-16 00:02:22 +01:00
parent ca5125eaf9
commit c6523b70d3
4 changed files with 60 additions and 35 deletions

View file

@ -11,3 +11,5 @@ path = "src/lib.rs"
[dependencies] [dependencies]
serialport = "4.2.0" serialport = "4.2.0"
rand = "0.8.5"

View file

@ -2,13 +2,11 @@
//! interacting with the B15 on a high level. If you are writing code //! interacting with the B15 on a high level. If you are writing code
//! for the B15, this is the module you want to use. //! for the B15, this is the module you want to use.
use std::{process::Command, time::Duration, fmt::{Debug, Display}, thread::sleep, error::Error}; use std::{process::Command, time::Duration, fmt::Debug, thread::sleep};
use rand::Rng;
use serialport::SerialPort; use serialport::SerialPort;
use crate::request::Request; use crate::{request::Request, build_request};
/// Hardcoded commit hash of the most recent firmware
static COMMIT_HASH: &'static str = "bc459c80cec755d7df2c11a807d74e085cbed332";
macro_rules! log { macro_rules! log {
($text: literal, $($arg:tt)*) => (println!(concat!("[B15F] ", $text), $($arg)*)); ($text: literal, $($arg:tt)*) => (println!(concat!("[B15F] ", $text), $($arg)*));
@ -31,6 +29,8 @@ pub struct B15F {
} }
impl B15F { impl B15F {
const MSG_OK: u8 = 0xFF;
/// Creates a new instance of the B15 /// Creates a new instance of the B15
/// ///
/// This function will establish a connection to a connected B15 and return /// This function will establish a connection to a connected B15 and return
@ -52,19 +52,32 @@ impl B15F {
}; };
log_start!("Testing connection"); log_start!("Testing connection");
for tries in 0..3 { let mut tries = 3;
while tries > 0 {
drv.discard(); drv.discard();
match drv.test_connection() {
Ok(()) => break,
Err(_) => {} // Do nothing
};
tries -= 1;
} }
if tries == 0 {
panic!("Testing connection failed!");
}
log_end!("Ok!"); log_end!("Ok!");
let info = drv.get_board_info(); let info = drv.get_board_info();
log!("AVR firmware version: {} built at {} ({})", info[0], info[1], info[2]); log!("AVR firmware version: {} built at {} ({})", info[0], info[1], info[2]);
let avr_commit_hash = info[3]; // let avr_commit_hash = info[3];
if avr_commit_hash != COMMIT_HASH { // if avr_commit_hash != COMMIT_HASH {
log!("Different commit hashes: {} vs {}", avr_commit_hash, COMMIT_HASH); // log!("Different commit hashes: {} vs {}", avr_commit_hash, COMMIT_HASH);
return Err("Versions incompatible. Please update the software!".into()); // return Err("Versions incompatible. Please update the software!".into());
} // }
Ok(drv) Ok(drv)
} }
@ -112,16 +125,34 @@ impl B15F {
/// Clears data in the USART buffers on this device and on the B15 /// Clears data in the USART buffers on this device and on the B15
pub fn discard(&mut self) { pub fn discard(&mut self) {
// TODO: In general, unwrap() will cause panic on failure and crash the application.
// It would be better to implement error handling
self.usart.clear(serialport::ClearBuffer::Output).unwrap(); self.usart.clear(serialport::ClearBuffer::Output).unwrap();
for i in 0..16 { for _ in 0..16 {
self.usart.write(&Request::new().discard().done()[..]).unwrap(); self.usart.write(build_request![Request::Discard]).unwrap();
sleep(Duration::from_millis(4)); sleep(Duration::from_millis(4));
} }
self.usart.clear(serialport::ClearBuffer::Input).unwrap() self.usart.clear(serialport::ClearBuffer::Input).unwrap()
} }
/// Tests the connetion to the B15
pub fn test_connection(&mut self) -> Result<(), String> {
let dummy: u8 = rand::thread_rng().gen_range(0x00..=0xFF);
self.usart.write(build_request![Request::Test, dummy]).unwrap();
let mut buffer: [u8; 2]= [0; 2];
self.usart.read(&mut buffer).unwrap();
if buffer[0] != B15F::MSG_OK || buffer[1] != dummy {
panic!("Test request failed");
}
Ok(())
}
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))] #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
fn get_devices() -> Vec<String> { fn get_devices() -> Vec<String> {
let output = Command::new("bash") let output = Command::new("bash")

View file

@ -1,6 +1,6 @@
#![deny(missing_docs, #![deny(missing_docs,
missing_debug_implementations, missing_debug_implementations,
trivial_casts, trivial_numeric_casts, trivial_casts,
unsafe_code, unsafe_code,
unstable_features, unstable_features,
unused_import_braces, unused_qualifications)] unused_import_braces, unused_qualifications)]

View file

@ -5,26 +5,18 @@
//! if you are trying to interact with the B15 consider using //! if you are trying to interact with the B15 consider using
//! the `b15f::B15F` structure instead. //! the `b15f::B15F` structure instead.
// TODO: There should be a more elegant way to do this
#[macro_export]
/// Builds a new request buffer from the given data
macro_rules! build_request {
[$($x:expr),*] => (
&[$($x as u8),*]
);
}
#[repr(u8)] #[repr(u8)]
enum RequestType { pub enum Request {
Discard = 0 Discard = 0,
} Test = 1
pub struct Request {
req: Vec<u8>
}
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<u8> {
self.req
}
} }