diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/easydabv3.ini | 37 | ||||
-rw-r--r-- | doc/example.ini | 21 | ||||
-rwxr-xr-x | doc/receive_events.py | 59 | ||||
-rwxr-xr-x | doc/zmq-ctrl/json_remote_server.py | 131 | ||||
-rwxr-xr-x | doc/zmq-ctrl/zmq_remote.py | 22 |
5 files changed, 216 insertions, 54 deletions
diff --git a/doc/easydabv3.ini b/doc/easydabv3.ini deleted file mode 100644 index 5f0103f..0000000 --- a/doc/easydabv3.ini +++ /dev/null @@ -1,37 +0,0 @@ -; This sample configuration is useful if ODR-DabMod is compiled -; with --enable-easydabv3 - -[remotecontrol] -zmqctrl=1 -zmqctrlendpoint=tcp://127.0.0.1:9400 -; There is no telnet RC available in this build - - -[log] -syslog=0 -filelog=0 -filename=odr-dabmod.log - -[input] -transport=zeromq -source=tcp://localhost:9100 -max_frames_queued=400 - -; There are no [modulator], [cfr], [firfilter], [poly] nor [tii] sections - -[output] -output=file - -[fileoutput] -; to be confirmed -format=complexf - -filename=/dev/csdiof1 - -show_metadata=0 -; TODO add option for writing out timestamps to csdiof1 - -[delaymanagement] -synchronous=0 -mutenotimestamps=0 -offset=1.002 diff --git a/doc/example.ini b/doc/example.ini index aca7634..f009fbe 100644 --- a/doc/example.ini +++ b/doc/example.ini @@ -69,13 +69,6 @@ loop=0 ;transport=tcp ;source=localhost:9200 -; When recieving data using ZeroMQ, the source is the URI to be used -;transport=zeromq -;source=tcp://localhost:9100 -; The option max_frames_queued defines the maximum number of ETI frames -; (frame duration: 24ms) that can be in the input queue -;max_frames_queued=100 - [modulator] ; Mode 'fix' uses a fixed factor and is really not recommended. It is more ; useful on an academic perspective for people trying to understand the DAB @@ -164,7 +157,7 @@ enabled=0 polycoeffile=polyCoefs [output] -; choose output: possible values: uhd, file, zmq, soapysdr, limesdr, bladerf +; choose output: possible values: uhd, file, zmq, dexter, soapysdr, limesdr, bladerf output=uhd [fileoutput] @@ -322,6 +315,18 @@ channel=13C ; Set to 0 to disable ;dpd_port=50055 +[dexteroutput] +txgain=65535 + +; channel/frequency is applied to ad9957.center_frequency +;frequency=234208000 +channel=13C + +; lo offset is applied to dexter_dsp_tx.frequency0 +lo_offset=0 + +max_gps_holdover_time=3600 + [limeoutput] ; Lime output directly runs against the LMS device driver. It does not support SFN nor predistortion. device= diff --git a/doc/receive_events.py b/doc/receive_events.py new file mode 100755 index 0000000..bfd6f86 --- /dev/null +++ b/doc/receive_events.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# +# This is an example program that shows +# how to receive runtime events from ODR-DabMod +# +# LICENSE: see bottom of file + +import sys +import zmq +import json +from pprint import pprint + +context = zmq.Context() +sock = context.socket(zmq.SUB) + +ep = "tcp://127.0.0.1:5556" +print(f"Receive from {ep}") +sock.connect(ep) + +# subscribe to all events +sock.setsockopt(zmq.SUBSCRIBE, bytes([])) + +while True: + parts = sock.recv_multipart() + if len(parts) == 2: + print("Received event '{}'".format(parts[0].decode())) + pprint(json.loads(parts[1].decode())) + + else: + print("Received strange event:") + pprint(parts) + + print() + + +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to <http://unlicense.org> diff --git a/doc/zmq-ctrl/json_remote_server.py b/doc/zmq-ctrl/json_remote_server.py new file mode 100755 index 0000000..728cf7c --- /dev/null +++ b/doc/zmq-ctrl/json_remote_server.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# +# This is an example program that illustrates +# how to interact with the zeromq remote control +# using JSON. +# +# LICENSE: see bottom of file + +import sys +import zmq +from pprint import pprint +import json +import re +from http.server import BaseHTTPRequestHandler, HTTPServer +import time + +re_url = re.compile(r"/([a-zA-Z0-9]+).json") + +ZMQ_REMOTE = "tcp://localhost:9400" +HTTP_HOSTNAME = "localhost" +HTTP_PORT = 8080 + +class DabMuxServer(BaseHTTPRequestHandler): + def err500(self, message): + self.send_response(500) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(json.dumps({"error": message}).encode()) + + def do_GET(self): + m = re_url.match(self.path) + if m: + sock = context.socket(zmq.REQ) + poller = zmq.Poller() + poller.register(sock, zmq.POLLIN) + sock.connect(ZMQ_REMOTE) + + sock.send(b"ping") + socks = dict(poller.poll(1000)) + if socks: + if socks.get(sock) == zmq.POLLIN: + data = sock.recv() + if data != b"ok": + print(f"Received {data} to ping!", file=sys.stderr) + self.err500("ping failure") + return + else: + print("ZMQ error: ping timeout", file=sys.stderr) + self.err500("ping timeout") + return + + sock.send(b"showjson", flags=zmq.SNDMORE) + sock.send(m.group(1).encode()) + + socks = dict(poller.poll(1000)) + if socks: + if socks.get(sock) == zmq.POLLIN: + data = sock.recv_multipart() + print("Received: {}".format(len(data)), file=sys.stderr) + parts = [] + for i, part_data in enumerate(data): + part = part_data.decode() + print(" RX {}: {}".format(i, part.replace('\n',' ')), file=sys.stderr) + + if i == 0 and part != "fail": + self.send_response(200) + self.send_header("Content-type", "application/json") + self.end_headers() + self.wfile.write(part_data) + return + parts.append(part) + self.err500("data error " + " ".join(parts)) + return + + else: + print("ZMQ error: timeout", file=sys.stderr) + self.err500("timeout") + return + else: + self.send_response(200) + self.send_header("Content-type", "text/html") + self.end_headers() + self.wfile.write("""<html><head><title>ODR-DabMod RC HTTP server</title></head>\n""".encode()) + self.wfile.write("""<body>\n""".encode()) + for mod in ("sdr", "tist", "modulator", "tii", "ofdm", "gain", "guardinterval"): + self.wfile.write(f"""<p><a href="{mod}.json">{mod}.json</a></p>\n""".encode()) + self.wfile.write("""</body></html>\n""".encode()) + + +if __name__ == "__main__": + context = zmq.Context() + + webServer = HTTPServer((HTTP_HOSTNAME, HTTP_PORT), DabMuxServer) + print("Server started http://%s:%s" % (HTTP_HOSTNAME, HTTP_PORT)) + + try: + webServer.serve_forever() + except KeyboardInterrupt: + pass + + webServer.server_close() + + context.destroy(linger=5) + + +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# For more information, please refer to <http://unlicense.org> + + diff --git a/doc/zmq-ctrl/zmq_remote.py b/doc/zmq-ctrl/zmq_remote.py index 56465d3..7581575 100755 --- a/doc/zmq-ctrl/zmq_remote.py +++ b/doc/zmq-ctrl/zmq_remote.py @@ -16,7 +16,7 @@ poller = zmq.Poller() poller.register(sock, zmq.POLLIN) if len(sys.argv) < 2: - print("Usage: program url cmd [args...]") + print("Usage: program url cmd [args...]", file=sys.stderr) sys.exit(1) sock.connect(sys.argv[1]) @@ -25,7 +25,7 @@ message_parts = sys.argv[2:] # first do a ping test -print("ping") +print("ping", file=sys.stderr) sock.send(b"ping") socks = dict(poller.poll(1000)) @@ -33,9 +33,9 @@ if socks: if socks.get(sock) == zmq.POLLIN: data = sock.recv_multipart() - print("Received: {}".format(len(data))) + print("Received: {}".format(len(data)), file=sys.stderr) for i,part in enumerate(data): - print(" {}".format(part)) + print(" {}".format(part), file=sys.stderr) for i, part in enumerate(message_parts): if i == len(message_parts) - 1: @@ -43,18 +43,22 @@ if socks: else: f = zmq.SNDMORE - print("Send {}({}): '{}'".format(i, f, part)) + print("Send {}({}): '{}'".format(i, f, part), file=sys.stderr) sock.send(part.encode(), flags=f) data = sock.recv_multipart() - print("Received: {}".format(len(data))) - for i,part in enumerate(data): - print(" RX {}: {}".format(i, part.decode().replace('\n',' '))) + print("Received: {}".format(len(data)), file=sys.stderr) + for i, part in enumerate(data): + if message_parts[0] == 'showjson': + # This allows you to pipe the JSON into another tool + print(part.decode()) + else: + print(" RX {}: {}".format(i, part.decode().replace('\n',' ')), file=sys.stderr) else: - print("ZMQ error: timeout") + print("ZMQ error: timeout", file=sys.stderr) context.destroy(linger=5) # This is free and unencumbered software released into the public domain. |