pcb_toolkit/impedance/
common.rs1use crate::constants;
7
8pub fn er_eff_static(u: f64, er: f64) -> f64 {
12 let f = if u <= 1.0 {
13 (1.0 + 12.0 / u).powf(-0.5) + 0.04 * (1.0 - u).powi(2)
14 } else {
15 (1.0 + 12.0 / u).powf(-0.5)
16 };
17 (er + 1.0) / 2.0 + (er - 1.0) / 2.0 * f
18}
19
20pub fn effective_width(w: f64, h: f64, t: f64) -> f64 {
25 if t <= 0.0 {
26 return w;
27 }
28 let u = w / h;
29 let dw = if u >= std::f64::consts::FRAC_PI_2 {
30 (t / std::f64::consts::PI) * (1.0 + (2.0 * h / t).ln())
31 } else {
32 (t / std::f64::consts::PI) * (1.0 + (4.0 * std::f64::consts::PI * w / t).ln())
33 };
34 w + dw
35}
36
37pub fn propagation_delay(er_eff: f64) -> f64 {
39 er_eff.sqrt() / constants::SPEED_OF_LIGHT_IN_NS * 1000.0
42}
43
44pub fn inductance_per_length(zo: f64, tpd_ps_per_in: f64) -> f64 {
46 zo * tpd_ps_per_in / 1000.0
48}
49
50pub fn capacitance_per_length(zo: f64, tpd_ps_per_in: f64) -> f64 {
52 (tpd_ps_per_in / 1000.0) / zo * 1000.0
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn er_eff_fr4_wide_trace() {
62 let er_eff = er_eff_static(2.0, 4.6);
64 assert!(er_eff > 3.0 && er_eff < 4.6, "er_eff = {er_eff}");
65 }
66
67 #[test]
68 fn er_eff_narrow_trace() {
69 let narrow = er_eff_static(0.5, 4.6);
71 let wide = er_eff_static(2.0, 4.6);
72 assert!(narrow < wide, "narrow {narrow} should be < wide {wide}");
73 }
74
75 #[test]
76 fn thickness_correction_increases_width() {
77 let w = 5.0; let h = 4.0;
79 let t = 1.4; let we = effective_width(w, h, t);
81 assert!(we > w, "effective width {we} should be > original {w}");
82 }
83}