diff options
author | Tom Rondeau <trondeau@vt.edu> | 2013-06-18 15:08:17 -0400 |
---|---|---|
committer | Tom Rondeau <trondeau@vt.edu> | 2013-06-18 15:08:17 -0400 |
commit | ad1d52fd9911114ad8c9748e808b55de4e16232b (patch) | |
tree | bb5696ca8617290e5ae76672544f308e3a21baae | |
parent | bec07463ddb722ed22bae83577ffe4c8029ff90d (diff) |
controlport: added support for complex data types.
Vectors of complex are still passed as interleaved. Single values can be passed as GNURadio::complex. ControlPort can translate these in GNU Radio to gr_complex; Python programs need to convert themselves. gr-ctrl-monitor updated to handle this.
multiply_const_cc block updated to export get and set of k value through ControlPort.
-rw-r--r-- | gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h | 1 | ||||
-rw-r--r-- | gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h | 57 | ||||
-rw-r--r-- | gnuradio-runtime/include/gnuradio/rpcserver_ice.h | 2 | ||||
-rw-r--r-- | gnuradio-runtime/lib/controlport/gnuradio.ice | 7 | ||||
-rw-r--r-- | gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc | 15 | ||||
-rw-r--r-- | gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py | 11 | ||||
-rwxr-xr-x | gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor | 60 | ||||
-rw-r--r-- | gnuradio-runtime/swig/gr_ctrlport.i | 3 | ||||
-rw-r--r-- | gr-blocks/lib/multiply_const_cc_impl.cc | 26 | ||||
-rw-r--r-- | gr-blocks/lib/multiply_const_cc_impl.h | 2 |
10 files changed, 164 insertions, 20 deletions
diff --git a/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h b/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h index 3b5b392ec3..3d2d4cc79a 100644 --- a/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h +++ b/gnuradio-runtime/include/gnuradio/rpccallbackregister_base.h @@ -52,6 +52,7 @@ enum priv_lvl_t { enum KnobType { KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT, KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL, + KNOBCOMPLEX, KNOBCOMPLEXD, KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE, KNOBVECSTRING, KNOBVECLONG }; diff --git a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h index e405f4e1ea..4431d15bd8 100644 --- a/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h +++ b/gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h @@ -170,6 +170,23 @@ public: }; template<typename T> +class rpcbasic_extractor<T,std::complex<float> > + : public virtual rpcextractor_base<T,std::complex<float> > +{ +public: + rpcbasic_extractor(T* source, void (T::*func)(std::complex<float>)) + : rpcextractor_base<T,std::complex<float> >(source, func) + {;} + + void post(pmt::pmt_t which_port, pmt::pmt_t msg) + { + std::complex<float> k = static_cast<std::complex<float> >(pmt::to_complex(msg)); + (rpcextractor_base<T,std::complex<float> >:: + _source->*rpcextractor_base<T,std::complex<float> >::_func)(k); + } +}; + +template<typename T> class rpcbasic_extractor<T,std::complex<double> > : public virtual rpcextractor_base<T,std::complex<double> > { @@ -305,6 +322,46 @@ public: } }; +template<typename T> +class rpcbasic_inserter<T,std::complex<float> > + : public virtual rpcinserter_base<T,std::complex<float > > { +public: + rpcbasic_inserter(T* source, std::complex<float> (T::*func)() const) + : rpcinserter_base<T,std::complex<float> >(source, func) + {;} + + rpcbasic_inserter(T* source, std::complex<float> (T::*func)()) + : rpcinserter_base<T,std::complex<float> >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::complex<float > k((rpcinserter_base<T,std::complex<float> >:: + _source->*rpcinserter_base<T,std::complex<float> >::_func)()); + return pmt::from_complex(k); + } +}; + +template<typename T> +class rpcbasic_inserter<T,std::complex<double> > + : public virtual rpcinserter_base<T,std::complex<double > > { +public: + rpcbasic_inserter(T* source, std::complex<double> (T::*func)() const) + : rpcinserter_base<T,std::complex<double> >(source, func) + {;} + + rpcbasic_inserter(T* source, std::complex<double> (T::*func)()) + : rpcinserter_base<T,std::complex<double> >(source, func) + {;} + + pmt::pmt_t retrieve() + { + std::complex<double > k((rpcinserter_base<T,std::complex<double> >:: + _source->*rpcinserter_base<T,std::complex<double> >::_func)()); + return pmt::from_complex(k); + } +}; + template <typename T> struct rpc_register_base { diff --git a/gnuradio-runtime/include/gnuradio/rpcserver_ice.h b/gnuradio-runtime/include/gnuradio/rpcserver_ice.h index f1e65bbbc8..c1c3d46a42 100644 --- a/gnuradio-runtime/include/gnuradio/rpcserver_ice.h +++ b/gnuradio-runtime/include/gnuradio/rpcserver_ice.h @@ -73,7 +73,7 @@ private: ConfigureCallbackMap_t::const_iterator iter(d_setcallbackmap.find(p.first)); if(iter != d_setcallbackmap.end()) { if(cur_priv <= iter->second.priv) { - (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::to_pmt(p.second,c)); + (*iter->second.callback).post(pmt::PMT_NIL, rpcpmtconverter::to_pmt(p.second,c)); } else { std::cout << "Key " << p.first << " requires PRIVLVL <= " diff --git a/gnuradio-runtime/lib/controlport/gnuradio.ice b/gnuradio-runtime/lib/controlport/gnuradio.ice index 29ddc2bfbe..8318875926 100644 --- a/gnuradio-runtime/lib/controlport/gnuradio.ice +++ b/gnuradio-runtime/lib/controlport/gnuradio.ice @@ -25,6 +25,12 @@ #define GNURADIO_DEBUG module GNURadio { + +struct complex { + float re; + float im; +}; + class Knob {}; class KnobB extends Knob { bool value; }; class KnobC extends Knob { byte value; }; @@ -33,6 +39,7 @@ class KnobF extends Knob { float value; }; class KnobD extends Knob { double value; }; class KnobL extends Knob { long value; }; class KnobS extends Knob { string value; }; +class KnobZ extends Knob { complex value; }; sequence<bool> VectorB; sequence<byte> VectorC; sequence<int> VectorI; sequence<float> VectorF; diff --git a/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc b/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc index 18b73faeba..9a36d6d31a 100644 --- a/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc +++ b/gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc @@ -42,7 +42,13 @@ rpcpmtconverter::from_pmt(const pmt::pmt_t& knob, const Ice::Current& c) } else if(pmt::is_uint64(knob)) { return new GNURadio::KnobL(pmt::to_uint64(knob)); - //const std::complex<float> *c32vector_elements(pmt_t v, size_t &len); //< len is in elements + } + else if(pmt::is_complex(knob)) { + std::complex<double> tmp = pmt::to_complex(knob); + GNURadio::complex cpx; + cpx.re = tmp.real(); + cpx.im = tmp.imag(); + return new GNURadio::KnobZ(cpx); } else if(pmt::is_c32vector(knob)) { // c32 sent as interleaved floats size_t size(pmt::length(knob)); @@ -102,6 +108,13 @@ rpcpmtconverter::to_pmt(const GNURadio::KnobPtr& knob, const Ice::Current& c) GNURadio::KnobLPtr k(GNURadio::KnobLPtr::dynamicCast(knob)); return pmt::mp((long)k->value); } + else if(id == "KnobZ") { + GNURadio::KnobZPtr k(GNURadio::KnobZPtr::dynamicCast(knob)); + std::complex<double> cpx; + cpx.real(k->value.re); + cpx.imag(k->value.im); + return pmt::from_complex(cpx); + } else if(id == "KnobVecC") { GNURadio::KnobVecCPtr k(GNURadio::KnobVecCPtr::dynamicCast(knob)); return pmt::init_u8vector(k->value.size(), &k->value[0]); diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py index 8597ca6497..4e9ef13133 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py @@ -23,6 +23,7 @@ from gnuradio import gr from gnuradio import blocks from gnuradio import filter +from gnuradio.ctrlport import GNURadio import sys, time try: @@ -248,11 +249,11 @@ class GrDataPlotterF(GrDataPlotParent): class GrDataPlotterConst(GrDataPlotParent): - def __init__(self, name, rate, pmin=None, pmax=None): + def __init__(self, name, rate, pmin=None, pmax=None, stripchart=False): GrDataPlotParent.__init__(self, name, rate, pmin, pmax) self._datasize = gr.sizeof_gr_complex - self._stripchart = False + self._stripchart = stripchart self._iscomplex = True self._setup(1) @@ -422,7 +423,11 @@ class GrDataPlotterValueTable: items = []; self.treeWidget.clear() for k, v in knobs.iteritems(): - items.append(QtGui.QTreeWidgetItem([str(k), str(v.value), + val = v.value + if(type(val) == GNURadio.complex): + val = val.re + val.im*1j + + items.append(QtGui.QTreeWidgetItem([str(k), str(val), knobprops[k].units, knobprops[k].description])) self.treeWidget.insertTopLevelItems(0, items) diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor index e71cd92ab7..ac6e6a4675 100755 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor @@ -111,14 +111,21 @@ class MAINWindow(QtGui.QMainWindow): props = radio.properties([key]) pmin = props[key].min.value pmax = props[key].max.value + + # Convert from GNURadio::complex to Python complex + if(type(pmin) == GNURadio.complex): + pmin = pmin.re + pmin.im*1j + if(type(pmax) == GNURadio.complex): + pmax = pmax.re + pmax.im*1j + if pmin == []: pmin = None else: - pmin = 1.1*pmin + pmin = 1.1*abs(pmin) if pmax == []: pmax = None else: - pmax = 1.1*pmax + pmax = 1.1*abs(pmax) # Use display option mask of item to set up available plot # types and default options. @@ -141,7 +148,8 @@ class MAINWindow(QtGui.QMainWindow): log, strip, stem) def newPlotterConstProxy(): - self.newPlotConst(key, uid, title, pmin, pmax, scatter) + self.newPlotConst(key, uid, title, pmin, pmax, + scatter, strip) def newPlotterPsdFProxy(): self.newPlotPsdF(key, uid, title) @@ -191,6 +199,12 @@ class MAINWindow(QtGui.QMainWindow): title = "{0}:{1}".format(r[3], r[5]) pmin = knobprop.min.value pmax = knobprop.max.value + + if(type(pmin) == GNURadio.complex): + pmin = pmin.re + pmin.im*1j + if(type(pmax) == GNURadio.complex): + pmax = pmax.re + pmax.im*1j + if pmin == []: pmin = None else: @@ -280,8 +294,8 @@ class MAINWindow(QtGui.QMainWindow): break def newPlotConst(self, tag, uid, title="", pmin=None, pmax=None, - scatter=False): - plot = GrDataPlotterConst(tag, 32e6, pmin, pmax) + scatter=False, stripchart=False): + plot = GrDataPlotterConst(tag, 32e6, pmin, pmax, stripchart) plot.scatter(scatter) self.createPlot(plot, uid, title) @@ -320,7 +334,10 @@ class MAINWindow(QtGui.QMainWindow): for plot in self.plots[uid]: data = [] for n in plot.knobnames: - data.append(knobs[n].value) + d = knobs[n].value + if(type(d) == GNURadio.complex): + d = [d.re, d.im] + data.append(d) plot.update(data) plot.stop() plot.wait() @@ -513,7 +530,7 @@ class UpdaterWindow(QtGui.QDialog): self.infoLabel = QtGui.QLabel(info) self.layout.addWidget(self.infoLabel) - # Test here to make sure that a 'set' function + # Test here to make sure that a 'set' function exists try: a = radio.set(radio.get([key])) has_set = True @@ -537,7 +554,11 @@ class UpdaterWindow(QtGui.QDialog): self.cancelButton = QtGui.QPushButton("Cancel") rv = radio.get([key]) - self.textInput.setText(str(rv[key].value)) + val = rv[key].value + if(type(val) == GNURadio.complex): + val = val.re + val.im*1j + + self.textInput.setText(str(val)) self.sv = rv[key] self.applyButton.connect(self.applyButton, QtCore.SIGNAL('clicked()'), self._apply) @@ -563,12 +584,14 @@ class UpdaterWindow(QtGui.QDialog): self.connect(self.slider, QtCore.SIGNAL("sliderReleased()"), self._slide) self.layout.addLayout(self.sliderlayout) + else: + self._set_slider_value = None - self.buttonlayout = QtGui.QHBoxLayout() - self.buttonlayout.addWidget(self.applyButton) - self.buttonlayout.addWidget(self.setButton) - self.buttonlayout.addWidget(self.cancelButton) - self.layout.addLayout(self.buttonlayout) + self.buttonlayout = QtGui.QHBoxLayout() + self.buttonlayout.addWidget(self.applyButton) + self.buttonlayout.addWidget(self.setButton) + self.buttonlayout.addWidget(self.cancelButton) + self.layout.addLayout(self.buttonlayout) # set layout and go... self.setLayout(self.layout) @@ -587,15 +610,22 @@ class UpdaterWindow(QtGui.QDialog): val = int(round(float(self.textInput.text()))) elif(type(self.sv.value) == float): val = float(self.textInput.text()) + elif(type(self.sv.value) == GNURadio.complex): + t = str(self.textInput.text()) + t = complex(t.strip("(").strip(")").replace(" ", "")) + val = GNURadio.complex() + val.re = t.real + val.im = t.imag else: sys.stderr.write("set type not supported! ({0})\n".format(type(self.sv.value))) - sys.exit(-1) + return self.sv.value = val km = {} km[self.key] = self.sv self.radio.set(km) - self._set_slider_value(self.sv.value) + if self._set_slider_value: + self._set_slider_value(self.sv.value) def _set(self): self._apply() diff --git a/gnuradio-runtime/swig/gr_ctrlport.i b/gnuradio-runtime/swig/gr_ctrlport.i index ac05c05ee5..d7fde34db3 100644 --- a/gnuradio-runtime/swig/gr_ctrlport.i +++ b/gnuradio-runtime/swig/gr_ctrlport.i @@ -48,6 +48,7 @@ enum priv_lvl_t { enum KnobType { KNOBBOOL, KNOBCHAR, KNOBINT, KNOBFLOAT, KNOBDOUBLE, KNOBSTRING, KNOBLONG, KNOBVECBOOL, + KNOBCOMPLEX, KNOBCOMPLEXD, KNOBVECCHAR, KNOBVECINT, KNOBVECFLOAT, KNOBVECDOUBLE, KNOBVECSTRING, KNOBVECLONG }; @@ -91,6 +92,8 @@ class GR_RUNTIME_API rpcmanager : public virtual rpcmanager_base %template(RPC_get_int) pycallback_object<int>; %template(RPC_get_float) pycallback_object<float>; %template(RPC_get_double) pycallback_object<double>; +%template(RPC_get_complex) pycallback_object<gr_complex>; +%template(RPC_get_complexd) pycallback_object<gr_complexd>; %template(RPC_get_vector_float) pycallback_object<std::vector<float> >; %template(RPC_get_vector_gr_complex) pycallback_object<std::vector<gr_complex> >; diff --git a/gr-blocks/lib/multiply_const_cc_impl.cc b/gr-blocks/lib/multiply_const_cc_impl.cc index 1f363fd4a3..d0393907b0 100644 --- a/gr-blocks/lib/multiply_const_cc_impl.cc +++ b/gr-blocks/lib/multiply_const_cc_impl.cc @@ -68,5 +68,31 @@ namespace gr { return noutput_items; } + void + multiply_const_cc_impl::setup_rpc() + { +#ifdef GR_CTRLPORT + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_get<multiply_const_cc, gr_complex>( + alias(), "Constant", + &multiply_const_cc::k, + pmt::from_complex(-1000.0f, 0.0f), + pmt::from_complex(1000.0f, 0.0f), + pmt::from_complex(0.0f, 0.0f), + "", "Constant to multiply", RPC_PRIVLVL_MIN, + DISPTIME | DISPOPTCPLX | DISPOPTSTRIP))); + + add_rpc_variable( + rpcbasic_sptr(new rpcbasic_register_set<multiply_const_cc, gr_complex>( + alias(), "Constant", + &multiply_const_cc::set_k, + pmt::from_complex(-1000.0f, 0.0f), + pmt::from_complex(1000.0f, 0.0f), + pmt::from_complex(0.0f, 0.0f), + "", "Constant to multiply", + RPC_PRIVLVL_MIN, DISPNULL))); +#endif /* GR_CTRLPORT */ + } + } /* namespace blocks */ } /* namespace gr */ diff --git a/gr-blocks/lib/multiply_const_cc_impl.h b/gr-blocks/lib/multiply_const_cc_impl.h index bdd7017c8f..29ba6dd14c 100644 --- a/gr-blocks/lib/multiply_const_cc_impl.h +++ b/gr-blocks/lib/multiply_const_cc_impl.h @@ -38,6 +38,8 @@ namespace gr { public: multiply_const_cc_impl(gr_complex k, size_t vlen); + void setup_rpc(); + gr_complex k() const { return d_k; } void set_k(gr_complex k) { d_k = k; } |