1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3 communication::{
4 AbstractCluster, FlexrayArTpConfig, FlexrayChannelName, FlexrayNmCluster, FlexrayPhysicalChannel,
5 FlexrayTpConfig,
6 },
7 get_reference_parents,
8};
9use autosar_data::{Element, ElementName, EnumItem};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct FlexrayCluster(Element);
15abstraction_element!(FlexrayCluster, FlexrayCluster);
16impl IdentifiableAbstractionElement for FlexrayCluster {}
17
18impl FlexrayCluster {
19 pub(crate) fn new(
21 name: &str,
22 package: &ArPackage,
23 settings: &FlexrayClusterSettings,
24 ) -> Result<Self, AutosarAbstractionError> {
25 let elem_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
26 let elem_cluster = elem_pkg_elements.create_named_sub_element(ElementName::FlexrayCluster, name)?;
27 if let Ok(cluster_content) = elem_cluster
28 .create_sub_element(ElementName::FlexrayClusterVariants)
29 .and_then(|fcv| fcv.create_sub_element(ElementName::FlexrayClusterConditional))
30 {
31 cluster_content
32 .create_sub_element(ElementName::ProtocolName)
33 .and_then(|pn| pn.set_character_data("FlexRay"))?;
34 cluster_content
35 .create_sub_element(ElementName::ProtocolVersion)
36 .and_then(|pv| pv.set_character_data("2.1"))?;
37
38 cluster_content.create_sub_element(ElementName::PhysicalChannels)?;
39 }
40
41 let flexray_cluster = FlexrayCluster(elem_cluster);
42 flexray_cluster.update_settings(settings);
43
44 Ok(flexray_cluster)
45 }
46
47 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
49 let channels_info = self.physical_channels();
51 if let Some(channel_a) = channels_info.channel_a {
52 channel_a.remove(deep)?;
53 }
54 if let Some(channel_b) = channels_info.channel_b {
55 channel_b.remove(deep)?;
56 }
57 let ref_parents = get_reference_parents(self.element())?;
58
59 AbstractionElement::remove(self, deep)?;
61
62 for (named_parent, _parent) in ref_parents {
65 match named_parent.element_name() {
66 ElementName::FlexrayTpConfig => {
67 if let Ok(flexray_tp_config) = FlexrayTpConfig::try_from(named_parent) {
68 flexray_tp_config.remove(deep)?;
69 }
70 }
71 ElementName::FlexrayArTpConfig => {
72 if let Ok(flexray_ar_tp_config) = FlexrayArTpConfig::try_from(named_parent) {
73 flexray_ar_tp_config.remove(deep)?;
74 }
75 }
76 ElementName::FlexrayNmCluster => {
77 if let Ok(flexray_nm_cluster) = FlexrayNmCluster::try_from(named_parent) {
78 flexray_nm_cluster.remove(deep)?;
79 }
80 }
81 _ => {}
82 }
83 }
84
85 Ok(())
86 }
87
88 pub fn update_settings(&self, settings: &FlexrayClusterSettings) {
115 if let Ok(cluster_content) = self
116 .0
117 .get_or_create_sub_element(ElementName::FlexrayClusterVariants)
118 .and_then(|fcv| fcv.get_or_create_sub_element(ElementName::FlexrayClusterConditional))
119 {
120 let _ = cluster_content
121 .get_or_create_sub_element(ElementName::Baudrate)
122 .and_then(|br| br.set_character_data(settings.baudrate.to_string()));
123 let _ = cluster_content
124 .get_or_create_sub_element(ElementName::ActionPointOffset)
125 .and_then(|apo| apo.set_character_data(settings.action_point_offset.to_string()));
126 let _ = cluster_content
127 .get_or_create_sub_element(ElementName::Bit)
128 .and_then(|bit| bit.set_character_data(settings.bit));
129 let _ = cluster_content
130 .get_or_create_sub_element(ElementName::CasRxLowMax)
131 .and_then(|crlm| crlm.set_character_data(settings.cas_rx_low_max.to_string()));
132 let _ = cluster_content
133 .get_or_create_sub_element(ElementName::ColdStartAttempts)
134 .and_then(|csa| csa.set_character_data(settings.cold_start_attempts.to_string()));
135 let _ = cluster_content
136 .get_or_create_sub_element(ElementName::Cycle)
137 .and_then(|apo| apo.set_character_data(settings.cycle));
138 let _ = cluster_content
139 .get_or_create_sub_element(ElementName::CycleCountMax)
140 .and_then(|ccm| ccm.set_character_data(settings.cycle_count_max.to_string()));
141 let _ = cluster_content
142 .get_or_create_sub_element(ElementName::DetectNitError)
143 .and_then(|dne| dne.set_character_data(settings.detect_nit_error.to_string()));
144 let _ = cluster_content
145 .get_or_create_sub_element(ElementName::DynamicSlotIdlePhase)
146 .and_then(|dsip| dsip.set_character_data(settings.dynamic_slot_idle_phase.to_string()));
147 let _ = cluster_content
148 .get_or_create_sub_element(ElementName::IgnoreAfterTx)
149 .and_then(|iat| iat.set_character_data(settings.ignore_after_tx.to_string()));
150 let _ = cluster_content
151 .get_or_create_sub_element(ElementName::ListenNoise)
152 .and_then(|ln| ln.set_character_data(settings.listen_noise.to_string()));
153 let _ = cluster_content
154 .get_or_create_sub_element(ElementName::MacroPerCycle)
155 .and_then(|mpc| mpc.set_character_data(settings.macro_per_cycle.to_string()));
156 let _ = cluster_content
157 .get_or_create_sub_element(ElementName::MacrotickDuration)
158 .and_then(|mpc| mpc.set_character_data(settings.macrotick_duration));
159 let _ = cluster_content
160 .get_or_create_sub_element(ElementName::MaxWithoutClockCorrectionFatal)
161 .and_then(|mwccf| mwccf.set_character_data(settings.max_without_clock_correction_fatal.to_string()));
162 let _ = cluster_content
163 .get_or_create_sub_element(ElementName::MaxWithoutClockCorrectionPassive)
164 .and_then(|mwccp| mwccp.set_character_data(settings.max_without_clock_correction_passive.to_string()));
165 let _ = cluster_content
166 .get_or_create_sub_element(ElementName::MinislotActionPointOffset)
167 .and_then(|mapo| mapo.set_character_data(settings.minislot_action_point_offset.to_string()));
168 let _ = cluster_content
169 .get_or_create_sub_element(ElementName::MinislotDuration)
170 .and_then(|md| md.set_character_data(settings.minislot_duration.to_string()));
171 let _ = cluster_content
172 .get_or_create_sub_element(ElementName::NetworkIdleTime)
173 .and_then(|nit| nit.set_character_data(settings.network_idle_time.to_string()));
174 let _ = cluster_content
175 .get_or_create_sub_element(ElementName::NetworkManagementVectorLength)
176 .and_then(|nmvl| nmvl.set_character_data(settings.network_management_vector_length.to_string()));
177 let _ = cluster_content
178 .get_or_create_sub_element(ElementName::NumberOfMinislots)
179 .and_then(|nom| nom.set_character_data(settings.number_of_minislots.to_string()));
180 let _ = cluster_content
181 .get_or_create_sub_element(ElementName::NumberOfStaticSlots)
182 .and_then(|noss| noss.set_character_data(settings.number_of_static_slots.to_string()));
183 let _ = cluster_content
184 .get_or_create_sub_element(ElementName::OffsetCorrectionStart)
185 .and_then(|ocs| ocs.set_character_data(settings.offset_correction_start.to_string()));
186 let _ = cluster_content
187 .get_or_create_sub_element(ElementName::PayloadLengthStatic)
188 .and_then(|pls| pls.set_character_data(settings.payload_length_static.to_string()));
189 let _ = cluster_content
190 .get_or_create_sub_element(ElementName::SafetyMargin)
191 .and_then(|sm| sm.set_character_data(settings.safety_margin.to_string()));
192 if let Some(sample_clock_period) = settings.sample_clock_period {
193 let _ = cluster_content
194 .get_or_create_sub_element(ElementName::SampleClockPeriod)
195 .and_then(|scp| scp.set_character_data(sample_clock_period));
196 } else if let Some(scp) = cluster_content.get_sub_element(ElementName::SampleClockPeriod) {
197 let _ = cluster_content.remove_sub_element(scp);
198 }
199 let _ = cluster_content
200 .get_or_create_sub_element(ElementName::StaticSlotDuration)
201 .and_then(|ssd| ssd.set_character_data(settings.static_slot_duration.to_string()));
202 let _ = cluster_content
203 .get_or_create_sub_element(ElementName::SymbolWindow)
204 .and_then(|sw| sw.set_character_data(settings.symbol_window.to_string()));
205
206 if let Some(symbol_window_action_point_offset) = settings.symbol_window_action_point_offset {
207 let _ = cluster_content
208 .get_or_create_sub_element(ElementName::SymbolWindowActionPointOffset)
209 .and_then(|swapo| swapo.set_character_data(symbol_window_action_point_offset.to_string()));
210 } else if let Some(swapo) = cluster_content.get_sub_element(ElementName::SymbolWindowActionPointOffset) {
211 let _ = cluster_content.remove_sub_element(swapo);
212 }
213 let _ = cluster_content
214 .get_or_create_sub_element(ElementName::SyncFrameIdCountMax)
215 .and_then(|sficm| sficm.set_character_data(settings.sync_frame_id_count_max.to_string()));
216 if let Some(transceiver_standby_delay) = settings.transceiver_standby_delay {
217 let _ = cluster_content
218 .get_or_create_sub_element(ElementName::TranceiverStandbyDelay)
219 .and_then(|tsd| tsd.set_character_data(transceiver_standby_delay));
220 } else if let Some(tsd) = cluster_content.get_sub_element(ElementName::TranceiverStandbyDelay) {
221 let _ = cluster_content.remove_sub_element(tsd);
222 }
223 let _ = cluster_content
224 .get_or_create_sub_element(ElementName::TransmissionStartSequenceDuration)
225 .and_then(|tssd| tssd.set_character_data(settings.transmission_start_sequence_duration.to_string()));
226 let _ = cluster_content
227 .get_or_create_sub_element(ElementName::WakeupRxIdle)
228 .and_then(|wri| wri.set_character_data(settings.wakeup_rx_idle.to_string()));
229 let _ = cluster_content
230 .get_or_create_sub_element(ElementName::WakeupRxLow)
231 .and_then(|wrl| wrl.set_character_data(settings.wakeup_rx_low.to_string()));
232 let _ = cluster_content
233 .get_or_create_sub_element(ElementName::WakeupRxWindow)
234 .and_then(|wrw| wrw.set_character_data(settings.wakeup_rx_window.to_string()));
235 let _ = cluster_content
236 .get_or_create_sub_element(ElementName::WakeupTxActive)
237 .and_then(|wta| wta.set_character_data(settings.wakeup_tx_active.to_string()));
238 let _ = cluster_content
239 .get_or_create_sub_element(ElementName::WakeupTxIdle)
240 .and_then(|wti| wti.set_character_data(settings.wakeup_tx_idle.to_string()));
241 }
242 }
243
244 #[must_use]
264 pub fn settings(&self) -> FlexrayClusterSettings {
265 let mut settings = FlexrayClusterSettings {
266 baudrate: 0,
267 action_point_offset: 0,
268 bit: 0.0,
269 cas_rx_low_max: 0,
270 cold_start_attempts: 0,
271 cycle: 0.0,
272 cycle_count_max: 0,
273 detect_nit_error: false,
274 dynamic_slot_idle_phase: 0,
275 ignore_after_tx: 0,
276 listen_noise: 0,
277 macro_per_cycle: 0,
278 macrotick_duration: 0.0,
279 max_without_clock_correction_fatal: 0,
280 max_without_clock_correction_passive: 0,
281 minislot_action_point_offset: 0,
282 minislot_duration: 0,
283 network_idle_time: 0,
284 network_management_vector_length: 0,
285 number_of_minislots: 0,
286 number_of_static_slots: 0,
287 offset_correction_start: 0,
288 payload_length_static: 0,
289 safety_margin: 0,
290 sample_clock_period: None,
291 static_slot_duration: 0,
292 symbol_window: 0,
293 symbol_window_action_point_offset: None,
294 sync_frame_id_count_max: 0,
295 transceiver_standby_delay: None,
296 transmission_start_sequence_duration: 0,
297 wakeup_rx_idle: 0,
298 wakeup_rx_low: 0,
299 wakeup_rx_window: 0,
300 wakeup_tx_active: 0,
301 wakeup_tx_idle: 0,
302 };
303
304 if let Some(cluster_content) = self
305 .0
306 .get_sub_element(ElementName::FlexrayClusterVariants)
307 .and_then(|fcv| fcv.get_sub_element(ElementName::FlexrayClusterConditional))
308 {
309 if let Some(baudrate) = cluster_content
310 .get_sub_element(ElementName::Baudrate)
311 .and_then(|br| br.character_data())
312 .and_then(|cdata| cdata.parse_integer())
313 {
314 settings.baudrate = baudrate;
315 }
316 if let Some(action_point_offset) = cluster_content
317 .get_sub_element(ElementName::ActionPointOffset)
318 .and_then(|apo| apo.character_data())
319 .and_then(|cdata| cdata.parse_integer())
320 {
321 settings.action_point_offset = action_point_offset;
322 }
323 if let Some(bit) = cluster_content
324 .get_sub_element(ElementName::Bit)
325 .and_then(|bit| bit.character_data())
326 .and_then(|cdata| cdata.float_value())
327 {
328 settings.bit = bit;
329 }
330 if let Some(cas_rx_low_max) = cluster_content
331 .get_sub_element(ElementName::CasRxLowMax)
332 .and_then(|crlm| crlm.character_data())
333 .and_then(|cdata| cdata.parse_integer())
334 {
335 settings.cas_rx_low_max = cas_rx_low_max;
336 }
337 if let Some(cold_start_attempts) = cluster_content
338 .get_sub_element(ElementName::ColdStartAttempts)
339 .and_then(|csa| csa.character_data())
340 .and_then(|cdata| cdata.parse_integer())
341 {
342 settings.cold_start_attempts = cold_start_attempts;
343 }
344 if let Some(cycle) = cluster_content
345 .get_sub_element(ElementName::Cycle)
346 .and_then(|apo| apo.character_data())
347 .and_then(|cdata| cdata.float_value())
348 {
349 settings.cycle = cycle;
350 }
351 if let Some(cycle_count_max) = cluster_content
352 .get_sub_element(ElementName::CycleCountMax)
353 .and_then(|ccm| ccm.character_data())
354 .and_then(|cdata| cdata.parse_integer())
355 {
356 settings.cycle_count_max = cycle_count_max;
357 }
358 if let Some(detect_nit_error) = cluster_content
359 .get_sub_element(ElementName::DetectNitError)
360 .and_then(|dne| dne.character_data())
361 .and_then(|cdata| cdata.string_value())
362 {
363 settings.detect_nit_error = (detect_nit_error == "true") || (detect_nit_error == "1");
364 }
365 if let Some(dynamic_slot_idle_phase) = cluster_content
366 .get_sub_element(ElementName::DynamicSlotIdlePhase)
367 .and_then(|dsip| dsip.character_data())
368 .and_then(|cdata| cdata.parse_integer())
369 {
370 settings.dynamic_slot_idle_phase = dynamic_slot_idle_phase;
371 }
372 if let Some(ignore_after_tx) = cluster_content
373 .get_sub_element(ElementName::IgnoreAfterTx)
374 .and_then(|iat| iat.character_data())
375 .and_then(|cdata| cdata.parse_integer())
376 {
377 settings.ignore_after_tx = ignore_after_tx;
378 }
379 if let Some(listen_noise) = cluster_content
380 .get_sub_element(ElementName::ListenNoise)
381 .and_then(|ln| ln.character_data())
382 .and_then(|cdata| cdata.parse_integer())
383 {
384 settings.listen_noise = listen_noise;
385 }
386 if let Some(macro_per_cycle) = cluster_content
387 .get_sub_element(ElementName::MacroPerCycle)
388 .and_then(|mpc| mpc.character_data())
389 .and_then(|cdata| cdata.parse_integer())
390 {
391 settings.macro_per_cycle = macro_per_cycle;
392 }
393 if let Some(macrotick_duration) = cluster_content
394 .get_sub_element(ElementName::MacrotickDuration)
395 .and_then(|mpc| mpc.character_data())
396 .and_then(|cdata| cdata.float_value())
397 {
398 settings.macrotick_duration = macrotick_duration;
399 }
400 if let Some(max_without_clock_correction_fatal) = cluster_content
401 .get_sub_element(ElementName::MaxWithoutClockCorrectionFatal)
402 .and_then(|mwccf| mwccf.character_data())
403 .and_then(|cdata| cdata.parse_integer())
404 {
405 settings.max_without_clock_correction_fatal = max_without_clock_correction_fatal;
406 }
407 if let Some(max_without_clock_correction_passive) = cluster_content
408 .get_sub_element(ElementName::MaxWithoutClockCorrectionPassive)
409 .and_then(|mwccp| mwccp.character_data())
410 .and_then(|cdata| cdata.parse_integer())
411 {
412 settings.max_without_clock_correction_passive = max_without_clock_correction_passive;
413 }
414 if let Some(minislot_action_point_offset) = cluster_content
415 .get_sub_element(ElementName::MinislotActionPointOffset)
416 .and_then(|mapo| mapo.character_data())
417 .and_then(|cdata| cdata.parse_integer())
418 {
419 settings.minislot_action_point_offset = minislot_action_point_offset;
420 }
421 if let Some(minislot_duration) = cluster_content
422 .get_sub_element(ElementName::MinislotDuration)
423 .and_then(|md| md.character_data())
424 .and_then(|cdata| cdata.parse_integer())
425 {
426 settings.minislot_duration = minislot_duration;
427 }
428 if let Some(network_idle_time) = cluster_content
429 .get_sub_element(ElementName::NetworkIdleTime)
430 .and_then(|nit| nit.character_data())
431 .and_then(|cdata| cdata.parse_integer())
432 {
433 settings.network_idle_time = network_idle_time;
434 }
435 if let Some(network_management_vector_length) = cluster_content
436 .get_sub_element(ElementName::NetworkManagementVectorLength)
437 .and_then(|nmvl| nmvl.character_data())
438 .and_then(|cdata| cdata.parse_integer())
439 {
440 settings.network_management_vector_length = network_management_vector_length;
441 }
442 if let Some(number_of_minislots) = cluster_content
443 .get_sub_element(ElementName::NumberOfMinislots)
444 .and_then(|nom| nom.character_data())
445 .and_then(|cdata| cdata.parse_integer())
446 {
447 settings.number_of_minislots = number_of_minislots;
448 }
449 if let Some(number_of_static_slots) = cluster_content
450 .get_sub_element(ElementName::NumberOfStaticSlots)
451 .and_then(|noss| noss.character_data())
452 .and_then(|cdata| cdata.parse_integer())
453 {
454 settings.number_of_static_slots = number_of_static_slots;
455 }
456 if let Some(offset_correction_start) = cluster_content
457 .get_sub_element(ElementName::OffsetCorrectionStart)
458 .and_then(|ocs| ocs.character_data())
459 .and_then(|cdata| cdata.parse_integer())
460 {
461 settings.offset_correction_start = offset_correction_start;
462 }
463 if let Some(payload_length_static) = cluster_content
464 .get_sub_element(ElementName::PayloadLengthStatic)
465 .and_then(|pls| pls.character_data())
466 .and_then(|cdata| cdata.parse_integer())
467 {
468 settings.payload_length_static = payload_length_static;
469 }
470 if let Some(safety_margin) = cluster_content
471 .get_sub_element(ElementName::SafetyMargin)
472 .and_then(|sm| sm.character_data())
473 .and_then(|cdata| cdata.parse_integer())
474 {
475 settings.safety_margin = safety_margin;
476 }
477
478 settings.sample_clock_period = cluster_content
479 .get_sub_element(ElementName::SampleClockPeriod)
480 .and_then(|scp| scp.character_data())
481 .and_then(|cdata| cdata.float_value());
482
483 if let Some(static_slot_duration) = cluster_content
484 .get_sub_element(ElementName::StaticSlotDuration)
485 .and_then(|ssd| ssd.character_data())
486 .and_then(|cdata| cdata.parse_integer())
487 {
488 settings.static_slot_duration = static_slot_duration;
489 }
490 if let Some(symbol_window) = cluster_content
491 .get_sub_element(ElementName::SymbolWindow)
492 .and_then(|sw| sw.character_data())
493 .and_then(|cdata| cdata.parse_integer())
494 {
495 settings.symbol_window = symbol_window;
496 }
497 settings.symbol_window_action_point_offset = cluster_content
498 .get_sub_element(ElementName::SymbolWindowActionPointOffset)
499 .and_then(|swapo| swapo.character_data())
500 .and_then(|cdata| cdata.parse_integer());
501
502 if let Some(sync_frame_id_count_max) = cluster_content
503 .get_sub_element(ElementName::SyncFrameIdCountMax)
504 .and_then(|sficm| sficm.character_data())
505 .and_then(|cdata| cdata.parse_integer())
506 {
507 settings.sync_frame_id_count_max = sync_frame_id_count_max;
508 }
509
510 settings.transceiver_standby_delay = cluster_content
511 .get_sub_element(ElementName::TranceiverStandbyDelay)
512 .and_then(|tsd| tsd.character_data())
513 .and_then(|cdata| cdata.float_value());
514
515 if let Some(transmission_start_sequence_duration) = cluster_content
516 .get_sub_element(ElementName::TransmissionStartSequenceDuration)
517 .and_then(|tssd| tssd.character_data())
518 .and_then(|cdata| cdata.parse_integer())
519 {
520 settings.transmission_start_sequence_duration = transmission_start_sequence_duration;
521 }
522 if let Some(wakeup_rx_idle) = cluster_content
523 .get_sub_element(ElementName::WakeupRxIdle)
524 .and_then(|wri| wri.character_data())
525 .and_then(|cdata| cdata.parse_integer())
526 {
527 settings.wakeup_rx_idle = wakeup_rx_idle;
528 }
529 if let Some(wakeup_rx_low) = cluster_content
530 .get_sub_element(ElementName::WakeupRxLow)
531 .and_then(|wrl| wrl.character_data())
532 .and_then(|cdata| cdata.parse_integer())
533 {
534 settings.wakeup_rx_low = wakeup_rx_low;
535 }
536 if let Some(wakeup_rx_window) = cluster_content
537 .get_sub_element(ElementName::WakeupRxWindow)
538 .and_then(|wrw| wrw.character_data())
539 .and_then(|cdata| cdata.parse_integer())
540 {
541 settings.wakeup_rx_window = wakeup_rx_window;
542 }
543 if let Some(wakeup_tx_active) = cluster_content
544 .get_sub_element(ElementName::WakeupTxActive)
545 .and_then(|wta| wta.character_data())
546 .and_then(|cdata| cdata.parse_integer())
547 {
548 settings.wakeup_tx_active = wakeup_tx_active;
549 }
550 if let Some(wakeup_tx_idle) = cluster_content
551 .get_sub_element(ElementName::WakeupTxIdle)
552 .and_then(|wti| wti.character_data())
553 .and_then(|cdata| cdata.parse_integer())
554 {
555 settings.wakeup_tx_idle = wakeup_tx_idle;
556 }
557 }
558
559 settings
560 }
561
562 pub fn create_physical_channel(
587 &self,
588 name: &str,
589 channel_name: FlexrayChannelName,
590 ) -> Result<FlexrayPhysicalChannel, AutosarAbstractionError> {
591 let phys_channels = self
592 .0
593 .get_or_create_sub_element(ElementName::FlexrayClusterVariants)?
594 .get_or_create_sub_element(ElementName::FlexrayClusterConditional)?
595 .get_or_create_sub_element(ElementName::PhysicalChannels)?;
596
597 for existing_channel in phys_channels.sub_elements() {
598 if let Some(existing_channel_name) = FlexrayPhysicalChannel::try_from(existing_channel)
599 .ok()
600 .and_then(|channel| channel.channel_name())
601 && existing_channel_name == channel_name
602 {
603 return Err(AutosarAbstractionError::ItemAlreadyExists);
604 }
605 }
606
607 let channel = phys_channels.create_named_sub_element(ElementName::FlexrayPhysicalChannel, name)?;
608
609 let cn_item = match channel_name {
610 FlexrayChannelName::A => EnumItem::ChannelA,
611 FlexrayChannelName::B => EnumItem::ChannelB,
612 };
613
614 let _ = channel
615 .create_sub_element(ElementName::ChannelName)
616 .and_then(|cn| cn.set_character_data(cn_item));
617
618 FlexrayPhysicalChannel::try_from(channel)
619 }
620
621 #[must_use]
638 pub fn physical_channels(&self) -> FlexrayPhysicalChannelsInfo {
639 let mut channel_info = FlexrayPhysicalChannelsInfo {
640 channel_a: None,
641 channel_b: None,
642 };
643 if let Some(phys_channels) = self
644 .0
645 .get_sub_element(ElementName::FlexrayClusterVariants)
646 .and_then(|fcv| fcv.get_sub_element(ElementName::FlexrayClusterConditional))
647 .and_then(|fcc| fcc.get_sub_element(ElementName::PhysicalChannels))
648 {
649 for channel_elem in phys_channels.sub_elements() {
650 if let Ok(channel) = FlexrayPhysicalChannel::try_from(channel_elem) {
651 match channel.channel_name() {
652 Some(FlexrayChannelName::A) => channel_info.channel_a = Some(channel),
653 Some(FlexrayChannelName::B) => channel_info.channel_b = Some(channel),
654 None => {}
655 }
656 }
657 }
658 }
659 channel_info
660 }
661}
662
663impl AbstractCluster for FlexrayCluster {}
664
665#[derive(Debug, Clone, PartialEq)]
669pub struct FlexrayPhysicalChannelsInfo {
670 pub channel_a: Option<FlexrayPhysicalChannel>,
672 pub channel_b: Option<FlexrayPhysicalChannel>,
674}
675
676#[derive(Debug, Clone, PartialEq)]
683pub struct FlexrayClusterSettings {
684 pub baudrate: u32,
686 pub action_point_offset: u8,
689 pub bit: f64,
691 pub cas_rx_low_max: u8,
693 pub cold_start_attempts: u8,
696 pub cycle: f64,
698 pub cycle_count_max: u8,
700 pub detect_nit_error: bool,
702 pub dynamic_slot_idle_phase: u8,
704 pub ignore_after_tx: u16,
706 pub listen_noise: u8,
709 pub macro_per_cycle: u16,
711 pub macrotick_duration: f64,
713 pub max_without_clock_correction_fatal: u8,
716 pub max_without_clock_correction_passive: u8,
719 pub minislot_action_point_offset: u8,
721 pub minislot_duration: u8,
723 pub network_idle_time: u16,
725 pub network_management_vector_length: u8,
727 pub number_of_minislots: u16,
729 pub number_of_static_slots: u16,
731 pub offset_correction_start: u16,
733 pub payload_length_static: u16,
735 pub safety_margin: u16,
737 pub sample_clock_period: Option<f64>,
739 pub static_slot_duration: u16,
741 pub symbol_window: u8,
743 pub symbol_window_action_point_offset: Option<u8>,
745 pub sync_frame_id_count_max: u8,
747 pub transceiver_standby_delay: Option<f64>,
749 pub transmission_start_sequence_duration: u8,
751 pub wakeup_rx_idle: u16,
754 pub wakeup_rx_low: u8,
757 pub wakeup_rx_window: u16,
759 pub wakeup_tx_active: u16,
761 pub wakeup_tx_idle: u16,
763}
764
765impl FlexrayClusterSettings {
766 #[must_use]
768 pub fn new() -> Self {
769 Self {
770 baudrate: 10_000_000,
771 action_point_offset: 4,
772 bit: 1e-7,
773 cas_rx_low_max: 80,
774 cold_start_attempts: 16,
775 cycle: 0.005,
776 cycle_count_max: 63,
777 detect_nit_error: true,
778 dynamic_slot_idle_phase: 0,
779 ignore_after_tx: 7,
780 listen_noise: 2,
781 macro_per_cycle: 5000,
782 macrotick_duration: 1e-6,
783 max_without_clock_correction_fatal: 5,
784 max_without_clock_correction_passive: 3,
785 minislot_action_point_offset: 3,
786 minislot_duration: 10,
787 network_idle_time: 46,
788 network_management_vector_length: 0,
789 number_of_minislots: 185,
790 number_of_static_slots: 50,
791 offset_correction_start: 4980,
792 payload_length_static: 32,
793 safety_margin: 1,
794 sample_clock_period: Some(1.25e-8),
795 static_slot_duration: 62,
796 symbol_window: 0,
797 symbol_window_action_point_offset: None,
798 sync_frame_id_count_max: 8,
799 transceiver_standby_delay: None,
800 transmission_start_sequence_duration: 9,
801 wakeup_rx_idle: 50,
802 wakeup_rx_low: 50,
803 wakeup_rx_window: 301,
804 wakeup_tx_active: 60,
805 wakeup_tx_idle: 180,
806 }
807 }
808
809 #[must_use]
823 pub fn verify(&self) -> bool {
824 if 1.0 / f64::from(self.baudrate) != self.bit {
826 return false;
827 }
828
829 if self.cycle > 0.016 {
831 return false;
832 }
833
834 if self.cycle_count_max != 63 {
836 return false;
837 }
838
839 if self.payload_length_static > 127 {
841 return false;
842 }
843
844 if self.static_slot_duration < 4 || self.static_slot_duration > 661 {
846 return false;
847 }
848
849 if self.minislot_duration < 2 || self.minislot_duration > 63 {
851 return false;
852 }
853
854 if self.action_point_offset < 1
856 || self.action_point_offset > 63
857 || u16::from(self.action_point_offset) >= self.static_slot_duration
858 {
859 return false;
860 }
861
862 if self.minislot_action_point_offset < 1 || self.minislot_action_point_offset > 31 {
864 return false;
865 }
866
867 if self.cas_rx_low_max < 67 || self.cas_rx_low_max > 99 {
869 return false;
870 }
871
872 if let Some(sample_clock_period) = self.sample_clock_period {
874 if sample_clock_period != 1.25e-8 && sample_clock_period != 2.5e-8 && sample_clock_period != 5e-8 {
875 return false;
876 }
877
878 if self.bit != (sample_clock_period * 8.0) {
879 return false;
880 }
881 }
882
883 if self.symbol_window > 142 {
885 return false;
886 }
887
888 if self.macro_per_cycle < 10 || self.macro_per_cycle > 16000 {
890 return false;
891 }
892
893 if self.cycle / f64::from(self.macro_per_cycle) != self.macrotick_duration {
894 return false;
895 }
896
897 if self.network_idle_time < 2 || self.network_idle_time > 805 {
899 return false;
900 }
901
902 if self.dynamic_slot_idle_phase > 2 {
904 return false;
905 }
906
907 if self.transmission_start_sequence_duration < 3 || self.transmission_start_sequence_duration > 15 {
909 return false;
910 }
911
912 if self.number_of_static_slots > 1023 || self.number_of_static_slots + self.number_of_minislots > 2047 {
914 return false;
915 }
916
917 let static_segment_length = u32::from(self.static_slot_duration) * u32::from(self.number_of_static_slots);
919 let dynamic_segment_length = u32::from(self.minislot_duration) * u32::from(self.number_of_minislots);
920 if (static_segment_length + dynamic_segment_length + u32::from(self.network_idle_time))
921 > u32::from(self.macro_per_cycle)
922 {
923 return false;
924 }
925
926 let static_frame_size = 5 + 2 * self.payload_length_static + 3;
929 let bits_per_macrotick = self.macrotick_duration / self.bit;
930 let static_frame_bits =
931 f64::from(self.static_slot_duration - u16::from(self.action_point_offset)) * bits_per_macrotick;
932 if (static_frame_bits as u32) < u32::from(static_frame_size * 8) {
933 return false;
934 }
935
936 if (self.offset_correction_start > self.macro_per_cycle)
938 || (self.offset_correction_start < self.macro_per_cycle - self.network_idle_time)
939 {
940 return false;
941 }
942
943 if self.cold_start_attempts < 2 || self.cold_start_attempts > 31 {
945 return false;
946 }
947
948 if self.wakeup_rx_idle < 14 || self.wakeup_rx_idle > 59 {
950 return false;
951 }
952
953 if self.wakeup_rx_low < 11 || self.wakeup_rx_low > 59 {
955 return false;
956 }
957
958 if self.wakeup_rx_window < 76 || self.wakeup_rx_window > 301 {
960 return false;
961 }
962
963 if self.wakeup_tx_idle < 45 || self.wakeup_tx_idle > 180 {
965 return false;
966 }
967
968 if self.wakeup_tx_active < 15 || self.wakeup_tx_active > 60 {
970 return false;
971 }
972
973 if self.listen_noise < 2 || self.listen_noise > 16 {
975 return false;
976 }
977
978 if (self.max_without_clock_correction_fatal < self.max_without_clock_correction_passive)
980 || (self.max_without_clock_correction_fatal > 15)
981 {
982 return false;
983 }
984
985 if self.sync_frame_id_count_max < 2 || self.sync_frame_id_count_max > 15 {
986 return false;
987 }
988
989 true
990 }
991}
992
993impl Default for FlexrayClusterSettings {
994 fn default() -> Self {
995 Self::new()
996 }
997}
998
999#[cfg(test)]
1002mod test {
1003 use crate::{
1004 AbstractionElement, AutosarModelAbstraction, SystemCategory,
1005 communication::{AbstractCluster, FlexrayChannelName, FlexrayClusterSettings, FlexrayNmClusterSettings},
1006 };
1007 use autosar_data::AutosarVersion;
1008
1009 #[test]
1010 fn cluster() {
1011 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1012 let pkg = model.get_or_create_package("/test").unwrap();
1013 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1014
1015 let pkg2 = model.get_or_create_package("/flexray").unwrap();
1016 let settings = FlexrayClusterSettings::default();
1018 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
1019 assert!(result.is_ok());
1020 let cluster = result.unwrap();
1021 let settings = FlexrayClusterSettings::default();
1023 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
1024 assert!(result.is_err());
1025
1026 let linked_system = cluster.system().unwrap();
1028 assert_eq!(linked_system, system);
1029
1030 let result = cluster.create_physical_channel("Channel1", FlexrayChannelName::A);
1032 assert!(result.is_ok());
1033 let result = cluster.create_physical_channel("Channel2", FlexrayChannelName::B);
1035 assert!(result.is_ok());
1036 let result = cluster.create_physical_channel("Channel3", FlexrayChannelName::A);
1038 assert!(result.is_err());
1039
1040 let pc = cluster.physical_channels();
1041 assert!(pc.channel_a.is_some());
1042 assert!(pc.channel_b.is_some());
1043 }
1044
1045 #[test]
1046 fn flexray_settings() {
1047 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1048 let pkg = model.get_or_create_package("/test").unwrap();
1049 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1050 let settings = FlexrayClusterSettings::default();
1051 let cluster = system.create_flexray_cluster("FlxCluster", &pkg, &settings).unwrap();
1052
1053 let mut settings = FlexrayClusterSettings::new();
1054 assert!(settings.verify());
1055
1056 settings.sample_clock_period = Some(1.25e-8);
1058 settings.symbol_window_action_point_offset = Some(settings.action_point_offset);
1059 settings.transceiver_standby_delay = Some(1.0);
1060 assert!(settings.verify());
1061 cluster.update_settings(&settings);
1062 let settings2 = cluster.settings();
1063 assert_eq!(settings, settings2);
1064
1065 settings.baudrate = 0;
1067 assert!(!settings.verify());
1068 settings.baudrate = settings2.baudrate;
1069
1070 settings.cycle = 0.0161;
1071 assert!(!settings.verify());
1072 settings.cycle = settings2.cycle;
1073
1074 settings.cycle_count_max = 64;
1075 assert!(!settings.verify());
1076 settings.cycle_count_max = settings2.cycle_count_max;
1077
1078 settings.payload_length_static = 128;
1079 assert!(!settings.verify());
1080 settings.payload_length_static = settings2.payload_length_static;
1081
1082 settings.static_slot_duration = 3;
1083 assert!(!settings.verify());
1084 settings.static_slot_duration = settings2.static_slot_duration;
1085
1086 settings.minislot_duration = 64;
1087 assert!(!settings.verify());
1088 settings.minislot_duration = settings2.minislot_duration;
1089
1090 settings.action_point_offset = 64;
1091 assert!(!settings.verify());
1092 settings.action_point_offset = settings2.action_point_offset;
1093
1094 settings.minislot_action_point_offset = 32;
1095 assert!(!settings.verify());
1096 settings.minislot_action_point_offset = settings2.minislot_action_point_offset;
1097
1098 settings.cas_rx_low_max = 66;
1099 assert!(!settings.verify());
1100 settings.cas_rx_low_max = settings2.cas_rx_low_max;
1101
1102 settings.sample_clock_period = Some(1.0);
1103 assert!(!settings.verify());
1104 settings.sample_clock_period = settings2.sample_clock_period;
1105
1106 settings.symbol_window = 143;
1107 assert!(!settings.verify());
1108 settings.symbol_window = settings2.symbol_window;
1109
1110 settings.macro_per_cycle = 9;
1111 assert!(!settings.verify());
1112 settings.macro_per_cycle = settings2.macro_per_cycle;
1113
1114 settings.macro_per_cycle -= 1;
1115 assert!(!settings.verify());
1116 settings.macro_per_cycle = settings2.macro_per_cycle;
1117
1118 settings.network_idle_time = 806;
1119 assert!(!settings.verify());
1120 settings.network_idle_time = settings2.network_idle_time;
1121
1122 settings.dynamic_slot_idle_phase = 3;
1123 assert!(!settings.verify());
1124 settings.dynamic_slot_idle_phase = settings2.dynamic_slot_idle_phase;
1125
1126 settings.transmission_start_sequence_duration = 16;
1127 assert!(!settings.verify());
1128 settings.transmission_start_sequence_duration = settings2.transmission_start_sequence_duration;
1129
1130 settings.number_of_static_slots = 1024;
1131 assert!(!settings.verify());
1132 settings.number_of_static_slots = settings2.number_of_static_slots;
1133
1134 settings.number_of_static_slots += 1;
1135 assert!(!settings.verify());
1136 settings.number_of_static_slots = settings2.number_of_static_slots;
1137
1138 settings.payload_length_static += 1;
1139 assert!(!settings.verify());
1140 settings.payload_length_static = settings2.payload_length_static;
1141
1142 settings.offset_correction_start = settings.macro_per_cycle + 1;
1143 assert!(!settings.verify());
1144 settings.offset_correction_start = settings2.offset_correction_start;
1145
1146 settings.cold_start_attempts = 1;
1147 assert!(!settings.verify());
1148 settings.cold_start_attempts = settings2.cold_start_attempts;
1149
1150 settings.wakeup_rx_idle = 13;
1151 assert!(!settings.verify());
1152 settings.wakeup_rx_idle = settings2.wakeup_rx_idle;
1153
1154 settings.wakeup_rx_low = 10;
1155 assert!(!settings.verify());
1156 settings.wakeup_rx_low = settings2.wakeup_rx_low;
1157
1158 settings.wakeup_rx_window = 75;
1159 assert!(!settings.verify());
1160 settings.wakeup_rx_window = settings2.wakeup_rx_window;
1161
1162 settings.wakeup_tx_idle = 44;
1163 assert!(!settings.verify());
1164 settings.wakeup_tx_idle = settings2.wakeup_tx_idle;
1165
1166 settings.wakeup_tx_active = 14;
1167 assert!(!settings.verify());
1168 settings.wakeup_tx_active = settings2.wakeup_tx_active;
1169
1170 settings.listen_noise = 1;
1171 assert!(!settings.verify());
1172 settings.listen_noise = settings2.listen_noise;
1173
1174 settings.max_without_clock_correction_passive = settings.max_without_clock_correction_fatal + 1;
1175 assert!(!settings.verify());
1176 settings.max_without_clock_correction_passive = settings2.max_without_clock_correction_passive;
1177
1178 settings.sync_frame_id_count_max = 1;
1179 assert!(!settings.verify());
1180 settings.sync_frame_id_count_max = settings2.sync_frame_id_count_max;
1181 }
1182
1183 #[test]
1184 fn remove_cluster() {
1185 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1186 let pkg = model.get_or_create_package("/test").unwrap();
1187 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1188 let settings = FlexrayClusterSettings::default();
1189 let cluster = system.create_flexray_cluster("FlxCluster", &pkg, &settings).unwrap();
1190 let channel = cluster
1191 .create_physical_channel("Channel1", FlexrayChannelName::A)
1192 .unwrap();
1193
1194 let nm_config = system.create_nm_config("NmConfig", &pkg).unwrap();
1195 let settings = FlexrayNmClusterSettings {
1196 nm_data_cycle: 5,
1197 nm_remote_sleep_indication_time: 5.0,
1198 nm_repeat_message_time: 5.0,
1199 nm_repetition_cycle: 5,
1200 nm_voting_cycle: 5,
1201 };
1202 let fr_nm_cluster = nm_config
1203 .create_flexray_nm_cluster("FrNmCluster", &settings, &cluster)
1204 .unwrap();
1205 let fr_tp_config = system.create_flexray_tp_config("FrTpConfig", &pkg, &cluster).unwrap();
1206 let fr_ar_tp_config = system
1207 .create_flexray_ar_tp_config("FrArTpConfig", &pkg, &cluster)
1208 .unwrap();
1209
1210 cluster.remove(true).unwrap();
1211
1212 assert!(channel.element().path().is_err());
1214 assert!(fr_nm_cluster.element().path().is_err());
1215 assert!(fr_tp_config.element().path().is_err());
1216 assert!(fr_ar_tp_config.element().path().is_err());
1217 }
1218}