1use crate::communication::{
2 AbstractFrame, AbstractFrameTriggering, AbstractPdu, CommunicationDirection, FlexrayPhysicalChannel, Frame,
3 FramePort, FrameTriggering, Pdu, PduToFrameMapping, PduTriggering,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, EcuInstance, IdentifiableAbstractionElement,
7 abstraction_element, make_unique_name,
8};
9use autosar_data::{Element, ElementName, EnumItem};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct FlexrayFrame(Element);
14abstraction_element!(FlexrayFrame, FlexrayFrame);
15impl IdentifiableAbstractionElement for FlexrayFrame {}
16
17impl FlexrayFrame {
18 pub(crate) fn new(name: &str, package: &ArPackage, byte_length: u64) -> Result<Self, AutosarAbstractionError> {
19 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
20 let fr_frame = pkg_elements.create_named_sub_element(ElementName::FlexrayFrame, name)?;
21
22 fr_frame
23 .create_sub_element(ElementName::FrameLength)?
24 .set_character_data(byte_length.to_string())?;
25
26 Ok(Self(fr_frame))
27 }
28}
29
30impl AbstractFrame for FlexrayFrame {
31 type FrameTriggeringType = FlexrayFrameTriggering;
32
33 fn frame_triggerings(&self) -> Vec<FlexrayFrameTriggering> {
35 let model_result = self.element().model();
36 let path_result = self.element().path();
37 if let (Ok(model), Ok(path)) = (model_result, path_result) {
38 model
39 .get_references_to(&path)
40 .iter()
41 .filter_map(|e| {
42 e.upgrade()
43 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
44 .and_then(|elem| FlexrayFrameTriggering::try_from(elem).ok())
45 })
46 .collect()
47 } else {
48 vec![]
49 }
50 }
51
52 fn map_pdu<T: AbstractPdu>(
54 &self,
55 gen_pdu: &T,
56 start_position: u32,
57 byte_order: ByteOrder,
58 update_bit: Option<u32>,
59 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
60 Frame::Flexray(self.clone()).map_pdu(gen_pdu, start_position, byte_order, update_bit)
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
68pub struct FlexrayFrameTriggering(Element);
69abstraction_element!(FlexrayFrameTriggering, FlexrayFrameTriggering);
70impl IdentifiableAbstractionElement for FlexrayFrameTriggering {}
71
72impl FlexrayFrameTriggering {
73 pub(crate) fn new(
74 channel: &FlexrayPhysicalChannel,
75 frame: &FlexrayFrame,
76 slot_id: u16,
77 timing: &FlexrayCommunicationCycle,
78 ) -> Result<Self, AutosarAbstractionError> {
79 let model = channel.element().model()?;
80 let base_path = channel.element().path()?;
81 let frame_name = frame
82 .name()
83 .ok_or(AutosarAbstractionError::InvalidParameter("invalid frame".to_string()))?;
84 let ft_name = format!("FT_{frame_name}");
85 let ft_name = make_unique_name(&model, &base_path, &ft_name);
86
87 let frame_triggerings = channel
88 .element()
89 .get_or_create_sub_element(ElementName::FrameTriggerings)?;
90 let fr_triggering =
91 frame_triggerings.create_named_sub_element(ElementName::FlexrayFrameTriggering, &ft_name)?;
92
93 fr_triggering
94 .create_sub_element(ElementName::FrameRef)?
95 .set_reference_target(frame.element())?;
96
97 let ft = Self(fr_triggering);
98 ft.set_slot(slot_id)?;
99 ft.set_timing(timing)?;
100
101 for pdu_mapping in frame.mapped_pdus() {
102 if let Some(pdu) = pdu_mapping.pdu() {
103 ft.add_pdu_triggering(&pdu)?;
104 }
105 }
106
107 Ok(ft)
108 }
109
110 pub fn set_slot(&self, slot_id: u16) -> Result<(), AutosarAbstractionError> {
112 self.element()
113 .get_or_create_sub_element(ElementName::AbsolutelyScheduledTimings)?
114 .get_or_create_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
115 .get_or_create_sub_element(ElementName::SlotId)?
116 .set_character_data(slot_id.to_string())?;
117 Ok(())
118 }
119
120 #[must_use]
124 pub fn slot(&self) -> Option<u16> {
125 self.element()
126 .get_sub_element(ElementName::AbsolutelyScheduledTimings)?
127 .get_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
128 .get_sub_element(ElementName::SlotId)?
129 .character_data()?
130 .parse_integer()
131 }
132
133 pub fn set_timing(&self, timing: &FlexrayCommunicationCycle) -> Result<(), AutosarAbstractionError> {
135 let timings_elem = self
136 .element()
137 .get_or_create_sub_element(ElementName::AbsolutelyScheduledTimings)?
138 .get_or_create_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
139 .get_or_create_sub_element(ElementName::CommunicationCycle)?;
140 match timing {
141 FlexrayCommunicationCycle::Counter { cycle_counter } => {
142 let _ = timings_elem.remove_sub_element_kind(ElementName::CycleRepetition);
143 timings_elem
144 .get_or_create_sub_element(ElementName::CycleCounter)?
145 .get_or_create_sub_element(ElementName::CycleCounter)?
146 .set_character_data(cycle_counter.to_string())?;
147 }
148 FlexrayCommunicationCycle::Repetition {
149 base_cycle,
150 cycle_repetition,
151 } => {
152 let _ = timings_elem.remove_sub_element_kind(ElementName::CycleCounter);
153 let repetition = timings_elem.get_or_create_sub_element(ElementName::CycleRepetition)?;
154 repetition
155 .get_or_create_sub_element(ElementName::BaseCycle)?
156 .set_character_data(base_cycle.to_string())?;
157 repetition
158 .get_or_create_sub_element(ElementName::CycleRepetition)?
159 .set_character_data::<EnumItem>((*cycle_repetition).into())?;
160 }
161 }
162 Ok(())
163 }
164
165 #[must_use]
169 pub fn timing(&self) -> Option<FlexrayCommunicationCycle> {
170 let timings = self
171 .element()
172 .get_sub_element(ElementName::AbsolutelyScheduledTimings)?
173 .get_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
174 .get_sub_element(ElementName::CommunicationCycle)?;
175
176 if let Some(counter_based) = timings.get_sub_element(ElementName::CycleCounter) {
177 let cycle_counter = counter_based
178 .get_sub_element(ElementName::CycleCounter)?
179 .character_data()?
180 .parse_integer()?;
181 Some(FlexrayCommunicationCycle::Counter { cycle_counter })
182 } else if let Some(repetition) = timings.get_sub_element(ElementName::CycleRepetition) {
183 let base_cycle = repetition
184 .get_sub_element(ElementName::BaseCycle)?
185 .character_data()?
186 .parse_integer()?;
187 let cycle_repetition = repetition
188 .get_sub_element(ElementName::CycleRepetition)?
189 .character_data()?
190 .enum_value()?
191 .try_into()
192 .ok()?;
193
194 Some(FlexrayCommunicationCycle::Repetition {
195 base_cycle,
196 cycle_repetition,
197 })
198 } else {
199 None
200 }
201 }
202
203 pub(crate) fn add_pdu_triggering(&self, pdu: &Pdu) -> Result<PduTriggering, AutosarAbstractionError> {
204 FrameTriggering::Flexray(self.clone()).add_pdu_triggering(pdu)
205 }
206
207 pub fn physical_channel(&self) -> Result<FlexrayPhysicalChannel, AutosarAbstractionError> {
209 let channel_elem = self.element().named_parent()?.unwrap();
210 FlexrayPhysicalChannel::try_from(channel_elem)
211 }
212
213 pub fn connect_to_ecu(
217 &self,
218 ecu: &EcuInstance,
219 direction: CommunicationDirection,
220 ) -> Result<FramePort, AutosarAbstractionError> {
221 FrameTriggering::Flexray(self.clone()).connect_to_ecu(ecu, direction)
222 }
223}
224
225impl AbstractFrameTriggering for FlexrayFrameTriggering {
226 type FrameType = FlexrayFrame;
227}
228
229impl From<FlexrayFrameTriggering> for FrameTriggering {
230 fn from(fft: FlexrayFrameTriggering) -> Self {
231 FrameTriggering::Flexray(fft)
232 }
233}
234
235#[derive(Debug, Clone, Copy, PartialEq, Eq)]
239pub enum FlexrayCommunicationCycle {
240 Counter {
242 cycle_counter: u8,
244 },
245 Repetition {
247 base_cycle: u8,
249 cycle_repetition: CycleRepetition,
251 },
252}
253
254#[derive(Debug, Clone, Copy, PartialEq, Eq)]
256pub enum CycleRepetition {
257 C1,
259 C2,
261 C4,
263 C5,
265 C8,
267 C10,
269 C16,
271 C20,
273 C32,
275 C40,
277 C50,
279 C64,
281}
282
283impl TryFrom<EnumItem> for CycleRepetition {
284 type Error = AutosarAbstractionError;
285
286 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
287 match value {
288 EnumItem::CycleRepetition1 => Ok(Self::C1),
289 EnumItem::CycleRepetition2 => Ok(Self::C2),
290 EnumItem::CycleRepetition4 => Ok(Self::C4),
291 EnumItem::CycleRepetition5 => Ok(Self::C5),
292 EnumItem::CycleRepetition8 => Ok(Self::C8),
293 EnumItem::CycleRepetition10 => Ok(Self::C10),
294 EnumItem::CycleRepetition16 => Ok(Self::C16),
295 EnumItem::CycleRepetition20 => Ok(Self::C20),
296 EnumItem::CycleRepetition32 => Ok(Self::C32),
297 EnumItem::CycleRepetition40 => Ok(Self::C40),
298 EnumItem::CycleRepetition50 => Ok(Self::C50),
299 EnumItem::CycleRepetition64 => Ok(Self::C64),
300
301 _ => Err(AutosarAbstractionError::ValueConversionError {
302 value: value.to_string(),
303 dest: "CycleRepetitionType".to_string(),
304 }),
305 }
306 }
307}
308
309impl From<CycleRepetition> for EnumItem {
310 fn from(value: CycleRepetition) -> Self {
311 match value {
312 CycleRepetition::C1 => EnumItem::CycleRepetition1,
313 CycleRepetition::C2 => EnumItem::CycleRepetition2,
314 CycleRepetition::C4 => EnumItem::CycleRepetition4,
315 CycleRepetition::C5 => EnumItem::CycleRepetition5,
316 CycleRepetition::C8 => EnumItem::CycleRepetition8,
317 CycleRepetition::C10 => EnumItem::CycleRepetition10,
318 CycleRepetition::C16 => EnumItem::CycleRepetition16,
319 CycleRepetition::C20 => EnumItem::CycleRepetition20,
320 CycleRepetition::C32 => EnumItem::CycleRepetition32,
321 CycleRepetition::C40 => EnumItem::CycleRepetition40,
322 CycleRepetition::C50 => EnumItem::CycleRepetition50,
323 CycleRepetition::C64 => EnumItem::CycleRepetition64,
324 }
325 }
326}
327
328#[cfg(test)]
331mod test {
332 use super::*;
333 use crate::{
334 AutosarModelAbstraction, ByteOrder, SystemCategory,
335 communication::{FlexrayChannelName, FlexrayClusterSettings},
336 };
337 use autosar_data::AutosarVersion;
338
339 #[test]
340 fn fr_frame() {
341 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
342 let package = model.get_or_create_package("/package").unwrap();
343 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
344 let flexray_cluster = system
345 .create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())
346 .unwrap();
347 let channel = flexray_cluster
348 .create_physical_channel("Channel", FlexrayChannelName::A)
349 .unwrap();
350
351 let ecu_instance = system.create_ecu_instance("ECU", &package).unwrap();
352 let can_controller = ecu_instance
353 .create_flexray_communication_controller("Controller")
354 .unwrap();
355 can_controller.connect_physical_channel("connection", &channel).unwrap();
356
357 let pdu1 = system.create_isignal_ipdu("pdu1", &package, 8).unwrap();
358 let pdu2 = system.create_isignal_ipdu("pdu2", &package, 8).unwrap();
359
360 let frame1 = system.create_flexray_frame("frame1", &package, 64).unwrap();
362 let frame2 = system.create_flexray_frame("frame2", &package, 64).unwrap();
363
364 assert_eq!(frame1.length().unwrap(), 64);
365 frame1.set_length(60).unwrap();
366 assert_eq!(frame1.length().unwrap(), 60);
367
368 let mapping = frame1
370 .map_pdu(&pdu1, 7, ByteOrder::MostSignificantByteFirst, Some(8))
371 .unwrap();
372 assert!(frame1.mapped_pdus().count() == 1);
373 assert_eq!(frame1.mapped_pdus().next().unwrap(), mapping);
374
375 let frame_triggering1 = channel
377 .trigger_frame(
378 &frame1,
379 1,
380 &FlexrayCommunicationCycle::Repetition {
381 base_cycle: 1,
382 cycle_repetition: CycleRepetition::C1,
383 },
384 )
385 .unwrap();
386 assert_eq!(frame1.frame_triggerings().len(), 1);
387 let frame_triggering2 = channel
388 .trigger_frame(&frame2, 2, &FlexrayCommunicationCycle::Counter { cycle_counter: 2 })
389 .unwrap();
390 assert_eq!(frame2.frame_triggerings().len(), 1);
391 assert_eq!(channel.frame_triggerings().count(), 2);
392
393 assert_eq!(frame_triggering1.pdu_triggerings().count(), 1);
395
396 let _ = frame1
398 .map_pdu(&pdu2, 71, ByteOrder::MostSignificantByteFirst, None)
399 .unwrap();
400 assert!(frame1.mapped_pdus().count() == 2);
401
402 assert_eq!(frame_triggering1.pdu_triggerings().count(), 2);
404
405 let frame_port = frame_triggering1
407 .connect_to_ecu(&ecu_instance, CommunicationDirection::Out)
408 .unwrap();
409 assert_eq!(frame_port.ecu().unwrap(), ecu_instance);
410 assert_eq!(
411 frame_port.communication_direction().unwrap(),
412 CommunicationDirection::Out
413 );
414 frame_port.set_name("port").unwrap();
415 assert_eq!(frame_port.name().unwrap(), "port");
416
417 assert_eq!(frame_triggering1.frame().unwrap(), frame1);
418 assert_eq!(frame_triggering1.slot().unwrap(), 1);
419 assert_eq!(
420 frame_triggering1.timing().unwrap(),
421 FlexrayCommunicationCycle::Repetition {
422 base_cycle: 1,
423 cycle_repetition: CycleRepetition::C1
424 }
425 );
426 assert_eq!(frame_triggering1.physical_channel().unwrap(), channel);
427 assert_eq!(frame_triggering2.frame().unwrap(), frame2);
428 assert_eq!(frame_triggering2.slot().unwrap(), 2);
429 assert_eq!(
430 frame_triggering2.timing().unwrap(),
431 FlexrayCommunicationCycle::Counter { cycle_counter: 2 }
432 );
433 assert_eq!(frame_triggering2.physical_channel().unwrap(), channel);
434
435 assert_eq!(mapping.pdu().unwrap(), pdu1.into());
436 assert_eq!(mapping.byte_order().unwrap(), ByteOrder::MostSignificantByteFirst);
437 assert_eq!(mapping.start_position().unwrap(), 7);
438 assert_eq!(mapping.update_bit(), Some(8));
439 }
440
441 #[test]
442 fn cycle_repetition() {
443 assert_eq!(EnumItem::CycleRepetition1, CycleRepetition::C1.into());
444 assert_eq!(EnumItem::CycleRepetition2, CycleRepetition::C2.into());
445 assert_eq!(EnumItem::CycleRepetition4, CycleRepetition::C4.into());
446 assert_eq!(EnumItem::CycleRepetition5, CycleRepetition::C5.into());
447 assert_eq!(EnumItem::CycleRepetition8, CycleRepetition::C8.into());
448 assert_eq!(EnumItem::CycleRepetition10, CycleRepetition::C10.into());
449 assert_eq!(EnumItem::CycleRepetition16, CycleRepetition::C16.into());
450 assert_eq!(EnumItem::CycleRepetition20, CycleRepetition::C20.into());
451 assert_eq!(EnumItem::CycleRepetition32, CycleRepetition::C32.into());
452 assert_eq!(EnumItem::CycleRepetition40, CycleRepetition::C40.into());
453 assert_eq!(EnumItem::CycleRepetition50, CycleRepetition::C50.into());
454 assert_eq!(EnumItem::CycleRepetition64, CycleRepetition::C64.into());
455
456 assert_eq!(CycleRepetition::C1, EnumItem::CycleRepetition1.try_into().unwrap());
457 assert_eq!(CycleRepetition::C2, EnumItem::CycleRepetition2.try_into().unwrap());
458 assert_eq!(CycleRepetition::C4, EnumItem::CycleRepetition4.try_into().unwrap());
459 assert_eq!(CycleRepetition::C5, EnumItem::CycleRepetition5.try_into().unwrap());
460 assert_eq!(CycleRepetition::C8, EnumItem::CycleRepetition8.try_into().unwrap());
461 assert_eq!(CycleRepetition::C10, EnumItem::CycleRepetition10.try_into().unwrap());
462 assert_eq!(CycleRepetition::C16, EnumItem::CycleRepetition16.try_into().unwrap());
463 assert_eq!(CycleRepetition::C20, EnumItem::CycleRepetition20.try_into().unwrap());
464 assert_eq!(CycleRepetition::C32, EnumItem::CycleRepetition32.try_into().unwrap());
465 assert_eq!(CycleRepetition::C40, EnumItem::CycleRepetition40.try_into().unwrap());
466 assert_eq!(CycleRepetition::C50, EnumItem::CycleRepetition50.try_into().unwrap());
467 assert_eq!(CycleRepetition::C64, EnumItem::CycleRepetition64.try_into().unwrap());
468
469 let result: Result<CycleRepetition, _> = EnumItem::Aa.try_into();
470 assert!(result.is_err());
471 }
472}