diff options
| author | Matthias P. Braendli (think) <matthias@mpb.li> | 2012-08-17 11:33:02 +0200 | 
|---|---|---|
| committer | Matthias P. Braendli (think) <matthias@mpb.li> | 2012-08-17 11:33:02 +0200 | 
| commit | d4a1f755a9e5426187fe6e80eb32c299f81104dd (patch) | |
| tree | b65bd65db58b277ac04a416da169b74da51099d8 | |
| parent | 63f6e31cad0276352dd508394742b3161dde77bf (diff) | |
| download | dabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.tar.gz dabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.tar.bz2 dabmod-d4a1f755a9e5426187fe6e80eb32c299f81104dd.zip  | |
crc-dabmod: remote control for FIRFilter
| -rw-r--r-- | src/DabMod.cpp | 10 | ||||
| -rw-r--r-- | src/DabModulator.cpp | 14 | ||||
| -rw-r--r-- | src/DabModulator.h | 8 | ||||
| -rw-r--r-- | src/FIRFilter.cpp | 174 | ||||
| -rw-r--r-- | src/FIRFilter.h | 25 | ||||
| -rw-r--r-- | src/OutputUHD.cpp | 3 | ||||
| -rw-r--r-- | src/RemoteControl.h | 3 | 
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.  | 
