pico-sdr/util/bridge.py

102 lines
2.4 KiB
Python
Executable file

#!/usr/bin/env python
import struct
from socket import (AF_INET, MSG_DONTWAIT, SO_REUSEADDR, SO_SNDBUF,
SOCK_STREAM, SOL_SOCKET, socket)
import click
import serial
COMMAND_NAMES = [
"reset",
"tune_freq",
"sample_rate",
"manual_gain",
"gain",
"ppm_offset",
"if_gain",
"test_mode",
"agc",
"direct_sampling",
"offset_tuning",
"11",
"12",
"gain_index",
"bias_tee",
]
def describe(cmd: int, arg: int):
try:
print("->", COMMAND_NAMES[cmd], arg)
except IndexError:
print("->", cmd, arg)
@click.command()
@click.option("-f", "--frequency", default=88200000, help="Frequency to tune to")
@click.option("-d", "--device", default="/dev/ttyACM0", help="Serial port device")
def bridge(frequency, device):
sock = socket(AF_INET, SOCK_STREAM)
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
sock.setsockopt(SOL_SOCKET, SO_SNDBUF, 1024 * 100)
print("Posing as rtl_tcp at tcp://127.0.0.1:1234")
sock.bind(("127.0.0.1", 1234))
sock.listen(3)
while True:
peer, addr = sock.accept()
print("Client connected:", addr)
with serial.Serial(device, baudrate=10_000_000, timeout=0.1) as fp:
print(f"Starting RX @ {frequency}")
# Remove any leftovers.
while fp.read(64):
fp.write(b"\x00")
fp.flush()
fp.write(struct.pack(">BL", 1, int(frequency)))
fp.flush()
print("Begin")
header = fp.read(12)
if header:
peer.send(header)
try:
cmd = b""
while True:
try:
cmd += peer.recv(1, MSG_DONTWAIT)
except BlockingIOError:
pass
while len(cmd) >= 5:
fp.write(cmd[:5])
info = struct.unpack(">Bl", cmd[:6])
describe(*info)
cmd = cmd[5:]
data = fp.read(64)
if data:
peer.send(data)
except ConnectionError:
pass
except KeyboardInterrupt:
pass
finally:
fp.write(b"\x00")
fp.flush()
print("Bye.")
if __name__ == "__main__":
bridge()