pcb_toolkit/
wavelength.rs1use serde::{Deserialize, Serialize};
6
7use crate::CalcError;
8
9const C_IN_PER_NS: f64 = 11.803;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct WavelengthResult {
15 pub lambda_inches: f64,
17 pub lambda_half_inches: f64,
19 pub lambda_quarter_inches: f64,
21 pub lambda_seventh_inches: f64,
23 pub lambda_tenth_inches: f64,
25 pub lambda_twentieth_inches: f64,
27 pub period_ns: f64,
29}
30
31pub fn wavelength(freq_hz: f64, er_eff: f64) -> Result<WavelengthResult, CalcError> {
40 if freq_hz <= 0.0 {
41 return Err(CalcError::OutOfRange {
42 name: "freq_hz",
43 value: freq_hz,
44 expected: "> 0",
45 });
46 }
47 if er_eff < 1.0 {
48 return Err(CalcError::OutOfRange {
49 name: "er_eff",
50 value: er_eff,
51 expected: ">= 1.0",
52 });
53 }
54
55 let period_ns = 1.0 / freq_hz * 1e9;
56 let lambda_inches = C_IN_PER_NS * period_ns / er_eff.sqrt();
58
59 Ok(WavelengthResult {
60 lambda_inches,
61 lambda_half_inches: lambda_inches / 2.0,
62 lambda_quarter_inches: lambda_inches / 4.0,
63 lambda_seventh_inches: lambda_inches / 7.0,
64 lambda_tenth_inches: lambda_inches / 10.0,
65 lambda_twentieth_inches: lambda_inches / 20.0,
66 period_ns,
67 })
68}
69
70#[cfg(test)]
71mod tests {
72 use approx::assert_relative_eq;
73
74 use super::*;
75
76 #[test]
81 fn saturn_notes_100mhz_er4() {
82 let result = wavelength(100e6, 4.0).unwrap();
83 assert_relative_eq!(result.period_ns, 10.0, epsilon = 1e-9);
84 assert_relative_eq!(result.lambda_inches, 59.015, epsilon = 1e-2);
85 assert_relative_eq!(result.lambda_half_inches, result.lambda_inches / 2.0, epsilon = 1e-10);
86 assert_relative_eq!(result.lambda_quarter_inches, result.lambda_inches / 4.0, epsilon = 1e-10);
87 assert_relative_eq!(result.lambda_seventh_inches, result.lambda_inches / 7.0, epsilon = 1e-10);
88 assert_relative_eq!(result.lambda_tenth_inches, result.lambda_inches / 10.0, epsilon = 1e-10);
89 assert_relative_eq!(result.lambda_twentieth_inches, result.lambda_inches / 20.0, epsilon = 1e-10);
90 }
91
92 #[test]
93 fn error_on_zero_freq() {
94 assert!(wavelength(0.0, 4.0).is_err());
95 }
96
97 #[test]
98 fn error_on_er_below_one() {
99 assert!(wavelength(100e6, 0.5).is_err());
100 }
101
102 #[test]
103 fn vacuum_er1() {
104 let result = wavelength(1e9, 1.0).unwrap();
105 assert_relative_eq!(result.lambda_inches, 11.803, epsilon = 1e-3);
107 }
108}