Skip to content

Commit 0417510

Browse files
committed
power meter added
1 parent b3ec394 commit 0417510

1 file changed

Lines changed: 63 additions & 0 deletions

File tree

hackrfpy/examples/power_meter.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#! /usr/bin/python3
2+
##--------------------------------------------------------------------\
3+
# hackrfpy 'examples/power_meter.py'
4+
# Live signal-strength meter at one frequency, using capture_callback.
5+
# Demonstrates the callback API (the binder-style inverted loop) on a real
6+
# stream: register a function, get each decoded complex64 block as it
7+
# arrives, print a rolling power reading. Read-only / receive-only.
8+
#
9+
# Usage:
10+
# uv run python examples/power_meter.py --freq 100e6
11+
# uv run python examples/power_meter.py --freq 433.92e6 --rate 2e6
12+
##--------------------------------------------------------------------\
13+
import argparse
14+
import sys
15+
import numpy as np
16+
from hackrfpy import HackRF
17+
18+
19+
def main():
20+
p = argparse.ArgumentParser(description="Live power meter (read-only).")
21+
p.add_argument("--freq", default="100e6", help="center frequency Hz")
22+
p.add_argument("--rate", default="2e6", help="sample rate sps")
23+
p.add_argument("--tools-dir", default=None)
24+
args = p.parse_args()
25+
freq, rate = float(args.freq), float(args.rate)
26+
27+
h = HackRF(tools_dir=args.tools_dir)
28+
det = h.detect()
29+
if not det["ready"]:
30+
print(f"no usable HackRF: {det['problem']}", file=sys.stderr)
31+
return 1
32+
33+
print(f"[*] power meter @ {freq/1e6:g} MHz (Ctrl-C to stop)\n")
34+
35+
# bar-graph scale in dBFS: roughly noise floor (-90) to full-scale (0)
36+
LO, HI, WIDTH = -90.0, 0.0, 40
37+
38+
def on_block(iq, total):
39+
if len(iq) == 0:
40+
return
41+
# raw dBFS, plus the gain-normalized relative reading (Level 1): the
42+
# relative value is comparable across gain settings; pass offset_db
43+
# from a calibration run (see examples/calibrate.py) to approximate dBm.
44+
db = h.power_dbfs(iq)
45+
rel = h.relative_power_db(db, lna=16, vga=20, amp=False)
46+
frac = max(0.0, min(1.0, (db - LO) / (HI - LO)))
47+
bar = "#" * int(frac * WIDTH)
48+
sys.stdout.write(f"\r {db:7.1f} dBFS (rel {rel:7.1f} dB) "
49+
f"|{bar:<{WIDTH}}|")
50+
sys.stdout.flush()
51+
52+
try:
53+
# callback fires per block; we never reach a sample cap, so it runs
54+
# until Ctrl-C, and the context manager inside reaps the child.
55+
h.capture_callback(freq, rate, on_block=on_block)
56+
except KeyboardInterrupt:
57+
pass
58+
print("\n[*] stopped")
59+
return 0
60+
61+
62+
if __name__ == "__main__":
63+
sys.exit(main())

0 commit comments

Comments
 (0)