summaryrefslogtreecommitdiff
path: root/gr-digital/lib
diff options
context:
space:
mode:
authorTom Rondeau2011-07-30 15:59:44 -0400
committerTom Rondeau2011-07-30 15:59:44 -0400
commita6fa43a9075e5123c741090622c80598a7e84c3a (patch)
tree062d89de86bbee5837d5a0d28ce8977200a87a33 /gr-digital/lib
parent6876cd276ed2e3f74161b2301f33941218fc7882 (diff)
downloadgnuradio-a6fa43a9075e5123c741090622c80598a7e84c3a.tar.gz
gnuradio-a6fa43a9075e5123c741090622c80598a7e84c3a.tar.bz2
gnuradio-a6fa43a9075e5123c741090622c80598a7e84c3a.zip
digital: updated Costas loop again. The damping factor is now set by default and is no longer part of the constructor. All variables are exposed in gets and sets, though, for any purposes.
Diffstat (limited to 'gr-digital/lib')
-rw-r--r--gr-digital/lib/digital_costas_loop_cc.cc138
-rw-r--r--gr-digital/lib/digital_costas_loop_cc.h148
2 files changed, 251 insertions, 35 deletions
diff --git a/gr-digital/lib/digital_costas_loop_cc.cc b/gr-digital/lib/digital_costas_loop_cc.cc
index 5d98bde4c..be914486f 100644
--- a/gr-digital/lib/digital_costas_loop_cc.cc
+++ b/gr-digital/lib/digital_costas_loop_cc.cc
@@ -33,28 +33,29 @@
#define M_TWOPI (2*M_PI)
digital_costas_loop_cc_sptr
-digital_make_costas_loop_cc (float damping, float nat_freq,
- int order
+digital_make_costas_loop_cc (float loop_bw, int order
) throw (std::invalid_argument)
{
- return gnuradio::get_initial_sptr(new digital_costas_loop_cc (damping,
- nat_freq,
- order));
+ return gnuradio::get_initial_sptr(new digital_costas_loop_cc
+ (loop_bw, order));
}
-digital_costas_loop_cc::digital_costas_loop_cc (float damping, float nat_freq,
- int order
+digital_costas_loop_cc::digital_costas_loop_cc (float loop_bw, int order
) throw (std::invalid_argument)
: gr_sync_block ("costas_loop_cc",
gr_make_io_signature (1, 1, sizeof (gr_complex)),
gr_make_io_signature2 (1, 2, sizeof (gr_complex), sizeof(float))),
- d_max_freq(1.0), d_min_freq(-1.0), d_phase(0), d_freq(0.0),
- d_nat_freq(nat_freq), d_damping(damping),
+ d_max_freq(1.0), d_min_freq(-1.0),
+ d_loop_bw(loop_bw),
d_order(order), d_phase_detector(NULL)
{
- // initialize gains from the natural freq and damping factors
- update_gains();
+ // Set the damping factor for a critically damped system
+ d_damping = sqrtf(2.0f)/2.0f;
+
+ // Set the bandwidth, which will then call update_gains()
+ set_loop_bandwidth(loop_bw);
+ // Set up the phase detector to use based on the constellation order
switch(d_order) {
case 2:
d_phase_detector = &digital_costas_loop_cc::phase_detector_2;
@@ -72,6 +73,10 @@ digital_costas_loop_cc::digital_costas_loop_cc (float damping, float nat_freq,
throw std::invalid_argument("order must be 2, 4, or 8");
break;
}
+
+ // Initialize loop values
+ d_freq = 0;
+ d_phase = 0;
}
float
@@ -115,25 +120,124 @@ digital_costas_loop_cc::phase_detector_2(gr_complex sample) const
return (sample.real()*sample.imag());
}
+/*******************************************************************
+ SET FUNCTIONS
+*******************************************************************/
+
void
-digital_costas_loop_cc::set_natural_freq(float w)
+digital_costas_loop_cc::set_loop_bandwidth(float bw)
{
- d_nat_freq = w;
+ if(bw < 0) {
+ throw std::out_of_range ("digital_costas_loop_cc: invalid bandwidth. Must be >= 0.");
+ }
+
+ d_loop_bw = bw;
update_gains();
}
void
-digital_costas_loop_cc::set_damping_factor(float eta)
+digital_costas_loop_cc::set_damping_factor(float df)
{
- d_damping = eta;
+ if(df < 0 || df > 1.0) {
+ throw std::out_of_range ("digital_costas_loop_cc: invalid damping factor. Must be in [0,1].");
+ }
+
+ d_damping = df;
update_gains();
}
void
+digital_costas_loop_cc::set_alpha(float alpha)
+{
+ if(alpha < 0 || alpha > 1.0) {
+ throw std::out_of_range ("digital_costas_loop_cc: invalid alpha. Must be in [0,1].");
+ }
+ d_alpha = alpha;
+}
+
+void
+digital_costas_loop_cc::set_beta(float beta)
+{
+ if(beta < 0 || beta > 1.0) {
+ throw std::out_of_range ("digital_costas_loop_cc: invalid beta. Must be in [0,1].");
+ }
+ d_beta = beta;
+}
+
+void
+digital_costas_loop_cc::set_frequency(float freq)
+{
+ if(freq > d_max_freq)
+ d_freq = d_min_freq;
+ else if(freq < d_min_freq)
+ d_freq = d_max_freq;
+ else
+ d_freq = freq;
+}
+
+void
+digital_costas_loop_cc::set_phase(float phase)
+{
+ d_phase = phase;
+ while(d_phase>M_TWOPI)
+ d_phase -= M_TWOPI;
+ while(d_phase<-M_TWOPI)
+ d_phase += M_TWOPI;
+}
+
+
+/*******************************************************************
+ GET FUNCTIONS
+*******************************************************************/
+
+
+float
+digital_costas_loop_cc::get_loop_bandwidth() const
+{
+ return d_loop_bw;
+}
+
+float
+digital_costas_loop_cc::get_damping_factor() const
+{
+ return d_damping;
+}
+
+float
+digital_costas_loop_cc::get_alpha() const
+{
+ return d_alpha;
+}
+
+float
+digital_costas_loop_cc::get_beta() const
+{
+ return d_beta;
+}
+
+float
+digital_costas_loop_cc::get_frequency() const
+{
+ return d_freq;
+}
+
+float
+digital_costas_loop_cc::get_phase() const
+{
+ return d_phase;
+}
+
+
+/*******************************************************************
+*******************************************************************/
+
+
+void
digital_costas_loop_cc::update_gains()
{
- d_beta = d_nat_freq*d_nat_freq;
- d_alpha = 2*d_damping*d_nat_freq;
+ float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw);
+ d_alpha = (4*d_damping*d_loop_bw) / denom;
+ d_beta = (4*d_loop_bw*d_loop_bw) / denom;
}
int
diff --git a/gr-digital/lib/digital_costas_loop_cc.h b/gr-digital/lib/digital_costas_loop_cc.h
index 9c112d328..530a2e2a3 100644
--- a/gr-digital/lib/digital_costas_loop_cc.h
+++ b/gr-digital/lib/digital_costas_loop_cc.h
@@ -58,8 +58,7 @@ typedef boost::shared_ptr<digital_costas_loop_cc> digital_costas_loop_cc_sptr;
digital_costas_loop_cc_sptr
-digital_make_costas_loop_cc (float damping, float nat_freq,
- int order
+digital_make_costas_loop_cc (float loop_bw, int order
) throw (std::invalid_argument);
@@ -76,19 +75,24 @@ digital_make_costas_loop_cc (float damping, float nat_freq,
class digital_costas_loop_cc : public gr_sync_block
{
friend digital_costas_loop_cc_sptr
- digital_make_costas_loop_cc (float damping, float nat_freq,
- int order
+ digital_make_costas_loop_cc (float loop_bw, int order
) throw (std::invalid_argument);
- float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq;
- float d_nat_freq, d_damping;
+ float d_max_freq;
+ float d_min_freq;
int d_order;
- digital_costas_loop_cc (float damping, float nat_freq,
- int order
+ float d_loop_bw;
+ float d_damping;
+ float d_alpha;
+ float d_beta;
+
+ float d_phase;
+ float d_freq;
+
+ digital_costas_loop_cc (float loop_bw, int order
) throw (std::invalid_argument);
-
/*! \brief update the system gains from omega and eta
*
* This function updates the system gains based on the natural
@@ -124,18 +128,126 @@ class digital_costas_loop_cc : public gr_sync_block
public:
- void set_natural_freq(float w);
- void set_damping_factor(float eta);
+ /*******************************************************************
+ SET FUNCTIONS
+ *******************************************************************/
+
+ /*!
+ * \brief Set the loop bandwidth
+ *
+ * Set the loop filter's bandwidth to \p bw. This should be between
+ * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive
+ * number.
+ *
+ * When a new damping factor is set, the gains, alpha and beta, of the loop
+ * are recalculated by a call to update_gains().
+ *
+ * \param bw (float) new bandwidth
+ *
+ */
+ void set_loop_bandwidth(float bw);
- /*! \brief get the first order gain
- *
+ /*!
+ * \brief Set the loop damping factor
+ *
+ * Set the loop filter's damping factor to \p df. The damping factor
+ * should be sqrt(2)/2.0 for critically damped systems.
+ * Set it to anything else only if you know what you are doing. It must
+ * be a number between 0 and 1.
+ *
+ * When a new damping factor is set, the gains, alpha and beta, of the loop
+ * are recalculated by a call to update_gains().
+ *
+ * \param df (float) new damping factor
+ *
*/
- float alpha() const { return d_alpha; }
-
- /*! \brief get the second order gain
- *
+ void set_damping_factor(float df);
+
+ /*!
+ * \brief Set the loop gain alpha
+ *
+ * Set's the loop filter's alpha gain parameter.
+ *
+ * This value should really only be set by adjusting the loop bandwidth
+ * and damping factor.
+ *
+ * \param alpha (float) new alpha gain
+ *
+ */
+ void set_alpha(float alpha);
+
+ /*!
+ * \brief Set the loop gain beta
+ *
+ * Set's the loop filter's beta gain parameter.
+ *
+ * This value should really only be set by adjusting the loop bandwidth
+ * and damping factor.
+ *
+ * \param beta (float) new beta gain
+ *
*/
- float beta() const { return d_beta; }
+ void set_beta(float beta);
+
+ /*!
+ * \brief Set the Costas loop's frequency.
+ *
+ * Set's the Costas Loop's frequency. While this is normally updated by the
+ * inner loop of the algorithm, it could be useful to manually initialize,
+ * set, or reset this under certain circumstances.
+ *
+ * \param freq (float) new frequency
+ *
+ */
+ void set_frequency(float freq);
+
+ /*!
+ * \brief Set the Costas loop's phase.
+ *
+ * Set's the Costas Loop's phase. While this is normally updated by the
+ * inner loop of the algorithm, it could be useful to manually initialize,
+ * set, or reset this under certain circumstances.
+ *
+ * \param phase (float) new phase
+ *
+ */
+ void set_phase(float phase);
+
+
+ /*******************************************************************
+ GET FUNCTIONS
+ *******************************************************************/
+
+ /*!
+ * \brief Returns the loop bandwidth
+ */
+ float get_loop_bandwidth() const;
+
+ /*!
+ * \brief Returns the loop damping factor
+ */
+ float get_damping_factor() const;
+
+ /*!
+ * \brief Returns the loop gain alpha
+ */
+ float get_alpha() const;
+
+ /*!
+ * \brief Returns the loop gain beta
+ */
+ float get_beta() const;
+
+ /*!
+ * \brief Get the Costas loop's frequency estimate
+ */
+ float get_frequency() const;
+
+ /*!
+ * \brief Get the Costas loop's phase estimate
+ */
+ float get_phase() const;
+
int work (int noutput_items,
gr_vector_const_void_star &input_items,