libusrp/limbo/apps-inband/ui_nco.h

203 lines
4.7 KiB
C++

/* -*- c++ -*- */
/*
* Copyright 2002 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* GNU Radio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3, or (at your option)
* any later version.
*
* GNU Radio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Radio; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_UI_NCO_H
#define INCLUDED_UI_NCO_H
#include <vector>
#include <ui_sincos.h>
#include <cmath>
#include <complex>
typedef std::complex<float> gr_complex;
/*!
* \brief base class template for Numerically Controlled Oscillator (NCO)
*/
//FIXME Eventually generalize this to fixed point
template<class o_type, class i_type>
class ui_nco {
public:
ui_nco () : phase (0), phase_inc(0) {}
virtual ~ui_nco () {}
// radians
void set_phase (double angle) {
phase = angle;
}
void adjust_phase (double delta_phase) {
phase += delta_phase;
}
// angle_rate is in radians / step
void set_freq (double angle_rate){
phase_inc = angle_rate;
}
// angle_rate is a delta in radians / step
void adjust_freq (double delta_angle_rate)
{
phase_inc += delta_angle_rate;
}
// increment current phase angle
void step ()
{
phase += phase_inc;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
void step (int n)
{
phase += phase_inc * n;
if (fabs (phase) > M_PI){
while (phase > M_PI)
phase -= 2*M_PI;
while (phase < -M_PI)
phase += 2*M_PI;
}
}
// units are radians / step
double get_phase () const { return phase; }
double get_freq () const { return phase_inc; }
// compute sin and cos for current phase angle
void sincos (float *sinx, float *cosx) const;
// compute cos or sin for current phase angle
float cos () const { return std::cos (phase); }
float sin () const { return std::sin (phase); }
// compute a block at a time
void sin (float *output, int noutput_items, double ampl = 1.0);
void cos (float *output, int noutput_items, double ampl = 1.0);
void sincos (gr_complex *output, int noutput_items, double ampl = 1.0);
void sin (short *output, int noutput_items, double ampl = 1.0);
void cos (short *output, int noutput_items, double ampl = 1.0);
void sin (int *output, int noutput_items, double ampl = 1.0);
void cos (int *output, int noutput_items, double ampl = 1.0);
protected:
double phase;
double phase_inc;
};
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const
{
ui_sincosf (phase, sinx, cosx);
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (float)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(sin() * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (short)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(sin () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
output[i] = (int)(cos () * ampl);
step ();
}
}
template<class o_type, class i_type>
void
ui_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++){
float cosx, sinx;
sincos (&sinx, &cosx);
output[i] = gr_complex(cosx * ampl, sinx * ampl);
step ();
}
}
#endif /* INCLUDED_UI_NCO_H */