1use crate::{
2 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
3 communication::{AbstractCluster, FlexrayChannelName, FlexrayPhysicalChannel},
4};
5use autosar_data::{Element, ElementName, EnumItem};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct FlexrayCluster(Element);
11abstraction_element!(FlexrayCluster, FlexrayCluster);
12impl IdentifiableAbstractionElement for FlexrayCluster {}
13
14impl FlexrayCluster {
15 pub(crate) fn new(
17 name: &str,
18 package: &ArPackage,
19 settings: &FlexrayClusterSettings,
20 ) -> Result<Self, AutosarAbstractionError> {
21 let elem_pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
22 let elem_cluster = elem_pkg_elements.create_named_sub_element(ElementName::FlexrayCluster, name)?;
23 if let Ok(cluster_content) = elem_cluster
24 .create_sub_element(ElementName::FlexrayClusterVariants)
25 .and_then(|fcv| fcv.create_sub_element(ElementName::FlexrayClusterConditional))
26 {
27 cluster_content
28 .create_sub_element(ElementName::ProtocolName)
29 .and_then(|pn| pn.set_character_data("FlexRay"))?;
30 cluster_content
31 .create_sub_element(ElementName::ProtocolVersion)
32 .and_then(|pv| pv.set_character_data("2.1"))?;
33
34 cluster_content.create_sub_element(ElementName::PhysicalChannels)?;
35 }
36
37 let flexray_cluster = FlexrayCluster(elem_cluster);
38 flexray_cluster.update_settings(settings);
39
40 Ok(flexray_cluster)
41 }
42
43 pub fn update_settings(&self, settings: &FlexrayClusterSettings) {
70 if let Ok(cluster_content) = self
71 .0
72 .get_or_create_sub_element(ElementName::FlexrayClusterVariants)
73 .and_then(|fcv| fcv.get_or_create_sub_element(ElementName::FlexrayClusterConditional))
74 {
75 let _ = cluster_content
76 .get_or_create_sub_element(ElementName::Baudrate)
77 .and_then(|br| br.set_character_data(settings.baudrate.to_string()));
78 let _ = cluster_content
79 .get_or_create_sub_element(ElementName::ActionPointOffset)
80 .and_then(|apo| apo.set_character_data(settings.action_point_offset.to_string()));
81 let _ = cluster_content
82 .get_or_create_sub_element(ElementName::Bit)
83 .and_then(|bit| bit.set_character_data(settings.bit));
84 let _ = cluster_content
85 .get_or_create_sub_element(ElementName::CasRxLowMax)
86 .and_then(|crlm| crlm.set_character_data(settings.cas_rx_low_max.to_string()));
87 let _ = cluster_content
88 .get_or_create_sub_element(ElementName::ColdStartAttempts)
89 .and_then(|csa| csa.set_character_data(settings.cold_start_attempts.to_string()));
90 let _ = cluster_content
91 .get_or_create_sub_element(ElementName::Cycle)
92 .and_then(|apo| apo.set_character_data(settings.cycle));
93 let _ = cluster_content
94 .get_or_create_sub_element(ElementName::CycleCountMax)
95 .and_then(|ccm| ccm.set_character_data(settings.cycle_count_max.to_string()));
96 let _ = cluster_content
97 .get_or_create_sub_element(ElementName::DetectNitError)
98 .and_then(|dne| dne.set_character_data(settings.detect_nit_error.to_string()));
99 let _ = cluster_content
100 .get_or_create_sub_element(ElementName::DynamicSlotIdlePhase)
101 .and_then(|dsip| dsip.set_character_data(settings.dynamic_slot_idle_phase.to_string()));
102 let _ = cluster_content
103 .get_or_create_sub_element(ElementName::IgnoreAfterTx)
104 .and_then(|iat| iat.set_character_data(settings.ignore_after_tx.to_string()));
105 let _ = cluster_content
106 .get_or_create_sub_element(ElementName::ListenNoise)
107 .and_then(|ln| ln.set_character_data(settings.listen_noise.to_string()));
108 let _ = cluster_content
109 .get_or_create_sub_element(ElementName::MacroPerCycle)
110 .and_then(|mpc| mpc.set_character_data(settings.macro_per_cycle.to_string()));
111 let _ = cluster_content
112 .get_or_create_sub_element(ElementName::MacrotickDuration)
113 .and_then(|mpc| mpc.set_character_data(settings.macrotick_duration));
114 let _ = cluster_content
115 .get_or_create_sub_element(ElementName::MaxWithoutClockCorrectionFatal)
116 .and_then(|mwccf| mwccf.set_character_data(settings.max_without_clock_correction_fatal.to_string()));
117 let _ = cluster_content
118 .get_or_create_sub_element(ElementName::MaxWithoutClockCorrectionPassive)
119 .and_then(|mwccp| mwccp.set_character_data(settings.max_without_clock_correction_passive.to_string()));
120 let _ = cluster_content
121 .get_or_create_sub_element(ElementName::MinislotActionPointOffset)
122 .and_then(|mapo| mapo.set_character_data(settings.minislot_action_point_offset.to_string()));
123 let _ = cluster_content
124 .get_or_create_sub_element(ElementName::MinislotDuration)
125 .and_then(|md| md.set_character_data(settings.minislot_duration.to_string()));
126 let _ = cluster_content
127 .get_or_create_sub_element(ElementName::NetworkIdleTime)
128 .and_then(|nit| nit.set_character_data(settings.network_idle_time.to_string()));
129 let _ = cluster_content
130 .get_or_create_sub_element(ElementName::NetworkManagementVectorLength)
131 .and_then(|nmvl| nmvl.set_character_data(settings.network_management_vector_length.to_string()));
132 let _ = cluster_content
133 .get_or_create_sub_element(ElementName::NumberOfMinislots)
134 .and_then(|nom| nom.set_character_data(settings.number_of_minislots.to_string()));
135 let _ = cluster_content
136 .get_or_create_sub_element(ElementName::NumberOfStaticSlots)
137 .and_then(|noss| noss.set_character_data(settings.number_of_static_slots.to_string()));
138 let _ = cluster_content
139 .get_or_create_sub_element(ElementName::OffsetCorrectionStart)
140 .and_then(|ocs| ocs.set_character_data(settings.offset_correction_start.to_string()));
141 let _ = cluster_content
142 .get_or_create_sub_element(ElementName::PayloadLengthStatic)
143 .and_then(|pls| pls.set_character_data(settings.payload_length_static.to_string()));
144 let _ = cluster_content
145 .get_or_create_sub_element(ElementName::SafetyMargin)
146 .and_then(|sm| sm.set_character_data(settings.safety_margin.to_string()));
147 if let Some(sample_clock_period) = settings.sample_clock_period {
148 let _ = cluster_content
149 .get_or_create_sub_element(ElementName::SampleClockPeriod)
150 .and_then(|scp| scp.set_character_data(sample_clock_period));
151 } else if let Some(scp) = cluster_content.get_sub_element(ElementName::SampleClockPeriod) {
152 let _ = cluster_content.remove_sub_element(scp);
153 }
154 let _ = cluster_content
155 .get_or_create_sub_element(ElementName::StaticSlotDuration)
156 .and_then(|ssd| ssd.set_character_data(settings.static_slot_duration.to_string()));
157 let _ = cluster_content
158 .get_or_create_sub_element(ElementName::SymbolWindow)
159 .and_then(|sw| sw.set_character_data(settings.symbol_window.to_string()));
160
161 if let Some(symbol_window_action_point_offset) = settings.symbol_window_action_point_offset {
162 let _ = cluster_content
163 .get_or_create_sub_element(ElementName::SymbolWindowActionPointOffset)
164 .and_then(|swapo| swapo.set_character_data(symbol_window_action_point_offset.to_string()));
165 } else if let Some(swapo) = cluster_content.get_sub_element(ElementName::SymbolWindowActionPointOffset) {
166 let _ = cluster_content.remove_sub_element(swapo);
167 }
168 let _ = cluster_content
169 .get_or_create_sub_element(ElementName::SyncFrameIdCountMax)
170 .and_then(|sficm| sficm.set_character_data(settings.sync_frame_id_count_max.to_string()));
171 if let Some(transceiver_standby_delay) = settings.transceiver_standby_delay {
172 let _ = cluster_content
173 .get_or_create_sub_element(ElementName::TranceiverStandbyDelay)
174 .and_then(|tsd| tsd.set_character_data(transceiver_standby_delay));
175 } else if let Some(tsd) = cluster_content.get_sub_element(ElementName::TranceiverStandbyDelay) {
176 let _ = cluster_content.remove_sub_element(tsd);
177 }
178 let _ = cluster_content
179 .get_or_create_sub_element(ElementName::TransmissionStartSequenceDuration)
180 .and_then(|tssd| tssd.set_character_data(settings.transmission_start_sequence_duration.to_string()));
181 let _ = cluster_content
182 .get_or_create_sub_element(ElementName::WakeupRxIdle)
183 .and_then(|wri| wri.set_character_data(settings.wakeup_rx_idle.to_string()));
184 let _ = cluster_content
185 .get_or_create_sub_element(ElementName::WakeupRxLow)
186 .and_then(|wrl| wrl.set_character_data(settings.wakeup_rx_low.to_string()));
187 let _ = cluster_content
188 .get_or_create_sub_element(ElementName::WakeupRxWindow)
189 .and_then(|wrw| wrw.set_character_data(settings.wakeup_rx_window.to_string()));
190 let _ = cluster_content
191 .get_or_create_sub_element(ElementName::WakeupTxActive)
192 .and_then(|wta| wta.set_character_data(settings.wakeup_tx_active.to_string()));
193 let _ = cluster_content
194 .get_or_create_sub_element(ElementName::WakeupTxIdle)
195 .and_then(|wti| wti.set_character_data(settings.wakeup_tx_idle.to_string()));
196 }
197 }
198
199 #[must_use]
219 pub fn settings(&self) -> FlexrayClusterSettings {
220 let mut settings = FlexrayClusterSettings {
221 baudrate: 0,
222 action_point_offset: 0,
223 bit: 0.0,
224 cas_rx_low_max: 0,
225 cold_start_attempts: 0,
226 cycle: 0.0,
227 cycle_count_max: 0,
228 detect_nit_error: false,
229 dynamic_slot_idle_phase: 0,
230 ignore_after_tx: 0,
231 listen_noise: 0,
232 macro_per_cycle: 0,
233 macrotick_duration: 0.0,
234 max_without_clock_correction_fatal: 0,
235 max_without_clock_correction_passive: 0,
236 minislot_action_point_offset: 0,
237 minislot_duration: 0,
238 network_idle_time: 0,
239 network_management_vector_length: 0,
240 number_of_minislots: 0,
241 number_of_static_slots: 0,
242 offset_correction_start: 0,
243 payload_length_static: 0,
244 safety_margin: 0,
245 sample_clock_period: None,
246 static_slot_duration: 0,
247 symbol_window: 0,
248 symbol_window_action_point_offset: None,
249 sync_frame_id_count_max: 0,
250 transceiver_standby_delay: None,
251 transmission_start_sequence_duration: 0,
252 wakeup_rx_idle: 0,
253 wakeup_rx_low: 0,
254 wakeup_rx_window: 0,
255 wakeup_tx_active: 0,
256 wakeup_tx_idle: 0,
257 };
258
259 if let Some(cluster_content) = self
260 .0
261 .get_sub_element(ElementName::FlexrayClusterVariants)
262 .and_then(|fcv| fcv.get_sub_element(ElementName::FlexrayClusterConditional))
263 {
264 if let Some(baudrate) = cluster_content
265 .get_sub_element(ElementName::Baudrate)
266 .and_then(|br| br.character_data())
267 .and_then(|cdata| cdata.parse_integer())
268 {
269 settings.baudrate = baudrate;
270 }
271 if let Some(action_point_offset) = cluster_content
272 .get_sub_element(ElementName::ActionPointOffset)
273 .and_then(|apo| apo.character_data())
274 .and_then(|cdata| cdata.parse_integer())
275 {
276 settings.action_point_offset = action_point_offset;
277 }
278 if let Some(bit) = cluster_content
279 .get_sub_element(ElementName::Bit)
280 .and_then(|bit| bit.character_data())
281 .and_then(|cdata| cdata.float_value())
282 {
283 settings.bit = bit;
284 }
285 if let Some(cas_rx_low_max) = cluster_content
286 .get_sub_element(ElementName::CasRxLowMax)
287 .and_then(|crlm| crlm.character_data())
288 .and_then(|cdata| cdata.parse_integer())
289 {
290 settings.cas_rx_low_max = cas_rx_low_max;
291 }
292 if let Some(cold_start_attempts) = cluster_content
293 .get_sub_element(ElementName::ColdStartAttempts)
294 .and_then(|csa| csa.character_data())
295 .and_then(|cdata| cdata.parse_integer())
296 {
297 settings.cold_start_attempts = cold_start_attempts;
298 }
299 if let Some(cycle) = cluster_content
300 .get_sub_element(ElementName::Cycle)
301 .and_then(|apo| apo.character_data())
302 .and_then(|cdata| cdata.float_value())
303 {
304 settings.cycle = cycle;
305 }
306 if let Some(cycle_count_max) = cluster_content
307 .get_sub_element(ElementName::CycleCountMax)
308 .and_then(|ccm| ccm.character_data())
309 .and_then(|cdata| cdata.parse_integer())
310 {
311 settings.cycle_count_max = cycle_count_max;
312 }
313 if let Some(detect_nit_error) = cluster_content
314 .get_sub_element(ElementName::DetectNitError)
315 .and_then(|dne| dne.character_data())
316 .and_then(|cdata| cdata.string_value())
317 {
318 settings.detect_nit_error = (detect_nit_error == "true") || (detect_nit_error == "1");
319 }
320 if let Some(dynamic_slot_idle_phase) = cluster_content
321 .get_sub_element(ElementName::DynamicSlotIdlePhase)
322 .and_then(|dsip| dsip.character_data())
323 .and_then(|cdata| cdata.parse_integer())
324 {
325 settings.dynamic_slot_idle_phase = dynamic_slot_idle_phase;
326 }
327 if let Some(ignore_after_tx) = cluster_content
328 .get_sub_element(ElementName::IgnoreAfterTx)
329 .and_then(|iat| iat.character_data())
330 .and_then(|cdata| cdata.parse_integer())
331 {
332 settings.ignore_after_tx = ignore_after_tx;
333 }
334 if let Some(listen_noise) = cluster_content
335 .get_sub_element(ElementName::ListenNoise)
336 .and_then(|ln| ln.character_data())
337 .and_then(|cdata| cdata.parse_integer())
338 {
339 settings.listen_noise = listen_noise;
340 }
341 if let Some(macro_per_cycle) = cluster_content
342 .get_sub_element(ElementName::MacroPerCycle)
343 .and_then(|mpc| mpc.character_data())
344 .and_then(|cdata| cdata.parse_integer())
345 {
346 settings.macro_per_cycle = macro_per_cycle;
347 }
348 if let Some(macrotick_duration) = cluster_content
349 .get_sub_element(ElementName::MacrotickDuration)
350 .and_then(|mpc| mpc.character_data())
351 .and_then(|cdata| cdata.float_value())
352 {
353 settings.macrotick_duration = macrotick_duration;
354 }
355 if let Some(max_without_clock_correction_fatal) = cluster_content
356 .get_sub_element(ElementName::MaxWithoutClockCorrectionFatal)
357 .and_then(|mwccf| mwccf.character_data())
358 .and_then(|cdata| cdata.parse_integer())
359 {
360 settings.max_without_clock_correction_fatal = max_without_clock_correction_fatal;
361 }
362 if let Some(max_without_clock_correction_passive) = cluster_content
363 .get_sub_element(ElementName::MaxWithoutClockCorrectionPassive)
364 .and_then(|mwccp| mwccp.character_data())
365 .and_then(|cdata| cdata.parse_integer())
366 {
367 settings.max_without_clock_correction_passive = max_without_clock_correction_passive;
368 }
369 if let Some(minislot_action_point_offset) = cluster_content
370 .get_sub_element(ElementName::MinislotActionPointOffset)
371 .and_then(|mapo| mapo.character_data())
372 .and_then(|cdata| cdata.parse_integer())
373 {
374 settings.minislot_action_point_offset = minislot_action_point_offset;
375 }
376 if let Some(minislot_duration) = cluster_content
377 .get_sub_element(ElementName::MinislotDuration)
378 .and_then(|md| md.character_data())
379 .and_then(|cdata| cdata.parse_integer())
380 {
381 settings.minislot_duration = minislot_duration;
382 }
383 if let Some(network_idle_time) = cluster_content
384 .get_sub_element(ElementName::NetworkIdleTime)
385 .and_then(|nit| nit.character_data())
386 .and_then(|cdata| cdata.parse_integer())
387 {
388 settings.network_idle_time = network_idle_time;
389 }
390 if let Some(network_management_vector_length) = cluster_content
391 .get_sub_element(ElementName::NetworkManagementVectorLength)
392 .and_then(|nmvl| nmvl.character_data())
393 .and_then(|cdata| cdata.parse_integer())
394 {
395 settings.network_management_vector_length = network_management_vector_length;
396 }
397 if let Some(number_of_minislots) = cluster_content
398 .get_sub_element(ElementName::NumberOfMinislots)
399 .and_then(|nom| nom.character_data())
400 .and_then(|cdata| cdata.parse_integer())
401 {
402 settings.number_of_minislots = number_of_minislots;
403 }
404 if let Some(number_of_static_slots) = cluster_content
405 .get_sub_element(ElementName::NumberOfStaticSlots)
406 .and_then(|noss| noss.character_data())
407 .and_then(|cdata| cdata.parse_integer())
408 {
409 settings.number_of_static_slots = number_of_static_slots;
410 }
411 if let Some(offset_correction_start) = cluster_content
412 .get_sub_element(ElementName::OffsetCorrectionStart)
413 .and_then(|ocs| ocs.character_data())
414 .and_then(|cdata| cdata.parse_integer())
415 {
416 settings.offset_correction_start = offset_correction_start;
417 }
418 if let Some(payload_length_static) = cluster_content
419 .get_sub_element(ElementName::PayloadLengthStatic)
420 .and_then(|pls| pls.character_data())
421 .and_then(|cdata| cdata.parse_integer())
422 {
423 settings.payload_length_static = payload_length_static;
424 }
425 if let Some(safety_margin) = cluster_content
426 .get_sub_element(ElementName::SafetyMargin)
427 .and_then(|sm| sm.character_data())
428 .and_then(|cdata| cdata.parse_integer())
429 {
430 settings.safety_margin = safety_margin;
431 }
432
433 settings.sample_clock_period = cluster_content
434 .get_sub_element(ElementName::SampleClockPeriod)
435 .and_then(|scp| scp.character_data())
436 .and_then(|cdata| cdata.float_value());
437
438 if let Some(static_slot_duration) = cluster_content
439 .get_sub_element(ElementName::StaticSlotDuration)
440 .and_then(|ssd| ssd.character_data())
441 .and_then(|cdata| cdata.parse_integer())
442 {
443 settings.static_slot_duration = static_slot_duration;
444 }
445 if let Some(symbol_window) = cluster_content
446 .get_sub_element(ElementName::SymbolWindow)
447 .and_then(|sw| sw.character_data())
448 .and_then(|cdata| cdata.parse_integer())
449 {
450 settings.symbol_window = symbol_window;
451 }
452 settings.symbol_window_action_point_offset = cluster_content
453 .get_sub_element(ElementName::SymbolWindowActionPointOffset)
454 .and_then(|swapo| swapo.character_data())
455 .and_then(|cdata| cdata.parse_integer());
456
457 if let Some(sync_frame_id_count_max) = cluster_content
458 .get_sub_element(ElementName::SyncFrameIdCountMax)
459 .and_then(|sficm| sficm.character_data())
460 .and_then(|cdata| cdata.parse_integer())
461 {
462 settings.sync_frame_id_count_max = sync_frame_id_count_max;
463 }
464
465 settings.transceiver_standby_delay = cluster_content
466 .get_sub_element(ElementName::TranceiverStandbyDelay)
467 .and_then(|tsd| tsd.character_data())
468 .and_then(|cdata| cdata.float_value());
469
470 if let Some(transmission_start_sequence_duration) = cluster_content
471 .get_sub_element(ElementName::TransmissionStartSequenceDuration)
472 .and_then(|tssd| tssd.character_data())
473 .and_then(|cdata| cdata.parse_integer())
474 {
475 settings.transmission_start_sequence_duration = transmission_start_sequence_duration;
476 }
477 if let Some(wakeup_rx_idle) = cluster_content
478 .get_sub_element(ElementName::WakeupRxIdle)
479 .and_then(|wri| wri.character_data())
480 .and_then(|cdata| cdata.parse_integer())
481 {
482 settings.wakeup_rx_idle = wakeup_rx_idle;
483 }
484 if let Some(wakeup_rx_low) = cluster_content
485 .get_sub_element(ElementName::WakeupRxLow)
486 .and_then(|wrl| wrl.character_data())
487 .and_then(|cdata| cdata.parse_integer())
488 {
489 settings.wakeup_rx_low = wakeup_rx_low;
490 }
491 if let Some(wakeup_rx_window) = cluster_content
492 .get_sub_element(ElementName::WakeupRxWindow)
493 .and_then(|wrw| wrw.character_data())
494 .and_then(|cdata| cdata.parse_integer())
495 {
496 settings.wakeup_rx_window = wakeup_rx_window;
497 }
498 if let Some(wakeup_tx_active) = cluster_content
499 .get_sub_element(ElementName::WakeupTxActive)
500 .and_then(|wta| wta.character_data())
501 .and_then(|cdata| cdata.parse_integer())
502 {
503 settings.wakeup_tx_active = wakeup_tx_active;
504 }
505 if let Some(wakeup_tx_idle) = cluster_content
506 .get_sub_element(ElementName::WakeupTxIdle)
507 .and_then(|wti| wti.character_data())
508 .and_then(|cdata| cdata.parse_integer())
509 {
510 settings.wakeup_tx_idle = wakeup_tx_idle;
511 }
512 }
513
514 settings
515 }
516
517 pub fn create_physical_channel(
542 &self,
543 name: &str,
544 channel_name: FlexrayChannelName,
545 ) -> Result<FlexrayPhysicalChannel, AutosarAbstractionError> {
546 let phys_channels = self
547 .0
548 .get_or_create_sub_element(ElementName::FlexrayClusterVariants)?
549 .get_or_create_sub_element(ElementName::FlexrayClusterConditional)?
550 .get_or_create_sub_element(ElementName::PhysicalChannels)?;
551
552 for existing_channel in phys_channels.sub_elements() {
553 if let Some(existing_channel_name) = FlexrayPhysicalChannel::try_from(existing_channel)
554 .ok()
555 .and_then(|channel| channel.channel_name())
556 {
557 if existing_channel_name == channel_name {
558 return Err(AutosarAbstractionError::ItemAlreadyExists);
559 }
560 }
561 }
562
563 let channel = phys_channels.create_named_sub_element(ElementName::FlexrayPhysicalChannel, name)?;
564
565 let cn_item = match channel_name {
566 FlexrayChannelName::A => EnumItem::ChannelA,
567 FlexrayChannelName::B => EnumItem::ChannelB,
568 };
569
570 let _ = channel
571 .create_sub_element(ElementName::ChannelName)
572 .and_then(|cn| cn.set_character_data(cn_item));
573
574 FlexrayPhysicalChannel::try_from(channel)
575 }
576
577 #[must_use]
594 pub fn physical_channels(&self) -> FlexrayPhysicalChannelsInfo {
595 let mut channel_info = FlexrayPhysicalChannelsInfo {
596 channel_a: None,
597 channel_b: None,
598 };
599 if let Some(phys_channels) = self
600 .0
601 .get_sub_element(ElementName::FlexrayClusterVariants)
602 .and_then(|fcv| fcv.get_sub_element(ElementName::FlexrayClusterConditional))
603 .and_then(|fcc| fcc.get_sub_element(ElementName::PhysicalChannels))
604 {
605 for channel_elem in phys_channels.sub_elements() {
606 if let Ok(channel) = FlexrayPhysicalChannel::try_from(channel_elem) {
607 match channel.channel_name() {
608 Some(FlexrayChannelName::A) => channel_info.channel_a = Some(channel),
609 Some(FlexrayChannelName::B) => channel_info.channel_b = Some(channel),
610 None => {}
611 }
612 }
613 }
614 }
615 channel_info
616 }
617}
618
619impl AbstractCluster for FlexrayCluster {}
620
621#[derive(Debug, Clone, PartialEq)]
625pub struct FlexrayPhysicalChannelsInfo {
626 pub channel_a: Option<FlexrayPhysicalChannel>,
628 pub channel_b: Option<FlexrayPhysicalChannel>,
630}
631
632#[derive(Debug, Clone, PartialEq)]
639pub struct FlexrayClusterSettings {
640 pub baudrate: u32,
642 pub action_point_offset: u8,
645 pub bit: f64,
647 pub cas_rx_low_max: u8,
649 pub cold_start_attempts: u8,
652 pub cycle: f64,
654 pub cycle_count_max: u8,
656 pub detect_nit_error: bool,
658 pub dynamic_slot_idle_phase: u8,
660 pub ignore_after_tx: u16,
662 pub listen_noise: u8,
665 pub macro_per_cycle: u16,
667 pub macrotick_duration: f64,
669 pub max_without_clock_correction_fatal: u8,
672 pub max_without_clock_correction_passive: u8,
675 pub minislot_action_point_offset: u8,
677 pub minislot_duration: u8,
679 pub network_idle_time: u16,
681 pub network_management_vector_length: u8,
683 pub number_of_minislots: u16,
685 pub number_of_static_slots: u16,
687 pub offset_correction_start: u16,
689 pub payload_length_static: u16,
691 pub safety_margin: u16,
693 pub sample_clock_period: Option<f64>,
695 pub static_slot_duration: u16,
697 pub symbol_window: u8,
699 pub symbol_window_action_point_offset: Option<u8>,
701 pub sync_frame_id_count_max: u8,
703 pub transceiver_standby_delay: Option<f64>,
705 pub transmission_start_sequence_duration: u8,
707 pub wakeup_rx_idle: u16,
710 pub wakeup_rx_low: u8,
713 pub wakeup_rx_window: u16,
715 pub wakeup_tx_active: u16,
717 pub wakeup_tx_idle: u16,
719}
720
721impl FlexrayClusterSettings {
722 #[must_use]
724 pub fn new() -> Self {
725 Self {
726 baudrate: 10_000_000,
727 action_point_offset: 4,
728 bit: 1e-7,
729 cas_rx_low_max: 80,
730 cold_start_attempts: 16,
731 cycle: 0.005,
732 cycle_count_max: 63,
733 detect_nit_error: true,
734 dynamic_slot_idle_phase: 0,
735 ignore_after_tx: 7,
736 listen_noise: 2,
737 macro_per_cycle: 5000,
738 macrotick_duration: 1e-6,
739 max_without_clock_correction_fatal: 5,
740 max_without_clock_correction_passive: 3,
741 minislot_action_point_offset: 3,
742 minislot_duration: 10,
743 network_idle_time: 46,
744 network_management_vector_length: 0,
745 number_of_minislots: 185,
746 number_of_static_slots: 50,
747 offset_correction_start: 4980,
748 payload_length_static: 32,
749 safety_margin: 1,
750 sample_clock_period: Some(1.25e-8),
751 static_slot_duration: 62,
752 symbol_window: 0,
753 symbol_window_action_point_offset: None,
754 sync_frame_id_count_max: 8,
755 transceiver_standby_delay: None,
756 transmission_start_sequence_duration: 9,
757 wakeup_rx_idle: 50,
758 wakeup_rx_low: 50,
759 wakeup_rx_window: 301,
760 wakeup_tx_active: 60,
761 wakeup_tx_idle: 180,
762 }
763 }
764
765 #[must_use]
779 pub fn verify(&self) -> bool {
780 if 1.0 / f64::from(self.baudrate) != self.bit {
782 return false;
783 }
784
785 if self.cycle > 0.016 {
787 return false;
788 }
789
790 if self.cycle_count_max != 63 {
792 return false;
793 }
794
795 if self.payload_length_static > 127 {
797 return false;
798 }
799
800 if self.static_slot_duration < 4 || self.static_slot_duration > 661 {
802 return false;
803 }
804
805 if self.minislot_duration < 2 || self.minislot_duration > 63 {
807 return false;
808 }
809
810 if self.action_point_offset < 1
812 || self.action_point_offset > 63
813 || u16::from(self.action_point_offset) >= self.static_slot_duration
814 {
815 return false;
816 }
817
818 if self.minislot_action_point_offset < 1 || self.minislot_action_point_offset > 31 {
820 return false;
821 }
822
823 if self.cas_rx_low_max < 67 || self.cas_rx_low_max > 99 {
825 return false;
826 }
827
828 if let Some(sample_clock_period) = self.sample_clock_period {
830 if sample_clock_period != 1.25e-8 && sample_clock_period != 2.5e-8 && sample_clock_period != 5e-8 {
831 return false;
832 }
833
834 if self.bit != (sample_clock_period * 8.0) {
835 return false;
836 }
837 }
838
839 if self.symbol_window > 142 {
841 return false;
842 }
843
844 if self.macro_per_cycle < 10 || self.macro_per_cycle > 16000 {
846 return false;
847 }
848
849 if self.cycle / f64::from(self.macro_per_cycle) != self.macrotick_duration {
850 return false;
851 }
852
853 if self.network_idle_time < 2 || self.network_idle_time > 805 {
855 return false;
856 }
857
858 if self.dynamic_slot_idle_phase > 2 {
860 return false;
861 }
862
863 if self.transmission_start_sequence_duration < 3 || self.transmission_start_sequence_duration > 15 {
865 return false;
866 }
867
868 if self.number_of_static_slots > 1023 || self.number_of_static_slots + self.number_of_minislots > 2047 {
870 return false;
871 }
872
873 let static_segment_length = u32::from(self.static_slot_duration) * u32::from(self.number_of_static_slots);
875 let dynamic_segment_length = u32::from(self.minislot_duration) * u32::from(self.number_of_minislots);
876 if (static_segment_length + dynamic_segment_length + u32::from(self.network_idle_time))
877 > u32::from(self.macro_per_cycle)
878 {
879 return false;
880 }
881
882 let static_frame_size = 5 + 2 * self.payload_length_static + 3;
885 let bits_per_macrotick = self.macrotick_duration / self.bit;
886 let static_frame_bits =
887 f64::from(self.static_slot_duration - u16::from(self.action_point_offset)) * bits_per_macrotick;
888 if (static_frame_bits as u32) < u32::from(static_frame_size * 8) {
889 return false;
890 }
891
892 if (self.offset_correction_start > self.macro_per_cycle)
894 || (self.offset_correction_start < self.macro_per_cycle - self.network_idle_time)
895 {
896 return false;
897 }
898
899 if self.cold_start_attempts < 2 || self.cold_start_attempts > 31 {
901 return false;
902 }
903
904 if self.wakeup_rx_idle < 14 || self.wakeup_rx_idle > 59 {
906 return false;
907 }
908
909 if self.wakeup_rx_low < 11 || self.wakeup_rx_low > 59 {
911 return false;
912 }
913
914 if self.wakeup_rx_window < 76 || self.wakeup_rx_window > 301 {
916 return false;
917 }
918
919 if self.wakeup_tx_idle < 45 || self.wakeup_tx_idle > 180 {
921 return false;
922 }
923
924 if self.wakeup_tx_active < 15 || self.wakeup_tx_active > 60 {
926 return false;
927 }
928
929 if self.listen_noise < 2 || self.listen_noise > 16 {
931 return false;
932 }
933
934 if (self.max_without_clock_correction_fatal < self.max_without_clock_correction_passive)
936 || (self.max_without_clock_correction_fatal > 15)
937 {
938 return false;
939 }
940
941 if self.sync_frame_id_count_max < 2 || self.sync_frame_id_count_max > 15 {
942 return false;
943 }
944
945 true
946 }
947}
948
949impl Default for FlexrayClusterSettings {
950 fn default() -> Self {
951 Self::new()
952 }
953}
954
955#[cfg(test)]
958mod test {
959 use crate::{
960 AutosarModelAbstraction, SystemCategory,
961 communication::{AbstractCluster, FlexrayChannelName, FlexrayClusterSettings},
962 };
963 use autosar_data::AutosarVersion;
964
965 #[test]
966 fn cluster() {
967 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
968 let pkg = model.get_or_create_package("/test").unwrap();
969 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
970
971 let pkg2 = model.get_or_create_package("/flexray").unwrap();
972 let settings = FlexrayClusterSettings::default();
974 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
975 assert!(result.is_ok());
976 let cluster = result.unwrap();
977 let settings = FlexrayClusterSettings::default();
979 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
980 assert!(result.is_err());
981
982 let linked_system = cluster.system().unwrap();
984 assert_eq!(linked_system, system);
985
986 let result = cluster.create_physical_channel("Channel1", FlexrayChannelName::A);
988 assert!(result.is_ok());
989 let result = cluster.create_physical_channel("Channel2", FlexrayChannelName::B);
991 assert!(result.is_ok());
992 let result = cluster.create_physical_channel("Channel3", FlexrayChannelName::A);
994 assert!(result.is_err());
995
996 let pc = cluster.physical_channels();
997 assert!(pc.channel_a.is_some());
998 assert!(pc.channel_b.is_some());
999 }
1000
1001 #[test]
1002 fn flexray_settings() {
1003 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1004 let pkg = model.get_or_create_package("/test").unwrap();
1005 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1006 let settings = FlexrayClusterSettings::default();
1007 let cluster = system.create_flexray_cluster("FlxCluster", &pkg, &settings).unwrap();
1008
1009 let mut settings = FlexrayClusterSettings::new();
1010 assert!(settings.verify());
1011
1012 settings.sample_clock_period = Some(1.25e-8);
1014 settings.symbol_window_action_point_offset = Some(settings.action_point_offset);
1015 settings.transceiver_standby_delay = Some(1.0);
1016 assert!(settings.verify());
1017 cluster.update_settings(&settings);
1018 let settings2 = cluster.settings();
1019 assert_eq!(settings, settings2);
1020
1021 settings.baudrate = 0;
1023 assert!(!settings.verify());
1024 settings.baudrate = settings2.baudrate;
1025
1026 settings.cycle = 0.0161;
1027 assert!(!settings.verify());
1028 settings.cycle = settings2.cycle;
1029
1030 settings.cycle_count_max = 64;
1031 assert!(!settings.verify());
1032 settings.cycle_count_max = settings2.cycle_count_max;
1033
1034 settings.payload_length_static = 128;
1035 assert!(!settings.verify());
1036 settings.payload_length_static = settings2.payload_length_static;
1037
1038 settings.static_slot_duration = 3;
1039 assert!(!settings.verify());
1040 settings.static_slot_duration = settings2.static_slot_duration;
1041
1042 settings.minislot_duration = 64;
1043 assert!(!settings.verify());
1044 settings.minislot_duration = settings2.minislot_duration;
1045
1046 settings.action_point_offset = 64;
1047 assert!(!settings.verify());
1048 settings.action_point_offset = settings2.action_point_offset;
1049
1050 settings.minislot_action_point_offset = 32;
1051 assert!(!settings.verify());
1052 settings.minislot_action_point_offset = settings2.minislot_action_point_offset;
1053
1054 settings.cas_rx_low_max = 66;
1055 assert!(!settings.verify());
1056 settings.cas_rx_low_max = settings2.cas_rx_low_max;
1057
1058 settings.sample_clock_period = Some(1.0);
1059 assert!(!settings.verify());
1060 settings.sample_clock_period = settings2.sample_clock_period;
1061
1062 settings.symbol_window = 143;
1063 assert!(!settings.verify());
1064 settings.symbol_window = settings2.symbol_window;
1065
1066 settings.macro_per_cycle = 9;
1067 assert!(!settings.verify());
1068 settings.macro_per_cycle = settings2.macro_per_cycle;
1069
1070 settings.macro_per_cycle -= 1;
1071 assert!(!settings.verify());
1072 settings.macro_per_cycle = settings2.macro_per_cycle;
1073
1074 settings.network_idle_time = 806;
1075 assert!(!settings.verify());
1076 settings.network_idle_time = settings2.network_idle_time;
1077
1078 settings.dynamic_slot_idle_phase = 3;
1079 assert!(!settings.verify());
1080 settings.dynamic_slot_idle_phase = settings2.dynamic_slot_idle_phase;
1081
1082 settings.transmission_start_sequence_duration = 16;
1083 assert!(!settings.verify());
1084 settings.transmission_start_sequence_duration = settings2.transmission_start_sequence_duration;
1085
1086 settings.number_of_static_slots = 1024;
1087 assert!(!settings.verify());
1088 settings.number_of_static_slots = settings2.number_of_static_slots;
1089
1090 settings.number_of_static_slots += 1;
1091 assert!(!settings.verify());
1092 settings.number_of_static_slots = settings2.number_of_static_slots;
1093
1094 settings.payload_length_static += 1;
1095 assert!(!settings.verify());
1096 settings.payload_length_static = settings2.payload_length_static;
1097
1098 settings.offset_correction_start = settings.macro_per_cycle + 1;
1099 assert!(!settings.verify());
1100 settings.offset_correction_start = settings2.offset_correction_start;
1101
1102 settings.cold_start_attempts = 1;
1103 assert!(!settings.verify());
1104 settings.cold_start_attempts = settings2.cold_start_attempts;
1105
1106 settings.wakeup_rx_idle = 13;
1107 assert!(!settings.verify());
1108 settings.wakeup_rx_idle = settings2.wakeup_rx_idle;
1109
1110 settings.wakeup_rx_low = 10;
1111 assert!(!settings.verify());
1112 settings.wakeup_rx_low = settings2.wakeup_rx_low;
1113
1114 settings.wakeup_rx_window = 75;
1115 assert!(!settings.verify());
1116 settings.wakeup_rx_window = settings2.wakeup_rx_window;
1117
1118 settings.wakeup_tx_idle = 44;
1119 assert!(!settings.verify());
1120 settings.wakeup_tx_idle = settings2.wakeup_tx_idle;
1121
1122 settings.wakeup_tx_active = 14;
1123 assert!(!settings.verify());
1124 settings.wakeup_tx_active = settings2.wakeup_tx_active;
1125
1126 settings.listen_noise = 1;
1127 assert!(!settings.verify());
1128 settings.listen_noise = settings2.listen_noise;
1129
1130 settings.max_without_clock_correction_passive = settings.max_without_clock_correction_fatal + 1;
1131 assert!(!settings.verify());
1132 settings.max_without_clock_correction_passive = settings2.max_without_clock_correction_passive;
1133
1134 settings.sync_frame_id_count_max = 1;
1135 assert!(!settings.verify());
1136 settings.sync_frame_id_count_max = settings2.sync_frame_id_count_max;
1137 }
1138}