The constraints
- 5V (~500mA) power from phone
- 1W RF output required
- Very compact with less "moving" parts
- 14 MHz capable
The design
We purposefully utilize "high Rds" EPC GaN parts with very low Qgs.

Simulation Results
Power consumption: Around 300mA @ 5V.
pout: AVG(v(out)*i(r3))=1.0606 FROM 5e-05 TO 0.0001
pin: AVG(-5*i(v3))=1.38209 FROM 5e-05 TO 0.0001
isupply: AVG(-i(v3))=0.276418 FROM 5e-05 TO 0.0001
eff: pout/pin*100=76.7393
Cost
Cost: < 500 INR.
Time to build
This will require factory assembly ;)
Bonus
#!/usr/bin/env python3
"""
lmatch.py - L-network impedance matching calculator.
Examples:
./lmatch.py 14e6 12.5 50
./lmatch.py 14 12.5 50 --freq-unit MHz --series E24 --ltspice
"""
import argparse
import math
from dataclasses import dataclass
E_SERIES = {
"E6": [10, 15, 22, 33, 47, 68],
"E12": [10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82],
"E24": [10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30,
33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91],
"E48": [100,105,110,115,121,127,133,140,147,154,162,169,
178,187,196,205,215,226,237,249,261,274,287,301,
316,332,348,365,383,402,422,442,464,487,511,536,
562,590,619,649,681,715,750,787,825,866,909,953],
"E96": [100,102,105,107,110,113,115,118,121,124,127,130,
133,137,140,143,147,150,154,158,162,165,169,174,
178,182,187,191,196,200,205,210,215,221,226,232,
237,243,249,255,261,267,274,280,287,294,301,309,
316,324,332,340,348,357,365,374,383,392,402,412,
422,432,442,453,464,475,487,499,511,523,536,549,
562,576,590,604,619,634,649,665,681,698,715,732,
750,768,787,806,825,845,866,887,909,931,953,976],
}
@dataclass
class Part:
kind: str
value: float
x_ohms: float
def nearest_preferred(value: float, series: str) -> float:
if value <= 0:
raise ValueError("value must be positive")
series = series.upper()
vals = E_SERIES[series]
decade = 10 ** math.floor(math.log10(value))
candidates = []
for d in (decade / 10, decade, decade * 10):
for v in vals:
base = v / 10 if series in ("E6", "E12", "E24") else v / 100
candidates.append(base * d)
return min(candidates, key=lambda x: abs(math.log(x / value)))
def fmt_value(kind: str, value: float) -> str:
if kind == "L":
if value < 1e-6:
return f"{value*1e9:.3g} nH"
if value < 1e-3:
return f"{value*1e6:.3g} uH"
return f"{value*1e3:.3g} mH"
if value < 1e-9:
return f"{value*1e12:.3g} pF"
if value < 1e-6:
return f"{value*1e9:.3g} nF"
return f"{value*1e6:.3g} uF"
def spice_value(kind: str, value: float) -> str:
if kind == "L":
if value < 1e-6:
return f"{value*1e9:.6g}n"
if value < 1e-3:
return f"{value*1e6:.6g}u"
return f"{value*1e3:.6g}m"
if value < 1e-9:
return f"{value*1e12:.6g}p"
if value < 1e-6:
return f"{value*1e9:.6g}n"
return f"{value*1e6:.6g}u"
def lmatch(rs: float, rl: float, freq_hz: float):
if rs <= 0 or rl <= 0 or freq_hz <= 0:
raise ValueError("rs, rl, and frequency must be positive")
if math.isclose(rs, rl):
return []
w = 2 * math.pi * freq_hz
r_low = min(rs, rl)
r_high = max(rs, rl)
q = math.sqrt(r_high / r_low - 1)
xs = q * r_low
xp = r_high / q
def cap(x): return 1 / (w * x)
def ind(x): return x / w
if rl > rs:
placement = "series first, shunt across load side"
else:
placement = "shunt across source side, then series"
return [
{"name": "Low-pass", "placement": placement, "q": q,
"series": Part("L", ind(xs), xs), "shunt": Part("C", cap(xp), -xp)},
{"name": "High-pass", "placement": placement, "q": q,
"series": Part("C", cap(xs), -xs), "shunt": Part("L", ind(xp), xp)},
]
def freq_to_hz(freq: float, unit: str) -> float:
return freq * {"Hz": 1, "kHz": 1e3, "MHz": 1e6, "GHz": 1e9}[unit]
def print_match(m, series_name, rounded, ltspice):
print(f"{m['name']}")
print("-" * len(m["name"]))
print(f"Placement : {m['placement']}")
print(f"Q : {m['q']:.4g}")
for label in ("series", "shunt"):
p = m[label]
shown = nearest_preferred(p.value, series_name) if rounded else p.value
arrow = f" -> {fmt_value(p.kind, shown)} ({series_name.upper()})" if rounded else ""
print(f"{label.capitalize():9}: {p.kind} {fmt_value(p.kind, p.value)}{arrow} X = {p.x_ohms:+.3g} ohm")
if ltspice:
s = m["series"]
p = m["shunt"]
sv = nearest_preferred(s.value, series_name) if rounded else s.value
pv = nearest_preferred(p.value, series_name) if rounded else p.value
print("\nLTspice fragment:")
print(f"{s.kind}1 in out {spice_value(s.kind, sv)}")
print(f"{p.kind}2 out 0 {spice_value(p.kind, pv)}")
print()
def main():
parser = argparse.ArgumentParser(description="LC L-match calculator with preferred-value rounding.")
parser.add_argument("frequency", type=float, help="Frequency, default unit Hz")
parser.add_argument("rs", type=float, help="Source resistance in ohms")
parser.add_argument("rl", type=float, help="Load resistance in ohms")
parser.add_argument("--freq-unit", choices=["Hz", "kHz", "MHz", "GHz"], default="Hz")
parser.add_argument("--series", choices=sorted(E_SERIES), default="E24",
help="Preferred value series for rounding")
parser.add_argument("--exact", action="store_true", help="Do not round to preferred values")
parser.add_argument("--ltspice", action="store_true", help="Print LTspice netlist fragments")
args = parser.parse_args()
f = freq_to_hz(args.frequency, args.freq_unit)
matches = lmatch(args.rs, args.rl, f)
print(f"Matching {args.rs:g} ohm -> {args.rl:g} ohm @ {f/1e6:.6g} MHz\n")
if not matches:
print("Source and load are already equal; no L-match needed.")
return
for m in matches:
print_match(m, args.series, not args.exact, args.ltspice)
if __name__ == "__main__":
main()
% python3 ./lmatch.py 14 15 50 --freq-unit MHz --series E24 --ltspice
Matching 15 ohm -> 50 ohm @ 14 MHz
Low-pass
--------
Placement : series first, shunt across load side
Q : 1.528
Series : L 260 nH -> 270 nH (E24) X = +22.9 ohm
Shunt : C 347 pF -> 360 pF (E24) X = -32.7 ohm
LTspice fragment:
L1 in out 270n
C2 out 0 360p
High-pass
---------
Placement : series first, shunt across load side
Q : 1.528
Series : C 496 pF -> 510 pF (E24) X = -22.9 ohm
Shunt : L 372 nH -> 360 nH (E24) X = +32.7 ohm
LTspice fragment:
C1 in out 510p
L2 out 0 360n