Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
2126c3284This file is pinned to the selected release. Download the original to open it in your design tool.
"""Unit conversions engineers reach for constantly.
References:
* Length: 1 inch = 25.4 mm **exactly** (International Yard and Pound
Agreement, 1959; NIST SP 811 §B.6). 1 mil = 1/1000 inch.
* Power/level: dBm is dB referenced to 1 mW (IEEE Std 100); P = 10^((dBm−30)/10) W;
V_rms = √(P·Z0).
* Copper weight: 1 oz/ft² foil — industry nominal thickness 1.37 mil
(34.8 µm), the value IPC-2221/IPC-4562 usage assumes; the pure-copper
physical equivalent is 34.06 µm (28.3495 g over 929.03 cm² at
ρ = 8.96 g/cm³). Both are reported.
"""
from __future__ import annotations
import math
from .registry import CalcError, Param, Result, register
_IN = 25.4e-3 # m, exact
_OZ_UM_NOMINAL = 34.80 # µm per oz/ft² (1.37 mil industry nominal)
_OZ_UM_PURE = 34.06 # µm per oz/ft² (pure Cu, ρ = 8.96 g/cm³)
@register(
"convert-length", "Length: mm ↔ mil ↔ inch ↔ µm", "convert",
"1 in = 25.4 mm exactly (International Yard & Pound Agreement 1959; "
"NIST SP 811 §B.6)",
(Param("value", "", "the number to convert"),
Param("unit", "", "unit of the given value", default="mm",
choices=("mm", "mil", "inch", "um", "m"))),
)
def _calc_convert_length(value: float, unit: str) -> list[Result]:
meters = value * {"mm": 1e-3, "mil": _IN / 1000, "inch": _IN,
"um": 1e-6, "m": 1.0}[unit]
return [Result("m", meters, "m"),
Result("mm", meters * 1e3, ""),
Result("um", meters * 1e6, ""),
Result("mil", meters / (_IN / 1000), ""),
Result("inch", meters / _IN, "")]
@register(
"convert-power", "Level: dBm ↔ W ↔ V(rms) at Z0", "convert",
"dBm = dB re 1 mW (IEEE Std 100); P = 10^((dBm−30)/10) W; Vrms = √(P·Z0)",
(Param("dbm", "dBm", "level (give exactly one of dbm/w/vrms)", default=0.0),
Param("w", "W", "power", default=0.0),
Param("vrms", "V", "RMS voltage across Z0", default=0.0),
Param("z0", "Ω", "reference impedance", default=50.0)),
)
def _calc_convert_power(dbm: float, w: float, vrms: float, z0: float) -> list[Result]:
given = [n for n, v in (("w", w), ("vrms", vrms)) if v]
if len(given) > 1:
raise CalcError("give only one of dbm / w / vrms")
if w:
p = w
elif vrms:
p = vrms * vrms / z0
else:
p = 10 ** ((dbm - 30) / 10)
return [Result("dbm", 10 * math.log10(p) + 30, "dBm"),
Result("w", p, "W"),
Result("vrms", math.sqrt(p * z0), "V", f"across {z0:g} Ω"),
Result("vpeak", math.sqrt(2 * p * z0), "V", "sine peak"),
Result("vpp", 2 * math.sqrt(2 * p * z0), "V", "sine peak-to-peak")]
@register(
"convert-copper", "Copper weight: oz/ft² ↔ thickness", "convert",
"Industry nominal 1 oz/ft² = 1.37 mil = 34.8 µm (IPC-2221/IPC-4562 "
"usage); pure-Cu physical equivalent 34.06 µm (ρ = 8.96 g/cm³)",
(Param("oz", "oz/ft²", "copper weight (0 if giving thickness)", default=0.0),
Param("um", "µm", "thickness in µm (0 if giving oz)", default=0.0)),
)
def _calc_convert_copper(oz: float, um: float) -> list[Result]:
if (oz > 0) == (um > 0):
raise CalcError("give exactly one of oz / um")
if um:
oz = um / _OZ_UM_NOMINAL
t_nom = oz * _OZ_UM_NOMINAL
return [Result("oz", oz, "oz/ft²"),
Result("thickness_nominal", t_nom * 1e-6, "m",
f"{t_nom:.1f} µm = {t_nom / 25.4:.2f} mil (industry nominal)"),
Result("thickness_pure_cu", oz * _OZ_UM_PURE * 1e-6, "m",
"from areal density at ρ = 8.96 g/cm³")]