Added a NCO with floating point phase calculation before conversion to int for table indexing. This increases frequency precision and is mandatory for CTCSS tone generator

This commit is contained in:
f4exb 2016-12-19 02:41:31 +01:00
parent 3cfdbe72a0
commit 1e881703e8
4 changed files with 158 additions and 0 deletions

View File

@ -118,6 +118,7 @@ set(sdrbase_SOURCES
sdrbase/dsp/lowpass.cpp
sdrbase/dsp/movingaverage.cpp
sdrbase/dsp/nco.cpp
sdrbase/dsp/ncof.cpp
sdrbase/dsp/pidcontroller.cpp
sdrbase/dsp/phaselock.cpp
sdrbase/dsp/samplesinkfifo.cpp
@ -225,6 +226,7 @@ set(sdrbase_HEADERS
sdrbase/dsp/misc.h
sdrbase/dsp/movingaverage.h
sdrbase/dsp/nco.h
sdrbase/dsp/ncof.h
sdrbase/dsp/phasediscri.h
sdrbase/dsp/phaselock.h
sdrbase/dsp/pidcontroller.h

92
sdrbase/dsp/ncof.cpp Normal file
View File

@ -0,0 +1,92 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// //
// This program 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 as version 3 of the License, or //
// //
// This program 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 V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QtGlobal>
#include <stdio.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "dsp/ncof.h"
Real NCOF::m_table[NCOF::TableSize];
bool NCOF::m_tableInitialized = false;
void NCOF::initTable()
{
if(m_tableInitialized)
return;
for(int i = 0; i < TableSize; i++)
m_table[i] = cos((2.0 * M_PI * i) / TableSize);
m_tableInitialized = true;
}
NCOF::NCOF()
{
initTable();
m_phase = 0.0f;
}
void NCOF::setFreq(Real freq, Real sampleRate)
{
m_phaseIncrement = (freq * TableSize) / sampleRate;
qDebug("NCO freq: %f phase inc %f", freq, m_phaseIncrement);
}
float NCOF::next()
{
int phase = nextPhase();
return m_table[phase];
}
Complex NCOF::nextIQ()
{
int phase = nextPhase();
return Complex(m_table[phase], -m_table[(phase + TableSize / 4) % TableSize]);
}
Complex NCOF::nextQI()
{
int phase = nextPhase();
return Complex(-m_table[(phase + TableSize / 4) % TableSize], m_table[phase]);
}
float NCOF::get()
{
return m_table[(int) m_phase];
}
Complex NCOF::getIQ()
{
return Complex(m_table[(int) m_phase], -m_table[((int) m_phase + TableSize / 4) % TableSize]);
}
void NCOF::getIQ(Complex& c)
{
c.real(m_table[(int) m_phase]);
c.imag(-m_table[((int) m_phase + TableSize / 4) % TableSize]);
}
Complex NCOF::getQI()
{
return Complex(-m_table[((int) m_phase + TableSize / 4) % TableSize], m_table[(int) m_phase]);
}
void NCOF::getQI(Complex& c)
{
c.imag(m_table[(int) m_phase]);
c.real(-m_table[((int) m_phase + TableSize / 4) % TableSize]);
}

62
sdrbase/dsp/ncof.h Normal file
View File

@ -0,0 +1,62 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB //
// //
// This program 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 as version 3 of the License, or //
// //
// This program 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 V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef INCLUDE_NCOF_H
#define INCLUDE_NCOF_H
#include "dsp/dsptypes.h"
#include "util/export.h"
class SDRANGEL_API NCOF {
private:
enum {
TableSize = (1 << 12),
};
static Real m_table[TableSize];
static bool m_tableInitialized;
static void initTable();
Real m_phaseIncrement;
Real m_phase;
public:
NCOF();
void setFreq(Real freq, Real sampleRate);
void setPhase(Real phase) { m_phase = phase; }
int nextPhase() //!< Increment phase and return its integer value
{
m_phase += m_phaseIncrement;
while(m_phase >= TableSize)
m_phase -= TableSize;
while(m_phase < 0)
m_phase += TableSize;
return (int) m_phase;
}
Real next(); //!< Return next real sample
Complex nextIQ(); //!< Return next complex sample
Complex nextQI(); //!< Return next complex sample (reversed)
Real get(); //!< Return current real sample (no phase increment)
Complex getIQ(); //!< Return current complex sample (no phase increment)
void getIQ(Complex& c); //!< Sets to the current complex sample (no phase increment)
Complex getQI(); //!< Return current complex sample (no phase increment, reversed)
void getQI(Complex& c); //!< Sets to the current complex sample (no phase increment, reversed)
};
#endif // INCLUDE_NCO_H

View File

@ -62,6 +62,7 @@ SOURCES += mainwindow.cpp\
dsp/lowpass.cpp\
dsp/movingaverage.cpp\
dsp/nco.cpp\
dsp/ncof.cpp\
dsp/pidcontroller.cpp\
dsp/phaselock.cpp\
dsp/samplesinkfifo.cpp\
@ -159,6 +160,7 @@ HEADERS += mainwindow.h\
dsp/misc.h\
dsp/movingaverage.h\
dsp/nco.h\
dsp/ncof.h\
dsp/phasediscri.h\
dsp/phaselock.h\
dsp/pidcontroller.h\