Index: impedance.c =================================================================== --- impedance.c (revision 31809) +++ impedance.c (revision 31810) @@ -64,3 +64,67 @@ return 0; } + +/* As documented at https://chemandy.com/calculators/elliptical-integrals-of-the-first-kind-calculator.htm + refrerence: These recursive equations were originally given for use in calculating the inductance of helical coils and are taken from Miller, H Craig, "Inductance Equation for a Single-Layer Circular Coil" Proceedings of the IEEE, Vol. 75, No 2, February 1987, pp. 256-257. +*/ +static double ellint(double k) +{ + double a = 1.0, b = sqrt(1.0-k*k), c = k, K, lastc = 100; + + if ((k <= -1.0) || (k >= 1.0)) + return 0; + + for(K = M_PI/(2*a); (c != 0) && (c != lastc);) { + double an, bn, cn; + + an = (a+b)/2; + bn = sqrt(a*b); + cn = (a-b)/2; + lastc = c; + a = an; b = bn; c = cn; + K = M_PI/(2*a); + } + return K; +} + +/* Formula from https://chemandy.com/calculators/coplanar-waveguide-with-ground-calculator.htm + ref: Transmission Line Design Handbook by Brian C Wadell, Artech House 1991 page 79 */ +double pcb_impedance_coplanar_waveguide(rnd_coord_t trace_width, rnd_coord_t trace_clearance, rnd_coord_t subst_height, double dielect) +{ + double a = TOM(trace_width), clr = TOM(trace_clearance), h = TOM(subst_height), Er = dielect; + double b = clr+a+clr, z0, eeff, ktmp, k, k_, kl, kl_, ktmp2; + + k = a/b; + k_ = sqrt(1.0 - k*k); + kl = tanh((M_PI * a)/(4.0*h)) / tanh((M_PI * b)/(4.0*h)); + kl_ = sqrt(1.0 - kl*kl); + + k = ellint(k); + k_ = ellint(k_); + kl = ellint(kl); + kl_ = ellint(kl_); + + ktmp = (k_ * kl) / (k * kl_); + eeff = (1.0 + Er * ktmp) / (1.0 + ktmp); + + ktmp2 = k / k_ + kl / kl_; + return ((60.0*M_PI) / sqrt(eeff)) * (1.0 / ktmp2); +} + +const char pcb_acts_impedance_coplanar_waveguide[] = "impedance_coplanar_waveguide(trace_width, trace_clearance, subst_height, dielectric)"; +const char pcb_acth_impedance_coplanar_waveguide[] = "Calculate the approximated impedance of a coplanar_waveguide transmission line, in ohms"; +fgw_error_t pcb_act_impedance_coplanar_waveguide(fgw_arg_t *res, int argc, fgw_arg_t *argv) +{ + rnd_coord_t trace_width, trace_clearance, subst_height; + double dielectric; + + RND_ACT_CONVARG(1, FGW_COORD, impedance_coplanar_waveguide, trace_width = fgw_coord(&argv[1])); + RND_ACT_CONVARG(2, FGW_COORD, impedance_coplanar_waveguide, trace_clearance = fgw_coord(&argv[2])); + RND_ACT_CONVARG(3, FGW_COORD, impedance_coplanar_waveguide, subst_height = fgw_coord(&argv[3])); + RND_ACT_CONVARG(4, FGW_DOUBLE, impedance_coplanar_waveguide, dielectric = argv[4].val.nat_double); + + res->type = FGW_DOUBLE; + res->val.nat_double = pcb_impedance_coplanar_waveguide(trace_width, trace_clearance, subst_height, dielectric); + return 0; +} Index: impedance.h =================================================================== --- impedance.h (revision 31809) +++ impedance.h (revision 31810) @@ -5,3 +5,7 @@ extern const char pcb_acts_impedance_microstrip[]; extern const char pcb_acth_impedance_microstrip[]; fgw_error_t pcb_act_impedance_microstrip(fgw_arg_t *res, int argc, fgw_arg_t *argv); + +extern const char pcb_acts_impedance_coplanar_waveguide[]; +extern const char pcb_acth_impedance_coplanar_waveguide[]; +fgw_error_t pcb_act_impedance_coplanar_waveguide(fgw_arg_t *res, int argc, fgw_arg_t *argv); Index: lib_formula.c =================================================================== --- lib_formula.c (revision 31809) +++ lib_formula.c (revision 31810) @@ -34,6 +34,7 @@ static rnd_action_t lib_formula_action_list[] = { {"impedance_microstrip", pcb_act_impedance_microstrip, pcb_acth_impedance_microstrip, pcb_acts_impedance_microstrip}, + {"impedance_coplanar_waveguide", pcb_act_impedance_coplanar_waveguide, pcb_acth_impedance_coplanar_waveguide, pcb_acts_impedance_coplanar_waveguide}, {"formula_bisect", pcb_act_formula_bisect, pcb_acth_formula_bisect, pcb_acts_formula_bisect} };