use crate::CalcError;
use crate::impedance::{common, types::ImpedanceResult};
pub struct MicrostripInput {
pub width: f64,
pub height: f64,
pub thickness: f64,
pub er: f64,
pub frequency: f64,
}
pub fn calculate(input: &MicrostripInput) -> Result<ImpedanceResult, CalcError> {
let MicrostripInput { width, height, thickness, er, .. } = *input;
if width <= 0.0 {
return Err(CalcError::NegativeDimension { name: "width", value: width });
}
if height <= 0.0 {
return Err(CalcError::NegativeDimension { name: "height", value: height });
}
if er < 1.0 {
return Err(CalcError::OutOfRange {
name: "er",
value: er,
expected: ">= 1.0",
});
}
let we = common::effective_width(width, height, thickness);
let u = we / height;
let er_eff = common::er_eff_static(u, er);
let zo = if u <= 1.0 {
(60.0 / er_eff.sqrt()) * (8.0 * height / we + we / (4.0 * height)).ln()
} else {
(120.0 * std::f64::consts::PI / er_eff.sqrt())
/ (u + 1.393 + 0.667 * (u + 1.444).ln())
};
let tpd = common::propagation_delay(er_eff);
let lo = common::inductance_per_length(zo, tpd);
let co = common::capacitance_per_length(zo, tpd);
Ok(ImpedanceResult {
zo,
er_eff,
tpd_ps_per_in: tpd,
lo_nh_per_in: lo,
co_pf_per_in: co,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn basic_microstrip() {
let result = calculate(&MicrostripInput {
width: 10.0,
height: 5.0,
thickness: 1.4,
er: 4.6,
frequency: 0.0,
})
.unwrap();
assert!(result.zo > 20.0 && result.zo < 80.0, "Zo = {}", result.zo);
assert!(result.er_eff > 1.0 && result.er_eff < 4.6, "Er_eff = {}", result.er_eff);
assert!(result.tpd_ps_per_in > 0.0);
assert!(result.lo_nh_per_in > 0.0);
assert!(result.co_pf_per_in > 0.0);
}
#[test]
fn narrow_trace_higher_impedance() {
let narrow = calculate(&MicrostripInput {
width: 3.0,
height: 5.0,
thickness: 1.4,
er: 4.6,
frequency: 0.0,
})
.unwrap();
let wide = calculate(&MicrostripInput {
width: 20.0,
height: 5.0,
thickness: 1.4,
er: 4.6,
frequency: 0.0,
})
.unwrap();
assert!(
narrow.zo > wide.zo,
"narrow Zo {} should be > wide Zo {}",
narrow.zo,
wide.zo
);
}
#[test]
fn rejects_negative_width() {
let result = calculate(&MicrostripInput {
width: -1.0,
height: 5.0,
thickness: 1.4,
er: 4.6,
frequency: 0.0,
});
assert!(result.is_err());
}
}