diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | lib/Json.cpp | 4 | ||||
-rw-r--r-- | lib/Json.h | 4 | ||||
-rw-r--r-- | lib/Socket.cpp | 22 | ||||
-rw-r--r-- | lib/Socket.h | 10 | ||||
-rw-r--r-- | lib/ThreadsafeQueue.h | 38 | ||||
-rw-r--r-- | lib/fec/decode_rs.h | 12 | ||||
-rw-r--r-- | src/Buffer.h | 3 | ||||
-rw-r--r-- | src/GainControl.cpp | 24 | ||||
-rw-r--r-- | src/Utils.cpp | 4 |
11 files changed, 88 insertions, 42 deletions
@@ -1,8 +1,8 @@ This file contains information about the changes done to ODR-DabMod in this repository -2023-11-21: Matthias P. Braendli <matthias@mpb.li> - (upcoming release): +2025-02-26: Matthias P. Braendli <matthias@mpb.li> + (v3.0.0): Add support for the PrecisionWave DEXTER Modulator. Improve timestamp decoding and handling. Fix TII carrier levels. @@ -11,6 +11,7 @@ ODR-DabMod in this repository Remove EasyDABv3 support. Remove ZeroMQ input. Require C++17. + v2.7.0 retracted. 2022-04-20: Matthias P. Braendli <matthias@mpb.li> (v2.6.0): diff --git a/configure.ac b/configure.ac index 5c3de90..46bbaf1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Her Majesty the # Queen in Right of Canada (Communications Research Center Canada) -# Copyright (C) 2023 Matthias P. Braendli, http://opendigitalradio.org +# Copyright (C) 2025 Matthias P. Braendli, http://opendigitalradio.org # This file is part of ODR-DabMod. # @@ -19,7 +19,7 @@ # along with ODR-DabMod. If not, see <http://www.gnu.org/licenses/>. AC_PREREQ([2.69]) -AC_INIT([ODR-DabMod],[2.6.0],[matthias.braendli@mpb.li]) +AC_INIT([ODR-DabMod],[3.0.0],[matthias.braendli@mpb.li]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_TARGET diff --git a/lib/Json.cpp b/lib/Json.cpp index 361a149..ee33671 100644 --- a/lib/Json.cpp +++ b/lib/Json.cpp @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2023 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -27,7 +27,7 @@ #include <sstream> #include <iomanip> #include <string> -#include <algorithm> +#include <stdexcept> #include "Json.h" @@ -3,7 +3,7 @@ Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2023 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li http://www.opendigitalradio.org @@ -34,10 +34,10 @@ #include <vector> #include <memory> #include <optional> -#include <stdexcept> #include <string> #include <unordered_map> #include <variant> +#include <cstdint> namespace json { diff --git a/lib/Socket.cpp b/lib/Socket.cpp index 938b573..5c920d7 100644 --- a/lib/Socket.cpp +++ b/lib/Socket.cpp @@ -24,6 +24,7 @@ #include "Socket.h" +#include <numeric> #include <stdexcept> #include <cstdio> #include <cstring> @@ -1063,6 +1064,17 @@ void TCPConnection::process() #endif } +TCPConnection::stats_t TCPConnection::get_stats() const +{ + TCPConnection::stats_t s; + const vector<size_t> buffer_sizes = queue.map<size_t>( + [](const vector<uint8_t>& vec) { return vec.size(); } + ); + + s.buffer_fullness = std::accumulate(buffer_sizes.cbegin(), buffer_sizes.cend(), 0); + s.remote_address = m_sock.get_remote_address(); + return s; +} TCPDataDispatcher::TCPDataDispatcher(size_t max_queue_size, size_t buffers_to_preroll) : m_max_queue_size(max_queue_size), @@ -1136,6 +1148,16 @@ void TCPDataDispatcher::process() } } + +std::vector<TCPConnection::stats_t> TCPDataDispatcher::get_stats() const +{ + std::vector<TCPConnection::stats_t> s; + for (const auto& conn : m_connections) { + s.push_back(conn.get_stats()); + } + return s; +} + TCPReceiveServer::TCPReceiveServer(size_t blocksize) : m_blocksize(blocksize) { diff --git a/lib/Socket.h b/lib/Socket.h index 7709145..29b618a 100644 --- a/lib/Socket.h +++ b/lib/Socket.h @@ -213,6 +213,8 @@ class TCPSocket { SOCKET get_sockfd() const { return m_sock; } + InetAddress get_remote_address() const { return m_remote_address; } + private: explicit TCPSocket(int sockfd); explicit TCPSocket(int sockfd, InetAddress remote_address); @@ -254,6 +256,12 @@ class TCPConnection ThreadsafeQueue<std::vector<uint8_t> > queue; + struct stats_t { + size_t buffer_fullness = 0; + InetAddress remote_address; + }; + stats_t get_stats() const; + private: std::atomic<bool> m_running; std::thread m_sender_thread; @@ -276,6 +284,8 @@ class TCPDataDispatcher void start(int port, const std::string& address); void write(const std::vector<uint8_t>& data); + std::vector<TCPConnection::stats_t> get_stats() const; + private: void process(); diff --git a/lib/ThreadsafeQueue.h b/lib/ThreadsafeQueue.h index 8b385d6..13bc19e 100644 --- a/lib/ThreadsafeQueue.h +++ b/lib/ThreadsafeQueue.h @@ -2,7 +2,7 @@ Copyright (C) 2007, 2008, 2009, 2010, 2011 Her Majesty the Queen in Right of Canada (Communications Research Center Canada) - Copyright (C) 2023 + Copyright (C) 2025 Matthias P. Braendli, matthias.braendli@mpb.li An implementation for a threadsafe queue, depends on C++11 @@ -28,6 +28,7 @@ #pragma once +#include <functional> #include <mutex> #include <condition_variable> #include <queue> @@ -63,10 +64,10 @@ public: std::unique_lock<std::mutex> lock(the_mutex); size_t queue_size_before = the_queue.size(); if (max_size == 0) { - the_queue.push(val); + the_queue.push_back(val); } else if (queue_size_before < max_size) { - the_queue.push(val); + the_queue.push_back(val); } size_t queue_size = the_queue.size(); lock.unlock(); @@ -80,10 +81,10 @@ public: std::unique_lock<std::mutex> lock(the_mutex); size_t queue_size_before = the_queue.size(); if (max_size == 0) { - the_queue.emplace(std::move(val)); + the_queue.emplace_back(std::move(val)); } else if (queue_size_before < max_size) { - the_queue.emplace(std::move(val)); + the_queue.emplace_back(std::move(val)); } size_t queue_size = the_queue.size(); lock.unlock(); @@ -110,9 +111,9 @@ public: bool overflow = false; while (the_queue.size() >= max_size) { overflow = true; - the_queue.pop(); + the_queue.pop_front(); } - the_queue.push(val); + the_queue.push_back(val); const size_t queue_size = the_queue.size(); lock.unlock(); @@ -129,9 +130,9 @@ public: bool overflow = false; while (the_queue.size() >= max_size) { overflow = true; - the_queue.pop(); + the_queue.pop_front(); } - the_queue.emplace(std::move(val)); + the_queue.emplace_back(std::move(val)); const size_t queue_size = the_queue.size(); lock.unlock(); @@ -152,7 +153,7 @@ public: while (the_queue.size() >= threshold) { the_tx_notification.wait(lock); } - the_queue.push(val); + the_queue.push_back(val); size_t queue_size = the_queue.size(); lock.unlock(); @@ -198,7 +199,7 @@ public: } popped_value = the_queue.front(); - the_queue.pop(); + the_queue.pop_front(); lock.unlock(); the_tx_notification.notify_one(); @@ -220,15 +221,26 @@ public: } else { std::swap(popped_value, the_queue.front()); - the_queue.pop(); + the_queue.pop_front(); lock.unlock(); the_tx_notification.notify_one(); } } + template<typename R> + std::vector<R> map(std::function<R(const T&)> func) const + { + std::vector<R> result; + std::unique_lock<std::mutex> lock(the_mutex); + for (const T& elem : the_queue) { + result.push_back(func(elem)); + } + return result; + } + private: - std::queue<T> the_queue; + std::deque<T> the_queue; mutable std::mutex the_mutex; std::condition_variable the_rx_notification; std::condition_variable the_tx_notification; diff --git a/lib/fec/decode_rs.h b/lib/fec/decode_rs.h index c165cf3..647b885 100644 --- a/lib/fec/decode_rs.h +++ b/lib/fec/decode_rs.h @@ -145,15 +145,15 @@ count++; } if (count != no_eras) { - printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); + fprintf(stderr, "count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); count = -1; goto finish; } #if DEBUG >= 2 - printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + fprintf(stderr, "\n Erasure positions as determined by roots of Eras Loc Poly:\n"); for (i = 0; i < count; i++) - printf("%d ", loc[i]); - printf("\n"); + fprintf(stderr, "%d ", loc[i]); + fprintf(stderr, "\n"); #endif #endif } @@ -227,7 +227,7 @@ continue; /* Not a root */ /* store root (index-form) and error location number */ #if DEBUG>=2 - printf("count %d root %d loc %d\n",count,i,k); + fprintf(stderr, "count %d root %d loc %d\n",count,i,k); #endif root[count] = i; loc[count] = k; @@ -279,7 +279,7 @@ } #if DEBUG >= 1 if (den == 0) { - printf("\n ERROR: denominator = 0\n"); + fprintf(stderr, "\n ERROR: denominator = 0\n"); count = -1; goto finish; } diff --git a/src/Buffer.h b/src/Buffer.h index 2c2a65e..a8130ed 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -34,11 +34,12 @@ #include <vector> #include <memory> #include <complex> +#include <cstdint> #include "fpm/fixed.hpp" typedef std::complex<float> complexf; -using fixed_16 = fpm::fixed<std::int16_t, std::int32_t, 14>; +using fixed_16 = fpm::fixed<int16_t, int32_t, 14>; typedef std::complex<fixed_16> complexfix; typedef std::complex<fpm::fixed_16_16> complexfix_wide; diff --git a/src/GainControl.cpp b/src/GainControl.cpp index 84cf065..e3e280f 100644 --- a/src/GainControl.cpp +++ b/src/GainControl.cpp @@ -35,7 +35,7 @@ #ifdef __SSE__ # include <xmmintrin.h> -union __u128 { +union u128_union_t { __m128 m; float f[4]; }; @@ -122,7 +122,7 @@ int GainControl::internal_process(Buffer* const dataIn, Buffer* dataOut) __m128* out = reinterpret_cast<__m128*>(dataOut->getData()); size_t sizeIn = dataIn->getLength() / sizeof(__m128); size_t sizeOut = dataOut->getLength() / sizeof(__m128); - __u128 gain128; + u128_union_t gain128; if ((sizeIn % m_frameSize) != 0) { @@ -200,10 +200,10 @@ __m128 GainControl::computeGainFix(const __m128* in, size_t sizeIn) __m128 GainControl::computeGainMax(const __m128* in, size_t sizeIn) { - __u128 gain128; - __u128 min128; - __u128 max128; - __u128 tmp128; + u128_union_t gain128; + u128_union_t min128; + u128_union_t max128; + u128_union_t tmp128; static const __m128 factor128 = _mm_set1_ps(0x7fff); //////////////////////////////////////////////////////////////////////// @@ -250,10 +250,10 @@ __m128 GainControl::computeGainMax(const __m128* in, size_t sizeIn) __m128 GainControl::computeGainVar(const __m128* in, size_t sizeIn) { - __u128 gain128; - __u128 mean128; - __u128 var128; - __u128 tmp128; + u128_union_t gain128; + u128_union_t mean128; + u128_union_t var128; + u128_union_t tmp128; static const __m128 factor128 = _mm_set1_ps(0x7fff); mean128.m = _mm_setzero_ps(); @@ -297,8 +297,8 @@ __m128 GainControl::computeGainVar(const __m128* in, size_t sizeIn) var128.m = _mm_add_ps(var128.m, q128); /* - __u128 udiff128; udiff128.m = diff128; - __u128 udelta128; udelta128.m = delta128; + u128_union_t udiff128; udiff128.m = diff128; + u128_union_t udelta128; udelta128.m = delta128; for (int off=0; off<4; off+=2) { printf("S %zu, %.2f+%.2fj\t", sample, diff --git a/src/Utils.cpp b/src/Utils.cpp index 78f36f0..23e0aa5 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -89,8 +89,8 @@ void printUsage(const char* progName) "\n\t" #if defined(HAVE_OUTPUT_UHD) " [-G txgain]" - " [-T filter_taps_file]" #endif // defined(HAVE_OUTPUT_UHD) + " [-T filter_taps_file]" " [-a gain]" " [-c clockrate]" "\n\t" @@ -114,9 +114,9 @@ void printUsage(const char* progName) fprintf(out, "-u device: Use UHD output with given device string. (use "" for default device)\n"); fprintf(out, "-F frequency: Set the transmit frequency when using UHD output. (mandatory option when using UHD)\n"); fprintf(out, "-G txgain: Set the transmit gain for the UHD driver (default: 0)\n"); +#endif // defined(HAVE_OUTPUT_UHD) fprintf(out, "-T taps_file: Enable filtering before the output, using the specified file containing the filter taps.\n"); fprintf(out, " Use 'default' as taps_file to use the internal taps.\n"); -#endif // defined(HAVE_OUTPUT_UHD) fprintf(out, "-a gain: Apply digital amplitude gain.\n"); fprintf(out, "-c rate: Set the DAC clock rate and enable Cic Equalisation.\n"); fprintf(out, "-g gainmode: Set computation gain mode: fix, max or var\n"); |