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,150 @@
1
+ """Protocol decoder package.
2
+
3
+ Provides protocol decoders for common serial and automotive protocols including
4
+ UART, SPI, I2C, CAN, LIN, FlexRay, JTAG, SWD, I2S, USB, HDLC, Manchester, CAN-FD,
5
+ and 1-Wire.
6
+ """
7
+
8
+ from oscura.analyzers.protocols.base import (
9
+ Annotation,
10
+ AnnotationLevel,
11
+ AsyncDecoder,
12
+ ChannelDef,
13
+ DecoderState,
14
+ OptionDef,
15
+ ProtocolDecoder,
16
+ SyncDecoder,
17
+ )
18
+ from oscura.analyzers.protocols.can import (
19
+ CAN_BITRATES,
20
+ CANDecoder,
21
+ CANFrame,
22
+ CANFrameType,
23
+ decode_can,
24
+ )
25
+ from oscura.analyzers.protocols.can_fd import (
26
+ CANFD_DLC_TO_LENGTH,
27
+ CANFDDecoder,
28
+ CANFDFrame,
29
+ CANFDFrameType,
30
+ decode_can_fd,
31
+ )
32
+ from oscura.analyzers.protocols.flexray import (
33
+ FlexRayDecoder,
34
+ FlexRayFrame,
35
+ FlexRaySegment,
36
+ decode_flexray,
37
+ )
38
+ from oscura.analyzers.protocols.hdlc import HDLCDecoder, decode_hdlc
39
+ from oscura.analyzers.protocols.i2c import I2CDecoder, decode_i2c
40
+ from oscura.analyzers.protocols.i2s import I2SDecoder, I2SMode, decode_i2s
41
+ from oscura.analyzers.protocols.jtag import (
42
+ JTAG_INSTRUCTIONS,
43
+ JTAGDecoder,
44
+ TAPState,
45
+ decode_jtag,
46
+ )
47
+ from oscura.analyzers.protocols.lin import LINDecoder, LINVersion, decode_lin
48
+ from oscura.analyzers.protocols.manchester import (
49
+ ManchesterDecoder,
50
+ ManchesterMode,
51
+ decode_manchester,
52
+ )
53
+ from oscura.analyzers.protocols.onewire import (
54
+ FAMILY_CODES,
55
+ ROM_COMMAND_NAMES,
56
+ OneWireDecoder,
57
+ OneWireMode,
58
+ OneWireROMCommand,
59
+ OneWireROMID,
60
+ OneWireTimings,
61
+ decode_onewire,
62
+ )
63
+ from oscura.analyzers.protocols.spi import SPIDecoder, decode_spi
64
+ from oscura.analyzers.protocols.swd import SWDDecoder, SWDResponse, decode_swd
65
+ from oscura.analyzers.protocols.uart import UARTDecoder, decode_uart
66
+ from oscura.analyzers.protocols.usb import (
67
+ PID_NAMES,
68
+ USBPID,
69
+ USBDecoder,
70
+ USBSpeed,
71
+ decode_usb,
72
+ )
73
+
74
+ __all__ = [
75
+ "CANFD_DLC_TO_LENGTH",
76
+ "CAN_BITRATES",
77
+ # 1-Wire (PRO-007)
78
+ "FAMILY_CODES",
79
+ "JTAG_INSTRUCTIONS",
80
+ "PID_NAMES",
81
+ "ROM_COMMAND_NAMES",
82
+ "USBPID",
83
+ "Annotation",
84
+ "AnnotationLevel",
85
+ "AsyncDecoder",
86
+ # CAN (PRO-005)
87
+ "CANDecoder",
88
+ # CAN-FD (PRO-015)
89
+ "CANFDDecoder",
90
+ "CANFDFrame",
91
+ "CANFDFrameType",
92
+ "CANFrame",
93
+ "CANFrameType",
94
+ "ChannelDef",
95
+ "DecoderState",
96
+ # FlexRay (PRO-016)
97
+ "FlexRayDecoder",
98
+ "FlexRayFrame",
99
+ "FlexRaySegment",
100
+ # HDLC (PRO-013)
101
+ "HDLCDecoder",
102
+ # I2C (PRO-004)
103
+ "I2CDecoder",
104
+ # I2S (PRO-011)
105
+ "I2SDecoder",
106
+ "I2SMode",
107
+ # JTAG (PRO-009)
108
+ "JTAGDecoder",
109
+ # LIN (PRO-008)
110
+ "LINDecoder",
111
+ "LINVersion",
112
+ # Manchester (PRO-014)
113
+ "ManchesterDecoder",
114
+ "ManchesterMode",
115
+ # 1-Wire
116
+ "OneWireDecoder",
117
+ "OneWireMode",
118
+ "OneWireROMCommand",
119
+ "OneWireROMID",
120
+ "OneWireTimings",
121
+ "OptionDef",
122
+ # Base
123
+ "ProtocolDecoder",
124
+ # SPI (PRO-003)
125
+ "SPIDecoder",
126
+ # SWD (PRO-010)
127
+ "SWDDecoder",
128
+ "SWDResponse",
129
+ "SyncDecoder",
130
+ "TAPState",
131
+ # UART (PRO-002)
132
+ "UARTDecoder",
133
+ # USB (PRO-012)
134
+ "USBDecoder",
135
+ "USBSpeed",
136
+ "decode_can",
137
+ "decode_can_fd",
138
+ "decode_flexray",
139
+ "decode_hdlc",
140
+ "decode_i2c",
141
+ "decode_i2s",
142
+ "decode_jtag",
143
+ "decode_lin",
144
+ "decode_manchester",
145
+ "decode_onewire",
146
+ "decode_spi",
147
+ "decode_swd",
148
+ "decode_uart",
149
+ "decode_usb",
150
+ ]
@@ -0,0 +1,500 @@
1
+ """Protocol decoder base class (sigrok-inspired).
2
+
3
+ This module provides the base class for protocol decoders,
4
+ following a sigrok-inspired API for consistency with the
5
+ open-source protocol decoding ecosystem.
6
+
7
+
8
+ Example:
9
+ >>> from oscura.analyzers.protocols.base import ProtocolDecoder
10
+ >>> class UARTDecoder(ProtocolDecoder):
11
+ ... id = "uart"
12
+ ... name = "UART"
13
+ ... channels = [{"id": "rx", "name": "RX", "desc": "Receive data"}]
14
+ ... def decode(self, trace):
15
+ ... # Implementation
16
+ ... pass
17
+
18
+ References:
19
+ sigrok Protocol Decoder API: https://sigrok.org/wiki/Protocol_decoder_API
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ from abc import ABC, abstractmethod
25
+ from dataclasses import dataclass, field
26
+ from enum import IntEnum
27
+ from typing import TYPE_CHECKING, Any
28
+
29
+ import numpy as np
30
+
31
+ from oscura.core.types import DigitalTrace, ProtocolPacket
32
+
33
+ if TYPE_CHECKING:
34
+ from collections.abc import Iterator
35
+
36
+ from numpy.typing import NDArray
37
+
38
+
39
+ class AnnotationLevel(IntEnum):
40
+ """Annotation hierarchy levels.
41
+
42
+ Protocol decoders use multiple annotation levels for different
43
+ levels of detail, from raw bits to high-level interpretations.
44
+ """
45
+
46
+ BITS = 0 # Raw bit values
47
+ BYTES = 1 # Byte values
48
+ WORDS = 2 # Words/frames
49
+ FIELDS = 3 # Named fields
50
+ PACKETS = 4 # Complete packets
51
+ MESSAGES = 5 # High-level messages
52
+
53
+
54
+ @dataclass
55
+ class Annotation:
56
+ """Protocol annotation at a specific time range.
57
+
58
+ Attributes:
59
+ start_time: Start time in seconds.
60
+ end_time: End time in seconds.
61
+ level: Annotation level (bits, bytes, packets, etc.).
62
+ text: Human-readable annotation text.
63
+ data: Raw data associated with annotation.
64
+ metadata: Additional annotation metadata.
65
+ """
66
+
67
+ start_time: float
68
+ end_time: float
69
+ level: AnnotationLevel
70
+ text: str
71
+ data: bytes | None = None
72
+ metadata: dict[str, Any] = field(default_factory=dict)
73
+
74
+
75
+ @dataclass
76
+ class ChannelDef:
77
+ """Channel definition for protocol decoder.
78
+
79
+ Attributes:
80
+ id: Channel identifier (e.g., "tx", "rx", "clk").
81
+ name: Human-readable name.
82
+ desc: Description of channel purpose.
83
+ required: Whether channel is required.
84
+ """
85
+
86
+ id: str
87
+ name: str
88
+ desc: str = ""
89
+ required: bool = True
90
+
91
+
92
+ @dataclass
93
+ class OptionDef:
94
+ """Option definition for protocol decoder.
95
+
96
+ Attributes:
97
+ id: Option identifier.
98
+ name: Human-readable name.
99
+ desc: Description.
100
+ default: Default value.
101
+ values: List of valid values (if enumerated).
102
+ """
103
+
104
+ id: str
105
+ name: str
106
+ desc: str = ""
107
+ default: Any = None
108
+ values: list[Any] | None = None
109
+
110
+
111
+ class DecoderState:
112
+ """Base class for decoder state machines.
113
+
114
+ Protocol decoders can subclass this to track their internal state
115
+ during frame/packet decoding.
116
+ """
117
+
118
+ def __init__(self) -> None:
119
+ """Initialize decoder state."""
120
+ self.reset()
121
+
122
+ def reset(self) -> None:
123
+ """Reset state to initial values."""
124
+
125
+
126
+ class ProtocolDecoder(ABC):
127
+ """Base class for protocol decoders.
128
+
129
+ Provides sigrok-inspired API for implementing protocol decoders
130
+ that convert digital traces to decoded protocol packets.
131
+
132
+ Class Attributes:
133
+ api_version: Protocol decoder API version.
134
+ id: Unique decoder identifier.
135
+ name: Human-readable decoder name.
136
+ longname: Full name with description.
137
+ desc: Short description.
138
+ license: License identifier.
139
+ inputs: Required input types (e.g., ["logic"]).
140
+ outputs: Output types produced.
141
+ channels: Required channel definitions.
142
+ optional_channels: Optional channel definitions.
143
+ options: Configurable options.
144
+ annotations: Annotation type definitions.
145
+
146
+ Example:
147
+ >>> class SPIDecoder(ProtocolDecoder):
148
+ ... id = "spi"
149
+ ... name = "SPI"
150
+ ... channels = [
151
+ ... ChannelDef("clk", "CLK", "Clock"),
152
+ ... ChannelDef("mosi", "MOSI", "Master Out Slave In"),
153
+ ... ChannelDef("miso", "MISO", "Master In Slave Out"),
154
+ ... ]
155
+ ... optional_channels = [
156
+ ... ChannelDef("cs", "CS#", "Chip Select", required=False),
157
+ ... ]
158
+ ... options = [
159
+ ... OptionDef("cpol", "Clock Polarity", default=0, values=[0, 1]),
160
+ ... OptionDef("cpha", "Clock Phase", default=0, values=[0, 1]),
161
+ ... ]
162
+ """
163
+
164
+ # API version
165
+ api_version: int = 3
166
+
167
+ # Decoder identification
168
+ id: str = "unknown"
169
+ name: str = "Unknown"
170
+ longname: str = ""
171
+ desc: str = ""
172
+ license: str = "MIT"
173
+
174
+ # Input/output types
175
+ inputs: list[str] = ["logic"] # noqa: RUF012
176
+ outputs: list[str] = ["packets"] # noqa: RUF012
177
+
178
+ # Channel definitions
179
+ channels: list[ChannelDef] = [] # noqa: RUF012
180
+ optional_channels: list[ChannelDef] = [] # noqa: RUF012
181
+
182
+ # Options
183
+ options: list[OptionDef] = [] # noqa: RUF012
184
+
185
+ # Annotation definitions (override in subclass)
186
+ annotations: list[tuple[str, str]] = [] # noqa: RUF012
187
+
188
+ def __init__(self, **options: Any) -> None:
189
+ """Initialize decoder with options.
190
+
191
+ Args:
192
+ **options: Decoder-specific options.
193
+
194
+ Raises:
195
+ ValueError: If unknown option is provided
196
+ """
197
+ self._options: dict[str, Any] = {}
198
+ self._annotations: list[Annotation] = []
199
+ self._packets: list[ProtocolPacket] = []
200
+ self._state = DecoderState()
201
+
202
+ # Set default options
203
+ for opt in self.options:
204
+ self._options[opt.id] = opt.default
205
+
206
+ # Override with provided options
207
+ for key, value in options.items():
208
+ if any(opt.id == key for opt in self.options):
209
+ self._options[key] = value
210
+ else:
211
+ raise ValueError(f"Unknown option: {key}")
212
+
213
+ def get_option(self, name: str) -> Any:
214
+ """Get option value.
215
+
216
+ Args:
217
+ name: Option name.
218
+
219
+ Returns:
220
+ Option value.
221
+ """
222
+ return self._options.get(name)
223
+
224
+ def set_option(self, name: str, value: Any) -> None:
225
+ """Set option value.
226
+
227
+ Args:
228
+ name: Option name.
229
+ value: New value.
230
+ """
231
+ self._options[name] = value
232
+
233
+ def reset(self) -> None:
234
+ """Reset decoder state.
235
+
236
+ Clears all accumulated annotations and packets, and resets
237
+ the internal state machine to initial state.
238
+ """
239
+ self._annotations.clear()
240
+ self._packets.clear()
241
+ self._state.reset()
242
+
243
+ def put_annotation(
244
+ self,
245
+ start_time: float,
246
+ end_time: float,
247
+ level: AnnotationLevel,
248
+ text: str,
249
+ data: bytes | None = None,
250
+ **metadata: Any,
251
+ ) -> None:
252
+ """Add an annotation.
253
+
254
+ Args:
255
+ start_time: Start time in seconds.
256
+ end_time: End time in seconds.
257
+ level: Annotation level.
258
+ text: Annotation text.
259
+ data: Associated binary data.
260
+ **metadata: Additional metadata.
261
+ """
262
+ self._annotations.append(
263
+ Annotation(
264
+ start_time=start_time,
265
+ end_time=end_time,
266
+ level=level,
267
+ text=text,
268
+ data=data,
269
+ metadata=metadata,
270
+ )
271
+ )
272
+
273
+ def put_packet(
274
+ self,
275
+ timestamp: float,
276
+ data: bytes,
277
+ annotations: dict[str, Any] | None = None,
278
+ errors: list[str] | None = None,
279
+ ) -> None:
280
+ """Add a decoded packet.
281
+
282
+ Args:
283
+ timestamp: Packet start time.
284
+ data: Decoded data bytes.
285
+ annotations: Packet annotations.
286
+ errors: Detected errors.
287
+ """
288
+ self._packets.append(
289
+ ProtocolPacket(
290
+ timestamp=timestamp,
291
+ protocol=self.id,
292
+ data=data,
293
+ annotations=annotations or {},
294
+ errors=errors or [],
295
+ )
296
+ )
297
+
298
+ @abstractmethod
299
+ def decode(
300
+ self,
301
+ trace: DigitalTrace,
302
+ **channels: NDArray[np.bool_],
303
+ ) -> Iterator[ProtocolPacket]:
304
+ """Decode a digital trace.
305
+
306
+ This is the main entry point for decoding. Implementations should
307
+ yield ProtocolPacket objects as they are decoded.
308
+
309
+ Args:
310
+ trace: Primary input trace.
311
+ **channels: Additional channel data by name.
312
+
313
+ Yields:
314
+ Decoded protocol packets.
315
+
316
+ Example:
317
+ >>> decoder = UARTDecoder(baudrate=115200)
318
+ >>> for packet in decoder.decode(trace):
319
+ ... print(f"Data: {packet.data.hex()}")
320
+ """
321
+
322
+ def get_annotations(
323
+ self,
324
+ *,
325
+ level: AnnotationLevel | None = None,
326
+ start_time: float | None = None,
327
+ end_time: float | None = None,
328
+ ) -> list[Annotation]:
329
+ """Get accumulated annotations.
330
+
331
+ Args:
332
+ level: Filter by annotation level.
333
+ start_time: Filter by start time (inclusive).
334
+ end_time: Filter by end time (inclusive).
335
+
336
+ Returns:
337
+ List of matching annotations.
338
+ """
339
+ result = self._annotations
340
+
341
+ if level is not None:
342
+ result = [a for a in result if a.level == level]
343
+
344
+ if start_time is not None:
345
+ result = [a for a in result if a.end_time >= start_time]
346
+
347
+ if end_time is not None:
348
+ result = [a for a in result if a.start_time <= end_time]
349
+
350
+ return result
351
+
352
+ def get_packets(self) -> list[ProtocolPacket]:
353
+ """Get all decoded packets.
354
+
355
+ Returns:
356
+ List of decoded packets.
357
+ """
358
+ return list(self._packets)
359
+
360
+ @classmethod
361
+ def get_channel_ids(cls, include_optional: bool = False) -> list[str]:
362
+ """Get list of channel IDs.
363
+
364
+ Args:
365
+ include_optional: Include optional channels.
366
+
367
+ Returns:
368
+ List of channel ID strings.
369
+ """
370
+ ids = [ch.id for ch in cls.channels]
371
+ if include_optional:
372
+ ids.extend(ch.id for ch in cls.optional_channels)
373
+ return ids
374
+
375
+ @classmethod
376
+ def get_option_ids(cls) -> list[str]:
377
+ """Get list of option IDs.
378
+
379
+ Returns:
380
+ List of option ID strings.
381
+ """
382
+ return [opt.id for opt in cls.options]
383
+
384
+
385
+ class SyncDecoder(ProtocolDecoder):
386
+ """Base class for synchronous protocol decoders.
387
+
388
+ Synchronous protocols use a clock signal for timing. This base class
389
+ provides helpers for clock edge detection and data sampling.
390
+ """
391
+
392
+ def sample_on_edge(
393
+ self,
394
+ clock: NDArray[np.bool_],
395
+ data: NDArray[np.bool_],
396
+ edge: str = "rising",
397
+ ) -> NDArray[np.bool_]:
398
+ """Sample data on clock edges.
399
+
400
+ Args:
401
+ clock: Clock signal.
402
+ data: Data signal.
403
+ edge: "rising" or "falling".
404
+
405
+ Returns:
406
+ Data values at clock edges.
407
+ """
408
+ if edge == "rising":
409
+ edges = np.where(~clock[:-1] & clock[1:])[0]
410
+ else:
411
+ edges = np.where(clock[:-1] & ~clock[1:])[0]
412
+
413
+ # Sample data after edge (shifted by 1)
414
+ sample_indices = edges + 1
415
+ sample_indices = sample_indices[sample_indices < len(data)]
416
+
417
+ result: NDArray[np.bool_] = data[sample_indices]
418
+ return result
419
+
420
+
421
+ class AsyncDecoder(ProtocolDecoder):
422
+ """Base class for asynchronous protocol decoders.
423
+
424
+ Asynchronous protocols (like UART) use timing-based sampling without
425
+ a separate clock signal. This base class provides helpers for
426
+ bit-timing and symbol detection.
427
+ """
428
+
429
+ def __init__(self, baudrate: int = 9600, **options: Any) -> None:
430
+ """Initialize async decoder.
431
+
432
+ Args:
433
+ baudrate: Bit rate in bps.
434
+ **options: Additional options.
435
+ """
436
+ super().__init__(**options)
437
+ self._baudrate = baudrate
438
+
439
+ @property
440
+ def baudrate(self) -> int:
441
+ """Get baud rate."""
442
+ return self._baudrate
443
+
444
+ @baudrate.setter
445
+ def baudrate(self, value: int) -> None:
446
+ """Set baud rate."""
447
+ self._baudrate = value
448
+
449
+ def bit_time(self, sample_rate: float) -> float:
450
+ """Get bit time in samples.
451
+
452
+ Args:
453
+ sample_rate: Sample rate in Hz.
454
+
455
+ Returns:
456
+ Number of samples per bit.
457
+ """
458
+ return sample_rate / self._baudrate
459
+
460
+ def find_start_bit(
461
+ self,
462
+ data: NDArray[np.bool_],
463
+ start_idx: int = 0,
464
+ idle_high: bool = True,
465
+ ) -> int | None:
466
+ """Find start bit transition.
467
+
468
+ Args:
469
+ data: Digital signal.
470
+ start_idx: Start search index.
471
+ idle_high: True if idle is high (standard UART).
472
+
473
+ Returns:
474
+ Index of start bit, or None if not found.
475
+ """
476
+ search_region = data[start_idx:]
477
+
478
+ if idle_high:
479
+ # Look for falling edge (high to low)
480
+ transitions = np.where(search_region[:-1] & ~search_region[1:])[0]
481
+ else:
482
+ # Look for rising edge (low to high)
483
+ transitions = np.where(~search_region[:-1] & search_region[1:])[0]
484
+
485
+ if len(transitions) == 0:
486
+ return None
487
+
488
+ return int(start_idx + transitions[0])
489
+
490
+
491
+ __all__ = [
492
+ "Annotation",
493
+ "AnnotationLevel",
494
+ "AsyncDecoder",
495
+ "ChannelDef",
496
+ "DecoderState",
497
+ "OptionDef",
498
+ "ProtocolDecoder",
499
+ "SyncDecoder",
500
+ ]