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