#![no_std]
use heapless::{BinaryHeap, binary_heap::{Min}};
use crate::{driver::CANAerospaceDriver, types::MessageType};
use crate::types::{DataType, HardwareRevision, IDSConfiguration, IDSHeaderConfiguration, IDSResponse, ServiceCodeEnum, SoftwareRevision};
use crate::message::{CANAerospaceFrame, CANAerospaceMessage};
pub mod types;
pub mod message;
pub mod driver;
#[cfg(feature = "bxcan-support")]
pub mod bxcan;
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> {
if let Some(frame) = self.rx_queue.pop() {
Some(CANAerospaceMessage::from(frame))
} else {
None
}
}
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(()); }
};
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}