oscura 0.0.1__py3-none-any.whl → 0.1.0__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.
Files changed (465) hide show
  1. oscura/__init__.py +813 -8
  2. oscura/__main__.py +392 -0
  3. oscura/analyzers/__init__.py +37 -0
  4. oscura/analyzers/digital/__init__.py +177 -0
  5. oscura/analyzers/digital/bus.py +691 -0
  6. oscura/analyzers/digital/clock.py +805 -0
  7. oscura/analyzers/digital/correlation.py +720 -0
  8. oscura/analyzers/digital/edges.py +632 -0
  9. oscura/analyzers/digital/extraction.py +413 -0
  10. oscura/analyzers/digital/quality.py +878 -0
  11. oscura/analyzers/digital/signal_quality.py +877 -0
  12. oscura/analyzers/digital/thresholds.py +708 -0
  13. oscura/analyzers/digital/timing.py +1104 -0
  14. oscura/analyzers/eye/__init__.py +46 -0
  15. oscura/analyzers/eye/diagram.py +434 -0
  16. oscura/analyzers/eye/metrics.py +555 -0
  17. oscura/analyzers/jitter/__init__.py +83 -0
  18. oscura/analyzers/jitter/ber.py +333 -0
  19. oscura/analyzers/jitter/decomposition.py +759 -0
  20. oscura/analyzers/jitter/measurements.py +413 -0
  21. oscura/analyzers/jitter/spectrum.py +220 -0
  22. oscura/analyzers/measurements.py +40 -0
  23. oscura/analyzers/packet/__init__.py +171 -0
  24. oscura/analyzers/packet/daq.py +1077 -0
  25. oscura/analyzers/packet/metrics.py +437 -0
  26. oscura/analyzers/packet/parser.py +327 -0
  27. oscura/analyzers/packet/payload.py +2156 -0
  28. oscura/analyzers/packet/payload_analysis.py +1312 -0
  29. oscura/analyzers/packet/payload_extraction.py +236 -0
  30. oscura/analyzers/packet/payload_patterns.py +670 -0
  31. oscura/analyzers/packet/stream.py +359 -0
  32. oscura/analyzers/patterns/__init__.py +266 -0
  33. oscura/analyzers/patterns/clustering.py +1036 -0
  34. oscura/analyzers/patterns/discovery.py +539 -0
  35. oscura/analyzers/patterns/learning.py +797 -0
  36. oscura/analyzers/patterns/matching.py +1091 -0
  37. oscura/analyzers/patterns/periodic.py +650 -0
  38. oscura/analyzers/patterns/sequences.py +767 -0
  39. oscura/analyzers/power/__init__.py +116 -0
  40. oscura/analyzers/power/ac_power.py +391 -0
  41. oscura/analyzers/power/basic.py +383 -0
  42. oscura/analyzers/power/conduction.py +314 -0
  43. oscura/analyzers/power/efficiency.py +297 -0
  44. oscura/analyzers/power/ripple.py +356 -0
  45. oscura/analyzers/power/soa.py +372 -0
  46. oscura/analyzers/power/switching.py +479 -0
  47. oscura/analyzers/protocol/__init__.py +150 -0
  48. oscura/analyzers/protocols/__init__.py +150 -0
  49. oscura/analyzers/protocols/base.py +500 -0
  50. oscura/analyzers/protocols/can.py +620 -0
  51. oscura/analyzers/protocols/can_fd.py +448 -0
  52. oscura/analyzers/protocols/flexray.py +405 -0
  53. oscura/analyzers/protocols/hdlc.py +399 -0
  54. oscura/analyzers/protocols/i2c.py +368 -0
  55. oscura/analyzers/protocols/i2s.py +296 -0
  56. oscura/analyzers/protocols/jtag.py +393 -0
  57. oscura/analyzers/protocols/lin.py +445 -0
  58. oscura/analyzers/protocols/manchester.py +333 -0
  59. oscura/analyzers/protocols/onewire.py +501 -0
  60. oscura/analyzers/protocols/spi.py +334 -0
  61. oscura/analyzers/protocols/swd.py +325 -0
  62. oscura/analyzers/protocols/uart.py +393 -0
  63. oscura/analyzers/protocols/usb.py +495 -0
  64. oscura/analyzers/signal_integrity/__init__.py +63 -0
  65. oscura/analyzers/signal_integrity/embedding.py +294 -0
  66. oscura/analyzers/signal_integrity/equalization.py +370 -0
  67. oscura/analyzers/signal_integrity/sparams.py +484 -0
  68. oscura/analyzers/spectral/__init__.py +53 -0
  69. oscura/analyzers/spectral/chunked.py +273 -0
  70. oscura/analyzers/spectral/chunked_fft.py +571 -0
  71. oscura/analyzers/spectral/chunked_wavelet.py +391 -0
  72. oscura/analyzers/spectral/fft.py +92 -0
  73. oscura/analyzers/statistical/__init__.py +250 -0
  74. oscura/analyzers/statistical/checksum.py +923 -0
  75. oscura/analyzers/statistical/chunked_corr.py +228 -0
  76. oscura/analyzers/statistical/classification.py +778 -0
  77. oscura/analyzers/statistical/entropy.py +1113 -0
  78. oscura/analyzers/statistical/ngrams.py +614 -0
  79. oscura/analyzers/statistics/__init__.py +119 -0
  80. oscura/analyzers/statistics/advanced.py +885 -0
  81. oscura/analyzers/statistics/basic.py +263 -0
  82. oscura/analyzers/statistics/correlation.py +630 -0
  83. oscura/analyzers/statistics/distribution.py +298 -0
  84. oscura/analyzers/statistics/outliers.py +463 -0
  85. oscura/analyzers/statistics/streaming.py +93 -0
  86. oscura/analyzers/statistics/trend.py +520 -0
  87. oscura/analyzers/validation.py +598 -0
  88. oscura/analyzers/waveform/__init__.py +36 -0
  89. oscura/analyzers/waveform/measurements.py +943 -0
  90. oscura/analyzers/waveform/measurements_with_uncertainty.py +371 -0
  91. oscura/analyzers/waveform/spectral.py +1689 -0
  92. oscura/analyzers/waveform/wavelets.py +298 -0
  93. oscura/api/__init__.py +62 -0
  94. oscura/api/dsl.py +538 -0
  95. oscura/api/fluent.py +571 -0
  96. oscura/api/operators.py +498 -0
  97. oscura/api/optimization.py +392 -0
  98. oscura/api/profiling.py +396 -0
  99. oscura/automotive/__init__.py +73 -0
  100. oscura/automotive/can/__init__.py +52 -0
  101. oscura/automotive/can/analysis.py +356 -0
  102. oscura/automotive/can/checksum.py +250 -0
  103. oscura/automotive/can/correlation.py +212 -0
  104. oscura/automotive/can/discovery.py +355 -0
  105. oscura/automotive/can/message_wrapper.py +375 -0
  106. oscura/automotive/can/models.py +385 -0
  107. oscura/automotive/can/patterns.py +381 -0
  108. oscura/automotive/can/session.py +452 -0
  109. oscura/automotive/can/state_machine.py +300 -0
  110. oscura/automotive/can/stimulus_response.py +461 -0
  111. oscura/automotive/dbc/__init__.py +15 -0
  112. oscura/automotive/dbc/generator.py +156 -0
  113. oscura/automotive/dbc/parser.py +146 -0
  114. oscura/automotive/dtc/__init__.py +30 -0
  115. oscura/automotive/dtc/database.py +3036 -0
  116. oscura/automotive/j1939/__init__.py +14 -0
  117. oscura/automotive/j1939/decoder.py +745 -0
  118. oscura/automotive/loaders/__init__.py +35 -0
  119. oscura/automotive/loaders/asc.py +98 -0
  120. oscura/automotive/loaders/blf.py +77 -0
  121. oscura/automotive/loaders/csv_can.py +136 -0
  122. oscura/automotive/loaders/dispatcher.py +136 -0
  123. oscura/automotive/loaders/mdf.py +331 -0
  124. oscura/automotive/loaders/pcap.py +132 -0
  125. oscura/automotive/obd/__init__.py +14 -0
  126. oscura/automotive/obd/decoder.py +707 -0
  127. oscura/automotive/uds/__init__.py +48 -0
  128. oscura/automotive/uds/decoder.py +265 -0
  129. oscura/automotive/uds/models.py +64 -0
  130. oscura/automotive/visualization.py +369 -0
  131. oscura/batch/__init__.py +55 -0
  132. oscura/batch/advanced.py +627 -0
  133. oscura/batch/aggregate.py +300 -0
  134. oscura/batch/analyze.py +139 -0
  135. oscura/batch/logging.py +487 -0
  136. oscura/batch/metrics.py +556 -0
  137. oscura/builders/__init__.py +41 -0
  138. oscura/builders/signal_builder.py +1131 -0
  139. oscura/cli/__init__.py +14 -0
  140. oscura/cli/batch.py +339 -0
  141. oscura/cli/characterize.py +273 -0
  142. oscura/cli/compare.py +775 -0
  143. oscura/cli/decode.py +551 -0
  144. oscura/cli/main.py +247 -0
  145. oscura/cli/shell.py +350 -0
  146. oscura/comparison/__init__.py +66 -0
  147. oscura/comparison/compare.py +397 -0
  148. oscura/comparison/golden.py +487 -0
  149. oscura/comparison/limits.py +391 -0
  150. oscura/comparison/mask.py +434 -0
  151. oscura/comparison/trace_diff.py +30 -0
  152. oscura/comparison/visualization.py +481 -0
  153. oscura/compliance/__init__.py +70 -0
  154. oscura/compliance/advanced.py +756 -0
  155. oscura/compliance/masks.py +363 -0
  156. oscura/compliance/reporting.py +483 -0
  157. oscura/compliance/testing.py +298 -0
  158. oscura/component/__init__.py +38 -0
  159. oscura/component/impedance.py +365 -0
  160. oscura/component/reactive.py +598 -0
  161. oscura/component/transmission_line.py +312 -0
  162. oscura/config/__init__.py +191 -0
  163. oscura/config/defaults.py +254 -0
  164. oscura/config/loader.py +348 -0
  165. oscura/config/memory.py +271 -0
  166. oscura/config/migration.py +458 -0
  167. oscura/config/pipeline.py +1077 -0
  168. oscura/config/preferences.py +530 -0
  169. oscura/config/protocol.py +875 -0
  170. oscura/config/schema.py +713 -0
  171. oscura/config/settings.py +420 -0
  172. oscura/config/thresholds.py +599 -0
  173. oscura/convenience.py +457 -0
  174. oscura/core/__init__.py +299 -0
  175. oscura/core/audit.py +457 -0
  176. oscura/core/backend_selector.py +405 -0
  177. oscura/core/cache.py +590 -0
  178. oscura/core/cancellation.py +439 -0
  179. oscura/core/confidence.py +225 -0
  180. oscura/core/config.py +506 -0
  181. oscura/core/correlation.py +216 -0
  182. oscura/core/cross_domain.py +422 -0
  183. oscura/core/debug.py +301 -0
  184. oscura/core/edge_cases.py +541 -0
  185. oscura/core/exceptions.py +535 -0
  186. oscura/core/gpu_backend.py +523 -0
  187. oscura/core/lazy.py +832 -0
  188. oscura/core/log_query.py +540 -0
  189. oscura/core/logging.py +931 -0
  190. oscura/core/logging_advanced.py +952 -0
  191. oscura/core/memoize.py +171 -0
  192. oscura/core/memory_check.py +274 -0
  193. oscura/core/memory_guard.py +290 -0
  194. oscura/core/memory_limits.py +336 -0
  195. oscura/core/memory_monitor.py +453 -0
  196. oscura/core/memory_progress.py +465 -0
  197. oscura/core/memory_warnings.py +315 -0
  198. oscura/core/numba_backend.py +362 -0
  199. oscura/core/performance.py +352 -0
  200. oscura/core/progress.py +524 -0
  201. oscura/core/provenance.py +358 -0
  202. oscura/core/results.py +331 -0
  203. oscura/core/types.py +504 -0
  204. oscura/core/uncertainty.py +383 -0
  205. oscura/discovery/__init__.py +52 -0
  206. oscura/discovery/anomaly_detector.py +672 -0
  207. oscura/discovery/auto_decoder.py +415 -0
  208. oscura/discovery/comparison.py +497 -0
  209. oscura/discovery/quality_validator.py +528 -0
  210. oscura/discovery/signal_detector.py +769 -0
  211. oscura/dsl/__init__.py +73 -0
  212. oscura/dsl/commands.py +246 -0
  213. oscura/dsl/interpreter.py +455 -0
  214. oscura/dsl/parser.py +689 -0
  215. oscura/dsl/repl.py +172 -0
  216. oscura/exceptions.py +59 -0
  217. oscura/exploratory/__init__.py +111 -0
  218. oscura/exploratory/error_recovery.py +642 -0
  219. oscura/exploratory/fuzzy.py +513 -0
  220. oscura/exploratory/fuzzy_advanced.py +786 -0
  221. oscura/exploratory/legacy.py +831 -0
  222. oscura/exploratory/parse.py +358 -0
  223. oscura/exploratory/recovery.py +275 -0
  224. oscura/exploratory/sync.py +382 -0
  225. oscura/exploratory/unknown.py +707 -0
  226. oscura/export/__init__.py +25 -0
  227. oscura/export/wireshark/README.md +265 -0
  228. oscura/export/wireshark/__init__.py +47 -0
  229. oscura/export/wireshark/generator.py +312 -0
  230. oscura/export/wireshark/lua_builder.py +159 -0
  231. oscura/export/wireshark/templates/dissector.lua.j2 +92 -0
  232. oscura/export/wireshark/type_mapping.py +165 -0
  233. oscura/export/wireshark/validator.py +105 -0
  234. oscura/exporters/__init__.py +94 -0
  235. oscura/exporters/csv.py +303 -0
  236. oscura/exporters/exporters.py +44 -0
  237. oscura/exporters/hdf5.py +219 -0
  238. oscura/exporters/html_export.py +701 -0
  239. oscura/exporters/json_export.py +291 -0
  240. oscura/exporters/markdown_export.py +367 -0
  241. oscura/exporters/matlab_export.py +354 -0
  242. oscura/exporters/npz_export.py +219 -0
  243. oscura/exporters/spice_export.py +210 -0
  244. oscura/extensibility/__init__.py +131 -0
  245. oscura/extensibility/docs.py +752 -0
  246. oscura/extensibility/extensions.py +1125 -0
  247. oscura/extensibility/logging.py +259 -0
  248. oscura/extensibility/measurements.py +485 -0
  249. oscura/extensibility/plugins.py +414 -0
  250. oscura/extensibility/registry.py +346 -0
  251. oscura/extensibility/templates.py +913 -0
  252. oscura/extensibility/validation.py +651 -0
  253. oscura/filtering/__init__.py +89 -0
  254. oscura/filtering/base.py +563 -0
  255. oscura/filtering/convenience.py +564 -0
  256. oscura/filtering/design.py +725 -0
  257. oscura/filtering/filters.py +32 -0
  258. oscura/filtering/introspection.py +605 -0
  259. oscura/guidance/__init__.py +24 -0
  260. oscura/guidance/recommender.py +429 -0
  261. oscura/guidance/wizard.py +518 -0
  262. oscura/inference/__init__.py +251 -0
  263. oscura/inference/active_learning/README.md +153 -0
  264. oscura/inference/active_learning/__init__.py +38 -0
  265. oscura/inference/active_learning/lstar.py +257 -0
  266. oscura/inference/active_learning/observation_table.py +230 -0
  267. oscura/inference/active_learning/oracle.py +78 -0
  268. oscura/inference/active_learning/teachers/__init__.py +15 -0
  269. oscura/inference/active_learning/teachers/simulator.py +192 -0
  270. oscura/inference/adaptive_tuning.py +453 -0
  271. oscura/inference/alignment.py +653 -0
  272. oscura/inference/bayesian.py +943 -0
  273. oscura/inference/binary.py +1016 -0
  274. oscura/inference/crc_reverse.py +711 -0
  275. oscura/inference/logic.py +288 -0
  276. oscura/inference/message_format.py +1305 -0
  277. oscura/inference/protocol.py +417 -0
  278. oscura/inference/protocol_dsl.py +1084 -0
  279. oscura/inference/protocol_library.py +1230 -0
  280. oscura/inference/sequences.py +809 -0
  281. oscura/inference/signal_intelligence.py +1509 -0
  282. oscura/inference/spectral.py +215 -0
  283. oscura/inference/state_machine.py +634 -0
  284. oscura/inference/stream.py +918 -0
  285. oscura/integrations/__init__.py +59 -0
  286. oscura/integrations/llm.py +1827 -0
  287. oscura/jupyter/__init__.py +32 -0
  288. oscura/jupyter/display.py +268 -0
  289. oscura/jupyter/magic.py +334 -0
  290. oscura/loaders/__init__.py +526 -0
  291. oscura/loaders/binary.py +69 -0
  292. oscura/loaders/configurable.py +1255 -0
  293. oscura/loaders/csv.py +26 -0
  294. oscura/loaders/csv_loader.py +473 -0
  295. oscura/loaders/hdf5.py +9 -0
  296. oscura/loaders/hdf5_loader.py +510 -0
  297. oscura/loaders/lazy.py +370 -0
  298. oscura/loaders/mmap_loader.py +583 -0
  299. oscura/loaders/numpy_loader.py +436 -0
  300. oscura/loaders/pcap.py +432 -0
  301. oscura/loaders/preprocessing.py +368 -0
  302. oscura/loaders/rigol.py +287 -0
  303. oscura/loaders/sigrok.py +321 -0
  304. oscura/loaders/tdms.py +367 -0
  305. oscura/loaders/tektronix.py +711 -0
  306. oscura/loaders/validation.py +584 -0
  307. oscura/loaders/vcd.py +464 -0
  308. oscura/loaders/wav.py +233 -0
  309. oscura/math/__init__.py +45 -0
  310. oscura/math/arithmetic.py +824 -0
  311. oscura/math/interpolation.py +413 -0
  312. oscura/onboarding/__init__.py +39 -0
  313. oscura/onboarding/help.py +498 -0
  314. oscura/onboarding/tutorials.py +405 -0
  315. oscura/onboarding/wizard.py +466 -0
  316. oscura/optimization/__init__.py +19 -0
  317. oscura/optimization/parallel.py +440 -0
  318. oscura/optimization/search.py +532 -0
  319. oscura/pipeline/__init__.py +43 -0
  320. oscura/pipeline/base.py +338 -0
  321. oscura/pipeline/composition.py +242 -0
  322. oscura/pipeline/parallel.py +448 -0
  323. oscura/pipeline/pipeline.py +375 -0
  324. oscura/pipeline/reverse_engineering.py +1119 -0
  325. oscura/plugins/__init__.py +122 -0
  326. oscura/plugins/base.py +272 -0
  327. oscura/plugins/cli.py +497 -0
  328. oscura/plugins/discovery.py +411 -0
  329. oscura/plugins/isolation.py +418 -0
  330. oscura/plugins/lifecycle.py +959 -0
  331. oscura/plugins/manager.py +493 -0
  332. oscura/plugins/registry.py +421 -0
  333. oscura/plugins/versioning.py +372 -0
  334. oscura/py.typed +0 -0
  335. oscura/quality/__init__.py +65 -0
  336. oscura/quality/ensemble.py +740 -0
  337. oscura/quality/explainer.py +338 -0
  338. oscura/quality/scoring.py +616 -0
  339. oscura/quality/warnings.py +456 -0
  340. oscura/reporting/__init__.py +248 -0
  341. oscura/reporting/advanced.py +1234 -0
  342. oscura/reporting/analyze.py +448 -0
  343. oscura/reporting/argument_preparer.py +596 -0
  344. oscura/reporting/auto_report.py +507 -0
  345. oscura/reporting/batch.py +615 -0
  346. oscura/reporting/chart_selection.py +223 -0
  347. oscura/reporting/comparison.py +330 -0
  348. oscura/reporting/config.py +615 -0
  349. oscura/reporting/content/__init__.py +39 -0
  350. oscura/reporting/content/executive.py +127 -0
  351. oscura/reporting/content/filtering.py +191 -0
  352. oscura/reporting/content/minimal.py +257 -0
  353. oscura/reporting/content/verbosity.py +162 -0
  354. oscura/reporting/core.py +508 -0
  355. oscura/reporting/core_formats/__init__.py +17 -0
  356. oscura/reporting/core_formats/multi_format.py +210 -0
  357. oscura/reporting/engine.py +836 -0
  358. oscura/reporting/export.py +366 -0
  359. oscura/reporting/formatting/__init__.py +129 -0
  360. oscura/reporting/formatting/emphasis.py +81 -0
  361. oscura/reporting/formatting/numbers.py +403 -0
  362. oscura/reporting/formatting/standards.py +55 -0
  363. oscura/reporting/formatting.py +466 -0
  364. oscura/reporting/html.py +578 -0
  365. oscura/reporting/index.py +590 -0
  366. oscura/reporting/multichannel.py +296 -0
  367. oscura/reporting/output.py +379 -0
  368. oscura/reporting/pdf.py +373 -0
  369. oscura/reporting/plots.py +731 -0
  370. oscura/reporting/pptx_export.py +360 -0
  371. oscura/reporting/renderers/__init__.py +11 -0
  372. oscura/reporting/renderers/pdf.py +94 -0
  373. oscura/reporting/sections.py +471 -0
  374. oscura/reporting/standards.py +680 -0
  375. oscura/reporting/summary_generator.py +368 -0
  376. oscura/reporting/tables.py +397 -0
  377. oscura/reporting/template_system.py +724 -0
  378. oscura/reporting/templates/__init__.py +15 -0
  379. oscura/reporting/templates/definition.py +205 -0
  380. oscura/reporting/templates/index.html +649 -0
  381. oscura/reporting/templates/index.md +173 -0
  382. oscura/schemas/__init__.py +158 -0
  383. oscura/schemas/bus_configuration.json +322 -0
  384. oscura/schemas/device_mapping.json +182 -0
  385. oscura/schemas/packet_format.json +418 -0
  386. oscura/schemas/protocol_definition.json +363 -0
  387. oscura/search/__init__.py +16 -0
  388. oscura/search/anomaly.py +292 -0
  389. oscura/search/context.py +149 -0
  390. oscura/search/pattern.py +160 -0
  391. oscura/session/__init__.py +34 -0
  392. oscura/session/annotations.py +289 -0
  393. oscura/session/history.py +313 -0
  394. oscura/session/session.py +445 -0
  395. oscura/streaming/__init__.py +43 -0
  396. oscura/streaming/chunked.py +611 -0
  397. oscura/streaming/progressive.py +393 -0
  398. oscura/streaming/realtime.py +622 -0
  399. oscura/testing/__init__.py +54 -0
  400. oscura/testing/synthetic.py +808 -0
  401. oscura/triggering/__init__.py +68 -0
  402. oscura/triggering/base.py +229 -0
  403. oscura/triggering/edge.py +353 -0
  404. oscura/triggering/pattern.py +344 -0
  405. oscura/triggering/pulse.py +581 -0
  406. oscura/triggering/window.py +453 -0
  407. oscura/ui/__init__.py +48 -0
  408. oscura/ui/formatters.py +526 -0
  409. oscura/ui/progressive_display.py +340 -0
  410. oscura/utils/__init__.py +99 -0
  411. oscura/utils/autodetect.py +338 -0
  412. oscura/utils/buffer.py +389 -0
  413. oscura/utils/lazy.py +407 -0
  414. oscura/utils/lazy_imports.py +147 -0
  415. oscura/utils/memory.py +836 -0
  416. oscura/utils/memory_advanced.py +1326 -0
  417. oscura/utils/memory_extensions.py +465 -0
  418. oscura/utils/progressive.py +352 -0
  419. oscura/utils/windowing.py +362 -0
  420. oscura/visualization/__init__.py +321 -0
  421. oscura/visualization/accessibility.py +526 -0
  422. oscura/visualization/annotations.py +374 -0
  423. oscura/visualization/axis_scaling.py +305 -0
  424. oscura/visualization/colors.py +453 -0
  425. oscura/visualization/digital.py +337 -0
  426. oscura/visualization/eye.py +420 -0
  427. oscura/visualization/histogram.py +281 -0
  428. oscura/visualization/interactive.py +858 -0
  429. oscura/visualization/jitter.py +702 -0
  430. oscura/visualization/keyboard.py +394 -0
  431. oscura/visualization/layout.py +365 -0
  432. oscura/visualization/optimization.py +1028 -0
  433. oscura/visualization/palettes.py +446 -0
  434. oscura/visualization/plot.py +92 -0
  435. oscura/visualization/power.py +290 -0
  436. oscura/visualization/power_extended.py +626 -0
  437. oscura/visualization/presets.py +467 -0
  438. oscura/visualization/protocols.py +932 -0
  439. oscura/visualization/render.py +207 -0
  440. oscura/visualization/rendering.py +444 -0
  441. oscura/visualization/reverse_engineering.py +791 -0
  442. oscura/visualization/signal_integrity.py +808 -0
  443. oscura/visualization/specialized.py +553 -0
  444. oscura/visualization/spectral.py +811 -0
  445. oscura/visualization/styles.py +381 -0
  446. oscura/visualization/thumbnails.py +311 -0
  447. oscura/visualization/time_axis.py +351 -0
  448. oscura/visualization/waveform.py +367 -0
  449. oscura/workflow/__init__.py +13 -0
  450. oscura/workflow/dag.py +377 -0
  451. oscura/workflows/__init__.py +58 -0
  452. oscura/workflows/compliance.py +280 -0
  453. oscura/workflows/digital.py +272 -0
  454. oscura/workflows/multi_trace.py +502 -0
  455. oscura/workflows/power.py +178 -0
  456. oscura/workflows/protocol.py +492 -0
  457. oscura/workflows/reverse_engineering.py +639 -0
  458. oscura/workflows/signal_integrity.py +227 -0
  459. oscura-0.1.0.dist-info/METADATA +300 -0
  460. oscura-0.1.0.dist-info/RECORD +463 -0
  461. oscura-0.1.0.dist-info/entry_points.txt +2 -0
  462. {oscura-0.0.1.dist-info → oscura-0.1.0.dist-info}/licenses/LICENSE +1 -1
  463. oscura-0.0.1.dist-info/METADATA +0 -63
  464. oscura-0.0.1.dist-info/RECORD +0 -5
  465. {oscura-0.0.1.dist-info → oscura-0.1.0.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"]