Merged r11377:11390 from jcorgan/usrp-headers in to trunk.
[debian/gnuradio] / usrp / limbo / apps-inband / ui_nco.h
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2002 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING.  If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 #ifndef INCLUDED_UI_NCO_H
23 #define INCLUDED_UI_NCO_H
24
25
26 #include <vector>
27 #include <ui_sincos.h>
28 #include <cmath>
29
30 #include <complex>
31 typedef std::complex<float>                     gr_complex;
32
33
34 /*!
35  * \brief base class template for Numerically Controlled Oscillator (NCO)
36  */
37
38
39 //FIXME  Eventually generalize this to fixed point
40
41 template<class o_type, class i_type> 
42 class ui_nco {
43 public:
44   ui_nco () : phase (0), phase_inc(0) {}
45
46   virtual ~ui_nco () {}
47
48   // radians
49   void set_phase (double angle) {
50     phase = angle;
51   }
52
53   void adjust_phase (double delta_phase) {
54     phase += delta_phase;
55   }
56
57
58   // angle_rate is in radians / step
59   void set_freq (double angle_rate){
60     phase_inc = angle_rate;
61   }
62
63   // angle_rate is a delta in radians / step
64   void adjust_freq (double delta_angle_rate)
65   {
66     phase_inc += delta_angle_rate;
67   }
68
69   // increment current phase angle
70
71   void step () 
72   { 
73     phase += phase_inc; 
74     if (fabs (phase) > M_PI){
75       
76       while (phase > M_PI)
77         phase -= 2*M_PI;
78
79       while (phase < -M_PI)
80         phase += 2*M_PI;
81     }
82   }
83
84   void step (int n)
85   {
86     phase += phase_inc * n;
87     if (fabs (phase) > M_PI){
88       
89       while (phase > M_PI)
90         phase -= 2*M_PI;
91
92       while (phase < -M_PI)
93         phase += 2*M_PI;
94     }
95   }
96
97   // units are radians / step
98   double get_phase () const { return phase; }
99   double get_freq () const { return phase_inc; }
100
101   // compute sin and cos for current phase angle
102   void sincos (float *sinx, float *cosx) const;
103
104   // compute cos or sin for current phase angle
105   float cos () const { return std::cos (phase); }
106   float sin () const { return std::sin (phase); }
107
108   // compute a block at a time
109   void sin (float *output, int noutput_items, double ampl = 1.0);
110   void cos (float *output, int noutput_items, double ampl = 1.0);
111   void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
112   void sin (short *output, int noutput_items, double ampl = 1.0);
113   void cos (short *output, int noutput_items, double ampl = 1.0);
114   void sin (int *output, int noutput_items, double ampl = 1.0);
115   void cos (int *output, int noutput_items, double ampl = 1.0);
116
117 protected:
118   double phase;
119   double phase_inc;
120 };
121
122 template<class o_type, class i_type> 
123 void
124 ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
125 {
126   ui_sincosf (phase, sinx, cosx);
127 }
128
129 template<class o_type, class i_type> 
130 void
131 ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
132 {
133   for (int i = 0; i < noutput_items; i++){
134     output[i] = (float)(sin () * ampl);
135     step ();
136   }
137 }
138
139 template<class o_type, class i_type> 
140 void
141 ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
142 {
143   for (int i = 0; i < noutput_items; i++){
144     output[i] = (float)(cos () * ampl);
145     step ();
146   }
147 }
148
149 template<class o_type, class i_type> 
150 void
151 ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
152 {
153   for (int i = 0; i < noutput_items; i++){
154     output[i] = (short)(sin() * ampl);
155     step ();
156   }
157 }
158
159 template<class o_type, class i_type> 
160 void
161 ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
162 {
163   for (int i = 0; i < noutput_items; i++){
164     output[i] = (short)(cos () * ampl);
165     step ();
166   }
167 }
168
169 template<class o_type, class i_type> 
170 void
171 ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
172 {
173   for (int i = 0; i < noutput_items; i++){
174     output[i] = (int)(sin () * ampl);
175     step ();
176   }
177 }
178
179 template<class o_type, class i_type> 
180 void
181 ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
182 {
183   for (int i = 0; i < noutput_items; i++){
184     output[i] = (int)(cos () * ampl);
185     step ();
186   }
187 }
188
189 template<class o_type, class i_type> 
190 void
191 ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
192 {
193   for (int i = 0; i < noutput_items; i++){
194     float cosx, sinx;
195     sincos (&sinx, &cosx);
196     output[i] = gr_complex(cosx * ampl, sinx * ampl);
197     step ();
198   }
199 }
200
201 #endif /* INCLUDED_UI_NCO_H */
202