use crate::std;
use std::fmt;
use crate::{
impl_message_ops, impl_omnibus_nop_reply,
len::{BAUD_CHANGE_REPLY, BAUD_CHANGE_REQUEST},
MessageOps, MessageType,
};
#[allow(dead_code)]
pub mod index {
pub const DATA0: usize = 3;
pub const BAUD_RATE: usize = 3;
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub enum BaudRate {
#[default]
_9600 = 0x01,
_19200 = 0x02,
_38400 = 0x03,
_115200 = 0x04,
Reserved = 0xff,
}
impl From<u8> for BaudRate {
fn from(b: u8) -> Self {
match b {
0x01 => Self::_9600,
0x02 => Self::_19200,
0x03 => Self::_38400,
0x04 => Self::_115200,
_ => Self::Reserved,
}
}
}
impl From<u32> for BaudRate {
fn from(b: u32) -> Self {
match b {
9_600 => Self::_9600,
19_200 => Self::_19200,
38_400 => Self::_38400,
115_200 => Self::_115200,
_ => Self::_9600,
}
}
}
impl From<BaudRate> for u8 {
fn from(b: BaudRate) -> Self {
b as u8
}
}
impl From<&BaudRate> for u8 {
fn from(b: &BaudRate) -> Self {
(*b).into()
}
}
impl From<BaudRate> for u32 {
fn from(b: BaudRate) -> Self {
match b {
BaudRate::_9600 => 9_600,
BaudRate::_19200 => 19_200,
BaudRate::_38400 => 38_400,
BaudRate::_115200 => 115_200,
_ => 9_600,
}
}
}
impl From<&BaudRate> for u32 {
fn from(b: &BaudRate) -> Self {
(*b).into()
}
}
impl From<BaudRate> for &'static str {
fn from(b: BaudRate) -> Self {
match b {
BaudRate::_9600 => "9600",
BaudRate::_19200 => "19200",
BaudRate::_38400 => "38400",
BaudRate::_115200 => "115200",
BaudRate::Reserved => "Reserved",
}
}
}
impl From<&BaudRate> for &'static str {
fn from(b: &BaudRate) -> Self {
(*b).into()
}
}
impl fmt::Display for BaudRate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let b: &str = self.into();
write!(f, "{b}")
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct BaudRateChangeRequest {
buf: [u8; BAUD_CHANGE_REQUEST],
}
impl BaudRateChangeRequest {
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; BAUD_CHANGE_REQUEST],
};
msg.init();
msg.set_message_type(MessageType::FirmwareDownload);
msg
}
pub fn baud_rate(&self) -> BaudRate {
self.buf[index::DATA0].into()
}
pub fn set_baud_rate(&mut self, baud_rate: BaudRate) {
match baud_rate {
BaudRate::Reserved => {
self.buf[index::DATA0] = BaudRate::_9600.into();
}
_ => {
self.buf[index::DATA0] = baud_rate.into();
}
}
}
}
impl_message_ops!(BaudRateChangeRequest);
impl fmt::Display for BaudRateChangeRequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AckNak: {}, DeviceType: {}, MessageType: {}, BaudRate: {}",
self.acknak(),
self.device_type(),
self.message_type(),
self.baud_rate(),
)
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct BaudRateChangeReply {
buf: [u8; BAUD_CHANGE_REPLY],
}
impl BaudRateChangeReply {
pub fn new() -> Self {
let mut msg = Self {
buf: [0u8; BAUD_CHANGE_REQUEST],
};
msg.init();
msg.set_message_type(MessageType::FirmwareDownload);
msg
}
pub fn baud_rate(&self) -> BaudRate {
self.buf[index::DATA0].into()
}
pub fn set_baud_rate(&mut self, baud_rate: BaudRate) {
match baud_rate {
BaudRate::Reserved => {
self.buf[index::DATA0] = BaudRate::_9600.into();
}
_ => {
self.buf[index::DATA0] = baud_rate.into();
}
}
}
}
impl_message_ops!(BaudRateChangeReply);
impl_omnibus_nop_reply!(BaudRateChangeReply);
impl fmt::Display for BaudRateChangeReply {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"AckNak: {}, DeviceType: {}, MessageType: {}, BaudRate: {}",
self.acknak(),
self.device_type(),
self.message_type(),
self.baud_rate(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Result;
#[test]
#[rustfmt::skip]
fn test_baud_rate_change_request_from_bytes() -> Result<()> {
let mut msg_bytes = [
0x02, 0x06, 0x50,
0x01,
0x03, 0x57,
];
let mut msg = BaudRateChangeRequest::new();
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_9600);
msg_bytes = [
0x02, 0x06, 0x50,
0x02,
0x03, 0x54,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_19200);
msg_bytes = [
0x02, 0x06, 0x50,
0x03,
0x03, 0x55,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_38400);
msg_bytes = [
0x02, 0x06, 0x50,
0x04,
0x03, 0x52,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_115200);
Ok(())
}
#[test]
#[rustfmt::skip]
fn test_baud_rate_change_reply_from_bytes() -> Result<()> {
let mut msg_bytes = [
0x02, 0x06, 0x50,
0x01,
0x03, 0x57,
];
let mut msg = BaudRateChangeReply::new();
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_9600);
msg_bytes = [
0x02, 0x06, 0x50,
0x02,
0x03, 0x54,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_19200);
msg_bytes = [
0x02, 0x06, 0x50,
0x03,
0x03, 0x55,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_38400);
msg_bytes = [
0x02, 0x06, 0x50,
0x04,
0x03, 0x52,
];
msg.from_buf(msg_bytes.as_ref())?;
assert_eq!(msg.message_type(), MessageType::FirmwareDownload);
assert_eq!(msg.baud_rate(), BaudRate::_115200);
Ok(())
}
}