oscura 0.0.1__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oscura/__init__.py +813 -8
- oscura/__main__.py +392 -0
- oscura/analyzers/__init__.py +37 -0
- oscura/analyzers/digital/__init__.py +177 -0
- oscura/analyzers/digital/bus.py +691 -0
- oscura/analyzers/digital/clock.py +805 -0
- oscura/analyzers/digital/correlation.py +720 -0
- oscura/analyzers/digital/edges.py +632 -0
- oscura/analyzers/digital/extraction.py +413 -0
- oscura/analyzers/digital/quality.py +878 -0
- oscura/analyzers/digital/signal_quality.py +877 -0
- oscura/analyzers/digital/thresholds.py +708 -0
- oscura/analyzers/digital/timing.py +1104 -0
- oscura/analyzers/eye/__init__.py +46 -0
- oscura/analyzers/eye/diagram.py +434 -0
- oscura/analyzers/eye/metrics.py +555 -0
- oscura/analyzers/jitter/__init__.py +83 -0
- oscura/analyzers/jitter/ber.py +333 -0
- oscura/analyzers/jitter/decomposition.py +759 -0
- oscura/analyzers/jitter/measurements.py +413 -0
- oscura/analyzers/jitter/spectrum.py +220 -0
- oscura/analyzers/measurements.py +40 -0
- oscura/analyzers/packet/__init__.py +171 -0
- oscura/analyzers/packet/daq.py +1077 -0
- oscura/analyzers/packet/metrics.py +437 -0
- oscura/analyzers/packet/parser.py +327 -0
- oscura/analyzers/packet/payload.py +2156 -0
- oscura/analyzers/packet/payload_analysis.py +1312 -0
- oscura/analyzers/packet/payload_extraction.py +236 -0
- oscura/analyzers/packet/payload_patterns.py +670 -0
- oscura/analyzers/packet/stream.py +359 -0
- oscura/analyzers/patterns/__init__.py +266 -0
- oscura/analyzers/patterns/clustering.py +1036 -0
- oscura/analyzers/patterns/discovery.py +539 -0
- oscura/analyzers/patterns/learning.py +797 -0
- oscura/analyzers/patterns/matching.py +1091 -0
- oscura/analyzers/patterns/periodic.py +650 -0
- oscura/analyzers/patterns/sequences.py +767 -0
- oscura/analyzers/power/__init__.py +116 -0
- oscura/analyzers/power/ac_power.py +391 -0
- oscura/analyzers/power/basic.py +383 -0
- oscura/analyzers/power/conduction.py +314 -0
- oscura/analyzers/power/efficiency.py +297 -0
- oscura/analyzers/power/ripple.py +356 -0
- oscura/analyzers/power/soa.py +372 -0
- oscura/analyzers/power/switching.py +479 -0
- oscura/analyzers/protocol/__init__.py +150 -0
- oscura/analyzers/protocols/__init__.py +150 -0
- oscura/analyzers/protocols/base.py +500 -0
- oscura/analyzers/protocols/can.py +620 -0
- oscura/analyzers/protocols/can_fd.py +448 -0
- oscura/analyzers/protocols/flexray.py +405 -0
- oscura/analyzers/protocols/hdlc.py +399 -0
- oscura/analyzers/protocols/i2c.py +368 -0
- oscura/analyzers/protocols/i2s.py +296 -0
- oscura/analyzers/protocols/jtag.py +393 -0
- oscura/analyzers/protocols/lin.py +445 -0
- oscura/analyzers/protocols/manchester.py +333 -0
- oscura/analyzers/protocols/onewire.py +501 -0
- oscura/analyzers/protocols/spi.py +334 -0
- oscura/analyzers/protocols/swd.py +325 -0
- oscura/analyzers/protocols/uart.py +393 -0
- oscura/analyzers/protocols/usb.py +495 -0
- oscura/analyzers/signal_integrity/__init__.py +63 -0
- oscura/analyzers/signal_integrity/embedding.py +294 -0
- oscura/analyzers/signal_integrity/equalization.py +370 -0
- oscura/analyzers/signal_integrity/sparams.py +484 -0
- oscura/analyzers/spectral/__init__.py +53 -0
- oscura/analyzers/spectral/chunked.py +273 -0
- oscura/analyzers/spectral/chunked_fft.py +571 -0
- oscura/analyzers/spectral/chunked_wavelet.py +391 -0
- oscura/analyzers/spectral/fft.py +92 -0
- oscura/analyzers/statistical/__init__.py +250 -0
- oscura/analyzers/statistical/checksum.py +923 -0
- oscura/analyzers/statistical/chunked_corr.py +228 -0
- oscura/analyzers/statistical/classification.py +778 -0
- oscura/analyzers/statistical/entropy.py +1113 -0
- oscura/analyzers/statistical/ngrams.py +614 -0
- oscura/analyzers/statistics/__init__.py +119 -0
- oscura/analyzers/statistics/advanced.py +885 -0
- oscura/analyzers/statistics/basic.py +263 -0
- oscura/analyzers/statistics/correlation.py +630 -0
- oscura/analyzers/statistics/distribution.py +298 -0
- oscura/analyzers/statistics/outliers.py +463 -0
- oscura/analyzers/statistics/streaming.py +93 -0
- oscura/analyzers/statistics/trend.py +520 -0
- oscura/analyzers/validation.py +598 -0
- oscura/analyzers/waveform/__init__.py +36 -0
- oscura/analyzers/waveform/measurements.py +943 -0
- oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
- oscura/analyzers/waveform/spectral.py +1689 -0
- oscura/analyzers/waveform/wavelets.py +298 -0
- oscura/api/__init__.py +62 -0
- oscura/api/dsl.py +538 -0
- oscura/api/fluent.py +571 -0
- oscura/api/operators.py +498 -0
- oscura/api/optimization.py +392 -0
- oscura/api/profiling.py +396 -0
- oscura/automotive/__init__.py +73 -0
- oscura/automotive/can/__init__.py +52 -0
- oscura/automotive/can/analysis.py +356 -0
- oscura/automotive/can/checksum.py +250 -0
- oscura/automotive/can/correlation.py +212 -0
- oscura/automotive/can/discovery.py +355 -0
- oscura/automotive/can/message_wrapper.py +375 -0
- oscura/automotive/can/models.py +385 -0
- oscura/automotive/can/patterns.py +381 -0
- oscura/automotive/can/session.py +452 -0
- oscura/automotive/can/state_machine.py +300 -0
- oscura/automotive/can/stimulus_response.py +461 -0
- oscura/automotive/dbc/__init__.py +15 -0
- oscura/automotive/dbc/generator.py +156 -0
- oscura/automotive/dbc/parser.py +146 -0
- oscura/automotive/dtc/__init__.py +30 -0
- oscura/automotive/dtc/database.py +3036 -0
- oscura/automotive/j1939/__init__.py +14 -0
- oscura/automotive/j1939/decoder.py +745 -0
- oscura/automotive/loaders/__init__.py +35 -0
- oscura/automotive/loaders/asc.py +98 -0
- oscura/automotive/loaders/blf.py +77 -0
- oscura/automotive/loaders/csv_can.py +136 -0
- oscura/automotive/loaders/dispatcher.py +136 -0
- oscura/automotive/loaders/mdf.py +331 -0
- oscura/automotive/loaders/pcap.py +132 -0
- oscura/automotive/obd/__init__.py +14 -0
- oscura/automotive/obd/decoder.py +707 -0
- oscura/automotive/uds/__init__.py +48 -0
- oscura/automotive/uds/decoder.py +265 -0
- oscura/automotive/uds/models.py +64 -0
- oscura/automotive/visualization.py +369 -0
- oscura/batch/__init__.py +55 -0
- oscura/batch/advanced.py +627 -0
- oscura/batch/aggregate.py +300 -0
- oscura/batch/analyze.py +139 -0
- oscura/batch/logging.py +487 -0
- oscura/batch/metrics.py +556 -0
- oscura/builders/__init__.py +41 -0
- oscura/builders/signal_builder.py +1131 -0
- oscura/cli/__init__.py +14 -0
- oscura/cli/batch.py +339 -0
- oscura/cli/characterize.py +273 -0
- oscura/cli/compare.py +775 -0
- oscura/cli/decode.py +551 -0
- oscura/cli/main.py +247 -0
- oscura/cli/shell.py +350 -0
- oscura/comparison/__init__.py +66 -0
- oscura/comparison/compare.py +397 -0
- oscura/comparison/golden.py +487 -0
- oscura/comparison/limits.py +391 -0
- oscura/comparison/mask.py +434 -0
- oscura/comparison/trace_diff.py +30 -0
- oscura/comparison/visualization.py +481 -0
- oscura/compliance/__init__.py +70 -0
- oscura/compliance/advanced.py +756 -0
- oscura/compliance/masks.py +363 -0
- oscura/compliance/reporting.py +483 -0
- oscura/compliance/testing.py +298 -0
- oscura/component/__init__.py +38 -0
- oscura/component/impedance.py +365 -0
- oscura/component/reactive.py +598 -0
- oscura/component/transmission_line.py +312 -0
- oscura/config/__init__.py +191 -0
- oscura/config/defaults.py +254 -0
- oscura/config/loader.py +348 -0
- oscura/config/memory.py +271 -0
- oscura/config/migration.py +458 -0
- oscura/config/pipeline.py +1077 -0
- oscura/config/preferences.py +530 -0
- oscura/config/protocol.py +875 -0
- oscura/config/schema.py +713 -0
- oscura/config/settings.py +420 -0
- oscura/config/thresholds.py +599 -0
- oscura/convenience.py +457 -0
- oscura/core/__init__.py +299 -0
- oscura/core/audit.py +457 -0
- oscura/core/backend_selector.py +405 -0
- oscura/core/cache.py +590 -0
- oscura/core/cancellation.py +439 -0
- oscura/core/confidence.py +225 -0
- oscura/core/config.py +506 -0
- oscura/core/correlation.py +216 -0
- oscura/core/cross_domain.py +422 -0
- oscura/core/debug.py +301 -0
- oscura/core/edge_cases.py +541 -0
- oscura/core/exceptions.py +535 -0
- oscura/core/gpu_backend.py +523 -0
- oscura/core/lazy.py +832 -0
- oscura/core/log_query.py +540 -0
- oscura/core/logging.py +931 -0
- oscura/core/logging_advanced.py +952 -0
- oscura/core/memoize.py +171 -0
- oscura/core/memory_check.py +274 -0
- oscura/core/memory_guard.py +290 -0
- oscura/core/memory_limits.py +336 -0
- oscura/core/memory_monitor.py +453 -0
- oscura/core/memory_progress.py +465 -0
- oscura/core/memory_warnings.py +315 -0
- oscura/core/numba_backend.py +362 -0
- oscura/core/performance.py +352 -0
- oscura/core/progress.py +524 -0
- oscura/core/provenance.py +358 -0
- oscura/core/results.py +331 -0
- oscura/core/types.py +504 -0
- oscura/core/uncertainty.py +383 -0
- oscura/discovery/__init__.py +52 -0
- oscura/discovery/anomaly_detector.py +672 -0
- oscura/discovery/auto_decoder.py +415 -0
- oscura/discovery/comparison.py +497 -0
- oscura/discovery/quality_validator.py +528 -0
- oscura/discovery/signal_detector.py +769 -0
- oscura/dsl/__init__.py +73 -0
- oscura/dsl/commands.py +246 -0
- oscura/dsl/interpreter.py +455 -0
- oscura/dsl/parser.py +689 -0
- oscura/dsl/repl.py +172 -0
- oscura/exceptions.py +59 -0
- oscura/exploratory/__init__.py +111 -0
- oscura/exploratory/error_recovery.py +642 -0
- oscura/exploratory/fuzzy.py +513 -0
- oscura/exploratory/fuzzy_advanced.py +786 -0
- oscura/exploratory/legacy.py +831 -0
- oscura/exploratory/parse.py +358 -0
- oscura/exploratory/recovery.py +275 -0
- oscura/exploratory/sync.py +382 -0
- oscura/exploratory/unknown.py +707 -0
- oscura/export/__init__.py +25 -0
- oscura/export/wireshark/README.md +265 -0
- oscura/export/wireshark/__init__.py +47 -0
- oscura/export/wireshark/generator.py +312 -0
- oscura/export/wireshark/lua_builder.py +159 -0
- oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
- oscura/export/wireshark/type_mapping.py +165 -0
- oscura/export/wireshark/validator.py +105 -0
- oscura/exporters/__init__.py +94 -0
- oscura/exporters/csv.py +303 -0
- oscura/exporters/exporters.py +44 -0
- oscura/exporters/hdf5.py +219 -0
- oscura/exporters/html_export.py +701 -0
- oscura/exporters/json_export.py +291 -0
- oscura/exporters/markdown_export.py +367 -0
- oscura/exporters/matlab_export.py +354 -0
- oscura/exporters/npz_export.py +219 -0
- oscura/exporters/spice_export.py +210 -0
- oscura/extensibility/__init__.py +131 -0
- oscura/extensibility/docs.py +752 -0
- oscura/extensibility/extensions.py +1125 -0
- oscura/extensibility/logging.py +259 -0
- oscura/extensibility/measurements.py +485 -0
- oscura/extensibility/plugins.py +414 -0
- oscura/extensibility/registry.py +346 -0
- oscura/extensibility/templates.py +913 -0
- oscura/extensibility/validation.py +651 -0
- oscura/filtering/__init__.py +89 -0
- oscura/filtering/base.py +563 -0
- oscura/filtering/convenience.py +564 -0
- oscura/filtering/design.py +725 -0
- oscura/filtering/filters.py +32 -0
- oscura/filtering/introspection.py +605 -0
- oscura/guidance/__init__.py +24 -0
- oscura/guidance/recommender.py +429 -0
- oscura/guidance/wizard.py +518 -0
- oscura/inference/__init__.py +251 -0
- oscura/inference/active_learning/README.md +153 -0
- oscura/inference/active_learning/__init__.py +38 -0
- oscura/inference/active_learning/lstar.py +257 -0
- oscura/inference/active_learning/observation_table.py +230 -0
- oscura/inference/active_learning/oracle.py +78 -0
- oscura/inference/active_learning/teachers/__init__.py +15 -0
- oscura/inference/active_learning/teachers/simulator.py +192 -0
- oscura/inference/adaptive_tuning.py +453 -0
- oscura/inference/alignment.py +653 -0
- oscura/inference/bayesian.py +943 -0
- oscura/inference/binary.py +1016 -0
- oscura/inference/crc_reverse.py +711 -0
- oscura/inference/logic.py +288 -0
- oscura/inference/message_format.py +1305 -0
- oscura/inference/protocol.py +417 -0
- oscura/inference/protocol_dsl.py +1084 -0
- oscura/inference/protocol_library.py +1230 -0
- oscura/inference/sequences.py +809 -0
- oscura/inference/signal_intelligence.py +1509 -0
- oscura/inference/spectral.py +215 -0
- oscura/inference/state_machine.py +634 -0
- oscura/inference/stream.py +918 -0
- oscura/integrations/__init__.py +59 -0
- oscura/integrations/llm.py +1827 -0
- oscura/jupyter/__init__.py +32 -0
- oscura/jupyter/display.py +268 -0
- oscura/jupyter/magic.py +334 -0
- oscura/loaders/__init__.py +526 -0
- oscura/loaders/binary.py +69 -0
- oscura/loaders/configurable.py +1255 -0
- oscura/loaders/csv.py +26 -0
- oscura/loaders/csv_loader.py +473 -0
- oscura/loaders/hdf5.py +9 -0
- oscura/loaders/hdf5_loader.py +510 -0
- oscura/loaders/lazy.py +370 -0
- oscura/loaders/mmap_loader.py +583 -0
- oscura/loaders/numpy_loader.py +436 -0
- oscura/loaders/pcap.py +432 -0
- oscura/loaders/preprocessing.py +368 -0
- oscura/loaders/rigol.py +287 -0
- oscura/loaders/sigrok.py +321 -0
- oscura/loaders/tdms.py +367 -0
- oscura/loaders/tektronix.py +711 -0
- oscura/loaders/validation.py +584 -0
- oscura/loaders/vcd.py +464 -0
- oscura/loaders/wav.py +233 -0
- oscura/math/__init__.py +45 -0
- oscura/math/arithmetic.py +824 -0
- oscura/math/interpolation.py +413 -0
- oscura/onboarding/__init__.py +39 -0
- oscura/onboarding/help.py +498 -0
- oscura/onboarding/tutorials.py +405 -0
- oscura/onboarding/wizard.py +466 -0
- oscura/optimization/__init__.py +19 -0
- oscura/optimization/parallel.py +440 -0
- oscura/optimization/search.py +532 -0
- oscura/pipeline/__init__.py +43 -0
- oscura/pipeline/base.py +338 -0
- oscura/pipeline/composition.py +242 -0
- oscura/pipeline/parallel.py +448 -0
- oscura/pipeline/pipeline.py +375 -0
- oscura/pipeline/reverse_engineering.py +1119 -0
- oscura/plugins/__init__.py +122 -0
- oscura/plugins/base.py +272 -0
- oscura/plugins/cli.py +497 -0
- oscura/plugins/discovery.py +411 -0
- oscura/plugins/isolation.py +418 -0
- oscura/plugins/lifecycle.py +959 -0
- oscura/plugins/manager.py +493 -0
- oscura/plugins/registry.py +421 -0
- oscura/plugins/versioning.py +372 -0
- oscura/py.typed +0 -0
- oscura/quality/__init__.py +65 -0
- oscura/quality/ensemble.py +740 -0
- oscura/quality/explainer.py +338 -0
- oscura/quality/scoring.py +616 -0
- oscura/quality/warnings.py +456 -0
- oscura/reporting/__init__.py +248 -0
- oscura/reporting/advanced.py +1234 -0
- oscura/reporting/analyze.py +448 -0
- oscura/reporting/argument_preparer.py +596 -0
- oscura/reporting/auto_report.py +507 -0
- oscura/reporting/batch.py +615 -0
- oscura/reporting/chart_selection.py +223 -0
- oscura/reporting/comparison.py +330 -0
- oscura/reporting/config.py +615 -0
- oscura/reporting/content/__init__.py +39 -0
- oscura/reporting/content/executive.py +127 -0
- oscura/reporting/content/filtering.py +191 -0
- oscura/reporting/content/minimal.py +257 -0
- oscura/reporting/content/verbosity.py +162 -0
- oscura/reporting/core.py +508 -0
- oscura/reporting/core_formats/__init__.py +17 -0
- oscura/reporting/core_formats/multi_format.py +210 -0
- oscura/reporting/engine.py +836 -0
- oscura/reporting/export.py +366 -0
- oscura/reporting/formatting/__init__.py +129 -0
- oscura/reporting/formatting/emphasis.py +81 -0
- oscura/reporting/formatting/numbers.py +403 -0
- oscura/reporting/formatting/standards.py +55 -0
- oscura/reporting/formatting.py +466 -0
- oscura/reporting/html.py +578 -0
- oscura/reporting/index.py +590 -0
- oscura/reporting/multichannel.py +296 -0
- oscura/reporting/output.py +379 -0
- oscura/reporting/pdf.py +373 -0
- oscura/reporting/plots.py +731 -0
- oscura/reporting/pptx_export.py +360 -0
- oscura/reporting/renderers/__init__.py +11 -0
- oscura/reporting/renderers/pdf.py +94 -0
- oscura/reporting/sections.py +471 -0
- oscura/reporting/standards.py +680 -0
- oscura/reporting/summary_generator.py +368 -0
- oscura/reporting/tables.py +397 -0
- oscura/reporting/template_system.py +724 -0
- oscura/reporting/templates/__init__.py +15 -0
- oscura/reporting/templates/definition.py +205 -0
- oscura/reporting/templates/index.html +649 -0
- oscura/reporting/templates/index.md +173 -0
- oscura/schemas/__init__.py +158 -0
- oscura/schemas/bus_configuration.json +322 -0
- oscura/schemas/device_mapping.json +182 -0
- oscura/schemas/packet_format.json +418 -0
- oscura/schemas/protocol_definition.json +363 -0
- oscura/search/__init__.py +16 -0
- oscura/search/anomaly.py +292 -0
- oscura/search/context.py +149 -0
- oscura/search/pattern.py +160 -0
- oscura/session/__init__.py +34 -0
- oscura/session/annotations.py +289 -0
- oscura/session/history.py +313 -0
- oscura/session/session.py +445 -0
- oscura/streaming/__init__.py +43 -0
- oscura/streaming/chunked.py +611 -0
- oscura/streaming/progressive.py +393 -0
- oscura/streaming/realtime.py +622 -0
- oscura/testing/__init__.py +54 -0
- oscura/testing/synthetic.py +808 -0
- oscura/triggering/__init__.py +68 -0
- oscura/triggering/base.py +229 -0
- oscura/triggering/edge.py +353 -0
- oscura/triggering/pattern.py +344 -0
- oscura/triggering/pulse.py +581 -0
- oscura/triggering/window.py +453 -0
- oscura/ui/__init__.py +48 -0
- oscura/ui/formatters.py +526 -0
- oscura/ui/progressive_display.py +340 -0
- oscura/utils/__init__.py +99 -0
- oscura/utils/autodetect.py +338 -0
- oscura/utils/buffer.py +389 -0
- oscura/utils/lazy.py +407 -0
- oscura/utils/lazy_imports.py +147 -0
- oscura/utils/memory.py +836 -0
- oscura/utils/memory_advanced.py +1326 -0
- oscura/utils/memory_extensions.py +465 -0
- oscura/utils/progressive.py +352 -0
- oscura/utils/windowing.py +362 -0
- oscura/visualization/__init__.py +321 -0
- oscura/visualization/accessibility.py +526 -0
- oscura/visualization/annotations.py +374 -0
- oscura/visualization/axis_scaling.py +305 -0
- oscura/visualization/colors.py +453 -0
- oscura/visualization/digital.py +337 -0
- oscura/visualization/eye.py +420 -0
- oscura/visualization/histogram.py +281 -0
- oscura/visualization/interactive.py +858 -0
- oscura/visualization/jitter.py +702 -0
- oscura/visualization/keyboard.py +394 -0
- oscura/visualization/layout.py +365 -0
- oscura/visualization/optimization.py +1028 -0
- oscura/visualization/palettes.py +446 -0
- oscura/visualization/plot.py +92 -0
- oscura/visualization/power.py +290 -0
- oscura/visualization/power_extended.py +626 -0
- oscura/visualization/presets.py +467 -0
- oscura/visualization/protocols.py +932 -0
- oscura/visualization/render.py +207 -0
- oscura/visualization/rendering.py +444 -0
- oscura/visualization/reverse_engineering.py +791 -0
- oscura/visualization/signal_integrity.py +808 -0
- oscura/visualization/specialized.py +553 -0
- oscura/visualization/spectral.py +811 -0
- oscura/visualization/styles.py +381 -0
- oscura/visualization/thumbnails.py +311 -0
- oscura/visualization/time_axis.py +351 -0
- oscura/visualization/waveform.py +367 -0
- oscura/workflow/__init__.py +13 -0
- oscura/workflow/dag.py +377 -0
- oscura/workflows/__init__.py +58 -0
- oscura/workflows/compliance.py +280 -0
- oscura/workflows/digital.py +272 -0
- oscura/workflows/multi_trace.py +502 -0
- oscura/workflows/power.py +178 -0
- oscura/workflows/protocol.py +492 -0
- oscura/workflows/reverse_engineering.py +639 -0
- oscura/workflows/signal_integrity.py +227 -0
- oscura-0.1.1.dist-info/METADATA +300 -0
- oscura-0.1.1.dist-info/RECORD +463 -0
- oscura-0.1.1.dist-info/entry_points.txt +2 -0
- {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/licenses/LICENSE +1 -1
- oscura-0.0.1.dist-info/METADATA +0 -63
- oscura-0.0.1.dist-info/RECORD +0 -5
- {oscura-0.0.1.dist-info → oscura-0.1.1.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"""FlexRay protocol decoder.
|
|
2
|
+
|
|
3
|
+
This module implements FlexRay automotive protocol decoder with support
|
|
4
|
+
for static and dynamic segments, 10 Mbps signaling, and CRC validation.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Example:
|
|
8
|
+
>>> from oscura.analyzers.protocols.flexray import FlexRayDecoder
|
|
9
|
+
>>> decoder = FlexRayDecoder()
|
|
10
|
+
>>> for packet in decoder.decode(bp=bp, bm=bm):
|
|
11
|
+
... print(f"Slot: {packet.annotations['slot_id']}")
|
|
12
|
+
|
|
13
|
+
References:
|
|
14
|
+
FlexRay Communications System Protocol Specification Version 3.0.1
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from dataclasses import dataclass
|
|
20
|
+
from enum import Enum
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
from oscura.analyzers.protocols.base import (
|
|
24
|
+
AnnotationLevel,
|
|
25
|
+
AsyncDecoder,
|
|
26
|
+
ChannelDef,
|
|
27
|
+
OptionDef,
|
|
28
|
+
)
|
|
29
|
+
from oscura.core.types import DigitalTrace, ProtocolPacket, WaveformTrace
|
|
30
|
+
|
|
31
|
+
if TYPE_CHECKING:
|
|
32
|
+
from collections.abc import Iterator
|
|
33
|
+
|
|
34
|
+
import numpy as np
|
|
35
|
+
from numpy.typing import NDArray
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class FlexRaySegment(Enum):
|
|
39
|
+
"""FlexRay communication segment types."""
|
|
40
|
+
|
|
41
|
+
STATIC = "static"
|
|
42
|
+
DYNAMIC = "dynamic"
|
|
43
|
+
SYMBOL = "symbol"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class FlexRayFrame:
|
|
48
|
+
"""Decoded FlexRay frame.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
slot_id: Slot identifier (1-2047).
|
|
52
|
+
cycle_count: Cycle counter (0-63).
|
|
53
|
+
payload_length: Payload length in 16-bit words (0-127).
|
|
54
|
+
header_crc: Header CRC value.
|
|
55
|
+
payload: Payload data bytes.
|
|
56
|
+
frame_crc: Frame CRC value (24-bit).
|
|
57
|
+
segment: Segment type (static or dynamic).
|
|
58
|
+
timestamp: Frame start time in seconds.
|
|
59
|
+
errors: List of detected errors.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
slot_id: int
|
|
63
|
+
cycle_count: int
|
|
64
|
+
payload_length: int
|
|
65
|
+
header_crc: int
|
|
66
|
+
payload: bytes
|
|
67
|
+
frame_crc: int
|
|
68
|
+
segment: FlexRaySegment
|
|
69
|
+
timestamp: float
|
|
70
|
+
errors: list[str]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class FlexRayDecoder(AsyncDecoder):
|
|
74
|
+
"""FlexRay protocol decoder.
|
|
75
|
+
|
|
76
|
+
Decodes FlexRay bus frames with header and frame CRC validation,
|
|
77
|
+
static and dynamic segment support, and slot/cycle identification.
|
|
78
|
+
|
|
79
|
+
Attributes:
|
|
80
|
+
id: "flexray"
|
|
81
|
+
name: "FlexRay"
|
|
82
|
+
channels: [bp, bm] (differential pair)
|
|
83
|
+
|
|
84
|
+
Example:
|
|
85
|
+
>>> decoder = FlexRayDecoder(bitrate=10000000)
|
|
86
|
+
>>> for packet in decoder.decode(bp=bp, bm=bm, sample_rate=100e6):
|
|
87
|
+
... print(f"Slot {packet.annotations['slot_id']}, Cycle {packet.annotations['cycle_count']}")
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
id = "flexray"
|
|
91
|
+
name = "FlexRay"
|
|
92
|
+
longname = "FlexRay Automotive Network"
|
|
93
|
+
desc = "FlexRay protocol decoder"
|
|
94
|
+
|
|
95
|
+
channels = [ # noqa: RUF012
|
|
96
|
+
ChannelDef("bp", "BP", "FlexRay Bus Plus", required=True),
|
|
97
|
+
ChannelDef("bm", "BM", "FlexRay Bus Minus", required=True),
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
optional_channels = [] # noqa: RUF012
|
|
101
|
+
|
|
102
|
+
options = [ # noqa: RUF012
|
|
103
|
+
OptionDef(
|
|
104
|
+
"bitrate",
|
|
105
|
+
"Bitrate",
|
|
106
|
+
"Bits per second",
|
|
107
|
+
default=10000000,
|
|
108
|
+
values=[2500000, 5000000, 10000000],
|
|
109
|
+
),
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
annotations = [ # noqa: RUF012
|
|
113
|
+
("tss", "Transmission Start Sequence"),
|
|
114
|
+
("fss", "Frame Start Sequence"),
|
|
115
|
+
("header", "Frame header"),
|
|
116
|
+
("payload", "Payload"),
|
|
117
|
+
("crc", "Frame CRC"),
|
|
118
|
+
("error", "Error"),
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
# FlexRay constants
|
|
122
|
+
TSS_LENGTH = 3 # Transmission Start Sequence (Low + Low + High)
|
|
123
|
+
FSS_LENGTH = 1 # Frame Start Sequence (Low)
|
|
124
|
+
BSS_LENGTH = 1 # Byte Start Sequence
|
|
125
|
+
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
bitrate: int = 10000000,
|
|
129
|
+
) -> None:
|
|
130
|
+
"""Initialize FlexRay decoder.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
bitrate: FlexRay bitrate in bps (2.5, 5, or 10 Mbps).
|
|
134
|
+
"""
|
|
135
|
+
super().__init__(baudrate=bitrate, bitrate=bitrate)
|
|
136
|
+
self._bitrate = bitrate
|
|
137
|
+
|
|
138
|
+
def decode( # type: ignore[override]
|
|
139
|
+
self,
|
|
140
|
+
trace: DigitalTrace | WaveformTrace | None = None,
|
|
141
|
+
*,
|
|
142
|
+
bp: NDArray[np.bool_] | None = None,
|
|
143
|
+
bm: NDArray[np.bool_] | None = None,
|
|
144
|
+
sample_rate: float = 1.0,
|
|
145
|
+
) -> Iterator[ProtocolPacket]:
|
|
146
|
+
"""Decode FlexRay frames.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
trace: Optional input trace.
|
|
150
|
+
bp: Bus Plus signal.
|
|
151
|
+
bm: Bus Minus signal.
|
|
152
|
+
sample_rate: Sample rate in Hz.
|
|
153
|
+
|
|
154
|
+
Yields:
|
|
155
|
+
Decoded FlexRay frames as ProtocolPacket objects.
|
|
156
|
+
|
|
157
|
+
Example:
|
|
158
|
+
>>> decoder = FlexRayDecoder(bitrate=10000000)
|
|
159
|
+
>>> for pkt in decoder.decode(bp=bp, bm=bm, sample_rate=100e6):
|
|
160
|
+
... print(f"Slot: {pkt.annotations['slot_id']}")
|
|
161
|
+
"""
|
|
162
|
+
if trace is not None:
|
|
163
|
+
if isinstance(trace, WaveformTrace):
|
|
164
|
+
from oscura.analyzers.digital.extraction import to_digital
|
|
165
|
+
|
|
166
|
+
digital_trace = to_digital(trace, threshold="auto")
|
|
167
|
+
else:
|
|
168
|
+
digital_trace = trace
|
|
169
|
+
bp = digital_trace.data
|
|
170
|
+
sample_rate = digital_trace.metadata.sample_rate
|
|
171
|
+
|
|
172
|
+
if bp is None or bm is None:
|
|
173
|
+
return
|
|
174
|
+
|
|
175
|
+
n_samples = min(len(bp), len(bm))
|
|
176
|
+
bp = bp[:n_samples]
|
|
177
|
+
bm = bm[:n_samples]
|
|
178
|
+
|
|
179
|
+
# Decode differential signal
|
|
180
|
+
# IdleLow: BP=0, BM=1 -> 0
|
|
181
|
+
# Data0: BP=1, BM=0 -> 1
|
|
182
|
+
# Data1: BP=0, BM=1 -> 0
|
|
183
|
+
# Simplified: use BP as primary signal
|
|
184
|
+
diff_signal = bp
|
|
185
|
+
|
|
186
|
+
bit_period = sample_rate / self._bitrate
|
|
187
|
+
|
|
188
|
+
frame_num = 0
|
|
189
|
+
idx = 0
|
|
190
|
+
|
|
191
|
+
while idx < len(diff_signal):
|
|
192
|
+
# Look for TSS (Transmission Start Sequence)
|
|
193
|
+
tss_idx = self._find_tss(diff_signal, idx, bit_period)
|
|
194
|
+
if tss_idx is None:
|
|
195
|
+
break
|
|
196
|
+
|
|
197
|
+
# Decode frame
|
|
198
|
+
frame, end_idx = self._decode_frame(diff_signal, tss_idx, sample_rate, bit_period)
|
|
199
|
+
|
|
200
|
+
if frame is not None:
|
|
201
|
+
# Add annotation
|
|
202
|
+
self.put_annotation(
|
|
203
|
+
frame.timestamp,
|
|
204
|
+
frame.timestamp + 0.001,
|
|
205
|
+
AnnotationLevel.PACKETS,
|
|
206
|
+
f"Slot {frame.slot_id}, Cycle {frame.cycle_count}",
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Create packet
|
|
210
|
+
annotations = {
|
|
211
|
+
"frame_num": frame_num,
|
|
212
|
+
"slot_id": frame.slot_id,
|
|
213
|
+
"cycle_count": frame.cycle_count,
|
|
214
|
+
"payload_length": frame.payload_length,
|
|
215
|
+
"header_crc": frame.header_crc,
|
|
216
|
+
"frame_crc": frame.frame_crc,
|
|
217
|
+
"segment": frame.segment.value,
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
packet = ProtocolPacket(
|
|
221
|
+
timestamp=frame.timestamp,
|
|
222
|
+
protocol="flexray",
|
|
223
|
+
data=frame.payload,
|
|
224
|
+
annotations=annotations,
|
|
225
|
+
errors=frame.errors,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
yield packet
|
|
229
|
+
frame_num += 1
|
|
230
|
+
|
|
231
|
+
idx = end_idx if end_idx > idx else idx + int(bit_period)
|
|
232
|
+
|
|
233
|
+
def _find_tss(
|
|
234
|
+
self,
|
|
235
|
+
data: NDArray[np.bool_],
|
|
236
|
+
start_idx: int,
|
|
237
|
+
bit_period: float,
|
|
238
|
+
) -> int | None:
|
|
239
|
+
"""Find Transmission Start Sequence.
|
|
240
|
+
|
|
241
|
+
Args:
|
|
242
|
+
data: Digital data array.
|
|
243
|
+
start_idx: Start search index.
|
|
244
|
+
bit_period: Bit period in samples.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Index of TSS start, or None if not found.
|
|
248
|
+
"""
|
|
249
|
+
# TSS pattern: Low (idle), Low (data0), High (data1)
|
|
250
|
+
# Simplified: look for specific transition pattern
|
|
251
|
+
idx = start_idx
|
|
252
|
+
while idx < len(data) - int(3 * bit_period):
|
|
253
|
+
# Sample at bit centers
|
|
254
|
+
sample1_idx = int(idx + bit_period / 2)
|
|
255
|
+
sample2_idx = int(idx + 1.5 * bit_period)
|
|
256
|
+
sample3_idx = int(idx + 2.5 * bit_period)
|
|
257
|
+
|
|
258
|
+
if sample1_idx < len(data) and sample2_idx < len(data) and sample3_idx < len(data):
|
|
259
|
+
# Check for low, low, high pattern
|
|
260
|
+
if not data[sample1_idx] and not data[sample2_idx] and data[sample3_idx]:
|
|
261
|
+
return idx
|
|
262
|
+
|
|
263
|
+
idx += int(bit_period / 4)
|
|
264
|
+
|
|
265
|
+
return None
|
|
266
|
+
|
|
267
|
+
def _decode_frame(
|
|
268
|
+
self,
|
|
269
|
+
data: NDArray[np.bool_],
|
|
270
|
+
tss_idx: int,
|
|
271
|
+
sample_rate: float,
|
|
272
|
+
bit_period: float,
|
|
273
|
+
) -> tuple[FlexRayFrame | None, int]:
|
|
274
|
+
"""Decode FlexRay frame starting from TSS.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
data: Digital data array.
|
|
278
|
+
tss_idx: TSS index.
|
|
279
|
+
sample_rate: Sample rate in Hz.
|
|
280
|
+
bit_period: Bit period in samples.
|
|
281
|
+
|
|
282
|
+
Returns:
|
|
283
|
+
(frame, end_index) tuple.
|
|
284
|
+
"""
|
|
285
|
+
errors = []
|
|
286
|
+
bit_idx = tss_idx + int(3 * bit_period) # Skip TSS
|
|
287
|
+
|
|
288
|
+
# Sample bits
|
|
289
|
+
def sample_bits(count: int) -> list[int]:
|
|
290
|
+
nonlocal bit_idx
|
|
291
|
+
bits = []
|
|
292
|
+
for _ in range(count):
|
|
293
|
+
sample_idx = int(bit_idx + bit_period / 2)
|
|
294
|
+
if sample_idx < len(data):
|
|
295
|
+
bits.append(1 if data[sample_idx] else 0)
|
|
296
|
+
bit_idx += bit_period # type: ignore[assignment]
|
|
297
|
+
else:
|
|
298
|
+
return bits
|
|
299
|
+
return bits
|
|
300
|
+
|
|
301
|
+
# FSS (Frame Start Sequence) - 1 bit
|
|
302
|
+
fss_bits = sample_bits(1)
|
|
303
|
+
if not fss_bits or fss_bits[0] != 0:
|
|
304
|
+
errors.append("Invalid FSS")
|
|
305
|
+
|
|
306
|
+
# Header (5 bytes = 40 bits)
|
|
307
|
+
# Byte 1: Reserved (1) + Payload preamble (1) + NULL frame (1) + Sync (1) + Startup (1) + Slot ID[10:8] (3)
|
|
308
|
+
# Byte 2: Slot ID[7:0] (8)
|
|
309
|
+
# Byte 3: Header CRC[10:3] (8)
|
|
310
|
+
# Byte 4: Header CRC[2:0] (3) + Cycle count[5:0] (6) - split to bits 7:5 and 4:0
|
|
311
|
+
# Byte 5: Cycle count continued + Payload length[6:0] (7)
|
|
312
|
+
|
|
313
|
+
header_bits = sample_bits(40)
|
|
314
|
+
if len(header_bits) < 40:
|
|
315
|
+
return None, int(bit_idx)
|
|
316
|
+
|
|
317
|
+
# Extract header fields (simplified)
|
|
318
|
+
# Slot ID (11 bits): bits 4-14
|
|
319
|
+
slot_id_bits = header_bits[4:15]
|
|
320
|
+
slot_id = 0
|
|
321
|
+
for bit in slot_id_bits:
|
|
322
|
+
slot_id = (slot_id << 1) | bit
|
|
323
|
+
|
|
324
|
+
# Header CRC (11 bits): bits 15-25
|
|
325
|
+
header_crc_bits = header_bits[15:26]
|
|
326
|
+
header_crc = 0
|
|
327
|
+
for bit in header_crc_bits:
|
|
328
|
+
header_crc = (header_crc << 1) | bit
|
|
329
|
+
|
|
330
|
+
# Cycle count (6 bits): bits 26-31
|
|
331
|
+
cycle_bits = header_bits[26:32]
|
|
332
|
+
cycle_count = 0
|
|
333
|
+
for bit in cycle_bits:
|
|
334
|
+
cycle_count = (cycle_count << 1) | bit
|
|
335
|
+
|
|
336
|
+
# Payload length (7 bits): bits 33-39
|
|
337
|
+
payload_len_bits = header_bits[33:40]
|
|
338
|
+
payload_length = 0
|
|
339
|
+
for bit in payload_len_bits:
|
|
340
|
+
payload_length = (payload_length << 1) | bit
|
|
341
|
+
|
|
342
|
+
# Payload (payload_length * 2 bytes, as length is in 16-bit words)
|
|
343
|
+
payload_byte_count = payload_length * 2
|
|
344
|
+
payload_bytes = []
|
|
345
|
+
|
|
346
|
+
for _ in range(payload_byte_count):
|
|
347
|
+
byte_bits = sample_bits(8)
|
|
348
|
+
if len(byte_bits) == 8:
|
|
349
|
+
byte_val = 0
|
|
350
|
+
for bit in byte_bits:
|
|
351
|
+
byte_val = (byte_val << 1) | bit
|
|
352
|
+
payload_bytes.append(byte_val)
|
|
353
|
+
else:
|
|
354
|
+
errors.append("Incomplete payload")
|
|
355
|
+
break
|
|
356
|
+
|
|
357
|
+
# Frame CRC (24 bits)
|
|
358
|
+
crc_bits = sample_bits(24)
|
|
359
|
+
frame_crc = 0
|
|
360
|
+
for bit in crc_bits:
|
|
361
|
+
frame_crc = (frame_crc << 1) | bit
|
|
362
|
+
|
|
363
|
+
# Create frame
|
|
364
|
+
frame = FlexRayFrame(
|
|
365
|
+
slot_id=slot_id,
|
|
366
|
+
cycle_count=cycle_count,
|
|
367
|
+
payload_length=payload_length,
|
|
368
|
+
header_crc=header_crc,
|
|
369
|
+
payload=bytes(payload_bytes),
|
|
370
|
+
frame_crc=frame_crc,
|
|
371
|
+
segment=FlexRaySegment.STATIC, # Simplified: assume static
|
|
372
|
+
timestamp=tss_idx / sample_rate,
|
|
373
|
+
errors=errors,
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
return frame, int(bit_idx)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
def decode_flexray(
|
|
380
|
+
bp: NDArray[np.bool_],
|
|
381
|
+
bm: NDArray[np.bool_],
|
|
382
|
+
sample_rate: float = 1.0,
|
|
383
|
+
bitrate: int = 10000000,
|
|
384
|
+
) -> list[ProtocolPacket]:
|
|
385
|
+
"""Convenience function to decode FlexRay frames.
|
|
386
|
+
|
|
387
|
+
Args:
|
|
388
|
+
bp: Bus Plus signal.
|
|
389
|
+
bm: Bus Minus signal.
|
|
390
|
+
sample_rate: Sample rate in Hz.
|
|
391
|
+
bitrate: FlexRay bitrate in bps.
|
|
392
|
+
|
|
393
|
+
Returns:
|
|
394
|
+
List of decoded FlexRay frames.
|
|
395
|
+
|
|
396
|
+
Example:
|
|
397
|
+
>>> packets = decode_flexray(bp, bm, sample_rate=100e6, bitrate=10e6)
|
|
398
|
+
>>> for pkt in packets:
|
|
399
|
+
... print(f"Slot: {pkt.annotations['slot_id']}")
|
|
400
|
+
"""
|
|
401
|
+
decoder = FlexRayDecoder(bitrate=bitrate)
|
|
402
|
+
return list(decoder.decode(bp=bp, bm=bm, sample_rate=sample_rate))
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
__all__ = ["FlexRayDecoder", "FlexRayFrame", "FlexRaySegment", "decode_flexray"]
|