aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dpd/dpd.ini3
-rwxr-xr-xdpd/main.py25
-rw-r--r--dpd/poly.coef11
-rw-r--r--dpd/poly_am.coef6
-rw-r--r--dpd/poly_pm.coef6
-rw-r--r--dpd/src/Adapt.py42
-rw-r--r--src/ConfigParser.cpp9
-rw-r--r--src/ConfigParser.h3
-rw-r--r--src/DabModulator.cpp6
-rw-r--r--src/MemlessPoly.cpp165
-rw-r--r--src/MemlessPoly.h16
11 files changed, 108 insertions, 184 deletions
diff --git a/dpd/dpd.ini b/dpd/dpd.ini
index 54af9ce..1bc51de 100644
--- a/dpd/dpd.ini
+++ b/dpd/dpd.ini
@@ -22,8 +22,7 @@ enabled=1
[poly]
enabled=1
-polycoeffileam=dpd/poly_am.coef
-polycoeffilepm=dpd/poly_pm.coef
+polycoeffile=dpd/poly.coef
# How many threads to use for the predistorter.
# If not set, detect automatically.
diff --git a/dpd/main.py b/dpd/main.py
index 7e1041b..ea570d3 100755
--- a/dpd/main.py
+++ b/dpd/main.py
@@ -38,12 +38,9 @@ parser.add_argument('--rc-port', default='9400',
parser.add_argument('--samplerate', default='8192000',
help='Sample rate',
required=False)
-parser.add_argument('--coefs_am', default='poly_am.coef',
- help='File with DPD Amplitude coefficients, which will be read by ODR-DabMod',
+parser.add_argument('--coefs', default='poly.coef',
+ help='File with DPD coefficients, which will be read by ODR-DabMod',
required=False)
-parser.add_argument('--coefs_pm', default='poly_am.coef',
- help='File with DPD Phase coefficients, which will be read by ODR-DabMod',
- required=False)
parser.add_argument('--samps', default='10240',
help='Number of samples to request from ODR-DabMod',
required=False)
@@ -52,37 +49,33 @@ cli_args = parser.parse_args()
port = int(cli_args.port)
port_rc = int(cli_args.rc_port)
-coef_am_path = cli_args.coefs_am
-coef_pm_path = cli_args.coefs_pm
+coef_path = cli_args.coefs
num_req = int(cli_args.samps)
samplerate = int(cli_args.samplerate)
meas = Measure.Measure(samplerate, port, num_req)
-adapt = Adapt.Adapt(port_rc, coef_am_path, coef_pm_path)
-coefs_am = adapt.get_coefs_am()
-coefs_pm = adapt.get_coefs_pm()
+adapt = Adapt.Adapt(port_rc, coef_path)
+coefs_am, coefs_pm = adapt.get_coefs()
#model = Model.Model(coefs)
-model = Model.Model([2.2, 0, 0, 0, 0], [0, 0, 0, 0, 0])
+model = Model.Model([1, 0, 0, 0, 0], [0, 0, 0, 0, 0])
adapt.set_txgain(70)
adapt.set_rxgain(30)
tx_gain = adapt.get_txgain()
rx_gain = adapt.get_rxgain()
-dpd_coefs_am = adapt.get_coefs_am()
-dpd_coefs_pm = adapt.get_coefs_pm()
+dpd_coefs_am, dpd_coefs_pm = adapt.get_coefs()
logging.info(
"TX gain {}, RX gain {}, dpd_coefs_am {}, dpd_coefs_pm {}".format(
tx_gain, rx_gain, dpd_coefs_am, dpd_coefs_pm
)
)
-for i in range(500):
+for i in range(1):
txframe_aligned, tx_ts, rxframe_aligned, rx_ts = meas.get_samples()
logging.debug("tx_ts {}, rx_ts {}".format(tx_ts, rx_ts))
coefs_am, coefs_pm = model.get_next_coefs(txframe_aligned, rxframe_aligned)
- adapt.set_coefs_am(coefs_am)
- adapt.set_coefs_pm(coefs_pm)
+ adapt.set_coefs(coefs_am, coefs_pm)
# The MIT License (MIT)
#
diff --git a/dpd/poly.coef b/dpd/poly.coef
new file mode 100644
index 0000000..d1e9967
--- /dev/null
+++ b/dpd/poly.coef
@@ -0,0 +1,11 @@
+5
+0.9999999999999999
+0.013989416705029524
+-0.17875129566117912
+1.189037605717911
+-1.7871717414839607
+-0.005118865951385803
+0.06831365867284998
+-0.32196849299538066
+0.6598790120324084
+-0.5099783166759195
diff --git a/dpd/poly_am.coef b/dpd/poly_am.coef
deleted file mode 100644
index ff09e5a..0000000
--- a/dpd/poly_am.coef
+++ /dev/null
@@ -1,6 +0,0 @@
-5
-2.2
-1.16110192544
--13.7895532562
-55.107515965
--53.8583673922
diff --git a/dpd/poly_pm.coef b/dpd/poly_pm.coef
deleted file mode 100644
index ae91b12..0000000
--- a/dpd/poly_pm.coef
+++ /dev/null
@@ -1,6 +0,0 @@
-5
-0.141477421551
--0.654864288614
-1.00568534673
--0.588530075442
-0.0935391293974
diff --git a/dpd/src/Adapt.py b/dpd/src/Adapt.py
index cc4c8c7..2fb596f 100644
--- a/dpd/src/Adapt.py
+++ b/dpd/src/Adapt.py
@@ -23,11 +23,10 @@ class Adapt:
ZMQ remote control.
"""
- def __init__(self, port, coef_am_path, coef_pm_path):
+ def __init__(self, port, coef_path):
logging.info("Instantiate Adapt object")
self.port = port
- self.coef_am_path = coef_am_path
- self.coef_pm_path = coef_pm_path
+ self.coef_path = coef_path
self.host = "localhost"
self._context = zmq.Context()
@@ -112,8 +111,10 @@ class Adapt:
return self.send_receive("get uhd rxgain")
def _read_coef_file(self, path):
- """Load the coefficients from the file in the format given in the README"""
- coefs_out = []
+ """Load the coefficients from the file in the format given in the README,
+ return ([AM coef], [PM coef])"""
+ coefs_am_out = []
+ coefs_pm_out = []
f = open(path, 'r')
lines = f.readlines()
n_coefs = int(lines[0])
@@ -121,35 +122,34 @@ class Adapt:
i = 0
for c in coefs:
if i < n_coefs:
- coefs_out.append(c)
+ coefs_am_out.append(c)
+ elif i < 2*n_coefs:
+ coefs_pm_out.append(c)
else:
raise ValueError(
"Incorrect coef file format: too many coefficients in {}, should be {}, coefs are {}"
.format(path, n_coefs, coefs))
i += 1
f.close()
- return coefs_out
+ return (coefs_am_out, coefs_pm_out)
- def get_coefs_am(self):
- return self._read_coef_file(self.coef_am_path)
+ def get_coefs(self):
+ return self._read_coef_file(self.coef_path)
- def get_coefs_pm(self):
- return self._read_coef_file(self.coef_pm_path)
+ def _write_coef_file(self, coefs_am, coefs_pm, path):
+ assert(len(coefs_am) == len(coefs_pm))
- def _write_coef_file(self, coefs, path):
f = open(path, 'w')
- f.write("{}\n".format(len(coefs)))
- for coef in coefs:
+ f.write("{}\n".format(len(coefs_am)))
+ for coef in coefs_am:
+ f.write("{}\n".format(coef))
+ for coef in coefs_pm:
f.write("{}\n".format(coef))
f.close()
- def set_coefs_am(self, coefs):
- self._write_coef_file(coefs, self.coef_am_path)
- self.send_receive("set memlesspoly coeffile_am {}".format(self.coef_am_path))
-
- def set_coefs_pm(self, coefs):
- self._write_coef_file(coefs, self.coef_pm_path)
- self.send_receive("set memlesspoly coeffile_pm {}".format(self.coef_pm_path))
+ def set_coefs(self, coefs_am, coefs_pm):
+ self._write_coef_file(coefs_am, coefs_pm, self.coef_path)
+ self.send_receive("set memlesspoly coeffile {}".format(self.coef_path))
# The MIT License (MIT)
#
diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp
index 062660b..9ac1280 100644
--- a/src/ConfigParser.cpp
+++ b/src/ConfigParser.cpp
@@ -168,13 +168,10 @@ static void parse_configfile(
pt.get<std::string>("firfilter.filtertapsfile", "default");
}
- // Poly coefficients amplitude:
+ // Poly coefficients:
if (pt.get("poly.enabled", 0) == 1) {
- mod_settings.polyCoefFilenameAm =
- pt.get<std::string>("poly.polycoeffileam", "dpd/poly_am.coef");
-
- mod_settings.polyCoefFilenamePm =
- pt.get<std::string>("poly.polycoeffilepm", "dpd/poly_pm.coef");
+ mod_settings.polyCoefFilename =
+ pt.get<std::string>("poly.polycoeffile", "dpd/poly.coef");
mod_settings.polyNumThreads =
pt.get<int>("poly.num_threads", 0);
diff --git a/src/ConfigParser.h b/src/ConfigParser.h
index d99fa08..89f0fb7 100644
--- a/src/ConfigParser.h
+++ b/src/ConfigParser.h
@@ -74,8 +74,7 @@ struct mod_settings_t {
std::string filterTapsFilename = "";
- std::string polyCoefFilenameAm = "";
- std::string polyCoefFilenamePm = "";
+ std::string polyCoefFilename = "";
unsigned polyNumThreads = 0;
#if defined(HAVE_OUTPUT_UHD)
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index f7f583a..cc2642a 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -204,10 +204,8 @@ int DabModulator::process(Buffer* dataOut)
}
shared_ptr<MemlessPoly> cifPoly;
- if (not m_settings.polyCoefFilenameAm.empty() and
- not m_settings.polyCoefFilenamePm.empty() ) {
- cifPoly = make_shared<MemlessPoly>(m_settings.polyCoefFilenameAm,
- m_settings.polyCoefFilenamePm,
+ if (not m_settings.polyCoefFilename.empty()) {
+ cifPoly = make_shared<MemlessPoly>(m_settings.polyCoefFilename,
m_settings.polyNumThreads);
rcs.enrol(cifPoly.get());
}
diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp
index 7fe465b..d5188f2 100644
--- a/src/MemlessPoly.cpp
+++ b/src/MemlessPoly.cpp
@@ -47,24 +47,20 @@
using namespace std;
-#define NUM_COEFS_AM 5
-#define NUM_COEFS_PM 5
+// Number of AM/AM coefs, identical to number of AM/PM coefs
+#define NUM_COEFS 5
-MemlessPoly::MemlessPoly(const std::string& coefs_am_file, const std::string& coefs_pm_file, unsigned int num_threads) :
+MemlessPoly::MemlessPoly(const std::string& coefs_file, unsigned int num_threads) :
PipelinedModCodec(),
RemoteControllable("memlesspoly"),
m_num_threads(num_threads),
m_coefs_am(),
- m_coefs_am_file(coefs_am_file),
- m_coefs_am_mutex(),
m_coefs_pm(),
- m_coefs_pm_file(coefs_pm_file),
- m_coefs_pm_mutex()
+ m_coefs_file(coefs_file),
+ m_coefs_mutex()
{
PDEBUG("MemlessPoly::MemlessPoly(%s) @ %p\n",
- coefs_am_file.c_str(), this);
- PDEBUG("MemlessPoly::MemlessPoly(%s) @ %p\n",
- coefs_pm_file.c_str(), this);
+ coefs_file.c_str(), this);
if (m_num_threads == 0) {
const unsigned int hw_concurrency = std::thread::hardware_concurrency();
@@ -76,98 +72,64 @@ MemlessPoly::MemlessPoly(const std::string& coefs_am_file, const std::string& co
m_num_threads << " threads (set in config file)";
}
- RC_ADD_PARAMETER(ncoefs_am, "(Read-only) number of coefficients for amplitude.");
- RC_ADD_PARAMETER(coeffile_am, "Filename containing coefficients for amplitude. When written to, the new file gets automatically loaded.");
-
- RC_ADD_PARAMETER(ncoefs_pm, "(Read-only) number of coefficients for phase.");
- RC_ADD_PARAMETER(coeffile_pm, "Filename containing coefficients for amplitude. When written to, the new file gets automatically loaded.");
+ RC_ADD_PARAMETER(ncoefs, "(Read-only) number of coefficients.");
+ RC_ADD_PARAMETER(coeffile, "Filename containing coefficients. "
+ "When set, the file gets loaded.");
- load_coefficients_am(m_coefs_am_file);
- load_coefficients_pm(m_coefs_pm_file);
+ load_coefficients(m_coefs_file);
start_pipeline_thread();
}
-void MemlessPoly::load_coefficients_am(const std::string &coefFile_am)
+void MemlessPoly::load_coefficients(const std::string &coefFile)
{
std::vector<float> coefs_am;
- std::ifstream coef_fstream_am(coefFile_am.c_str());
- if (!coef_fstream_am) {
- throw std::runtime_error("MemlessPoly: Could not open file with coefs_am!");
+ std::vector<float> coefs_pm;
+ std::ifstream coef_fstream(coefFile.c_str());
+ if (!coef_fstream) {
+ throw std::runtime_error("MemlessPoly: Could not open file with coefs!");
}
- int n_coefs_am;
- coef_fstream_am >> n_coefs_am;
+ int n_coefs;
+ coef_fstream >> n_coefs;
- if (n_coefs_am <= 0) {
- throw std::runtime_error("MemlessPoly: coefs_am file has invalid format.");
+ if (n_coefs <= 0) {
+ throw std::runtime_error("MemlessPoly: coefs file has invalid format.");
}
- else if (n_coefs_am != NUM_COEFS_AM) {
- throw std::runtime_error("MemlessPoly: invalid number of coefs_am: " +
- std::to_string(n_coefs_am) + " expected " + std::to_string(NUM_COEFS_AM));
+ else if (n_coefs != NUM_COEFS) {
+ throw std::runtime_error("MemlessPoly: invalid number of coefs: " +
+ std::to_string(n_coefs) + " expected " + std::to_string(NUM_COEFS));
}
- etiLog.log(debug, "MemlessPoly: Reading %d coefs_am...", n_coefs_am);
+ const size_t n_entries = 2 * n_coefs;
- coefs_am.resize(n_coefs_am);
-
- for (int n = 0; n < n_coefs_am; n++) {
- float a;
- coef_fstream_am >> a;
- coefs_am[n] = a;
-
- if (coef_fstream_am.eof()) {
- etiLog.log(error, "MemlessPoly: file %s should contains %d coefs_am, "
- "but EOF reached after %d coefs_am !",
- coefFile_am.c_str(), n_coefs_am, n);
- throw std::runtime_error("MemlessPoly: coefs_am file invalid !");
- }
- }
-
- {
- std::lock_guard<std::mutex> lock(m_coefs_am_mutex);
-
- m_coefs_am = coefs_am;
- }
-}
-
-void MemlessPoly::load_coefficients_pm(const std::string &coefFile_pm)
-{
- std::vector<float> coefs_pm;
- std::ifstream coef_fstream_pm(coefFile_pm.c_str());
- if (!coef_fstream_pm) {
- throw std::runtime_error("MemlessPoly: Could not open file with coefs_pm!");
- }
- int n_coefs_pm;
- coef_fstream_pm >> n_coefs_pm;
+ etiLog.log(debug, "MemlessPoly: Reading %d coefs...", n_entries);
- if (n_coefs_pm <= 0) {
- throw std::runtime_error("MemlessPoly: coefs_pm file has invalid format.");
- }
- else if (n_coefs_pm != NUM_COEFS_PM) {
- throw std::runtime_error("MemlessPoly: invalid number of coefs_pm: " +
- std::to_string(n_coefs_pm) + " expected " + std::to_string(NUM_COEFS_PM));
- }
+ coefs_am.resize(n_coefs);
+ coefs_pm.resize(n_coefs);
- etiLog.log(debug, "MemlessPoly: Reading %d coefs_pm...", n_coefs_pm);
+ for (int n = 0; n < n_entries; n++) {
+ float a;
+ coef_fstream >> a;
- coefs_pm.resize(n_coefs_pm);
+ if (n < n_coefs) {
+ coefs_am[n] = a;
+ }
+ else {
+ coefs_pm[n - n_coefs] = a;
+ }
- for (int n = 0; n < n_coefs_pm; n++) {
- float a;
- coef_fstream_pm >> a;
- coefs_pm[n] = a;
-
- if (coef_fstream_pm.eof()) {
- etiLog.log(error, "MemlessPoly: file %s should contains %d coefs_pm, "
- "but EOF reached after %d coefs_pm !",
- coefFile_pm.c_str(), n_coefs_pm, n);
- throw std::runtime_error("MemlessPoly: coefs_pm file invalid !");
+ if (coef_fstream.eof()) {
+ etiLog.log(error, "MemlessPoly: file %s should contains %d coefs, "
+ "but EOF reached after %d coefs !",
+ coefFile.c_str(), n_entries, n);
+ throw std::runtime_error("MemlessPoly: coefs file invalid !");
}
}
{
- std::lock_guard<std::mutex> lock(m_coefs_pm_mutex);
+ std::lock_guard<std::mutex> lock(m_coefs_mutex);
+ m_coefs_am = coefs_am;
m_coefs_pm = coefs_pm;
}
}
@@ -176,8 +138,7 @@ void MemlessPoly::load_coefficients_pm(const std::string &coefFile_pm)
* instead, and this allows the compiler to auto-vectorize the loop.
*/
static void apply_coeff(
- const vector<float> &coefs_am,
- const vector<float> &coefs_pm,
+ const vector<float> &coefs_am, const vector<float> &coefs_pm,
const complexf *__restrict in, size_t start, size_t stop,
complexf *__restrict out)
{
@@ -226,8 +187,7 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut)
size_t sizeOut = dataOut->getLength() / sizeof(complexf);
{
- std::lock_guard<std::mutex> lock_am(m_coefs_am_mutex);
- std::lock_guard<std::mutex> lock_pm(m_coefs_pm_mutex);
+ std::lock_guard<std::mutex> lock(m_coefs_mutex);
const unsigned int hw_concurrency = std::thread::hardware_concurrency();
const unsigned int num_threads =
@@ -240,7 +200,8 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut)
size_t start = 0;
for (size_t i = 0; i < num_threads - 1; i++) {
flags.push_back(async(launch::async, apply_coeff,
- m_coefs_am, m_coefs_pm, in, start, start + step, out));
+ m_coefs_am, m_coefs_pm,
+ in, start, start + step, out));
start += step;
}
@@ -266,25 +227,13 @@ void MemlessPoly::set_parameter(const string& parameter, const string& value)
stringstream ss(value);
ss.exceptions ( stringstream::failbit | stringstream::badbit );
- if (parameter == "ncoefs_am") {
- throw ParameterError("Parameter 'ncoefs_am' is read-only");
- }
- else if (parameter == "ncoefs_pm") {
- throw ParameterError("Parameter 'ncoefs_pm' is read-only");
+ if (parameter == "ncoefs") {
+ throw ParameterError("Parameter 'ncoefs' is read-only");
}
- else if (parameter == "coeffile_am") {
+ else if (parameter == "coeffile") {
try {
- load_coefficients_am(value);
- m_coefs_am_file = value;
- }
- catch (std::runtime_error &e) {
- throw ParameterError(e.what());
- }
- }
- else if (parameter == "coeffile_pm") {
- try {
- load_coefficients_pm(value);
- m_coefs_pm_file = value;
+ load_coefficients(value);
+ m_coefs_file = value;
}
catch (std::runtime_error &e) {
throw ParameterError(e.what());
@@ -301,17 +250,11 @@ void MemlessPoly::set_parameter(const string& parameter, const string& value)
const string MemlessPoly::get_parameter(const string& parameter) const
{
stringstream ss;
- if (parameter == "ncoefs_am") {
+ if (parameter == "ncoefs") {
ss << m_coefs_am.size();
}
- else if (parameter == "ncoefs_pm") {
- ss << m_coefs_pm.size();
- }
- else if (parameter == "coeffile_am") {
- ss << m_coefs_am_file;
- }
- else if (parameter == "coeffile_pm") {
- ss << m_coefs_pm_file;
+ else if (parameter == "coeffile") {
+ ss << m_coefs_file;
}
else {
ss << "Parameter '" << parameter <<
diff --git a/src/MemlessPoly.h b/src/MemlessPoly.h
index 536b054..4dcd44a 100644
--- a/src/MemlessPoly.h
+++ b/src/MemlessPoly.h
@@ -52,7 +52,7 @@ typedef std::complex<float> complexf;
class MemlessPoly : public PipelinedModCodec, public RemoteControllable
{
public:
- MemlessPoly(const std::string& coefs_am_file, const std::string& coefs_pm_file, unsigned int num_threads);
+ MemlessPoly(const std::string& coefs_file, unsigned int num_threads);
virtual const char* name() { return "MemlessPoly"; }
@@ -65,16 +65,12 @@ public:
private:
int internal_process(Buffer* const dataIn, Buffer* dataOut);
- void load_coefficients_am(const std::string &coefFile_am);
- void load_coefficients_pm(const std::string &coefFile_pm);
+ void load_coefficients(const std::string &coefFile);
unsigned int m_num_threads;
- std::vector<float> m_coefs_am;
- std::string m_coefs_am_file;
- mutable std::mutex m_coefs_am_mutex;
-
- std::vector<float> m_coefs_pm;
- std::string m_coefs_pm_file;
- mutable std::mutex m_coefs_pm_mutex;
+ std::vector<float> m_coefs_am; // AM/AM coefficients
+ std::vector<float> m_coefs_pm; // AM/PM coefficients
+ std::string m_coefs_file;
+ mutable std::mutex m_coefs_mutex;
};