#![no_std]
use heapless::{binary_heap::Min, BinaryHeap};
use crate::message::{CANAerospaceFrame, CANAerospaceMessage};
use crate::types::{
DataType, HardwareRevision, IDSConfiguration, IDSHeaderConfiguration, IDSResponse,
ServiceCodeEnum, SoftwareRevision,
};
use crate::{driver::CANAerospaceDriver, types::MessageType};
pub mod driver;
#[cfg(not(tarpaulin_include))]
#[cfg(feature = "ids-standard")]
pub mod id_distribution;
pub mod message;
mod tests;
pub mod types;
#[cfg(not(tarpaulin_include))]
#[cfg(feature = "bxcan-support")]
pub mod bxcan;
#[cfg(not(tarpaulin_include))]
#[cfg(feature = "ids-standard")]
pub use id_distribution as ids;
pub const IDS_CONF_STANDARD: IDSConfiguration = IDSConfiguration(0);
pub const IDS_MSG_HEADER_STANDARD: IDSHeaderConfiguration = 0;
#[derive(Debug)]
pub struct CANAerospaceLite<D>
where
D: CANAerospaceDriver,
{
pub node_id: u8,
identification: IDSResponse,
nod_count: u8,
driver: D,
pub(crate) rx_queue: BinaryHeap<CANAerospaceFrame, Min, 10>,
}
impl<D> CANAerospaceLite<D>
where
D: CANAerospaceDriver,
{
pub fn new(node_id: u8, driver: D) -> Self {
Self {
node_id,
identification: IDSResponse {
hw_rev: HardwareRevision(0),
sw_rev: SoftwareRevision(0),
configuration: IDS_CONF_STANDARD,
header: IDS_MSG_HEADER_STANDARD,
},
nod_count: 0,
driver,
rx_queue: BinaryHeap::new(),
}
}
pub fn set_hw_revision(&mut self, rev: HardwareRevision) {
self.identification.hw_rev = rev;
}
pub fn set_sw_revision(&mut self, rev: SoftwareRevision) {
self.identification.sw_rev = rev;
}
pub fn set_ids_configuration(&mut self, conf: IDSConfiguration) {
self.identification.configuration = conf;
}
pub fn set_message_header_conf(&mut self, conf: IDSHeaderConfiguration) {
self.identification.header = conf;
}
pub fn send_message(&mut self, message: CANAerospaceMessage) {
self.driver.send_frame(CANAerospaceFrame::from(message));
}
pub fn read_message(&mut self) -> Option<CANAerospaceMessage> {
self.rx_queue.pop().map(CANAerospaceMessage::from)
}
pub fn notify_receive_event(&mut self) {
if let Some(frame) = self.driver.recv_frame() {
match frame.message_type {
types::MessageType::NSH(id) | types::MessageType::NSL(id) => {
if id % 2 == 0 {
self.handle_service_request(frame);
} else {
self.rx_queue.push(frame).unwrap_or(());
}
}
types::MessageType::INVALID => { }
_ => {
self.rx_queue.push(frame).unwrap_or(());
}
};
}
}
fn handle_service_request(&mut self, frame: CANAerospaceFrame) {
if frame.message.node_id == self.node_id || frame.message.node_id == 0 {
match ServiceCodeEnum::from(frame.message.service_code) {
ServiceCodeEnum::IDS => {
let response_message_type = match frame.message_type {
MessageType::NSH(id) => MessageType::NSH(id + 1),
MessageType::NSL(id) => MessageType::NSL(id + 1),
_ => frame.message_type,
};
let message = CANAerospaceMessage {
message_type: response_message_type,
node_id: self.node_id,
service_code: ServiceCodeEnum::IDS,
message_code: frame.message.message_code,
data: DataType::UCHAR4(
self.identification.hw_rev.0,
self.identification.sw_rev.0,
self.identification.configuration.0,
self.identification.header,
),
};
self.send_message(message);
}
_ => {
self.rx_queue.push(frame).unwrap_or(());
}
};
}
}
}