diff options
author | Tom Rondeau <tom@trondeau.com> | 2013-11-07 12:28:01 -0500 |
---|---|---|
committer | Tom Rondeau <tom@trondeau.com> | 2013-11-07 12:28:01 -0500 |
commit | d800bc32c3d93364e0c34ff60f01f97b64ec30f4 (patch) | |
tree | 6c8529ea67c897da8bfe4edb7deba1de95154aed | |
parent | 73d26d6c7129cf2f84ca8b37896e2ecf8c8f3973 (diff) |
qtgui: improved handling of qtgui time plotting. Simpler work function. Triggering now handled better, including better delay functionality.
-rw-r--r-- | gr-qtgui/examples/qtgui_tags_viewing.grc | 682 | ||||
-rw-r--r-- | gr-qtgui/lib/TimeDomainDisplayPlot.cc | 22 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_c_impl.cc | 374 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_c_impl.h | 15 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_f_impl.cc | 369 | ||||
-rw-r--r-- | gr-qtgui/lib/time_sink_f_impl.h | 17 |
6 files changed, 785 insertions, 694 deletions
diff --git a/gr-qtgui/examples/qtgui_tags_viewing.grc b/gr-qtgui/examples/qtgui_tags_viewing.grc index c77e34565d..296641d5cb 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 Nov 1 18:04:05 2013</timestamp> + <timestamp>Wed Nov 6 11:52:40 2013</timestamp> <block> <key>options</key> <param> @@ -153,10 +153,10 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>blocks_delay</key> <param> <key>id</key> - <value>blocks_add_xx_1</value> + <value>blocks_delay_0</value> </param> <param> <key>_enabled</key> @@ -167,8 +167,12 @@ <value>complex</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>delay</key> + <value>1000</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> </param> <param> <key>vlen</key> @@ -184,7 +188,7 @@ </param> <param> <key>_coordinate</key> - <value>(707, 176)</value> + <value>(300, 240)</value> </param> <param> <key>_rotation</key> @@ -192,10 +196,10 @@ </param> </block> <block> - <key>analog_fastnoise_source_x</key> + <key>blocks_tags_strobe</key> <param> <key>id</key> - <value>analog_fastnoise_source_x_0</value> + <value>blocks_tags_strobe_0</value> </param> <param> <key>_enabled</key> @@ -206,20 +210,16 @@ <value>complex</value> </param> <param> - <key>noise_type</key> - <value>analog.GR_GAUSSIAN</value> - </param> - <param> - <key>amp</key> - <value>0.004</value> + <key>value</key> + <value>pmt.intern("TEST")</value> </param> <param> - <key>seed</key> - <value>0</value> + <key>nsamps</key> + <value>10000</value> </param> <param> - <key>samples</key> - <value>8192</value> + <key>vlen</key> + <value>1</value> </param> <param> <key>affinity</key> @@ -231,7 +231,7 @@ </param> <param> <key>_coordinate</key> - <value>(350, 39)</value> + <value>(16, 232)</value> </param> <param> <key>_rotation</key> @@ -239,109 +239,46 @@ </param> </block> <block> - <key>variable_qtgui_range</key> + <key>analog_fastnoise_source_x</key> <param> <key>id</key> - <value>ntaps</value> + <value>analog_fastnoise_source_x_0</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> + <key>type</key> + <value>complex</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>noise_type</key> + <value>analog.GR_GAUSSIAN</value> </param> <param> - <key>_coordinate</key> - <value>(899, 430)</value> + <key>amp</key> + <value>0.004</value> </param> <param> - <key>_rotation</key> + <key>seed</key> <value>0</value> </param> - </block> - <block> - <key>variable_qtgui_range</key> - <param> - <key>id</key> - <value>delay</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> <param> - <key>label</key> - <value>Delay</value> + <key>samples</key> + <value>8192</value> </param> <param> - <key>value</key> - <value>20</value> + <key>affinity</key> + <value></value> </param> <param> - <key>start</key> + <key>minoutbuf</key> <value>0</value> </param> <param> - <key>stop</key> - <value>200</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>(762, 428)</value> + <value>(350, 39)</value> </param> <param> <key>_rotation</key> @@ -364,7 +301,7 @@ </param> <param> <key>vector</key> - <value>[0.85+0.5j,] + (10000-1)*[0,]</value> + <value>[0.85+0.5j, 0.85, 0.85, 0.85+0.5j] + (10000-4)*[0,]</value> </param> <param> <key>tags</key> @@ -388,7 +325,7 @@ </param> <param> <key>_coordinate</key> - <value>(13, 133)</value> + <value>(13, 132)</value> </param> <param> <key>_rotation</key> @@ -396,10 +333,10 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>blocks_add_xx</key> <param> <key>id</key> - <value>blocks_throttle_0</value> + <value>blocks_add_xx_0</value> </param> <param> <key>_enabled</key> @@ -410,8 +347,8 @@ <value>complex</value> </param> <param> - <key>samples_per_second</key> - <value>50e3</value> + <key>num_inputs</key> + <value>2</value> </param> <param> <key>vlen</key> @@ -427,7 +364,7 @@ </param> <param> <key>_coordinate</key> - <value>(266, 149)</value> + <value>(482, 193)</value> </param> <param> <key>_rotation</key> @@ -435,30 +372,22 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>blocks_add_xx</key> <param> <key>id</key> - <value>blocks_vector_source_x_0_0_0</value> + <value>blocks_add_xx_1</value> </param> <param> <key>_enabled</key> - <value>False</value> + <value>True</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> + <value>complex</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>num_inputs</key> + <value>2</value> </param> <param> <key>vlen</key> @@ -474,7 +403,7 @@ </param> <param> <key>_coordinate</key> - <value>(14, 512)</value> + <value>(707, 176)</value> </param> <param> <key>_rotation</key> @@ -482,30 +411,22 @@ </param> </block> <block> - <key>blocks_vector_source_x</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>blocks_vector_source_x_0_1</value> + <value>blocks_throttle_0</value> </param> <param> <key>_enabled</key> - <value>False</value> + <value>True</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> + <value>complex</value> </param> <param> - <key>repeat</key> - <value>True</value> + <key>samples_per_second</key> + <value>50e3</value> </param> <param> <key>vlen</key> @@ -521,7 +442,7 @@ </param> <param> <key>_coordinate</key> - <value>(14, 421)</value> + <value>(266, 149)</value> </param> <param> <key>_rotation</key> @@ -529,38 +450,54 @@ </param> </block> <block> - <key>blocks_throttle</key> + <key>variable_qtgui_range</key> <param> <key>id</key> - <value>blocks_throttle_0_0</value> + <value>ntaps</value> </param> <param> <key>_enabled</key> - <value>False</value> + <value>True</value> </param> <param> - <key>type</key> - <value>float</value> + <key>label</key> + <value>Num Taps</value> </param> <param> - <key>samples_per_second</key> - <value>samp_rate</value> + <key>value</key> + <value>30</value> </param> <param> - <key>vlen</key> + <key>start</key> <value>1</value> </param> <param> - <key>affinity</key> - <value></value> + <key>stop</key> + <value>100</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <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>(264, 437)</value> + <value>(936, 392)</value> </param> <param> <key>_rotation</key> @@ -571,15 +508,15 @@ <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_0</value> </param> <param> <key>_enabled</key> - <value>False</value> + <value>True</value> </param> <param> <key>type</key> - <value>float</value> + <value>complex</value> </param> <param> <key>name</key> @@ -587,7 +524,7 @@ </param> <param> <key>size</key> - <value>18000</value> + <value>5100</value> </param> <param> <key>srate</key> @@ -595,23 +532,23 @@ </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> + <value>0.001</value> </param> <param> <key>tr_mode</key> - <value>qtgui.TRIG_MODE_FREE</value> + <value>qtgui.TRIG_MODE_TAG</value> </param> <param> <key>tr_slope</key> @@ -619,11 +556,11 @@ </param> <param> <key>tr_level</key> - <value>0.0</value> + <value>.5</value> </param> <param> <key>tr_delay</key> - <value>0</value> + <value>0.06</value> </param> <param> <key>tr_chan</key> @@ -631,7 +568,7 @@ </param> <param> <key>tr_tag</key> - <value>""</value> + <value>strobe</value> </param> <param> <key>entags</key> @@ -639,7 +576,7 @@ </param> <param> <key>gui_hint</key> - <value></value> + <value>1,1,1,1</value> </param> <param> <key>affinity</key> @@ -647,7 +584,7 @@ </param> <param> <key>_coordinate</key> - <value>(474, 467)</value> + <value>(857, 173)</value> </param> <param> <key>_rotation</key> @@ -702,10 +639,10 @@ </param> </block> <block> - <key>blocks_tags_strobe</key> + <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>blocks_tags_strobe_0</value> + <value>qtgui_time_sink_x_0</value> </param> <param> <key>_enabled</key> @@ -716,71 +653,72 @@ <value>complex</value> </param> <param> - <key>value</key> - <value>pmt.intern("TEST")</value> + <key>name</key> + <value>QT GUI Plot</value> </param> <param> - <key>nsamps</key> - <value>10000</value> + <key>size</key> + <value>18000</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>srate</key> + <value>samp_rate</value> </param> <param> - <key>affinity</key> - <value></value> + <key>ymin</key> + <value>-0.1</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>ymax</key> + <value>1.5</value> </param> <param> - <key>_coordinate</key> - <value>(16, 232)</value> + <key>nconnections</key> + <value>2</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>update_time</key> + <value>0.10</value> </param> - </block> - <block> - <key>blocks_delay</key> <param> - <key>id</key> - <value>blocks_delay_0</value> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_NORM</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> </param> <param> - <key>type</key> - <value>complex</value> + <key>tr_level</key> + <value>0.1</value> </param> <param> - <key>delay</key> - <value>1000</value> + <key>tr_delay</key> + <value>0</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>tr_chan</key> + <value>0</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>tr_tag</key> + <value>""</value> </param> <param> - <key>affinity</key> + <key>entags</key> + <value>True</value> + </param> + <param> + <key>gui_hint</key> <value></value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(300, 240)</value> + <value>(860, 298)</value> </param> <param> <key>_rotation</key> @@ -788,10 +726,10 @@ </param> </block> <block> - <key>blocks_add_xx</key> + <key>fir_filter_xxx</key> <param> <key>id</key> - <value>blocks_add_xx_0</value> + <value>fir_filter_xxx_0</value> </param> <param> <key>_enabled</key> @@ -799,15 +737,19 @@ </param> <param> <key>type</key> - <value>complex</value> + <value>ccc</value> </param> <param> - <key>num_inputs</key> - <value>2</value> + <key>decim</key> + <value>1</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>taps</key> + <value>int(ntaps)*[1,]+[1,]</value> + </param> + <param> + <key>samp_delay</key> + <value>int(ntaps)</value> </param> <param> <key>affinity</key> @@ -819,7 +761,7 @@ </param> <param> <key>_coordinate</key> - <value>(482, 193)</value> + <value>(660, 76)</value> </param> <param> <key>_rotation</key> @@ -827,10 +769,10 @@ </param> </block> <block> - <key>blocks_delay</key> + <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>blocks_delay_0_0</value> + <value>qtgui_time_sink_x_0_1</value> </param> <param> <key>_enabled</key> @@ -841,71 +783,72 @@ <value>complex</value> </param> <param> - <key>delay</key> - <value>int(delay)</value> + <key>name</key> + <value>QT GUI Plot</value> </param> <param> - <key>num_ports</key> - <value>1</value> + <key>size</key> + <value>1000</value> </param> <param> - <key>vlen</key> - <value>1</value> + <key>srate</key> + <value>samp_rate</value> </param> <param> - <key>affinity</key> - <value></value> + <key>ymin</key> + <value>-0.1</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>ymax</key> + <value>4.5</value> </param> <param> - <key>_coordinate</key> - <value>(890, 44)</value> + <key>nconnections</key> + <value>2</value> </param> <param> - <key>_rotation</key> - <value>0</value> + <key>update_time</key> + <value>0.10</value> </param> - </block> - <block> - <key>fir_filter_xxx</key> <param> - <key>id</key> - <value>fir_filter_xxx_0</value> + <key>tr_mode</key> + <value>qtgui.TRIG_MODE_NORM</value> </param> <param> - <key>_enabled</key> - <value>True</value> + <key>tr_slope</key> + <value>qtgui.TRIG_SLOPE_POS</value> </param> <param> - <key>type</key> - <value>ccc</value> + <key>tr_level</key> + <value>.1</value> </param> <param> - <key>decim</key> - <value>1</value> + <key>tr_delay</key> + <value>0.015</value> </param> <param> - <key>taps</key> - <value>int(ntaps)*[1,]+[1,]</value> + <key>tr_chan</key> + <value>0</value> </param> <param> - <key>samp_delay</key> - <value>int(ntaps)</value> + <key>tr_tag</key> + <value>""</value> </param> <param> - <key>affinity</key> - <value></value> + <key>entags</key> + <value>True</value> </param> <param> - <key>minoutbuf</key> - <value>0</value> + <key>gui_hint</key> + <value>1,0,1,1</value> + </param> + <param> + <key>affinity</key> + <value></value> </param> <param> <key>_coordinate</key> - <value>(660, 76)</value> + <value>(1072, 77)</value> </param> <param> <key>_rotation</key> @@ -916,15 +859,15 @@ <key>qtgui_time_sink_x</key> <param> <key>id</key> - <value>qtgui_time_sink_x_0_1_0</value> + <value>qtgui_time_sink_x_0_0</value> </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> <key>type</key> - <value>complex</value> + <value>float</value> </param> <param> <key>name</key> @@ -932,7 +875,7 @@ </param> <param> <key>size</key> - <value>18000</value> + <value>1024</value> </param> <param> <key>srate</key> @@ -940,15 +883,15 @@ </param> <param> <key>ymin</key> - <value>-0.1</value> + <value>-1</value> </param> <param> <key>ymax</key> - <value>1.5</value> + <value>1</value> </param> <param> <key>nconnections</key> - <value>1</value> + <value>2</value> </param> <param> <key>update_time</key> @@ -956,7 +899,7 @@ </param> <param> <key>tr_mode</key> - <value>qtgui.TRIG_MODE_NORM</value> + <value>qtgui.TRIG_MODE_TAG</value> </param> <param> <key>tr_slope</key> @@ -964,7 +907,7 @@ </param> <param> <key>tr_level</key> - <value>.1</value> + <value>0.0</value> </param> <param> <key>tr_delay</key> @@ -972,11 +915,11 @@ </param> <param> <key>tr_chan</key> - <value>0</value> + <value>1</value> </param> <param> <key>tr_tag</key> - <value>""</value> + <value>second stream</value> </param> <param> <key>entags</key> @@ -984,7 +927,7 @@ </param> <param> <key>gui_hint</key> - <value>1,1,1,1</value> + <value></value> </param> <param> <key>affinity</key> @@ -992,7 +935,7 @@ </param> <param> <key>_coordinate</key> - <value>(857, 173)</value> + <value>(475, 444)</value> </param> <param> <key>_rotation</key> @@ -1000,86 +943,93 @@ </param> </block> <block> - <key>qtgui_time_sink_x</key> + <key>blocks_vector_source_x</key> <param> <key>id</key> - <value>qtgui_time_sink_x_0_1</value> + <value>blocks_vector_source_x_0_0_0</value> </param> <param> <key>_enabled</key> - <value>True</value> + <value>False</value> </param> <param> <key>type</key> - <value>complex</value> + <value>float</value> </param> <param> - <key>name</key> - <value>QT GUI Plot</value> + <key>vector</key> + <value>10*[0,] + [0.5,] + (100-10-1)*[0,]</value> </param> <param> - <key>size</key> - <value>1000</value> + <key>tags</key> + <value>tagged_streams.make_lengthtags((128,), (110,), "second stream")</value> </param> <param> - <key>srate</key> - <value>samp_rate</value> + <key>repeat</key> + <value>True</value> </param> <param> - <key>ymin</key> - <value>-0.1</value> + <key>vlen</key> + <value>1</value> </param> <param> - <key>ymax</key> - <value>1.5</value> + <key>affinity</key> + <value></value> </param> <param> - <key>nconnections</key> - <value>2</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>_coordinate</key> + <value>(15, 489)</value> </param> <param> - <key>tr_mode</key> - <value>qtgui.TRIG_MODE_NORM</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>blocks_vector_source_x</key> <param> - <key>tr_slope</key> - <value>qtgui.TRIG_SLOPE_POS</value> + <key>id</key> + <value>blocks_vector_source_x_0_1</value> </param> <param> - <key>tr_level</key> - <value>.1</value> + <key>_enabled</key> + <value>False</value> </param> <param> - <key>tr_delay</key> - <value>0.015</value> + <key>type</key> + <value>float</value> </param> <param> - <key>tr_chan</key> - <value>0</value> + <key>vector</key> + <value>[-0.85,] + (100-1)*[0,]</value> </param> <param> - <key>tr_tag</key> - <value>""</value> + <key>tags</key> + <value>tagged_streams.make_lengthtags((1024,), (0,), "testing tags")</value> </param> <param> - <key>entags</key> + <key>repeat</key> <value>True</value> </param> <param> - <key>gui_hint</key> - <value>1,0,1,1</value> + <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>(1072, 77)</value> + <value>(15, 398)</value> </param> <param> <key>_rotation</key> @@ -1087,10 +1037,49 @@ </param> </block> <block> - <key>qtgui_time_sink_x</key> + <key>blocks_throttle</key> <param> <key>id</key> - <value>qtgui_time_sink_x_0</value> + <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>(267, 414)</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> @@ -1101,72 +1090,83 @@ <value>complex</value> </param> <param> - <key>name</key> - <value>QT GUI Plot</value> + <key>delay</key> + <value>int(delay)</value> </param> <param> - <key>size</key> - <value>18000</value> + <key>num_ports</key> + <value>1</value> </param> <param> - <key>srate</key> + <key>vlen</key> <value>1</value> </param> <param> - <key>ymin</key> - <value>-0.1</value> + <key>affinity</key> + <value></value> </param> <param> - <key>ymax</key> - <value>1.5</value> + <key>minoutbuf</key> + <value>0</value> </param> <param> - <key>nconnections</key> - <value>2</value> + <key>_coordinate</key> + <value>(890, 44)</value> </param> <param> - <key>update_time</key> - <value>0.10</value> + <key>_rotation</key> + <value>0</value> </param> + </block> + <block> + <key>variable_qtgui_range</key> <param> - <key>tr_mode</key> - <value>qtgui.TRIG_MODE_NORM</value> + <key>id</key> + <value>delay</value> </param> <param> - <key>tr_slope</key> - <value>qtgui.TRIG_SLOPE_POS</value> + <key>_enabled</key> + <value>True</value> </param> <param> - <key>tr_level</key> - <value>.1</value> + <key>label</key> + <value>Delay</value> </param> <param> - <key>tr_delay</key> - <value>1000</value> + <key>value</key> + <value>300</value> </param> <param> - <key>tr_chan</key> + <key>start</key> <value>0</value> </param> <param> - <key>tr_tag</key> - <value>""</value> + <key>stop</key> + <value>1000</value> </param> <param> - <key>entags</key> - <value>True</value> + <key>step</key> + <value>1</value> </param> <param> - <key>gui_hint</key> - <value></value> + <key>widget</key> + <value>counter_slider</value> </param> <param> - <key>affinity</key> + <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>(860, 298)</value> + <value>(814, 390)</value> </param> <param> <key>_rotation</key> @@ -1204,18 +1204,6 @@ <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_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_add_xx_0</source_block_id> <sink_block_id>fir_filter_xxx_0</sink_block_id> <source_key>0</source_key> @@ -1240,33 +1228,45 @@ <sink_key>1</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_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_vector_source_x_0_1</source_block_id> - <sink_block_id>blocks_throttle_0_0</sink_block_id> + <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_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_tags_strobe_0</source_block_id> - <sink_block_id>blocks_delay_0</sink_block_id> + <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_vector_source_x_0_0</source_block_id> - <sink_block_id>qtgui_time_sink_x_0</sink_block_id> + <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>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> </flow_graph> diff --git a/gr-qtgui/lib/TimeDomainDisplayPlot.cc b/gr-qtgui/lib/TimeDomainDisplayPlot.cc index 052aaf8cf7..adc6baa4a9 100644 --- a/gr-qtgui/lib/TimeDomainDisplayPlot.cc +++ b/gr-qtgui/lib/TimeDomainDisplayPlot.cc @@ -255,6 +255,12 @@ TimeDomainDisplayPlot::plotNewData(const std::vector<double*> dataPoints, std::vector<gr::tag_t>::const_iterator t; for(t = tag->begin(); t != tag->end(); t++) { uint64_t offset = (*t).offset; + + // Ignore tag if its offset is outside our plottable vector. + if(offset >= (uint64_t)d_numPoints) { + continue; + } + double sample_offset = double(offset)/d_sample_rate; std::stringstream s; @@ -265,8 +271,20 @@ TimeDomainDisplayPlot::plotNewData(const std::vector<double*> dataPoints, // real and imaginary parts and put the tag on that one. int which = i; if(cmplx) { - if(fabs(d_ydata[i][offset]) < fabs(d_ydata[i+1][offset])) - which = i+1; + bool show0 = d_plot_curve[i]->isVisible(); + bool show1 = d_plot_curve[i+1]->isVisible(); + + // If we are showing both streams, select the inptu stream + // with the larger value + if(show0 && show1) { + if(fabs(d_ydata[i][offset]) < fabs(d_ydata[i+1][offset])) + which = i+1; + } + else { + // If show0, we keep which = i; otherwise, use i+1. + if(show1) + which = i+1; + } } double yval = d_ydata[which][offset]; diff --git a/gr-qtgui/lib/time_sink_c_impl.cc b/gr-qtgui/lib/time_sink_c_impl.cc index c87a9ee900..fb3ffcd00b 100644 --- a/gr-qtgui/lib/time_sink_c_impl.cc +++ b/gr-qtgui/lib/time_sink_c_impl.cc @@ -26,8 +26,6 @@ #include "time_sink_c_impl.h" #include <gnuradio/io_signature.h> -#include <gnuradio/block_detail.h> -#include <gnuradio/buffer.h> #include <string.h> #include <volk/volk.h> #include <gnuradio/fft/fft.h> @@ -53,16 +51,14 @@ namespace gr { : sync_block("time_sink_c", 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_size(size), d_buffer_size(2*size), d_samp_rate(samp_rate), d_name(name), d_nconnections(2*nconnections), d_parent(parent) { d_main_gui = NULL; - d_index = 0; - - for(int i = 0; i < d_nconnections; i++) { - d_residbufs.push_back(fft::malloc_double(d_size)); - memset(d_residbufs[i], 0, d_size*sizeof(double)); + for(int n = 0; n < d_nconnections; n++) { + d_buffers.push_back(fft::malloc_double(d_buffer_size)); + memset(d_buffers[n], 0, d_buffer_size*sizeof(double)); } // Set alignment properties for VOLK @@ -74,10 +70,11 @@ namespace gr { 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); - d_initial_delay = d_trigger_delay; + d_main_gui->setNPoints(d_size); // setup GUI box with size + set_trigger_mode(TRIG_MODE_FREE, TRIG_SLOPE_POS, 0, 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 } time_sink_c_impl::~time_sink_c_impl() @@ -86,8 +83,8 @@ namespace gr { d_main_gui->close(); // d_main_gui is a qwidget destroyed with its parent - for(int i = 0; i < d_nconnections; i++) { - fft::free(d_residbufs[i]); + for(int n = 0; n < d_nconnections; n++) { + fft::free(d_buffers[n]); } } @@ -202,6 +199,8 @@ namespace gr { float delay, 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; @@ -211,10 +210,11 @@ namespace gr { d_triggered = false; d_trigger_count = 0; - if(d_trigger_delay >= d_size) { - GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (%2%).") \ - % d_trigger_delay % d_size); - d_trigger_delay = d_size-1; + if((d_trigger_delay < 0) || (d_trigger_delay >= d_size)) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%).") \ + % (d_trigger_delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + d_trigger_delay = std::max(0, std::min(d_size-1, d_trigger_delay)); + delay = d_trigger_delay/d_samp_rate; } d_main_gui->setTriggerMode(d_trigger_mode); @@ -224,8 +224,7 @@ namespace gr { d_main_gui->setTriggerChannel(d_trigger_channel); d_main_gui->setTriggerTagKey(tag_key); - set_history(d_trigger_delay + 2); - declare_sample_delay(d_trigger_delay+1); + _reset(); } void @@ -279,23 +278,31 @@ namespace gr { void time_sink_c_impl::set_nsamps(const int newsize) { - gr::thread::scoped_lock lock(d_mutex); - if(newsize != d_size) { - // Resize residbuf and replace data - for(int i = 0; i < d_nconnections; i++) { - fft::free(d_residbufs[i]); - d_residbufs[i] = fft::malloc_double(newsize); - - memset(d_residbufs[i], 0, newsize*sizeof(double)); - } + gr::thread::scoped_lock lock(d_mutex); // Set new size and reset buffer index // (throws away any currently held data, but who cares?) d_size = newsize; - d_index = 0; + d_buffer_size = 2*d_size; + + // Resize buffers and replace data + for(int n = 0; n < d_nconnections; n++) { + fft::free(d_buffers[n]); + d_buffers[n] = fft::malloc_double(d_buffer_size); + memset(d_buffers[n], 0, d_buffer_size*sizeof(double)); + } + + // If delay was set beyond the new boundary, pull it back. + if(d_trigger_delay >= d_size) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%). Moving to 50%% point.") \ + % (d_trigger_delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + d_trigger_delay = d_size/2; + d_main_gui->setTriggerDelay(d_trigger_delay/d_samp_rate); + } d_main_gui->setNPoints(d_size); + _reset(); } } @@ -364,7 +371,57 @@ namespace gr { void time_sink_c_impl::reset() { - d_index = 0; + gr::thread::scoped_lock lock(d_mutex); + _reset(); + } + + void + time_sink_c_impl::_reset() + { + // Move the tail of the buffers to the front. This section + // represents data that might have to be plotted again if a + // trigger occurs and we have a trigger delay set. The tail + // section is between (d_end-d_trigger_delay) and d_end. + int n; + if(d_trigger_delay) { + for(n = 0; n < d_nconnections; n++) { + memmove(d_buffers[n], &d_buffers[n][d_size-d_trigger_delay], d_trigger_delay*sizeof(double)); + } + + // Also move the offsets of any tags that occur in the tail + // section so they would be plotted again, too. + for(n = 0; n < d_nconnections/2; n++) { + std::vector<gr::tag_t> tmp_tags; + for(size_t t = 0; t < d_tags[n].size(); t++) { + if(d_tags[n][t].offset > (d_size - d_trigger_delay)) { + d_tags[n][t].offset = d_tags[n][t].offset - (d_size - d_trigger_delay); + tmp_tags.push_back(d_tags[n][t]); + } + } + d_tags[n] = tmp_tags; + } + } + // Otherwise, just clear the local list of tags. + else { + for(n = 0; n < d_nconnections/2; n++) { + d_tags[n].clear(); + } + } + + // Reset the start and end indices. + d_start = 0; + d_end = d_size; + + // Reset the trigger. If in free running mode, ignore the + // trigger delay and always set trigger to true. + if(d_trigger_mode == TRIG_MODE_FREE) { + d_index = 0; + d_triggered = true; + } + else { + d_index = d_trigger_delay; + d_triggered = false; + } } void @@ -375,55 +432,94 @@ namespace gr { } void + time_sink_c_impl::_adjust_tags(int adj) + { + for(size_t n = 0; n < d_tags.size(); n++) { + for(size_t t = 0; t < d_tags[n].size(); t++) { + d_tags[n][t].offset += adj; + } + } + } + + 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(); + d_trigger_count = 0; float delayf = d_main_gui->getTriggerDelay(); int delay = static_cast<int>(delayf*d_samp_rate); if(delay != d_trigger_delay) { // We restrict the delay to be within the window of time being - // plotted. This also restrict it to be less than the number - // of output items since we cannot set the history greater - // than this. We can probably get around this latter part by - // not using history and doing more work inside 'work' to keep - // track of things. - int maxn; - - // If we have built the detail and buffers, we're stuck with - // the max number of item; otherwise the buffer will be built - // around this value so we just don't want to go over d_size. - int correction = 5; // give us a bit of room at the edge. - block_detail_sptr d = detail(); - if(d) { - int max_possible = d->input(d_trigger_channel/2)->max_possible_items_available()/2 - d_initial_delay; - maxn = std::max(1, std::min(max_possible, d_size) - correction); - } - else { - maxn = d_size-correction; - d_initial_delay = d_trigger_delay; // store this value before we create a d_detail - } - - if(delay > maxn) { - GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1% / %2% sec) outside of max range (%3% / %4% sec)") \ - % delay % delayf % maxn % (maxn/d_samp_rate)); - delay = maxn - d_initial_delay; + // plotted. + if((delay < 0) || (delay >= d_size)) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%).") \ + % (delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + delay = std::max(0, std::min(d_size-1, delay)); delayf = delay/d_samp_rate; } d_trigger_delay = delay; d_main_gui->setTriggerDelay(delayf); - set_history(d_trigger_delay+1); + _reset(); } std::string tagkey = d_main_gui->getTriggerTagKey(); d_trigger_tag_key = pmt::intern(tagkey); } + void + time_sink_c_impl::_test_trigger_tags(int nitems) + { + int trigger_index; + + uint64_t nr = nitems_read(d_trigger_channel/2); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, d_trigger_channel/2, + 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 - d_trigger_delay - 1; + d_end = d_start + d_size; + d_trigger_count = 0; + _adjust_tags(-d_start); + } + } + + void + time_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/2]; + 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_trigger_delay; + d_end = d_start + d_size; + d_trigger_count = 0; + _adjust_tags(-d_start); + 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 time_sink_c_impl::_test_trigger_slope(const gr_complex *in) const { @@ -449,134 +545,70 @@ namespace gr { gr_vector_void_star &output_items) { int n=0, idx=0; - int trigger_index=0; const gr_complex *in; _npoints_resize(); _gui_update_trigger(); - for(int i=0; i < noutput_items; i+=d_size) { - - // If auto or normal trigger, look for the trigger - trigger_index = i; - if((d_trigger_mode != TRIG_MODE_FREE) && !d_triggered) { - - if(d_trigger_mode == TRIG_MODE_TAG) { - uint64_t nr = nitems_read(d_trigger_channel/2); - - // Look for tags past the delay so we can subtract delay - // to calculate the trigger_index without it going - // negative. - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, d_trigger_channel/2, - nr + trigger_index + d_trigger_delay, - nr + trigger_index + d_trigger_delay + noutput_items, - d_trigger_tag_key); - if(tags.size() > 0) { - d_index = 0; - d_triggered = true; - d_trigger_count = 0; - trigger_index = tags[0].offset - nr - trigger_index - d_trigger_delay; - break; - } - else - trigger_index = noutput_items; - } - else { - 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; - 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; - } - } + gr::thread::scoped_lock lock(d_mutex); + + 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 - i = trigger_index; + // 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); } + } - unsigned int datasize = noutput_items - trigger_index; - unsigned int resid = d_size-d_index; - idx = 0; - - // 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[trigger_index], resid); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + trigger_index, - nr + trigger_index + resid); - for(size_t t = 0; t < tags.size(); t++) { - tags[t].offset = tags[t].offset - (nr + trigger_index) + d_index; - } - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } + // Copy data into the buffers. + for(n = 0; n < d_nconnections; n+=2) { + in = (const gr_complex*)input_items[idx]; + volk_32fc_deinterleave_64f_x2(&d_buffers[n][d_index], + &d_buffers[n+1][d_index], + &in[0], nitems); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr, nr + nitems); + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - nr + (d_index-d_start); + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + idx++; + } + d_index += nitems; - // 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)); - } + // 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_buffers[n], &d_buffers[n][d_start], d_size*sizeof(double)); + } - d_index = 0; - trigger_index += resid; - d_triggered = false; + // 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 TimeUpdateEvent(d_buffers, d_size, d_tags)); + } - for(n = 0; n < d_nconnections/2; n++) { - d_tags[n].clear(); - } - } + // We've plotting, so reset the state + _reset(); + } - // 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[trigger_index], datasize); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + trigger_index, - nr + trigger_index + datasize); - - for(size_t t = 0; t < tags.size(); t++) { - tags[t].offset = tags[t].offset - (nr + trigger_index) + d_index; - } - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } - d_index += datasize; - trigger_index += datasize; - } - } + // If we've filled up the buffers but haven't triggered, reset. + if(d_index == d_end) { + _reset(); } - return trigger_index; + return nitems; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/time_sink_c_impl.h b/gr-qtgui/lib/time_sink_c_impl.h index 9353a96802..6fe8c9c2bd 100644 --- a/gr-qtgui/lib/time_sink_c_impl.h +++ b/gr-qtgui/lib/time_sink_c_impl.h @@ -38,13 +38,13 @@ namespace gr { gr::thread::mutex d_mutex; - int d_size; + int d_size, d_buffer_size; double d_samp_rate; std::string d_name; int d_nconnections; - int d_index; - std::vector<double*> d_residbufs; + int d_index, d_start, d_end; + std::vector<double*> d_buffers; std::vector< std::vector<gr::tag_t> > d_tags; QWidget *d_parent; @@ -53,8 +53,6 @@ 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; @@ -66,8 +64,13 @@ namespace gr { int d_trigger_count; int d_initial_delay; // used for limiting d_trigger_delay - bool _test_trigger_slope(const gr_complex *in) const; + void _reset(); + void _npoints_resize(); + void _adjust_tags(int adj); 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: time_sink_c_impl(int size, double samp_rate, diff --git a/gr-qtgui/lib/time_sink_f_impl.cc b/gr-qtgui/lib/time_sink_f_impl.cc index e3c385288f..85f9dc4fdd 100644 --- a/gr-qtgui/lib/time_sink_f_impl.cc +++ b/gr-qtgui/lib/time_sink_f_impl.cc @@ -53,16 +53,14 @@ namespace gr { : sync_block("time_sink_f", 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_size(size), d_buffer_size(2*size), d_samp_rate(samp_rate), d_name(name), d_nconnections(nconnections), d_parent(parent) { d_main_gui = NULL; - d_index = 0; - - for(int i = 0; i < d_nconnections; i++) { - d_residbufs.push_back(fft::malloc_double(d_size)); - memset(d_residbufs[i], 0, d_size*sizeof(double)); + for(int n = 0; n < d_nconnections; n++) { + d_buffers.push_back(fft::malloc_double(d_buffer_size)); + memset(d_buffers[n], 0, d_buffer_size*sizeof(double)); } // Set alignment properties for VOLK @@ -74,10 +72,11 @@ namespace gr { 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); - d_initial_delay = d_trigger_delay; + d_main_gui->setNPoints(d_size); // setup GUI box with size + set_trigger_mode(TRIG_MODE_FREE, TRIG_SLOPE_POS, 0, 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 } time_sink_f_impl::~time_sink_f_impl() @@ -86,8 +85,8 @@ namespace gr { d_main_gui->close(); // d_main_gui is a qwidget destroyed with its parent - for(int i = 0; i < d_nconnections; i++) { - fft::free(d_residbufs[i]); + for(int n = 0; n < d_nconnections; n++) { + fft::free(d_buffers[n]); } } @@ -202,6 +201,8 @@ namespace gr { float delay, 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; @@ -211,10 +212,11 @@ namespace gr { d_triggered = false; d_trigger_count = 0; - if(d_trigger_delay >= d_size) { - GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (%2%).") \ - % d_trigger_delay % d_size); - d_trigger_delay = d_size-1; + if((d_trigger_delay < 0) || (d_trigger_delay >= d_size)) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%).") \ + % (d_trigger_delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + d_trigger_delay = std::max(0, std::min(d_size-1, d_trigger_delay)); + delay = d_trigger_delay/d_samp_rate; } d_main_gui->setTriggerMode(d_trigger_mode); @@ -224,8 +226,7 @@ namespace gr { d_main_gui->setTriggerChannel(d_trigger_channel); d_main_gui->setTriggerTagKey(tag_key); - set_history(d_trigger_delay + 2); - declare_sample_delay(d_trigger_delay+1); + _reset(); } void @@ -279,23 +280,31 @@ namespace gr { void time_sink_f_impl::set_nsamps(const int newsize) { - gr::thread::scoped_lock lock(d_mutex); - if(newsize != d_size) { - // Resize residbuf and replace data - for(int i = 0; i < d_nconnections; i++) { - fft::free(d_residbufs[i]); - d_residbufs[i] = fft::malloc_double(newsize); - - memset(d_residbufs[i], 0, newsize*sizeof(double)); - } + gr::thread::scoped_lock lock(d_mutex); // Set new size and reset buffer index // (throws away any currently held data, but who cares?) d_size = newsize; - d_index = 0; + d_buffer_size = 2*d_size; + + // Resize buffers and replace data + for(int n = 0; n < d_nconnections; n++) { + fft::free(d_buffers[n]); + d_buffers[n] = fft::malloc_double(d_buffer_size); + memset(d_buffers[n], 0, d_buffer_size*sizeof(double)); + } + + // If delay was set beyond the new boundary, pull it back. + if(d_trigger_delay >= d_size) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%). Moving to 50%% point.") \ + % (d_trigger_delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + d_trigger_delay = d_size-1; + d_main_gui->setTriggerDelay(d_trigger_delay/d_samp_rate); + } d_main_gui->setNPoints(d_size); + _reset(); } } @@ -364,7 +373,57 @@ namespace gr { void time_sink_f_impl::reset() { - d_index = 0; + gr::thread::scoped_lock lock(d_mutex); + _reset(); + } + + void + time_sink_f_impl::_reset() + { + // Move the tail of the buffers to the front. This section + // represents data that might have to be plotted again if a + // trigger occurs and we have a trigger delay set. The tail + // section is between (d_end-d_trigger_delay) and d_end. + int n; + if(d_trigger_delay) { + for(n = 0; n < d_nconnections; n++) { + memmove(d_buffers[n], &d_buffers[n][d_size-d_trigger_delay], d_trigger_delay*sizeof(double)); + } + + // Also move the offsets of any tags that occur in the tail + // section so they would be plotted again, too. + for(n = 0; n < d_nconnections; n++) { + std::vector<gr::tag_t> tmp_tags; + for(size_t t = 0; t < d_tags[n].size(); t++) { + if(d_tags[n][t].offset > (d_size - d_trigger_delay)) { + d_tags[n][t].offset = d_tags[n][t].offset - (d_size - d_trigger_delay); + tmp_tags.push_back(d_tags[n][t]); + } + } + d_tags[n] = tmp_tags; + } + } + // Otherwise, just clear the local list of tags. + else { + for(n = 0; n < d_nconnections; n++) { + d_tags[n].clear(); + } + } + + // Reset the start and end indices. + d_start = 0; + d_end = d_size; + + // Reset the trigger. If in free running mode, ignore the + // trigger delay and always set trigger to true. + if(d_trigger_mode == TRIG_MODE_FREE) { + d_index = 0; + d_triggered = true; + } + else { + d_index = d_trigger_delay; + d_triggered = false; + } } void @@ -375,55 +434,94 @@ namespace gr { } void + time_sink_f_impl::_adjust_tags(int adj) + { + for(size_t n = 0; n < d_tags.size(); n++) { + for(size_t t = 0; t < d_tags[n].size(); t++) { + d_tags[n][t].offset += adj; + } + } + } + + 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(); + d_trigger_count = 0; float delayf = d_main_gui->getTriggerDelay(); int delay = static_cast<int>(delayf*d_samp_rate); if(delay != d_trigger_delay) { // We restrict the delay to be within the window of time being - // plotted. This also restrict it to be less than the number - // of output items since we cannot set the history greater - // than this. We can probably get around this latter part by - // not using history and doing more work inside 'work' to keep - // track of things. - int maxn; - - // If we have built the detail and buffers, we're stuck with - // the max number of item; otherwise the buffer will be built - // around this value so we just don't want to go over d_size. - int correction = 5; // give us a bit of room at the edge. - block_detail_sptr d = detail(); - if(d) { - int max_possible = d->input(d_trigger_channel)->max_possible_items_available()/2 - d_initial_delay; - maxn = std::max(1, std::min(max_possible, d_size) - correction); - } - else { - maxn = d_size-correction; - d_initial_delay = d_trigger_delay; // store this value before we create a d_detail - } - - if(delay > maxn) { - GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1% / %2% sec) outside of max range (%3% / %4% sec)") \ - % delay % delayf % maxn % (maxn/d_samp_rate)); - delay = maxn - d_initial_delay; + // plotted. + if((delay < 0) || (delay >= d_size)) { + GR_LOG_WARN(d_logger, boost::format("Trigger delay (%1%) outside of display range (0:%2%).") \ + % (delay/d_samp_rate) % ((d_size-1)/d_samp_rate)); + delay = std::max(0, std::min(d_size-1, delay)); delayf = delay/d_samp_rate; } d_trigger_delay = delay; d_main_gui->setTriggerDelay(delayf); - set_history(d_trigger_delay+1); + _reset(); } std::string tagkey = d_main_gui->getTriggerTagKey(); d_trigger_tag_key = pmt::intern(tagkey); } + void + time_sink_f_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 - d_trigger_delay - 1; + d_end = d_start + d_size; + d_trigger_count = 0; + _adjust_tags(-d_start); + } + } + + void + time_sink_f_impl::_test_trigger_norm(int nitems, gr_vector_const_void_star inputs) + { + int trigger_index; + const float *in = (const float*)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_trigger_delay; + d_end = d_start + d_size; + d_trigger_count = 0; + _adjust_tags(-d_start); + 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 time_sink_f_impl::_test_trigger_slope(const float *in) const { @@ -443,132 +541,69 @@ namespace gr { gr_vector_void_star &output_items) { int n=0, idx=0; - int trigger_index=0; const float *in; _npoints_resize(); _gui_update_trigger(); - for(int i=0; i < noutput_items; i+=d_size) { - - // If auto or normal trigger, look for the trigger - trigger_index = i; - if((d_trigger_mode != TRIG_MODE_FREE) && !d_triggered) { - - if(d_trigger_mode == TRIG_MODE_TAG) { - uint64_t nr = nitems_read(d_trigger_channel/2); - - // Look for tags past the delay so we can subtract delay - // to calculate the trigger_index without it going - // negative. - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, d_trigger_channel/2, - nr + trigger_index + d_trigger_delay, - nr + trigger_index + d_trigger_delay + noutput_items, - d_trigger_tag_key); - if(tags.size() > 0) { - d_index = 0; - d_triggered = true; - d_trigger_count = 0; - trigger_index = tags[0].offset - nr - trigger_index - d_trigger_delay; - break; - } - else - trigger_index = noutput_items; - } - else { - 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; - 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; - } - } - - i = trigger_index; - } - - unsigned int datasize = noutput_items - trigger_index; - unsigned int resid = d_size-d_index; - idx = 0; - - // 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[trigger_index], resid); - - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + trigger_index, - nr + trigger_index + resid); - for(size_t t = 0; t < tags.size(); t++) { - tags[t].offset = tags[t].offset - (nr + trigger_index) + d_index; - } - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); - - idx++; - } + gr::thread::scoped_lock lock(d_mutex); - // 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)); - } + 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 - d_index = 0; - trigger_index += resid; - d_triggered = false; + // 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); + } + } - for(n = 0; n < d_nconnections; n++) { - d_tags[n].clear(); - } - } + // Copy data into the buffers. + for(n = 0; n < d_nconnections; n++) { + in = (const float*)input_items[idx]; + volk_32f_convert_64f(&d_buffers[n][d_index], + &in[0], nitems); + + uint64_t nr = nitems_read(idx); + std::vector<gr::tag_t> tags; + get_tags_in_range(tags, idx, nr, nr + nitems); + for(size_t t = 0; t < tags.size(); t++) { + tags[t].offset = tags[t].offset - nr + (d_index-d_start); + } + d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + idx++; + } + d_index += nitems; - // 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[trigger_index], datasize); + // 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_buffers[n], &d_buffers[n][d_start], d_size*sizeof(double)); + } - uint64_t nr = nitems_read(idx); - std::vector<gr::tag_t> tags; - get_tags_in_range(tags, idx, nr + trigger_index, - nr + trigger_index + datasize); + // 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 TimeUpdateEvent(d_buffers, d_size, d_tags)); + } - for(size_t t = 0; t < tags.size(); t++) { - tags[t].offset = tags[t].offset - (nr + trigger_index) + d_index; - } - d_tags[idx].insert(d_tags[idx].end(), tags.begin(), tags.end()); + // We've plotting, so reset the state + _reset(); + } - idx++; - } - d_index += datasize; - trigger_index += datasize; - } - } + // If we've filled up the buffers but haven't triggered, reset. + if(d_index == d_end) { + _reset(); } - return trigger_index; + return nitems; } } /* namespace qtgui */ diff --git a/gr-qtgui/lib/time_sink_f_impl.h b/gr-qtgui/lib/time_sink_f_impl.h index 87ffe39850..7a203b742a 100644 --- a/gr-qtgui/lib/time_sink_f_impl.h +++ b/gr-qtgui/lib/time_sink_f_impl.h @@ -38,13 +38,13 @@ namespace gr { gr::thread::mutex d_mutex; - int d_size; + int d_size, d_buffer_size; double d_samp_rate; std::string d_name; int d_nconnections; - int d_index; - std::vector<double*> d_residbufs; + int d_index, d_start, d_end; + std::vector<double*> d_buffers; std::vector< std::vector<gr::tag_t> > d_tags; QWidget *d_parent; @@ -53,8 +53,6 @@ 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; @@ -66,8 +64,13 @@ namespace gr { int d_trigger_count; int d_initial_delay; // used for limiting d_trigger_delay - bool _test_trigger_slope(const float *in) const; + void _reset(); + void _npoints_resize(); + void _adjust_tags(int adj); 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 float *in) const; public: time_sink_f_impl(int size, double samp_rate, @@ -90,7 +93,7 @@ namespace gr { void set_line_width(int which, int width); void set_line_style(int which, int style); void set_line_marker(int which, int marker); - void set_nsamps(const int newsize); + 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, |