Example #1
0
/* Receiver */
void CUtilizeFACData::ProcessDataInternal(CParameter& ReceiverParam)
{
	/* Do not use received FAC data in case of simulation */
	{
		bCRCOk = FACReceive.FACParam(pvecInputData, ReceiverParam);

		if (bCRCOk == TRUE)
		{
			PostWinMessage(MS_FAC_CRC, 0);
		}
		else
		{
			PostWinMessage(MS_FAC_CRC, 2);
		}
	}

	if (bCRCOk == FALSE)
	{
		/* If FAC CRC check failed we should increase the frame-counter 
		   manually. If only FAC data was corrupted, the others can still
		   decode if they have the right frame number. In case of simulation
		   no FAC data is used, we have to increase the counter here */
		ReceiverParam.iFrameIDReceiv++;

		if (ReceiverParam.iFrameIDReceiv == NUM_FRAMES_IN_SUPERFRAME)
			ReceiverParam.iFrameIDReceiv = 0;
	}
}
Example #2
0
void CSoundBase::run()
{
    // Set thread priority (The working thread should have a higher
    // priority than the GUI)
#ifdef _WIN32
    SetThreadPriority ( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL );
#else
/*
    // set the process to realtime privs, taken from
    // "http://www.gardena.net/benno/linux/audio" but does not seem to work,
    // maybe a problem with user rights
    struct sched_param schp;
    memset ( &schp, 0, sizeof ( schp ) );
    schp.sched_priority = sched_get_priority_max ( SCHED_FIFO );
    sched_setscheduler ( 0, SCHED_FIFO, &schp );
*/
#endif

    // main loop of working thread
    while ( bRun )
    {
        // get audio from sound card (blocking function)
        if ( Read ( vecsAudioSndCrdStereo ) )
        {
            PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_RED );
        }
        else
        {
            PostWinMessage ( MS_SOUND_IN, MUL_COL_LED_GREEN );
        }

        // process audio data
        (*fpProcessCallback) ( vecsAudioSndCrdStereo, pProcessCallbackArg );

        // play the new block
        if ( Write ( vecsAudioSndCrdStereo ) )
        {
            PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_RED );
        }
        else
        {
            PostWinMessage ( MS_SOUND_OUT, MUL_COL_LED_GREEN );
        }
    }
}
Example #3
0
/* Implementation *************************************************************/
void CSyncUsingPil::ProcessDataInternal(CParameter& ReceiverParam)
{
	int i;

	/**************************************************************************\
	* Frame synchronization detection										   *
	\**************************************************************************/
	_BOOLEAN bSymbolIDHasChanged = FALSE;

	if ((bSyncInput == FALSE) && (bAquisition == TRUE))
	{
#ifdef USE_DRM_FRAME_SYNC_IR_BASED
		/* DRM frame synchronization using impulse response ----------------- */
		/* We assume that the current received OFDM symbol is the first symbol
		   in a DRM frame and estimate the channel transfer function at the
		   pilot positions (the positions of pilots in the first OFDM symbol in
		   a DRM frame). Then we calculate an FFT to get the impulse response of
		   the channel. If the assumption was correct and this really was the
		   correct OFDM symbol, we will get something which looks like an
		   impulse response (contains peaks -> peak-to-average ratio is high).
		   If not, we will certainly get only noise -> no peaks -> peak to
		   average ratio is small. This is because the transmitted values at
		   the pilot positions are different from the values at the pilot cells
		   when transmitting the correct OFDM symbol (which we assumed) */

		/* Pick pilot positions and calculate "test" channel estimation */
		int iCurIndex = 0;
		for (i = 0; i < iNumCarrier; i++)
		{
			if (_IsScatPil(ReceiverParam.matiMapTab[0][i]))
			{
				/* Get channel estimate */
				veccChan[iCurIndex] =
					(*pvecInputData)[i] / ReceiverParam.matcPilotCells[0][i];

				/* We have to introduce a new index because not on all carriers
				   is a pilot */
				iCurIndex++;
			}
		}

		/* Calculate abs(IFFT) for getting estimate of impulse response */
		vecrTestImpResp = Abs(Ifft(veccChan, FftPlan));

		/* Calculate peak to average */
		const CReal rResultIREst = Max(vecrTestImpResp) / Sum(vecrTestImpResp);

		/* Store correlation results in a shift register for finding the peak */
		vecrCorrHistory.AddEnd(rResultIREst);

#else

		/* DRM frame synchronization based on time pilots ------------------- */
		/* Calculate correlation of received cells with pilot pairs */
		CReal rResultPilPairCorr = (CReal) 0.0;
		for (i = 0; i < iNumPilPairs; i++)
		{
			/* Actual correlation */
			const CComplex cCorrRes = (*pvecInputData)[vecPilCorr[i].iIdx1] *
				Conj(vecPilCorr[i].cPil1) *
				Conj((*pvecInputData)[vecPilCorr[i].iIdx2]) *
				vecPilCorr[i].cPil2 * cR_HH;

			rResultPilPairCorr += Real(cCorrRes);
		}

		/* Store correlation results in a shift register for finding the peak */
		vecrCorrHistory.AddEnd(rResultPilPairCorr);
#endif


		/* Finding beginning of DRM frame in results ------------------------ */
		/* Wait until history is filled completly */
		if (iInitCntFraSy > 0)
			iInitCntFraSy--;
		else
		{
			/* Search for maximum */
			int iMaxIndex = 0;
			CReal rMaxValue = -_MAXREAL;
			for (i = 0; i < iNumSymPerFrame; i++)
			{
				if (vecrCorrHistory[i] > rMaxValue)
				{
					rMaxValue = vecrCorrHistory[i];
					iMaxIndex = i;
				}
			}

			/* For initial frame synchronization, use maximum directly */
			if (bInitFrameSync == TRUE)
			{
				/* Reset init flag */
				bInitFrameSync = FALSE;

				/* Set symbol ID index according to received data */
				iSymbCntFraSy = iNumSymPerFrame - iMaxIndex - 1;
			}
			else
			{
				/* If maximum is in the middle of the interval
				   (check frame sync) */
				if (iMaxIndex == iMiddleOfInterval)
				{
					if (iSymbCntFraSy == iNumSymPerFrame - iMiddleOfInterval - 1)
					{
						/* Reset flags */
						bBadFrameSync = FALSE;
						bFrameSyncWasOK = TRUE;

						/* Post Message for GUI (Good frame sync) */
						PostWinMessage(MS_FRAME_SYNC, 0); /* green */
					}
					else
					{
						if (bBadFrameSync == TRUE)
						{
							/* Reset symbol ID index according to received
							   data */
							iSymbCntFraSy =
								iNumSymPerFrame - iMiddleOfInterval - 1;

							/* Inform that symbol ID has changed */
							bSymbolIDHasChanged = TRUE;

							/* Reset flag */
							bBadFrameSync = FALSE;

							PostWinMessage(MS_FRAME_SYNC, 2); /* red */
						}
						else
						{
							/* One false detected frame sync should not reset
							   the actual frame sync because the measurement
							   could be wrong. Sometimes the frame sync
							   detection gets false results. If the next time
							   the frame sync is still unequal to the
							   measurement, then correct it */
							bBadFrameSync = TRUE;

							if (bFrameSyncWasOK == TRUE)
							{
								/* Post Message that frame sync was wrong but
								   was not yet corrected (yellow light) */
								PostWinMessage(MS_FRAME_SYNC, 1); /* yellow */
							}
							else
								PostWinMessage(MS_FRAME_SYNC, 2); /* red */
						}

						/* Set flag for bad sync */
						bFrameSyncWasOK = FALSE;
					}
				}
			}
		}
	}
	else
	{
		/* Frame synchronization has successfully finished, show always green
		   light */
		PostWinMessage(MS_FRAME_SYNC, 0);
	}

	/* Set current symbol ID and flag in extended data of output vector */
	(*pvecOutputData).GetExData().iSymbolID = iSymbCntFraSy;
	(*pvecOutputData).GetExData().bSymbolIDHasChanged = bSymbolIDHasChanged;

	/* Increase symbol counter and take care of wrap around */
	iSymbCntFraSy++;
	if (iSymbCntFraSy >= iNumSymPerFrame)
		iSymbCntFraSy = 0;


	/**************************************************************************\
	* Using Frequency pilot information										   *
	\**************************************************************************/
	if ((bSyncInput == FALSE) && (bTrackPil == TRUE))
	{
		CComplex cFreqOffEstVecSym = CComplex((CReal) 0.0, (CReal) 0.0);

		for (i = 0; i < NUM_FREQ_PILOTS; i++)
		{
			/* The old pilots must be rotated due to timing corrections */
			const CComplex cOldFreqPilCorr =
				Rotate(cOldFreqPil[i], iPosFreqPil[i],
				(*pvecInputData).GetExData().iCurTimeCorr);

			/* Calculate the inner product of the sum */
			const CComplex cCurPilMult =
				(*pvecInputData)[iPosFreqPil[i]] * Conj(cOldFreqPilCorr);

			/* Save "old" frequency pilots for next symbol. Special treatment
			   for robustness mode D (carriers 7 and 21) necessary 
			   (See 8.4.2.2) */
			if ((ReceiverParam.GetWaveMode() == RM_ROBUSTNESS_MODE_E) &&
				(i < 2))
			{
				cOldFreqPil[i] = -(*pvecInputData)[iPosFreqPil[i]];
			}
			else
				cOldFreqPil[i] = (*pvecInputData)[iPosFreqPil[i]];

#ifdef USE_SAMOFFS_TRACK_FRE_PIL
			/* Get phase difference for sample rate offset estimation. Average
			   the vector, real and imaginary part separately */
			IIR1(cFreqPilotPhDiff[i], cCurPilMult, rLamSamRaOff);
#endif

			/* Calculate estimation of frequency offset */
			cFreqOffEstVecSym += cCurPilMult;
		}


		/* Frequency offset ------------------------------------------------- */
		/* Correct frequency offset estimation for resample offset corrections.
		   When a sample rate offset correction was applied, the frequency
		   offset is shifted proportional to this correction. The correction
		   is mandatory if large sample rate offsets occur */

		/* Get sample rate offset change */
		const CReal rDiffSamOffset =
			rPrevSamRateOffset - ReceiverParam.rResampleOffset;

		/* Save current resample offset for next symbol */
		rPrevSamRateOffset = ReceiverParam.rResampleOffset;

		/* Correct sample-rate offset correction according to the proportional
		   rule. Use relative DC frequency offset plus relative average offset
		   of frequency pilots to the DC frequency. Normalize this offset so
		   that it can be used as a phase correction for frequency offset
		   estimation  */
		CReal rPhaseCorr = (ReceiverParam.rFreqOffsetAcqui +
			ReceiverParam.rFreqOffsetTrack + rAvFreqPilDistToDC) *
			rDiffSamOffset / SOUNDCRD_SAMPLE_RATE / rNormConstFOE;

		/* Actual correction (rotate vector) */
		cFreqOffVec *= CComplex(Cos(rPhaseCorr), Sin(rPhaseCorr));


		/* Average vector, real and imaginary part separately */
		IIR1(cFreqOffVec, cFreqOffEstVecSym, rLamFreqOff);

		/* Calculate argument */
		const CReal rFreqOffsetEst = Angle(cFreqOffVec);

		/* Correct measurement average for actually applied frequency
		   correction */
		cFreqOffVec *= CComplex(Cos(-rFreqOffsetEst), Sin(-rFreqOffsetEst));

#ifndef USE_FRQOFFS_TRACK_GUARDCORR
		/* Integrate the result for controling the frequency offset, normalize
		   estimate */
		ReceiverParam.rFreqOffsetTrack += rFreqOffsetEst * rNormConstFOE;
#endif


#ifdef USE_SAMOFFS_TRACK_FRE_PIL
		/* Sample rate offset ----------------------------------------------- */
		/* Calculate estimation of sample frequency offset. We use the different
		   frequency offset estimations of the frequency pilots. We normalize
		   them with the distance between them and average the result (/ 2.0) */
		CReal rSampFreqOffsetEst =
			((Angle(cFreqPilotPhDiff[1]) - Angle(cFreqPilotPhDiff[0])) /
			(iPosFreqPil[1] - iPosFreqPil[0]) +
			(Angle(cFreqPilotPhDiff[2]) - Angle(cFreqPilotPhDiff[0])) /
			(iPosFreqPil[2] - iPosFreqPil[0])) / (CReal) 2.0;

		/* Integrate the result for controling the resampling */
		ReceiverParam.rResampleOffset +=
			CONTR_SAMP_OFF_INTEGRATION * rSampFreqOffsetEst;
#endif

#ifdef _DEBUG_
/* Save frequency and sample rate tracking */
static FILE* pFile = fopen("test/freqtrack.dat", "w");
fprintf(pFile, "%e %e\n", SOUNDCRD_SAMPLE_RATE * ReceiverParam.rFreqOffsetTrack,
	ReceiverParam.rResampleOffset);
fflush(pFile);
#endif
	}


	/* If synchronized DRM input stream is used, overwrite the detected
	   frequency offest estimate by "0", because we know this value */
	if (bSyncInput == TRUE)
		ReceiverParam.rFreqOffsetTrack = (CReal) 0.0;

	/* Do not ship data before first frame synchronization was done. The flag
	   "bAquisition" must not be set to FALSE since in that case we would run
	   into an infinite loop since we would not ever ship any data. But since
	   the flag is set after this module, we should be fine with that. */
	if ((bInitFrameSync == TRUE) && (bSyncInput == FALSE))
		iOutputBlockSize = 0;
	else
	{
		iOutputBlockSize = iNumCarrier;

		/* Copy data from input to the output. Data is not modified in this
		   module */
		for (i = 0; i < iOutputBlockSize; i++)
			(*pvecOutputData)[i] = (*pvecInputData)[i];
	}
}
Example #4
0
/******************************************************************************\
* Decoder                                                                      *
\******************************************************************************/
void CDataDecoder::ProcessDataInternal(CParameter& ReceiverParam)
{
	int			i, j;
	int			iPacketID;
	int			iNewContInd;
	int			iNewPacketDataSize;
	int			iOldPacketDataSize;
	int			iNumSkipBytes;
	_BINARY		biFirstFlag;
	_BINARY		biLastFlag;
	_BINARY		biPadPackInd;
	CCRC		CRCObject;

	/* Check if something went wrong in the initialization routine */
	if (DoNotProcessData == TRUE)
		return;


	/* CRC check for all packets -------------------------------------------- */
	/* Reset bit extraction access */
	(*pvecInputData).ResetBitAccess();

	for (j = 0; j < iNumDataPackets; j++)
	{
		/* Check the CRC of this packet */
		CRCObject.Reset(16);

		/* "- 2": 16 bits for CRC at the end */
		for (i = 0; i < iTotalPacketSize - 2; i++)
			CRCObject.AddByte((_BYTE) (*pvecInputData).Separate(SIZEOF__BYTE));

		/* Store result in vector and show CRC in multimedia window */
		if (CRCObject.CheckCRC((*pvecInputData).Separate(16)) == TRUE)
		{
			veciCRCOk[j] = 1; /* CRC ok */
			PostWinMessage(MS_MSC_CRC, 0); /* Green light */
		}
		else
		{
			veciCRCOk[j] = 0; /* CRC wrong */
			PostWinMessage(MS_MSC_CRC, 2); /* Red light */
		}
	}


	/* Extract packet data -------------------------------------------------- */
	/* Reset bit extraction access */
	(*pvecInputData).ResetBitAccess();

	for (j = 0; j < iNumDataPackets; j++)
	{
		/* Check if CRC was ok */
		if (veciCRCOk[j] == 1)
		{
			/* Read header data --------------------------------------------- */
			/* First flag */
			biFirstFlag = (_BINARY) (*pvecInputData).Separate(1);

			/* Last flag */
			biLastFlag = (_BINARY) (*pvecInputData).Separate(1);

			/* Packet ID */
			iPacketID = (int) (*pvecInputData).Separate(2);

			/* Padded packet indicator (PPI) */
			biPadPackInd = (_BINARY) (*pvecInputData).Separate(1);

			/* Continuity index (CI) */
			iNewContInd = (int) (*pvecInputData).Separate(3);


			/* Act on parameters given in header */
			/* Continuity index: this 3-bit field shall increment by one
			   modulo-8 for each packet with this packet Id */
			if ((iContInd[iPacketID] + 1) % 8 != iNewContInd)
				DataUnit[iPacketID].bOK = FALSE;

			/* Store continuity index */
			iContInd[iPacketID] = iNewContInd;

			/* Reset flag for data unit ok when receiving the first packet of
			   a new data unit */
			if (biFirstFlag == TRUE)
			{
				DataUnit[iPacketID].Reset();

				DataUnit[iPacketID].bOK = TRUE;
			}

			/* If all packets are received correctely, data unit is ready */
			if (biLastFlag == TRUE)
				if (DataUnit[iPacketID].bOK == TRUE)
					DataUnit[iPacketID].bReady = TRUE;


			/* Data field --------------------------------------------------- */
			/* Get size of new data block */
			if (biPadPackInd == TRUE)
			{
				/* Padding is present: the first byte gives the number of
				   useful data bytes in the data field. */
				iNewPacketDataSize =
					(int) (*pvecInputData).Separate(SIZEOF__BYTE) *
					SIZEOF__BYTE;

				if (iNewPacketDataSize > iMaxPacketDataSize)
				{
					/* Error, reset flags */
					DataUnit[iPacketID].bOK = FALSE;
					DataUnit[iPacketID].bReady = FALSE;

					/* Set values to read complete packet size */
					iNewPacketDataSize = iNewPacketDataSize;
					iNumSkipBytes = 2; /* Only CRC has to be skipped */
				}
				else
				{
					/* Number of unused bytes ("- 2" because we also have the
					   one byte which stored the size, the other byte is the
					   header) */
					iNumSkipBytes = iTotalPacketSize - 2 -
						iNewPacketDataSize / SIZEOF__BYTE;
				}

				/* Packets with no useful data are permitted if no packet
				   data is available to fill the logical frame. The PPI
				   shall be set to 1 and the first byte of the data field
				   shall be set to 0 to indicate no useful data. The first
				   and last flags shall be set to 1. The continuity index
				   shall be incremented for these empty packets */
				if ((biFirstFlag == TRUE) &&
					(biLastFlag == TRUE) &&
					(iNewPacketDataSize == 0))
				{
					/* Packet with no useful data, reset flag */
					DataUnit[iPacketID].bReady = FALSE;
				}
			}
			else
			{
				iNewPacketDataSize = iMaxPacketDataSize;

				/* All bytes are useful bytes, only CRC has to be skipped */
				iNumSkipBytes = 2;
			}

			/* Add new data to data unit vector (bit-wise copying) */
			iOldPacketDataSize = DataUnit[iPacketID].vecbiData.Size();

			DataUnit[iPacketID].vecbiData.Enlarge(iNewPacketDataSize);

			/* Read useful bits */
			for (i = 0; i < iNewPacketDataSize; i++)
				DataUnit[iPacketID].vecbiData[iOldPacketDataSize + i] =
					(_BINARY) (*pvecInputData).Separate(1);

			/* Read bytes which are not used */
			for (i = 0; i < iNumSkipBytes; i++)
				(*pvecInputData).Separate(SIZEOF__BYTE);


			/* Use data unit ------------------------------------------------ */
			if (DataUnit[iPacketID].bReady == TRUE)
			{
				/* Decode all IDs regardless whether activated or not
				   (iPacketID == or != iServPacketID) */
				/* Only DAB multimedia is supported */
				switch (eAppType)
				{
				case AT_MOTSLISHOW: /* MOTSlideshow */
					/* Packet unit decoding */
					MOTSlideShow[iPacketID].
						AddDataUnit(DataUnit[iPacketID].vecbiData);
					break;

				case AT_JOURNALINE:
					break;
				}

				/* Packet was used, reset it now for new filling with new data
				   (this will also reset the flag
				   "DataUnit[iPacketID].bReady") */
				DataUnit[iPacketID].Reset();
			}
		}
		else
		{
			/* Skip incorrect packet */
			for (i = 0; i < iTotalPacketSize; i++)
				(*pvecInputData).Separate(SIZEOF__BYTE);
		}
	}
}