diff options
-rw-r--r-- | gr-qtgui/examples/qtgui_tags_viewing.grc | 788 | ||||
-rw-r--r-- | gr-qtgui/grc/qtgui_time_sink_x.xml | 73 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/form_menus.h | 217 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/time_sink_c.h | 5 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/time_sink_f.h | 5 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/timedisplayform.h | 27 | ||||
-rw-r--r-- | gr-qtgui/include/gnuradio/qtgui/trigger_mode.h | 44 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_c_impl.cc | 241 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_c_impl.h | 18 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_f_impl.cc | 231 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_f_impl.h | 18 | ||||
-rw-r--r-- | gr-qtgui/lib/timedisplayform.cc | 123 | ||||
-rw-r--r-- | gr-qtgui/swig/qtgui_swig.i | 2 |
14 files changed, 1545 insertions, 248 deletions
diff --git a/gr-qtgui/examples/qtgui_tags_viewing.grc b/gr-qtgui/examples/qtgui_tags_viewing.grc index 01c3f5c696..b8809a1617 100644 --- a/gr-qtgui/examples/qtgui_tags_viewing.grc +++ b/gr-qtgui/examples/qtgui_tags_viewing.grc @@ -1,6 +1,6 @@ <?xml version='1.0' encoding='ASCII'?> <flow_graph> - <timestamp>Fri Sep 13 15:29:13 2013</timestamp> + <timestamp>Thu Sep 19 10:45:35 2013</timestamp> <block> <key>options</key> <param> @@ -87,6 +87,284 @@ <key>import</key> <param> <key>id</key> + <value>import_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>from gnuradio.digital.utils import tagged_streams</value> + </param> + <param> + <key>_coordinate</key> + <value>(99, 72)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(266, 149)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_throttle</key> + <param> + <key>id</key> + <value>blocks_throttle_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(263, 387)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>vector</key> + <value>[-0.85,] + (10000-1)*[0,]</value> + </param> + <param> + <key>tags</key> + <value>tagged_streams.make_lengthtags((1024,), (0,), "testing tags")</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(13, 371)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_0_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>vector</key> + <value>1000*[0,] + [0.5,] + (10000-1000-1)*[0,]</value> + </param> + <param> + <key>tags</key> + <value>tagged_streams.make_lengthtags((128,), (1000,), "second stream")</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(13, 462)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>qtgui_time_sink_x</key> + <param> + <key>id</key> + <value>qtgui_time_sink_x_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>False</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>name</key> + <value>QT GUI Plot</value> + </param> + <param> + <key>size</key> + <value>18000</value> + </param> + <param> + <key>srate</key> + <value>samp_rate</value> + </param> + <param> + <key>ymin</key> + <value>-1</value> + </param> + <param> + <key>ymax</key> + <value>1</value> + </param> + <param> + <key>nconnections</key> + <value>2</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_FREE</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>0.0</value> + </param> + <param> + <key>tr_delay</key> + <value>0</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> + <key>entags</key> + <value>True</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> + <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(473, 417)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> <value>import_0</value> </param> <param> @@ -110,7 +388,7 @@ <key>import</key> <param> <key>id</key> - <value>import_1</value> + <value>import_2</value> </param> <param> <key>_enabled</key> @@ -118,11 +396,11 @@ </param> <param> <key>import</key> - <value>from gnuradio.digital.utils import tagged_streams</value> + <value>import time</value> </param> <param> <key>_coordinate</key> - <value>(99, 72)</value> + <value>(253, 71)</value> </param> <param> <key>_rotation</key> @@ -145,11 +423,11 @@ </param> <param> <key>vector</key> - <value>[-0.85+0.75j,] + (10000-1)*[0,]</value> + <value>[0.85+0.5j,] + (10000-1)*[0,]</value> </param> <param> <key>tags</key> - <value>tagged_streams.make_lengthtags((1024,), (0,), "testing tags")</value> + <value>tagged_streams.make_lengthtags((1024,), (0,), "testing tags 0")</value> </param> <param> <key>repeat</key> @@ -177,10 +455,10 @@ </param> </block> <block> - <key>blocks_delay</key> + <key>blocks_tags_strobe</key> <param> <key>id</key> - <value>blocks_delay_0</value> + <value>blocks_tags_strobe_0</value> </param> <param> <key>_enabled</key> @@ -191,14 +469,61 @@ <value>complex</value> </param> <param> - <key>delay</key> - <value>1000</value> + <key>value</key> + <value>pmt.intern("TEST")</value> </param> <param> - <key>num_ports</key> + <key>nsamps</key> + <value>10000</value> + </param> + <param> + <key>vlen</key> <value>1</value> </param> <param> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(13, 215)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_vector_source_x</key> + <param> + <key>id</key> + <value>blocks_vector_source_x_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>vector</key> + <value>1500*[0,] + [0.25+0j,] + (10000-1500-1)*[0,]</value> + </param> + <param> + <key>tags</key> + <value>tagged_streams.make_lengthtags((128,), (1500,), "second stream")</value> + </param> + <param> + <key>repeat</key> + <value>True</value> + </param> + <param> <key>vlen</key> <value>1</value> </param> @@ -212,7 +537,7 @@ </param> <param> <key>_coordinate</key> - <value>(202, 223)</value> + <value>(14, 283)</value> </param> <param> <key>_rotation</key> @@ -223,7 +548,7 @@ <key>blocks_add_xx</key> <param> <key>id</key> - <value>blocks_add_xx_0</value> + <value>blocks_add_xx_1</value> </param> <param> <key>_enabled</key> @@ -251,7 +576,7 @@ </param> <param> <key>_coordinate</key> - <value>(482, 193)</value> + <value>(707, 176)</value> </param> <param> <key>_rotation</key> @@ -259,10 +584,10 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>analog_fastnoise_source_x</key> <param> <key>id</key> - <value>blocks_vector_source_x_0_0</value> + <value>analog_fastnoise_source_x_0</value> </param> <param> <key>_enabled</key> @@ -273,20 +598,20 @@ <value>complex</value> </param> <param> - <key>vector</key> - <value>1000*[0,] + [0.5+0j,] + (10000-1000-1)*[0,]</value> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> </param> <param> - <key>tags</key> - <value>tagged_streams.make_lengthtags((128,), (1000,), "second stream")</value> + <key>amp</key> + <value>0.004</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>seed</key> + <value>0</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>samples</key> + <value>8192</value> </param> <param> <key>affinity</key> @@ -298,7 +623,7 @@ </param> <param> <key>_coordinate</key> - <value>(14, 283)</value> + <value>(350, 39)</value> </param> <param> <key>_rotation</key> @@ -309,7 +634,7 @@ <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>qtgui_time_sink_x_0</value> + <value>qtgui_time_sink_x_0_1_0</value> </param> <param> <key>_enabled</key> @@ -329,31 +654,51 @@ </param> <param> <key>srate</key> - <value>samp_rate</value> + <value>1</value> </param> <param> <key>ymin</key> - <value>-1</value> + <value>-0.1</value> </param> <param> <key>ymax</key> - <value>1</value> + <value>1.5</value> </param> <param> <key>nconnections</key> - <value>2</value> + <value>1</value> </param> <param> <key>update_time</key> <value>0.10</value> </param> <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_NORM</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>.1</value> + </param> + <param> + <key>tr_delay</key> + <value>8015</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> <key>entags</key> <value>True</value> </param> <param> <key>gui_hint</key> - <value></value> + <value>1,1,1,1</value> </param> <param> <key>affinity</key> @@ -361,7 +706,7 @@ </param> <param> <key>_coordinate</key> - <value>(630, 266)</value> + <value>(857, 173)</value> </param> <param> <key>_rotation</key> @@ -369,32 +714,59 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>blocks_null_source</key> <param> <key>id</key> - <value>blocks_vector_source_x_0_0_0</value> + <value>blocks_null_source_0</value> </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> <key>type</key> - <value>float</value> + <value>complex</value> </param> <param> - <key>vector</key> - <value>1000*[0,] + [0.5,] + (10000-1000-1)*[0,]</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>tags</key> - <value>tagged_streams.make_lengthtags((128,), (1000,), "second stream")</value> + <key>affinity</key> + <value></value> </param> <param> - <key>repeat</key> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(289, 278)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_add_xx</key> + <param> + <key>id</key> + <value>blocks_add_xx_0</value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>num_inputs</key> + <value>2</value> + </param> + <param> <key>vlen</key> <value>1</value> </param> @@ -408,7 +780,7 @@ </param> <param> <key>_coordinate</key> - <value>(13, 462)</value> + <value>(482, 193)</value> </param> <param> <key>_rotation</key> @@ -416,10 +788,10 @@ </param> </block> <block> - <key>blocks_tags_strobe</key> + <key>blocks_delay</key> <param> <key>id</key> - <value>blocks_tags_strobe_0</value> + <value>blocks_delay_0</value> </param> <param> <key>_enabled</key> @@ -430,12 +802,12 @@ <value>complex</value> </param> <param> - <key>value</key> - <value>pmt.intern("TEST")</value> + <key>delay</key> + <value>1000</value> </param> <param> - <key>nsamps</key> - <value>5000</value> + <key>num_ports</key> + <value>1</value> </param> <param> <key>vlen</key> @@ -451,7 +823,7 @@ </param> <param> <key>_coordinate</key> - <value>(13, 215)</value> + <value>(297, 223)</value> </param> <param> <key>_rotation</key> @@ -459,10 +831,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>qtgui_time_sink_x_0</value> </param> <param> <key>_enabled</key> @@ -473,24 +845,123 @@ <value>complex</value> </param> <param> - <key>samples_per_second</key> - <value>samp_rate</value> + <key>name</key> + <value>QT GUI Plot</value> </param> <param> - <key>vlen</key> + <key>size</key> + <value>18000</value> + </param> + <param> + <key>srate</key> <value>1</value> </param> <param> + <key>ymin</key> + <value>-0.1</value> + </param> + <param> + <key>ymax</key> + <value>1.5</value> + </param> + <param> + <key>nconnections</key> + <value>2</value> + </param> + <param> + <key>update_time</key> + <value>0.10</value> + </param> + <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_NORM</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>.1</value> + </param> + <param> + <key>tr_delay</key> + <value>100</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> + <key>entags</key> + <value>True</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> + <param> <key>affinity</key> <value></value> </param> <param> - <key>minoutbuf</key> + <key>_coordinate</key> + <value>(858, 282)</value> + </param> + <param> + <key>_rotation</key> <value>0</value> </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>id</key> + <value>ntaps</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Num Taps</value> + </param> + <param> + <key>value</key> + <value>30</value> + </param> + <param> + <key>start</key> + <value>1</value> + </param> + <param> + <key>stop</key> + <value>100</value> + </param> + <param> + <key>step</key> + <value>1</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>gui_hint</key> + <value></value> + </param> <param> <key>_coordinate</key> - <value>(266, 149)</value> + <value>(899, 430)</value> </param> <param> <key>_rotation</key> @@ -498,10 +969,10 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>fir_filter_xxx</key> <param> <key>id</key> - <value>blocks_vector_source_x_0_1</value> + <value>fir_filter_xxx_0</value> </param> <param> <key>_enabled</key> @@ -509,21 +980,56 @@ </param> <param> <key>type</key> - <value>float</value> + <value>ccc</value> </param> <param> - <key>vector</key> - <value>[-0.85,] + (10000-1)*[0,]</value> + <key>decim</key> + <value>1</value> </param> <param> - <key>tags</key> - <value>tagged_streams.make_lengthtags((1024,), (0,), "testing tags")</value> + <key>taps</key> + <value>int(ntaps)*[1,]+[1,]</value> </param> <param> - <key>repeat</key> + <key>affinity</key> + <value></value> + </param> + <param> + <key>minoutbuf</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(660, 76)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blocks_delay</key> + <param> + <key>id</key> + <value>blocks_delay_0_0</value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>delay</key> + <value>int(delay)</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> <key>vlen</key> <value>1</value> </param> @@ -537,7 +1043,7 @@ </param> <param> <key>_coordinate</key> - <value>(13, 371)</value> + <value>(890, 44)</value> </param> <param> <key>_rotation</key> @@ -548,7 +1054,7 @@ <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>qtgui_time_sink_x_0_0</value> + <value>qtgui_time_sink_x_0_1</value> </param> <param> <key>_enabled</key> @@ -556,7 +1062,7 @@ </param> <param> <key>type</key> - <value>float</value> + <value>complex</value> </param> <param> <key>name</key> @@ -564,19 +1070,19 @@ </param> <param> <key>size</key> - <value>18000</value> + <value>1000</value> </param> <param> <key>srate</key> - <value>samp_rate</value> + <value>1</value> </param> <param> <key>ymin</key> - <value>-1</value> + <value>-0.1</value> </param> <param> <key>ymax</key> - <value>1</value> + <value>1.5</value> </param> <param> <key>nconnections</key> @@ -587,12 +1093,32 @@ <value>0.10</value> </param> <param> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_NORM</value> + </param> + <param> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> + </param> + <param> + <key>tr_level</key> + <value>.1</value> + </param> + <param> + <key>tr_delay</key> + <value>500</value> + </param> + <param> + <key>tr_chan</key> + <value>0</value> + </param> + <param> <key>entags</key> <value>True</value> </param> <param> <key>gui_hint</key> - <value></value> + <value>1,0,1,1</value> </param> <param> <key>affinity</key> @@ -600,7 +1126,7 @@ </param> <param> <key>_coordinate</key> - <value>(473, 417)</value> + <value>(1072, 77)</value> </param> <param> <key>_rotation</key> @@ -608,38 +1134,54 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>variable_qtgui_range</key> <param> <key>id</key> - <value>blocks_throttle_0_0</value> + <value>delay</value> </param> <param> <key>_enabled</key> <value>True</value> </param> <param> - <key>type</key> - <value>float</value> + <key>label</key> + <value>Delay</value> </param> <param> - <key>samples_per_second</key> - <value>samp_rate</value> + <key>value</key> + <value>20</value> </param> <param> - <key>vlen</key> + <key>start</key> + <value>0</value> + </param> + <param> + <key>stop</key> + <value>200</value> + </param> + <param> + <key>step</key> <value>1</value> </param> <param> - <key>affinity</key> - <value></value> + <key>widget</key> + <value>counter_slider</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>gui_hint</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(263, 387)</value> + <value>(762, 428)</value> </param> <param> <key>_rotation</key> @@ -653,51 +1195,99 @@ <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_vector_source_x_0_0</source_block_id> - <sink_block_id>qtgui_time_sink_x_0</sink_block_id> + <source_block_id>blocks_throttle_0</source_block_id> + <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0</source_block_id> + <source_block_id>blocks_delay_0</source_block_id> <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blocks_tags_strobe_0</source_block_id> + <sink_block_id>blocks_delay_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_throttle_0_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_vector_source_x_0_1</source_block_id> + <sink_block_id>blocks_throttle_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>blocks_vector_source_x_0_0_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>analog_fastnoise_source_x_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> <source_block_id>blocks_add_xx_0</source_block_id> + <sink_block_id>blocks_add_xx_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blocks_add_xx_1</source_block_id> <sink_block_id>qtgui_time_sink_x_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_delay_0</source_block_id> + <source_block_id>blocks_null_source_0</source_block_id> <sink_block_id>blocks_add_xx_0</sink_block_id> <source_key>0</source_key> <sink_key>1</sink_key> </connection> <connection> - <source_block_id>blocks_tags_strobe_0</source_block_id> - <sink_block_id>blocks_delay_0</sink_block_id> + <source_block_id>blocks_vector_source_x_0_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>blocks_add_xx_1</source_block_id> + <sink_block_id>qtgui_time_sink_x_0_1_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_vector_source_x_0_0_0</source_block_id> - <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id> + <source_block_id>blocks_add_xx_0</source_block_id> + <sink_block_id>fir_filter_xxx_0</sink_block_id> <source_key>0</source_key> - <sink_key>1</sink_key> + <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_vector_source_x_0_1</source_block_id> - <sink_block_id>blocks_throttle_0_0</sink_block_id> + <source_block_id>fir_filter_xxx_0</source_block_id> + <sink_block_id>blocks_delay_0_0</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> <connection> - <source_block_id>blocks_throttle_0_0</source_block_id> - <sink_block_id>qtgui_time_sink_x_0_0</sink_block_id> + <source_block_id>blocks_delay_0_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0_1</sink_block_id> <source_key>0</source_key> <sink_key>0</sink_key> </connection> + <connection> + <source_block_id>fir_filter_xxx_0</source_block_id> + <sink_block_id>qtgui_time_sink_x_0_1</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> </flow_graph> diff --git a/gr-qtgui/grc/qtgui_time_sink_x.xml b/gr-qtgui/grc/qtgui_time_sink_x.xml index 724b40c17e..66c02517d5 100644 --- a/gr-qtgui/grc/qtgui_time_sink_x.xml +++ b/gr-qtgui/grc/qtgui_time_sink_x.xml @@ -21,6 +21,7 @@ qtgui.$(type.fcn)( self.$(id).set_update_time($update_time) self.$(id).set_y_axis($ymin, $ymax) self.$(id).enable_tags(-1, $entags) +self.$(id).set_trigger_mode($tr_mode, $tr_slope, $tr_level, $tr_delay, $tr_chan) self._$(id)_win = sip.wrapinstance(self.$(id).pyqwidget(), Qt.QWidget) $(gui_hint()($win))</make> <callback>set_time_domain_axis($min, $max)</callback> @@ -53,20 +54,20 @@ $(gui_hint()($win))</make> <name>Sample Rate</name> <key>srate</key> <value>samp_rate</value> - <type>real</type> + <type>float</type> </param> <param> <name>Y min</name> <key>ymin</key> <value>-1</value> - <type>real</type> + <type>float</type> <hide>part</hide> </param> <param> <name>Y max</name> <key>ymax</key> <value>1</value> - <type>real</type> + <type>float</type> <hide>part</hide> </param> <param> @@ -80,9 +81,70 @@ $(gui_hint()($win))</make> <name>Update Period</name> <key>update_time</key> <value>0.10</value> - <type>real</type> + <type>float</type> <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> + </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> + </param> + + <param> + <name>Trigger Level</name> + <key>tr_level</key> + <value>0.0</value> + <type>float</type> + <hide>part</hide> + </param> + + <param> + <name>Trigger Delay</name> + <key>tr_delay</key> + <value>0</value> + <type>float</type> + <hide>part</hide> + </param> + + <param> + <name>Trigger Channel</name> + <key>tr_chan</key> + <value>0</value> + <type>int</type> + <hide>part</hide> + </param> + <param> <name>Disp. Tags</name> <key>entags</key> @@ -105,6 +167,9 @@ $(gui_hint()($win))</make> <type>gui_hint</type> <hide>part</hide> </param> + + <check>$tr_chan < 2*$nconnections</check> + <sink> <name>in</name> <type>$type</type> diff --git a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt index 0d5cb58f5d..3c6309d9c3 100644 --- a/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt +++ b/gr-qtgui/include/gnuradio/qtgui/CMakeLists.txt @@ -53,6 +53,7 @@ install(FILES time_raster_sink_f.h time_sink_c.h time_sink_f.h + trigger_mode.h utils.h waterfalldisplayform.h WaterfallDisplayPlot.h diff --git a/gr-qtgui/include/gnuradio/qtgui/form_menus.h b/gr-qtgui/include/gnuradio/qtgui/form_menus.h index 1158f337a2..dcd82e885d 100644 --- a/gr-qtgui/include/gnuradio/qtgui/form_menus.h +++ b/gr-qtgui/include/gnuradio/qtgui/form_menus.h @@ -29,6 +29,7 @@ #include <qwt_symbol.h> #include <gnuradio/filter/firdes.h> #include <gnuradio/qtgui/qtgui_types.h> +#include <gnuradio/qtgui/trigger_mode.h> class LineColorMenu: public QMenu { @@ -475,6 +476,7 @@ public: : QAction("Other", parent) { d_diag = new QDialog(parent); + d_diag->setWindowTitle("Other"); d_diag->setModal(true); d_text = new QLineEdit(); @@ -529,6 +531,7 @@ public: : QAction("Other", parent) { d_diag = new QDialog(parent); + d_diag->setWindowTitle("Other"); d_diag->setModal(true); d_text0 = new QLineEdit(); @@ -816,6 +819,7 @@ public: : QAction("Number of Points", parent) { d_diag = new QDialog(parent); + d_diag->setWindowTitle("Number of Points"); d_diag->setModal(true); d_text = new QLineEdit(); @@ -837,6 +841,11 @@ public: ~NPointsMenu() {} + void setDiagText(const int npts) + { + d_text->setText(QString().setNum(npts)); + } + signals: void whichTrigger(const int npts); @@ -943,6 +952,208 @@ private: /********************************************************************/ +class TriggerModeMenu: public QMenu +{ + Q_OBJECT + +public: + TriggerModeMenu(QWidget *parent) + : QMenu("Mode", parent) + { + d_grp = new QActionGroup(this); + d_act.push_back(new QAction("Free", this)); + d_act.push_back(new QAction("Auto", this)); + d_act.push_back(new QAction("Normal", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getFree())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getAuto())); + connect(d_act[2], SIGNAL(triggered()), this, SLOT(getNorm())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + a->setCheckable(true); + a->setActionGroup(d_grp); + addAction(a); + } + } + + ~TriggerModeMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("TriggerModeMenu::getAction: which out of range.\n"); + } + + QAction * getAction(gr::qtgui::trigger_mode mode) + { + switch(mode) { + case gr::qtgui::TRIG_MODE_FREE: + return d_act[0]; + break; + case gr::qtgui::TRIG_MODE_AUTO: + return d_act[1]; + break; + case gr::qtgui::TRIG_MODE_NORM: + return d_act[2]; + break; + default: + throw std::runtime_error("TriggerModeMenu::getAction: unknown trigger mode.\n"); + } + } + +signals: + void whichTrigger(gr::qtgui::trigger_mode mode); + +public slots: + void getFree() { emit whichTrigger(gr::qtgui::TRIG_MODE_FREE); } + void getAuto() { emit whichTrigger(gr::qtgui::TRIG_MODE_AUTO); } + void getNorm() { emit whichTrigger(gr::qtgui::TRIG_MODE_NORM); } + +private: + QList<QAction *> d_act; + QActionGroup *d_grp; +}; + + +/********************************************************************/ + + +class TriggerSlopeMenu: public QMenu +{ + Q_OBJECT + +public: + TriggerSlopeMenu(QWidget *parent) + : QMenu("Slope", parent) + { + d_grp = new QActionGroup(this); + d_act.push_back(new QAction("Positive", this)); + d_act.push_back(new QAction("Negative", this)); + + connect(d_act[0], SIGNAL(triggered()), this, SLOT(getPos())); + connect(d_act[1], SIGNAL(triggered()), this, SLOT(getNeg())); + + QListIterator<QAction*> i(d_act); + while(i.hasNext()) { + QAction *a = i.next(); + a->setCheckable(true); + a->setActionGroup(d_grp); + addAction(a); + } + } + + ~TriggerSlopeMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("TriggerSlopeMenu::getAction: which out of range.\n"); + } + + QAction * getAction(gr::qtgui::trigger_slope slope) + { + switch(slope) { + case gr::qtgui::TRIG_SLOPE_POS: + return d_act[0]; + break; + case gr::qtgui::TRIG_SLOPE_NEG: + return d_act[1]; + break; + default: + throw std::runtime_error("TriggerSlopeMenu::getAction: unknown trigger slope.\n"); + } + } + +signals: + void whichTrigger(gr::qtgui::trigger_slope slope); + +public slots: + void getPos() { emit whichTrigger(gr::qtgui::TRIG_SLOPE_POS); } + void getNeg() { emit whichTrigger(gr::qtgui::TRIG_SLOPE_NEG); } + +private: + QList<QAction *> d_act; + QActionGroup *d_grp; +}; + + +/********************************************************************/ + + +class TriggerChannelMenu: public QMenu +{ + Q_OBJECT + +public: + TriggerChannelMenu(int nchans, QWidget *parent) + : QMenu("Channel", parent) + { + d_grp = new QActionGroup(this); + for(int i = 0; i < nchans; i++) { + d_act.push_back(new QAction(QString().setNum(i), this)); + d_act[i]->setCheckable(true); + d_act[i]->setActionGroup(d_grp); + + addAction(d_act[i]); + connect(d_act[i], SIGNAL(triggered()), this, SLOT(getChannel())); + } + } + + ~TriggerChannelMenu() + {} + + int getNumActions() const + { + return d_act.size(); + } + + QAction * getAction(int which) + { + if(which < d_act.size()) + return d_act[which]; + else + throw std::runtime_error("TriggerChannelMenu::getAction: which out of range.\n"); + } + + +signals: + void whichTrigger(int n); + +public slots: + void getChannel() + { + QAction *a = d_grp->checkedAction(); + int which = a->text().toInt(); + emit whichTrigger(which); + } + +private: + QList<QAction *> d_act; + QActionGroup *d_grp; +}; + + +/********************************************************************/ + + class PopupMenu: public QAction { Q_OBJECT @@ -952,6 +1163,7 @@ public: : QAction(desc, parent) { d_diag = new QDialog(parent); + d_diag->setWindowTitle(desc); d_diag->setModal(true); d_text = new QLineEdit(); @@ -973,6 +1185,11 @@ public: ~PopupMenu() {} + void setText(QString s) + { + d_text->setText(s); + } + signals: void whichTrigger(const QString data); diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h index b6947a7678..afe574742f 100644 --- a/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h +++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_c.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011,2012 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,6 +25,7 @@ #include <Python.h> #include <gnuradio/qtgui/api.h> +#include <gnuradio/qtgui/trigger_mode.h> #include <gnuradio/sync_block.h> #include <qapplication.h> @@ -78,6 +79,8 @@ 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; + virtual void set_trigger_mode(trigger_mode mode, trigger_slope slope, + float level, float delay, int channel) = 0; virtual std::string title() = 0; virtual std::string line_label(int which) = 0; diff --git a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h index 9d54d5c314..9eb239c65d 100644 --- a/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h +++ b/gr-qtgui/include/gnuradio/qtgui/time_sink_f.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -25,6 +25,7 @@ #include <Python.h> #include <gnuradio/qtgui/api.h> +#include <gnuradio/qtgui/trigger_mode.h> #include <gnuradio/sync_block.h> #include <qapplication.h> @@ -76,6 +77,8 @@ 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; + virtual void set_trigger_mode(trigger_mode mode, trigger_slope slope, + float level, float delay, int channel) = 0; virtual std::string title() = 0; virtual std::string line_label(int which) = 0; diff --git a/gr-qtgui/include/gnuradio/qtgui/timedisplayform.h b/gr-qtgui/include/gnuradio/qtgui/timedisplayform.h index 866bca8174..2f873edfcd 100644 --- a/gr-qtgui/include/gnuradio/qtgui/timedisplayform.h +++ b/gr-qtgui/include/gnuradio/qtgui/timedisplayform.h @@ -45,6 +45,11 @@ class TimeDisplayForm : public DisplayForm TimeDomainDisplayPlot* getPlot(); int getNPoints() const; + gr::qtgui::trigger_mode getTriggerMode() const; + gr::qtgui::trigger_slope getTriggerSlope() const; + float getTriggerLevel() const; + float getTriggerDelay() const; + int getTriggerChannel() const; public slots: void customEvent(QEvent * e); @@ -60,6 +65,14 @@ public slots: void tagMenuSlot(bool en); void setTagMenu(int which, bool en); + void setTriggerMode(gr::qtgui::trigger_mode mode); + void setTriggerSlope(gr::qtgui::trigger_slope slope); + void setTriggerLevel(QString s); + void setTriggerLevel(float level); + void setTriggerDelay(QString s); + void setTriggerDelay(float delay); + void setTriggerChannel(int chan); + private slots: void newData(const QEvent*); @@ -75,10 +88,24 @@ private: bool d_semilogx; bool d_semilogy; + NPointsMenu *d_nptsmenu; QAction *d_stemmenu; QAction *d_semilogxmenu; QAction *d_semilogymenu; std::vector<QAction*> d_tagsmenu; + + QMenu *d_triggermenu; + TriggerModeMenu *d_tr_mode_menu; + TriggerSlopeMenu *d_tr_slope_menu; + PopupMenu *d_tr_level_act; + PopupMenu *d_tr_delay_act; + TriggerChannelMenu *d_tr_channel_menu; + + gr::qtgui::trigger_mode d_trig_mode; + gr::qtgui::trigger_slope d_trig_slope; + float d_trig_level; + float d_trig_delay; + int d_trig_channel; }; #endif /* TIME_DISPLAY_FORM_H */ diff --git a/gr-qtgui/include/gnuradio/qtgui/trigger_mode.h b/gr-qtgui/include/gnuradio/qtgui/trigger_mode.h new file mode 100644 index 0000000000..3c7accecb8 --- /dev/null +++ b/gr-qtgui/include/gnuradio/qtgui/trigger_mode.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_QTGUI_TRIGGER_MODE_H +#define INCLUDED_QTGUI_TRIGGER_MODE_H + +namespace gr { + namespace qtgui { + + enum trigger_mode { + TRIG_MODE_FREE, + TRIG_MODE_AUTO, + TRIG_MODE_NORM, + TRIG_MODE_STRIPCHART, + }; + + enum trigger_slope { + TRIG_SLOPE_POS, + TRIG_SLOPE_NEG, + }; + + } /* namespace qtgui */ +} /* namespace gr */ + +#endif /* INCLUDED_QTGUI_TRIGGER_MODE_H */ diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc index 442b47c49f..e68cbe5b1a 100644 --- a/gr-qtgui/lib/time_sink_c_impl.cc +++ b/gr-qtgui/lib/time_sink_c_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011,2012 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -49,8 +49,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("time_sink_c", - io_signature::make(nconnections, nconnections, sizeof(gr_complex)), - io_signature::make(0, 0, 0)), + io_signature::make(nconnections, nconnections, sizeof(gr_complex)), + io_signature::make(0, 0, 0)), d_size(size), d_samp_rate(samp_rate), d_name(name), d_nconnections(2*nconnections), d_parent(parent) { @@ -71,6 +71,10 @@ namespace gr { d_tags = std::vector< std::vector<gr::tag_t> >(d_nconnections/2); initialize(); + + d_size += 1; // trick the next line into updating + set_nsamps(size); + set_trigger_mode(TRIG_MODE_AUTO, TRIG_SLOPE_POS, 0, 0, 0); } time_sink_c_impl::~time_sink_c_impl() @@ -189,6 +193,32 @@ namespace gr { } void + time_sink_c_impl::set_trigger_mode(trigger_mode mode, + trigger_slope slope, + float level, + float delay, int channel) + { + d_trigger_mode = mode; + d_trigger_slope = slope; + d_trigger_level = level; + d_trigger_delay = static_cast<int>(delay*d_samp_rate); + d_trigger_channel = channel; + d_triggered = false; + d_trigger_count = 0; + + if(d_trigger_delay > d_size) + throw std::runtime_error("qtgui::time_sink_c: trigger delay set outside of display range.\n"); + + d_main_gui->setTriggerMode(d_trigger_mode); + d_main_gui->setTriggerSlope(d_trigger_slope); + d_main_gui->setTriggerLevel(d_trigger_level); + d_main_gui->setTriggerDelay(delay); + d_main_gui->setTriggerChannel(d_trigger_channel); + + set_history(d_trigger_delay + 2); + } + + void time_sink_c_impl::set_size(int width, int height) { d_main_gui->resize(QSize(width, height)); @@ -267,13 +297,6 @@ namespace gr { d_main_gui->setSampleRate(d_samp_rate); } - void - time_sink_c_impl::npoints_resize() - { - int newsize = d_main_gui->getNPoints(); - set_nsamps(newsize); - } - int time_sink_c_impl::nsamps() const { @@ -334,79 +357,161 @@ namespace gr { d_index = 0; } + void + time_sink_c_impl::_npoints_resize() + { + int newsize = d_main_gui->getNPoints(); + set_nsamps(newsize); + } + + void + time_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(); + + float d = d_main_gui->getTriggerDelay(); + int delay = static_cast<int>(d*d_samp_rate); + + if(delay != d_trigger_delay) { + if(d_trigger_delay > d_size) + throw std::runtime_error("qtgui::time_sink_c: trigger delay set outside of display range.\n"); + d_trigger_delay = delay; + set_history(d_trigger_delay + 2); + } + } + + bool + time_sink_c_impl::_test_trigger_slope(const gr_complex *in) const + { + float x0, x1; + if(d_trigger_channel % 2 == 0) { + x0 = in[0].real(); + x1 = in[1].real(); + } + else { + x0 = in[0].imag(); + x1 = in[1].imag(); + } + + 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 time_sink_c_impl::work(int noutput_items, 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]; + int n=0, j=0, idx=0, ret=0; + const gr_complex *in; - npoints_resize(); + _npoints_resize(); + _gui_update_trigger(); for(int i=0; i < noutput_items; i+=d_size) { - unsigned int datasize = noutput_items - i; + + // If auto or normal trigger, look for the trigger + int trigger_index = i; + if((d_trigger_mode != TRIG_MODE_FREE) && !d_triggered) { + for(; trigger_index < noutput_items; trigger_index++) { + d_trigger_count++; + + // Test if trigger has occurred based on the input stream, + // channel number, and slope direction + in = (const gr_complex*)input_items[d_trigger_channel/2]; + if(_test_trigger_slope(&in[trigger_index + d_trigger_delay])) { + d_triggered = true; + j = trigger_index; + 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; + } + + ret = trigger_index; + i = trigger_index; + } + + unsigned int datasize = noutput_items - trigger_index; 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+=2) { - in = (const gr_complex*)input_items[idx]; - volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], - &d_residbufs[n+1][d_index], - &in[j], resid); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + j, nr + j + resid); - for(size_t t = 0; t < tags.size(); t++) - tags[t].offset = tags[t].offset - (nr + j) + d_index; - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } - - // Update the plot if it's 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 TimeUpdateEvent(d_residbufs, d_size, d_tags)); - } - - d_index = 0; - j += resid; - - for(n = 0; n < d_nconnections/2; n++) { - d_tags[n].clear(); + // If we're in trigger mode, test if we have triggered + if((d_trigger_mode == TRIG_MODE_FREE) || d_triggered) { + // 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+=2) { + in = (const gr_complex*)input_items[idx]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], + &d_residbufs[n+1][d_index], + &in[j], resid); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr + j, nr + j + resid); + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - (nr + j) + d_index; + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + + idx++; + } + + // Update the plot if it's 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 TimeUpdateEvent(d_residbufs, d_size, d_tags)); + } + + d_index = 0; + j += resid; + d_triggered = false; + + for(n = 0; n < d_nconnections/2; n++) { + d_tags[n].clear(); + } } - } - // Otherwise, copy what we received into the residbufs for next time - else { - for(n = 0; n < d_nconnections; n+=2) { - in = (const gr_complex*)input_items[idx]; - volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], - &d_residbufs[n+1][d_index], - &in[j], datasize); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + j, nr + j + datasize); - for(size_t t = 0; t < tags.size(); t++) - tags[t].offset = tags[t].offset - (nr + j) + d_index; - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } - d_index += datasize; - j += datasize; - } + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx]; + volk_32fc_deinterleave_64f_x2_u(&d_residbufs[n][d_index], + &d_residbufs[n+1][d_index], + &in[j], datasize); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr + j, nr + j + datasize); + + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - (nr + j) + d_index; + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + + idx++; + } + d_index += datasize; + j += datasize; + } + + ret = j; + } } - return j; + return ret; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h index 48a534aa67..e111dd863e 100644 --- a/gr-qtgui/lib/time_sink_c_impl.h +++ b/gr-qtgui/lib/time_sink_c_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011,2012 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -53,7 +53,19 @@ namespace gr { gr::high_res_timer_type d_update_time; gr::high_res_timer_type d_last_time; - void npoints_resize(); + 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; + int d_trigger_delay; + bool d_triggered; + int d_trigger_count; + + bool _test_trigger_slope(const gr_complex *in) const; + void _gui_update_trigger(); public: time_sink_c_impl(int size, double samp_rate, @@ -79,6 +91,8 @@ namespace gr { void set_nsamps(const int size); void set_samp_rate(const double samp_rate); void set_line_alpha(int which, double alpha); + void set_trigger_mode(trigger_mode mode, trigger_slope slope, + float level, float delay, int channel); std::string title(); std::string line_label(int which); diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc index cbfa2f1480..ca3cef3d92 100644 --- a/gr-qtgui/lib/time_sink_f_impl.cc +++ b/gr-qtgui/lib/time_sink_f_impl.cc @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011,2012 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -49,8 +49,8 @@ namespace gr { int nconnections, QWidget *parent) : sync_block("time_sink_f", - io_signature::make(nconnections, nconnections, sizeof(float)), - io_signature::make(0, 0, 0)), + io_signature::make(nconnections, nconnections, sizeof(float)), + io_signature::make(0, 0, 0)), d_size(size), d_samp_rate(samp_rate), d_name(name), d_nconnections(nconnections), d_parent(parent) { @@ -65,7 +65,7 @@ namespace gr { // Set alignment properties for VOLK const int alignment_multiple = - volk_get_alignment() / sizeof(gr_complex); + volk_get_alignment() / sizeof(float); set_alignment(std::max(1,alignment_multiple)); d_tags = std::vector< std::vector<gr::tag_t> >(d_nconnections); @@ -189,6 +189,32 @@ namespace gr { } void + time_sink_f_impl::set_trigger_mode(trigger_mode mode, + trigger_slope slope, + float level, + float delay, int channel) + { + d_trigger_mode = mode; + d_trigger_slope = slope; + d_trigger_level = level; + d_trigger_delay = static_cast<int>(delay*d_samp_rate); + d_trigger_channel = channel; + d_triggered = false; + d_trigger_count = 0; + + if(d_trigger_delay > d_size) + throw std::runtime_error("qtgui::time_sink_f: trigger delay set outside of display range.\n"); + + d_main_gui->setTriggerMode(d_trigger_mode); + d_main_gui->setTriggerSlope(d_trigger_slope); + d_main_gui->setTriggerLevel(d_trigger_level); + d_main_gui->setTriggerDelay(delay); + d_main_gui->setTriggerChannel(d_trigger_channel); + + set_history(d_trigger_delay + 2); + } + + void time_sink_f_impl::set_size(int width, int height) { d_main_gui->resize(QSize(width, height)); @@ -274,13 +300,6 @@ namespace gr { } void - time_sink_f_impl::npoints_resize() - { - int newsize = d_main_gui->getNPoints(); - set_nsamps(newsize); - } - - void time_sink_f_impl::enable_stem_plot(bool en) { d_main_gui->setStem(en); @@ -334,77 +353,153 @@ namespace gr { d_index = 0; } + void + time_sink_f_impl::_npoints_resize() + { + int newsize = d_main_gui->getNPoints(); + set_nsamps(newsize); + } + + void + time_sink_f_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(); + + float d = d_main_gui->getTriggerDelay(); + int delay = static_cast<int>(d*d_samp_rate); + + if(delay != d_trigger_delay) { + if(d_trigger_delay > d_size) + throw std::runtime_error("qtgui::time_sink_f: trigger delay set outside of display range.\n"); + d_trigger_delay = delay; + set_history(d_trigger_delay + 2); + } + } + + bool + time_sink_f_impl::_test_trigger_slope(const float *in) const + { + float x0, x1; + x0 = in[0]; + x1 = 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 time_sink_f_impl::work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int n=0, j=0, idx=0; - const float *in = (const float*)input_items[idx]; + int n=0, j=0, idx=0, ret=0; + const float *in; - npoints_resize(); + _npoints_resize(); + _gui_update_trigger(); for(int i=0; i < noutput_items; i+=d_size) { - unsigned int datasize = noutput_items - i; + + // If auto or normal trigger, look for the trigger + int trigger_index = i; + if((d_trigger_mode != TRIG_MODE_FREE) && !d_triggered) { + for(; trigger_index < noutput_items; trigger_index++) { + d_trigger_count++; + + // Test if trigger has occurred based on the input stream, + // channel number, and slope direction + in = (const float*)input_items[d_trigger_channel]; + if(_test_trigger_slope(&in[trigger_index + d_trigger_delay])) { + d_triggered = true; + j = trigger_index; + 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; + } + + ret = trigger_index; + i = trigger_index; + } + + unsigned int datasize = noutput_items - trigger_index; 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 float*)input_items[idx]; - volk_32f_convert_64f_u(&d_residbufs[n][d_index], - &in[j], resid); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + j, nr + j + resid); - for(size_t t = 0; t < tags.size(); t++) - tags[t].offset = tags[t].offset - (nr + j) + d_index; - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } - - // 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 TimeUpdateEvent(d_residbufs, d_size, d_tags)); - } - - d_index = 0; - j += resid; - - for(n = 0; n < d_nconnections; n++) { - d_tags[n].clear(); + // If we're in trigger mode, test if we have triggered + if((d_trigger_mode == TRIG_MODE_FREE) || d_triggered) { + // 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 float*)input_items[idx]; + volk_32f_convert_64f_u(&d_residbufs[n][d_index], + &in[j], resid); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr + j, nr + j + resid); + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - (nr + j) + d_index; + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + + idx++; + } + + // Update the plot if it's 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 TimeUpdateEvent(d_residbufs, d_size, d_tags)); + } + + d_index = 0; + j += resid; + d_triggered = false; + + for(n = 0; n < d_nconnections; n++) { + d_tags[n].clear(); + } } - } - // Otherwise, copy what we received into the residbufs for next time - // because we set the output_multiple, this should never need to be called - else { - for(n = 0; n < d_nconnections; n++) { - in = (const float*)input_items[idx]; - volk_32f_convert_64f_u(&d_residbufs[n][d_index], - &in[j], datasize); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + j, nr + j + datasize); - for(size_t t = 0; t < tags.size(); t++) - tags[t].offset = tags[t].offset - (nr + j) + d_index; - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } - d_index += datasize; - j += datasize; - } + + // Otherwise, copy what we received into the residbufs for next time + else { + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx]; + volk_32f_convert_64f_u(&d_residbufs[n][d_index], + &in[j], datasize); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr + j, nr + j + datasize); + + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - (nr + j) + d_index; + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + + idx++; + } + d_index += datasize; + j += datasize; + } + + ret = j; + } } - return j; + return ret; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h index effac56b96..43d73b7d70 100644 --- a/gr-qtgui/lib/time_sink_f_impl.h +++ b/gr-qtgui/lib/time_sink_f_impl.h @@ -1,6 +1,6 @@ /* -*- c++ -*- */ /* - * Copyright 2011,2012 Free Software Foundation, Inc. + * Copyright 2011-2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * @@ -53,7 +53,19 @@ namespace gr { gr::high_res_timer_type d_update_time; gr::high_res_timer_type d_last_time; - void npoints_resize(); + 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; + int d_trigger_delay; + bool d_triggered; + int d_trigger_count; + + bool _test_trigger_slope(const float *in) const; + void _gui_update_trigger(); public: time_sink_f_impl(int size, double samp_rate, @@ -79,6 +91,8 @@ namespace gr { void set_nsamps(const int newsize); void set_samp_rate(const double samp_rate); void set_line_alpha(int which, double alpha); + void set_trigger_mode(trigger_mode mode, trigger_slope slope, + float level, float delay, int channel); std::string title(); std::string line_label(int which); diff --git a/gr-qtgui/lib/timedisplayform.cc b/gr-qtgui/lib/timedisplayform.cc index 419606bbc7..a1b871d0b7 100644 --- a/gr-qtgui/lib/timedisplayform.cc +++ b/gr-qtgui/lib/timedisplayform.cc @@ -40,9 +40,9 @@ TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) _layout->addWidget(_displayPlot, 0, 0); setLayout(_layout); - NPointsMenu *nptsmenu = new NPointsMenu(this); - _menu->addAction(nptsmenu); - connect(nptsmenu, SIGNAL(whichTrigger(int)), + d_nptsmenu = new NPointsMenu(this); + _menu->addAction(d_nptsmenu); + connect(d_nptsmenu, SIGNAL(whichTrigger(int)), this, SLOT(setNPoints(const int))); d_stemmenu = new QAction("Stem Plot", this); @@ -72,6 +72,40 @@ TimeDisplayForm::TimeDisplayForm(int nplots, QWidget* parent) _lines_menu[i]->addAction(d_tagsmenu[i]); } + // 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_delay_act = new PopupMenu("Delay", this); + d_tr_channel_menu = new TriggerChannelMenu(nplots, this); + d_triggermenu->addMenu(d_tr_mode_menu); + d_triggermenu->addMenu(d_tr_slope_menu); + d_triggermenu->addAction(d_tr_level_act); + d_triggermenu->addAction(d_tr_delay_act); + d_triggermenu->addMenu(d_tr_channel_menu); + _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))); + + 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))); + + setTriggerDelay(0); + connect(d_tr_delay_act, SIGNAL(whichTrigger(QString)), + this, SLOT(setTriggerDelay(QString))); + + setTriggerChannel(0); + connect(d_tr_channel_menu, SIGNAL(whichTrigger(int)), + this, SLOT(setTriggerChannel(int))); + Reset(); connect(_displayPlot, SIGNAL(plotPointSelected(const QPointF)), @@ -153,6 +187,7 @@ void TimeDisplayForm::setNPoints(const int npoints) { d_npoints = npoints; + d_nptsmenu->setDiagText(d_npoints); } void @@ -205,3 +240,85 @@ TimeDisplayForm::tagMenuSlot(bool en) getPlot()->enableTagMarker(i, d_tagsmenu[i]->isChecked()); } } + + +/******************************************************************** + * TRIGGER METHODS + *******************************************************************/ + +void +TimeDisplayForm::setTriggerMode(gr::qtgui::trigger_mode mode) +{ + d_trig_mode = mode; + d_tr_mode_menu->getAction(mode)->setChecked(true); +} + +gr::qtgui::trigger_mode +TimeDisplayForm::getTriggerMode() const +{ + return d_trig_mode; +} + +void +TimeDisplayForm::setTriggerSlope(gr::qtgui::trigger_slope slope) +{ + d_trig_slope = slope; + d_tr_slope_menu->getAction(slope)->setChecked(true); +} + +gr::qtgui::trigger_slope +TimeDisplayForm::getTriggerSlope() const +{ + return d_trig_slope; +} + +void +TimeDisplayForm::setTriggerLevel(QString s) +{ + d_trig_level = s.toFloat(); +} + +void +TimeDisplayForm::setTriggerLevel(float level) +{ + d_trig_level = level; + d_tr_level_act->setText(QString().setNum(d_trig_level)); +} + +float +TimeDisplayForm::getTriggerLevel() const +{ + return d_trig_level; +} + +void +TimeDisplayForm::setTriggerDelay(QString s) +{ + d_trig_delay = s.toFloat(); +} + +void +TimeDisplayForm::setTriggerDelay(float delay) +{ + d_trig_delay = delay; + d_tr_delay_act->setText(QString().setNum(d_trig_delay)); +} + +float +TimeDisplayForm::getTriggerDelay() const +{ + return d_trig_delay; +} + +void +TimeDisplayForm::setTriggerChannel(int channel) +{ + d_trig_channel = channel; + d_tr_channel_menu->getAction(d_trig_channel)->setChecked(true); +} + +int +TimeDisplayForm::getTriggerChannel() const +{ + return d_trig_channel; +} diff --git a/gr-qtgui/swig/qtgui_swig.i b/gr-qtgui/swig/qtgui_swig.i index 124c5ee7fc..234a8791b5 100644 --- a/gr-qtgui/swig/qtgui_swig.i +++ b/gr-qtgui/swig/qtgui_swig.i @@ -28,6 +28,8 @@ //load generated python docstrings %include "qtgui_swig_doc.i" +%include "gnuradio/qtgui/trigger_mode.h" + // So we understand the firdes window types %import "gnuradio/filter/firdes.h" |