Optimize datasheet timing to be spec-compliant with symmetric cycles. Strategy: 1. Keep measured T0H and T1H (high times are most critical) 2. Minimize T0H (reduce jitter impact - timers never fire early) 3. Adjust T0L and T1L to create symmetric cycles (T0H+T0L = T1H+T1
(
measured: TimingDatasheet, spec: TimingSpec
)
| 222 | |
| 223 | |
| 224 | def optimize_datasheet_timing( |
| 225 | measured: TimingDatasheet, spec: TimingSpec |
| 226 | ) -> TimingDatasheet: |
| 227 | """Optimize datasheet timing to be spec-compliant with symmetric cycles. |
| 228 | |
| 229 | Strategy: |
| 230 | 1. Keep measured T0H and T1H (high times are most critical) |
| 231 | 2. Minimize T0H (reduce jitter impact - timers never fire early) |
| 232 | 3. Adjust T0L and T1L to create symmetric cycles (T0H+T0L = T1H+T1L) |
| 233 | 4. Ensure all values are within spec ranges |
| 234 | |
| 235 | Args: |
| 236 | measured: Measured timing values (may be out of spec or asymmetric) |
| 237 | spec: Datasheet specifications (min/max ranges) |
| 238 | |
| 239 | Returns: |
| 240 | Optimized spec-compliant symmetric timing |
| 241 | |
| 242 | Example: |
| 243 | >>> spec = TimingSpec(220, 380, 580, 1000, 580, 1000, 580, 1000) |
| 244 | >>> measured = TimingDatasheet(264, 920, 640, 552) # Asymmetric, T1L out of spec |
| 245 | >>> optimized = optimize_datasheet_timing(measured, spec) |
| 246 | >>> print(optimized) |
| 247 | T0H=264ns, T0L=1000ns, T1H=640ns, T1L=624ns (cycle=1264ns) |
| 248 | """ |
| 249 | # Use measured high times (most critical for signal integrity) |
| 250 | # KEEP both T0H and T1H from measured values because they're hardware-dependent |
| 251 | T0H = measured.T0H |
| 252 | T1H = measured.T1H |
| 253 | |
| 254 | # Clamp high times to spec ranges |
| 255 | T0H = max(spec.T0H_min, min(T0H, spec.T0H_max)) |
| 256 | T1H = max(spec.T1H_min, min(T1H, spec.T1H_max)) |
| 257 | |
| 258 | # For symmetric cycles: T0H + T0L = T1H + T1L |
| 259 | # We need to find T0L and T1L such that: |
| 260 | # 1. T0L and T1L are both in spec ranges |
| 261 | # 2. T0H + T0L = T1H + T1L (symmetric) |
| 262 | |
| 263 | # From symmetry: T0L = T1L + (T1H - T0H) |
| 264 | # We need: T0L_min <= T1L + (T1H - T0H) <= T0L_max |
| 265 | # T1L_min <= T1L <= T1L_max |
| 266 | |
| 267 | # Solving for valid T1L range: |
| 268 | # T0L_min <= T1L + (T1H - T0H) <= T0L_max |
| 269 | # T0L_min - (T1H - T0H) <= T1L <= T0L_max - (T1H - T0H) |
| 270 | |
| 271 | delta = T1H - T0H |
| 272 | T1L_min_constrained = max(spec.T1L_min, spec.T0L_min - delta) |
| 273 | T1L_max_constrained = min(spec.T1L_max, spec.T0L_max - delta) |
| 274 | |
| 275 | if T1L_min_constrained > T1L_max_constrained: |
| 276 | # No valid solution - use fallback (maximize T1L to get T0L at max) |
| 277 | T1L = spec.T1L_max |
| 278 | T0L = T1L + delta |
| 279 | else: |
| 280 | # CRITICAL: Maximize T1L to provide maximum margin above minimum spec |
| 281 | # This is important because measured T1L is often below spec due to |
no test coverage detected