diff options
20 files changed, 590 insertions, 231 deletions
diff --git a/docs/doxygen/other/metadata.dox b/docs/doxygen/other/metadata.dox index d64f404e96..b58d2a6aee 100644 --- a/docs/doxygen/other/metadata.dox +++ b/docs/doxygen/other/metadata.dox @@ -14,9 +14,8 @@ Metadata files have extra information in the form of headers that carry metadata about the samples in the file. Raw, binary files carry no extra information and must be handled delicately. Any changes in -the system state such as sample rate or if a receiver's frequency are -not conveyed with the data in the file itself. Header of metadata -solve this problem. +the system state such as a receiver's sample rate or frequency are +not conveyed with the data in the file itself. Headers solve this problem. We write metadata files using gr::blocks::file_meta_sink and read metadata files using gr::blocks::file_meta_source. @@ -35,14 +34,14 @@ information. - version: (char) version number (usually set to METADATA_VERSION) - rx_rate: (double) Stream's sample rate - rx_time: (pmt::pmt_t pair - (uint64_t, double)) Time stamp (format from UHD) -- size: (int) item size in bytes - reflects vector length if any. +- size: (int) item size in bytes - reflects vector length if any - type: (int) data type (enum below) - cplx: (bool) true if data is complex - strt: (uint64_t) start of data relative to current header - bytes: (uint64_t) size of following data segment in bytes An optional extra section of the header stores information in any -received tags. The two main tags associated with tags are: +received tags. The two main tags associated with headers are: - rx_rate: the sample rate of the stream. - rx_time: the time stamp of the first item in the segment. @@ -51,15 +50,15 @@ These tags were inspired by the UHD tag format. The header gives enough information to process and handle the data. One cautionary note, though, is that the data type should never -change within a file. There should be very little need for this, but -more importantly. GNU Radio blocks can only set the data type of their +change within a file. There should be very little need for this, because +GNU Radio blocks can only set the data type of their IO signatures in the constructor, so changes in the data type afterward will not be recognized. -We also have an extra header segment that is option. This can be +We also have an extra header segment that is optional. This can be loaded up at the beginning by the user specifying some extra metadata that should be transmitted along with the data. It also grows whenever -it sees a stream tag, so the dictionary will contain and key:value +it sees a stream tag, so the dictionary will contain any key:value pairs out of tags from the flowgraph. @@ -114,7 +113,7 @@ Metadata files are created using gr::blocks::file_meta_sink. The default behavior is to create a single file with inline headers as metadata. An option can be set to switch to detached header mode. -Metadata file are read into a flowgraph using +Metadata files are read into a flowgraph using gr::blocks::file_meta_source. This source reads a metadata file, inline by default with a settable option to use detached headers. The data from the segments is converted into a standard streaming @@ -132,7 +131,7 @@ dictionary. Headers are created by building a PMT dictionary serialized into a string to be written to file. The header is always the same length that is predetermined by the version of the header (this must be known already). The header will then indicate if there -is an extra data to be extracted as a separate serialized dictionary. +is extra data to be extracted as a separate serialized dictionary. To work with the PMTs for creating and extracting header information, we use PMT operators. For example, we create a simplified version of @@ -261,7 +260,7 @@ data type of the PMT value. The key is always a PMT symbol, but the value can be any other PMT type. There are PMT functions that allow us to query the PMT to test if it is a particular type. We also have the ability to do pmt::print on any PMT object to print it to -screen. Before converting from a PMT to it's natural data type, it is +screen. Before converting from a PMT to its natural data type, it is necessary to know the data type. @@ -327,7 +326,7 @@ vectors of data. The following shows a simple way of creating extra metadata for a metadata file. This example is just showing how we can insert a date -into the metadata to keep track of later. The date in this case is +into the metadata to keep track of it later. The date in this case is encoded as a vector of uint16 with [day, month, year]. \code diff --git a/docs/doxygen/other/operating_fg.dox b/docs/doxygen/other/operating_fg.dox index c2c66cccd9..62cc56fd4e 100644 --- a/docs/doxygen/other/operating_fg.dox +++ b/docs/doxygen/other/operating_fg.dox @@ -22,7 +22,7 @@ between. A program must at least create a GNU Radio 'top_block', which represents the top-most structure of the flowgraph. The top blocks provide the overall control and hold methods such as 'start,' 'stop,' -and 'wait.' +and 'wait'. The general construction of a GNU Radio application is to create a gr_top_block, instantiate the blocks, connect the blocks together, and @@ -67,7 +67,7 @@ By default, GNU Radio runs a scheduler that attempts to optimize throughput. Using a dynamic scheduler, blocks in a flowgraph pass chunks of items from sources to sinks. The sizes of these chunks will vary depending on the speed of processing. For each block, the number -of items is can process is dependent on how much space it has in its +of items it can process is dependent on how much space it has in its output buffer(s) and how many items are available on the input buffer(s). @@ -153,8 +153,8 @@ latency. Limiting the size of the buffer may decrease performance. 4. The real buffer size is actually based on a minimum granularity of the system. Typically, this is a page size, which is typically 4096 bytes. This means that any buffer size that is specified with this -command will get rounded up to the nearest granularity (e.g., page) -size. When calling max_output_buffer(port) after the flowgraph is +command will get rounded up to the nearest granularity (e.g., page size). +When calling max_output_buffer(port) after the flowgraph is started, you will get how many items were actually allocated in the buffer, which may be different than what was initially specified. diff --git a/docs/doxygen/other/pmt.dox b/docs/doxygen/other/pmt.dox index 932f6c0a83..1bc6cbecd4 100644 --- a/docs/doxygen/other/pmt.dox +++ b/docs/doxygen/other/pmt.dox @@ -55,7 +55,7 @@ std::cout << P2 << std::endl; std::cout << pmt::is_complex(P2) << std::endl; \endcode -Two things stand out in both Python and C++: First we can simply print +Two things stand out in both Python and C++. First, we can simply print the contents of a PMT. How is this possible? Well, the PMTs have in-built capability to cast their value to a string (this is not possible with all types, though). Second, PMTs must obviously know @@ -85,7 +85,7 @@ The pmt::intern is another way of saying pmt::string_to_symbol. In Python, we can make use of the dynamic typing, and there's actually a helper function to do these conversions (C++ also has a helper -function for converting to PMTs called pmt::mp(), but its less +function for converting to PMTs called pmt::mp(), but it's less powerful, and not quite as useful, because types are always strictly known in C++): @@ -283,7 +283,7 @@ if(pmt::is_double(pmt_a)) \section pmt_dict Dictionaries -PMT dictionaries and lists of key:value pairs. They have a +PMT dictionaries are lists of key:value pairs. They have a well-defined interface for creating, adding, removing, and accessing items in the dictionary. Note that every operation that changes the dictionary both takes a PMT dictionary as an argument and returns a diff --git a/docs/exploring-gnuradio/exploring_gnuradio.dox b/docs/exploring-gnuradio/exploring_gnuradio.dox index 78dcfdf3cc..d762db443b 100644 --- a/docs/exploring-gnuradio/exploring_gnuradio.dox +++ b/docs/exploring-gnuradio/exploring_gnuradio.dox @@ -43,7 +43,7 @@ We next take the three blocks we've built and connect together the flowgraph. The flowgraph connects sources to sinks through other signal processing blocks. Here, we are directly connecting two sources to a single sink. The next example uses more complex flowgraphs to -farther explore these concepts. The two lines containing the +further explore these concepts. The two lines containing the "tb.connect" statements are where the connections are made. The flowgraph will look like: @@ -69,7 +69,7 @@ is implied. Otherwise, we could write this as "tb.connect((src0, 0), When we are done connecting the blocks, we have a flowgraph in the object "tb". While it's connected, the sources are not generating any -samples. We have to start the flowgraph running. In the main section, +samples. We have to start running the flowgraph. In the main section, we return the top_block object and then call the "start" function on it. This is a non-blocking call that launches the flowgraph's main thread, which initiates the sources to start sending samples through @@ -97,15 +97,15 @@ outputting the original signal to the audio system as well as viewing it in time and frequency at different stages. The intent of this example is to generate a frequency-modulated dial -tone signal and save itto a file. While saving it to a file, we only -want to generate a signal large enough to make use of but it doesn't +tone signal and save it to a file. While saving it to a file, we only +want to generate a signal large enough to make use of it, but it doesn't have to be too large. So we put a gr::blocks::head block that limits the number of samples into the file sink. Once this block has seen N number of samples, it will stop the flowgraph. Meanwhile, we use a gr::blocks::skiphead block to ignore the first M samples, which helps us avoid the transients and group delay of the filters in the system. -We run this either using the menu "Build->Execute" or using the gears +We run this either using the menu "Build->Execute" or using the play button on the toolbar. It will run for a short amount of time and stop once the head has seen the items set in the "nitems" parameter. The result is a file "dummy.dat" that contains the complex FM samples. @@ -129,7 +129,7 @@ any rate as well as filter the signal to the audio rate we want. The output of this block is filtered to a 15 kHz bandwidth at a sample rate of 44.1 ksps, which is ready for the gr::audio::sink block. -Both the GRC and Python files can be explored farther to better +Both the GRC and Python files can be explored further to better understand the operations of the blocks. -*/
\ No newline at end of file +*/ diff --git a/gnuradio-runtime/include/gnuradio/block_gateway.h b/gnuradio-runtime/include/gnuradio/block_gateway.h index 060e525358..bb0c26f8f2 100644 --- a/gnuradio-runtime/include/gnuradio/block_gateway.h +++ b/gnuradio-runtime/include/gnuradio/block_gateway.h @@ -41,6 +41,11 @@ namespace gr { GR_BLOCK_GW_WORK_INTERP, }; + //! Magic return values from general_work, \ref gr::block::WORK_CALLED_PRODUCE + enum block_gw_work_return_type{ + WORK_CALLED_PRODUCE = -2, + WORK_DONE = -1 + }; enum tag_propagation_policy_t { TPP_DONT = 0, TPP_ALL_TO_ALL = 1, diff --git a/gr-blocks/python/blocks/qa_block_gateway.py b/gr-blocks/python/blocks/qa_block_gateway.py index d4794179bd..23036eec57 100644 --- a/gr-blocks/python/blocks/qa_block_gateway.py +++ b/gr-blocks/python/blocks/qa_block_gateway.py @@ -27,6 +27,19 @@ import pmt from gnuradio import gr, gr_unittest, blocks + +class non_sync_block(gr.basic_block): + def __init__(self): + gr.basic_block.__init__(self, + name="non_sync_block", + in_sig=[numpy.float32], + out_sig=[numpy.float32, numpy.float32]) + def general_work(self, input_items, output_items): + self.consume(0, len(input_items[0])) + self.produce(0,2) + self.produce(1,1) + return gr.WORK_CALLED_PRODUCE + class add_2_f32_1_f32(gr.sync_block): def __init__(self): gr.sync_block.__init__( @@ -277,5 +290,17 @@ class test_block_gateway(gr_unittest.TestCase): tb.run() self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + def test_non_sync_block(self): + tb = gr.top_block () + src = blocks.vector_source_f(range(1000000)) + sinks = [blocks.vector_sink_f(), blocks.vector_sink_f()] + dut = non_sync_block() + tb.connect(src, dut) + tb.connect((dut,0), sinks[0]) + tb.connect((dut,1), sinks[1]) + tb.run () + self.assertEqual(len(sinks[0].data()), 2*len(sinks[1].data())) + + if __name__ == '__main__': gr_unittest.run(test_block_gateway, "test_block_gateway.xml") diff --git a/gr-digital/examples/demod/symbol_sync_test_complex.grc b/gr-digital/examples/demod/symbol_sync_test_complex.grc index 1b7ac50f8d..cd0ca99e23 100644 --- a/gr-digital/examples/demod/symbol_sync_test_complex.grc +++ b/gr-digital/examples/demod/symbol_sync_test_complex.grc @@ -239,7 +239,7 @@ </param> <param> <key>_coordinate</key> - <value>(2304, 572)</value> + <value>(2288, 588)</value> </param> <param> <key>_rotation</key> @@ -247,11 +247,11 @@ </param> <param> <key>id</key> - <value>gain_mu</value> + <value>integral_gain</value> </param> <param> <key>value</key> - <value>2.0*math.exp(-zeta*omega_n_norm)*math.sinh(zeta*omega_n_norm)</value> + <value>(2.0-proportional_gain-2.0*math.exp(-zeta*omega_n_norm)*(math.cosh(omega_d_norm) if zeta > 1.0 else math.cos(omega_d_norm)))/ted_gain</value> </param> </block> <block> @@ -262,7 +262,7 @@ </param> <param> <key>value</key> - <value>"%8.6f" % gain_mu</value> + <value>"%8.6f" % integral_gain</value> </param> <param> <key>_enabled</key> @@ -274,77 +274,7 @@ </param> <param> <key>_coordinate</key> - <value>(2808, 572)</value> - </param> - <param> - <key>gui_hint</key> - <value>1,2,1,1</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - <param> - <key>id</key> - <value>gain_mu_label</value> - </param> - <param> - <key>label</key> - <value>Gain Mu</value> - </param> - <param> - <key>type</key> - <value>string</value> - </param> - </block> - <block> - <key>variable</key> - <param> - <key>comment</key> - <value></value> - </param> - <param> - <key>_enabled</key> - <value>1</value> - </param> - <param> - <key>_coordinate</key> - <value>(2304, 636)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - <param> - <key>id</key> - <value>gain_omega</value> - </param> - <param> - <key>value</key> - <value>2.0-gain_mu-2.0*math.exp(-zeta*omega_n_norm)*(math.cosh(omega_d_norm) if zeta > 1.0 else math.cos(omega_d_norm))</value> - </param> - </block> - <block> - <key>variable_qtgui_label</key> - <param> - <key>comment</key> - <value></value> - </param> - <param> - <key>value</key> - <value>"%8.6f" % gain_omega</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>formatter</key> - <value>None</value> - </param> - <param> - <key>_coordinate</key> - <value>(2640, 572)</value> + <value>(2760, 484)</value> </param> <param> <key>gui_hint</key> @@ -356,11 +286,11 @@ </param> <param> <key>id</key> - <value>gain_omega_label</value> + <value>integral_gain_label</value> </param> <param> <key>label</key> - <value>Gain Omega</value> + <value>Integral Gain</value> </param> <param> <key>type</key> @@ -379,7 +309,7 @@ </param> <param> <key>_coordinate</key> - <value>(2304, 508)</value> + <value>(2288, 460)</value> </param> <param> <key>_rotation</key> @@ -402,7 +332,7 @@ </param> <param> <key>value</key> - <value>0.54</value> + <value>0.25</value> </param> <param> <key>_enabled</key> @@ -531,6 +461,76 @@ </param> <param> <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(2288, 524)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>proportional_gain</value> + </param> + <param> + <key>value</key> + <value>2.0/ted_gain*math.exp(-zeta*omega_n_norm)*math.sinh(zeta*omega_n_norm)</value> + </param> + </block> + <block> + <key>variable_qtgui_label</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>"%8.6f" % proportional_gain</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(2760, 564)</value> + </param> + <param> + <key>gui_hint</key> + <value>1,2,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>proportional_gain_label</value> + </param> + <param> + <key>label</key> + <value>Proportional Gain</value> + </param> + <param> + <key>type</key> + <value>string</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> @@ -558,7 +558,70 @@ </param> <param> <key>value</key> - <value>1.0/math.sqrt(2.0)*0+1.3</value> + <value>1.0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(2608, 568)</value> + </param> + <param> + <key>gui_hint</key> + <value>1,0,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>ted_gain</value> + </param> + <param> + <key>label</key> + <value>Expected TED Gain</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>0.1</value> + </param> + <param> + <key>step</key> + <value>0.1</value> + </param> + <param> + <key>stop</key> + <value>5.0</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1.0</value> </param> <param> <key>_enabled</key> @@ -837,7 +900,7 @@ </param> <param> <key>_coordinate</key> - <value>(2752, 320)</value> + <value>(2752, 328)</value> </param> <param> <key>_rotation</key> @@ -1707,12 +1770,16 @@ <value>True</value> </param> <param> + <key>ted_gain</key> + <value>1.0</value> + </param> + <param> <key>nfilters</key> <value>128</value> </param> <param> <key>_coordinate</key> - <value>(2376, 296)</value> + <value>(2376, 292)</value> </param> <param> <key>_rotation</key> diff --git a/gr-digital/examples/demod/symbol_sync_test_float.grc b/gr-digital/examples/demod/symbol_sync_test_float.grc index f81111b957..5507cbf848 100644 --- a/gr-digital/examples/demod/symbol_sync_test_float.grc +++ b/gr-digital/examples/demod/symbol_sync_test_float.grc @@ -239,76 +239,6 @@ </param> <param> <key>_coordinate</key> - <value>(1800, 484)</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - <param> - <key>id</key> - <value>gain_mu</value> - </param> - <param> - <key>value</key> - <value>2.0*math.exp(-zeta*omega_n_norm)*math.sinh(zeta*omega_n_norm)</value> - </param> - </block> - <block> - <key>variable_qtgui_label</key> - <param> - <key>comment</key> - <value></value> - </param> - <param> - <key>value</key> - <value>"%8.6f" % gain_mu</value> - </param> - <param> - <key>_enabled</key> - <value>True</value> - </param> - <param> - <key>formatter</key> - <value>None</value> - </param> - <param> - <key>_coordinate</key> - <value>(2168, 500)</value> - </param> - <param> - <key>gui_hint</key> - <value>1,2,1,1</value> - </param> - <param> - <key>_rotation</key> - <value>0</value> - </param> - <param> - <key>id</key> - <value>gain_mu_label</value> - </param> - <param> - <key>label</key> - <value>Gain Mu</value> - </param> - <param> - <key>type</key> - <value>string</value> - </param> - </block> - <block> - <key>variable</key> - <param> - <key>comment</key> - <value></value> - </param> - <param> - <key>_enabled</key> - <value>1</value> - </param> - <param> - <key>_coordinate</key> <value>(1800, 548)</value> </param> <param> @@ -317,11 +247,11 @@ </param> <param> <key>id</key> - <value>gain_omega</value> + <value>integral_gain</value> </param> <param> <key>value</key> - <value>2.0-gain_mu-2.0*math.exp(-zeta*omega_n_norm)*(math.cosh(omega_d_norm) if zeta > 1.0 else math.cos(omega_d_norm))</value> + <value>(2.0-proportional_gain-2.0*math.exp(-zeta*omega_n_norm)*(math.cosh(omega_d_norm) if zeta > 1.0 else math.cos(omega_d_norm)))/ted_gain</value> </param> </block> <block> @@ -332,7 +262,7 @@ </param> <param> <key>value</key> - <value>"%8.6f" % gain_omega</value> + <value>"%8.6f" % integral_gain</value> </param> <param> <key>_enabled</key> @@ -344,7 +274,7 @@ </param> <param> <key>_coordinate</key> - <value>(2168, 420)</value> + <value>(2296, 420)</value> </param> <param> <key>gui_hint</key> @@ -356,11 +286,11 @@ </param> <param> <key>id</key> - <value>gain_omega_label</value> + <value>integral_gain_label</value> </param> <param> <key>label</key> - <value>Gain Omega</value> + <value>Integral Gain</value> </param> <param> <key>type</key> @@ -402,7 +332,7 @@ </param> <param> <key>value</key> - <value>0.58</value> + <value>0.07</value> </param> <param> <key>_enabled</key> @@ -531,6 +461,76 @@ </param> <param> <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(1800, 484)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>proportional_gain</value> + </param> + <param> + <key>value</key> + <value>2.0/ted_gain*math.exp(-zeta*omega_n_norm)*math.sinh(zeta*omega_n_norm)</value> + </param> + </block> + <block> + <key>variable_qtgui_label</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>"%8.6f" % proportional_gain</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>_coordinate</key> + <value>(2296, 500)</value> + </param> + <param> + <key>gui_hint</key> + <value>1,2,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>proportional_gain_label</value> + </param> + <param> + <key>label</key> + <value>Proportional Gain</value> + </param> + <param> + <key>type</key> + <value>string</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>_enabled</key> <value>True</value> </param> <param> @@ -558,7 +558,70 @@ </param> <param> <key>value</key> - <value>1.0/math.sqrt(2.0)*0+1.5</value> + <value>1.0</value> + </param> + <param> + <key>_enabled</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(2120, 536)</value> + </param> + <param> + <key>gui_hint</key> + <value>1,0,1,1</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + <param> + <key>id</key> + <value>ted_gain</value> + </param> + <param> + <key>label</key> + <value>Expected TED Gain</value> + </param> + <param> + <key>min_len</key> + <value>200</value> + </param> + <param> + <key>orient</key> + <value>Qt.Horizontal</value> + </param> + <param> + <key>start</key> + <value>0.1</value> + </param> + <param> + <key>step</key> + <value>0.1</value> + </param> + <param> + <key>stop</key> + <value>5.0</value> + </param> + <param> + <key>rangeType</key> + <value>float</value> + </param> + <param> + <key>widget</key> + <value>counter_slider</value> + </param> + </block> + <block> + <key>variable_qtgui_range</key> + <param> + <key>comment</key> + <value></value> + </param> + <param> + <key>value</key> + <value>1.0</value> </param> <param> <key>_enabled</key> @@ -1527,12 +1590,16 @@ <value>True</value> </param> <param> + <key>ted_gain</key> + <value>1.0</value> + </param> + <param> <key>nfilters</key> <value>128</value> </param> <param> <key>_coordinate</key> - <value>(1944, 280)</value> + <value>(1944, 276)</value> </param> <param> <key>_rotation</key> diff --git a/gr-digital/grc/digital_symbol_sync_xx.xml b/gr-digital/grc/digital_symbol_sync_xx.xml index 1f597ef8ce..ffd2f5daff 100644 --- a/gr-digital/grc/digital_symbol_sync_xx.xml +++ b/gr-digital/grc/digital_symbol_sync_xx.xml @@ -26,10 +26,11 @@ <category>[Core]/Synchronizers</category> <import>from gnuradio import digital</import> <import>from gnuradio import filter</import> - <make>digital.symbol_sync_$(type)($ted_type, $sps, $loop_bw, $damping, $max_dev, $osps, $constellation, $resamp_type, $nfilters, $pfb_mf_taps)</make> + <make>digital.symbol_sync_$(type)($ted_type, $sps, $loop_bw, $damping, $ted_gain, $max_dev, $osps, $constellation, $resamp_type, $nfilters, $pfb_mf_taps)</make> <callback>set_loop_bandwidth($loop_bw)</callback> <callback>set_damping_factor($damping)</callback> + <callback>set_ted_gain($ted_gain)</callback> <param> <name>I/O Type</name> @@ -112,6 +113,12 @@ <type>real</type> </param> <param> + <name>Expected TED Gain</name> + <key>ted_gain</key> + <value>1.0</value> + <type>real</type> + </param> + <param> <name>Loop Bandwidth</name> <key>loop_bw</key> <value>0.045</value> @@ -120,7 +127,7 @@ <param> <name>Damping Factor</name> <key>damping</key> - <value>1.0/math.sqrt(2.0)</value> + <value>1.0</value> <type>real</type> </param> <param> diff --git a/gr-digital/include/gnuradio/digital/symbol_sync_cc.h b/gr-digital/include/gnuradio/digital/symbol_sync_cc.h index 5e51c3cdf1..dc856ecaf6 100644 --- a/gr-digital/include/gnuradio/digital/symbol_sync_cc.h +++ b/gr-digital/include/gnuradio/digital/symbol_sync_cc.h @@ -97,6 +97,15 @@ namespace gr { * Damping = 1.0f is a critically-damped loop. * Damping > 1.0f is an over-damped loop. * + * \param ted_gain + * Expected gain of the timing error detector, given the TED in use + * and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * * \param max_deviation * Maximum absolute deviation of the average clock period estimate * from the user specified nominal clock period in samples per symbol. @@ -126,7 +135,8 @@ namespace gr { static sptr make(enum ted_type detector_type, float sps, float loop_bw, - float damping_factor = 2.0f, + float damping_factor = 1.0f, + float ted_gain = 1.0f, float max_deviation = 1.5f, int osps = 1, constellation_sptr slicer = constellation_sptr(), @@ -157,6 +167,15 @@ namespace gr { virtual float damping_factor() const = 0; /*! + * \brief Returns the user provided expected gain of the Timing Error + * Detector. + * + * \details + * See the documenation for set_ted_gain() for more details. + */ + virtual float ted_gain() const = 0; + + /*! * \brief Returns the PI filter proportional gain, alpha. * * \details @@ -224,6 +243,25 @@ namespace gr { virtual void set_damping_factor (float zeta) = 0; /*! + * \brief Set the expected gain of the Timing Error Detector. + * + * \details + * Sets the expected gain of the timing error detector, given the TED in + * use and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * When a new ted_gain is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param ted_gain expected gain of the timing error detector + */ + virtual void set_ted_gain (float ted_gain) = 0; + + /*! * \brief Set the PI filter proportional gain, alpha. * * \details diff --git a/gr-digital/include/gnuradio/digital/symbol_sync_ff.h b/gr-digital/include/gnuradio/digital/symbol_sync_ff.h index 2fdac08e2d..f551c0a96c 100644 --- a/gr-digital/include/gnuradio/digital/symbol_sync_ff.h +++ b/gr-digital/include/gnuradio/digital/symbol_sync_ff.h @@ -97,6 +97,15 @@ namespace gr { * Damping = 1.0f is a critically-damped loop. * Damping > 1.0f is an over-damped loop. * + * \param ted_gain + * Expected gain of the timing error detector, given the TED in use + * and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * * \param max_deviation * Maximum absolute deviation of the average clock period estimate * from the user specified nominal clock period in samples per symbol. @@ -126,7 +135,8 @@ namespace gr { static sptr make(enum ted_type detector_type, float sps, float loop_bw, - float damping_factor = 2.0f, + float damping_factor = 1.0f, + float ted_gain = 1.0f, float max_deviation = 1.5f, int osps = 1, constellation_sptr slicer = constellation_sptr(), @@ -157,6 +167,15 @@ namespace gr { virtual float damping_factor() const = 0; /*! + * \brief Returns the user provided expected gain of the Timing Error + * Detector. + * + * \details + * See the documenation for set_ted_gain() for more details. + */ + virtual float ted_gain() const = 0; + + /*! * \brief Returns the PI filter proportional gain, alpha. * * \details @@ -224,6 +243,25 @@ namespace gr { virtual void set_damping_factor (float zeta) = 0; /*! + * \brief Set the expected gain of the Timing Error Detector. + * + * \details + * Sets the expected gain of the timing error detector, given the TED in + * use and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * When a new ted_gain is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param ted_gain expected gain of the timing error detector + */ + virtual void set_ted_gain (float ted_gain) = 0; + + /*! * \brief Set the PI filter proportional gain, alpha. * * \details diff --git a/gr-digital/lib/clock_tracking_loop.cc b/gr-digital/lib/clock_tracking_loop.cc index d74e4b2120..51a1db9e71 100644 --- a/gr-digital/lib/clock_tracking_loop.cc +++ b/gr-digital/lib/clock_tracking_loop.cc @@ -34,7 +34,8 @@ namespace gr { clock_tracking_loop::clock_tracking_loop(float loop_bw, float max_period, float min_period, float nominal_period, - float damping) + float damping, + float ted_gain) : d_avg_period(nominal_period), d_max_avg_period(max_period), d_min_avg_period(min_period), @@ -43,6 +44,7 @@ namespace gr { d_phase(0.0f), d_zeta(damping), d_omega_n_norm(loop_bw), + d_ted_gain(ted_gain), d_alpha(0.0f), d_beta(0.0f), d_prev_avg_period(nominal_period), @@ -64,6 +66,10 @@ namespace gr { throw std::out_of_range ( "clock_tracking_loop: loop bandwidth must be greater than 0.0"); + if (d_ted_gain <= 0.0f) + throw std::out_of_range ( + "clock_tracking_loop: expected ted gain must be greater than 0.0"); + update_gains(); } @@ -74,12 +80,15 @@ namespace gr { void clock_tracking_loop::update_gains() { - float omega_n_T, omega_d_T, zeta_omega_n_T, k1, cosx_omega_d_T; + float omega_n_T, omega_d_T, zeta_omega_n_T, cosx_omega_d_T; + float k0, k1, sinh_zeta_omega_n_T; float alpha, beta; omega_n_T = d_omega_n_norm; zeta_omega_n_T = d_zeta * omega_n_T; - k1 = 2.0f * expf(-zeta_omega_n_T); + k0 = 2.0f/d_ted_gain; + k1 = expf(-zeta_omega_n_T); + sinh_zeta_omega_n_T = sinhf(zeta_omega_n_T); if (d_zeta > 1.0f) { // Over-damped (or critically-damped too) @@ -100,8 +109,8 @@ namespace gr { // cos ----------^^^ } - alpha = k1 * sinhf(zeta_omega_n_T); - beta = 2.0f - (alpha + k1 * cosx_omega_d_T); + alpha = k0 * k1 * sinh_zeta_omega_n_T; + beta = k0 * (1 - k1*(sinh_zeta_omega_n_T + cosx_omega_d_T)); set_alpha(alpha); set_beta(beta); @@ -180,6 +189,17 @@ namespace gr { } void + clock_tracking_loop::set_ted_gain(float ted_gain) + { + if (ted_gain <= 0.0f) + throw std::out_of_range ( + "clock_tracking_loop: expected ted gain must be > 0.0"); + + d_ted_gain = ted_gain; + update_gains(); + } + + void clock_tracking_loop::set_alpha(float alpha) { d_alpha = alpha; @@ -256,6 +276,12 @@ namespace gr { } float + clock_tracking_loop::get_ted_gain() const + { + return d_ted_gain; + } + + float clock_tracking_loop::get_alpha() const { return d_alpha; diff --git a/gr-digital/lib/clock_tracking_loop.h b/gr-digital/lib/clock_tracking_loop.h index 84c77e197a..1a20713c48 100644 --- a/gr-digital/lib/clock_tracking_loop.h +++ b/gr-digital/lib/clock_tracking_loop.h @@ -35,9 +35,9 @@ namespace gr { * which need a symbol clock tracking loop to determine the optimal * instant to sample a received symbol from an input sample * stream (i.e. *_clock_recovery* and *_clock_sync* blocks). - * It takes in a normalized loop bandwidth and damping factor - * as well as clock period bounds and provides the functions that - * control the update of the loop. + * It takes in an expected timing error detector gain, a normalized loop + * bandwidth and damping factor, as well as clock period bounds, and + * provides the functions that control the update of the loop. * * This control loop runs at the rate of the output clock, so * each step of the loop produces estimates about the output clock, @@ -51,9 +51,9 @@ namespace gr { * The loop's low pass filter is a Proportional-Integral (PI) filter. * The proportional and integral gains of the filter are termed alpha * and beta respectively. These gains are calculated using the input - * loop bandwidth and damping factor. If needed, the alpha and beta - * gain values can be set using their respective #set_alpha or #set_beta - * functions. + * expected timing error detector gain, loop bandwidth and damping factor. + * If needed, the alpha and beta gain values can be set using their + * respective #set_alpha or #set_beta functions. * * The class estimates the average clock period, T_avg; the instantaneous * clock period, T_inst; and the instantaneous clock phase, tau; of a @@ -70,20 +70,21 @@ namespace gr { * keeps the phase within +/-T_avg/2). * * The clock tracking loop, with its PI filter, when properly implemented, has - * a digital loop phase-transfer function, in terms of the proportional gain - * \f$\alpha\f$ and the integral gain \f$\beta\f$ as follows: + * a digital loop phase-transfer function, in terms of the timing error + * detector gain, \f$K_{ted}\f$; proportional gain, \f$\alpha\f$; and the + * integral gain, \f$\beta\f$, as follows: * * \f{align*} * H(z) &= \dfrac {\Theta_o(z)}{\Theta_i(z)} - * = (\alpha + \beta)z^{-1} \cdot + * = K_{ted}(\alpha + \beta)z^{-1} \cdot * \dfrac{ * 1 * - \dfrac{\alpha}{\alpha + \beta} z^{-1} * } * { * 1 - * - 2 \left(1 - \dfrac{\alpha + \beta}{2}\right) z^{-1} - * + (1 - \alpha) z^{-2} + * - 2 \left(1 - K_{ted}\dfrac{\alpha + \beta}{2}\right) z^{-1} + * + (1 - K_{ted}\alpha) z^{-2} * } \\ * \f} * @@ -140,23 +141,27 @@ namespace gr { * \\ * \f} * - * The PI filter gains, expressed in terms of the damping factor \f$\zeta\f$, - * the natural radian frequency \f$\omega_{n}\f$, the damped radian frequency of - * oscillation \f$\omega_{d}\f$, and the clock period \f$T\f$ are: + * The PI filter gains, expressed in terms of the damping factor, \f$\zeta\f$; + * the natural radian frequency, \f$\omega_{n}\f$; the damped radian frequency of + * oscillation, \f$\omega_{d}\f$; the timing error detector gain \f$K_{ted}\f$; + * and the clock period \f$T\f$ are: * * \f{align*} - * \alpha &= 2e^{-\zeta\omega_{n}T} \sinh(\zeta\omega_{n}T) \\ + * \alpha &= \dfrac{2}{K_{ted}}e^{-\zeta\omega_{n}T} \sinh(\zeta\omega_{n}T) \\ * \\ * \beta &= * \begin{cases} - * 2 - * -2e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) + \cos(\omega_{d}T)] & - * \text{for} \quad \zeta < 1 \quad (under \: damped)\\ - * 2 - * -2e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) + 1] & - * \text{for} \quad \zeta = 1 \quad (critically \: damped)\\ - * 2 - * -2e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) +\cosh(\omega_{d}T)] & + * \dfrac{2}{K_{ted}} \left(1 - + * e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) + \cos(\omega_{d}T)] + * \right) & + * \text{for} \quad \zeta < 1 \quad (under \: damped)\\ \\ + * \dfrac{2}{K_{ted}} \left(1 - + * e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) + 1] + * \right) & + * \text{for} \quad \zeta = 1 \quad (critically \: damped)\\ \\ + * \dfrac{2}{K_{ted}} \left(1 - + * e^{-\zeta\omega_{n}T} [\sinh(\zeta\omega_{n}T) +\cosh(\omega_{d}T)] + * \right) & * \text{for} \quad \zeta > 1 \quad (over \: damped)\\ * \end{cases} \\ * \\ @@ -179,6 +184,17 @@ namespace gr { * \pi \dfrac{f_{n}}{\left(\dfrac{F_{c}}{2}\right)} * \f} * + * In practice, the timing error detector (TED) of the symbol clock + * tracking loop is implemented with an estimator of symbol clock phase + * error, which has some gain \f$K_{ted}\f$. The gain, \f$K_{ted}\f$, is + * defined as the slope of a TED's S-curve plot at a symbol clock phase + * offset of \f$\tau = 0\f$. The S-curve shape and central slope, and + * hence the gain \f$K_{ted}\f$, depend on the TED's estimator espression, + * the input signal level, the pulse shaping filter, and the \f$E_s/N_0\f$ + * of the incomping signal. The user must determine the TED's + * S-curve by analysis or simulation of the particular situation, in order + * to determine an appropriate value for \f$K_{ted}\f$. + * * * A note on symbol clock phase vs. interpolating resampler sample phase, * since most GNURadio symbol synchronization blocks seem to have the same * implementation error: @@ -263,6 +279,13 @@ namespace gr { // omega_n_norm = omega_n*T = 2*pi*f_n*T = 2*pi*f_n_norm float d_omega_n_norm; + // Expected gain of the timing error detector in use, given the + // TED estimator expression, the expected input amplitude, the + // input pulse shape, and the expected input Es/No. (This value is the + // slope of the TED's S-curve plot at a timing offset of tau = 0, and + // must be determined by analysis and/or simulation by the user.) + float d_ted_gain; + // Proportional gain of the PI loop filter (aka gain_mu) // (aka gain_mu in some clock recovery blocks) float d_alpha; @@ -315,16 +338,27 @@ namespace gr { * Damping in the range (1.0, Inf) yields an over-damped loop. * Damping equal to 1.0 yields a crtically-damped loop. * Under-damped loops are not generally useful for clock tracking. - * This parameter defaults to 2.0, if not specified. + * This parameter defaults to 1.0, if not specified. + * + * \param ted_gain + * Expected gain of the timing error detector, given the TED in use + * and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * This parameter defaults to 1.0, if not specified. */ clock_tracking_loop(float loop_bw, float max_period, float min_period, float nominal_period = 0.0f, - float damping = 2.0f); + float damping = 1.0f, + float ted_gain = 1.0f); virtual ~clock_tracking_loop(); - /*! \brief Update the gains from the loop bandwidth and damping factor. + /*! \brief Update the gains from the ted_gain, loop bw and damping factor. * * \details * This function updates the gains based on the loop @@ -445,6 +479,25 @@ namespace gr { void set_damping_factor(float df); /*! + * \brief Set the expected gain of the Timing Error Detector. + * + * \details + * Sets the expected gain of the timing error detector, given the TED in + * use and the anticipated input amplitude, pulse shape, and Es/No. + * This value is the slope of the TED's S-curve at timing offset tau = 0. + * This value is normally computed by the user analytically or by + * simulation in a tool outside of GNURadio. + * This value must be correct for the loop filter gains to be computed + * properly from the desired input loop bandwidth and damping factor. + * + * When a new ted_gain is set, the gains, alpha and beta, + * of the loop are automatcally recalculated. + * + * \param ted_gain expected gain of the timing error detector + */ + void set_ted_gain (float ted_gain); + + /*! * \brief Set the PI filter proportional gain, alpha. * * \details @@ -621,6 +674,15 @@ namespace gr { float get_damping_factor() const; /*! + * \brief Returns the user providded expected gain of the Timing Error + * Detector. + * + * \details + * See the documenation for set_ted_gain() for more details. + */ + float get_ted_gain() const; + + /*! * \brief Returns the PI filter proportional gain, alpha. * * \details diff --git a/gr-digital/lib/symbol_sync_cc_impl.cc b/gr-digital/lib/symbol_sync_cc_impl.cc index 3df84be134..986a7e97de 100644 --- a/gr-digital/lib/symbol_sync_cc_impl.cc +++ b/gr-digital/lib/symbol_sync_cc_impl.cc @@ -38,6 +38,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -50,6 +51,7 @@ namespace gr { sps, loop_bw, damping_factor, + ted_gain, max_deviation, osps, slicer, @@ -63,6 +65,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -146,7 +149,8 @@ namespace gr { sps + max_deviation, sps - max_deviation, sps, - damping_factor); + damping_factor, + ted_gain); // Timing Error Detector d_ted->sync_reset(); diff --git a/gr-digital/lib/symbol_sync_cc_impl.h b/gr-digital/lib/symbol_sync_cc_impl.h index e0b85069d2..a146f7ed2e 100644 --- a/gr-digital/lib/symbol_sync_cc_impl.h +++ b/gr-digital/lib/symbol_sync_cc_impl.h @@ -38,6 +38,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -55,6 +56,7 @@ namespace gr { // Symbol Clock Tracking and Estimation float loop_bandwidth() const { return d_clock->get_loop_bandwidth(); } float damping_factor() const { return d_clock->get_damping_factor(); } + float ted_gain() const { return d_clock->get_ted_gain(); } float alpha() const { return d_clock->get_alpha(); } float beta() const { return d_clock->get_beta(); } @@ -64,6 +66,7 @@ namespace gr { void set_damping_factor (float zeta) { d_clock->set_damping_factor(zeta); } + void set_ted_gain (float ted_gain) { d_clock->set_ted_gain(ted_gain); } void set_alpha (float alpha) { d_clock->set_alpha(alpha); } void set_beta (float beta) { d_clock->set_beta(beta); } diff --git a/gr-digital/lib/symbol_sync_ff_impl.cc b/gr-digital/lib/symbol_sync_ff_impl.cc index 48509e4ba9..2497e52359 100644 --- a/gr-digital/lib/symbol_sync_ff_impl.cc +++ b/gr-digital/lib/symbol_sync_ff_impl.cc @@ -38,6 +38,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -50,6 +51,7 @@ namespace gr { sps, loop_bw, damping_factor, + ted_gain, max_deviation, osps, slicer, @@ -63,6 +65,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -146,7 +149,8 @@ namespace gr { sps + max_deviation, sps - max_deviation, sps, - damping_factor); + damping_factor, + ted_gain); // Timing Error Detector d_ted->sync_reset(); diff --git a/gr-digital/lib/symbol_sync_ff_impl.h b/gr-digital/lib/symbol_sync_ff_impl.h index f4bd6658b3..b0fea13929 100644 --- a/gr-digital/lib/symbol_sync_ff_impl.h +++ b/gr-digital/lib/symbol_sync_ff_impl.h @@ -38,6 +38,7 @@ namespace gr { float sps, float loop_bw, float damping_factor, + float ted_gain, float max_deviation, int osps, constellation_sptr slicer, @@ -55,6 +56,7 @@ namespace gr { // Symbol Clock Tracking and Estimation float loop_bandwidth() const { return d_clock->get_loop_bandwidth(); } float damping_factor() const { return d_clock->get_damping_factor(); } + float ted_gain() const { return d_clock->get_ted_gain(); } float alpha() const { return d_clock->get_alpha(); } float beta() const { return d_clock->get_beta(); } @@ -64,6 +66,7 @@ namespace gr { void set_damping_factor (float zeta) { d_clock->set_damping_factor(zeta); } + void set_ted_gain (float ted_gain) { d_clock->set_ted_gain(ted_gain); } void set_alpha (float alpha) { d_clock->set_alpha(alpha); } void set_beta (float beta) { d_clock->set_beta(beta); } diff --git a/grc/core/Param.py b/grc/core/Param.py index e8c81383f3..a1e4c782fb 100644 --- a/grc/core/Param.py +++ b/grc/core/Param.py @@ -54,10 +54,19 @@ class TemplateArg(str): setattr(instance, '_param', param) return instance + def __getitem__(self, item): + return str(self._param.get_opt(item)) if self._param.is_enum() else NotImplemented + def __getattr__(self, item): - param = self._param - attributes = param.options.attributes[param.get_value()] - return str(attributes.get(item)) or NotImplemented + if not self._param.is_enum(): + raise AttributeError() + try: + return str(self._param.get_opt(item)) + except KeyError: + raise AttributeError() + + def __str__(self): + return str(self._param.to_code()) def __call__(self): return self._param.get_evaluated() diff --git a/grc/gui/Application.py b/grc/gui/Application.py index b4df4d172e..458210a3f4 100644 --- a/grc/gui/Application.py +++ b/grc/gui/Application.py @@ -703,9 +703,10 @@ class Application(Gtk.Application): elif action == Actions.FLOW_GRAPH_KILL: if page.process: try: - page.process.kill() + page.term_proc() except: - print("could not kill process: %d" % page.process.pid) + print("could not terminate process: %d" % page.get_proc().pid) + elif action == Actions.PAGE_CHANGE: # pass and run the global actions pass elif action == Actions.RELOAD_BLOCKS: diff --git a/grc/scripts/freedesktop/gnuradio-grc.desktop b/grc/scripts/freedesktop/gnuradio-grc.desktop index 39beeca1b8..f065ce4568 100644 --- a/grc/scripts/freedesktop/gnuradio-grc.desktop +++ b/grc/scripts/freedesktop/gnuradio-grc.desktop @@ -1,7 +1,8 @@ [Desktop Entry] Version=1.0 Type=Application -Name=GRC +Name=GNU Radio Companion +Comment=Graphical tool for creating signal flow graphs and generating flow-graph source code Exec=gnuradio-companion %F Categories=Development; MimeType=application/gnuradio-grc; |