use std::{
io,
time::{Duration, Instant},
};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use crate::Optolink;
const RESET: u8 = 0x04;
const SYNC: u8 = 0x05;
#[allow(unused)]
#[non_exhaustive]
#[repr(u8)]
enum Function {
VirtualRead = 247,
VirtualWrite = 244,
GfaRead = 107,
GfaWrite = 104,
ProcessRead = 123,
ProcessWrite = 120,
}
#[derive(Debug)]
pub enum Vs1 {}
impl Vs1 {
async fn sync(o: &mut Optolink) -> Result<(), std::io::Error> {
log::trace!("Vs1::sync(…)");
let mut buf = [0xff];
Self::negotiate(o).await?;
loop {
log::trace!("Vs1::sync(…) loop");
if o.read_exact(&mut buf).await.is_ok() && buf == [SYNC] {
o.purge().await?;
return Ok(());
}
}
}
pub async fn negotiate(o: &mut Optolink) -> Result<(), io::Error> {
log::trace!("Vs1::negotiate(…)");
o.purge().await?;
o.write_all(&[RESET]).await?;
o.flush().await?;
Ok(())
}
pub async fn get(o: &mut Optolink, addr: u16, buf: &mut [u8]) -> Result<(), io::Error> {
log::trace!("Vs1::get(…)");
let mut vec = Vec::new();
vec.extend(&[0x01, Function::VirtualRead as u8]);
vec.extend(addr.to_be_bytes());
vec.extend(&[buf.len() as u8]);
Self::sync(o).await?;
loop {
log::trace!("Vs1::get(…) loop");
o.write_all(&vec).await?;
o.flush().await?;
let read_start = Instant::now();
o.read_exact(buf).await?;
let stop = Instant::now();
if buf.contains(&SYNC) {
let read_time = stop - read_start;
log::debug!(
"Vs1::get(…) buf = {}",
buf.iter().map(|b| format!("{:02X}", b)).collect::<Vec<String>>().join(" ")
);
log::debug!("Vs1::get(…) read_time = {:?}", read_time);
if read_time < Duration::from_millis(500 * buf.len() as u64) {
return Ok(());
}
o.purge().await?;
} else {
return Ok(());
}
}
}
pub async fn set(o: &mut Optolink, addr: u16, value: &[u8]) -> Result<(), io::Error> {
log::trace!("Vs1::set(…)");
let mut vec = Vec::new();
vec.extend(&[0x01, Function::VirtualWrite as u8]);
vec.extend(addr.to_be_bytes());
vec.extend(&[value.len() as u8]);
vec.extend(value);
Self::sync(o).await?;
loop {
o.write_all(&vec).await?;
o.flush().await?;
let mut buf = [0xff];
o.read_exact(&mut buf).await?;
if buf == [0x00] {
return Ok(());
}
}
}
}