[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] [gnuradio] 01/05: qtgui: adding a trigger for the cons
From: |
git |
Subject: |
[Commit-gnuradio] [gnuradio] 01/05: qtgui: adding a trigger for the constellation plots. Probably most useful with tags, but normal and auto triggering supported, too. |
Date: |
Fri, 25 Apr 2014 16:44:46 +0000 (UTC) |
This is an automated email from the git hooks/post-receive script.
trondeau pushed a commit to branch master
in repository gnuradio.
commit d78d1ce2069ae20c86f9f301d89f303c2ae5942e
Author: Tom Rondeau <address@hidden>
Date: Thu Apr 24 14:10:26 2014 -0400
qtgui: adding a trigger for the constellation plots. Probably most useful
with tags, but normal and auto triggering supported, too.
Updates test_corr_and_sync block to use the time_est tag to trigger
constellation plot.
---
gr-digital/examples/demod/test_corr_and_sync.grc | 176 +++++++------
gr-qtgui/grc/qtgui_const_sink_x.xml | 79 ++++++
gr-qtgui/include/gnuradio/qtgui/const_sink_c.h | 41 +++-
.../gnuradio/qtgui/constellationdisplayform.h | 31 ++-
gr-qtgui/include/gnuradio/qtgui/time_sink_c.h | 49 +++-
gr-qtgui/include/gnuradio/qtgui/time_sink_f.h | 41 +++-
gr-qtgui/lib/const_sink_c_impl.cc | 272 +++++++++++++++------
gr-qtgui/lib/const_sink_c_impl.h | 27 +-
gr-qtgui/lib/constellationdisplayform.cc | 138 ++++++++++-
gr-qtgui/lib/time_sink_c_impl.cc | 2 +-
10 files changed, 692 insertions(+), 164 deletions(-)
diff --git a/gr-digital/examples/demod/test_corr_and_sync.grc
b/gr-digital/examples/demod/test_corr_and_sync.grc
index 8701690..496a0be 100644
--- a/gr-digital/examples/demod/test_corr_and_sync.grc
+++ b/gr-digital/examples/demod/test_corr_and_sync.grc
@@ -1,6 +1,6 @@
<?xml version='1.0' encoding='ASCII'?>
<flow_graph>
- <timestamp>Thu Apr 10 15:34:59 2014</timestamp>
+ <timestamp>Thu Apr 24 14:08:23 2014</timestamp>
<block>
<key>options</key>
<param>
@@ -64,30 +64,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>samp_rate</value>
- </param>
- <param>
- <key>_enabled</key>
- <value>True</value>
- </param>
- <param>
- <key>value</key>
- <value>100000</value>
- </param>
- <param>
- <key>_coordinate</key>
- <value>(11, 72)</value>
- </param>
- <param>
- <key>_rotation</key>
- <value>0</value>
- </param>
- </block>
- <block>
- <key>variable</key>
- <param>
- <key>id</key>
- <value>eb</value>
+ <value>rrc_taps</value>
</param>
<param>
<key>_enabled</key>
@@ -95,11 +72,11 @@
</param>
<param>
<key>value</key>
- <value>0.35</value>
+ <value>firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), eb,
5*sps*nfilts)</value>
</param>
<param>
<key>_coordinate</key>
- <value>(346, 72)</value>
+ <value>(1075, 73)</value>
</param>
<param>
<key>_rotation</key>
@@ -110,7 +87,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>matched_filter</value>
+ <value>nfilts</value>
</param>
<param>
<key>_enabled</key>
@@ -118,11 +95,11 @@
</param>
<param>
<key>value</key>
- <value>firdes.root_raised_cosine(nfilts, nfilts, 1, eb,
int(11*sps*nfilts))</value>
+ <value>32</value>
</param>
<param>
<key>_coordinate</key>
- <value>(429, 72)</value>
+ <value>(1074, 9)</value>
</param>
<param>
<key>_rotation</key>
@@ -133,7 +110,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>preamble</value>
+ <value>payload_size</value>
</param>
<param>
<key>_enabled</key>
@@ -141,11 +118,11 @@
</param>
<param>
<key>value</key>
-
<value>[1,-1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,1,1,1,-1,-1,-1,1,-1,1,1,1,1,-1,-1,1,-1,1,-1,-1,-1,1,1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1]</value>
+ <value>992</value>
</param>
<param>
<key>_coordinate</key>
- <value>(279, 8)</value>
+ <value>(101, 73)</value>
</param>
<param>
<key>_rotation</key>
@@ -156,7 +133,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>sps</value>
+ <value>gap</value>
</param>
<param>
<key>_enabled</key>
@@ -164,11 +141,11 @@
</param>
<param>
<key>value</key>
- <value>4</value>
+ <value>20000</value>
</param>
<param>
<key>_coordinate</key>
- <value>(278, 72)</value>
+ <value>(202, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -202,7 +179,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>gap</value>
+ <value>sps</value>
</param>
<param>
<key>_enabled</key>
@@ -210,11 +187,11 @@
</param>
<param>
<key>value</key>
- <value>20000</value>
+ <value>4</value>
</param>
<param>
<key>_coordinate</key>
- <value>(202, 72)</value>
+ <value>(278, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -225,7 +202,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>payload_size</value>
+ <value>preamble</value>
</param>
<param>
<key>_enabled</key>
@@ -233,11 +210,11 @@
</param>
<param>
<key>value</key>
- <value>992</value>
+
<value>[1,-1,1,-1,1,1,-1,-1,1,1,-1,1,1,1,-1,1,1,-1,1,-1,-1,1,-1,-1,1,1,1,-1,-1,-1,1,-1,1,1,1,1,-1,-1,1,-1,1,-1,-1,-1,1,1,-1,-1,-1,-1,1,-1,-1,-1,-1,-1,1,1,1,1,1,1,-1,-1]</value>
</param>
<param>
<key>_coordinate</key>
- <value>(101, 73)</value>
+ <value>(279, 8)</value>
</param>
<param>
<key>_rotation</key>
@@ -248,7 +225,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>nfilts</value>
+ <value>matched_filter</value>
</param>
<param>
<key>_enabled</key>
@@ -256,11 +233,11 @@
</param>
<param>
<key>value</key>
- <value>32</value>
+ <value>firdes.root_raised_cosine(nfilts, nfilts, 1, eb,
int(11*sps*nfilts))</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1074, 9)</value>
+ <value>(429, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -271,7 +248,7 @@
<key>variable</key>
<param>
<key>id</key>
- <value>rrc_taps</value>
+ <value>eb</value>
</param>
<param>
<key>_enabled</key>
@@ -279,11 +256,11 @@
</param>
<param>
<key>value</key>
- <value>firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), eb,
5*sps*nfilts)</value>
+ <value>0.35</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1075, 73)</value>
+ <value>(346, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -291,38 +268,22 @@
</param>
</block>
<block>
- <key>digital_costas_loop_cc</key>
+ <key>variable</key>
<param>
<key>id</key>
- <value>digital_costas_loop_cc_0</value>
+ <value>samp_rate</value>
</param>
<param>
<key>_enabled</key>
<value>True</value>
</param>
<param>
- <key>w</key>
- <value>1*3.14/50.0</value>
- </param>
- <param>
- <key>order</key>
- <value>2</value>
- </param>
- <param>
- <key>affinity</key>
- <value></value>
- </param>
- <param>
- <key>minoutbuf</key>
- <value>0</value>
- </param>
- <param>
- <key>maxoutbuf</key>
- <value>0</value>
+ <key>value</key>
+ <value>100000</value>
</param>
<param>
<key>_coordinate</key>
- <value>(1091, 303)</value>
+ <value>(11, 72)</value>
</param>
<param>
<key>_rotation</key>
@@ -2611,10 +2572,49 @@
</param>
</block>
<block>
+ <key>digital_costas_loop_cc</key>
+ <param>
+ <key>id</key>
+ <value>digital_costas_loop_cc_0</value>
+ </param>
+ <param>
+ <key>_enabled</key>
+ <value>True</value>
+ </param>
+ <param>
+ <key>w</key>
+ <value>1*3.14/50.0</value>
+ </param>
+ <param>
+ <key>order</key>
+ <value>2</value>
+ </param>
+ <param>
+ <key>affinity</key>
+ <value></value>
+ </param>
+ <param>
+ <key>minoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>maxoutbuf</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>_coordinate</key>
+ <value>(1091, 303)</value>
+ </param>
+ <param>
+ <key>_rotation</key>
+ <value>0</value>
+ </param>
+ </block>
+ <block>
<key>qtgui_const_sink_x</key>
<param>
<key>id</key>
- <value>qtgui_const_sink_x_0_0</value>
+ <value>qtgui_const_sink_x_0</value>
</param>
<param>
<key>_enabled</key>
@@ -2630,7 +2630,7 @@
</param>
<param>
<key>size</key>
- <value>20000</value>
+ <value>1000</value>
</param>
<param>
<key>autoscale</key>
@@ -2665,6 +2665,26 @@
<value>0,1,1,1</value>
</param>
<param>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_TAG</value>
+ </param>
+ <param>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_SLOPE_POS</value>
+ </param>
+ <param>
+ <key>tr_level</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_chan</key>
+ <value>0</value>
+ </param>
+ <param>
+ <key>tr_tag</key>
+ <value>time_est</value>
+ </param>
+ <param>
<key>label1</key>
<value></value>
</param>
@@ -2910,7 +2930,7 @@
</param>
<param>
<key>_coordinate</key>
- <value>(1399, 291)</value>
+ <value>(1399, 283)</value>
</param>
<param>
<key>_rotation</key>
@@ -2919,12 +2939,6 @@
</block>
<connection>
<source_block_id>digital_costas_loop_cc_0</source_block_id>
- <sink_block_id>qtgui_const_sink_x_0_0</sink_block_id>
- <source_key>0</source_key>
- <sink_key>0</sink_key>
- </connection>
- <connection>
- <source_block_id>digital_costas_loop_cc_0</source_block_id>
<sink_block_id>qtgui_time_sink_x_0</sink_block_id>
<source_key>0</source_key>
<sink_key>0</sink_key>
@@ -3097,4 +3111,10 @@
<source_key>0</source_key>
<sink_key>0</sink_key>
</connection>
+ <connection>
+ <source_block_id>digital_costas_loop_cc_0</source_block_id>
+ <sink_block_id>qtgui_const_sink_x_0</sink_block_id>
+ <source_key>0</source_key>
+ <sink_key>0</sink_key>
+ </connection>
</flow_graph>
diff --git a/gr-qtgui/grc/qtgui_const_sink_x.xml
b/gr-qtgui/grc/qtgui_const_sink_x.xml
index 08f9064..3b549e2 100644
--- a/gr-qtgui/grc/qtgui_const_sink_x.xml
+++ b/gr-qtgui/grc/qtgui_const_sink_x.xml
@@ -19,6 +19,7 @@ qtgui.$(type.fcn)(
self.$(id).set_update_time($update_time)
self.$(id).set_y_axis($ymin, $ymax)
self.$(id).set_x_axis($xmin, $xmax)
+self.$(id).set_trigger_mode($tr_mode, $tr_slope, $tr_level, $tr_chan, $tr_tag)
self.$(id).enable_autoscale($autoscale)
labels = [$label1, $label2, $label3, $label4, $label5,
@@ -51,6 +52,12 @@ $(gui_hint()($win))</make>
<callback>set_title($which, $title)</callback>
<callback>set_color($which, $color)</callback>
+ <param_tab_order>
+ <tab>General</tab>
+ <tab>Trigger</tab>
+ <tab>Config</tab>
+ </param_tab_order>
+
<param>
<name>Type</name>
<key>type</key>
@@ -137,6 +144,78 @@ $(gui_hint()($win))</make>
<hide>part</hide>
</param>
+
+ <param>
+ <name>Trigger Mode</name>
+ <key>tr_mode</key>
+ <value>qtgui.TRIG_MODE_FREE</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Free</name>
+ <key>qtgui.TRIG_MODE_FREE</key>
+ </option>
+ <option>
+ <name>Auto</name>
+ <key>qtgui.TRIG_MODE_AUTO</key>
+ </option>
+ <option>
+ <name>Normal</name>
+ <key>qtgui.TRIG_MODE_NORM</key>
+ </option>
+ <option>
+ <name>Tag</name>
+ <key>qtgui.TRIG_MODE_TAG</key>
+ </option>
+ <tab>Trigger</tab>
+ </param>
+
+ <param>
+ <name>Trigger Slope</name>
+ <key>tr_slope</key>
+ <value>qtgui.TRIG_MODE_POS</value>
+ <type>enum</type>
+ <hide>part</hide>
+ <option>
+ <name>Positive</name>
+ <key>qtgui.TRIG_SLOPE_POS</key>
+ </option>
+ <option>
+ <name>Negative</name>
+ <key>qtgui.TRIG_SLOPE_NEG</key>
+ </option>
+ <tab>Trigger</tab>
+ </param>
+
+ <param>
+ <name>Trigger Level</name>
+ <key>tr_level</key>
+ <value>0.0</value>
+ <type>float</type>
+ <hide>part</hide>
+ <tab>Trigger</tab>
+ </param>
+
+ <param>
+ <name>Trigger Channel</name>
+ <key>tr_chan</key>
+ <value>0</value>
+ <type>int</type>
+ <hide>part</hide>
+ <tab>Trigger</tab>
+ </param>
+
+ <param>
+ <name>Trigger Tag Key</name>
+ <key>tr_tag</key>
+ <value>""</value>
+ <type>string</type>
+ <hide>part</hide>
+ <tab>Trigger</tab>
+ </param>
+
+
+
<param>
<name>Line 1 Label</name>
<key>label1</key>
diff --git a/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
b/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
index f413ce9..84f9a87 100644
--- a/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/const_sink_c.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -28,13 +28,14 @@
#endif
#include <gnuradio/qtgui/api.h>
+#include <gnuradio/qtgui/trigger_mode.h>
#include <gnuradio/sync_block.h>
#include <qapplication.h>
#include <gnuradio/filter/firdes.h>
namespace gr {
namespace qtgui {
-
+
/*!
* \brief A graphical sink to display the IQ constellation of multiple
signals.
* \ingroup instrumentation_blk
@@ -51,7 +52,7 @@ namespace gr {
typedef boost::shared_ptr<const_sink_c> sptr;
/*!
- * \brief Build a complex PSD sink.
+ * \brief Build a constellation plot sink.
*
* \param size number of points to plot at once
* \param name title for the plot
@@ -85,6 +86,40 @@ namespace gr {
virtual void set_nsamps(const int newsize) = 0;
virtual void set_line_alpha(int which, double alpha) = 0;
+ /*!
+ * Set up a trigger for the sink to know when to start
+ * plotting. Useful to isolate events and avoid noise.
+ *
+ * The trigger modes are Free, Auto, Normal, and Tag (see
+ * gr::qtgui::trigger_mode). The first three are like a normal
+ * oscope trigger function. Free means free running with no
+ * trigger, auto will trigger if the trigger event is seen, but
+ * will still plot otherwise, and normal will hold until the
+ * trigger event is observed. The Tag trigger mode allows us to
+ * trigger off a specific stream tag. The tag trigger is based
+ * only on the name of the tag, so when a tag of the given name
+ * is seen, the trigger is activated.
+ *
+ * In auto and normal mode, we look for the slope of the
+ * magnitude of the signal. As a constellation sink, this only
+ * takes in complex numbers to plot. Given a
+ * gr::qtgui::trigger_slope as either Positive or Negative, if
+ * the magnitude between two samples moves in the given
+ * direction (x[1] > x[0] for Positive or x[1] < x[0] for
+ * Negative), then the trigger is activated.
+ *
+ * \param mode The trigger_mode: free, auto, normal, or tag.
+ * \param slope The trigger_slope: positive or negative. Only
+ * used for auto and normal modes.
+ * \param level The magnitude of the trigger even for auto or normal
modes.
+ * \param channel Which input channel to use for the trigger events.
+ * \param tag_key The name (as a string) of the tag to trigger off
+ * of if using the tag mode.
+ */
+ virtual void set_trigger_mode(trigger_mode mode, trigger_slope slope,
+ float level, int channel,
+ const std::string &tag_key="") = 0;
+
virtual std::string title() = 0;
virtual std::string line_label(int which) = 0;
virtual std::string line_color(int which) = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/constellationdisplayform.h
b/gr-qtgui/include/gnuradio/qtgui/constellationdisplayform.h
index fb14388..e75eac9 100644
--- a/gr-qtgui/include/gnuradio/qtgui/constellationdisplayform.h
+++ b/gr-qtgui/include/gnuradio/qtgui/constellationdisplayform.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -46,6 +46,11 @@ public:
ConstellationDisplayPlot* getPlot();
int getNPoints() const;
+ gr::qtgui::trigger_mode getTriggerMode() const;
+ gr::qtgui::trigger_slope getTriggerSlope() const;
+ float getTriggerLevel() const;
+ int getTriggerChannel() const;
+ std::string getTriggerTagKey() const;
public slots:
void customEvent(QEvent * e);
@@ -56,12 +61,36 @@ public slots:
void setXaxis(double min, double max);
void autoScale(bool en);
+ void updateTrigger(gr::qtgui::trigger_mode mode);
+ void setTriggerMode(gr::qtgui::trigger_mode mode);
+ void setTriggerSlope(gr::qtgui::trigger_slope slope);
+ void setTriggerLevel(QString s);
+ void setTriggerLevel(float level);
+ void setTriggerChannel(int chan);
+ void setTriggerTagKey(QString s);
+ void setTriggerTagKey(const std::string &s);
+
private slots:
void newData(const QEvent*);
private:
QIntValidator* d_int_validator;
int d_npoints;
+
+ NPointsMenu *d_nptsmenu;
+
+ QMenu *d_triggermenu;
+ TriggerModeMenu *d_tr_mode_menu;
+ TriggerSlopeMenu *d_tr_slope_menu;
+ PopupMenu *d_tr_level_act;
+ TriggerChannelMenu *d_tr_channel_menu;
+ PopupMenu *d_tr_tag_key_act;
+
+ gr::qtgui::trigger_mode d_trig_mode;
+ gr::qtgui::trigger_slope d_trig_slope;
+ float d_trig_level;
+ int d_trig_channel;
+ std::string d_trig_tag_key;
};
#endif /* CONSTELLATION_DISPLAY_FORM_H */
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
index 2d52485..8ce6e2e 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h
@@ -34,7 +34,7 @@
namespace gr {
namespace qtgui {
-
+
/*!
* \brief A graphical sink to display multiple signals in time.
* \ingroup instrumentation_blk
@@ -88,6 +88,53 @@ namespace gr {
virtual void set_nsamps(const int newsize) = 0;
virtual void set_samp_rate(const double samp_rate) = 0;
virtual void set_line_alpha(int which, double alpha) = 0;
+
+ /*!
+ * Set up a trigger for the sink to know when to start
+ * plotting. Useful to isolate events and avoid noise.
+ *
+ * The trigger modes are Free, Auto, Normal, and Tag (see
+ * gr::qtgui::trigger_mode). The first three are like a normal
+ * oscope trigger function. Free means free running with no
+ * trigger, auto will trigger if the trigger event is seen, but
+ * will still plot otherwise, and normal will hold until the
+ * trigger event is observed. The Tag trigger mode allows us to
+ * trigger off a specific stream tag. The tag trigger is based
+ * only on the name of the tag, so when a tag of the given name
+ * is seen, the trigger is activated.
+ *
+ * In auto and normal mode, we look for the slope of the of the
+ * signal. Given a gr::qtgui::trigger_slope as either Positive
+ * or Negative, if the value between two samples moves in the
+ * given direction (x[1] > x[0] for Positive or x[1] < x[0] for
+ * Negative), then the trigger is activated.
+ *
+ * With the complex time sink, each input has two lines drawn
+ * for the real and imaginary parts of the signal. When
+ * selecting the \p channel value, channel 0 is the real signal
+ * and channel 1 is the imaginary signal. For more than 1 input
+ * stream, channel 2i is the real part of the ith input and
+ * channel (2i+1) is the imaginary part of the ith input
+ * channel.
+ *
+ * The \p delay value is specified in time based off the sample
+ * rate. If the sample rate of the block is set to 1, the delay
+ * is then also the sample number offset. This is the offset
+ * from the left-hand y-axis of the plot. It delays the signal
+ * to show the trigger event at the given delay along with some
+ * portion of the signal before the event. The delay must be
+ * within 0 - t_max where t_max is the maximum amount of time
+ * displayed on the time plot.
+ *
+ * \param mode The trigger_mode: free, auto, normal, or tag.
+ * \param slope The trigger_slope: positive or negative. Only
+ * used for auto and normal modes.
+ * \param level The magnitude of the trigger even for auto or normal
modes.
+ * \param delay The delay (in units of time) for where the trigger
happens.
+ * \param channel Which input channel to use for the trigger events.
+ * \param tag_key The name (as a string) of the tag to trigger off
+ * of if using the tag mode.
+ */
virtual void set_trigger_mode(trigger_mode mode, trigger_slope slope,
float level, float delay, int channel,
const std::string &tag_key="") = 0;
diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
index add53ef..1a09492 100644
--- a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
+++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h
@@ -34,7 +34,7 @@
namespace gr {
namespace qtgui {
-
+
/*!
* \brief A graphical sink to display multiple signals in time.
* \ingroup instrumentation_blk
@@ -86,6 +86,45 @@ namespace gr {
virtual void set_nsamps(const int newsize) = 0;
virtual void set_samp_rate(const double samp_rate) = 0;
virtual void set_line_alpha(int which, double alpha) = 0;
+
+ /*!
+ * Set up a trigger for the sink to know when to start
+ * plotting. Useful to isolate events and avoid noise.
+ *
+ * The trigger modes are Free, Auto, Normal, and Tag (see
+ * gr::qtgui::trigger_mode). The first three are like a normal
+ * oscope trigger function. Free means free running with no
+ * trigger, auto will trigger if the trigger event is seen, but
+ * will still plot otherwise, and normal will hold until the
+ * trigger event is observed. The Tag trigger mode allows us to
+ * trigger off a specific stream tag. The tag trigger is based
+ * only on the name of the tag, so when a tag of the given name
+ * is seen, the trigger is activated.
+ *
+ * In auto and normal mode, we look for the slope of the of the
+ * signal. Given a gr::qtgui::trigger_slope as either Positive
+ * or Negative, if the value between two samples moves in the
+ * given direction (x[1] > x[0] for Positive or x[1] < x[0] for
+ * Negative), then the trigger is activated.
+ *
+ * The \p delay value is specified in time based off the sample
+ * rate. If the sample rate of the block is set to 1, the delay
+ * is then also the sample number offset. This is the offset
+ * from the left-hand y-axis of the plot. It delays the signal
+ * to show the trigger event at the given delay along with some
+ * portion of the signal before the event. The delay must be
+ * within 0 - t_max where t_max is the maximum amount of time
+ * displayed on the time plot.
+ *
+ * \param mode The trigger_mode: free, auto, normal, or tag.
+ * \param slope The trigger_slope: positive or negative. Only
+ * used for auto and normal modes.
+ * \param level The magnitude of the trigger even for auto or normal
modes.
+ * \param delay The delay (in units of time) for where the trigger
happens.
+ * \param channel Which input channel to use for the trigger events.
+ * \param tag_key The name (as a string) of the tag to trigger off
+ * of if using the tag mode.
+ */
virtual void set_trigger_mode(trigger_mode mode, trigger_slope slope,
float level, float delay, int channel,
const std::string &tag_key="") = 0;
diff --git a/gr-qtgui/lib/const_sink_c_impl.cc
b/gr-qtgui/lib/const_sink_c_impl.cc
index fb0cdad..a703336 100644
--- a/gr-qtgui/lib/const_sink_c_impl.cc
+++ b/gr-qtgui/lib/const_sink_c_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -49,9 +49,9 @@ namespace gr {
int nconnections,
QWidget *parent)
: sync_block("const_sink_c",
- io_signature::make(nconnections, nconnections,
sizeof(gr_complex)),
- io_signature::make(0, 0, 0)),
- d_size(size), d_name(name),
+ io_signature::make(nconnections, nconnections,
sizeof(gr_complex)),
+ io_signature::make(0, 0, 0)),
+ d_size(size), d_buffer_size(2*size), d_name(name),
d_nconnections(nconnections), d_parent(parent)
{
// Required now for Qt; argc must be greater than 0 and argv
@@ -67,12 +67,12 @@ namespace gr {
d_index = 0;
for(int i = 0; i < d_nconnections; i++) {
- d_residbufs_real.push_back((double*)volk_malloc(d_size*sizeof(double),
+
d_residbufs_real.push_back((double*)volk_malloc(d_buffer_size*sizeof(double),
volk_get_alignment()));
- d_residbufs_imag.push_back((double*)volk_malloc(d_size*sizeof(double),
+
d_residbufs_imag.push_back((double*)volk_malloc(d_buffer_size*sizeof(double),
volk_get_alignment()));
- memset(d_residbufs_real[i], 0, d_size*sizeof(double));
- memset(d_residbufs_imag[i], 0, d_size*sizeof(double));
+ memset(d_residbufs_real[i], 0, d_buffer_size*sizeof(double));
+ memset(d_residbufs_imag[i], 0, d_buffer_size*sizeof(double));
}
// Set alignment properties for VOLK
@@ -81,7 +81,12 @@ namespace gr {
set_alignment(std::max(1,alignment_multiple));
initialize();
- }
+
+ set_trigger_mode(TRIG_MODE_FREE, TRIG_SLOPE_POS, 0, 0);
+
+ set_history(2); // so we can look ahead for the trigger slope
+ declare_sample_delay(1); // delay the tags for a history of 2
+ }
const_sink_c_impl::~const_sink_c_impl()
{
@@ -221,6 +226,32 @@ namespace gr {
}
void
+ const_sink_c_impl::set_trigger_mode(trigger_mode mode,
+ trigger_slope slope,
+ float level,
+ int channel,
+ const std::string &tag_key)
+ {
+ gr::thread::scoped_lock lock(d_mutex);
+
+ d_trigger_mode = mode;
+ d_trigger_slope = slope;
+ d_trigger_level = level;
+ d_trigger_channel = channel;
+ d_trigger_tag_key = pmt::intern(tag_key);
+ d_triggered = false;
+ d_trigger_count = 0;
+
+ d_main_gui->setTriggerMode(d_trigger_mode);
+ d_main_gui->setTriggerSlope(d_trigger_slope);
+ d_main_gui->setTriggerLevel(d_trigger_level);
+ d_main_gui->setTriggerChannel(d_trigger_channel);
+ d_main_gui->setTriggerTagKey(tag_key);
+
+ _reset();
+ }
+
+ void
const_sink_c_impl::set_size(int width, int height)
{
d_main_gui->resize(QSize(width, height));
@@ -274,35 +305,29 @@ namespace gr {
gr::thread::scoped_lock lock(d_mutex);
if(newsize != d_size) {
+ // Set new size and reset buffer index
+ // (throws away any currently held data, but who cares?)
+ d_size = newsize;
+ d_buffer_size = 2*d_size;
+ d_index = 0;
+
// Resize residbuf and replace data
for(int i = 0; i < d_nconnections; i++) {
volk_free(d_residbufs_real[i]);
volk_free(d_residbufs_imag[i]);
- d_residbufs_real[i] = (double*)volk_malloc(newsize*sizeof(double),
+ d_residbufs_real[i] =
(double*)volk_malloc(d_buffer_size*sizeof(double),
volk_get_alignment());
- d_residbufs_imag[i] = (double*)volk_malloc(newsize*sizeof(double),
+ d_residbufs_imag[i] =
(double*)volk_malloc(d_buffer_size*sizeof(double),
volk_get_alignment());
- memset(d_residbufs_real[i], 0, newsize*sizeof(double));
- memset(d_residbufs_imag[i], 0, newsize*sizeof(double));
+ memset(d_residbufs_real[i], 0, d_buffer_size*sizeof(double));
+ memset(d_residbufs_imag[i], 0, d_buffer_size*sizeof(double));
}
- // Set new size and reset buffer index
- // (throws away any currently held data, but who cares?)
- d_size = newsize;
- d_index = 0;
-
d_main_gui->setNPoints(d_size);
}
}
- void
- const_sink_c_impl::npoints_resize()
- {
- int newsize = d_main_gui->getNPoints();
- set_nsamps(newsize);
- }
-
int
const_sink_c_impl::nsamps() const
{
@@ -324,7 +349,104 @@ namespace gr {
void
const_sink_c_impl::reset()
{
+ gr::thread::scoped_lock lock(d_mutex);
+ _reset();
+ }
+
+ void
+ const_sink_c_impl::_reset()
+ {
+ // Reset the start and end indices.
+ d_start = 0;
+ d_end = d_size;
d_index = 0;
+
+ // Reset the trigger.
+ if(d_trigger_mode == TRIG_MODE_FREE) {
+ d_triggered = true;
+ }
+ else {
+ d_triggered = false;
+ }
+ }
+
+ void
+ const_sink_c_impl::_npoints_resize()
+ {
+ int newsize = d_main_gui->getNPoints();
+ set_nsamps(newsize);
+ }
+
+ void
+ const_sink_c_impl::_gui_update_trigger()
+ {
+ d_trigger_mode = d_main_gui->getTriggerMode();
+ d_trigger_slope = d_main_gui->getTriggerSlope();
+ d_trigger_level = d_main_gui->getTriggerLevel();
+ d_trigger_channel = d_main_gui->getTriggerChannel();
+ d_trigger_count = 0;
+
+ std::string tagkey = d_main_gui->getTriggerTagKey();
+ d_trigger_tag_key = pmt::intern(tagkey);
+ }
+
+ void
+ const_sink_c_impl::_test_trigger_tags(int nitems)
+ {
+ int trigger_index;
+
+ uint64_t nr = nitems_read(d_trigger_channel);
+ std::vector<gr::tag_t> tags;
+ get_tags_in_range(tags, d_trigger_channel,
+ nr, nr + nitems,
+ d_trigger_tag_key);
+ if(tags.size() > 0) {
+ d_triggered = true;
+ trigger_index = tags[0].offset - nr;
+ d_start = d_index + trigger_index - 1;
+ d_end = d_start + d_size;
+ d_trigger_count = 0;
+ }
+ }
+
+ void
+ const_sink_c_impl::_test_trigger_norm(int nitems,
gr_vector_const_void_star inputs)
+ {
+ int trigger_index;
+ const gr_complex *in = (const gr_complex*)inputs[d_trigger_channel];
+ for(trigger_index = 0; trigger_index < nitems; trigger_index++) {
+ d_trigger_count++;
+
+ // Test if trigger has occurred based on the input stream,
+ // channel number, and slope direction
+ if(_test_trigger_slope(&in[trigger_index])) {
+ d_triggered = true;
+ d_start = d_index + trigger_index;
+ d_end = d_start + d_size;
+ d_trigger_count = 0;
+ break;
+ }
+ }
+
+ // If using auto trigger mode, trigger periodically even
+ // without a trigger event.
+ if((d_trigger_mode == TRIG_MODE_AUTO) && (d_trigger_count > d_size)) {
+ d_triggered = true;
+ d_trigger_count = 0;
+ }
+ }
+
+ bool
+ const_sink_c_impl::_test_trigger_slope(const gr_complex *in) const
+ {
+ float x0, x1;
+ x0 = abs(in[0]);
+ x1 = abs(in[1]);
+
+ if(d_trigger_slope == TRIG_SLOPE_POS)
+ return ((x0 <= d_trigger_level) && (x1 > d_trigger_level));
+ else
+ return ((x0 >= d_trigger_level) && (x1 < d_trigger_level));
}
int
@@ -332,54 +454,64 @@ namespace gr {
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
- int n=0, j=0, idx=0;
- const gr_complex *in = (const gr_complex*)input_items[idx];
-
- npoints_resize();
-
- for(int i=0; i < noutput_items; i+=d_size) {
- unsigned int datasize = noutput_items - i;
- unsigned int resid = d_size-d_index;
- idx = 0;
-
- // If we have enough input for one full plot, do it
- if(datasize >= resid) {
-
- // Fill up residbufs with d_size number of items
- for(n = 0; n < d_nconnections; n++) {
- in = (const gr_complex*)input_items[idx++];
- volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index],
- &d_residbufs_imag[n][d_index],
- &in[j], resid);
- }
-
- // Update the plot if its time
- if(gr::high_res_timer_now() - d_last_time > d_update_time) {
- d_last_time = gr::high_res_timer_now();
- d_qApplication->postEvent(d_main_gui,
- new ConstUpdateEvent(d_residbufs_real,
- d_residbufs_imag,
- d_size));
- }
-
- d_index = 0;
- j += resid;
- }
+ int n=0;
+ const gr_complex *in;
+
+ _npoints_resize();
+ _gui_update_trigger();
+
+ int nfill = d_end - d_index; // how much room left in
buffers
+ int nitems = std::min(noutput_items, nfill); // num items we can put in
buffers
+
+ // If auto, normal, or tag trigger, look for the trigger
+ if((d_trigger_mode != TRIG_MODE_FREE) && !d_triggered) {
+ // trigger off a tag key (first one found)
+ if(d_trigger_mode == TRIG_MODE_TAG) {
+ _test_trigger_tags(nitems);
+ }
+ // Normal or Auto trigger
+ else {
+ _test_trigger_norm(nitems, input_items);
+ }
+ }
- // Otherwise, copy what we received into the residbufs for next time
- else {
- for(n = 0; n < d_nconnections; n++) {
- in = (const gr_complex*)input_items[idx++];
- volk_32fc_deinterleave_64f_x2_u(&d_residbufs_real[n][d_index],
- &d_residbufs_imag[n][d_index],
- &in[j], datasize);
- }
- d_index += datasize;
- j += datasize;
- }
+ // Copy data into the buffers.
+ for(n = 0; n < d_nconnections; n++) {
+ in = (const gr_complex*)input_items[n];
+ volk_32fc_deinterleave_64f_x2(&d_residbufs_real[n][d_index],
+ &d_residbufs_imag[n][d_index],
+ &in[0], nitems);
+ }
+ d_index += nitems;
+
+
+ // If we've have a trigger and a full d_size of items in the buffers,
plot.
+ if((d_triggered) && (d_index == d_end)) {
+ // Copy data to be plotted to start of buffers.
+ for(n = 0; n < d_nconnections; n++) {
+ memmove(d_residbufs_real[n], &d_residbufs_real[n][d_start],
d_size*sizeof(double));
+ memmove(d_residbufs_imag[n], &d_residbufs_imag[n][d_start],
d_size*sizeof(double));
+ }
+
+ // Plot if we are able to update
+ if(gr::high_res_timer_now() - d_last_time > d_update_time) {
+ d_last_time = gr::high_res_timer_now();
+ d_qApplication->postEvent(d_main_gui,
+ new ConstUpdateEvent(d_residbufs_real,
+ d_residbufs_imag,
+ d_size));
+ }
+
+ // We've plotting, so reset the state
+ _reset();
+ }
+
+ // If we've filled up the buffers but haven't triggered, reset.
+ if(d_index == d_end) {
+ _reset();
}
- return j;
+ return nitems;
}
} /* namespace qtgui */
diff --git a/gr-qtgui/lib/const_sink_c_impl.h b/gr-qtgui/lib/const_sink_c_impl.h
index 3b1de22..0f1540d 100644
--- a/gr-qtgui/lib/const_sink_c_impl.h
+++ b/gr-qtgui/lib/const_sink_c_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -30,7 +30,7 @@
namespace gr {
namespace qtgui {
-
+
class QTGUI_API const_sink_c_impl : public const_sink_c
{
private:
@@ -38,11 +38,11 @@ namespace gr {
gr::thread::mutex d_mutex;
- int d_size;
+ int d_size, d_buffer_size;
std::string d_name;
int d_nconnections;
- int d_index;
+ int d_index, d_start, d_end;
std::vector<double*> d_residbufs_real;
std::vector<double*> d_residbufs_imag;
@@ -54,7 +54,21 @@ namespace gr {
gr::high_res_timer_type d_update_time;
gr::high_res_timer_type d_last_time;
- void npoints_resize();
+ // Members used for triggering scope
+ trigger_mode d_trigger_mode;
+ trigger_slope d_trigger_slope;
+ float d_trigger_level;
+ int d_trigger_channel;
+ pmt::pmt_t d_trigger_tag_key;
+ bool d_triggered;
+ int d_trigger_count;
+
+ void _reset();
+ void _npoints_resize();
+ void _gui_update_trigger();
+ void _test_trigger_tags(int nitems);
+ void _test_trigger_norm(int nitems, gr_vector_const_void_star inputs);
+ bool _test_trigger_slope(const gr_complex *in) const;
public:
const_sink_c_impl(int size,
@@ -86,6 +100,9 @@ namespace gr {
void set_line_marker(int which, int marker);
void set_nsamps(const int size);
void set_line_alpha(int which, double alpha);
+ void set_trigger_mode(trigger_mode mode, trigger_slope slope,
+ float level, int channel,
+ const std::string &tag_key="");
std::string title();
std::string line_label(int which);
diff --git a/gr-qtgui/lib/constellationdisplayform.cc
b/gr-qtgui/lib/constellationdisplayform.cc
index d0424b0..1325bec 100644
--- a/gr-qtgui/lib/constellationdisplayform.cc
+++ b/gr-qtgui/lib/constellationdisplayform.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2012 Free Software Foundation, Inc.
+ * Copyright 2012,2014 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -36,11 +36,48 @@ ConstellationDisplayForm::ConstellationDisplayForm(int
nplots, QWidget* parent)
d_layout->addWidget(d_display_plot, 0, 0);
setLayout(d_layout);
- NPointsMenu *nptsmenu = new NPointsMenu(this);
- d_menu->addAction(nptsmenu);
- connect(nptsmenu, SIGNAL(whichTrigger(int)),
+ d_nptsmenu = new NPointsMenu(this);
+ d_menu->addAction(d_nptsmenu);
+ connect(d_nptsmenu, SIGNAL(whichTrigger(int)),
this, SLOT(setNPoints(const int)));
+ // Set up the trigger menu
+ d_triggermenu = new QMenu("Trigger", this);
+ d_tr_mode_menu = new TriggerModeMenu(this);
+ d_tr_slope_menu = new TriggerSlopeMenu(this);
+ d_tr_level_act = new PopupMenu("Level", this);
+ d_tr_channel_menu = new TriggerChannelMenu(nplots, this);
+ d_tr_tag_key_act = new PopupMenu("Tag Key", this);
+ d_triggermenu->addMenu(d_tr_mode_menu);
+ d_triggermenu->addMenu(d_tr_slope_menu);
+ d_triggermenu->addAction(d_tr_level_act);
+ d_triggermenu->addMenu(d_tr_channel_menu);
+ d_triggermenu->addAction(d_tr_tag_key_act);
+ d_menu->addMenu(d_triggermenu);
+
+ setTriggerMode(gr::qtgui::TRIG_MODE_FREE);
+ connect(d_tr_mode_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_mode)),
+ this, SLOT(setTriggerMode(gr::qtgui::trigger_mode)));
+ // updates trigger state by calling set level or set tag key.
+ connect(d_tr_mode_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_mode)),
+ this, SLOT(updateTrigger(gr::qtgui::trigger_mode)));
+
+ setTriggerSlope(gr::qtgui::TRIG_SLOPE_POS);
+ connect(d_tr_slope_menu, SIGNAL(whichTrigger(gr::qtgui::trigger_slope)),
+ this, SLOT(setTriggerSlope(gr::qtgui::trigger_slope)));
+
+ setTriggerLevel(0);
+ connect(d_tr_level_act, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setTriggerLevel(QString)));
+
+ setTriggerChannel(0);
+ connect(d_tr_channel_menu, SIGNAL(whichTrigger(int)),
+ this, SLOT(setTriggerChannel(int)));
+
+ setTriggerTagKey(std::string(""));
+ connect(d_tr_tag_key_act, SIGNAL(whichTrigger(QString)),
+ this, SLOT(setTriggerTagKey(QString)));
+
Reset();
connect(d_display_plot, SIGNAL(plotPointSelected(const QPointF)),
@@ -120,3 +157,96 @@ void
ConstellationDisplayForm::setSampleRate(const QString &samprate)
{
}
+
+/********************************************************************
+ * TRIGGER METHODS
+ *******************************************************************/
+
+void
+ConstellationDisplayForm::setTriggerMode(gr::qtgui::trigger_mode mode)
+{
+ d_trig_mode = mode;
+ d_tr_mode_menu->getAction(mode)->setChecked(true);
+}
+
+void
+ConstellationDisplayForm::updateTrigger(gr::qtgui::trigger_mode mode)
+{
+ // If auto or normal mode, popup trigger level box to set
+ if((d_trig_mode == gr::qtgui::TRIG_MODE_AUTO) || (d_trig_mode ==
gr::qtgui::TRIG_MODE_NORM))
+ d_tr_level_act->activate(QAction::Trigger);
+
+ // if tag mode, popup tag key box to set
+ if(d_trig_mode == gr::qtgui::TRIG_MODE_TAG)
+ d_tr_tag_key_act->activate(QAction::Trigger);
+}
+
+gr::qtgui::trigger_mode
+ConstellationDisplayForm::getTriggerMode() const
+{
+ return d_trig_mode;
+}
+
+void
+ConstellationDisplayForm::setTriggerSlope(gr::qtgui::trigger_slope slope)
+{
+ d_trig_slope = slope;
+ d_tr_slope_menu->getAction(slope)->setChecked(true);
+}
+
+gr::qtgui::trigger_slope
+ConstellationDisplayForm::getTriggerSlope() const
+{
+ return d_trig_slope;
+}
+
+void
+ConstellationDisplayForm::setTriggerLevel(QString s)
+{
+ d_trig_level = s.toFloat();
+}
+
+void
+ConstellationDisplayForm::setTriggerLevel(float level)
+{
+ d_trig_level = level;
+ d_tr_level_act->setText(QString().setNum(d_trig_level));
+}
+
+float
+ConstellationDisplayForm::getTriggerLevel() const
+{
+ return d_trig_level;
+}
+
+void
+ConstellationDisplayForm::setTriggerChannel(int channel)
+{
+ d_trig_channel = channel;
+ d_tr_channel_menu->getAction(d_trig_channel)->setChecked(true);
+}
+
+int
+ConstellationDisplayForm::getTriggerChannel() const
+{
+ return d_trig_channel;
+}
+
+void
+ConstellationDisplayForm::setTriggerTagKey(QString s)
+{
+ d_trig_tag_key = s.toStdString();
+}
+
+void
+ConstellationDisplayForm::setTriggerTagKey(const std::string &key)
+{
+ d_trig_tag_key = key;
+ d_tr_tag_key_act->setText(QString().fromStdString(d_trig_tag_key));
+}
+
+std::string
+ConstellationDisplayForm::getTriggerTagKey() const
+{
+ return d_trig_tag_key;
+}
diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc
index e86ffca..499529c 100644
--- a/gr-qtgui/lib/time_sink_c_impl.cc
+++ b/gr-qtgui/lib/time_sink_c_impl.cc
@@ -67,7 +67,7 @@ namespace gr {
for(int n = 0; n < d_nconnections; n++) {
d_buffers.push_back((double*)volk_malloc(d_buffer_size*sizeof(double),
- volk_get_alignment()));
+ volk_get_alignment()));
memset(d_buffers[n], 0, d_buffer_size*sizeof(double));
}
- [Commit-gnuradio] [gnuradio] branch master updated (3831dd3 -> 754cfa7), git, 2014/04/25
- [Commit-gnuradio] [gnuradio] 02/05: Merge branch 'maint', git, 2014/04/25
- [Commit-gnuradio] [gnuradio] 04/05: Merge branch 'master' of git.gnuradio.org:gnuradio, git, 2014/04/25
- [Commit-gnuradio] [gnuradio] 05/05: Merge branch 'maint', git, 2014/04/25
- [Commit-gnuradio] [gnuradio] 03/05: Merge branch 'maint', git, 2014/04/25
- [Commit-gnuradio] [gnuradio] 01/05: qtgui: adding a trigger for the constellation plots. Probably most useful with tags, but normal and auto triggering supported, too.,
git <=