// MyMonModulesPocsag512.cpp: Implementierung der Klasse CMyMonModulesPocsag512. // ////////////////////////////////////////////////////////////////////// #include "MonitorModulePocsag512.h" #ifdef _DEBUG #undef THIS_FILE //static char THIS_FILE[]=__FILE__; #endif #define BAUD 512 //#define POC512SUBSAMP 1 // es wird nur jedes x-te Sample ausgewertet (Auch PLLFaktor und Detektorbreite anpassen) #define SUBSAMP 1 // max. Prozent-�nderungen Frq.-�nderung am PLL // und Schmitt-Trigger // und Breite der Rechtecke des Flankendetektors // 1.0 ,0 ,7 - ganz gut // 0.3 , 0.0001 , 7 - gut // 0.1 , 0.0001 , 7 - ? // 0.15 , 0.0001, 3 - schaut gut aus #define PLLFaktor (0.25/100.0) #define SchmittTriggerLevel (0.0000) #define DETEKTOR_BREITE 5 // war SUBSAMP = 5 /* ---------------------------------------------------------------------- */ ////////////////////////////////////////////////////////////////////// // Konstruktion/Destruktion ////////////////////////////////////////////////////////////////////// MonitorModulePocsag512::MonitorModulePocsag512(int sampleRate,XMLNode *pConfig) { bool crccheck=getNodeBool(*pConfig,"crc-check",true) ; bool errorcorrection=getNodeBool(*pConfig,"ecc",false) ; int minpreambel=getNodeInt(*pConfig,"minpreambel",300) ; int maxerrors=getNodeInt(*pConfig,"maxerrors",10) ; int algorithmus=getNodeInt(*pConfig,"algorithm",1) ; FILE_LOG(logINFO) << "(1) sample - crc - ecc - minpreambel - maxerrors - algo:" << sampleRate << " - " << crccheck << " - " << errorcorrection << " - " << minpreambel << " - " << maxerrors << " - " << algorithmus ; MonitorModulePocsag512(sampleRate,1,0) ; /* MonitorModulePocsag512( sampleRate, crccheck == true ? 1:0 , errorcorrection== true ? 1:0, minpreambel, maxerrors, algorithmus); */ } MonitorModulePocsag512::MonitorModulePocsag512(int sampleRate, bool crccheck, bool errorcorrection, int minpreambel, int maxerrors, int algorithmus) { FILE_LOG(logINFO) << "(2) sample - crc - ecc - minpreambel - maxerrors - algo:" << sampleRate << " - " << crccheck << " - " << errorcorrection << " - " << minpreambel << " - " << maxerrors << " - " << algorithmus ; m_bErrorCorrection=errorcorrection ; MAX_RX_ERRORS=maxerrors ; PREAMBEL_MINLEN=minpreambel ; m_iAlgorithmus=algorithmus ; FILE_LOG(logINFO) << "Algorithmus:" << m_iAlgorithmus ; FREQ_SAMP=sampleRate ; SPHASEINC=(0x10000u * BAUD * SUBSAMP) / FREQ_SAMP ; SPHASEINC_BASE=(0x10000u * BAUD * SUBSAMP) / FREQ_SAMP ; FILE_LOG(logINFO) << "SPHASE_INC is:" << SPHASEINC_BASE ; m_lpszName="POC 512" ; m_fPLLFaktor=PLLFaktor ; // max. Prozent-�nderungen Frq.-�nderung am PLL m_fTrigger=SchmittTriggerLevel ; // debugging #ifdef POCDEBUG512 debugFile1 = fopen("_in.raw", "wb"); debugFile2 = fopen("_takt.raw", "wb"); debugFile3 = fopen("_trigger.raw", "wb"); debugFile4 = fopen("_pfd.raw", "wb"); #endif set_filters(1200,1800,BAUD); } MonitorModulePocsag512::~MonitorModulePocsag512() { #ifdef POCDEBUG512 fclose(debugFile1) ; fclose(debugFile2) ; fclose(debugFile3) ; fclose(debugFile4) ; #endif } void MonitorModulePocsag512::demod_se(float *buffer, int length) { double y ; if (subsamp) { int numfill = SUBSAMP - subsamp; if (length < numfill) { subsamp += length; return; } buffer += numfill; length -= numfill; subsamp = 0; } #ifdef POCDEBUG512 // Startwerte fwrite(buffer, sizeof(float), length,debugFile1); pBuffer1=fileBuffer1 ; pBuffer2=fileBuffer2 ; pBuffer3=fileBuffer3 ; bufferLen1=0 ; bufferLen2=0 ; bufferLen3=0 ; #endif 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; } ; } ; y=biq_lp(biq_lp( (lastbit==1? 1.0:-1.0) ,lp1_c,lp1_b),lp2_c,lp2_b); //dcd_shreg |= (lastbit==1 ? 1 : 0) ; lastbit= (y>0 ? 1:0) ; dcd_shreg |= (lastbit==1 ? 1 : 0) ; for (int ming=40;ming>0;ming--) { m_lastVal[ming] = m_lastVal[ming-1] ; } m_lastVal[0] = lastbit ; if ((m_lastVal[0] + m_lastVal[DETEKTOR_BREITE]) == 1 ) //if ( ((dcd_shreg >>9) &0x01) ^ (dcd_shreg & 0x01)) // Flankendetektor { Udiff=1 ; } else { Udiff=0 ; } // Udiff = Eingang zum PD // // PD ist ein Exor -> // SPHASE 0...0x8000 = positive Halbwelle (1) // SPHASE 0x8000...0x10000 = negative Halbwelle (0) // 0x8 ist die Hälfte von 0x10 -> Hexadezimal !! :) if (sphase <= 0x8000) { Uphase=1 ; } else { Uphase=0 ; } if (Udiff > lastUdiff) { // Flanke im Schmitt-Trigger (u1) if (sphase >0x8000) { Ud= (0x10000-sphase) ; } else { Ud = sphase ; } } #ifdef POCDEBUG512 *pBuffer1=Uphase*0.75 ; *pBuffer2=Udiff*0.75 ; *pBuffer3=(Ud*0.75)/0x8000 ; //*pBuffer3=m_LastFilterVal ; if ((rx_buff+1)->rx_sync) // inSync { *pBuffer2=Udiff*0.45+0.5 ; } pBuffer1++ ; pBuffer2++ ; pBuffer3++ ; bufferLen1++ ; bufferLen2++ ; bufferLen3++ ; #endif SPHASEINC=(unsigned int) (( (double) SPHASEINC_BASE) * (1.0 + ( m_fPLLFaktor*Ud)/0x8000 )) ; sphase += SPHASEINC ; lastUdiff = Udiff ; if ((sphase>=0x8000u) && (didBit==false)) { #ifdef POCDEBUG512 *(pBuffer2-1)=-0.3 - 0.3*lastbit ; #endif rxbit( lastbit ) ; didBit = true ; } if (sphase>=0x10000u) { // FILE_LOG(logINFO) << "sphase:" << sphase << " -> " << (sphase & (0xffff)) ; sphase = sphase & 0xffffu ; didBit = false ; } } #ifdef POCDEBUG512 fwrite(fileBuffer1, sizeof(float), bufferLen1,debugFile2); fwrite(fileBuffer2, sizeof(float), bufferLen2,debugFile3); fwrite(fileBuffer3, sizeof(float), bufferLen3,debugFile4); #endif subsamp = length; } // --------- old function ----------- void MonitorModulePocsag512::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; } // ********************************************************* // ** IIR Filter // ********************************************************* inline float MonitorModulePocsag512::biq_lp(float x, float *pcoef, float *buf) { float y; y =(*pcoef++)*(x+buf[0]+buf[0]+buf[1]); y+=(*pcoef++)*buf[2]; y+=(*pcoef)*buf[3]; buf[1]=buf[0]; buf[0]=x; buf[3]=buf[2]; buf[2]=y; return y; } inline float MonitorModulePocsag512::biq_bp(float x, float *pcoef, float *buf) { float y; y =(*pcoef++)*(x-buf[1]); y+=(*pcoef++)*buf[2]; y+=(*pcoef)*buf[3]; buf[1]=buf[0]; buf[0]=x; buf[3]=buf[2]; buf[2]=y; return y; } inline float MonitorModulePocsag512::biq_hp(float x, float *pcoef, float *buf) { float y; y =(*pcoef++)*(x-buf[0]-buf[0]+buf[1]); y+=(*pcoef++)*buf[2]; y+=(*pcoef)*buf[3]; buf[1]=buf[0]; buf[0]=x; buf[3]=buf[2]; buf[2]=y; return y; } void MonitorModulePocsag512::gen_coef(int tipo, float f0, float Q, float *pcoef) { float w0,a,d; w0=2.*M_PI*f0; //Prewharping w0=2.0*FREQ_SAMP*tan(w0/FREQ_SAMP/2.0); a=FREQ_SAMP/w0; d=4.*a*a +2.*a/Q +1.; switch(tipo){ case 0: (*pcoef++)=1.0/d; break; case 1: (*pcoef++)=2.*a/Q/d; break; case 2: (*pcoef++)=4.*a*a/d; break; } (*pcoef++)=(8.*a*a -2.)/d; (*pcoef++)=-(4.*a*a -2.*a/Q +1.)/d; } void MonitorModulePocsag512::set_filters(float f0, float f1, float dr) { gen_coef(1,f0,f0/dr/2.0,bp0_c); /* Space filter */ gen_coef(1,f1,f1/dr/2.0,bp1_c); /* Mark filter */ gen_coef(0,dr,0.5412,lp1_c); /* Low-Pass order-4 Butt. filter */ gen_coef(0,dr,1.3066,lp2_c); for (int i=0;i<4;i++) lp1_b[i]=lp2_b[i]=bp0_b[i]=bp1_b[i]=0.0; }