aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMatthias P. Braendli (think) <matthias@mpb.li>2012-08-17 11:33:02 +0200
committerMatthias P. Braendli (think) <matthias@mpb.li>2012-08-17 11:33:02 +0200
commitd4a1f755a9e5426187fe6e80eb32c299f81104dd (patch)
treeb65bd65db58b277ac04a416da169b74da51099d8 /src
parent63f6e31cad0276352dd508394742b3161dde77bf (diff)
downloaddabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.tar.gz
dabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.tar.bz2
dabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.zip
crc-dabmod: remote control for FIRFilter
Diffstat (limited to 'src')
-rw-r--r--src/DabMod.cpp10
-rw-r--r--src/DabModulator.cpp14
-rw-r--r--src/DabModulator.h8
-rw-r--r--src/FIRFilter.cpp174
-rw-r--r--src/FIRFilter.h25
-rw-r--r--src/OutputUHD.cpp3
-rw-r--r--src/RemoteControl.h3
7 files changed, 173 insertions, 64 deletions
diff --git a/src/DabMod.cpp b/src/DabMod.cpp
index 83fb210..1de320d 100644
--- a/src/DabMod.cpp
+++ b/src/DabMod.cpp
@@ -42,6 +42,7 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <complex>
+#include <string>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
@@ -49,7 +50,6 @@
#include <sys/stat.h>
#include <stdexcept>
#include <signal.h>
-#include <string.h>
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
@@ -174,7 +174,7 @@ int main(int argc, char* argv[])
GainMode gainMode = GAIN_VAR;
Buffer data;
- const char* filterTapsFilename = NULL;
+ std::string filterTapsFilename = "";
// Two configuration sources exist: command line and (new) INI file
bool use_configuration_cmdline = false;
@@ -368,7 +368,7 @@ int main(int argc, char* argv[])
// FIR Filter parameters:
if (pt.get("firfilter.enabled", 0) == 1) {
try {
- filterTapsFilename = pt.get<std::string>("firfilter.enabled").c_str();
+ filterTapsFilename = pt.get<std::string>("firfilter.filtertapsfile");
}
catch (std::exception &e) {
std::cerr << "Error: " << e.what() << "\n";
@@ -455,7 +455,7 @@ int main(int argc, char* argv[])
// When using the FIRFilter, increase the modulator offset pipelining delay
// by the correct amount
- if (filterTapsFilename != NULL) {
+ if (filterTapsFilename != "") {
modconf.delay_calculation_pipeline_stages += FIRFILTER_PIPELINE_DELAY;
}
@@ -543,7 +543,7 @@ int main(int argc, char* argv[])
flowgraph = new Flowgraph();
data.setLength(6144);
input = new InputMemory(&data);
- modulator = new DabModulator(modconf, outputRate, clockRate,
+ modulator = new DabModulator(modconf, rc, outputRate, clockRate,
dabMode, gainMode, amplitude, filterTapsFilename);
flowgraph->connect(input, modulator);
flowgraph->connect(modulator, output);
diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp
index d89716b..14c6d3d 100644
--- a/src/DabModulator.cpp
+++ b/src/DabModulator.cpp
@@ -23,6 +23,8 @@
along with CRC-DADMOD. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <string>
+
#include "DabModulator.h"
#include "PcDebug.h"
@@ -45,13 +47,15 @@
#include "PuncturingEncoder.h"
#include "TimeInterleaver.h"
#include "TimestampDecoder.h"
+#include "RemoteControl.h"
DabModulator::DabModulator(
struct modulator_offset_config& modconf,
+ BaseRemoteController* rc,
unsigned outputRate, unsigned clockRate,
unsigned dabMode, GainMode gainMode, float factor,
- const char* filterTapsFilename
+ std::string filterTapsFilename
) :
ModCodec(ModFormat(1), ModFormat(0)),
myOutputRate(outputRate),
@@ -61,7 +65,8 @@ DabModulator::DabModulator(
myFactor(factor),
myEtiReader(EtiReader(modconf)),
myFlowgraph(NULL),
- myFilterTapsFilename(filterTapsFilename)
+ myFilterTapsFilename(filterTapsFilename),
+ myRC(rc)
{
PDEBUG("DabModulator::DabModulator(%u, %u, %u, %u) @ %p\n",
outputRate, clockRate, dabMode, gainMode, this);
@@ -193,8 +198,9 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut)
cifGain = new GainControl(mySpacing, myGainMode, myFactor);
cifGuard = new GuardIntervalInserter(myNbSymbols, mySpacing,
myNullSize, mySymSize);
- if (myFilterTapsFilename != NULL) {
+ if (myFilterTapsFilename != "") {
cifFilter = new FIRFilter(myFilterTapsFilename);
+ cifFilter->enrol_at(*myRC);
}
myOutput = new OutputMemory();
@@ -338,7 +344,7 @@ int DabModulator::process(Buffer* const dataIn, Buffer* dataOut)
myFlowgraph->connect(cifOfdm, cifGain);
myFlowgraph->connect(cifGain, cifGuard);
- if (myFilterTapsFilename != NULL) {
+ if (myFilterTapsFilename != "") {
myFlowgraph->connect(cifGuard, cifFilter);
if (cifRes != NULL) {
myFlowgraph->connect(cifFilter, cifRes);
diff --git a/src/DabModulator.h b/src/DabModulator.h
index 72fee41..e91507c 100644
--- a/src/DabModulator.h
+++ b/src/DabModulator.h
@@ -31,12 +31,14 @@
#endif
#include <sys/types.h>
+#include <string>
#include "ModCodec.h"
#include "EtiReader.h"
#include "Flowgraph.h"
#include "GainControl.h"
#include "OutputMemory.h"
+#include "RemoteControl.h"
class DabModulator : public ModCodec
@@ -44,9 +46,10 @@ class DabModulator : public ModCodec
public:
DabModulator(
struct modulator_offset_config& modconf,
+ BaseRemoteController* rc,
unsigned outputRate = 2048000, unsigned clockRate = 0,
unsigned dabMode = 0, GainMode gainMode = GAIN_VAR,
- float factor = 1.0, const char* filterTapsFilename = NULL);
+ float factor = 1.0, std::string filterTapsFilename = "");
DabModulator(const DabModulator& copy);
virtual ~DabModulator();
@@ -67,7 +70,8 @@ protected:
EtiReader myEtiReader;
Flowgraph* myFlowgraph;
OutputMemory* myOutput;
- const char* myFilterTapsFilename;
+ std::string myFilterTapsFilename;
+ BaseRemoteController* myRC;
size_t myNbSymbols;
size_t myNbCarriers;
diff --git a/src/FIRFilter.cpp b/src/FIRFilter.cpp
index 540e015..c6a2350 100644
--- a/src/FIRFilter.cpp
+++ b/src/FIRFilter.cpp
@@ -82,28 +82,32 @@ void FIRFilterWorker::process(struct FIRFilterWorkerData *fwd)
__m128 SSEout;
__m128 SSEtaps;
__m128 SSEin;
- for (i = 0; i < sizeIn - 2*fwd->n_taps; i += 4) {
- SSEout = _mm_setr_ps(0,0,0,0);
+ {
+ boost::mutex::scoped_lock lock(fwd->taps_mutex);
- for (int j = 0; j < fwd->n_taps; j++) {
- if ((uintptr_t)(&in[i+2*j]) % 16 == 0) {
- SSEin = _mm_load_ps(&in[i+2*j]); //faster when aligned
- }
- else {
- SSEin = _mm_loadu_ps(&in[i+2*j]);
- }
+ for (i = 0; i < sizeIn - 2*fwd->n_taps; i += 4) {
+ SSEout = _mm_setr_ps(0,0,0,0);
+
+ for (int j = 0; j < fwd->n_taps; j++) {
+ if ((uintptr_t)(&in[i+2*j]) % 16 == 0) {
+ SSEin = _mm_load_ps(&in[i+2*j]); //faster when aligned
+ }
+ else {
+ SSEin = _mm_loadu_ps(&in[i+2*j]);
+ }
- SSEtaps = _mm_load1_ps(&fwd->taps[j]);
+ SSEtaps = _mm_load1_ps(&fwd->taps[j]);
- SSEout = _mm_add_ps(SSEout, _mm_mul_ps(SSEin, SSEtaps));
+ SSEout = _mm_add_ps(SSEout, _mm_mul_ps(SSEin, SSEtaps));
+ }
+ _mm_store_ps(&out[i], SSEout);
}
- _mm_store_ps(&out[i], SSEout);
- }
- for (; i < sizeIn; i++) {
- out[i] = 0.0;
- for (int j = 0; i+2*j < sizeIn; j++) {
- out[i] += in[i+2*j] * fwd->taps[j];
+ for (; i < sizeIn; i++) {
+ out[i] = 0.0;
+ for (int j = 0; i+2*j < sizeIn; j++) {
+ out[i] += in[i+2*j] * fwd->taps[j];
+ }
}
}
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time_end);
@@ -117,28 +121,31 @@ void FIRFilterWorker::process(struct FIRFilterWorkerData *fwd)
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &time_start);
- // Convolve by aligning both frame and taps at zero.
- for (i = 0; i < sizeIn - 2*fwd->n_taps; i += 4) {
- out[i] = 0.0;
- out[i+1] = 0.0;
- out[i+2] = 0.0;
- out[i+3] = 0.0;
-
- for (int j = 0; j < fwd->n_taps; j++) {
- out[i] += in[i + 2*j] * fwd->taps[j];
- out[i+1] += in[i+1 + 2*j] * fwd->taps[j];
- out[i+2] += in[i+2 + 2*j] * fwd->taps[j];
- out[i+3] += in[i+3 + 2*j] * fwd->taps[j];
+ {
+ boost::mutex::scoped_lock lock(fwd->taps_mutex);
+ // Convolve by aligning both frame and taps at zero.
+ for (i = 0; i < sizeIn - 2*fwd->n_taps; i += 4) {
+ out[i] = 0.0;
+ out[i+1] = 0.0;
+ out[i+2] = 0.0;
+ out[i+3] = 0.0;
+
+ for (int j = 0; j < fwd->n_taps; j++) {
+ out[i] += in[i + 2*j] * fwd->taps[j];
+ out[i+1] += in[i+1 + 2*j] * fwd->taps[j];
+ out[i+2] += in[i+2 + 2*j] * fwd->taps[j];
+ out[i+3] += in[i+3 + 2*j] * fwd->taps[j];
+ }
}
- }
- // At the end of the frame, we cut the convolution off.
- // The beginning of the next frame starts with a NULL symbol
- // anyway.
- for (; i < sizeIn; i++) {
- out[i] = 0.0;
- for (int j = 0; i+2*j < sizeIn; j++) {
- out[i] += in[i+2*j] * fwd->taps[j];
+ // At the end of the frame, we cut the convolution off.
+ // The beginning of the next frame starts with a NULL symbol
+ // anyway.
+ for (; i < sizeIn; i++) {
+ out[i] = 0.0;
+ for (int j = 0; i+2*j < sizeIn; j++) {
+ out[i] += in[i+2*j] * fwd->taps[j];
+ }
}
}
@@ -227,27 +234,50 @@ void FIRFilterWorker::process(struct FIRFilterWorkerData *fwd)
}
-FIRFilter::FIRFilter(const char* taps_file) :
- ModCodec(ModFormat(sizeof(complexf)), ModFormat(sizeof(complexf)))
+FIRFilter::FIRFilter(std::string taps_file) :
+ ModCodec(ModFormat(sizeof(complexf)), ModFormat(sizeof(complexf))),
+ RemoteControllable("firfilter"),
+ myTapsFile(taps_file)
{
PDEBUG("FIRFilter::FIRFilter(%s) @ %p\n",
taps_file, this);
+ RC_ADD_PARAMETER(ntaps, "(Read-only) number of filter taps.");
+ RC_ADD_PARAMETER(tapsfile, "Filename containing filter taps. When written to, the new file gets automatically loaded.");
+
number_of_runs = 0;
- std::ifstream taps_fstream(taps_file);
+ load_filter_taps();
+
+ PDEBUG("FIRFilter: Starting worker\n" );
+ worker.start(&firwd);
+}
+
+void
+FIRFilter::load_filter_taps()
+{
+ std::ifstream taps_fstream(myTapsFile.c_str());
if(!taps_fstream) {
- fprintf(stderr, "FIRFilter: file %s could not be opened !\n", taps_file);
+ fprintf(stderr, "FIRFilter: file %s could not be opened !\n", myTapsFile.c_str());
throw std::runtime_error("FIRFilter: Could not open file with taps! ");
}
int n_taps;
taps_fstream >> n_taps;
- my_Ntaps = n_taps;
+ if (n_taps <= 0) {
+ fprintf(stderr, "FIRFilter: warning: taps file has invalid format\n");
+ throw std::runtime_error("FIRFilter: taps file has invalid format.");
+ }
+
+ if (n_taps > 100) {
+ fprintf(stderr, "FIRFilter: warning: taps file has more than 100 taps\n");
+ }
+
+ myNtaps = n_taps;
- fprintf(stderr, "FIRFilter: Reading %d taps...\n", my_Ntaps);
+ fprintf(stderr, "FIRFilter: Reading %d taps...\n", myNtaps);
- myFilter = new float[my_Ntaps];
+ myFilter = new float[myNtaps];
int n;
for (n = 0; n < n_taps; n++) {
@@ -255,16 +285,20 @@ FIRFilter::FIRFilter(const char* taps_file) :
PDEBUG("FIRFilter: tap: %f\n", myFilter[n] );
if (taps_fstream.eof()) {
fprintf(stderr, "FIRFilter: file %s should contains %d taps, but EOF reached "\
- "after %d taps !\n", taps_file, n_taps, n);
+ "after %d taps !\n", myTapsFile.c_str(), n_taps, n);
+ delete myFilter;
throw std::runtime_error("FIRFilter: filtertaps file invalid ! ");
}
}
- firwd.taps = myFilter;
- firwd.n_taps = my_Ntaps;
+ {
+ boost::mutex::scoped_lock lock(firwd.taps_mutex);
- PDEBUG("FIRFilter: Starting worker\n" );
- worker.start(&firwd);
+ delete firwd.taps;
+
+ firwd.taps = myFilter;
+ firwd.n_taps = myNtaps;
+ }
}
@@ -309,3 +343,45 @@ int FIRFilter::process(Buffer* const dataIn, Buffer* dataOut)
return dataOut->getLength();
}
+
+void FIRFilter::set_parameter(string parameter, string value)
+{
+ stringstream ss(value);
+ ss.exceptions ( stringstream::failbit | stringstream::badbit );
+
+ if (parameter == "ntaps") {
+ throw ParameterError("Parameter 'ntaps' is read-only");
+ }
+ else if (parameter == "tapsfile") {
+ myTapsFile = value;
+ try {
+ load_filter_taps();
+ }
+ catch (std::runtime_error &e) {
+ throw ParameterError(e.what());
+ }
+ }
+ else {
+ stringstream ss;
+ ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+}
+
+string FIRFilter::get_parameter(string parameter)
+{
+ stringstream ss;
+ if (parameter == "ntaps") {
+ ss << myNtaps;
+ }
+ else if (parameter == "tapsfile") {
+ ss << myTapsFile;
+ }
+ else {
+ ss << "Parameter '" << parameter << "' is not exported by controllable " << get_rc_name();
+ throw ParameterError(ss.str());
+ }
+ return ss.str();
+
+}
+
diff --git a/src/FIRFilter.h b/src/FIRFilter.h
index 0c06930..b9abb3e 100644
--- a/src/FIRFilter.h
+++ b/src/FIRFilter.h
@@ -32,6 +32,7 @@
#include <boost/thread.hpp>
#include <queue>
+#include "RemoteControl.h"
#include "ModCodec.h"
#include "PcDebug.h"
@@ -40,6 +41,7 @@
#include <time.h>
#include <cstdio>
+#include <string>
#define FIRFILTER_PIPELINE_DELAY 1
@@ -94,8 +96,17 @@ public:
};
struct FIRFilterWorkerData {
+ /* Thread-safe queues to give data to and get data from
+ * the worker
+ */
ThreadsafeQueue<Buffer*> input_queue;
ThreadsafeQueue<Buffer*> output_queue;
+
+ /* Remote-control can change the taps while the filter
+ * runs. This lock makes sure nothing bad happens when
+ * the taps are being modified
+ */
+ mutable boost::mutex taps_mutex;
float* taps;
int n_taps;
};
@@ -133,10 +144,10 @@ class FIRFilterWorker {
};
-class FIRFilter : public ModCodec
+class FIRFilter : public ModCodec, public RemoteControllable
{
public:
- FIRFilter(const char* taps_file);
+ FIRFilter(std::string taps_file);
virtual ~FIRFilter();
FIRFilter(const FIRFilter&);
FIRFilter& operator=(const FIRFilter&);
@@ -144,8 +155,16 @@ public:
int process(Buffer* const dataIn, Buffer* dataOut);
const char* name() { return "FIRFilter"; }
+ /******* REMOTE CONTROL ********/
+ void set_parameter(string parameter, string value);
+ string get_parameter(string parameter);
+
+
protected:
- int my_Ntaps;
+ void load_filter_taps();
+
+ std::string myTapsFile;
+ int myNtaps;
float* myFilter;
FIRFilterWorker worker;
diff --git a/src/OutputUHD.cpp b/src/OutputUHD.cpp
index a852c10..eb55c0d 100644
--- a/src/OutputUHD.cpp
+++ b/src/OutputUHD.cpp
@@ -332,7 +332,7 @@ void UHDWorker::process(struct UHDWorkerData *uwd)
frame->fct, tx_second, pps_offset);
uwd->logger->log(info, "OutputUHD: Throwing sample %d away: incomplete timestamp %zu + %f\n",
frame->fct, tx_second, pps_offset);
- usleep(20000);
+ usleep(20000); //TODO should this be TM-dependant ?
goto loopend;
}
@@ -500,6 +500,7 @@ void UHDWorker::process(struct UHDWorkerData *uwd)
frame->fct,
tx_second,
pps_offset);
+ usleep(23000); // 23ms, a bit faster than realtime for TM 2
#endif
last_pps = pps_offset;
diff --git a/src/RemoteControl.h b/src/RemoteControl.h
index 5ffb2fb..17352bf 100644
--- a/src/RemoteControl.h
+++ b/src/RemoteControl.h
@@ -4,6 +4,9 @@
Center Canada)
Written by Matthias P. Braendli, matthias.braendli@mpb.li, 2012
+
+ This module adds remote-control capability to some of the dabmod modules.
+ see testremotecontrol/test.cpp for an example of how to use this.
*/
/*
This file is part of CRC-DADMOD.