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