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