oscura 0.5.0__py3-none-any.whl → 0.5.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. oscura/__init__.py +1 -1
  2. oscura/analyzers/digital/__init__.py +0 -48
  3. oscura/analyzers/digital/extraction.py +0 -195
  4. oscura/analyzers/protocols/__init__.py +1 -22
  5. oscura/automotive/__init__.py +1 -1
  6. oscura/automotive/dtc/data.json +2763 -0
  7. oscura/export/__init__.py +0 -12
  8. oscura/export/wireshark/README.md +15 -15
  9. oscura/exporters/json_export.py +0 -47
  10. oscura/inference/active_learning/README.md +7 -7
  11. oscura/pipeline/composition.py +10 -2
  12. oscura/reporting/__init__.py +0 -7
  13. oscura/reporting/templates/index.md +13 -13
  14. oscura/schemas/bus_configuration.json +322 -0
  15. oscura/schemas/device_mapping.json +182 -0
  16. oscura/schemas/packet_format.json +418 -0
  17. oscura/schemas/protocol_definition.json +363 -0
  18. oscura/utils/autodetect.py +1 -5
  19. oscura-0.5.1.dist-info/METADATA +583 -0
  20. {oscura-0.5.0.dist-info → oscura-0.5.1.dist-info}/RECORD +23 -28
  21. oscura/analyzers/digital/ic_database.py +0 -498
  22. oscura/analyzers/digital/timing_paths.py +0 -339
  23. oscura/analyzers/digital/vintage.py +0 -377
  24. oscura/analyzers/digital/vintage_result.py +0 -148
  25. oscura/analyzers/protocols/parallel_bus.py +0 -449
  26. oscura/export/wavedrom.py +0 -430
  27. oscura/exporters/vintage_logic_csv.py +0 -247
  28. oscura/reporting/vintage_logic_report.py +0 -523
  29. oscura/visualization/digital_advanced.py +0 -718
  30. oscura/visualization/figure_manager.py +0 -156
  31. oscura-0.5.0.dist-info/METADATA +0 -407
  32. {oscura-0.5.0.dist-info → oscura-0.5.1.dist-info}/WHEEL +0 -0
  33. {oscura-0.5.0.dist-info → oscura-0.5.1.dist-info}/entry_points.txt +0 -0
  34. {oscura-0.5.0.dist-info → oscura-0.5.1.dist-info}/licenses/LICENSE +0 -0
oscura/__init__.py CHANGED
@@ -46,7 +46,7 @@ Example:
46
46
  For more information, see https://github.com/oscura-re/oscura
47
47
  """
48
48
 
49
- __version__ = "0.5.0"
49
+ __version__ = "0.5.1"
50
50
  __author__ = "Oscura Contributors"
51
51
 
52
52
  # Core types
@@ -52,17 +52,9 @@ from oscura.analyzers.digital.edges import (
52
52
  from oscura.analyzers.digital.extraction import (
53
53
  LOGIC_FAMILIES,
54
54
  detect_edges,
55
- detect_logic_family,
56
- detect_open_collector,
57
55
  get_logic_threshold,
58
56
  to_digital,
59
57
  )
60
- from oscura.analyzers.digital.ic_database import (
61
- IC_DATABASE,
62
- ICTiming,
63
- identify_ic,
64
- validate_ic_timing,
65
- )
66
58
  from oscura.analyzers.digital.quality import (
67
59
  Glitch,
68
60
  NoiseMarginResult,
@@ -105,37 +97,13 @@ from oscura.analyzers.digital.timing import (
105
97
  skew,
106
98
  slew_rate,
107
99
  )
108
- from oscura.analyzers.digital.timing_paths import (
109
- ICStage,
110
- SetupHoldAnalysis,
111
- TimingPathResult,
112
- analyze_setup_hold,
113
- analyze_timing_path,
114
- calculate_timing_budget,
115
- find_critical_paths,
116
- )
117
- from oscura.analyzers.digital.vintage import (
118
- REPLACEMENT_DATABASE,
119
- analyze_vintage_logic,
120
- )
121
- from oscura.analyzers.digital.vintage_result import (
122
- BOMEntry,
123
- ICIdentificationResult,
124
- ModernReplacementIC,
125
- VintageLogicAnalysisResult,
126
- )
127
100
 
128
101
  __all__ = [
129
- # IC Database
130
- "IC_DATABASE",
131
102
  # Extraction
132
103
  "LOGIC_FAMILIES",
133
- "REPLACEMENT_DATABASE",
134
104
  "AdaptiveThresholdResult",
135
105
  # Adaptive Thresholds (RE-THR-001)
136
106
  "AdaptiveThresholder",
137
- # Vintage Logic Analysis
138
- "BOMEntry",
139
107
  # Clock Recovery (DSP-002)
140
108
  "BaudRateResult",
141
109
  # Bus Decoding (DSP-003)
@@ -157,10 +125,6 @@ __all__ = [
157
125
  "EdgeTimingViolation",
158
126
  # Quality
159
127
  "Glitch",
160
- "ICIdentificationResult",
161
- "ICStage",
162
- "ICTiming",
163
- "ModernReplacementIC",
164
128
  # Multi-Level Logic (RE-THR-002)
165
129
  "MultiLevelDetector",
166
130
  "MultiLevelResult",
@@ -168,25 +132,18 @@ __all__ = [
168
132
  # Signal Quality (DSP-005)
169
133
  "NoiseMargins",
170
134
  "ParallelBusConfig",
171
- "SetupHoldAnalysis",
172
135
  "SignalIntegrityReport",
173
136
  "SignalQualityAnalyzer",
174
137
  "SimpleQualityMetrics",
175
138
  "ThresholdConfig",
176
139
  "TimingConstraint",
177
- "TimingPathResult",
178
140
  "TimingViolation",
179
141
  "TransitionMetrics",
180
- "VintageLogicAnalysisResult",
181
142
  "Violation",
182
143
  "align_by_trigger",
183
- "analyze_setup_hold",
184
144
  "analyze_signal_integrity",
185
- "analyze_timing_path",
186
- "analyze_vintage_logic",
187
145
  "apply_adaptive_threshold",
188
146
  "calculate_threshold_snr",
189
- "calculate_timing_budget",
190
147
  "check_timing_constraints",
191
148
  "classify_edge_quality",
192
149
  "correlate_channels",
@@ -196,14 +153,10 @@ __all__ = [
196
153
  "detect_edges",
197
154
  "detect_edges_advanced",
198
155
  "detect_glitches",
199
- "detect_logic_family",
200
156
  "detect_multi_level",
201
- "detect_open_collector",
202
157
  "detect_violations",
203
- "find_critical_paths",
204
158
  "get_logic_threshold",
205
159
  "hold_time",
206
- "identify_ic",
207
160
  "interpolate_edge_time",
208
161
  "measure_clock_jitter",
209
162
  "measure_edge_timing",
@@ -221,5 +174,4 @@ __all__ = [
221
174
  "skew",
222
175
  "slew_rate",
223
176
  "to_digital",
224
- "validate_ic_timing",
225
177
  ]
@@ -25,7 +25,6 @@ if TYPE_CHECKING:
25
25
  # Standard logic family threshold constants
26
26
  # Reference: Various IC manufacturer datasheets
27
27
  LOGIC_FAMILIES: dict[str, dict[str, float]] = {
28
- # Modern logic families (5V)
29
28
  "TTL": {
30
29
  "VIL_max": 0.8, # Maximum input low voltage
31
30
  "VIH_min": 2.0, # Minimum input high voltage
@@ -75,63 +74,6 @@ LOGIC_FAMILIES: dict[str, dict[str, float]] = {
75
74
  "VOH_min": 1.1,
76
75
  "VCC": 1.2,
77
76
  },
78
- # Vintage logic families (1960s-1970s)
79
- "ECL": {
80
- "VIL_max": -1.475, # ECL 10K series
81
- "VIH_min": -1.105,
82
- "VOL_max": -1.630, # Typical -1.63V
83
- "VOH_min": -0.980, # Typical -0.98V
84
- "VCC": 0.0, # Ground-referenced
85
- "VEE": -5.2, # Negative supply
86
- "differential": True, # Differential signaling
87
- },
88
- "ECL_100K": {
89
- "VIL_max": -1.810, # ECL 100K series (faster)
90
- "VIH_min": -1.620,
91
- "VOL_max": -1.950,
92
- "VOH_min": -1.650,
93
- "VCC": 0.0,
94
- "VEE": -5.2,
95
- "differential": True,
96
- },
97
- "RTL": {
98
- "VIL_max": 0.4, # Resistor-Transistor Logic
99
- "VIH_min": 0.9,
100
- "VOL_max": 0.2,
101
- "VOH_min": 3.6, # Typical 3.6V high output
102
- "VCC": 3.6, # 3.6V supply common
103
- },
104
- "DTL": {
105
- "VIL_max": 0.5, # Diode-Transistor Logic
106
- "VIH_min": 2.0,
107
- "VOL_max": 0.4,
108
- "VOH_min": 4.0, # Typical 4V high output
109
- "VCC": 5.0,
110
- },
111
- "MOS": {
112
- "VIL_max": -3.0, # P-channel MOS (negative logic)
113
- "VIH_min": -10.0,
114
- "VOL_max": -0.5,
115
- "VOH_min": -11.5,
116
- "VCC": 0.0, # Ground
117
- "VDD": -12.0, # Negative supply
118
- },
119
- "PMOS": {
120
- "VIL_max": -3.0, # PMOS (4000 series at -12V)
121
- "VIH_min": -9.0,
122
- "VOL_max": -0.5,
123
- "VOH_min": -11.5,
124
- "VCC": 0.0,
125
- "VDD": -12.0,
126
- },
127
- "NMOS": {
128
- "VIL_max": 1.5, # NMOS (positive logic, 12V)
129
- "VIH_min": 8.0,
130
- "VOL_max": 0.5,
131
- "VOH_min": 11.5,
132
- "VCC": 12.0,
133
- "VSS": 0.0,
134
- },
135
77
  }
136
78
 
137
79
 
@@ -463,146 +405,9 @@ def get_logic_threshold(
463
405
  raise ValueError(f"Unknown threshold_type: {threshold_type}")
464
406
 
465
407
 
466
- def detect_logic_family(
467
- trace: WaveformTrace,
468
- *,
469
- confidence_threshold: float = 0.8,
470
- ) -> tuple[str, float]:
471
- """Auto-detect logic family from signal voltage levels.
472
-
473
- Analyzes the signal to determine which logic family it most likely represents
474
- based on voltage levels.
475
-
476
- Args:
477
- trace: Input analog waveform trace.
478
- confidence_threshold: Minimum confidence (0-1) to return a match.
479
-
480
- Returns:
481
- Tuple of (family_name, confidence_score).
482
- Returns ("unknown", 0.0) if no match above threshold.
483
-
484
- Example:
485
- >>> family, conf = detect_logic_family(trace)
486
- >>> print(f"Detected: {family} ({conf*100:.1f}% confidence)")
487
- """
488
- if len(trace.data) < 10:
489
- return ("unknown", 0.0)
490
-
491
- data = np.asarray(trace.data)
492
-
493
- # Find voltage levels using percentiles
494
- p10, p90 = np.percentile(data, [10, 90])
495
- vlow = p10
496
- vhigh = p90
497
-
498
- # Calculate midpoint and swing
499
- vmid = (vlow + vhigh) / 2.0
500
- vswing = vhigh - vlow
501
-
502
- if vswing < 0.1: # Insufficient signal
503
- return ("unknown", 0.0)
504
-
505
- # Score each logic family
506
- scores: dict[str, float] = {}
507
-
508
- for family_name, levels in LOGIC_FAMILIES.items():
509
- # Check if voltage levels match this family
510
- vil_max = levels["VIL_max"]
511
- vih_min = levels["VIH_min"]
512
- vcc = levels.get("VCC", 5.0)
513
-
514
- # Expected midpoint for this family
515
- expected_mid = (vil_max + vih_min) / 2.0
516
-
517
- # Score based on:
518
- # 1. Midpoint proximity
519
- # 2. High level proximity to VOH
520
- # 3. Low level proximity to VOL
521
-
522
- mid_error = abs(vmid - expected_mid)
523
- high_error = abs(vhigh - levels.get("VOH_min", vih_min))
524
- low_error = abs(vlow - levels.get("VOL_max", vil_max))
525
-
526
- # Normalize errors (handle VCC=0 for ECL/PMOS)
527
- if vcc != 0:
528
- mid_score = max(0, 1.0 - mid_error / abs(vcc))
529
- high_score = max(0, 1.0 - high_error / abs(vcc))
530
- low_score = max(0, 1.0 - low_error / abs(vcc))
531
- else:
532
- # For VCC=0 families (ECL), use voltage range instead
533
- voltage_range = abs(vih_min - vil_max)
534
- if voltage_range > 0:
535
- mid_score = max(0, 1.0 - mid_error / voltage_range)
536
- high_score = max(0, 1.0 - high_error / voltage_range)
537
- low_score = max(0, 1.0 - low_error / voltage_range)
538
- else:
539
- mid_score = high_score = low_score = 0.0
540
-
541
- # Combined score (weighted average)
542
- total_score = mid_score * 0.5 + high_score * 0.25 + low_score * 0.25
543
- scores[family_name] = total_score
544
-
545
- # Find best match
546
- if not scores:
547
- return ("unknown", 0.0)
548
-
549
- best_family = max(scores.items(), key=lambda x: x[1])
550
-
551
- if best_family[1] < confidence_threshold:
552
- return ("unknown", best_family[1])
553
-
554
- return best_family
555
-
556
-
557
- def detect_open_collector(
558
- trace: WaveformTrace,
559
- *,
560
- asymmetry_threshold: float = 3.0,
561
- ) -> tuple[bool, float]:
562
- """Detect open-collector or open-drain output.
563
-
564
- Open-collector outputs have slow rise times (limited by pull-up resistor)
565
- and fast fall times (active transistor).
566
-
567
- Args:
568
- trace: Input analog waveform trace.
569
- asymmetry_threshold: Minimum rise/fall ratio to indicate open-collector.
570
-
571
- Returns:
572
- Tuple of (is_open_collector, asymmetry_ratio).
573
-
574
- Example:
575
- >>> is_oc, ratio = detect_open_collector(trace)
576
- >>> if is_oc:
577
- ... print(f"Open-collector detected (rise/fall = {ratio:.1f})")
578
- """
579
- from oscura.analyzers.waveform.measurements import fall_time, rise_time
580
-
581
- if len(trace.data) < 10:
582
- return (False, 1.0)
583
-
584
- # Measure rise and fall times
585
- tr = rise_time(trace, ref_levels=(0.1, 0.9))
586
- tf = fall_time(trace, ref_levels=(0.9, 0.1))
587
-
588
- # Check for valid measurements
589
- if np.isnan(tr) or np.isnan(tf) or tf == 0:
590
- return (False, 1.0)
591
-
592
- # Calculate asymmetry ratio
593
- asymmetry = tr / tf
594
-
595
- # Open-collector has slow rise, fast fall
596
- is_oc = bool(asymmetry >= asymmetry_threshold)
597
-
598
- return (is_oc, float(asymmetry))
599
-
600
-
601
408
  __all__ = [
602
409
  "LOGIC_FAMILIES",
603
410
  "detect_edges",
604
- "detect_logic_family",
605
- "detect_open_collector",
606
411
  "get_logic_threshold",
607
412
  "to_digital",
608
413
  ]
@@ -2,7 +2,7 @@
2
2
 
3
3
  Provides protocol decoders for common serial and automotive protocols including
4
4
  UART, SPI, I2C, CAN, LIN, FlexRay, JTAG, SWD, I2S, USB, HDLC, Manchester, CAN-FD,
5
- 1-Wire, and parallel bus protocols (GPIB, Centronics, ISA).
5
+ and 1-Wire.
6
6
  """
7
7
 
8
8
  from oscura.analyzers.protocols.base import (
@@ -60,18 +60,6 @@ from oscura.analyzers.protocols.onewire import (
60
60
  OneWireTimings,
61
61
  decode_onewire,
62
62
  )
63
-
64
- # Parallel bus protocols
65
- from oscura.analyzers.protocols.parallel_bus import (
66
- CentronicsFrame,
67
- GPIBFrame,
68
- GPIBMessageType,
69
- ISACycleType,
70
- ISATransaction,
71
- decode_centronics,
72
- decode_gpib,
73
- decode_isa_bus,
74
- )
75
63
  from oscura.analyzers.protocols.spi import SPIDecoder, decode_spi
76
64
  from oscura.analyzers.protocols.swd import SWDDecoder, SWDResponse, decode_swd
77
65
  from oscura.analyzers.protocols.uart import UARTDecoder, decode_uart
@@ -103,16 +91,12 @@ __all__ = [
103
91
  "CANFDFrameType",
104
92
  "CANFrame",
105
93
  "CANFrameType",
106
- # Parallel bus protocols
107
- "CentronicsFrame",
108
94
  "ChannelDef",
109
95
  "DecoderState",
110
96
  # FlexRay (PRO-016)
111
97
  "FlexRayDecoder",
112
98
  "FlexRayFrame",
113
99
  "FlexRaySegment",
114
- "GPIBFrame",
115
- "GPIBMessageType",
116
100
  # HDLC (PRO-013)
117
101
  "HDLCDecoder",
118
102
  # I2C (PRO-004)
@@ -120,8 +104,6 @@ __all__ = [
120
104
  # I2S (PRO-011)
121
105
  "I2SDecoder",
122
106
  "I2SMode",
123
- "ISACycleType",
124
- "ISATransaction",
125
107
  # JTAG (PRO-009)
126
108
  "JTAGDecoder",
127
109
  # LIN (PRO-008)
@@ -153,13 +135,10 @@ __all__ = [
153
135
  "USBSpeed",
154
136
  "decode_can",
155
137
  "decode_can_fd",
156
- "decode_centronics",
157
138
  "decode_flexray",
158
- "decode_gpib",
159
139
  "decode_hdlc",
160
140
  "decode_i2c",
161
141
  "decode_i2s",
162
- "decode_isa_bus",
163
142
  "decode_jtag",
164
143
  "decode_lin",
165
144
  "decode_manchester",
@@ -42,7 +42,7 @@ Example:
42
42
  P0420: Catalyst System Efficiency Below Threshold (Bank 1)
43
43
  """
44
44
 
45
- __version__ = "0.5.0" # pragma: no cover
45
+ __version__ = "0.5.1" # pragma: no cover
46
46
 
47
47
  __all__ = [
48
48
  "CANMessage",