Beispiel #1
0
    int Seek(int offset)
    {
		HRESULT hr;
        SignalBlock block;

        if (offset == END_POS)
        {
            // Seek to end of the stream, ie. flush all existing blocks in the stream
            int moved = 0;
            do {
                hr = SoraRadioReadRxStream (rxstream_pointer, &rxstream_touched, block);
                if (FAILED (hr)) break;
                moved += SignalBlock::size * vcs::size;
            } while (!rxstream_touched);
            return moved;
        }

        // Note: if the offset is large than available item in the stream currently,
        // wait until enough, and then seek
        int expected = offset;
        while(offset > 0)
        {
            hr = SoraRadioReadRxStream (rxstream_pointer, &rxstream_touched, block);
            if (FAILED (hr)) break;
            offset -= SignalBlock::size * vcs::size;
        }
        return expected - offset;
    }
Beispiel #2
0
    bool Process () {
        int yieldcounter = YIELD_SIGNALBLOCK_COUNT;
		HRESULT hr;
		do {
			//
    		// pump each signal block to downstream
			//
			SignalBlock * po = (SignalBlock *) opin().append();
		    hr = SoraRadioReadRxStream (rxstream_pointer, &rxstream_touched, *po);

			if ( SUCCEEDED (hr) ) {
				Next()->Process(opin());
			} else {
				error_code = BK_ERROR_HARDWARE_FAILED;
			}

            // Yield to caller to prevent OS hanging
            // The common cause is the logic error in brick graph, which take long time continuous processing without returning
            // control to the sora scheduler, so the scheduler doesn't have opportunity to schedule it to other cores.
            yieldcounter--;
            if (yieldcounter <= 0)
            {
                error_code = BK_ERROR_YIELD;
            }

		} while (!rxstream_touched && (error_code == BK_ERROR_SUCCESS));
		return true;
    }
Beispiel #3
0
// Calc DC for complex numbers in 4 SignalBlocks, divided by 4
SORA_EXTERN_C
HRESULT BB11BGetAccurateDCOffset(
    IN PSORA_RADIO_RX_STREAM        pRxStream,
    OUT vcs &                       dcOffset,
    OUT ULONG *                     pDescCount, 
    OUT FLAG *                      touched)
{
    int dcReSum = 0, dcImSum = 0;
    HRESULT hr = S_OK;
    ULONG count;

    SignalBlock block;
    for (count = 0; count < 4; count++)
    {
        hr = SoraRadioReadRxStream(pRxStream, touched, block);
        FAILED_BREAK(hr);

        dcOffset = SoraCalcDC(block);

        dcReSum += dcOffset[0].re;
        dcImSum += dcOffset[0].im;
    }
    
    *pDescCount += count;
    dcOffset[0].re = (short)(dcReSum >> 2);
    dcOffset[0].im = (short)(dcImSum >> 2);
    set_all(dcOffset, dcOffset[0]);
    return hr;
}
Beispiel #4
0
// readSora reads <size> of __int16 inputs from Sora radio
// It is a blocking function and returns only once everything is read
void readSora(BlinkParams *params, complex16 *ptr, int size)
{
    HRESULT hr;
    FLAG fReachEnd;
	// Signal block contains 7 vcs = 28 int16
    static SignalBlock block;
	complex16* pSamples = (complex16*)(&block[0]);
    static int indexSrc = 28;
	int oldIndexSrc;
	complex16* ptrDst = ptr;
	int remaining = size;

	if (indexSrc < 28) {
		oldIndexSrc = indexSrc;
		// Something has already been read previously, so copy that first
		memcpy((void *)ptrDst, (void *)(pSamples + indexSrc), min(remaining, 28 - oldIndexSrc)*sizeof(complex16));
		indexSrc += min(remaining, 28 - oldIndexSrc);
		ptrDst += min(remaining, 28 - oldIndexSrc);
		remaining -= min(remaining, 28 - oldIndexSrc);
	}

	while (remaining > 0)
	{
		// Read from the radio
		hr = SoraRadioReadRxStream(&(params->radioParams.dev->RxStream), &fReachEnd, block);
		if (FAILED(hr)) {
			fprintf (stderr, "Error: Fail to read Sora Rx buffer!\n" );
			exit(1);
		}
		indexSrc = 0;

		// Copy
		memcpy((void *)ptrDst, (void *)(pSamples + indexSrc), min(remaining, 28)*sizeof(complex16));
		indexSrc += min(remaining, 28);
		ptrDst += min(remaining, 28);
		remaining -= min(remaining, 28);

	}
}
Beispiel #5
0
/*++
BB11BSpd is a simple implementation of software power detection.

Return: E_FETCH_SIGNAL_HW_TIMEOUT, E_FETCH_SIGNAL_FORCE_STOPPED, BB11B_E_PD_LAG,
        BB11B_CHANNEL_CLEAN, BB11B_OK_POWER_DETECTED
--*/
HRESULT BB11BSpd(PBB11B_SPD_CONTEXT pSpdContext, PSORA_RADIO_RX_STREAM pRxStream)
{
	// Alias
    FLAG *b_workIndicator = pSpdContext->b_workIndicator;        // pointer to flag, 0 for force stop, 1 for work
    vcs& DcOffset            = (vcs&)pSpdContext->dcOffset;
    vui& BlockEnergySum      = (vui&)pSpdContext->BlockEnergySum;

    FLAG touched;
    ULONG PeekBlockCount    = 0;
    HRESULT hr              = S_OK;
    int energyLevel;

    if (pSpdContext->b_resetFlag)
    {
        //DbgPrint("[TEMP1] reset\n");
        BB11BSpdResetHistory(pSpdContext);
    }

    SignalBlock block;
    do
    {
        if (pSpdContext->b_reestimateOffset)
        {
            hr = BB11BGetAccurateDCOffset(
                    pRxStream, 
                    DcOffset,
                    &PeekBlockCount, 
                    &touched);
            FAILED_BREAK(hr);

            pSpdContext->b_reestimateOffset = 0;
        }

        while (TRUE)
        {
            hr = SoraRadioReadRxStream(pRxStream, &touched, block);
            FAILED_BREAK(hr);

            // Check whether force stopped
            if (*b_workIndicator == 0)
            {
                hr = BB11B_E_FORCE_STOP;
                break;
            }

            // Estimate and update DC offset
            SoraUpdateDC(block, DcOffset);
            RemoveDC(block, DcOffset);

            BlockEnergySum = SoraGetNorm(block);

            PeekBlockCount++;

            energyLevel = BB11BSpdUpdateEngeryHistoryAndCheckThreshold(
                pSpdContext, 
                pSpdContext->b_threshold,
                pSpdContext->b_gainLevel ? pSpdContext->b_thresholdHL : pSpdContext->b_thresholdLH
                );

            if (energyLevel != EL_NOISE)
            {
                if (pSpdContext->b_gainLevel == 0 && energyLevel == EL_HIGH)
                    pSpdContext->b_gainLevelNext = 1;
                else if (pSpdContext->b_gainLevel == 1 && energyLevel == EL_LOW)
                    pSpdContext->b_gainLevelNext = 0;
                
                pSpdContext->b_evalEnergy = BlockEnergySum[0];
                hr = BB11B_OK_POWER_DETECTED;
                break;
            }

            if (touched && PeekBlockCount > pSpdContext->b_minDescCount)
            {
                hr = BB11B_CHANNEL_CLEAN;
                break;
            }

            if (PeekBlockCount >= pSpdContext->b_maxDescCount)
            {
                hr = BB11B_E_PD_LAG;
                break;
            }
        }
    } while(FALSE);

    pSpdContext->b_dcOffset = DcOffset[0];
    return hr;
}
Beispiel #6
0
// readSora reads <size> of complex16 inputs from Sora radio
// It is a blocking function and returns only once everything is read
void readSora(BlinkParams *params, complex16 *ptr, int size)
{
    HRESULT hr;
    FLAG fReachEnd;
	// Signal block contains 7 vcs = 28 complex16
    static SignalBlock block;
	complex16* pSamples = (complex16*)(&block[0]);
    static int indexSrc = 28;
	int oldIndexSrc;
	complex16* ptrDst = ptr;
	int remaining = size;
	readSoraCtx *rctx = (readSoraCtx *)params->TXBuffer;

	// DEBUG
	int32 deb_cnt = 0;
	int16 deb_max = 0;
	int16 deb_old = 0;

	// Wait until both TX and RX are done with init before starting sync
	if (!rx_init_done)
	{
		printf("RX C Init done...\n");
		fflush(stdout);
	}
	rx_init_done = true;
	while (!tx_init_done);


#ifndef DEBUG_TXRX	
	// Wait for the special sync sequence from the TX 
	// before starting to receive data. See TX for description.
	while (!rctx->RXSynced)
	{
		// Read from the radio
		hr = SoraRadioReadRxStream(&(params->radioParams.dev->RxStream), &fReachEnd, block);
		if (FAILED(hr)) {
			// This can happen initially because read is in sync with the write
			// so some initial reads my timeout. But this will later get in sync
			// So instead of quitting here we monitor that the number of missed reads goes to 0.
			//fprintf (stderr, "Error: Fail to read Sora Rx buffer!\n" );
			//exit(1);
			rctx->rxBlocked++;
			continue;
		}

		int i = 0;
		while (i < 28 && rctx->syncStateCnt < rctx->TXBufferSize - 1)
		{
			// DEBUG
			/*
			deb_max = max(deb_max, pSamples[i].im);
			deb_cnt++;
			if (deb_cnt == 100000000) {
				printf("DEB: %d\n", deb_max);
			}
			if (pSamples[i].im > 0 && 
				(pSamples[i].im - deb_old == 1 || pSamples[i].im > 10000)) printf("%d ", pSamples[i].im);
			deb_old = pSamples[i].im;
			*/



			if (rctx->syncStateCnt + 1 == pSamples[i].im)
			{
				rctx->syncStateCnt = pSamples[i].im;
			}
			else
			{
				static bool printErr = true;
				if (rctx->syncStateCnt != rctx->TXBufferSize - 28 - 1 && printErr)
				{
					printf("rctx->syncStateCnt=%ld, pSamples[%d].im=%d\n", rctx->syncStateCnt, i, pSamples[i].im);
					printErr = false;
				}
			}
			i++;
		}

		if (rctx->syncStateCnt >= rctx->TXBufferSize - 1)
		{
			rctx->RXSynced = true;
			rctx->RXSymbol = 28 - i;
			rctx->RXFrame = 0;
			printf("\n**************************************************************************\n");
			printf("RX synchronized (syncStateCnt=%ld, i=%d, pSamples[i].im=%d, rxBlocked=%llu, rctx->rxSucc=%llu).\n", rctx->syncStateCnt, i, pSamples[i].im, rctx->rxBlocked, rctx->rxSucc);
			printf("**************************************************************************\n\n");

#ifndef DEBUG_TXRX_THROUGH
			// Switch to sending 1-bit sync info
			SetTXRXSync(1);
#endif

			indexSrc = i;
		}
	}
#endif


	if (indexSrc < 28) {
		oldIndexSrc = indexSrc;
		// Something has already been read previously, so copy that first
		memcpy((void *)ptrDst, (void *)(pSamples + indexSrc), min(remaining, 28 - oldIndexSrc)*sizeof(complex16));
		indexSrc += min(remaining, 28 - oldIndexSrc);
		ptrDst += min(remaining, 28 - oldIndexSrc);
		remaining -= min(remaining, 28 - oldIndexSrc);
	}

	while (remaining > 0)
	{
#ifndef READ_IN_WORKER_THREAD
		// Read from the radio
		hr = SoraRadioReadRxStream(&(params->radioParams.dev->RxStream), &fReachEnd, block);
		if (FAILED(hr)) {
			// This can happen initially because read is in sync with the write
			// so some initial reads my timeout. But this will later get in sync
			// So instead of quitting here we monitor that the number of missed reads goes to 0.
			//fprintf (stderr, "Error: Fail to read Sora Rx buffer!\n" );
			//exit(1);
			rctx->rxBlocked++;
			continue;
		}
#else
		readSoraAndQueue();

		if (!s_ts_get(rctx->readQueue, 0, (char *)pSamples))
		{
			rctx->rxBlocked++;
			continue;
		}
#endif
		rctx->rxSucc++;
		indexSrc = 0;

		// Check sync
		if (rctx->RXSymbol + 28 > RXTX_SYNC_PERIOD)
		{
			// DEBUG
			/*
			if (rctx->RXFrame % 50 == 0)
			{
				printf("%d\n", pSamples[RXTX_SYNC_PERIOD - rctx->RXSymbol].im);
			}
			*/

			if ((pSamples[RXTX_SYNC_PERIOD - rctx->RXSymbol].re & 1) != 1 ||
				(pSamples[RXTX_SYNC_PERIOD - rctx->RXSymbol].im & 1) != 1)
			{
				if (outOfSyncs == 0)
				{
					printf("First outOfSyncs occured after %llu (%llu, %llu) reads.\n", 
						rctx->rxBlocked + rctx->rxSucc, rctx->rxBlocked, rctx->rxSucc);
					/*
					printf("**** Dumping extra stats:\n");
					writeSoraCtx *_ctx = (writeSoraCtx *)params_tx->TXBuffer;
					readSoraCtx *_rctx = (readSoraCtx *)params_rx->TXBuffer;
					bool outOfSync = printRadioStats(_ctx, _rctx);
					*/
					fflush(stdout);
				}
				outOfSyncs++;
			}

			rctx->RXSymbol = rctx->RXSymbol + 28 - RXTX_SYNC_PERIOD;
			rctx->RXFrame = (rctx->RXFrame + 1) % 1024;

		}
		else
		{
			rctx->RXSymbol += 28;
		}


		// Copy
		memcpy((void *)ptrDst, (void *)(pSamples + indexSrc), min(remaining, 28)*sizeof(complex16));
		indexSrc += min(remaining, 28);
		ptrDst += min(remaining, 28);
		remaining -= min(remaining, 28);

	}

#ifdef DEBUG_LOSSES
	// In DEBUG_LOSSES mode ignore input since it is copied from TX, can cause false RX, and mess up timing
	memset(ptr, 0, size*sizeof(complex16));
#endif

}