diff options
Diffstat (limited to 'src/zmq2farsync')
-rw-r--r-- | src/zmq2farsync/README.md | 5 | ||||
-rw-r--r-- | src/zmq2farsync/zmq2farsync.cpp | 137 |
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; +} + |