diff --git a/CMakeLists.txt b/CMakeLists.txt
index b39960963..6c380de0f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/sdrbase/dsp/ncof.cpp b/sdrbase/dsp/ncof.cpp
new file mode 100644
index 000000000..c63206c81
--- /dev/null
+++ b/sdrbase/dsp/ncof.cpp
@@ -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]);
+}
diff --git a/sdrbase/dsp/ncof.h b/sdrbase/dsp/ncof.h
new file mode 100644
index 000000000..349541809
--- /dev/null
+++ b/sdrbase/dsp/ncof.h
@@ -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
diff --git a/sdrbase/sdrbase.pro b/sdrbase/sdrbase.pro
index 801126768..3423cf11c 100644
--- a/sdrbase/sdrbase.pro
+++ b/sdrbase/sdrbase.pro
@@ -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\