diff options
Diffstat (limited to 'gr-digital')
-rwxr-xr-x | gr-digital/examples/snr_estimators.py | 6 | ||||
-rw-r--r-- | gr-digital/include/digital_impl_mpsk_snr_est.h | 88 | ||||
-rw-r--r-- | gr-digital/lib/digital_impl_mpsk_snr_est.cc | 50 | ||||
-rw-r--r-- | gr-digital/lib/digital_mpsk_snr_est_cc.cc | 6 | ||||
-rw-r--r-- | gr-digital/lib/digital_probe_mpsk_snr_est_c.cc | 4 | ||||
-rw-r--r-- | gr-digital/swig/digital_swig.i | 2 |
6 files changed, 140 insertions, 16 deletions
diff --git a/gr-digital/examples/snr_estimators.py b/gr-digital/examples/snr_estimators.py index 0f9fbca2b..6bd9257fa 100755 --- a/gr-digital/examples/snr_estimators.py +++ b/gr-digital/examples/snr_estimators.py @@ -68,7 +68,7 @@ def snr_est_m2m4(signal): snr_rat = 2*scipy.sqrt(2*M2*M2 - M4) / (M2 - scipy.sqrt(2*M2*M2 - M4)) return 10.0*scipy.log10(snr_rat), snr_rat -def snr_est_svn(signal): +def snr_est_svr(signal): N = len(signal) ssum = 0 msum = 0 @@ -87,11 +87,11 @@ def main(): gr_estimators = {"simple": digital.SNR_EST_SIMPLE, "skew": digital.SNR_EST_SKEW, "m2m4": digital.SNR_EST_M2M4, - "svn": digital.SNR_EST_SVN} + "svr": digital.SNR_EST_SVR} py_estimators = {"simple": snr_est_simple, "skew": snr_est_skew, "m2m4": snr_est_m2m4, - "svn": snr_est_svn} + "svr": snr_est_svr} parser = OptionParser(option_class=eng_option, conflict_handler="resolve") diff --git a/gr-digital/include/digital_impl_mpsk_snr_est.h b/gr-digital/include/digital_impl_mpsk_snr_est.h index a96f3e9c1..e530782bc 100644 --- a/gr-digital/include/digital_impl_mpsk_snr_est.h +++ b/gr-digital/include/digital_impl_mpsk_snr_est.h @@ -29,7 +29,7 @@ enum snr_est_type_t { SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB) SNR_EST_SKEW, // Skewness-base est (>= 5 dB) SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB) - SNR_EST_SVN // SVN-based est (>= 0dB) + SNR_EST_SVR // SVR-based est (>= 0dB) }; /*! @@ -98,6 +98,21 @@ class DIGITAL_API digital_impl_mpsk_snr_est_m2m4 : double d_y1, d_y2; public: + /*! \brief SNR Estimator using 2nd and 4th-order moments. + * + * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th + * (M4) order moments. This estimator uses knowledge of the + * kurtosis of the signal (k_a) and noise (k_w) to make its + * estimation. We use Beaulieu's approximations here to M-PSK + * signals and AWGN channels such that k_a=1 and k_w=2. These + * approximations significantly reduce the complexity of the + * calculations (and computations) required. + * + * Reference: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ digital_impl_mpsk_snr_est_m2m4(double alpha); ~digital_impl_mpsk_snr_est_m2m4() {} @@ -106,16 +121,81 @@ class DIGITAL_API digital_impl_mpsk_snr_est_m2m4 : double snr(); }; +class DIGITAL_API digital_impl_snr_est_m2m4 : + public digital_impl_mpsk_snr_est +{ + private: + double d_y1, d_y2; + double d_ka, d_kw; + + public: + /*! \brief SNR Estimator using 2nd and 4th-order moments. + * + * An SNR estimator for M-PSK signals that uses 2nd (M2) and 4th + * (M4) order moments. This estimator uses knowledge of the + * kurtosis of the signal (k_a) and noise (k_w) to make its + * estimation. In this case, you can set your own estimations for + * k_a and k_w, the kurtosis of the signal and noise, to fit this + * estimation better to your signal and channel conditions. + * + * A word of warning: this estimator has not been fully tested or + * proved with any amount of rigor. The estimation for M4 in + * particular might be ignoring effectf of when k_a and k_w are + * different. Use this estimator with caution and a copy of the + * reference on hand. + * + * The digital_mpsk_snr_est_m2m4 assumes k_a and k_w to simplify + * the computations for M-PSK and AWGN channels. Use that estimator + * unless you have a way to guess or estimate these values here. + * + * Original paper: + * R. Matzner, "An SNR estimation algorithm for complex baseband + * signal using higher order statistics," Facta Universitatis + * (Nis), no. 6, pp. 41-52, 1993. + * + * Reference used in derivation: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ + digital_impl_snr_est_m2m4(double alpha, double ka, double kw); + ~digital_impl_snr_est_m2m4() {} + + int update(int noutput_items, + gr_vector_const_void_star &input_items); + double snr(); +}; + -class DIGITAL_API digital_impl_mpsk_snr_est_svn : +class DIGITAL_API digital_impl_mpsk_snr_est_svr : public digital_impl_mpsk_snr_est { private: double d_y1, d_y2; public: - digital_impl_mpsk_snr_est_svn(double alpha); - ~digital_impl_mpsk_snr_est_svn() {} + /*! \brief Signal-to-Variation Ratio SNR Estimator. + * + * This estimator actually comes from an SNR estimator for M-PSK + * signals in fading channels, but this implementation is + * specifically for AWGN channels. The math was simplified to + * assume a signal and noise kurtosis (k_a and k_w) for M-PSK + * signals in AWGN. These approximations significantly reduce the + * complexity of the calculations (and computations) required. + * + * Original paper: + * A. L. Brandao, L. B. Lopes, and D. C. McLernon, "In-service + * monitoring of multipath delay and cochannel interference for + * indoor mobile communication systems," Proc. IEEE + * Int. Conf. Communications, vol. 3, pp. 1458-1462, May 1994. + * + * Reference: + * D. R. Pauluzzi and N. C. Beaulieu, "A comparison of SNR + * estimation techniques for the AWGN channel," IEEE + * Trans. Communications, Vol. 48, No. 10, pp. 1681-1691, 2000. + */ + digital_impl_mpsk_snr_est_svr(double alpha); + ~digital_impl_mpsk_snr_est_svr() {} int update(int noutput_items, gr_vector_const_void_star &input_items); diff --git a/gr-digital/lib/digital_impl_mpsk_snr_est.cc b/gr-digital/lib/digital_impl_mpsk_snr_est.cc index 8adc6ffed..87ac84e04 100644 --- a/gr-digital/lib/digital_impl_mpsk_snr_est.cc +++ b/gr-digital/lib/digital_impl_mpsk_snr_est.cc @@ -187,7 +187,51 @@ digital_impl_mpsk_snr_est_m2m4::snr() /********************************************************************/ -digital_impl_mpsk_snr_est_svn::digital_impl_mpsk_snr_est_svn( +digital_impl_snr_est_m2m4::digital_impl_snr_est_m2m4( + double alpha, double ka, double kw) : + digital_impl_mpsk_snr_est(alpha) +{ + d_y1 = 0; + d_y2 = 0; + d_ka = ka; + d_kw = kw; +} + +int +digital_impl_snr_est_m2m4::update( + int noutput_items, + gr_vector_const_void_star &input_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + + for (int i = 0; i < noutput_items; i++) { + double y1 = abs(in[i])*abs(in[i]); + d_y1 = d_alpha*y1 + d_beta*d_y1; + + double y2 = abs(in[i])*abs(in[i])*abs(in[i])*abs(in[i]); + d_y2 = d_alpha*y2 + d_beta*d_y2; + } + return noutput_items; +} + +double +digital_impl_snr_est_m2m4::snr() +{ + double M2 = d_y1; + double M4 = d_y2; + double s = M2*(d_kw - 2) + + sqrt((4.0-d_ka*d_kw)*M2*M2 + M4*(d_ka+d_kw-4.0)) / + (d_ka + d_kw - 4.0); + double n = M2 - s; + + return 10.0*log10(s / n); +} + + +/********************************************************************/ + + +digital_impl_mpsk_snr_est_svr::digital_impl_mpsk_snr_est_svr( double alpha) : digital_impl_mpsk_snr_est(alpha) { @@ -196,7 +240,7 @@ digital_impl_mpsk_snr_est_svn::digital_impl_mpsk_snr_est_svn( } int -digital_impl_mpsk_snr_est_svn::update( +digital_impl_mpsk_snr_est_svr::update( int noutput_items, gr_vector_const_void_star &input_items) { @@ -215,7 +259,7 @@ digital_impl_mpsk_snr_est_svn::update( } double -digital_impl_mpsk_snr_est_svn::snr() +digital_impl_mpsk_snr_est_svr::snr() { double x = d_y1 / (d_y2 - d_y1); return 10.0*log10(2.*((x-1) + sqrt(x*(x-1)))); diff --git a/gr-digital/lib/digital_mpsk_snr_est_cc.cc b/gr-digital/lib/digital_mpsk_snr_est_cc.cc index 7d75dbb8b..b71ac0022 100644 --- a/gr-digital/lib/digital_mpsk_snr_est_cc.cc +++ b/gr-digital/lib/digital_mpsk_snr_est_cc.cc @@ -67,7 +67,7 @@ digital_mpsk_snr_est_cc::work(int noutput_items, memcpy(output_items[0], input_items[0], noutput_items * sizeof(gr_complex)); - // Update the SNR estimate registers from the current inputs + // Update the SNR estimate registers from the current return d_snr_est->update(noutput_items, input_items); } @@ -110,8 +110,8 @@ digital_mpsk_snr_est_cc::set_type(snr_est_type_t t) case(SNR_EST_M2M4): d_snr_est = new digital_impl_mpsk_snr_est_m2m4(d_alpha); break; - case(SNR_EST_SVN): - d_snr_est = new digital_impl_mpsk_snr_est_svn(d_alpha); + case(SNR_EST_SVR): + d_snr_est = new digital_impl_mpsk_snr_est_svr(d_alpha); break; default: throw std::invalid_argument("digital_mpsk_snr_est_cc: unknown type specified.\n"); diff --git a/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc b/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc index 259074e13..07f4e93de 100644 --- a/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc +++ b/gr-digital/lib/digital_probe_mpsk_snr_est_c.cc @@ -106,8 +106,8 @@ digital_probe_mpsk_snr_est_c::set_type(snr_est_type_t t) case(SNR_EST_M2M4): d_snr_est = new digital_impl_mpsk_snr_est_m2m4(d_alpha); break; - case(SNR_EST_SVN): - d_snr_est = new digital_impl_mpsk_snr_est_svn(d_alpha); + case(SNR_EST_SVR): + d_snr_est = new digital_impl_mpsk_snr_est_svr(d_alpha); break; default: throw std::invalid_argument("digital_probe_mpsk_snr_est_c: unknown type specified.\n"); diff --git a/gr-digital/swig/digital_swig.i b/gr-digital/swig/digital_swig.i index bc50fc727..962cb5d28 100644 --- a/gr-digital/swig/digital_swig.i +++ b/gr-digital/swig/digital_swig.i @@ -28,7 +28,7 @@ enum snr_est_type_t { SNR_EST_SIMPLE = 0, // Simple estimator (>= 7 dB) SNR_EST_SKEW, // Skewness-base est (>= 5 dB) SNR_EST_M2M4, // 2nd & 4th moment est (>= 1 dB) - SNR_EST_SVN // SVN-based est (>= 0dB) + SNR_EST_SVR // SVR-based est (>= 0dB) }; %include <gri_control_loop.i> |