GNU Radio 3.7.1 C++ API
|
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_ */