GNU Radio 3.7.1 C++ API
nco.h
Go to the documentation of this file.
00001 /* -*- c++ -*- */
00002 /*
00003  * Copyright 2002,2013 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 _GR_NCO_H_
00024 #define _GR_NCO_H_
00025 
00026 #include <gnuradio/sincos.h>
00027 #include <gnuradio/gr_complex.h>
00028 #include <vector>
00029 #include <cmath>
00030 
00031 namespace gr {
00032 
00033   /*!
00034    * \brief base class template for Numerically Controlled Oscillator (NCO)
00035    * \ingroup misc
00036    */
00037   template<class o_type, class i_type>
00038   class nco
00039   {
00040   public:
00041     nco() : phase(0), phase_inc(0) {}
00042 
00043     virtual ~nco() {}
00044 
00045     // radians
00046     void set_phase(double angle)
00047     {
00048       phase = angle;
00049     }
00050 
00051     void adjust_phase(double delta_phase)
00052     {
00053       phase += delta_phase;
00054     }
00055 
00056     // angle_rate is in radians / step
00057     void set_freq(double angle_rate)
00058     {
00059       phase_inc = angle_rate;
00060     }
00061 
00062     // angle_rate is a delta in radians / step
00063     void adjust_freq(double delta_angle_rate)
00064     {
00065       phase_inc += delta_angle_rate;
00066     }
00067 
00068     // increment current phase angle
00069     void step()
00070     {
00071       phase += phase_inc;
00072       if(fabs(phase) > M_PI) {
00073         while(phase > M_PI)
00074           phase -= 2*M_PI;
00075 
00076         while(phase < -M_PI)
00077           phase += 2*M_PI;
00078       }
00079     }
00080 
00081     void step(int n)
00082     {
00083       phase += phase_inc * n;
00084       if(fabs(phase) > M_PI){
00085         while(phase > M_PI)
00086           phase -= 2*M_PI;
00087 
00088         while(phase < -M_PI)
00089           phase += 2*M_PI;
00090       }
00091     }
00092 
00093     // units are radians / step
00094     double get_phase() const { return phase; }
00095     double get_freq() const { return phase_inc; }
00096 
00097     // compute sin and cos for current phase angle
00098     void sincos(float *sinx, float *cosx) const;
00099 
00100     // compute cos or sin for current phase angle
00101     float cos() const { return std::cos(phase); }
00102     float sin() const { return std::sin(phase); }
00103 
00104     // compute a block at a time
00105     void sin(float *output, int noutput_items, double ampl = 1.0);
00106     void cos(float *output, int noutput_items, double ampl = 1.0);
00107     void sincos(gr_complex *output, int noutput_items, double ampl = 1.0);
00108     void sin(short *output, int noutput_items, double ampl = 1.0);
00109     void cos(short *output, int noutput_items, double ampl = 1.0);
00110     void sin(int *output, int noutput_items, double ampl = 1.0);
00111     void cos(int *output, int noutput_items, double ampl = 1.0);
00112 
00113   protected:
00114     double phase;
00115     double phase_inc;
00116   };
00117 
00118   template<class o_type, class i_type>
00119   void
00120   nco<o_type,i_type>::sincos(float *sinx, float *cosx) const
00121   {
00122     gr::sincosf(phase, sinx, cosx);
00123   }
00124 
00125   template<class o_type, class i_type>
00126   void
00127   nco<o_type,i_type>::sin(float *output, int noutput_items, double ampl)
00128   {
00129     for(int i = 0; i < noutput_items; i++) {
00130       output[i] = (float)(sin () * ampl);
00131       step();
00132     }
00133   }
00134 
00135   template<class o_type, class i_type>
00136   void
00137   nco<o_type,i_type>::cos(float *output, int noutput_items, double ampl)
00138   {
00139     for(int i = 0; i < noutput_items; i++) {
00140       output[i] = (float)(cos() * ampl);
00141       step();
00142     }
00143   }
00144 
00145   template<class o_type, class i_type>
00146   void
00147   nco<o_type,i_type>::sin(short *output, int noutput_items, double ampl)
00148   {
00149     for(int i = 0; i < noutput_items; i++) {
00150       output[i] = (short)(sin() * ampl);
00151       step();
00152     }
00153   }
00154 
00155   template<class o_type, class i_type>
00156   void
00157   nco<o_type,i_type>::cos(short *output, int noutput_items, double ampl)
00158   {
00159     for(int i = 0; i < noutput_items; i++) {
00160       output[i] = (short)(cos() * ampl);
00161       step();
00162     }
00163   }
00164 
00165   template<class o_type, class i_type>
00166   void
00167   nco<o_type,i_type>::sin(int *output, int noutput_items, double ampl)
00168   {
00169     for(int i = 0; i < noutput_items; i++) {
00170       output[i] = (int)(sin() * ampl);
00171       step();
00172     }
00173   }
00174 
00175   template<class o_type, class i_type>
00176   void
00177   nco<o_type,i_type>::cos(int *output, int noutput_items, double ampl)
00178   {
00179     for(int i = 0; i < noutput_items; i++) {
00180       output[i] = (int)(cos() * ampl);
00181       step();
00182     }
00183   }
00184 
00185   template<class o_type, class i_type>
00186   void
00187   nco<o_type,i_type>::sincos(gr_complex *output, int noutput_items, double ampl)
00188   {
00189     for(int i = 0; i < noutput_items; i++) {
00190       float cosx, sinx;
00191       nco::sincos(&sinx, &cosx);
00192       output[i] = gr_complex(cosx * ampl, sinx * ampl);
00193       step();
00194     }
00195   }
00196 
00197 } /* namespace gr */
00198 
00199 #endif /* _NCO_H_ */