summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gr-digital/examples/demod/symbol_sync_test_complex.grc231
-rw-r--r--gr-digital/examples/demod/symbol_sync_test_float.grc225
-rw-r--r--gr-digital/grc/digital_symbol_sync_xx.xml11
-rw-r--r--gr-digital/include/gnuradio/digital/symbol_sync_cc.h40
-rw-r--r--gr-digital/include/gnuradio/digital/symbol_sync_ff.h40
-rw-r--r--gr-digital/lib/clock_tracking_loop.cc36
-rw-r--r--gr-digital/lib/clock_tracking_loop.h114
-rw-r--r--gr-digital/lib/symbol_sync_cc_impl.cc6
-rw-r--r--gr-digital/lib/symbol_sync_cc_impl.h3
-rw-r--r--gr-digital/lib/symbol_sync_ff_impl.cc6
-rw-r--r--gr-digital/lib/symbol_sync_ff_impl.h3
11 files changed, 517 insertions, 198 deletions
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 &gt; 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 &gt; 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 &gt; 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 &gt; 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); }