aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dpd/dpd.ini10
-rw-r--r--src/DabModulator.cpp6
-rw-r--r--src/MemlessPoly.cpp124
-rw-r--r--src/MemlessPoly.h8
4 files changed, 95 insertions, 53 deletions
diff --git a/dpd/dpd.ini b/dpd/dpd.ini
index 5e809e5..af83a63 100644
--- a/dpd/dpd.ini
+++ b/dpd/dpd.ini
@@ -14,12 +14,16 @@ transport=tcp
source=localhost:9200
[modulator]
-digital_gain=0.8
+digital_gain=0.95
rate=8192000
[firfilter]
enabled=0
+[poly]
+enabled=1
+polycoeffile=polyCoefs
+
[output]
output=uhd
@@ -27,14 +31,14 @@ output=uhd
device=
master_clock_rate=32768000
type=b200
-txgain=75
+txgain=87
channel=13C
refclk_source=internal
pps_source=none
behaviour_refclk_lock_lost=ignore
max_gps_holdover_time=600
dpd_port=50055
-rxgain=0
+rxgain=15
[delaymanagement]
; Use synchronous=1 so that the USRP time is set. This works
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index 4e0bc33..5282a2d 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -223,12 +223,6 @@ int DabModulator::process(Buffer* dataOut)
shared_ptr<MemlessPoly> cifPoly;
if (not myPolyCoefFilename.empty()) {
cifPoly = make_shared<MemlessPoly>(myPolyCoefFilename);
- etiLog.level(debug) << myPolyCoefFilename << "\n";
- etiLog.level(debug) << cifPoly->m_coefs[0] << " " <<
- cifPoly->m_coefs[1] << " "<< cifPoly->m_coefs[2] << " "<<
- cifPoly->m_coefs[3] << " "<< cifPoly->m_coefs[4] << " "<<
- cifPoly->m_coefs[5] << " "<< cifPoly->m_coefs[6] << " "<<
- cifPoly->m_coefs[7] << "\n";
rcs.enrol(cifPoly.get());
}
diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp
index 7e074eb..71ceac3 100644
--- a/src/MemlessPoly.cpp
+++ b/src/MemlessPoly.cpp
@@ -36,6 +36,7 @@
#include <stdio.h>
#include <stdexcept>
+#include <future>
#include <array>
#include <iostream>
#include <fstream>
@@ -43,18 +44,21 @@
using namespace std;
+#define NUM_COEFS 5
// By default the signal is unchanged
-static const std::array<float, 8> default_coefficients({
+static const std::array<complexf, 8> default_coefficients({{
1, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0
- });
+ }});
MemlessPoly::MemlessPoly(const std::string& coefs_file) :
PipelinedModCodec(),
RemoteControllable("memlesspoly"),
- m_coefs_file(coefs_file)
+ m_coefs(),
+ m_coefs_file(coefs_file),
+ m_coefs_mutex()
{
PDEBUG("MemlessPoly::MemlessPoly(%s) @ %p\n",
coefs_file.c_str(), this);
@@ -69,41 +73,42 @@ MemlessPoly::MemlessPoly(const std::string& coefs_file) :
void MemlessPoly::load_coefficients(const std::string &coefFile)
{
- std::vector<float> coefs;
+ std::vector<complexf> coefs;
if (coefFile == "default") {
std::copy(default_coefficients.begin(), default_coefficients.end(),
std::back_inserter(coefs));
}
else {
std::ifstream coef_fstream(coefFile.c_str());
- if(!coef_fstream) {
- fprintf(stderr, "MemlessPoly: file %s could not be opened !\n", coefFile.c_str());
- throw std::runtime_error("MemlessPoly: Could not open file with coefs! ");
+ if (!coef_fstream) {
+ throw std::runtime_error("MemlessPoly: Could not open file with coefs!");
}
int n_coefs;
coef_fstream >> n_coefs;
if (n_coefs <= 0) {
- fprintf(stderr, "MemlessPoly: warning: coefs file has invalid format\n");
throw std::runtime_error("MemlessPoly: coefs file has invalid format.");
}
-
- if (n_coefs != 8) {
- throw std::runtime_error( "MemlessPoly: error: coefs file does not have 8 coefs\n");
+ else if (n_coefs != NUM_COEFS) {
+ throw std::runtime_error("MemlessPoly: invalid number of coefs: " +
+ std::to_string(coefs.size()));
}
- fprintf(stderr, "MemlessPoly: Reading %d coefs...\n", n_coefs);
+ etiLog.log(debug, "MemlessPoly: Reading %d coefs...", n_coefs);
coefs.resize(n_coefs);
- int n;
- for (n = 0; n < n_coefs; n++) {
- coef_fstream >> coefs[n];
- PDEBUG("MemlessPoly: coef: %f\n", coefs[n] );
+ for (int n = 0; n < n_coefs; n++) {
+ float a, b;
+ coef_fstream >> a;
+ coef_fstream >> b;
+ coefs[n] = complexf(a, b);
+
if (coef_fstream.eof()) {
- fprintf(stderr, "MemlessPoly: file %s should contains %d coefs, but EOF reached "\
- "after %d coefs !\n", coefFile.c_str(), n_coefs, n);
- throw std::runtime_error("MemlessPoly: coefs file invalid ! ");
+ etiLog.log(error, "MemlessPoly: file %s should contains %d coefs, "
+ "but EOF reached after %d coefs !",
+ coefFile.c_str(), n_coefs, n);
+ throw std::runtime_error("MemlessPoly: coefs file invalid !");
}
}
}
@@ -115,30 +120,73 @@ void MemlessPoly::load_coefficients(const std::string &coefFile)
}
}
+static void apply_coeff(
+ const vector<complexf> &coefs,
+ const complexf* in, size_t start, size_t stop,
+ complexf* out)
+{
+ for (size_t i = start; i < stop; i++) {
+
+ /* Implement
+ a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5;
+ with less multiplications:
+ a0 + x*(a1 + x*(a2 + x*(a3 + x*(a3 + x*(a4 + a5*x)))));
+ */
+
+ /* Make sure to adapt NUM_COEFS when you change this */
+ out[i] =
+ coefs[0] + in[i] *
+ ( coefs[1] + in[i] *
+ ( coefs[2] + in[i] *
+ ( coefs[3] + in[i] *
+ ( coefs[4] + in[i] *
+ ( coefs[5] + in[i] )))));
+ }
+}
int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut)
{
- const float* in = reinterpret_cast<const float*>(dataIn->getData());
- float* out = reinterpret_cast<float*>(dataOut->getData());
- size_t sizeIn = dataIn->getLength() / sizeof(float);
-
- {
- std::lock_guard<std::mutex> lock(m_coefs_mutex);
- for (size_t i = 0; i < sizeIn; i += 1) {
- float mag = std::abs(in[i]);
- //out[i] = in[i];
- out[i] = in[i] * (
- m_coefs[0] +
- m_coefs[1] * mag +
- m_coefs[2] * mag*mag +
- m_coefs[3] * mag*mag*mag +
- m_coefs[4] * mag*mag*mag*mag +
- m_coefs[5] * mag*mag*mag*mag*mag +
- m_coefs[6] * mag*mag*mag*mag*mag*mag +
- m_coefs[7] * mag*mag*mag*mag*mag*mag*mag
- );
+ dataOut->setLength(dataIn->getLength());
+
+ const complexf* in = reinterpret_cast<const complexf*>(dataIn->getData());
+ complexf* out = reinterpret_cast<complexf*>(dataOut->getData());
+ size_t sizeOut = dataOut->getLength() / sizeof(complexf);
+
+ {
+ std::lock_guard<std::mutex> lock(m_coefs_mutex);
+ const unsigned int hw_concurrency = std::thread::hardware_concurrency();
+
+ if (hw_concurrency) {
+ const size_t step = sizeOut / hw_concurrency;
+ vector<future<void> > flags;
+
+ size_t start = 0;
+ for (size_t i = 0; i < hw_concurrency - 1; i++) {
+ flags.push_back(async(launch::async, apply_coeff,
+ m_coefs, in, start, start + step, out));
+
+ start += step;
}
+
+ // Do the last in this thread
+ apply_coeff(m_coefs, in, start, sizeOut, out);
+
+ // Wait for completion of the tasks
+ for (auto& f : flags) {
+ f.get();
+ }
+ }
+ else {
+ static bool error_printed = false;
+ if (not error_printed) {
+ etiLog.level(warn) <<
+ "Your platform doesn't seem to have hardware concurrency. "
+ "MemlessPoly will run single-threaded";
+ }
+ // For some reason we don't have hw concurrency.
+ apply_coeff(m_coefs, in, 0, sizeOut, out);
}
+ }
return dataOut->getLength();
}
diff --git a/src/MemlessPoly.h b/src/MemlessPoly.h
index 210b4b4..9fe19d7 100644
--- a/src/MemlessPoly.h
+++ b/src/MemlessPoly.h
@@ -63,16 +63,12 @@ public:
virtual const std::string get_parameter(
const std::string& parameter) const;
-//TODO to protected
- std::vector<float> m_coefs;
-
-
-protected:
+private:
int internal_process(Buffer* const dataIn, Buffer* dataOut);
void load_coefficients(const std::string &coefFile);
+ std::vector<complexf> m_coefs;
std::string m_coefs_file;
-
mutable std::mutex m_coefs_mutex;
};