use embedded_hal::digital::{InputPin, OutputPin};
use embedded_io::{ErrorType, Read, Write};
use hart_protocol::{
commands::{CommandRequest, CommandResponse},
consts::{DEFAULT_PREAMBLE_COUNT, MAX_FRAME_LENGTH},
decode::Decoder,
encode::encode_frame,
types::{Address, FrameType, ResponseStatus},
};
use crate::{blocking::Ad5700, error::HartError};
pub struct HartMasterBlocking<UART, RTS, CD> {
modem: Ad5700<UART, RTS, CD>,
decoder: Decoder,
tx_buf: [u8; MAX_FRAME_LENGTH],
rx_buf: [u8; MAX_FRAME_LENGTH],
preamble_count: u8,
}
impl<UART, RTS, CD> HartMasterBlocking<UART, RTS, CD>
where
UART: Read + Write,
RTS: OutputPin,
CD: InputPin,
{
pub fn new(modem: Ad5700<UART, RTS, CD>) -> Self {
HartMasterBlocking {
modem,
decoder: Decoder::new(),
tx_buf: [0u8; MAX_FRAME_LENGTH],
rx_buf: [0u8; MAX_FRAME_LENGTH],
preamble_count: DEFAULT_PREAMBLE_COUNT,
}
}
pub fn set_preamble_count(&mut self, count: u8) {
self.preamble_count = count;
}
pub fn send_command<Req, Resp>(
&mut self,
address: &Address,
request: &Req,
) -> Result<(ResponseStatus, Resp), HartError<<UART as ErrorType>::Error>>
where
Req: CommandRequest,
Resp: CommandResponse,
{
let mut data_buf = [0u8; 255];
let data_len = request
.encode_data(&mut data_buf)
.map_err(HartError::Encode)?;
let frame_len = encode_frame(
FrameType::Request,
address,
Req::COMMAND_NUMBER,
&data_buf[..data_len],
self.preamble_count,
&mut self.tx_buf,
)
.map_err(HartError::Encode)?;
self.modem
.transmit(&self.tx_buf[..frame_len])
.map_err(HartError::Modem)?;
self.decoder.reset();
loop {
let n = self
.modem
.receive_into(&mut self.rx_buf)
.map_err(HartError::Modem)?;
if n == 0 {
return Err(HartError::Timeout);
}
for i in 0..n {
match self.decoder.feed(self.rx_buf[i]) {
Ok(None) => {}
Ok(Some(frame)) => {
let data = frame.data.as_slice();
if data.len() < 2 {
return Err(HartError::Decode(
hart_protocol::error::DecodeError::BufferTooShort,
));
}
let status = ResponseStatus::from_bytes([data[0], data[1]]);
let resp = Resp::decode_data(&data[2..]).map_err(HartError::Decode)?;
return Ok((status, resp));
}
Err(e) => return Err(HartError::Decode(e)),
}
}
}
}
}