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]
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
//! 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 crate::request::Request;
/// Hardcoded commit hash of the most recent firmware
static COMMIT_HASH: &'static str = "bc459c80cec755d7df2c11a807d74e085cbed332";
use crate::{request::Request, build_request};
macro_rules! log {
($text: literal, $($arg:tt)*) => (println!(concat!("[B15F] ", $text), $($arg)*));
@ -31,6 +29,8 @@ pub struct B15F {
}
impl B15F {
const MSG_OK: u8 = 0xFF;
/// Creates a new instance of the B15
///
/// This function will establish a connection to a connected B15 and return
@ -52,19 +52,32 @@ impl B15F {
};
log_start!("Testing connection");
for tries in 0..3 {
let mut tries = 3;
while tries > 0 {
drv.discard();
match drv.test_connection() {
Ok(()) => break,
Err(_) => {} // Do nothing
};
tries -= 1;
}
if tries == 0 {
panic!("Testing connection failed!");
}
log_end!("Ok!");
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!".into());
}
// 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!".into());
// }
Ok(drv)
}
@ -112,16 +125,34 @@ impl B15F {
/// Clears data in the USART buffers on this device and on the B15
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();
for i in 0..16 {
self.usart.write(&Request::new().discard().done()[..]).unwrap();
for _ in 0..16 {
self.usart.write(build_request![Request::Discard]).unwrap();
sleep(Duration::from_millis(4));
}
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"))]
fn get_devices() -> Vec<String> {
let output = Command::new("bash")

View file

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

View file

@ -5,26 +5,18 @@
//! if you are trying to interact with the B15 consider using
//! 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)]
enum RequestType {
Discard = 0
}
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
}
pub enum Request {
Discard = 0,
Test = 1
}