summaryrefslogtreecommitdiffstats
path: root/src/zmq2farsync
diff options
context:
space:
mode:
Diffstat (limited to 'src/zmq2farsync')
-rw-r--r--src/zmq2farsync/README.md5
-rw-r--r--src/zmq2farsync/zmq2farsync.cpp137
2 files changed, 142 insertions, 0 deletions
diff --git a/src/zmq2farsync/README.md b/src/zmq2farsync/README.md
new file mode 100644
index 0000000..2949f9a
--- /dev/null
+++ b/src/zmq2farsync/README.md
@@ -0,0 +1,5 @@
+Drive a Farsync card from a ZMQ ETI stream
+==========================================
+
+This *zmq2farsync* tool can receive a ZMQ ETI stream from
+ODR-DabMux and drive a Farsync card with it.
diff --git a/src/zmq2farsync/zmq2farsync.cpp b/src/zmq2farsync/zmq2farsync.cpp
new file mode 100644
index 0000000..72f4cc3
--- /dev/null
+++ b/src/zmq2farsync/zmq2farsync.cpp
@@ -0,0 +1,137 @@
+/*
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2011, 2012 Her Majesty the Queen in Right of Canada (Communications
+ Research Center Canada)
+
+ Copyright (C) 2015
+ Matthias P. Braendli, matthias.braendli@mpb.li
+
+ http://www.opendigitalradio.org
+ */
+/*
+ This file is part of ODR-DabMux.
+
+ ODR-DabMux is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ ODR-DabMux is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with ODR-DabMux. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dabOutput/dabOutput.h"
+#include "Log.h"
+#include "zmq.hpp"
+#include <iostream>
+#include <vector>
+
+void usage(void)
+{
+ using namespace std;
+
+ cerr << "Usage:" << endl;
+ cerr << "odr-zmq2farsync <source> <destination>" << endl << endl;
+
+ cerr << "Where" << endl;
+ cerr << " <source> is a ZMQ URL that points to a ODR-DabMux ZMQ output." << endl;
+ cerr << " <destination> is the device information for the FarSync card." << endl << endl;
+ cerr << " The syntax is the same as for ODR-DabMux" << endl;
+}
+
+int main(int argc, char **argv)
+{
+ etiLog.level(info) << "ZMQ2FarSync ETI converter from " <<
+ PACKAGE_NAME << " " <<
+#if defined(GITVERSION)
+ GITVERSION <<
+#else
+ PACKAGE_VERSION <<
+#endif
+ " starting up";
+
+ if (argc != 3) {
+ usage();
+ return 1;
+ }
+
+ const char* source_url = argv[1];
+ const char* destination_device = argv[2];
+
+ etiLog.level(info) << "Opening FarSync card: " << destination_device;
+ DabOutputRaw output;
+ if (output.Open(destination_device) == -1) {
+ etiLog.level(error) <<
+ "Unable to open output ";
+ return -1;
+ }
+
+ etiLog.level(info) << "Opening ZMQ input: " << source_url;
+ zmq::context_t zmq_ctx(1);
+ zmq::socket_t zmq_sock(zmq_ctx, ZMQ_SUB);
+
+ zmq_sock.connect(source_url);
+ zmq_sock.setsockopt(ZMQ_SUBSCRIBE, NULL, 0); // subscribe to all messages
+
+ etiLog.level(info) << "Entering main loop";
+ size_t frame_count = 0;
+ size_t loop_counter = 0;
+ size_t error_count = 0;
+ while (error_count < 10)
+ {
+ zmq::message_t incoming;
+ zmq_sock.recv(&incoming);
+
+ zmq_dab_message_t* dab_msg = (zmq_dab_message_t*)incoming.data();
+
+ if (dab_msg->version != 1) {
+ etiLog.level(error) << "ZeroMQ wrong packet version " << dab_msg->version;
+ error_count++;
+ }
+
+ int offset = sizeof(dab_msg->version) +
+ NUM_FRAMES_PER_ZMQ_MESSAGE * sizeof(*dab_msg->buflen);
+
+ for (int i = 0; i < NUM_FRAMES_PER_ZMQ_MESSAGE; i++) {
+ if (dab_msg->buflen[i] <= 0 ||
+ dab_msg->buflen[i] > 6144)
+ {
+ etiLog.level(error) << "ZeroMQ buffer " << i << " has invalid length " <<
+ dab_msg->buflen[i];
+ error_count++;
+ }
+ else {
+ std::vector<uint8_t> buf(6144, 0x55);
+
+ const int framesize = dab_msg->buflen[i];
+
+ memcpy(&buf.front(),
+ ((uint8_t*)incoming.data()) + offset,
+ framesize);
+
+ offset += framesize;
+
+ if (output.Write(&buf.front(), buf.size()) == -1) {
+ etiLog.level(error) << "Cannot write to output!";
+ error_count++;
+ }
+
+ frame_count++;
+ }
+ }
+
+ loop_counter++;
+ if (loop_counter > 250) {
+ etiLog.level(info) << "Transmitted " << frame_count << " ETI frames";
+ loop_counter = 0;
+ }
+ }
+
+ return error_count > 0 ? 2 : 0;
+}
+