/* MyMonModulesPocsag1200.h
 *
 *      This file is part of MyMonitor
 *
 *		Copyright (C) 1996
 *          Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
 *
 *      Copyright (C) 1998-2002
 *          Markus Grohmann (markus_grohmann@gmx.de)
 *
 *      Copyright (c) 2002
 *          Stephan Effertz (info@stephan-effertz.de)
 *
 *
 *		(Demodulation parts taken from monitor (c) Markus Grohmann)
 *
 *      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; either version 2 of the License, or
 *      (at your option) any later version.
 *
 *      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 for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with this program; if not, write to the Free Software
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
// MyMonModulePocsag1200.cpp: Implementierung der Klasse MonitorModulePocsag1200.
//
//////////////////////////////////////////////////////////////////////


#include "MonitorModulePocsag1200.h"

#ifdef _DEBUG
#undef THIS_FILE
//static char THIS_FILE[]=__FILE__;
#endif

#define BAUD       1200
#define SUBSAMP    2
// SUBSAMP war 2
#define FILTLEN    1

#define GRENZWERT	0.3

//////////////////////////////////////////////////////////////////////
// Konstruktion/Destruktion
//////////////////////////////////////////////////////////////////////

MonitorModulePocsag1200::MonitorModulePocsag1200(XMLNode *pConfig)
{
	int sampleRate=22050 ;
	bool crccheck=getNodeBool(*pConfig,"crc-check",true) ;
	bool errorcorrection=getNodeBool(*pConfig,"ecc",false) ;
	int minpreambel=getNodeInt(*pConfig,"minpreambel",0) ;
	int maxerrors=getNodeInt(*pConfig,"maxerrors",0) ;
	int algorithmus=getNodeInt(*pConfig,"algorithm",0) ;
	MonitorModulePocsag1200(	sampleRate,
								crccheck,
								errorcorrection,
								minpreambel,
								maxerrors,
								algorithmus);

}

MonitorModulePocsag1200::MonitorModulePocsag1200(int sampleRate, bool crccheck, bool errorcorrection, int minpreambel, int maxerrors, int algorithmus)
{
	m_bErrorCorrection=errorcorrection ;
	// m_bCRCCheck=crccheck ;
	MAX_RX_ERRORS=maxerrors ;
	PREAMBEL_MINLEN=minpreambel ;
	m_iAlgorithmus=algorithmus ;

	FREQ_SAMP=sampleRate ;


	SPHASEINC=(0x10000u * BAUD * SUBSAMP) / FREQ_SAMP ;
	m_lpszName="POC 1200" ;
}

MonitorModulePocsag1200::~MonitorModulePocsag1200()
{

}

void MonitorModulePocsag1200::demod(float *buffer, int length)
{
	switch (m_iAlgorithmus)
	{
	case 0:
		demod_mg(buffer, length) ; // war demod_se ...
		break ;
	case 1:
	default:
		demod_mg(buffer, length) ;
	} ;
}

void MonitorModulePocsag1200::demod_se(float *buffer, int length)
{
	if (subsamp) {
		int numfill = SUBSAMP - subsamp;
		if (length < numfill) {
			subsamp += length;
			return;
		}
		buffer += numfill;
		length -= numfill;
		subsamp = 0;
	}


	for (; length >= SUBSAMP; length -= SUBSAMP, buffer += SUBSAMP) {
		dcd_shreg <<= 1;

		// Mit einem Schmitt-Trigger die Flanken ansteilen und Rauschen
		// Eliminieren
		//
		if (lastbit==0)
			{
				if ((*buffer)>m_fTrigger)
				{
					lastbit=1 ;
				} ;
			} else {
				if ( (*buffer) < -m_fTrigger)
				{
					lastbit=0 ;
				} ;
			} ;

		dcd_shreg |= lastbit==1 ? true : false ;

		//	check if transition
		if ((dcd_shreg ^ (dcd_shreg >> 1)) & 1) {
			if (sphase < (0x8000u - (SPHASEINC / 2)))
				sphase += SPHASEINC / 8;
			else
				sphase -= SPHASEINC / 8;
		}
		sphase += SPHASEINC;

		if (sphase >= 0x10000u) {
			sphase &= 0xffffu;
			rxbit(dcd_shreg & 1);
		}
	}
	subsamp = length;
}




// ------------------ old version -------------------------

void MonitorModulePocsag1200::demod_mg(float *buffer, int length)
{
	if (subsamp) {
		int numfill = SUBSAMP - subsamp;
		if (length < numfill) {
			subsamp += length;
			return;
		}
		buffer += numfill;
		length -= numfill;
		subsamp = 0;
	}
	for (; length >= SUBSAMP; length -= SUBSAMP, buffer += SUBSAMP) {
		dcd_shreg <<= 1;
		dcd_shreg |= ((*buffer) > 0);

		//	check if transition
		if ((dcd_shreg ^ (dcd_shreg >> 1)) & 1) {
			if (sphase < (0x8000u - (SPHASEINC / 2)))
				sphase += SPHASEINC / 8;
			else
				sphase -= SPHASEINC / 8;
		}
		sphase += SPHASEINC;

		if (sphase >= 0x10000u) {
			sphase &= 0xffffu;
			rxbit(dcd_shreg & 1);
		}
	}
	subsamp = length;
}
