GNU Radio 3.7.0 C++ API
agc2.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2006,2012 Free Software Foundation, Inc.
00004  *
00005  * This file is part of GNU Radio
00006  *
00007  * GNU Radio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 3, or (at your option)
00010  * any later version.
00011  *
00012  * GNU Radio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with GNU Radio; see the file COPYING.  If not, write to
00019  * the Free Software Foundation, Inc., 51 Franklin Street,
00020  * Boston, MA 02110-1301, USA.
00021  */
00022 
00023 #ifndef INCLUDED_ANALOG_AGC2_H
00024 #define INCLUDED_ANALOG_AGC2_H
00025 
00026 #include <gnuradio/analog/api.h>
00027 #include <gnuradio/gr_complex.h>
00028 #include <math.h>
00029 
00030 namespace gr {
00031   namespace analog {
00032     namespace kernel {
00033 
00034       /*!
00035        * \brief high performance Automatic Gain Control class
00036        * \ingroup level_controllers_blk
00037        *
00038        * \details
00039        * For Power the absolute value of the complex number is used.
00040        */
00041       class ANALOG_API agc2_cc
00042       {
00043       public:
00044         /*!
00045          * Construct a comple value AGC loop implementation object.
00046          *
00047          * \param attack_rate the update rate of the loop when in attack mode.
00048          * \param decay_rate the update rate of the loop when in decay mode.
00049          * \param reference reference value to adjust signal power to.
00050          * \param gain initial gain value.
00051          * \param max_gain maximum gain value (0 for unlimited).
00052          */
00053         agc2_cc(float attack_rate = 1e-1, float decay_rate = 1e-2,
00054                 float reference = 1.0,
00055                 float gain = 1.0, float max_gain = 0.0)
00056           : _attack_rate(attack_rate), _decay_rate(decay_rate),
00057           _reference(reference),
00058           _gain(gain), _max_gain(max_gain) {};
00059 
00060         float decay_rate() const  { return _decay_rate; }
00061         float attack_rate() const { return _attack_rate; }
00062         float reference() const   { return _reference; }
00063         float gain() const        { return _gain;  }
00064         float max_gain() const     { return _max_gain; }
00065 
00066         void set_decay_rate(float rate) { _decay_rate = rate; }
00067         void set_attack_rate(float rate) { _attack_rate = rate; }
00068         void set_reference(float reference) { _reference = reference; }
00069         void set_gain(float gain) { _gain = gain; }
00070         void set_max_gain(float max_gain) { _max_gain = max_gain; }
00071 
00072         gr_complex scale(gr_complex input)
00073         {
00074           gr_complex output = input * _gain;
00075 
00076           float tmp = -_reference + sqrt(output.real()*output.real() +
00077                                          output.imag()*output.imag());
00078           float rate = _decay_rate;
00079           if((tmp) > _gain) {
00080             rate = _attack_rate;
00081           }
00082           _gain -= tmp*rate;
00083 
00084           // Not sure about this; will blow up if _gain < 0 (happens
00085           // when rates are too high), but is this the solution?
00086           if(_gain < 0.0)
00087             _gain = 10e-5;
00088 
00089           if(_max_gain > 0.0 && _gain > _max_gain) {
00090             _gain = _max_gain;
00091           }
00092           return output;
00093         }
00094 
00095         void scaleN(gr_complex output[], const gr_complex input[], unsigned n)
00096         {
00097           for(unsigned i = 0; i < n; i++)
00098             output[i] = scale (input[i]);
00099         }
00100 
00101       protected:
00102         float _attack_rate;     // attack rate for fast changing signals
00103         float _decay_rate;      // decay rate for slow changing signals
00104         float _reference;       // reference value
00105         float _gain;            // current gain
00106         float _max_gain;        // max allowable gain
00107       };
00108 
00109 
00110       class ANALOG_API agc2_ff
00111       {
00112       public:
00113         /*!
00114          * Construct a floating point value AGC loop implementation object.
00115          *
00116          * \param attack_rate the update rate of the loop when in attack mode.
00117          * \param decay_rate the update rate of the loop when in decay mode.
00118          * \param reference reference value to adjust signal power to.
00119          * \param gain initial gain value.
00120          * \param max_gain maximum gain value (0 for unlimited).
00121          */
00122         agc2_ff(float attack_rate = 1e-1, float decay_rate = 1e-2,
00123                 float reference = 1.0,
00124                 float gain = 1.0, float max_gain = 0.0)
00125           : _attack_rate(attack_rate), _decay_rate(decay_rate),
00126           _reference(reference),
00127           _gain(gain), _max_gain(max_gain) {};
00128 
00129         float attack_rate() const { return _attack_rate; }
00130         float decay_rate() const  { return _decay_rate; }
00131         float reference() const   { return _reference; }
00132         float gain() const        { return _gain;  }
00133         float max_gain() const    { return _max_gain; }
00134 
00135         void set_attack_rate(float rate) { _attack_rate = rate; }
00136         void set_decay_rate(float rate) { _decay_rate = rate; }
00137         void set_reference(float reference) { _reference = reference; }
00138         void set_gain(float gain) { _gain = gain; }
00139         void set_max_gain(float max_gain) { _max_gain = max_gain; }
00140 
00141         float scale(float input)
00142         {
00143           float output = input * _gain;
00144 
00145           float tmp = (fabsf(output)) - _reference;
00146           float rate = _decay_rate;
00147           if(fabsf(tmp) > _gain) {
00148             rate = _attack_rate;
00149           }
00150           _gain -= tmp*rate;
00151 
00152           // Not sure about this
00153           if(_gain < 0.0)
00154             _gain = 10e-5;
00155 
00156           if(_max_gain > 0.0 && _gain > _max_gain) {
00157             _gain = _max_gain;
00158           }
00159           return output;
00160         }
00161 
00162         void scaleN(float output[], const float input[], unsigned n)
00163         {
00164           for(unsigned i = 0; i < n; i++)
00165             output[i] = scale (input[i]);
00166         }
00167 
00168       protected:
00169         float _attack_rate;     // attack_rate for fast changing signals
00170         float _decay_rate;      // decay rate for slow changing signals
00171         float _reference;       // reference value
00172         float _gain;            // current gain
00173         float _max_gain;        // maximum gain
00174       };
00175       
00176     } /* namespace kernel */
00177   } /* namespace analog */
00178 } /* namespace gr */
00179 
00180 #endif /* INCLUDED_ANALOG_AGC2_H */