Break out stage IO into separate file.

Signed-off-by: Henner Zeller <h.zeller@acm.org>
This commit is contained in:
Henner Zeller 2026-03-08 12:48:39 +01:00
parent 4e946eef77
commit cc8152a75d
3 changed files with 61 additions and 54 deletions

View file

@ -3,6 +3,9 @@ use std::{thread::sleep, time::Duration};
mod stage; mod stage;
mod stage_io;
use crate::stage_io::StageIO;
#[derive(clap::Parser, Debug)] #[derive(clap::Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
struct CliArgs { struct CliArgs {
@ -18,7 +21,7 @@ struct CliArgs {
fn main() { fn main() {
let args = CliArgs::parse(); let args = CliArgs::parse();
env_logger::init(); env_logger::init();
let stage_io = stage::StageIO::new(&args.stage_device, args.tty_speed).unwrap(); let stage_io = StageIO::new(&args.stage_device, args.tty_speed).unwrap();
let mut s = stage::Stage::new(stage_io, 1.12).unwrap(); let mut s = stage::Stage::new(stage_io, 1.12).unwrap();
let origin = nalgebra::vector![3000.0, 0.0, -6000.0]; let origin = nalgebra::vector![3000.0, 0.0, -6000.0];
//println!("{}", s.version().unwrap()); //println!("{}", s.version().unwrap());

View file

@ -1,7 +1,6 @@
//! Stage controller for openflexure-delta like stage controllers. //! Stage controller for openflexure-delta like stage controllers.
use log::debug; use crate::stage_io::{StageIO, StageIOError};
use std::time::Duration;
use thiserror::Error; use thiserror::Error;
fn new_camera_rotation(theta: f64) -> nalgebra::Matrix3<f64> { fn new_camera_rotation(theta: f64) -> nalgebra::Matrix3<f64> {
@ -23,16 +22,6 @@ fn new_delta_into_cartesian(flex_h: f64, flex_a: f64, flex_b: f64) -> nalgebra::
] ]
} }
#[derive(Error, Debug)]
pub enum StageIOError {
#[error("could not connect to stage controller")]
Open(#[from] serialport::Error),
#[error("error when sending data to the stage controller")]
Write(std::io::Error),
#[error("error when receiving data from the stage controller")]
Read(std::io::Error),
}
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum StageError { pub enum StageError {
#[error("Interface issue")] #[error("Interface issue")]
@ -41,10 +30,6 @@ pub enum StageError {
Mumble, Mumble,
} }
pub struct StageIO {
serial: Box<dyn serialport::SerialPort>,
}
pub struct Stage { pub struct Stage {
stage_io: StageIO, stage_io: StageIO,
delta_pos: nalgebra::Vector3<i32>, delta_pos: nalgebra::Vector3<i32>,
@ -52,43 +37,6 @@ pub struct Stage {
delta_to_cartesian: nalgebra::Matrix3<f64>, delta_to_cartesian: nalgebra::Matrix3<f64>,
} }
pub type StageIOResult<T> = std::result::Result<T, StageIOError>;
impl StageIO {
pub fn new(port: &str, speed: u32) -> StageIOResult<Self> {
let serial = serialport::new(port, speed)
.timeout(Duration::from_secs(60))
.open()?;
// TODO: read and discard initial characters; some devices like to be
// chatty on start-up.
Ok(Self { serial })
}
fn receive_until<S: AsRef<str>>(&mut self, needle: S) -> StageIOResult<String> {
let mut res: Vec<u8> = vec![];
loop {
let mut buf = [0u8; 1];
self.serial
.read_exact(&mut buf)
.map_err(|e| StageIOError::Read(e))?;
res.push(buf[0]);
if res.ends_with(needle.as_ref().as_bytes()) {
return Ok(String::from_utf8_lossy(&res).to_string());
}
}
}
// Send request and wait for response deliminated with a newline
pub fn send_request<S: AsRef<str>>(&mut self, command: S) -> StageIOResult<String> {
debug!("->: {:?}", command.as_ref());
self.serial
.write_all(command.as_ref().as_bytes())
.map_err(|e| StageIOError::Write(e))?;
let response = self.receive_until("\n")?;
debug!("<-: {:?}", response);
Ok(response.trim().to_string())
}
}
pub type Result<T> = std::result::Result<T, StageError>; pub type Result<T> = std::result::Result<T, StageError>;
impl Stage { impl Stage {
pub fn new(stage_io: StageIO, camera_rotation: f64) -> Result<Self> { pub fn new(stage_io: StageIO, camera_rotation: f64) -> Result<Self> {

View file

@ -0,0 +1,56 @@
use log::debug;
use std::time::Duration;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum StageIOError {
#[error("could not connect to stage controller")]
Open(#[from] serialport::Error),
#[error("error when sending data to the stage controller")]
Write(std::io::Error),
#[error("error when receiving data from the stage controller")]
Read(std::io::Error),
}
pub struct StageIO {
serial: Box<dyn serialport::SerialPort>,
}
pub type StageIOResult<T> = std::result::Result<T, StageIOError>;
impl StageIO {
/// Create a new serial StageIO at given serial device and speed.
pub fn new(port: &str, speed: u32) -> StageIOResult<Self> {
let serial = serialport::new(port, speed)
.timeout(Duration::from_secs(60))
.open()?;
// TODO: read and discard initial characters; some devices like to be
// chatty on start-up.
Ok(Self { serial })
}
/// Receive data until the given character string "needle" is seen.
fn receive_until<S: AsRef<str>>(&mut self, needle: S) -> StageIOResult<String> {
let mut res: Vec<u8> = vec![];
loop {
let mut buf = [0u8; 1];
self.serial
.read_exact(&mut buf)
.map_err(|e| StageIOError::Read(e))?;
res.push(buf[0]);
if res.ends_with(needle.as_ref().as_bytes()) {
return Ok(String::from_utf8_lossy(&res).to_string());
}
}
}
/// Send request and wait for response deliminated with a newline
pub fn send_request<S: AsRef<str>>(&mut self, command: S) -> StageIOResult<String> {
debug!("->: {:?}", command.as_ref());
self.serial
.write_all(command.as_ref().as_bytes())
.map_err(|e| StageIOError::Write(e))?;
let response = self.receive_until("\n")?;
debug!("<-: {:?}", response);
Ok(response.trim().to_string())
}
}