Files
fpga_modem/modem/modem_dtmf.py

80 lines
2.5 KiB
Python
Executable File

#!/usr/bin/env python3
import argparse
import sys
import time
import serial
def read_response(port: serial.Serial, timeout_s: float) -> list[str]:
deadline = time.monotonic() + timeout_s
lines: list[str] = []
while time.monotonic() < deadline:
raw = port.readline()
if not raw:
continue
line = raw.decode(errors="replace").strip()
if not line:
continue
lines.append(line)
if line in {"OK", "ERROR"}:
break
return lines
def send_at(port: serial.Serial, command: str, timeout_s: float) -> tuple[bool, list[str]]:
port.write((command + "\r").encode())
port.flush()
lines = read_response(port, timeout_s)
ok = any(line == "OK" for line in lines)
err = any(line == "ERROR" for line in lines)
return ok and not err, lines
def send_and_log(port: serial.Serial, command: str, timeout_s: float) -> tuple[bool, list[str]]:
ok, lines = send_at(port, command, timeout_s)
print(f"> {command}")
for line in lines:
print(f"< {line}")
return ok, lines
def main() -> int:
parser = argparse.ArgumentParser(description="Control an AT modem and send DTMF tones")
parser.add_argument("device", help="Serial device path, e.g. /dev/ttyACM0")
parser.add_argument("--baud", type=int, default=115200, help="Serial baudrate (default: 115200)")
parser.add_argument("--timeout", type=float, default=2.0, help="AT command timeout seconds")
args = parser.parse_args()
try:
with serial.Serial(args.device, args.baud, timeout=0.2, write_timeout=1.0) as port:
port.reset_input_buffer()
port.reset_output_buffer()
# Inicialise
for cmd in ("AT", "ATZ0", "ATE1", "ATX0"):
ok, lines = send_and_log(port, cmd, args.timeout)
if not ok:
print(f"Modem did not accept {cmd}", file=sys.stderr)
return 1
send_and_log(port, "ATS6=0", args.timeout) # Set wait for dial tone time to 0
send_and_log(port, "ATS11=2", args.timeout) # set tone length to 1 ms
send_and_log(port, "ATH1", args.timeout)
while True:
send_and_log(port, "ATDT0123456789;", args.timeout)
send_and_log(port, "ATH0", args.timeout)
except serial.SerialException as exc:
print(f"Serial error: {exc}", file=sys.stderr)
return 1
print("Done")
return 0
if __name__ == "__main__":
raise SystemExit(main())