// ----------------------------------------------------------------------------
// psk.cxx  --  psk modem
//
// Copyright (C) 2006-2015
//		Dave Freese, W1HKJ
// Copyright (C) 2009-2010
//		John Douyere, VK2ETA
// Copyright (C) 2014
//		John Phelps, KL4YFD
//
// PSK-FEC and PSK-R modes contributed by VK2ETA
//
// This file is part of fldigi.  Adapted from code contained in gmfsk
// source code distribution.
// gmfsk Copyright (C) 2001, 2002, 2003
// Tomi Manninen (oh2bns@sral.fi)
//
// Fldigi 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 of the License, or
// (at your option) any later version.
//
// Fldigi 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 fldigi.  If not, see <http://www.gnu.org/licenses/>.
// ----------------------------------------------------------------------------


#include <config.h>

#include <stdlib.h>
#include <stdio.h>
#include <iomanip>
#include <iostream>

#include "psk.h"
#include "main.h"
#include "fl_digi.h"
#include "trx.h"
#include "misc.h"
#include "waterfall.h"
#include "configuration.h"
#include "status.h"
#include "viewpsk.h"
#include "pskeval.h"
#include "modem.h"
#include "Viewer.h"
#include "macros.h"

extern waterfall *wf;

// Change the following for DCD low pass filter adjustment
#define SQLCOEFF 0.01
#define SQLDECAY 50

//=====================================================================

#define K		5
#define POLY1	0x17
#define POLY2	0x19

// PSK + FEC + INTERLEAVE
// df=10 : correct up to 4 bits
#define PSKR_K		7
#define PSKR_POLY1	0x6d
#define PSKR_POLY2	0x4f

// df=14 : correct up to 6 bits
#define K11		11
#define K11_POLY1	03073 // 1595
#define K11_POLY2	02365 // 1269

// df=16 : correct up to 7 bits
// Code has good ac(df) and bc(df) parameters for puncturing
#define K13		13
#define K13_POLY1	016461 // 7473
#define K13_POLY2	012767 // 5623

// df=19 : correct up to 9 bits
#define	K16		16
#define	K16_POLY1	0152711 // 54729
#define	K16_POLY2	0126723 // 44499

// For Gray-mapped 8PSK:
// Even when the received phase is distorted by +- 1 phase-position:
//  - One of the bits is still known with 100% certianty.
//  - Only up to 1 bit can be in error
static cmplx graymapped_8psk_pos[] = {
	//			Degrees  Bits In  Mapped Soft-Symbol
	cmplx (1.0, 0.0),         // 0   | 0b000  | 025,000,025
	cmplx (0.7071, 0.7071),   // 45  | 0b001  | 000,025,230
	cmplx (-0.7071, 0.7071),  // 135 | 0b010  | 025,255,025
	cmplx (0.0, 1.0),         // 90  | 0b011  | 000,230,230
	cmplx (0.7071, -0.7071),  // 315 | 0b100  | 230,000,025
	cmplx (0.0, -1.0),        // 270 | 0b101  | 255,025,230
	cmplx (-1.0, 0.0),        // 180 | 0b110  | 230,255,025
	cmplx (-0.7071, -0.7071)  // 225 | 0b111  | 255,230,230
};

// Associated soft-symbols to be used with graymapped_8psk_pos[] constellation
// These softbits have precalculated (a-priori) probabilities applied
// Use of this table automatically Gray-decodes incoming symbols.
static unsigned char graymapped_8psk_softbits[8][3] =  {
	{ 25,   0,  25}, // 0
	{  0,  25, 230}, // 1
	{  0, 230, 230}, // 3
	{ 25, 255,  25}, // 2
	{230, 255,  25}, // 6
	{255, 230, 230}, // 7
	{255,  25, 230}, // 5
	{230,   0,  25}  // 4
};


char pskmsg[80];

void psk::tx_init(SoundBase *sc)
{
	scard = sc;
	for (int car = 0; car < numcarriers; car++) {
		phaseacc[car] = 0;
		prevsymbol[car] = cmplx (1.0, 0.0);
	}
	preamble = dcdbits;
	if (_pskr || _xpsk || _8psk || _16psk) {
		// MFSK based varicode instead of psk
		shreg = 1;
		shreg2 = 1;
	} else {
		shreg = 0;
		shreg2 = 0;
	}
	videoText();

	// interleaver
	bitshreg = 0;
	startpreamble = true;

	symbols = 0;
	acc_symbols = 0;
	ovhd_symbols = 0;
	accumulated_bits = 0;

	if(_8psk && _puncturing) {
		enc->init();
		Txinlv->flush();
	}

	vphase = 0;
	maxamp = 0;

}

void psk::rx_init()
{
	for (int car = 0; car < numcarriers; car++) {
		phaseacc[car] = 0;
		prevsymbol[car] = cmplx (1.0, 0.0);
	}
	quality		= cmplx (0.0, 0.0);
	if (_pskr || _xpsk || _8psk || _16psk) {
		// MFSK varicode instead of psk
		shreg = 1;
		shreg2 = 1;
	} else {
		shreg = 0;
		shreg2 = 0;
	}
	dcdshreg = 0;
	dcdshreg2 = 0;
	dcd = 0;
	bitclk = 0;
	freqerr = 0.0;
	if (mailserver && progdefaults.PSKmailSweetSpot) sigsearch = SIGSEARCH;
	else sigsearch = 0;
	put_MODEstatus(mode);
	resetSN_IMD();
	imdValid = false;
	afcmetric = 0.0;
	// interleaver, split incoming bit stream into two, one late by one bit
	rxbitstate = 0;
	fecmet = fecmet2 = 0;
	if (Rxinlv) Rxinlv->flush();
	if (Rxinlv2) Rxinlv2->flush();

}


void psk::restart()
{
	if ((mode >= MODE_PSK31 && mode <= MODE_PSK125) ||
		(mode >= MODE_QPSK31 && mode <= MODE_QPSK125))
		pskviewer->restart(mode);
	evalpsk->setbw(sc_bw);
}

void psk::init()
{
	restart();
	modem::init();
	set_scope_mode(Digiscope::PHASE);
	initSN_IMD();
	snratio = 1.0;
	imdratio = 0.001;
	rx_init();
}

psk::~psk()
{
	if (tx_shape) delete [] tx_shape;
	if (enc) delete enc;
	if (dec) delete dec;
	// FEC 2nd Viterbi decoder
	if (dec2) delete dec2;

	for (int i = 0; i < MAX_CARRIERS; i++) {
		if (fir1[i]) delete fir1[i];
		if (fir2[i]) delete fir2[i];
	}
	if (snfilt) delete snfilt;
	if (imdfilt) delete imdfilt;

	if (pskviewer) delete pskviewer;
	if (evalpsk) delete evalpsk;

	// Interleaver
	if (Rxinlv) delete Rxinlv;
	if (Rxinlv2) delete Rxinlv2;
	if (Txinlv) delete Txinlv;

	if (vestigial_sfft) delete vestigial_sfft;
}

psk::psk(trx_mode pskmode) : modem()
{
	cap |= CAP_AFC | CAP_AFC_SR;

	mode = pskmode;

	// Set the defaults that are common to most modes
	samplerate = 8000;
	numcarriers = 1;
	separation = 1.4;
	_16psk = _8psk = _xpsk = _pskr = _qpsk = _disablefec = _puncturing = false;
	symbits = 1;
	flushlength = 0;
	int  isize = 2;
	idepth = 2;
	PSKviterbi = false;
	vestigial = false;

	switch (mode) {
		case MODE_PSK31:
			symbollen = 256;
			dcdbits = 32;
			break;
		case MODE_PSK63:
			symbollen = 128;
			dcdbits = 64;
			break;
		case MODE_PSK125:
			symbollen = 64;
			dcdbits = 128;
			break;
		case MODE_PSK250:
			symbollen = 32;
			dcdbits = 256;
			break;
		case MODE_PSK500:
			symbollen = 16;
			dcdbits = 512;
			break;
		case MODE_PSK1000:
			symbollen = 8;
			dcdbits = 128;
			break;

		case MODE_QPSK31:
			symbollen = 256;
			_qpsk = true;
			dcdbits = 32;
			cap |= CAP_REV;
			break;
		case MODE_QPSK63:
			symbollen = 128;
			_qpsk = true;
			dcdbits = 64;
			cap |= CAP_REV;
			break;
		case MODE_QPSK125:
			symbollen = 64;
			_qpsk = true;
			dcdbits = 128;
			cap |= CAP_REV;
			break;
		case MODE_QPSK250:
			symbollen = 32;
			_qpsk = true;
			dcdbits = 256;
			cap |= CAP_REV;
			break;
		case MODE_QPSK500:
			symbollen = 16;
			_qpsk = true;
			dcdbits = 512;
			cap |= CAP_REV;
			break;
		case MODE_PSK63F:  // As per Multipsk (BPSK63 + FEC + MFSK Varicode)
			symbollen = 128;
			_pskr = true;
			dcdbits = 64;
			break;

	// 8psk modes without FEC
		case MODE_8PSK125:
			symbollen = 128;
			samplerate = 16000;
			_8psk = true;
			_disablefec = true;
			dcdbits = 128;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK250: // 250 baud | 375 bits/sec @ 1/2 Rate FEC
			symbollen = 64;
			samplerate = 16000;
			_8psk = true;
			_disablefec = true;
			dcdbits = 256;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK500: // 500 baud | 1000 bits/sec @ 2/3 rate FEC
			symbollen = 32;
			samplerate = 16000;
			_8psk = true;
			_disablefec = true;
			dcdbits = 512;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK1000: // 1000 baud | 3000 bits/sec  No FEC
			symbollen = 16;
			samplerate = 16000;
			_8psk = true;
			_disablefec = true;
			dcdbits = 1024;
			vestigial = true;
			cap |= CAP_REV;
			break;

	// 8psk modes with FEC
		case MODE_8PSK125FL:
			symbollen = 128;
			idepth = 384; // 1024 milliseconds
			flushlength = 38;
			samplerate = 16000;
			_8psk = true;
			dcdbits = 128;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK250FL: // 250 baud | 375 bits/sec @ 1/2 Rate FEC
			symbollen = 64;
			idepth = 512; // 682 milliseconds
			flushlength = 47;
			samplerate = 16000;
			_8psk = true;
			dcdbits = 256;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK125F:
			symbollen = 128;
			idepth = 384; // 1024 milliseconds
			flushlength = 38;
			samplerate = 16000;
			_8psk = true;
			dcdbits = 128;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK250F: // 250 baud | 375 bits/sec @ 1/2 Rate FEC
			symbollen = 64;
			idepth = 512; // 682 milliseconds
			flushlength = 47;
			samplerate = 16000;
			_8psk = true;
			dcdbits = 256;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK500F: // 500 baud | 1000 bits/sec @ 2/3 rate FEC
			symbollen = 32;
			idepth = 640; // 426 milliseconds
			flushlength = 62;
			samplerate = 16000;
			_8psk = true;
			_puncturing = true;
			dcdbits = 512;
			vestigial = true;
			cap |= CAP_REV;
			break;
		case MODE_8PSK1000F: // 1000 baud | 3000 bits/sec
			symbollen = 16;
			idepth = 512;
			flushlength = 56;
			samplerate = 16000;
			_8psk = true;
			dcdbits = 1024;
			cap |= CAP_REV;
			_puncturing = true;
			vestigial = true;
			PSKviterbi = true;
			break;
		case MODE_8PSK1200F: // 1200 baud | 1800 bits/sec
			symbollen = 13;
			idepth = 512;
			flushlength = 56;
			samplerate = 16000;
			_8psk = true;
			_puncturing = true;
			dcdbits = 2048;
			cap |= CAP_REV;
			vestigial = true;
			PSKviterbi = true;
			break;
			// end 8psk modes

		case MODE_PSK125R:
			symbollen = 64;
			_pskr = true;
			dcdbits = 128;
			idepth = 40;  // 2x2x40 interleaver
			break;
		case MODE_PSK250R:
			symbollen = 32;
			_pskr = true;
			dcdbits = 256;
			idepth = 80;  // 2x2x80 interleaver
			break;
		case MODE_PSK500R:
			symbollen = 16;
			_pskr = true;
			dcdbits = 512;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_PSK1000R:
			symbollen = 8;
			_pskr = true;
			dcdbits = 512;
			idepth = 160; // 2x2x160 interleaver
			break;

			// multi-carrier modems
		case MODE_4X_PSK63R:
			symbollen = 128;//PSK63
			dcdbits = 128;
			_pskr = true;//PSKR
			numcarriers = 4;
			idepth = 80; // 2x2x80 interleaver
			break;
		case MODE_5X_PSK63R:
			symbollen = 128; //PSK63
			dcdbits = 512;
			_pskr = true; //PSKR
			numcarriers = 5;
			idepth = 260; // 2x2x160 interleaver
			break;
		case MODE_10X_PSK63R:
			symbollen = 128; //PSK63
			dcdbits = 512;
			_pskr = true; //PSKR
			numcarriers = 10;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_20X_PSK63R:
			symbollen = 128; //PSK63
			dcdbits = 512;
			_pskr = true; //PSKR
			numcarriers = 20;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_32X_PSK63R:
			symbollen = 128; //PSK63
			dcdbits = 512;
			_pskr = true; //PSKR
			numcarriers = 32;
			idepth = 160; // 2x2x160 interleaver
			break;

		case MODE_4X_PSK125R:
			symbollen = 64;//PSK125
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 4;
			idepth = 80; // 2x2x80 interleaver
			break;
		case MODE_5X_PSK125R:
			symbollen = 64;//PSK125
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 5;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_10X_PSK125R:
			symbollen = 64;//PSK125
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 10;
			idepth = 160; // 2x2x160 interleaver
			break;

		case MODE_12X_PSK125:
			symbollen = 64;//PSK125
			dcdbits = 128;//512;
			numcarriers = 12;
			break;
		case MODE_12X_PSK125R:
			symbollen = 64;//PSK125
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 12;
			idepth = 160; // 2x2x160 interleaver
			break;

		case MODE_16X_PSK125R:
			symbollen = 64;//PSK125
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 16;
			idepth = 160; // 2x2x160 interleaver
			break;

		case MODE_2X_PSK250R:
			symbollen = 32;//PSK250
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 2;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_3X_PSK250R:
			symbollen = 32;//PSK250
			dcdbits = 512;
			_pskr = true;//PSKR
			numcarriers = 3;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_5X_PSK250R:
			symbollen = 32;//PSK250
			_pskr = true;//PSKR
			dcdbits = 1024;
			numcarriers = 5;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_6X_PSK250:
			symbollen = 32;//PSK250
			dcdbits = 512;
			numcarriers = 6;
			break;
		case MODE_6X_PSK250R:
			symbollen = 32;//PSK250
			_pskr = true;//PSKR
			dcdbits = 1024;
			numcarriers = 6;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_7X_PSK250R:
			symbollen = 32;//PSK250
			_pskr = true;//PSKR
			dcdbits = 1024;
			numcarriers = 7;
			idepth = 160; // 2x2x160 interleaver
			break;

		case MODE_2X_PSK500:
			symbollen = 16;
			dcdbits = 512;
			numcarriers = 2;
			break;
		case MODE_4X_PSK500:
			symbollen = 16;
			dcdbits = 512;
			numcarriers = 4;
			break;

		case MODE_2X_PSK500R:
			symbollen = 16;
			_pskr = true;
			dcdbits = 1024;
			idepth = 160; // 2x2x160 interleaver
			numcarriers = 2;
			break;
		case MODE_3X_PSK500R:
			symbollen = 16;
			_pskr = true;
			dcdbits = 1024;
			idepth = 160; // 2x2x160 interleaver
			numcarriers = 3;
			break;
		case MODE_4X_PSK500R:
			symbollen = 16;
			_pskr = true;
			dcdbits = 1024;
			idepth = 160; // 2x2x160 interleaver
			numcarriers = 4;
			break;

		case MODE_2X_PSK800:
			symbollen = 10;
			_pskr = false;
			dcdbits = 512;
			numcarriers = 2;
			break;
		case MODE_2X_PSK800R:
			symbollen = 10;
			_pskr = true;
			dcdbits = 1024;
			idepth = 160; // 2x2x160 interleaver
			numcarriers = 2;
			break;

		case MODE_2X_PSK1000:
			symbollen = 8;//PSK1000
			dcdbits = 1024;
			numcarriers = 2;
			idepth = 160; // 2x2x160 interleaver
			break;
		case MODE_2X_PSK1000R:
			symbollen = 8;//PSK1000
			_pskr = true;//PSKR
			dcdbits = 1024;
			numcarriers = 2;
			idepth = 160; // 2x2x160 interleaver
			break;

		default:
			mode = MODE_PSK31;
			symbollen = 256;
			dcdbits = 32;
			numcarriers = 1;
	}

	// Set the number of bits-per-symbol based on the chosen constellation
	if (_qpsk || _xpsk) symbits = 2;
	else if (_8psk) symbits = 3;
	else if (_16psk) symbits = 4;
	else symbits = 1; // else BPSK / PSKR


	//printf("%s: symlen %d, dcdbits %d, _qpsk %d, _pskr %d, numc %f\n",
	//mode_info[mode].sname,
	//symbollen, dcdbits, _qpsk, _pskr, numcarriers);


	enc = (encoder *)0;
	dec = (viterbi *)0;
	// BPSK+FEC - 2nd Viterbi decoder and de-interleaver
	dec2 = (viterbi *)0;
	Txinlv = (interleave *)0;
	Rxinlv = (interleave *)0;
	Rxinlv2 = (interleave *)0;
	vestigial_sfft = (sfft *)0;

	// create impulse response for experimental FIR filters
	double fir1c[64];
	double fir2c[64];

	for (int i = 0; i < MAX_CARRIERS; i++) {
		if (i < numcarriers) {
			fir1[i] = new C_FIR_filter();
			fir2[i] = new C_FIR_filter();
		} else {
			fir1[i] = (C_FIR_filter *)0;
			fir2[i] = (C_FIR_filter *)0;
		}
	}

	switch (progdefaults.PSK_filter) {
		case 1:
			// use the original gmfsk matched filters
			for (int i = 0; i < 64; i++) {
				fir1c[i] = gmfir1c[i];
				fir2c[i] = gmfir2c[i];
			}
			for (int i = 0; i < numcarriers; i++) {
				fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c);
				fir2[i]->init(FIRLEN, 1, fir2c, fir2c);
			}
			break;
		case 2:
			// creates fir1c matched sin(x)/x filter w hamming
			wsincfilt(fir1c, 1.0 / symbollen, false);
			// creates fir2c matched sin(x)/x filter w hamming
			wsincfilt(fir2c, 1.0 / 16.0, false);
			for (int i = 0; i < numcarriers; i++) {
				fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c);
				fir2[i]->init(FIRLEN, 1, fir2c, fir2c);
			}
			break;
		case 3:
			// creates fir1c matched sin(x)/x filter w hamming
			wsincfilt(fir1c, 1.0 / symbollen, false);
			// 1/22 with Hamming window nearly identical to gmfir2c
			wsincfilt(fir2c, 1.0 / 22.0, false);
			for (int i = 0; i < numcarriers; i++) {
				fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c);
				fir2[i]->init(FIRLEN, 1, fir2c, fir2c);
			}
			break;
		case 4:
			wsincfilt(fir2c, 1.5 / 16.0, true);
			for (int i = 0; i < numcarriers; i++) {
				fir1[i]->init_lowpass (FIRLEN, 16, 1.5 / symbollen);
				fir2[i]->init(FIRLEN, 1, fir2c, fir2c);
			}
		case 0:
		default :
			// creates fir1c matched sin(x)/x filter w blackman
			wsincfilt(fir1c, 1.0 / symbollen, true);
			// creates fir2c matched sin(x)/x filter w blackman
			wsincfilt(fir2c, 1.0 / 16.0, true);
			for (int i = 0; i < numcarriers; i++) {
				fir1[i]->init(FIRLEN, symbollen > 15 ? symbollen / 16 : 1, fir1c, fir1c);
				fir2[i]->init(FIRLEN, 1, fir2c, fir2c);
			}
	}

	snfilt = new Cmovavg(16);
	imdfilt = new Cmovavg(16);

	if (_disablefec) {
		enc = NULL;
		dec = dec2 = NULL;

	} else if (_qpsk) {
		enc = new encoder(K, POLY1, POLY2);
		dec = new viterbi(K, POLY1, POLY2);

	} else if (_pskr || PSKviterbi) {
		// FEC for BPSK. Use a 2nd Viterbi decoder for comparison.
		// Set decode size to 4 since some characters can be as small
		// as 3 bits long. This minimises intercharacters decoding
		// interactions.
		enc = new encoder(PSKR_K, PSKR_POLY1, PSKR_POLY2);
		dec = new viterbi(PSKR_K, PSKR_POLY1, PSKR_POLY2);
		dec->setchunksize(4);
		dec2 = new viterbi(PSKR_K, PSKR_POLY1, PSKR_POLY2);
		dec2->setchunksize(4);

	} else if (mode == MODE_8PSK125F || mode == MODE_8PSK250F) {
		enc = new encoder(K16, K16_POLY1, K16_POLY2);
		dec = new viterbi(K16, K16_POLY1, K16_POLY2);
		dec->setchunksize(4);
		dec2 = new viterbi(K13, K16_POLY1, K16_POLY2);
		dec2->setchunksize(4);
	
	} else if (_xpsk || _8psk || _16psk) {
		enc = new encoder(K13, K13_POLY1, K13_POLY2);
		dec = new viterbi(K13, K13_POLY1, K13_POLY2);
		dec->setchunksize(4);
		// Second viterbi decoder is only needed when modem has an odd number of bits/symbol.
		if ( _8psk && !_puncturing ) { // (punctured 8psk has 3-real bits + 1-punctured bit per transmitted symbol)
			dec2 = new viterbi(K13, K13_POLY1, K13_POLY2);
			dec2->setchunksize(4);
		}
		if (_puncturing) { // punctured codes benefit from a longer traceback
			dec->settraceback(K13 * 16);
			if (dec2) dec2->settraceback(K13 * 16);
		}
	}

	// Interleaver. For PSKR to maintain constant time delay between bits,
	// we double the number of concatenated square iterleavers for
	// each doubling of speed: 2x2x20 for BSK63+FEC, 2x2x40 for
	// BPSK125+FEC, etc..

	Txinlv = new interleave (isize, idepth, INTERLEAVE_FWD);
	Rxinlv = new interleave (isize, idepth, INTERLEAVE_REV);
	if (dec2) Rxinlv2 = new interleave (isize, idepth, INTERLEAVE_REV);

	bitshreg = 0;
	rxbitstate = 0;
	startpreamble = true;

	tx_shape = new double[symbollen];

	// raised cosine shape for the transmitter
	for ( int i = 0; i < symbollen; i++)
		tx_shape[i] = 0.5 * cos(i * M_PI / symbollen) + 0.5;

	fragmentsize = symbollen;
	sc_bw = samplerate / symbollen;
	//JD added for multiple carriers
	inter_carrier = separation * sc_bw;
	bandwidth = sc_bw * ( 1 + separation * (numcarriers - 1));

	snratio = s2n = imdratio = imd = 0;

	if (mailserver && progdefaults.PSKmailSweetSpot)
		sigsearch = SIGSEARCH;
	else
		sigsearch = 0;
	for (int i = 0; i < 16; i++)
		syncbuf[i] = 0.0;
	E1 = E2 = E3 = 0.0;
	acquire = 0;

	evalpsk = new pskeval;
	if ((mode >= MODE_PSK31 && mode <= MODE_PSK125) ||
		(mode >= MODE_QPSK31 && mode <= MODE_QPSK125))
		pskviewer = new viewpsk(evalpsk, mode);
	else
		pskviewer = 0;

	if (vestigial) {
		if (samplerate == 16000)
			sfft_size = 16384;
		else
			sfft_size = 8192;

		int bin = sc_bw * sfft_size / samplerate;
		vestigial_sfft = new sfft(sfft_size, bin - 5, bin + 6); // 11 bins
		for (int i = 0; i < 11; i++) sfft_bins[i] = cmplx(0,0);
	}
}

//=============================================================================
//=========================== psk31 receive routines ==========================
//=============================================================================


void psk::s2nreport(void)
{
	modem::s2nreport();
	s2n_sum = s2n_sum2 = s2n_ncount = 0.0;
}

void psk::rx_bit(int bit)
{
	int c;
	bool do_s2nreport = false;
	shreg = (shreg << 1) | !!bit;
	if (_pskr || _xpsk || _8psk || _16psk) {
		// MFSK varicode instead of PSK Varicode
		if ((shreg & 7) == 1) {
			c = varidec(shreg >> 1);
			// Voting at the character level for only PSKR modes
			if (fecmet >= fecmet2 || _disablefec) {
				if ((c != -1) && (c != 0) && (dcd == true)) {
					put_rx_char(c);
					do_s2nreport = true;
				}
			}
			shreg = 1;
		}
	} else {
		// PSK varicode
		if ((shreg & 3) == 0) {
			c = psk_varicode_decode(shreg >> 2);
			if ((c != -1) && (dcd == true)) {
				put_rx_char(c);
				do_s2nreport = true;
			}
			shreg = 0;
		}
	}

	if (do_s2nreport) {
		if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) {
			s2n_sum += s2n_metric;
			s2n_sum2 += (s2n_metric * s2n_metric);
			s2n_ncount ++;
			if (c == EOT)
				s2nreport();
		}
	}

}




void psk::rx_bit2(int bit)
{
	int c;
	bool do_s2nreport = false;

	shreg2 = (shreg2 << 1) | !!bit;
	// MFSK varicode instead of PSK Varicode
	if ((shreg2 & 7) == 1) {
		c = varidec(shreg2 >> 1);
		// Voting at the character level for only PSKR modes
		if (fecmet < fecmet2 || _disablefec) {
			if ((c != -1) && (c != 0) && (dcd == true)) {
				put_rx_char(c);
				do_s2nreport = true;
			}
		}
		shreg2 = 1;
	}

	if (do_s2nreport) {
		if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) {
			s2n_sum += s2n_metric;
			s2n_sum2 += (s2n_metric * s2n_metric);
			s2n_ncount ++;
			if (c == EOT)
				s2nreport();
		}
	}
}

void psk::rx_qpsk(int bits)
{
	unsigned char sym[2];
	int c;

	if (_qpsk && !reverse)
		bits = (4 - bits) & 3;

	sym[0] = (bits & 1) ? 255 : 0;
	sym[1] = (bits & 2) ? 0 : 255;	// top bit is flipped

	//JD added de-interleaver
	//	Rxinlv->symbols(sym);

	c = dec->decode(sym, NULL);

	if (c != -1) {
		rx_bit(c & 0x80);
		rx_bit(c & 0x40);
		rx_bit(c & 0x20);
		rx_bit(c & 0x10);
		rx_bit(c & 0x08);
		rx_bit(c & 0x04);
		rx_bit(c & 0x02);
		rx_bit(c & 0x01);
	}
}


void psk::rx_pskr(unsigned char symbol)
{
	int met;
	unsigned char twosym[2];
	unsigned char tempc;
	int c;

	//In the case of multiple carriers, if even number of carriers then we
	// know the bit-order and don't need voting otherwise
	// we accumulate the soft bits for the interleaver THEN submit to Viterbi
	// decoder in alternance so that each one is processed one bit later.
	// Only two possibilities for sync: current bit or previous one since
	// we encode with R = 1/2 and send encoded bits one after the other
	// through the interleaver.

	symbolpair[1] = symbolpair[0];
	symbolpair[0] = symbol;


	if (rxbitstate == 0) {
		rxbitstate++;
		//Only use one decoder is using even carriers (we know the bits order)
		//		if (((int)numcarriers) % 2 == 0) {
		//			fecmet2 = -9999.0;
		//			return;
		//		}
		// XPSK and 16PSK have even number of bits/symbol
		// Punctured 8PSK has even number of bits/symbol (3 real + 1 punctured)
		// so bit order known: can use only one decoder to reduce CPU usage
		if ( _xpsk || _16psk || (_8psk && _puncturing) ) {
			fecmet2 = -9999.0;
			return;
		}
		// copy to avoid scrambling symbolpair for the next bit
		twosym[0] = symbolpair[0];
		twosym[1] = symbolpair[1];
		// De-interleave
		if (mode != MODE_PSK63F) Rxinlv2->symbols(twosym);
		// pass de-interleaved bits pair to the decoder, reversed
		tempc = twosym[1];
		twosym[1] = twosym[0];
		twosym[0] = tempc;
		// Then viterbi decoder
		c = dec2->decode(twosym, &met);
		if (c != -1) {
			// FEC only take metric measurement after backtrace
			// Will be used for voting between the two decoded streams
			fecmet2 = decayavg(fecmet2, met, 20);
			rx_bit2(c & 0x08);
			rx_bit2(c & 0x04);
			rx_bit2(c & 0x02);
			rx_bit2(c & 0x01);
		}
	} else {
		// Again for the same stream shifted by one bit
		rxbitstate = 0;
		twosym[0] = symbolpair[0];
		twosym[1] = symbolpair[1];
		// De-interleave
		if (mode != MODE_PSK63F) Rxinlv->symbols(twosym);
		tempc = twosym[1];
		twosym[1] = twosym[0];
		twosym[0] = tempc;
		// Then viterbi decoder
		c = dec->decode(twosym, &met);
		if (c != -1) {
			fecmet = decayavg(fecmet, met, 20);
			rx_bit(c & 0x08);
			rx_bit(c & 0x04);
			rx_bit(c & 0x02);
			rx_bit(c & 0x01);
		}
	}
}

void psk::searchDown()
{
	double srchfreq = frequency - sc_bw * 2;
	double minfreq = sc_bw * 2;
	double spwr, npwr;
	while (srchfreq > minfreq) {
		spwr = wf->powerDensity(srchfreq, sc_bw);
		npwr = wf->powerDensity(srchfreq + sc_bw, sc_bw/2) + 1e-10;
		if (spwr / npwr > pow(10, progdefaults.ServerACQsn / 10)) {
			frequency = srchfreq;
			set_freq(frequency);
			sigsearch = SIGSEARCH;
			break;
		}
		srchfreq -= sc_bw;
	}
}

void psk::searchUp()
{
	double srchfreq = frequency + sc_bw * 2;
	double maxfreq = IMAGE_WIDTH - sc_bw * 2;
	double spwr, npwr;
	while (srchfreq < maxfreq) {
		spwr = wf->powerDensity(srchfreq, sc_bw/2);
		npwr = wf->powerDensity(srchfreq - sc_bw, sc_bw/2) + 1e-10;
		if (spwr / npwr > pow(10, progdefaults.ServerACQsn / 10)) {
			frequency = srchfreq;
			set_freq(frequency);
			sigsearch = SIGSEARCH;
			break;
		}
		srchfreq += sc_bw;
	}
}

int waitcount = 0;

void psk::findsignal()
{
	int ftest, f1, f2;

	if (sigsearch > 0) {
		sigsearch--;
		if (mailserver) { // mail server search algorithm
			if (progdefaults.PSKmailSweetSpot) {
				f1 = (int)(progdefaults.ServerCarrier - progdefaults.ServerOffset);
				f2 = (int)(progdefaults.ServerCarrier + progdefaults.ServerOffset);
			} else {
				f1 = (int)(frequency - progdefaults.ServerOffset);
				f2 = (int)(frequency + progdefaults.ServerOffset);
			}
			if (evalpsk->sigpeak(ftest, f1, f2) > pow(10, progdefaults.ServerACQsn / 10) ) {
				if (progdefaults.PSKmailSweetSpot) {
					if (fabs(ftest - progdefaults.ServerCarrier) < progdefaults.ServerOffset) {
						frequency = ftest;
						set_freq(frequency);
						freqerr = 0.0;
					} else {
						frequency = progdefaults.ServerCarrier;
						set_freq(frequency);
						freqerr = 0.0;
					}
				} else {
					frequency = ftest;
					set_freq(frequency);
					freqerr = 0.0;
				}
			} else { // less than the detection threshold
				if (progdefaults.PSKmailSweetSpot) {
					frequency = progdefaults.ServerCarrier;
					set_freq(frequency);
					sigsearch = SIGSEARCH;
				}
			}
		} else { // normal signal search algorithm
			f1 = (int)(frequency - progdefaults.SearchRange/2);
			f2 = (int)(frequency + progdefaults.SearchRange/2);
			if (evalpsk->sigpeak(ftest, f1, f2) > pow(10, progdefaults.ACQsn / 10.0) ) {
				frequency = ftest;
				set_freq(frequency);
				freqerr = 0.0;
				sigsearch = 0;
				acquire = dcdbits;
			}
		}
	}
}

//DHF: AFC based on vestigial carrier located at f0 - bandwidth
void psk::vestigial_afc() {

	if (!progdefaults.pskpilot) return;
	if (!vestigial_sfft->is_stable()) return;

	double avg = 0;
	int i = 0;
	for (i = 0; i < 11; i++) avg += abs(sfft_bins[i]);
	avg /= 11.0;
	std::setprecision(2); std::setw(5);
	for (i = 0; i < 11; i++) if (abs(sfft_bins[i]) > 2.0*avg) break;
	if (i < 11) {
//		std::cout	<< "bin: " << i 
//					<< ", freq offset: " << (i - 5)*samplerate/16384.0
//					<< ", amp: " << abs(sfft_bins[i]) 
//					<< ", avg: " << avg << "\n";
		if (i != 5) {
			frequency -= 1.0*(i-5)*samplerate/sfft_size;
			set_freq (frequency);
		}
	}
	vestigial_sfft->reset();
}

//JD: disable for multiple carriers as we are running as modem and
//    therefore use other strategies for frequency alignment like RSID
void psk::phaseafc()
{
	double error;
	// Skip AFC for modes it does not work with

	if (vestigial) return vestigial_afc();

	if (afcmetric < 0.05 ||
		mode == MODE_PSK500 ||
		mode == MODE_QPSK500 || numcarriers > 1) return;

	error = (phase - bits * M_PI / 2.0);
	if (error < -M_PI / 2.0 || error > M_PI / 2.0) return;
	error *= samplerate / (TWOPI * symbollen);
	if (fabs(error) < sc_bw ) {
		freqerr = error / dcdbits;
		frequency -= freqerr;
		if (mailserver) {
			if (frequency < progdefaults.ServerCarrier - progdefaults.ServerAFCrange)
				frequency = progdefaults.ServerCarrier - progdefaults.ServerAFCrange;
			if (frequency > progdefaults.ServerCarrier + progdefaults.ServerAFCrange)
				frequency = progdefaults.ServerCarrier + progdefaults.ServerAFCrange;
		}
		set_freq (frequency);
	}
	if (acquire) acquire--;
}

void psk::afc()
{
	if (!progStatus.afconoff)
		return;
	if (dcd == true || acquire)
		phaseafc();
}


void psk::rx_symbol(cmplx symbol, int car)
{
	int n;
	unsigned char softbit = 0;
	double softangle;
	double softamp;
	double sigamp = norm(symbol);

	static double averageamp;

	phase = arg ( conj(prevsymbol[car]) * symbol );
	prevsymbol[car] = symbol;

	/// align the RX constellation to the TX constellation, for Non-FEC modes
	if (_disablefec && (_16psk || _8psk || _xpsk )) phase -= M_PI;

	if (phase < 0) phase += TWOPI;

	if (_qpsk) {
		n = 4;
		bits = ((int) (phase / M_PI_2 + 0.5)) & (n-1);
	} else if (_xpsk) {
		n = 4;
		bits = ((int) (phase / M_PI_2)) & (n-1);
	} else if (_8psk) {
		n = 8;
		bits = ((int) (phase / (M_PI/4.0) + 0.5)) & (n-1);
	} else if (_16psk) {
		n = 16;
		bits = ((int) (phase / (M_PI/8.0) + 0.5)) & (n-1);
	} else { // bpsk and pskr
		n = 2;
		bits = (((int) (phase / M_PI + 0.5)) & (n-1) ) << 1;
		// hard decode if needed
		// softbit = (bits & 2) ? 0 : 255;
		// reversed as we normally pass "!bits" when hard decoding
		averageamp = decayavg(averageamp, sigamp, SQLDECAY);
		if (sigamp > 0 && averageamp > 0) {
			if (sigamp > averageamp) {
				softamp = clamp( sqrt(sigamp / averageamp), 1.0, 1e6);
			} else {
				softamp = clamp( sqrt(averageamp / sigamp), 1.0, 1e6);
			}
		} else {
			softamp = 2; // arbritary number (50% impact)
		}
		// Compute values between -128 and +127 for phase value only
		double alpha = phase / M_PI;
		if (alpha > 1.0) alpha = 2.0 - alpha;
		softangle = 127.0 - 255.0 * alpha;
		softbit = (unsigned char) ((softangle / ( 1.0 + softamp / 2.0)) + 128);
	}

	// simple low pass filter for quality of signal
	double decay = SQLDECAY;
	double attack = SQLDECAY;
	double cval = cos(n*phase);
	double sval = sin(n*phase);

	if (_8psk) {
		attack *= 2;
		decay *= 4;
	}

	if (_pskr) {
		decay *= 10;
		quality = cmplx(
			decayavg(quality.real(), cval, decay),
			decayavg(quality.imag(), sval, decay));
	} else
		quality = cmplx(
			decayavg(quality.real(), cval, cval > quality.real() ? attack : decay),
			decayavg(quality.imag(), sval, sval > quality.real() ? attack : decay));

	metric = 100.0 * norm(quality);
	if (_pskr && (averageamp < 3e-5)) metric = 0;

	if (progdefaults.Pskmails2nreport && (mailserver || mailclient)) {
		//s2n reporting: rescale depending on mode, clip after scaling
		if (_pskr)
			s2n_metric = metric * 1.5 + 8;
		else
			s2n_metric = metric;
		s2n_metric = CLAMP(s2n_metric, 0.0, 100.0);
	}

	// FEC: adjust squelch for extra sensitivity.
	// Otherwise we miss good characters
	// ***********************************************************
	// **** DHF still needed with attack/decay filtering?
	// ***********************************************************
	//	if (_pskr) {
	//		metric = metric * 4;
	//	}
	//	else if ( (_xpsk || _8psk || _16psk) && !_disablefec) {
	//		metric *= 2 * symbits; /// @TODO scale the metric with the psk constellation density
	//	}

	if (metric > 100)
		metric = 100;

	afcmetric = decayavg(afcmetric, norm(quality), 50);

	dcdshreg = ( dcdshreg << (symbits+1) ) | bits;

	int set_dcdON = -1; // 1 sets DCD on ; 0 sets DCD off ; -1 does neither (no-op)
	imdValid = false;
	//printf("\n%.8X", dcdshreg);
	switch (dcdshreg) {

			// bpsk DCD on
		case 0xAAAAAAAA:
			if ( _xpsk || _8psk || _16psk) break;
			if (_pskr) break;
			set_dcdON = 1;
			break;

			// pskr DCD on
		case 0x0A0A0A0A:
			if ( _xpsk || _8psk || _16psk) break;
			if (_qpsk) break;
			if (!_pskr) break;
			set_dcdON = 1;
			break;

			// 8psk DCD on (FEC enabled, with Gray-mapped constellation)
		case 0x25252525: // UN-punctured
			if (_pskr || _xpsk || _16psk) break;
			if (!_8psk) break;
			if (_disablefec) break;
			set_dcdON = 1;
			break;
		case 0x22222222: // punctured @ 2/3 rate
			if (_pskr || _xpsk || _16psk) break;
			if (!_8psk) break;
			if (_disablefec) break;
			set_dcdON = 1;
			break;

		case 0x92492492:	// xpsk DCD off (with FEC disabled)
			if (_pskr) break;
			if (_qpsk) break;
			if (!_xpsk) break;
			if (!_disablefec) break;
			set_dcdON = 0;
			break;

		case 0x10842108:	// 16psk DCD off (with FEC disabled)
			if (_pskr) break;
			if (!_16psk) break;
			if (!_disablefec) break;
			set_dcdON = 0;
			break;

		case 0x44444444:	// 8psk DCD off (with FEC disabled)
			if (!_8psk) break;
			if (!_disablefec) break;
			set_dcdON = 0;
			break;
		
		case 0x10410410:	// xpsk DCD on (with FEC enabled)
			if (_pskr) break;
			if (_qpsk) break;
			if (_8psk) break;
			if (_16psk) break;
			if (!_xpsk) break;
			if (_disablefec) break;
			set_dcdON = 1;
			break;
 
		case 0x00000000:	// bpsk DCD off.  x,8,16psk DCD on (with FEC disabled).
			if (_pskr) break;
			if (_xpsk || _8psk || _16psk) {
				if (!_disablefec) break;
				set_dcdON = 1;
				break;
			}
			set_dcdON = 0;
			break;

		default:
			if (metric > progStatus.sldrSquelchValue || progStatus.sqlonoff == false) {
				dcd = true;
			} else {
				dcd = false;
			}
	}

	if ( 1 == set_dcdON ) {
		dcd = true;
		acquire = 0;
		quality = cmplx (1.0, 0.0);
		imdValid = true;
		if (progdefaults.Pskmails2nreport && (mailserver || mailclient))
			s2n_sum = s2n_sum2 = s2n_ncount = 0.0;
		//printf("\n DCD ON!!");
	} else if ( 0 == set_dcdON ){
		dcd = false;
		acquire = 0;
		quality = cmplx (0.0, 0.0);
		//printf("\n DCD OFF!!!!!!!!!");
	}

	if (_pskr) {
		rx_pskr(softbit);
		set_phase(phase, norm(quality), dcd);

	} else if (dcd == true) {

		set_phase(phase, norm(quality), dcd);

		if (!_disablefec && (_16psk || _8psk || _xpsk) ) {
			int bitmask = 1;
			unsigned char xsoftsymbols[symbits];

			//printf("\n");
			if ( (_puncturing && _16psk) ) rx_pskr(128); // 16psk: recover punctured low bit

			// Soft-decode of Gray-mapped 8psk
			if (_8psk) {
				bool softpuncture = false;
				static double lastphasequality=0;
				double phasequality = fabs(cos( n/2 * phase));
				phasequality = (phasequality + lastphasequality) / 2; // Differential modem: average probabilities between current and previous symbols
				lastphasequality = phasequality;
				int soft_qualityerror = static_cast<int>(128 - (128 * phasequality)) ;
				
				if (soft_qualityerror > 255-25) // Prevent soft-bit wrap-around (crossing of value 128)
					softpuncture = true;
				else if (soft_qualityerror < 128/3) // First 1/3 of phase delta is considered a perfect signal
					soft_qualityerror = 0;
				else if (soft_qualityerror > 128 - (128/8) ) // Last 1/8 of phase delta triggers a puncture
					softpuncture = true;
				else
					soft_qualityerror /= 2; // Scale the FEC error to prevent premature cutoff 
			

				if (softpuncture) {
					for(int i=0; i<symbits; i++) rx_pskr(128);
				} else {
					int bitindex = static_cast<int>(bits);
					for(int i=symbits-1; i>=0; i--) { // Use predefined Gray-mapped softbits for soft-decoding
						if (graymapped_8psk_softbits[bitindex][i] > 128) // Soft-One
							rx_pskr( (graymapped_8psk_softbits[bitindex][i]) - soft_qualityerror );
						else // Soft-Zero
							rx_pskr( (graymapped_8psk_softbits[bitindex][i]) + soft_qualityerror  );
					} 
				}

			} else {
				//Hard Decode Section
				for(int i=0; i<symbits; i++) { // Hard decode symbits into soft-symbols
					xsoftsymbols[i] = (bits & bitmask) ? 255 : 0 ;
					//printf(" %.3u ", xsoftsymbols[i]);
					rx_pskr(xsoftsymbols[i]); // Feed to the PSKR FEC decoder, one bit at a time.
					bitmask = bitmask << 1;
				}
			}
			if (_puncturing) rx_pskr(128); // x/8/16psk: Recover punctured high bit

		} else if (_16psk || _8psk || _xpsk) {
			// Decode symbol one bit at a time
			int bitmask = 1;
			for (int i = 0; i < symbits; i++) {
				rx_bit( ((bits) & bitmask) );
				bitmask = bitmask << 1;
			}

		} else if (_qpsk)
			rx_qpsk(bits);

		else
			rx_bit(!bits); //default to BPSK
	}
}

void psk::signalquality()
{

	if (m_Energy[1])
		snratio = snfilt->run(m_Energy[0]/m_Energy[1]);
	else
		snratio = snfilt->run(1.0);

	if (m_Energy[0] && imdValid)
		imdratio = imdfilt->run(m_Energy[2]/m_Energy[0]);
	else
		imdratio = imdfilt->run(0.001);

}

void psk::update_syncscope()
{
	static char msg1[16];
	static char msg2[16];

	display_metric(metric);

	memset(msg1, 0, sizeof(msg1));
	memset(msg2, 0, sizeof(msg2));

	s2n = 10.0*log10( snratio );
	snprintf(msg1, sizeof(msg1)-1, "s/n %2d dB", (int)(floor(s2n)));

	imd = 10.0*log10( imdratio );
	snprintf(msg2, sizeof(msg2)-1, "imd %3d dB", (int)(floor(imd)));

	if (imdValid) {
		put_Status1(msg1, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
		put_Status2(msg2, progdefaults.StatusTimeout, progdefaults.StatusDim ? STATUS_DIM : STATUS_CLEAR);
	}
}

char bitstatus[100];

int psk::rx_process(const double *buf, int len)
{
	double delta[MAX_CARRIERS], frequencies[MAX_CARRIERS];
	cmplx z, z2[MAX_CARRIERS];
	bool can_rx_symbol = false;

	if (mode >= MODE_PSK31 && mode <= MODE_PSK125) {
		if (!progdefaults.report_when_visible ||
			dlgViewer->visible() || progStatus.show_channels )
			if (pskviewer && !bHistory) pskviewer->rx_process(buf, len);
		if (evalpsk)
			evalpsk->sigdensity();
	}

	frequencies[0] = frequency + ((-1 * numcarriers) + 1) * inter_carrier / 2;
	delta[0] = TWOPI * frequencies[0] / samplerate;
	for (int car = 1; car < numcarriers; car++) {
		frequencies[car] = frequencies[car - 1] + inter_carrier;
		delta[car] = TWOPI * frequencies[car] / samplerate;
	}

	while (len-- > 0) {

		for (int car = 0; car < numcarriers; car++) {

			// Mix with the internal NCO
			z = cmplx ( *buf * cos(phaseacc[car]), *buf * sin(phaseacc[car]) );

// if we re-enable multi-carrier vestigial carrier
//			if (vestigial && car == 0) vestigial_sfft->run(z, sfft_bins, 1);
			if (vestigial && progdefaults.pskpilot) vestigial_sfft->run(z, sfft_bins, 1);

			phaseacc[car] += delta[car];
			if (phaseacc[car] > TWOPI) phaseacc[car] -= TWOPI;

			// Filter and downsample
			// by 16 (psk31, qpsk31)
			// by  8 (psk63, qpsk63)
			// by  4 (psk125, qpsk125)
			// by  2 (psk250, qpsk250)
			// by  1 (psk500, qpsk500) = no down sampling
			// first filter
			if (fir1[car]->run( z, z )) { // fir1 returns true every Nth sample
										  // final filter
				fir2[car]->run( z, z2[car] ); // fir2 returns value on every sample

				//On last carrier processing
				if (car == numcarriers - 1) {

					calcSN_IMD(z); //JD OR all carriers together check logic???

	/**
	* This is the symbol timing recovery mechanism.  After the demodulated
	* signal is processed by the matched filters, the signal lobes are
	* expected to have been modified to a fairly symmetric shape.  The
	* magnitude of the samples are taken, thus rectifying the signal to
	* positive values. "bitclk" is a counter that is very close in rate to
	* (samples / symbol).  Its purpose is to repeatedly "draw" one symbol
	* waveform in the syncbuf array, according to its amplitude (not phase).
	*/

					int idx = (int) bitclk;
					double sum = 0.0;
					double ampsum = 0.0;
					for (int ii = 0; ii < numcarriers; ii++) {
						sum += abs(z2[ii])/numcarriers;
					}
					//			syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * z2[car].mag();
					syncbuf[idx] = 0.8 * syncbuf[idx] + 0.2 * sum;
					sum = 0.0;

					double bitsteps = (symbollen >= 16 ? 16 : symbollen);
					int symsteps = (int) (bitsteps / 2);

	/**
	* Here we sum up the difference between each sample's magnitude in the
	* lower half of the array with its counterpart on the upper half of the
	* array, or the other side of the waveform.  Each pair's difference is
	* divided by their sum, scaling it so that the signal amplitude does not
	* affect the result.  When the differences are summed, it gives an
	* indication of which side is larger than the other.
	*/

					for (int i = 0; i < symsteps; i++) {
						sum += (syncbuf[i] - syncbuf[i+symsteps]);
						ampsum += (syncbuf[i] + syncbuf[i+symsteps]);
					}
					// added correction as per PocketDigi
					sum = (ampsum == 0 ? 0 : sum / ampsum);

	/**
	* If the lower side is larger (meaning that the waveform is shifted in that
	* direction), then the sum is negative, and bitclk needs to be adjusted to
	* be a little faster, so that the next drawing of the waveform in syncbuf
	* will be shifted right. Conversely, if the sum is positive, then it needs
	* to slow down bitclk so that the waveform is shifted left.  Thus the
	* error is subtracted from bitclk, rather than added.  The goal is to
	* get the error as close to zero as possible, so that the receiver is
	* exactly synced with the transmitter and the waveform is exactly in
	* the middle of syncbuf.
	*/

					//			bitclk -= sum / 5.0;
					bitclk -= sum / (5.0 * 16 / bitsteps);
					bitclk += 1;

	/**
	* When bitclock reaches the end of the buffer, then a complete waveform
	* has been received.  It is time to output the current sample and wrap
	* around to the next cycle.
	*
	* There is a complete symbol waveform in syncbuf, so that each
	* sample[0..N/2-1] is very close in amplitude with the corresponding
	* sample in [N/2..N-1].
	*
	*     |            ********                       ********            |
	*     |        ****        ****               ****        ****        |
	*     |     ***                ***         ***                ***     |
	*     |   **                      **     **                      **   |
	*     |  *                          *   *                          *  |
	*     | *                            * *                            * |
	*     |*                              *                              *|
	*     |_______________________________________________________________|
	*     0                              N/2                             N-1
	*
	*     === or some variation of it .... ===
	*
	*     |****                       ********                       *****|
	*     |    ****               ****        ****               ****     |
	*     |        ***         ***                ***         ***         |
	*     |           **     **                      **     **            |
	*     |             *   *                          *   *              |
	*     |              * *                            * *               |
	*     |               *                              *                |
	*     |_______________________________________________________________|
	*     0                              N/2                             N-1
	*
	* A	t the end of this cycle, bitclk is pointing at a sample which will
	* have the maximum phase difference, if any, from the previous symbol's
	* phase.
	*
	*/

					if (bitclk < 0) bitclk += bitsteps;
					if (bitclk >= bitsteps) {
						bitclk -= bitsteps;
						can_rx_symbol = true;
						update_syncscope();
						afc();
					}
				}

			}
		}
		if (can_rx_symbol) {
			for (int car = 0; car < numcarriers; car++) {
				rx_symbol(z2[car], car);
			}
			can_rx_symbol = false;
		}
		buf++;
	}

	if (sigsearch)
		findsignal();
	else if (mailserver) {
		if (waitcount > 0) {
			--waitcount;
			if (waitcount == 0) {
				if (progdefaults.PSKmailSweetSpot) {
					frequency = progdefaults.PSKsweetspot;
					set_freq(frequency);
				}
				sigsearch = SIGSEARCH;
			}
		}
		else if ( E1/ E2 <= 1.0) {
			waitcount = 8;
			sigsearch = 0;
		}
	}
	return 0;
}

//=====================================================================
// transmit processes
//=====================================================================

#define SVP_MASK 0xF
#define SVP_COUNT (SVP_MASK + 1)

static cmplx sym_vec_pos[SVP_COUNT] = {
	cmplx (-1.0, 0.0),        // 180 degrees
	cmplx (-0.9238, -0.3826), // 202.5 degrees
	cmplx (-0.7071, -0.7071), // 225 degrees
	cmplx (-0.3826, -0.9238), // 247.5 degrees
	cmplx (0.0, -1.0),        // 270 degrees
	cmplx (0.3826, -0.9238),  // 292.5 degrees
	cmplx (0.7071, -0.7071),  // 315 degrees
	cmplx (0.9238, -0.3826),  // 337.5 degrees
	cmplx (1.0, 0.0),         // 0 degrees
	cmplx (0.9238, 0.3826),   // 22.5 degrees
	cmplx (0.7071, 0.7071),   // 45 degrees
	cmplx (0.3826, 0.9238),   // 67.5 degrees
	cmplx (0.0, 1.0),         // 90 degrees
	cmplx (-0.3826, 0.9238),  // 112.5 degrees
	cmplx (-0.7071, 0.7071),  // 135 degrees
	cmplx (-0.9238, 0.3826)   // 157.5 degrees
};

void psk::tx_carriers()
{
	double delta[MAX_CARRIERS];
	double	ival, qval, shapeA, shapeB;
	cmplx symbol;
	double	frequencies[MAX_CARRIERS];

	//Process all carrier's symbols, then submit to sound card
	accumulated_bits = 0; //reset
	frequencies[0] = get_txfreq_woffset() + ((-1 * numcarriers) + 1) * inter_carrier / 2;
	delta[0] = TWOPI * frequencies[0] / samplerate;
	for (int car = 1; car < symbols; car++) {
		frequencies[car] = frequencies[car - 1] + inter_carrier;
		delta[car] = TWOPI * frequencies[car] / samplerate;
	}

	int sym;
	for (int car = 0; car < symbols; car++) {
		sym = txsymbols[car];

		if (_qpsk && !reverse)
			sym = (4 - sym) & 3;

		if (_8psk && !_disablefec) // Use Gray-mapped 8psk constellation
			symbol = prevsymbol[car] * graymapped_8psk_pos[(sym & 7)];	// complex multiplication

		else { // Map the incoming symbols to the underlying 16psk constellation.
			if (_xpsk) sym = sym * 4 + 2; // Give it the "X" constellation shape
			else if (_8psk) sym *= 2; // Map 8psk to 16psk
			else sym *= 4; // For BPSK and QPSK
			symbol = prevsymbol[car] * sym_vec_pos[(sym & SVP_MASK)];	// complex multiplication
		}


		for (int i = 0; i < symbollen; i++) {

			shapeA = tx_shape[i];
			shapeB = (1.0 - shapeA);

			ival = shapeA * prevsymbol[car].real() + shapeB * symbol.real();
			qval = shapeA * prevsymbol[car].imag() + shapeB * symbol.imag();

			if (car != 0) {
				outbuf[i] += (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car])) / numcarriers;
			} else {
				outbuf[i] = (ival * cos(phaseacc[car]) + qval * sin(phaseacc[car])) / numcarriers;
			}
			if (maxamp < fabs(outbuf[i]))
				maxamp = fabs(outbuf[i]);

			phaseacc[car] += delta[car];
			if (phaseacc[car] > TWOPI) phaseacc[car] -= TWOPI;
		}

		prevsymbol[car] = symbol;
	}

	if (vestigial && progdefaults.pskpilot) {
		double dvp = TWOPI * (frequencies[0] - sc_bw) / samplerate;
		double amp = pow(10, progdefaults.pilot_power / 20.0) * maxamp;
		for (int i = 0; i < symbollen; i++) {
			outbuf[i] += amp * cos(vphase);
			outbuf[i] /= (1 + amp);
			vphase += dvp;
			if (vphase > TWOPI) vphase -= TWOPI;
		}
	}

	if (maxamp) {
		for (int i = 0; i < symbollen; i++) outbuf[i] *= (0.9 * maxamp);
	}

	ModulateXmtr(outbuf, symbollen);
}

void psk::tx_symbol(int sym)
{
	acc_symbols++;
	txsymbols[symbols] = sym;
	if (++symbols < numcarriers) {
		return;
	}
	tx_carriers();
	symbols = 0; //reset
}

void psk::tx_bit(int bit)
{
	unsigned int sym;
	static int bitcount=0;
	static int xpsk_sym=0;

	// qpsk transmission
	if (_qpsk) {
		sym = enc->encode(bit);
		sym = sym & 3;//JD just to make sure
		tx_symbol(sym);
		// pskr (fec + interleaver) transmission
	} else if (_pskr) {
		// Encode into two bits
		bitshreg = enc->encode(bit);
		// pass through interleaver
		if (mode != MODE_PSK63F) Txinlv->bits(&bitshreg);
		// Send low bit first. tx_symbol expects 0 or 2 for BPSK
		sym = (bitshreg & 1) << 1;
		tx_symbol(sym);
		sym = bitshreg & 2;
		tx_symbol(sym);
	} else if (_16psk || _8psk || _xpsk) {
		if (_disablefec) {
			//Accumulate tx bits until the correct number for symbol-size is reached
			xpsk_sym |= bit << bitcount++ ;
			if (bitcount == symbits) {
				tx_symbol(xpsk_sym);
				xpsk_sym = bitcount = 0;
			}
		} else
			tx_xpsk(bit);
		// else normal bpsk transmission
	} else {
		sym = bit << 1;
		tx_symbol(sym);
	}
}

void psk::tx_xpsk(int bit)
{
	static int bitcount = 0;
	static unsigned int xpsk_sym = 0;
	int fecbits = 0;

	// If invalid value of bitcount, reset to 0
	if (_puncturing || _xpsk || _16psk)
		if ( (bitcount & 0x1) )
			bitcount = 0;

	//printf("\n\n bit: %d", bit);

	// Pass one bit and return two bits
	bitshreg = enc->encode(bit);
	// Interleave
	Txinlv->bits(&bitshreg); // Bit-interleave
	fecbits = bitshreg;


	/// DEBUG
	/*
	 * 	static bool flip;
	 if (flip) {
	 flip = false;
	 fecbits = 0;
	 } else {
	 flip = true;
	 fecbits = 3;
	 }
	 */

	//printf("\nfecbits: %u", fecbits);
	//printf("\nbitcount: %d", bitcount);

	if (_xpsk) { // 2 bits-per-symbol. Transmit every call
		xpsk_sym = static_cast<unsigned int>(fecbits);
		tx_symbol(xpsk_sym);
		return;
	}

	// DEBUG
	/*
	 if (_8psk) {
	 tx_symbol(0);
	 tx_symbol(7);
	 return;
	 }
	 */

	// DEBUG, send a known pattern of symbols / bits
	/*
	 * 	static int counter = 0;
	 counter++;
	 if ( counter > 7 ) counter = 0;
	 tx_symbol(1);
	 return;
	 */

	/*
	 else if (mode == MODE_8PSK ???) { // Puncture @ 5/6 rate | tx 3bits/symbol (8psk)
	 // Collect up to 8 bits
	 if ( x_bitcount < 8 ) {
	 x_xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << x_bitcount ;
	 x_xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << x_bitcount ;
	 x_bitcount += 2;
	 return;

	 // When 10 bits are buffered,
	 //	drop 4 bits then transmit 6 bits (2-symbols)
	 } else {
	 x_xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << x_bitcount ;
	 x_xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << x_bitcount ;
	 tx_symbol( (x_xpsk_sym & 14) >> 1);
	 tx_symbol( (x_xpsk_sym & 448) >> 6);
	 x_xpsk_sym = x_bitcount = 0;
	 return;
	 }
	 }
	 */

	else if (_8psk && _puncturing) { // @ 2/3 rate

		if ( 0 == bitcount) {
			xpsk_sym = static_cast<unsigned int>(fecbits);
			bitcount = 2;
			return;

		} else if ( 2 == bitcount ) {
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 2 ;
			/// Puncture -> //xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << 2 ;
			tx_symbol(xpsk_sym & 7);
			xpsk_sym = bitcount = 0;
			return;
		}
	}


	else if (_8psk) { // 3 bits-per-symbol. Accumulate then tx.

		if ( 0 == bitcount ) { // Empty xpsk_sym buffer: add 2 bits and return
							   //printf("\nxpsk_sym|preadd: %u", xpsk_sym);
			xpsk_sym = static_cast<unsigned int>(fecbits);
			//printf("\nxpsk_sym|postadd: %u", xpsk_sym);
			bitcount = 2;
			return ;

		} else if ( 1 == bitcount ) { // xpsk_sym buffer with one bit: add 2 bits then tx and clear
									  //xpsk_sym <<= 2; // shift left 2 bits

			//printf("\nxpsk_sym|preadd: %u", xpsk_sym);
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 1 ;
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << 1 ;
			//printf("\nxpsk_sym|postadd: %u", xpsk_sym);

			//printf("\nxpsk_sym|postinlv: %u", xpsk_sym);
			tx_symbol(xpsk_sym);
			xpsk_sym = bitcount = 0;
			return;

		} else if ( 2 == bitcount ) { // xpsk_sym buffer with 2 bits: add 1 then tx and save next bit
									  //printf("\nxpsk_sym|preadd: %u", xpsk_sym);
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 2 ;
			//printf("\nxpsk_sym|postadd: %u", xpsk_sym);

			//printf("\nxpsk_sym|postinlv: %u", xpsk_sym);

			tx_symbol(xpsk_sym);
			xpsk_sym = bitcount = 0;

			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) >> 1 ;
			bitcount = 1;
			return;
		}
	}

	else if (_puncturing && _16psk) { // @ 3/4 Rate

		if ( 0 == bitcount) {
			xpsk_sym = static_cast<unsigned int>(fecbits);
			bitcount = 2;
			return;

		} else if ( 2 == bitcount ) {
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 2 ;
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << 2 ;
			bitcount = 4;
			return;
		} else if ( 4 == bitcount ) {
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 4 ;
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << 4 ;
			xpsk_sym >>= 1; // Shift right to drop the lowest bit
			xpsk_sym &= 15; // Drop the highest bit
			tx_symbol(xpsk_sym);
			xpsk_sym = bitcount = 0;
			return;
		}
	}

	else if (_16psk) { // 4 bits-per-symbol. Transmit every-other run.

		if ( 0 == bitcount) {
			xpsk_sym = static_cast<unsigned int>(fecbits);
			bitcount = 2;
			return;

		} else if ( 2 == bitcount ) {
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 1) << 2 ;
			xpsk_sym |= (static_cast<unsigned int>(fecbits) & 2) << 2 ;
			//Txinlv->bits(&xpsk_sym);
			tx_symbol(xpsk_sym & 7);
			xpsk_sym = bitcount = 0;
			return;
		}
	}
}


unsigned char ch;
void psk::tx_char(unsigned char c)
{
	ch = c;
	const char *code;
	char_symbols = acc_symbols;
	if (_pskr || _xpsk || _8psk || _16psk) {
		//		acc_symbols = 0;
		// ARQ varicode instead of MFSK for PSK63FEC
		code = varienc(c);
	} else {
		code = psk_varicode_encode(c);
	}
	while (*code) {
		tx_bit((*code - '0'));
		code++;
	}

	// Insert PSK varicode character-delimiting bits
	if (! _pskr && !_xpsk && !_8psk && !_16psk) {
		tx_bit(0);
		tx_bit(0);
	}
	char_symbols = acc_symbols - char_symbols;
}


void psk::tx_flush()
{
	if (_pskr) {
		ovhd_symbols = ((numcarriers - symbols) % numcarriers);
		//VK2ETA replace with a more effective flushing sequence (avoids cutting the last characters in low s/n)
		for (int i = 0; i < ovhd_symbols/2; i++) tx_bit(0);

		for (int i = 0; i < dcdbits / 2; i++) {
			tx_bit(1);
			tx_bit(1);
		}
		// QPSK - flush the encoder
	} else if (_qpsk) {
		for (int i = 0; i < dcdbits; i++)
			tx_bit(0);
		// FEC : replace unmodulated carrier by an encoded sequence of zeros
	} else if (!_disablefec && (_xpsk || _8psk || _16psk) ) {
		for (int i = 0; i < flushlength; i++) {
			tx_char(0);   // <NUL>
		}
		// FEC disabled: use unmodulated carrier
	} else if (_disablefec && ( _xpsk || _8psk || _16psk) ) {
		for (int i=0; i<symbits; i++) {
			tx_char(0); // Send <NUL> to clear bit accumulators on both Tx and Rx ends.
		}
		int symbol;
		if (_16psk) symbol = 8;
		else if (_8psk) symbol = 4;
		else symbol = 2;
		for (int i = 0; i < dcdbits; i++)
			tx_symbol(symbol); // 0 degrees
							   // Standard BPSK postamble
							   // DCD off sequence (unmodulated carrier)
	} else {
		for (int i = 0; i < dcdbits; i++)
			tx_symbol(2); // 0 degrees
	}
}

// Necessary to clear the interleaver before we start sending
void psk::clearbits()
{
	bitshreg = 0;
	enc->init();
	Txinlv->flush();
}

int psk::tx_process()
{
	int c;

	if (preamble > 0) {
		if (_pskr || ((_xpsk || _8psk || _16psk) && !_disablefec) ) {
			if (startpreamble == true) {
				if (mode != MODE_PSK63F) clearbits();
				startpreamble = false;
			}
			// FEC prep the encoder with one/zero sequences of bits
			preamble--;
			preamble--;
			tx_bit(1);
			tx_bit(0);
			// FEC: Mark start of first character with a double zero
			// to ensure sync at end of preamble
			if (preamble == 0) {
				while (acc_symbols % numcarriers) tx_bit(0);
				tx_char(0); // <NUL>
			}
			return 0;
		} else {
			//JD for QPSK500R
			//			if (mode == MODE_QPSK500) clearbits();
			// Standard BPSK/QPSK preamble
			preamble--;
			tx_symbol(0);   // send phase reversals
			return 0;
		}
	}

	c = get_tx_char();

	if (c == GET_TX_CHAR_ETX || stopflag) {
		tx_flush();
		stopflag = false;
		cwid();

		char_samples = char_symbols * symbollen / numcarriers;
		xmt_samples  = acc_symbols * symbollen / numcarriers;
		ovhd_samples = (acc_symbols - char_symbols - ovhd_symbols) * symbollen / numcarriers;

		return -1;   // we're done
	}

	if (c == GET_TX_CHAR_NODATA) {
		if (_pskr || _xpsk || _8psk || _16psk) {
			// MFSK varicode instead of psk
			tx_char(0);   // <NUL>
			tx_bit(1);
			// extended zero bit stream
			for (int i = 0; i < 32; i++)
				tx_bit(0);
		} else {
			tx_bit(0);
		}
	} else {
		tx_char(c);
		put_echo_char(c);
	}
	return 0;
}

//============================================================================
// psk signal evaluation
// using Goertzel IIR filter
// derived from pskcore by Moe Wheatley, AE4JY
//============================================================================

void psk::initSN_IMD()
{
	for(int i = 0; i < NUM_FILTERS; i++)
	{
		I1[i] = I2[i] = Q1[i] = Q2[i] = 0.0;
		m_Energy[i] = 0.0;
	}
	m_NCount = 0;

	COEF[0] = 2.0 * cos(TWOPI * 9 / GOERTZEL);
	COEF[1] = 2.0 * cos(TWOPI * 18 / GOERTZEL);
	COEF[2] = 2.0 * cos(TWOPI  * 27 / GOERTZEL);
}

void psk::resetSN_IMD()
{
	for(int i = 0; i < NUM_FILTERS; i++) {
		I1[i] = I2[i] = Q1[i] = Q2[i] = 0.0;
	}
	m_NCount = 0;
}

//============================================================================
//  This routine calculates the energy in the frequency bands of
//   carrier=F0(15.625), noise=F1(31.25), and
//   3rd order product=F2(46.875)
//  It is called with cmplx data samples at 500 Hz.
//============================================================================

void psk::calcSN_IMD(cmplx z)
{
	int i;
	double tempI = 0, tempQ = 0;

	for(i = 0; i < NUM_FILTERS; i++) {
		tempI = I1[i];
		tempQ = Q1[i];
		I1[i] = I1[i] * COEF[i]- I2[i] + z.real();
		Q1[i] = Q1[i] * COEF[i]- Q2[i] + z.imag();
		I2[i] = tempI;
		Q2[i] = tempQ;
	}

	if( ++m_NCount >= GOERTZEL ) {
		m_NCount = 0;
		for(i = 0; i < NUM_FILTERS; i++) {
			m_Energy[i] =   I1[i]*I1[i] + Q1[i]*Q1[i]
			+ I2[i]*I2[i] + Q2[i]*Q2[i]
			- I1[i]*I2[i]*COEF[i]
			- Q1[i]*Q2[i]*COEF[i];
			I1[i] = I2[i] = Q1[i] = Q2[i] = 0.0;
		}
		signalquality();
	}
}
