summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rondeau <trondeau@vt.edu>2013-06-18 15:08:17 -0400
committerTom Rondeau <trondeau@vt.edu>2013-06-18 15:08:17 -0400
commitad1d52fd9911114ad8c9748e808b55de4e16232b (patch)
treebb5696ca8617290e5ae76672544f308e3a21baae
parentbec07463ddb722ed22bae83577ffe4c8029ff90d (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.h1
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcregisterhelpers.h57
-rw-r--r--gnuradio-runtime/include/gnuradio/rpcserver_ice.h2
-rw-r--r--gnuradio-runtime/lib/controlport/gnuradio.ice7
-rw-r--r--gnuradio-runtime/lib/controlport/rpcpmtconverters_ice.cc15
-rw-r--r--gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py11
-rwxr-xr-xgnuradio-runtime/python/gnuradio/ctrlport/gr-ctrlport-monitor60
-rw-r--r--gnuradio-runtime/swig/gr_ctrlport.i3
-rw-r--r--gr-blocks/lib/multiply_const_cc_impl.cc26
-rw-r--r--gr-blocks/lib/multiply_const_cc_impl.h2
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; }