Skip to main content

pcb_toolkit/differential/
types.rs

1use serde::{Deserialize, Serialize};
2
3/// Differential pair protocol presets with target Zdiff.
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
5pub enum DiffProtocol {
6    Ddr2ClkDqs,
7    Ddr3ClkDqs,
8    Ddr4ClkDqs,
9    Usb2x,
10    Usb3x,
11    Lvds,
12    Hdmi,
13    Sata,
14    Ethernet,
15    DisplayPort,
16    DisplayPortEaglelake,
17    DisplayPortCalpella,
18    PcieGen1,
19    PcieGen2,
20    PcieGen3,
21    PcieGen4,
22    SsrxSstx,
23    Custom,
24}
25
26impl DiffProtocol {
27    /// Target differential impedance (Ohms) for this protocol.
28    pub fn target_zdiff(self) -> Option<f64> {
29        match self {
30            Self::Ddr2ClkDqs | Self::Ddr3ClkDqs => Some(100.0),
31            Self::Ddr4ClkDqs => Some(80.0),
32            Self::Usb2x => Some(90.0),
33            Self::Usb3x => Some(90.0),
34            Self::Lvds | Self::Hdmi | Self::Sata | Self::Ethernet => Some(100.0),
35            Self::DisplayPort => Some(100.0),
36            Self::DisplayPortEaglelake | Self::DisplayPortCalpella => Some(85.0),
37            Self::PcieGen1 => Some(100.0),
38            Self::PcieGen2 | Self::PcieGen3 | Self::PcieGen4 => Some(85.0),
39            Self::SsrxSstx => Some(85.0),
40            Self::Custom => None,
41        }
42    }
43}
44
45/// Result of a differential impedance calculation.
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct DifferentialResult {
48    /// Differential impedance (Ohms). Zdiff = 2 × Zodd.
49    pub zdiff: f64,
50    /// Single-ended impedance (Ohms).
51    pub zo: f64,
52    /// Odd-mode impedance (Ohms).
53    pub zodd: f64,
54    /// Even-mode impedance (Ohms).
55    pub zeven: f64,
56    /// Backward coupling coefficient Kb (unterminated).
57    pub kb: f64,
58    /// Unterminated coupling coefficient in dB.
59    pub kb_db: f64,
60    /// Terminated backward coupling coefficient.
61    pub kb_term: f64,
62    /// Terminated coupling coefficient in dB.
63    pub kb_term_db: f64,
64}
65
66/// Compute terminated backward coupling coefficient from unterminated Kb.
67///
68/// Formula: `Kb_term = (1 − √(1 − Kb²)) / Kb`
69///
70/// Saturn validation (PDF p.11): Kb=0.4041 → Kb_term=0.2111
71pub fn kb_terminated(kb: f64) -> f64 {
72    if kb.abs() < 1e-15 {
73        return 0.0;
74    }
75    (1.0 - (1.0 - kb * kb).sqrt()) / kb
76}