oscura 0.5.0__py3-none-any.whl → 0.6.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 (513) hide show
  1. oscura/__init__.py +169 -167
  2. oscura/analyzers/__init__.py +3 -0
  3. oscura/analyzers/classification.py +659 -0
  4. oscura/analyzers/digital/__init__.py +0 -48
  5. oscura/analyzers/digital/edges.py +325 -65
  6. oscura/analyzers/digital/extraction.py +0 -195
  7. oscura/analyzers/digital/quality.py +293 -166
  8. oscura/analyzers/digital/timing.py +260 -115
  9. oscura/analyzers/digital/timing_numba.py +334 -0
  10. oscura/analyzers/entropy.py +605 -0
  11. oscura/analyzers/eye/diagram.py +176 -109
  12. oscura/analyzers/eye/metrics.py +5 -5
  13. oscura/analyzers/jitter/__init__.py +6 -4
  14. oscura/analyzers/jitter/ber.py +52 -52
  15. oscura/analyzers/jitter/classification.py +156 -0
  16. oscura/analyzers/jitter/decomposition.py +163 -113
  17. oscura/analyzers/jitter/spectrum.py +80 -64
  18. oscura/analyzers/ml/__init__.py +39 -0
  19. oscura/analyzers/ml/features.py +600 -0
  20. oscura/analyzers/ml/signal_classifier.py +604 -0
  21. oscura/analyzers/packet/daq.py +246 -158
  22. oscura/analyzers/packet/parser.py +12 -1
  23. oscura/analyzers/packet/payload.py +50 -2110
  24. oscura/analyzers/packet/payload_analysis.py +361 -181
  25. oscura/analyzers/packet/payload_patterns.py +133 -70
  26. oscura/analyzers/packet/stream.py +84 -23
  27. oscura/analyzers/patterns/__init__.py +26 -5
  28. oscura/analyzers/patterns/anomaly_detection.py +908 -0
  29. oscura/analyzers/patterns/clustering.py +169 -108
  30. oscura/analyzers/patterns/clustering_optimized.py +227 -0
  31. oscura/analyzers/patterns/discovery.py +1 -1
  32. oscura/analyzers/patterns/matching.py +581 -197
  33. oscura/analyzers/patterns/pattern_mining.py +778 -0
  34. oscura/analyzers/patterns/periodic.py +121 -38
  35. oscura/analyzers/patterns/sequences.py +175 -78
  36. oscura/analyzers/power/conduction.py +1 -1
  37. oscura/analyzers/power/soa.py +6 -6
  38. oscura/analyzers/power/switching.py +250 -110
  39. oscura/analyzers/protocol/__init__.py +17 -1
  40. oscura/analyzers/protocols/__init__.py +1 -22
  41. oscura/analyzers/protocols/base.py +6 -6
  42. oscura/analyzers/protocols/ble/__init__.py +38 -0
  43. oscura/analyzers/protocols/ble/analyzer.py +809 -0
  44. oscura/analyzers/protocols/ble/uuids.py +288 -0
  45. oscura/analyzers/protocols/can.py +257 -127
  46. oscura/analyzers/protocols/can_fd.py +107 -80
  47. oscura/analyzers/protocols/flexray.py +139 -80
  48. oscura/analyzers/protocols/hdlc.py +93 -58
  49. oscura/analyzers/protocols/i2c.py +247 -106
  50. oscura/analyzers/protocols/i2s.py +138 -86
  51. oscura/analyzers/protocols/industrial/__init__.py +40 -0
  52. oscura/analyzers/protocols/industrial/bacnet/__init__.py +33 -0
  53. oscura/analyzers/protocols/industrial/bacnet/analyzer.py +708 -0
  54. oscura/analyzers/protocols/industrial/bacnet/encoding.py +412 -0
  55. oscura/analyzers/protocols/industrial/bacnet/services.py +622 -0
  56. oscura/analyzers/protocols/industrial/ethercat/__init__.py +30 -0
  57. oscura/analyzers/protocols/industrial/ethercat/analyzer.py +474 -0
  58. oscura/analyzers/protocols/industrial/ethercat/mailbox.py +339 -0
  59. oscura/analyzers/protocols/industrial/ethercat/topology.py +166 -0
  60. oscura/analyzers/protocols/industrial/modbus/__init__.py +31 -0
  61. oscura/analyzers/protocols/industrial/modbus/analyzer.py +525 -0
  62. oscura/analyzers/protocols/industrial/modbus/crc.py +79 -0
  63. oscura/analyzers/protocols/industrial/modbus/functions.py +436 -0
  64. oscura/analyzers/protocols/industrial/opcua/__init__.py +21 -0
  65. oscura/analyzers/protocols/industrial/opcua/analyzer.py +552 -0
  66. oscura/analyzers/protocols/industrial/opcua/datatypes.py +446 -0
  67. oscura/analyzers/protocols/industrial/opcua/services.py +264 -0
  68. oscura/analyzers/protocols/industrial/profinet/__init__.py +23 -0
  69. oscura/analyzers/protocols/industrial/profinet/analyzer.py +441 -0
  70. oscura/analyzers/protocols/industrial/profinet/dcp.py +263 -0
  71. oscura/analyzers/protocols/industrial/profinet/ptcp.py +200 -0
  72. oscura/analyzers/protocols/jtag.py +180 -98
  73. oscura/analyzers/protocols/lin.py +219 -114
  74. oscura/analyzers/protocols/manchester.py +4 -4
  75. oscura/analyzers/protocols/onewire.py +253 -149
  76. oscura/analyzers/protocols/parallel_bus/__init__.py +20 -0
  77. oscura/analyzers/protocols/parallel_bus/centronics.py +92 -0
  78. oscura/analyzers/protocols/parallel_bus/gpib.py +137 -0
  79. oscura/analyzers/protocols/spi.py +192 -95
  80. oscura/analyzers/protocols/swd.py +321 -167
  81. oscura/analyzers/protocols/uart.py +267 -125
  82. oscura/analyzers/protocols/usb.py +235 -131
  83. oscura/analyzers/side_channel/power.py +17 -12
  84. oscura/analyzers/signal/__init__.py +15 -0
  85. oscura/analyzers/signal/timing_analysis.py +1086 -0
  86. oscura/analyzers/signal_integrity/__init__.py +4 -1
  87. oscura/analyzers/signal_integrity/sparams.py +2 -19
  88. oscura/analyzers/spectral/chunked.py +129 -60
  89. oscura/analyzers/spectral/chunked_fft.py +300 -94
  90. oscura/analyzers/spectral/chunked_wavelet.py +100 -80
  91. oscura/analyzers/statistical/checksum.py +376 -217
  92. oscura/analyzers/statistical/classification.py +229 -107
  93. oscura/analyzers/statistical/entropy.py +78 -53
  94. oscura/analyzers/statistics/correlation.py +407 -211
  95. oscura/analyzers/statistics/outliers.py +2 -2
  96. oscura/analyzers/statistics/streaming.py +30 -5
  97. oscura/analyzers/validation.py +216 -101
  98. oscura/analyzers/waveform/measurements.py +9 -0
  99. oscura/analyzers/waveform/measurements_with_uncertainty.py +31 -15
  100. oscura/analyzers/waveform/spectral.py +500 -228
  101. oscura/api/__init__.py +31 -5
  102. oscura/api/dsl/__init__.py +582 -0
  103. oscura/{dsl → api/dsl}/commands.py +43 -76
  104. oscura/{dsl → api/dsl}/interpreter.py +26 -51
  105. oscura/{dsl → api/dsl}/parser.py +107 -77
  106. oscura/{dsl → api/dsl}/repl.py +2 -2
  107. oscura/api/dsl.py +1 -1
  108. oscura/{integrations → api/integrations}/__init__.py +1 -1
  109. oscura/{integrations → api/integrations}/llm.py +201 -102
  110. oscura/api/operators.py +3 -3
  111. oscura/api/optimization.py +144 -30
  112. oscura/api/rest_server.py +921 -0
  113. oscura/api/server/__init__.py +17 -0
  114. oscura/api/server/dashboard.py +850 -0
  115. oscura/api/server/static/README.md +34 -0
  116. oscura/api/server/templates/base.html +181 -0
  117. oscura/api/server/templates/export.html +120 -0
  118. oscura/api/server/templates/home.html +284 -0
  119. oscura/api/server/templates/protocols.html +58 -0
  120. oscura/api/server/templates/reports.html +43 -0
  121. oscura/api/server/templates/session_detail.html +89 -0
  122. oscura/api/server/templates/sessions.html +83 -0
  123. oscura/api/server/templates/waveforms.html +73 -0
  124. oscura/automotive/__init__.py +8 -1
  125. oscura/automotive/can/__init__.py +10 -0
  126. oscura/automotive/can/checksum.py +3 -1
  127. oscura/automotive/can/dbc_generator.py +590 -0
  128. oscura/automotive/can/message_wrapper.py +121 -74
  129. oscura/automotive/can/patterns.py +98 -21
  130. oscura/automotive/can/session.py +292 -56
  131. oscura/automotive/can/state_machine.py +6 -3
  132. oscura/automotive/can/stimulus_response.py +97 -75
  133. oscura/automotive/dbc/__init__.py +10 -2
  134. oscura/automotive/dbc/generator.py +84 -56
  135. oscura/automotive/dbc/parser.py +6 -6
  136. oscura/automotive/dtc/data.json +2763 -0
  137. oscura/automotive/dtc/database.py +2 -2
  138. oscura/automotive/flexray/__init__.py +31 -0
  139. oscura/automotive/flexray/analyzer.py +504 -0
  140. oscura/automotive/flexray/crc.py +185 -0
  141. oscura/automotive/flexray/fibex.py +449 -0
  142. oscura/automotive/j1939/__init__.py +45 -8
  143. oscura/automotive/j1939/analyzer.py +605 -0
  144. oscura/automotive/j1939/spns.py +326 -0
  145. oscura/automotive/j1939/transport.py +306 -0
  146. oscura/automotive/lin/__init__.py +47 -0
  147. oscura/automotive/lin/analyzer.py +612 -0
  148. oscura/automotive/loaders/blf.py +13 -2
  149. oscura/automotive/loaders/csv_can.py +143 -72
  150. oscura/automotive/loaders/dispatcher.py +50 -2
  151. oscura/automotive/loaders/mdf.py +86 -45
  152. oscura/automotive/loaders/pcap.py +111 -61
  153. oscura/automotive/uds/__init__.py +4 -0
  154. oscura/automotive/uds/analyzer.py +725 -0
  155. oscura/automotive/uds/decoder.py +140 -58
  156. oscura/automotive/uds/models.py +7 -1
  157. oscura/automotive/visualization.py +1 -1
  158. oscura/cli/analyze.py +348 -0
  159. oscura/cli/batch.py +142 -122
  160. oscura/cli/benchmark.py +275 -0
  161. oscura/cli/characterize.py +137 -82
  162. oscura/cli/compare.py +224 -131
  163. oscura/cli/completion.py +250 -0
  164. oscura/cli/config_cmd.py +361 -0
  165. oscura/cli/decode.py +164 -87
  166. oscura/cli/export.py +286 -0
  167. oscura/cli/main.py +115 -31
  168. oscura/{onboarding → cli/onboarding}/__init__.py +3 -3
  169. oscura/{onboarding → cli/onboarding}/help.py +80 -58
  170. oscura/{onboarding → cli/onboarding}/tutorials.py +97 -72
  171. oscura/{onboarding → cli/onboarding}/wizard.py +55 -36
  172. oscura/cli/progress.py +147 -0
  173. oscura/cli/shell.py +157 -135
  174. oscura/cli/validate_cmd.py +204 -0
  175. oscura/cli/visualize.py +158 -0
  176. oscura/convenience.py +125 -79
  177. oscura/core/__init__.py +4 -2
  178. oscura/core/backend_selector.py +3 -3
  179. oscura/core/cache.py +126 -15
  180. oscura/core/cancellation.py +1 -1
  181. oscura/{config → core/config}/__init__.py +20 -11
  182. oscura/{config → core/config}/defaults.py +1 -1
  183. oscura/{config → core/config}/loader.py +7 -5
  184. oscura/{config → core/config}/memory.py +5 -5
  185. oscura/{config → core/config}/migration.py +1 -1
  186. oscura/{config → core/config}/pipeline.py +99 -23
  187. oscura/{config → core/config}/preferences.py +1 -1
  188. oscura/{config → core/config}/protocol.py +3 -3
  189. oscura/{config → core/config}/schema.py +426 -272
  190. oscura/{config → core/config}/settings.py +1 -1
  191. oscura/{config → core/config}/thresholds.py +195 -153
  192. oscura/core/correlation.py +5 -6
  193. oscura/core/cross_domain.py +0 -2
  194. oscura/core/debug.py +9 -5
  195. oscura/{extensibility → core/extensibility}/docs.py +158 -70
  196. oscura/{extensibility → core/extensibility}/extensions.py +160 -76
  197. oscura/{extensibility → core/extensibility}/logging.py +1 -1
  198. oscura/{extensibility → core/extensibility}/measurements.py +1 -1
  199. oscura/{extensibility → core/extensibility}/plugins.py +1 -1
  200. oscura/{extensibility → core/extensibility}/templates.py +73 -3
  201. oscura/{extensibility → core/extensibility}/validation.py +1 -1
  202. oscura/core/gpu_backend.py +11 -7
  203. oscura/core/log_query.py +101 -11
  204. oscura/core/logging.py +126 -54
  205. oscura/core/logging_advanced.py +5 -5
  206. oscura/core/memory_limits.py +108 -70
  207. oscura/core/memory_monitor.py +2 -2
  208. oscura/core/memory_progress.py +7 -7
  209. oscura/core/memory_warnings.py +1 -1
  210. oscura/core/numba_backend.py +13 -13
  211. oscura/{plugins → core/plugins}/__init__.py +9 -9
  212. oscura/{plugins → core/plugins}/base.py +7 -7
  213. oscura/{plugins → core/plugins}/cli.py +3 -3
  214. oscura/{plugins → core/plugins}/discovery.py +186 -106
  215. oscura/{plugins → core/plugins}/lifecycle.py +1 -1
  216. oscura/{plugins → core/plugins}/manager.py +7 -7
  217. oscura/{plugins → core/plugins}/registry.py +3 -3
  218. oscura/{plugins → core/plugins}/versioning.py +1 -1
  219. oscura/core/progress.py +16 -1
  220. oscura/core/provenance.py +8 -2
  221. oscura/{schemas → core/schemas}/__init__.py +2 -2
  222. oscura/core/schemas/bus_configuration.json +322 -0
  223. oscura/core/schemas/device_mapping.json +182 -0
  224. oscura/core/schemas/packet_format.json +418 -0
  225. oscura/core/schemas/protocol_definition.json +363 -0
  226. oscura/core/types.py +4 -0
  227. oscura/core/uncertainty.py +3 -3
  228. oscura/correlation/__init__.py +52 -0
  229. oscura/correlation/multi_protocol.py +811 -0
  230. oscura/discovery/auto_decoder.py +117 -35
  231. oscura/discovery/comparison.py +191 -86
  232. oscura/discovery/quality_validator.py +155 -68
  233. oscura/discovery/signal_detector.py +196 -79
  234. oscura/export/__init__.py +18 -20
  235. oscura/export/kaitai_struct.py +513 -0
  236. oscura/export/scapy_layer.py +801 -0
  237. oscura/export/wireshark/README.md +15 -15
  238. oscura/export/wireshark/generator.py +1 -1
  239. oscura/export/wireshark/templates/dissector.lua.j2 +2 -2
  240. oscura/export/wireshark_dissector.py +746 -0
  241. oscura/guidance/wizard.py +207 -111
  242. oscura/hardware/__init__.py +19 -0
  243. oscura/{acquisition → hardware/acquisition}/__init__.py +4 -4
  244. oscura/{acquisition → hardware/acquisition}/file.py +2 -2
  245. oscura/{acquisition → hardware/acquisition}/hardware.py +7 -7
  246. oscura/{acquisition → hardware/acquisition}/saleae.py +15 -12
  247. oscura/{acquisition → hardware/acquisition}/socketcan.py +1 -1
  248. oscura/{acquisition → hardware/acquisition}/streaming.py +2 -2
  249. oscura/{acquisition → hardware/acquisition}/synthetic.py +3 -3
  250. oscura/{acquisition → hardware/acquisition}/visa.py +33 -11
  251. oscura/hardware/firmware/__init__.py +29 -0
  252. oscura/hardware/firmware/pattern_recognition.py +874 -0
  253. oscura/hardware/hal_detector.py +736 -0
  254. oscura/hardware/security/__init__.py +37 -0
  255. oscura/hardware/security/side_channel_detector.py +1126 -0
  256. oscura/inference/__init__.py +4 -0
  257. oscura/inference/active_learning/README.md +7 -7
  258. oscura/inference/active_learning/observation_table.py +4 -1
  259. oscura/inference/alignment.py +216 -123
  260. oscura/inference/bayesian.py +113 -33
  261. oscura/inference/crc_reverse.py +101 -55
  262. oscura/inference/logic.py +6 -2
  263. oscura/inference/message_format.py +342 -183
  264. oscura/inference/protocol.py +95 -44
  265. oscura/inference/protocol_dsl.py +180 -82
  266. oscura/inference/signal_intelligence.py +1439 -706
  267. oscura/inference/spectral.py +99 -57
  268. oscura/inference/state_machine.py +810 -158
  269. oscura/inference/stream.py +270 -110
  270. oscura/iot/__init__.py +34 -0
  271. oscura/iot/coap/__init__.py +32 -0
  272. oscura/iot/coap/analyzer.py +668 -0
  273. oscura/iot/coap/options.py +212 -0
  274. oscura/iot/lorawan/__init__.py +21 -0
  275. oscura/iot/lorawan/crypto.py +206 -0
  276. oscura/iot/lorawan/decoder.py +801 -0
  277. oscura/iot/lorawan/mac_commands.py +341 -0
  278. oscura/iot/mqtt/__init__.py +27 -0
  279. oscura/iot/mqtt/analyzer.py +999 -0
  280. oscura/iot/mqtt/properties.py +315 -0
  281. oscura/iot/zigbee/__init__.py +31 -0
  282. oscura/iot/zigbee/analyzer.py +615 -0
  283. oscura/iot/zigbee/security.py +153 -0
  284. oscura/iot/zigbee/zcl.py +349 -0
  285. oscura/jupyter/display.py +125 -45
  286. oscura/{exploratory → jupyter/exploratory}/__init__.py +8 -8
  287. oscura/{exploratory → jupyter/exploratory}/error_recovery.py +298 -141
  288. oscura/jupyter/exploratory/fuzzy.py +746 -0
  289. oscura/{exploratory → jupyter/exploratory}/fuzzy_advanced.py +258 -100
  290. oscura/{exploratory → jupyter/exploratory}/legacy.py +464 -242
  291. oscura/{exploratory → jupyter/exploratory}/parse.py +167 -145
  292. oscura/{exploratory → jupyter/exploratory}/recovery.py +119 -87
  293. oscura/jupyter/exploratory/sync.py +612 -0
  294. oscura/{exploratory → jupyter/exploratory}/unknown.py +299 -176
  295. oscura/jupyter/magic.py +4 -4
  296. oscura/{ui → jupyter/ui}/__init__.py +2 -2
  297. oscura/{ui → jupyter/ui}/formatters.py +3 -3
  298. oscura/{ui → jupyter/ui}/progressive_display.py +153 -82
  299. oscura/loaders/__init__.py +171 -63
  300. oscura/loaders/binary.py +88 -1
  301. oscura/loaders/chipwhisperer.py +153 -137
  302. oscura/loaders/configurable.py +208 -86
  303. oscura/loaders/csv_loader.py +458 -215
  304. oscura/loaders/hdf5_loader.py +278 -119
  305. oscura/loaders/lazy.py +87 -54
  306. oscura/loaders/mmap_loader.py +1 -1
  307. oscura/loaders/numpy_loader.py +253 -116
  308. oscura/loaders/pcap.py +226 -151
  309. oscura/loaders/rigol.py +110 -49
  310. oscura/loaders/sigrok.py +201 -78
  311. oscura/loaders/tdms.py +81 -58
  312. oscura/loaders/tektronix.py +291 -174
  313. oscura/loaders/touchstone.py +182 -87
  314. oscura/loaders/vcd.py +215 -117
  315. oscura/loaders/wav.py +155 -68
  316. oscura/reporting/__init__.py +9 -7
  317. oscura/reporting/analyze.py +352 -146
  318. oscura/reporting/argument_preparer.py +69 -14
  319. oscura/reporting/auto_report.py +97 -61
  320. oscura/reporting/batch.py +131 -58
  321. oscura/reporting/chart_selection.py +57 -45
  322. oscura/reporting/comparison.py +63 -17
  323. oscura/reporting/content/executive.py +76 -24
  324. oscura/reporting/core_formats/multi_format.py +11 -8
  325. oscura/reporting/engine.py +312 -158
  326. oscura/reporting/enhanced_reports.py +949 -0
  327. oscura/reporting/export.py +86 -43
  328. oscura/reporting/formatting/numbers.py +69 -42
  329. oscura/reporting/html.py +139 -58
  330. oscura/reporting/index.py +137 -65
  331. oscura/reporting/output.py +158 -67
  332. oscura/reporting/pdf.py +67 -102
  333. oscura/reporting/plots.py +191 -112
  334. oscura/reporting/sections.py +88 -47
  335. oscura/reporting/standards.py +104 -61
  336. oscura/reporting/summary_generator.py +75 -55
  337. oscura/reporting/tables.py +138 -54
  338. oscura/reporting/templates/enhanced/protocol_re.html +525 -0
  339. oscura/reporting/templates/index.md +13 -13
  340. oscura/sessions/__init__.py +14 -23
  341. oscura/sessions/base.py +3 -3
  342. oscura/sessions/blackbox.py +106 -10
  343. oscura/sessions/generic.py +2 -2
  344. oscura/sessions/legacy.py +783 -0
  345. oscura/side_channel/__init__.py +63 -0
  346. oscura/side_channel/dpa.py +1025 -0
  347. oscura/utils/__init__.py +15 -1
  348. oscura/utils/autodetect.py +1 -5
  349. oscura/utils/bitwise.py +118 -0
  350. oscura/{builders → utils/builders}/__init__.py +1 -1
  351. oscura/{comparison → utils/comparison}/__init__.py +6 -6
  352. oscura/{comparison → utils/comparison}/compare.py +202 -101
  353. oscura/{comparison → utils/comparison}/golden.py +83 -63
  354. oscura/{comparison → utils/comparison}/limits.py +313 -89
  355. oscura/{comparison → utils/comparison}/mask.py +151 -45
  356. oscura/{comparison → utils/comparison}/trace_diff.py +1 -1
  357. oscura/{comparison → utils/comparison}/visualization.py +147 -89
  358. oscura/{component → utils/component}/__init__.py +3 -3
  359. oscura/{component → utils/component}/impedance.py +122 -58
  360. oscura/{component → utils/component}/reactive.py +165 -168
  361. oscura/{component → utils/component}/transmission_line.py +3 -3
  362. oscura/{filtering → utils/filtering}/__init__.py +6 -6
  363. oscura/{filtering → utils/filtering}/base.py +1 -1
  364. oscura/{filtering → utils/filtering}/convenience.py +2 -2
  365. oscura/{filtering → utils/filtering}/design.py +169 -93
  366. oscura/{filtering → utils/filtering}/filters.py +2 -2
  367. oscura/{filtering → utils/filtering}/introspection.py +2 -2
  368. oscura/utils/geometry.py +31 -0
  369. oscura/utils/imports.py +184 -0
  370. oscura/utils/lazy.py +1 -1
  371. oscura/{math → utils/math}/__init__.py +2 -2
  372. oscura/{math → utils/math}/arithmetic.py +114 -48
  373. oscura/{math → utils/math}/interpolation.py +139 -106
  374. oscura/utils/memory.py +129 -66
  375. oscura/utils/memory_advanced.py +92 -9
  376. oscura/utils/memory_extensions.py +10 -8
  377. oscura/{optimization → utils/optimization}/__init__.py +1 -1
  378. oscura/{optimization → utils/optimization}/search.py +2 -2
  379. oscura/utils/performance/__init__.py +58 -0
  380. oscura/utils/performance/caching.py +889 -0
  381. oscura/utils/performance/lsh_clustering.py +333 -0
  382. oscura/utils/performance/memory_optimizer.py +699 -0
  383. oscura/utils/performance/optimizations.py +675 -0
  384. oscura/utils/performance/parallel.py +654 -0
  385. oscura/utils/performance/profiling.py +661 -0
  386. oscura/{pipeline → utils/pipeline}/base.py +1 -1
  387. oscura/{pipeline → utils/pipeline}/composition.py +11 -3
  388. oscura/{pipeline → utils/pipeline}/parallel.py +3 -2
  389. oscura/{pipeline → utils/pipeline}/pipeline.py +1 -1
  390. oscura/{pipeline → utils/pipeline}/reverse_engineering.py +412 -221
  391. oscura/{search → utils/search}/__init__.py +3 -3
  392. oscura/{search → utils/search}/anomaly.py +188 -58
  393. oscura/utils/search/context.py +294 -0
  394. oscura/{search → utils/search}/pattern.py +138 -10
  395. oscura/utils/serial.py +51 -0
  396. oscura/utils/storage/__init__.py +61 -0
  397. oscura/utils/storage/database.py +1166 -0
  398. oscura/{streaming → utils/streaming}/chunked.py +302 -143
  399. oscura/{streaming → utils/streaming}/progressive.py +1 -1
  400. oscura/{streaming → utils/streaming}/realtime.py +3 -2
  401. oscura/{triggering → utils/triggering}/__init__.py +6 -6
  402. oscura/{triggering → utils/triggering}/base.py +6 -6
  403. oscura/{triggering → utils/triggering}/edge.py +2 -2
  404. oscura/{triggering → utils/triggering}/pattern.py +2 -2
  405. oscura/{triggering → utils/triggering}/pulse.py +115 -74
  406. oscura/{triggering → utils/triggering}/window.py +2 -2
  407. oscura/utils/validation.py +32 -0
  408. oscura/validation/__init__.py +121 -0
  409. oscura/{compliance → validation/compliance}/__init__.py +5 -5
  410. oscura/{compliance → validation/compliance}/advanced.py +5 -5
  411. oscura/{compliance → validation/compliance}/masks.py +1 -1
  412. oscura/{compliance → validation/compliance}/reporting.py +127 -53
  413. oscura/{compliance → validation/compliance}/testing.py +114 -52
  414. oscura/validation/compliance_tests.py +915 -0
  415. oscura/validation/fuzzer.py +990 -0
  416. oscura/validation/grammar_tests.py +596 -0
  417. oscura/validation/grammar_validator.py +904 -0
  418. oscura/validation/hil_testing.py +977 -0
  419. oscura/{quality → validation/quality}/__init__.py +4 -4
  420. oscura/{quality → validation/quality}/ensemble.py +251 -171
  421. oscura/{quality → validation/quality}/explainer.py +3 -3
  422. oscura/{quality → validation/quality}/scoring.py +1 -1
  423. oscura/{quality → validation/quality}/warnings.py +4 -4
  424. oscura/validation/regression_suite.py +808 -0
  425. oscura/validation/replay.py +788 -0
  426. oscura/{testing → validation/testing}/__init__.py +2 -2
  427. oscura/{testing → validation/testing}/synthetic.py +5 -5
  428. oscura/visualization/__init__.py +9 -0
  429. oscura/visualization/accessibility.py +1 -1
  430. oscura/visualization/annotations.py +64 -67
  431. oscura/visualization/colors.py +7 -7
  432. oscura/visualization/digital.py +180 -81
  433. oscura/visualization/eye.py +236 -85
  434. oscura/visualization/interactive.py +320 -143
  435. oscura/visualization/jitter.py +587 -247
  436. oscura/visualization/layout.py +169 -134
  437. oscura/visualization/optimization.py +103 -52
  438. oscura/visualization/palettes.py +1 -1
  439. oscura/visualization/power.py +427 -211
  440. oscura/visualization/power_extended.py +626 -297
  441. oscura/visualization/presets.py +2 -0
  442. oscura/visualization/protocols.py +495 -181
  443. oscura/visualization/render.py +79 -63
  444. oscura/visualization/reverse_engineering.py +171 -124
  445. oscura/visualization/signal_integrity.py +460 -279
  446. oscura/visualization/specialized.py +190 -100
  447. oscura/visualization/spectral.py +670 -255
  448. oscura/visualization/thumbnails.py +166 -137
  449. oscura/visualization/waveform.py +150 -63
  450. oscura/workflows/__init__.py +3 -0
  451. oscura/{batch → workflows/batch}/__init__.py +5 -5
  452. oscura/{batch → workflows/batch}/advanced.py +150 -75
  453. oscura/workflows/batch/aggregate.py +531 -0
  454. oscura/workflows/batch/analyze.py +236 -0
  455. oscura/{batch → workflows/batch}/logging.py +2 -2
  456. oscura/{batch → workflows/batch}/metrics.py +1 -1
  457. oscura/workflows/complete_re.py +1144 -0
  458. oscura/workflows/compliance.py +44 -54
  459. oscura/workflows/digital.py +197 -51
  460. oscura/workflows/legacy/__init__.py +12 -0
  461. oscura/{workflow → workflows/legacy}/dag.py +4 -1
  462. oscura/workflows/multi_trace.py +9 -9
  463. oscura/workflows/power.py +42 -62
  464. oscura/workflows/protocol.py +82 -49
  465. oscura/workflows/reverse_engineering.py +351 -150
  466. oscura/workflows/signal_integrity.py +157 -82
  467. oscura-0.6.0.dist-info/METADATA +643 -0
  468. oscura-0.6.0.dist-info/RECORD +590 -0
  469. oscura/analyzers/digital/ic_database.py +0 -498
  470. oscura/analyzers/digital/timing_paths.py +0 -339
  471. oscura/analyzers/digital/vintage.py +0 -377
  472. oscura/analyzers/digital/vintage_result.py +0 -148
  473. oscura/analyzers/protocols/parallel_bus.py +0 -449
  474. oscura/batch/aggregate.py +0 -300
  475. oscura/batch/analyze.py +0 -139
  476. oscura/dsl/__init__.py +0 -73
  477. oscura/exceptions.py +0 -59
  478. oscura/exploratory/fuzzy.py +0 -513
  479. oscura/exploratory/sync.py +0 -384
  480. oscura/export/wavedrom.py +0 -430
  481. oscura/exporters/__init__.py +0 -94
  482. oscura/exporters/csv.py +0 -303
  483. oscura/exporters/exporters.py +0 -44
  484. oscura/exporters/hdf5.py +0 -217
  485. oscura/exporters/html_export.py +0 -701
  486. oscura/exporters/json_export.py +0 -338
  487. oscura/exporters/markdown_export.py +0 -367
  488. oscura/exporters/matlab_export.py +0 -354
  489. oscura/exporters/npz_export.py +0 -219
  490. oscura/exporters/spice_export.py +0 -210
  491. oscura/exporters/vintage_logic_csv.py +0 -247
  492. oscura/reporting/vintage_logic_report.py +0 -523
  493. oscura/search/context.py +0 -149
  494. oscura/session/__init__.py +0 -34
  495. oscura/session/annotations.py +0 -289
  496. oscura/session/history.py +0 -313
  497. oscura/session/session.py +0 -520
  498. oscura/visualization/digital_advanced.py +0 -718
  499. oscura/visualization/figure_manager.py +0 -156
  500. oscura/workflow/__init__.py +0 -13
  501. oscura-0.5.0.dist-info/METADATA +0 -407
  502. oscura-0.5.0.dist-info/RECORD +0 -486
  503. /oscura/core/{config.py → config/legacy.py} +0 -0
  504. /oscura/{extensibility → core/extensibility}/__init__.py +0 -0
  505. /oscura/{extensibility → core/extensibility}/registry.py +0 -0
  506. /oscura/{plugins → core/plugins}/isolation.py +0 -0
  507. /oscura/{builders → utils/builders}/signal_builder.py +0 -0
  508. /oscura/{optimization → utils/optimization}/parallel.py +0 -0
  509. /oscura/{pipeline → utils/pipeline}/__init__.py +0 -0
  510. /oscura/{streaming → utils/streaming}/__init__.py +0 -0
  511. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/WHEEL +0 -0
  512. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/entry_points.txt +0 -0
  513. {oscura-0.5.0.dist-info → oscura-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,449 +0,0 @@
1
- """Parallel bus protocol decoders for vintage systems.
2
-
3
- Implements decoders for classic parallel bus protocols:
4
- - IEEE-488 (GPIB): General Purpose Interface Bus for instruments
5
- - Centronics: Parallel printer interface
6
- - ISA: Industry Standard Architecture bus
7
-
8
- Example:
9
- >>> from oscura.analyzers.protocols.parallel_bus import decode_gpib, decode_centronics
10
- >>> frames = decode_gpib(dio_lines, dav, nrfd, ndac, eoi, atn)
11
- >>> print_data = decode_centronics(data_lines, strobe, busy, ack)
12
- """
13
-
14
- from __future__ import annotations
15
-
16
- from dataclasses import dataclass
17
- from enum import Enum
18
- from typing import TYPE_CHECKING
19
-
20
- import numpy as np
21
-
22
- if TYPE_CHECKING:
23
- from numpy.typing import NDArray
24
-
25
-
26
- # =============================================================================
27
- # IEEE-488 (GPIB) Protocol Decoder
28
- # =============================================================================
29
-
30
-
31
- class GPIBMessageType(Enum):
32
- """GPIB message types."""
33
-
34
- DATA = "data" # Data bytes (ATN=0)
35
- COMMAND = "command" # Command bytes (ATN=1)
36
- TALK_ADDRESS = "talk_address" # Talk address
37
- LISTEN_ADDRESS = "listen_address" # Listen address
38
- SECONDARY_ADDRESS = "secondary_address" # Secondary address
39
- UNIVERSAL_COMMAND = "universal_command" # Universal command
40
- ADDRESSED_COMMAND = "addressed_command" # Addressed command
41
-
42
-
43
- @dataclass
44
- class GPIBFrame:
45
- """A decoded GPIB frame.
46
-
47
- Attributes:
48
- timestamp: Frame timestamp in seconds.
49
- data: Data byte value (0-255).
50
- message_type: Type of GPIB message.
51
- eoi: End-Or-Identify asserted.
52
- description: Human-readable description.
53
- """
54
-
55
- timestamp: float
56
- data: int
57
- message_type: GPIBMessageType
58
- eoi: bool
59
- description: str
60
-
61
-
62
- def decode_gpib(
63
- dio_lines: list[NDArray[np.bool_]], # DIO1-DIO8 (8 data lines)
64
- dav: NDArray[np.bool_], # Data Valid
65
- nrfd: NDArray[np.bool_], # Not Ready For Data
66
- ndac: NDArray[np.bool_], # Not Data Accepted
67
- eoi: NDArray[np.bool_], # End Or Identify
68
- atn: NDArray[np.bool_], # Attention
69
- sample_rate: float = 1.0,
70
- ) -> list[GPIBFrame]:
71
- """Decode IEEE-488 (GPIB) bus transactions.
72
-
73
- Args:
74
- dio_lines: List of 8 digital traces for DIO1-DIO8.
75
- dav: Data Valid signal (active low).
76
- nrfd: Not Ready For Data signal (active low).
77
- ndac: Not Data Accepted signal (active low).
78
- eoi: End Or Identify signal (active low).
79
- atn: Attention signal (active low).
80
- sample_rate: Sample rate in Hz.
81
-
82
- Returns:
83
- List of GPIBFrame objects.
84
-
85
- Example:
86
- >>> frames = decode_gpib(dio, dav, nrfd, ndac, eoi, atn, 1e6)
87
- >>> for frame in frames:
88
- ... print(f"{frame.timestamp*1e6:.1f}us: {frame.description}")
89
- """
90
- if len(dio_lines) != 8:
91
- raise ValueError("GPIB requires exactly 8 DIO lines")
92
-
93
- frames: list[GPIBFrame] = []
94
- time_base = 1.0 / sample_rate
95
-
96
- # Combine DIO lines into data bus
97
- data_bus = np.zeros(len(dio_lines[0]), dtype=np.uint8)
98
- for i, line in enumerate(dio_lines):
99
- data_bus |= (line.astype(np.uint8) << i).astype(np.uint8)
100
-
101
- # Detect DAV falling edges (data valid)
102
- dav_falling = np.where(np.diff(dav.astype(np.int8)) == -1)[0]
103
-
104
- for idx in dav_falling:
105
- # Sample data after falling edge
106
- sample_idx = idx + 1
107
- if sample_idx >= len(data_bus):
108
- continue
109
-
110
- timestamp = idx * time_base
111
- data_byte = int(data_bus[sample_idx])
112
- eoi_active = not eoi[sample_idx] # Active low
113
- atn_active = not atn[sample_idx] # Active low
114
-
115
- # Decode message type based on ATN and data
116
- if atn_active:
117
- # Check address bytes first (bit patterns for talk/listen)
118
- if data_byte & 0x40:
119
- # Talk address (bit 6 set)
120
- address = data_byte & 0x1F
121
- msg_type = GPIBMessageType.TALK_ADDRESS
122
- desc = f"Talk address {address}"
123
- elif data_byte & 0x20:
124
- # Listen address (bit 5 set, bit 6 clear)
125
- address = data_byte & 0x1F
126
- msg_type = GPIBMessageType.LISTEN_ADDRESS
127
- desc = f"Listen address {address}"
128
- elif 0x10 <= data_byte <= 0x1F:
129
- # Universal commands
130
- msg_type = GPIBMessageType.UNIVERSAL_COMMAND
131
- desc = _gpib_universal_command_name(data_byte)
132
- else:
133
- # Addressed commands (0x00-0x0F and others)
134
- msg_type = GPIBMessageType.ADDRESSED_COMMAND
135
- desc = _gpib_addressed_command_name(data_byte)
136
- else:
137
- # Data byte
138
- msg_type = GPIBMessageType.DATA
139
- desc = f"Data: 0x{data_byte:02X}"
140
- if 32 <= data_byte <= 126:
141
- desc += f" ('{chr(data_byte)}')"
142
-
143
- if eoi_active:
144
- desc += " [EOI]"
145
-
146
- frames.append(
147
- GPIBFrame(
148
- timestamp=timestamp,
149
- data=data_byte,
150
- message_type=msg_type,
151
- eoi=eoi_active,
152
- description=desc,
153
- )
154
- )
155
-
156
- return frames
157
-
158
-
159
- def _gpib_universal_command_name(cmd: int) -> str:
160
- """Get name of GPIB universal command."""
161
- commands = {
162
- 0x11: "DCL (Device Clear)",
163
- 0x14: "GET (Group Execute Trigger)",
164
- 0x15: "GTL (Go To Local)",
165
- 0x08: "LLO (Local Lockout)",
166
- 0x01: "SPD (Serial Poll Disable)",
167
- 0x18: "SPE (Serial Poll Enable)",
168
- 0x13: "PPU (Parallel Poll Unconfigure)",
169
- }
170
- return commands.get(cmd, f"Unknown universal command 0x{cmd:02X}")
171
-
172
-
173
- def _gpib_addressed_command_name(cmd: int) -> str:
174
- """Get name of GPIB addressed command."""
175
- commands = {
176
- 0x04: "SDC (Selected Device Clear)",
177
- 0x05: "PPC (Parallel Poll Configure)",
178
- 0x09: "TCT (Take Control)",
179
- }
180
- return commands.get(cmd, f"Unknown addressed command 0x{cmd:02X}")
181
-
182
-
183
- # =============================================================================
184
- # Centronics Parallel Printer Protocol Decoder
185
- # =============================================================================
186
-
187
-
188
- @dataclass
189
- class CentronicsFrame:
190
- """A decoded Centronics printer frame.
191
-
192
- Attributes:
193
- timestamp: Frame timestamp in seconds.
194
- data: Data byte value (0-255).
195
- character: ASCII character (if printable).
196
- control: Control signal states.
197
- """
198
-
199
- timestamp: float
200
- data: int
201
- character: str | None
202
- control: dict[str, bool]
203
-
204
-
205
- def decode_centronics(
206
- data_lines: list[NDArray[np.bool_]], # D0-D7 (8 data lines)
207
- strobe: NDArray[np.bool_], # Strobe signal (active low)
208
- busy: NDArray[np.bool_], # Busy signal
209
- ack: NDArray[np.bool_], # Acknowledge signal (active low)
210
- sample_rate: float = 1.0,
211
- *,
212
- select: NDArray[np.bool_] | None = None, # Select signal
213
- paper_out: NDArray[np.bool_] | None = None, # Paper Out signal
214
- error: NDArray[np.bool_] | None = None, # Error signal
215
- ) -> list[CentronicsFrame]:
216
- """Decode Centronics parallel printer protocol.
217
-
218
- Args:
219
- data_lines: List of 8 digital traces for D0-D7.
220
- strobe: Strobe signal (active low).
221
- busy: Busy signal (high when printer busy).
222
- ack: Acknowledge signal (active low pulse).
223
- sample_rate: Sample rate in Hz.
224
- select: Optional select signal.
225
- paper_out: Optional paper out signal.
226
- error: Optional error signal.
227
-
228
- Returns:
229
- List of CentronicsFrame objects.
230
-
231
- Example:
232
- >>> frames = decode_centronics(data, strobe, busy, ack, 1e6)
233
- >>> for frame in frames:
234
- ... if frame.character:
235
- ... print(frame.character, end='')
236
- """
237
- if len(data_lines) != 8:
238
- raise ValueError("Centronics requires exactly 8 data lines")
239
-
240
- frames: list[CentronicsFrame] = []
241
- time_base = 1.0 / sample_rate
242
-
243
- # Combine data lines into bytes
244
- data_bus = np.zeros(len(data_lines[0]), dtype=np.uint8)
245
- for i, line in enumerate(data_lines):
246
- data_bus |= (line.astype(np.uint8) << i).astype(np.uint8)
247
-
248
- # Detect STROBE falling edges (data latch)
249
- strobe_falling = np.where(np.diff(strobe.astype(np.int8)) == -1)[0]
250
-
251
- for idx in strobe_falling:
252
- # Sample data after falling edge
253
- sample_idx = idx + 1
254
- if sample_idx >= len(data_bus):
255
- continue
256
-
257
- timestamp = idx * time_base
258
- data_byte = int(data_bus[sample_idx])
259
-
260
- # Check if printable ASCII
261
- char = chr(data_byte) if 32 <= data_byte <= 126 else None
262
-
263
- # Capture control signals
264
- control = {
265
- "busy": bool(busy[sample_idx]),
266
- "ack": not ack[sample_idx], # Active low
267
- }
268
-
269
- if select is not None:
270
- control["select"] = bool(select[sample_idx])
271
- if paper_out is not None:
272
- control["paper_out"] = bool(paper_out[sample_idx])
273
- if error is not None:
274
- control["error"] = bool(error[sample_idx])
275
-
276
- frames.append(
277
- CentronicsFrame(
278
- timestamp=timestamp,
279
- data=data_byte,
280
- character=char,
281
- control=control,
282
- )
283
- )
284
-
285
- return frames
286
-
287
-
288
- # =============================================================================
289
- # ISA Bus Protocol Analyzer
290
- # =============================================================================
291
-
292
-
293
- class ISACycleType(Enum):
294
- """ISA bus cycle types."""
295
-
296
- MEMORY_READ = "memory_read"
297
- MEMORY_WRITE = "memory_write"
298
- IO_READ = "io_read"
299
- IO_WRITE = "io_write"
300
- DMA = "dma"
301
- INTERRUPT = "interrupt"
302
-
303
-
304
- @dataclass
305
- class ISATransaction:
306
- """An ISA bus transaction.
307
-
308
- Attributes:
309
- timestamp: Transaction timestamp in seconds.
310
- cycle_type: Type of bus cycle.
311
- address: Address (20-bit for memory, 16-bit for I/O).
312
- data: Data byte (if applicable).
313
- description: Human-readable description.
314
- """
315
-
316
- timestamp: float
317
- cycle_type: ISACycleType
318
- address: int
319
- data: int | None
320
- description: str
321
-
322
-
323
- def decode_isa_bus(
324
- address_lines: list[NDArray[np.bool_]], # SA0-SA19 (20 address lines)
325
- data_lines: list[NDArray[np.bool_]], # SD0-SD7 (8 data lines)
326
- ior: NDArray[np.bool_], # I/O Read (active low)
327
- iow: NDArray[np.bool_], # I/O Write (active low)
328
- memr: NDArray[np.bool_], # Memory Read (active low)
329
- memw: NDArray[np.bool_], # Memory Write (active low)
330
- ale: NDArray[np.bool_], # Address Latch Enable
331
- sample_rate: float = 1.0,
332
- ) -> list[ISATransaction]:
333
- """Decode ISA bus transactions.
334
-
335
- Args:
336
- address_lines: List of 20 digital traces for SA0-SA19.
337
- data_lines: List of 8 digital traces for SD0-SD7.
338
- ior: I/O Read signal (active low).
339
- iow: I/O Write signal (active low).
340
- memr: Memory Read signal (active low).
341
- memw: Memory Write signal (active low).
342
- ale: Address Latch Enable.
343
- sample_rate: Sample rate in Hz.
344
-
345
- Returns:
346
- List of ISATransaction objects.
347
-
348
- Example:
349
- >>> trans = decode_isa_bus(addr, data, ior, iow, memr, memw, ale, 1e6)
350
- >>> for t in trans:
351
- ... print(f"{t.timestamp*1e6:.1f}us: {t.description}")
352
- """
353
- if len(address_lines) < 16:
354
- raise ValueError("ISA bus requires at least 16 address lines")
355
- if len(data_lines) != 8:
356
- raise ValueError("ISA bus requires exactly 8 data lines")
357
-
358
- transactions: list[ISATransaction] = []
359
- time_base = 1.0 / sample_rate
360
-
361
- # Combine address lines
362
- address_bus = np.zeros(len(address_lines[0]), dtype=np.uint32)
363
- for i, line in enumerate(address_lines):
364
- address_bus |= (line.astype(np.uint32) << i).astype(np.uint32)
365
-
366
- # Combine data lines
367
- data_bus = np.zeros(len(data_lines[0]), dtype=np.uint8)
368
- for i, line in enumerate(data_lines):
369
- data_bus |= (line.astype(np.uint8) << i).astype(np.uint8)
370
-
371
- # Detect ALE falling edges (address latch)
372
- ale_falling = np.where(np.diff(ale.astype(np.int8)) == -1)[0]
373
-
374
- for idx in ale_falling:
375
- if idx >= len(address_bus):
376
- continue
377
-
378
- timestamp = idx * time_base
379
- address = int(address_bus[idx])
380
-
381
- # Look ahead for read/write strobes (larger window to catch delayed strobes)
382
- search_window = min(idx + 200, len(ior))
383
-
384
- ior_active = np.any(~ior[idx:search_window])
385
- iow_active = np.any(~iow[idx:search_window])
386
- memr_active = np.any(~memr[idx:search_window])
387
- memw_active = np.any(~memw[idx:search_window])
388
-
389
- # Determine cycle type
390
- data_val = None
391
-
392
- if ior_active:
393
- cycle_type = ISACycleType.IO_READ
394
- desc = f"I/O Read from 0x{address:04X}"
395
- # Find data at IOR falling edge
396
- ior_idx = np.where(~ior[idx:search_window])[0]
397
- if len(ior_idx) > 0:
398
- data_val = int(data_bus[idx + ior_idx[0]])
399
- desc += f" = 0x{data_val:02X}"
400
-
401
- elif iow_active:
402
- cycle_type = ISACycleType.IO_WRITE
403
- iow_idx = np.where(~iow[idx:search_window])[0]
404
- if len(iow_idx) > 0:
405
- data_val = int(data_bus[idx + iow_idx[0]])
406
- desc = f"I/O Write 0x{data_val:02X} to 0x{address:04X}"
407
-
408
- elif memr_active:
409
- cycle_type = ISACycleType.MEMORY_READ
410
- desc = f"Memory Read from 0x{address:05X}"
411
- memr_idx = np.where(~memr[idx:search_window])[0]
412
- if len(memr_idx) > 0:
413
- data_val = int(data_bus[idx + memr_idx[0]])
414
- desc += f" = 0x{data_val:02X}"
415
-
416
- elif memw_active:
417
- cycle_type = ISACycleType.MEMORY_WRITE
418
- memw_idx = np.where(~memw[idx:search_window])[0]
419
- if len(memw_idx) > 0:
420
- data_val = int(data_bus[idx + memw_idx[0]])
421
- desc = f"Memory Write 0x{data_val:02X} to 0x{address:05X}"
422
-
423
- else:
424
- # No control signals active
425
- continue
426
-
427
- transactions.append(
428
- ISATransaction(
429
- timestamp=timestamp,
430
- cycle_type=cycle_type,
431
- address=address,
432
- data=data_val,
433
- description=desc,
434
- )
435
- )
436
-
437
- return transactions
438
-
439
-
440
- __all__ = [
441
- "CentronicsFrame",
442
- "GPIBFrame",
443
- "GPIBMessageType",
444
- "ISACycleType",
445
- "ISATransaction",
446
- "decode_centronics",
447
- "decode_gpib",
448
- "decode_isa_bus",
449
- ]