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 && existing_channel_name == channel_name
557 {
558 return Err(AutosarAbstractionError::ItemAlreadyExists);
559 }
560 }
561
562 let channel = phys_channels.create_named_sub_element(ElementName::FlexrayPhysicalChannel, name)?;
563
564 let cn_item = match channel_name {
565 FlexrayChannelName::A => EnumItem::ChannelA,
566 FlexrayChannelName::B => EnumItem::ChannelB,
567 };
568
569 let _ = channel
570 .create_sub_element(ElementName::ChannelName)
571 .and_then(|cn| cn.set_character_data(cn_item));
572
573 FlexrayPhysicalChannel::try_from(channel)
574 }
575
576 #[must_use]
593 pub fn physical_channels(&self) -> FlexrayPhysicalChannelsInfo {
594 let mut channel_info = FlexrayPhysicalChannelsInfo {
595 channel_a: None,
596 channel_b: None,
597 };
598 if let Some(phys_channels) = self
599 .0
600 .get_sub_element(ElementName::FlexrayClusterVariants)
601 .and_then(|fcv| fcv.get_sub_element(ElementName::FlexrayClusterConditional))
602 .and_then(|fcc| fcc.get_sub_element(ElementName::PhysicalChannels))
603 {
604 for channel_elem in phys_channels.sub_elements() {
605 if let Ok(channel) = FlexrayPhysicalChannel::try_from(channel_elem) {
606 match channel.channel_name() {
607 Some(FlexrayChannelName::A) => channel_info.channel_a = Some(channel),
608 Some(FlexrayChannelName::B) => channel_info.channel_b = Some(channel),
609 None => {}
610 }
611 }
612 }
613 }
614 channel_info
615 }
616}
617
618impl AbstractCluster for FlexrayCluster {}
619
620#[derive(Debug, Clone, PartialEq)]
624pub struct FlexrayPhysicalChannelsInfo {
625 pub channel_a: Option<FlexrayPhysicalChannel>,
627 pub channel_b: Option<FlexrayPhysicalChannel>,
629}
630
631#[derive(Debug, Clone, PartialEq)]
638pub struct FlexrayClusterSettings {
639 pub baudrate: u32,
641 pub action_point_offset: u8,
644 pub bit: f64,
646 pub cas_rx_low_max: u8,
648 pub cold_start_attempts: u8,
651 pub cycle: f64,
653 pub cycle_count_max: u8,
655 pub detect_nit_error: bool,
657 pub dynamic_slot_idle_phase: u8,
659 pub ignore_after_tx: u16,
661 pub listen_noise: u8,
664 pub macro_per_cycle: u16,
666 pub macrotick_duration: f64,
668 pub max_without_clock_correction_fatal: u8,
671 pub max_without_clock_correction_passive: u8,
674 pub minislot_action_point_offset: u8,
676 pub minislot_duration: u8,
678 pub network_idle_time: u16,
680 pub network_management_vector_length: u8,
682 pub number_of_minislots: u16,
684 pub number_of_static_slots: u16,
686 pub offset_correction_start: u16,
688 pub payload_length_static: u16,
690 pub safety_margin: u16,
692 pub sample_clock_period: Option<f64>,
694 pub static_slot_duration: u16,
696 pub symbol_window: u8,
698 pub symbol_window_action_point_offset: Option<u8>,
700 pub sync_frame_id_count_max: u8,
702 pub transceiver_standby_delay: Option<f64>,
704 pub transmission_start_sequence_duration: u8,
706 pub wakeup_rx_idle: u16,
709 pub wakeup_rx_low: u8,
712 pub wakeup_rx_window: u16,
714 pub wakeup_tx_active: u16,
716 pub wakeup_tx_idle: u16,
718}
719
720impl FlexrayClusterSettings {
721 #[must_use]
723 pub fn new() -> Self {
724 Self {
725 baudrate: 10_000_000,
726 action_point_offset: 4,
727 bit: 1e-7,
728 cas_rx_low_max: 80,
729 cold_start_attempts: 16,
730 cycle: 0.005,
731 cycle_count_max: 63,
732 detect_nit_error: true,
733 dynamic_slot_idle_phase: 0,
734 ignore_after_tx: 7,
735 listen_noise: 2,
736 macro_per_cycle: 5000,
737 macrotick_duration: 1e-6,
738 max_without_clock_correction_fatal: 5,
739 max_without_clock_correction_passive: 3,
740 minislot_action_point_offset: 3,
741 minislot_duration: 10,
742 network_idle_time: 46,
743 network_management_vector_length: 0,
744 number_of_minislots: 185,
745 number_of_static_slots: 50,
746 offset_correction_start: 4980,
747 payload_length_static: 32,
748 safety_margin: 1,
749 sample_clock_period: Some(1.25e-8),
750 static_slot_duration: 62,
751 symbol_window: 0,
752 symbol_window_action_point_offset: None,
753 sync_frame_id_count_max: 8,
754 transceiver_standby_delay: None,
755 transmission_start_sequence_duration: 9,
756 wakeup_rx_idle: 50,
757 wakeup_rx_low: 50,
758 wakeup_rx_window: 301,
759 wakeup_tx_active: 60,
760 wakeup_tx_idle: 180,
761 }
762 }
763
764 #[must_use]
778 pub fn verify(&self) -> bool {
779 if 1.0 / f64::from(self.baudrate) != self.bit {
781 return false;
782 }
783
784 if self.cycle > 0.016 {
786 return false;
787 }
788
789 if self.cycle_count_max != 63 {
791 return false;
792 }
793
794 if self.payload_length_static > 127 {
796 return false;
797 }
798
799 if self.static_slot_duration < 4 || self.static_slot_duration > 661 {
801 return false;
802 }
803
804 if self.minislot_duration < 2 || self.minislot_duration > 63 {
806 return false;
807 }
808
809 if self.action_point_offset < 1
811 || self.action_point_offset > 63
812 || u16::from(self.action_point_offset) >= self.static_slot_duration
813 {
814 return false;
815 }
816
817 if self.minislot_action_point_offset < 1 || self.minislot_action_point_offset > 31 {
819 return false;
820 }
821
822 if self.cas_rx_low_max < 67 || self.cas_rx_low_max > 99 {
824 return false;
825 }
826
827 if let Some(sample_clock_period) = self.sample_clock_period {
829 if sample_clock_period != 1.25e-8 && sample_clock_period != 2.5e-8 && sample_clock_period != 5e-8 {
830 return false;
831 }
832
833 if self.bit != (sample_clock_period * 8.0) {
834 return false;
835 }
836 }
837
838 if self.symbol_window > 142 {
840 return false;
841 }
842
843 if self.macro_per_cycle < 10 || self.macro_per_cycle > 16000 {
845 return false;
846 }
847
848 if self.cycle / f64::from(self.macro_per_cycle) != self.macrotick_duration {
849 return false;
850 }
851
852 if self.network_idle_time < 2 || self.network_idle_time > 805 {
854 return false;
855 }
856
857 if self.dynamic_slot_idle_phase > 2 {
859 return false;
860 }
861
862 if self.transmission_start_sequence_duration < 3 || self.transmission_start_sequence_duration > 15 {
864 return false;
865 }
866
867 if self.number_of_static_slots > 1023 || self.number_of_static_slots + self.number_of_minislots > 2047 {
869 return false;
870 }
871
872 let static_segment_length = u32::from(self.static_slot_duration) * u32::from(self.number_of_static_slots);
874 let dynamic_segment_length = u32::from(self.minislot_duration) * u32::from(self.number_of_minislots);
875 if (static_segment_length + dynamic_segment_length + u32::from(self.network_idle_time))
876 > u32::from(self.macro_per_cycle)
877 {
878 return false;
879 }
880
881 let static_frame_size = 5 + 2 * self.payload_length_static + 3;
884 let bits_per_macrotick = self.macrotick_duration / self.bit;
885 let static_frame_bits =
886 f64::from(self.static_slot_duration - u16::from(self.action_point_offset)) * bits_per_macrotick;
887 if (static_frame_bits as u32) < u32::from(static_frame_size * 8) {
888 return false;
889 }
890
891 if (self.offset_correction_start > self.macro_per_cycle)
893 || (self.offset_correction_start < self.macro_per_cycle - self.network_idle_time)
894 {
895 return false;
896 }
897
898 if self.cold_start_attempts < 2 || self.cold_start_attempts > 31 {
900 return false;
901 }
902
903 if self.wakeup_rx_idle < 14 || self.wakeup_rx_idle > 59 {
905 return false;
906 }
907
908 if self.wakeup_rx_low < 11 || self.wakeup_rx_low > 59 {
910 return false;
911 }
912
913 if self.wakeup_rx_window < 76 || self.wakeup_rx_window > 301 {
915 return false;
916 }
917
918 if self.wakeup_tx_idle < 45 || self.wakeup_tx_idle > 180 {
920 return false;
921 }
922
923 if self.wakeup_tx_active < 15 || self.wakeup_tx_active > 60 {
925 return false;
926 }
927
928 if self.listen_noise < 2 || self.listen_noise > 16 {
930 return false;
931 }
932
933 if (self.max_without_clock_correction_fatal < self.max_without_clock_correction_passive)
935 || (self.max_without_clock_correction_fatal > 15)
936 {
937 return false;
938 }
939
940 if self.sync_frame_id_count_max < 2 || self.sync_frame_id_count_max > 15 {
941 return false;
942 }
943
944 true
945 }
946}
947
948impl Default for FlexrayClusterSettings {
949 fn default() -> Self {
950 Self::new()
951 }
952}
953
954#[cfg(test)]
957mod test {
958 use crate::{
959 AutosarModelAbstraction, SystemCategory,
960 communication::{AbstractCluster, FlexrayChannelName, FlexrayClusterSettings},
961 };
962 use autosar_data::AutosarVersion;
963
964 #[test]
965 fn cluster() {
966 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
967 let pkg = model.get_or_create_package("/test").unwrap();
968 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
969
970 let pkg2 = model.get_or_create_package("/flexray").unwrap();
971 let settings = FlexrayClusterSettings::default();
973 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
974 assert!(result.is_ok());
975 let cluster = result.unwrap();
976 let settings = FlexrayClusterSettings::default();
978 let result = system.create_flexray_cluster("FlxCluster", &pkg2, &settings);
979 assert!(result.is_err());
980
981 let linked_system = cluster.system().unwrap();
983 assert_eq!(linked_system, system);
984
985 let result = cluster.create_physical_channel("Channel1", FlexrayChannelName::A);
987 assert!(result.is_ok());
988 let result = cluster.create_physical_channel("Channel2", FlexrayChannelName::B);
990 assert!(result.is_ok());
991 let result = cluster.create_physical_channel("Channel3", FlexrayChannelName::A);
993 assert!(result.is_err());
994
995 let pc = cluster.physical_channels();
996 assert!(pc.channel_a.is_some());
997 assert!(pc.channel_b.is_some());
998 }
999
1000 #[test]
1001 fn flexray_settings() {
1002 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
1003 let pkg = model.get_or_create_package("/test").unwrap();
1004 let system = pkg.create_system("System", SystemCategory::SystemDescription).unwrap();
1005 let settings = FlexrayClusterSettings::default();
1006 let cluster = system.create_flexray_cluster("FlxCluster", &pkg, &settings).unwrap();
1007
1008 let mut settings = FlexrayClusterSettings::new();
1009 assert!(settings.verify());
1010
1011 settings.sample_clock_period = Some(1.25e-8);
1013 settings.symbol_window_action_point_offset = Some(settings.action_point_offset);
1014 settings.transceiver_standby_delay = Some(1.0);
1015 assert!(settings.verify());
1016 cluster.update_settings(&settings);
1017 let settings2 = cluster.settings();
1018 assert_eq!(settings, settings2);
1019
1020 settings.baudrate = 0;
1022 assert!(!settings.verify());
1023 settings.baudrate = settings2.baudrate;
1024
1025 settings.cycle = 0.0161;
1026 assert!(!settings.verify());
1027 settings.cycle = settings2.cycle;
1028
1029 settings.cycle_count_max = 64;
1030 assert!(!settings.verify());
1031 settings.cycle_count_max = settings2.cycle_count_max;
1032
1033 settings.payload_length_static = 128;
1034 assert!(!settings.verify());
1035 settings.payload_length_static = settings2.payload_length_static;
1036
1037 settings.static_slot_duration = 3;
1038 assert!(!settings.verify());
1039 settings.static_slot_duration = settings2.static_slot_duration;
1040
1041 settings.minislot_duration = 64;
1042 assert!(!settings.verify());
1043 settings.minislot_duration = settings2.minislot_duration;
1044
1045 settings.action_point_offset = 64;
1046 assert!(!settings.verify());
1047 settings.action_point_offset = settings2.action_point_offset;
1048
1049 settings.minislot_action_point_offset = 32;
1050 assert!(!settings.verify());
1051 settings.minislot_action_point_offset = settings2.minislot_action_point_offset;
1052
1053 settings.cas_rx_low_max = 66;
1054 assert!(!settings.verify());
1055 settings.cas_rx_low_max = settings2.cas_rx_low_max;
1056
1057 settings.sample_clock_period = Some(1.0);
1058 assert!(!settings.verify());
1059 settings.sample_clock_period = settings2.sample_clock_period;
1060
1061 settings.symbol_window = 143;
1062 assert!(!settings.verify());
1063 settings.symbol_window = settings2.symbol_window;
1064
1065 settings.macro_per_cycle = 9;
1066 assert!(!settings.verify());
1067 settings.macro_per_cycle = settings2.macro_per_cycle;
1068
1069 settings.macro_per_cycle -= 1;
1070 assert!(!settings.verify());
1071 settings.macro_per_cycle = settings2.macro_per_cycle;
1072
1073 settings.network_idle_time = 806;
1074 assert!(!settings.verify());
1075 settings.network_idle_time = settings2.network_idle_time;
1076
1077 settings.dynamic_slot_idle_phase = 3;
1078 assert!(!settings.verify());
1079 settings.dynamic_slot_idle_phase = settings2.dynamic_slot_idle_phase;
1080
1081 settings.transmission_start_sequence_duration = 16;
1082 assert!(!settings.verify());
1083 settings.transmission_start_sequence_duration = settings2.transmission_start_sequence_duration;
1084
1085 settings.number_of_static_slots = 1024;
1086 assert!(!settings.verify());
1087 settings.number_of_static_slots = settings2.number_of_static_slots;
1088
1089 settings.number_of_static_slots += 1;
1090 assert!(!settings.verify());
1091 settings.number_of_static_slots = settings2.number_of_static_slots;
1092
1093 settings.payload_length_static += 1;
1094 assert!(!settings.verify());
1095 settings.payload_length_static = settings2.payload_length_static;
1096
1097 settings.offset_correction_start = settings.macro_per_cycle + 1;
1098 assert!(!settings.verify());
1099 settings.offset_correction_start = settings2.offset_correction_start;
1100
1101 settings.cold_start_attempts = 1;
1102 assert!(!settings.verify());
1103 settings.cold_start_attempts = settings2.cold_start_attempts;
1104
1105 settings.wakeup_rx_idle = 13;
1106 assert!(!settings.verify());
1107 settings.wakeup_rx_idle = settings2.wakeup_rx_idle;
1108
1109 settings.wakeup_rx_low = 10;
1110 assert!(!settings.verify());
1111 settings.wakeup_rx_low = settings2.wakeup_rx_low;
1112
1113 settings.wakeup_rx_window = 75;
1114 assert!(!settings.verify());
1115 settings.wakeup_rx_window = settings2.wakeup_rx_window;
1116
1117 settings.wakeup_tx_idle = 44;
1118 assert!(!settings.verify());
1119 settings.wakeup_tx_idle = settings2.wakeup_tx_idle;
1120
1121 settings.wakeup_tx_active = 14;
1122 assert!(!settings.verify());
1123 settings.wakeup_tx_active = settings2.wakeup_tx_active;
1124
1125 settings.listen_noise = 1;
1126 assert!(!settings.verify());
1127 settings.listen_noise = settings2.listen_noise;
1128
1129 settings.max_without_clock_correction_passive = settings.max_without_clock_correction_fatal + 1;
1130 assert!(!settings.verify());
1131 settings.max_without_clock_correction_passive = settings2.max_without_clock_correction_passive;
1132
1133 settings.sync_frame_id_count_max = 1;
1134 assert!(!settings.verify());
1135 settings.sync_frame_id_count_max = settings2.sync_frame_id_count_max;
1136 }
1137}