示例#1
0
void InitSoraTx(BlinkParams *params)
{
	writeSoraCtx *ctx = (writeSoraCtx *)inmem_malloc(sizeof(writeSoraCtx));
	params->TXBuffer = (PVOID)ctx;

	ctx->prepareBuf = 0;
	ctx->transferBuf = 0;

	ctx->firstTx = 0;
	ctx->lastTx = 0;

	ctx->idleTXDetected = 0;
	ctx->TXBufferSize = params->radioParams.TXBufferSize;

	printf("TX-sora-tx-buffer-size=%ld, cmd-fifo-queue-size=%d, no-tx-bufs=%d\n", 
		ctx->TXBufferSize, cmd_fifo_queue_size, no_tx_bufs);
	for (int i = 0; i < no_tx_bufs; i++)
	{
		ctx->TXBuffers[i] = SoraUAllocBuffer(ctx->TXBufferSize * sizeof(complex16));		// alloc tx sample buffers
		if (ctx->TXBuffers[i] == NULL)
		{
			fprintf(stderr, "Error: Fail to allocate Sora Tx buffer memory!\n");
			exit(1);
		}

		// Set to 0 as it is not expensive in init and can be useful for gaps between packets
		memset(ctx->TXBuffers[i], 0, params->radioParams.TXBufferSize * sizeof(complex16));
	}

}
示例#2
0
void InitSoraRx(BlinkParams *params)
{
    HRESULT hr;
    ULONG nRxBufSize = 0;

	readSoraCtx *rctx = (readSoraCtx *)inmem_malloc(sizeof(readSoraCtx));
	params->TXBuffer = (PVOID)rctx;

	// Create queue between worker and RX
	// (only used if READ_IN_WORKER_THREAD defined)
	size_t size = 28*sizeof(complex16);
	rctx->readQueue = s_ts_init(1, &size);

	// Map Rx Buffer 
    hr = SoraURadioMapRxSampleBuf( params->radioParams.radioId, &params->pRxBuf, & nRxBufSize);
    if ( FAILED (hr) ) {
        fprintf (stderr, "Error: Fail to map Sora Rx buffer!\n" );
        exit(1);
    }
    
    // Generate a sample stream from mapped Rx buffer
	params->radioParams.dev = (SoraRadioParam *)inmem_malloc(sizeof(SoraRadioParam));
	SoraURadioAllocRxStream(&(params->radioParams.dev->RxStream), params->radioParams.radioId, (PUCHAR)params->pRxBuf, nRxBufSize);
}
示例#3
0
void InitSoraRx(BlinkParams *params)
{
    HRESULT hr;
    ULONG nRxBufSize = 0;

	// Map Rx Buffer 
    hr = SoraURadioMapRxSampleBuf( params->radioParams.radioId, &params->pRxBuf, & nRxBufSize);
    if ( FAILED (hr) ) {
        fprintf (stderr, "Error: Fail to map Sora Rx buffer!\n" );
        exit(1);
    }
    
    // Generate a sample stream from mapped Rx buffer
	params->radioParams.dev = (SoraRadioParam *)inmem_malloc(sizeof(SoraRadioParam));
	SoraURadioAllocRxStream(&(params->radioParams.dev->RxStream), params->radioParams.radioId, (PUCHAR)params->pRxBuf, nRxBufSize);
}
示例#4
0
// Transit a buffer of <size> complex16 numbers
void writeSora(BlinkParams *params, complex16 *ptr, ULONG size)
{
    HRESULT hr;
	static int indexSrc = 0;
	int indexPtr = 0;
	writeSoraCtx *ctx = (writeSoraCtx *)params->TXBuffer;
	complex16 *remainBuf = ptr;
	ULONG remainCnt = size;
	int nextPrepareBuf;
	static complex16 *syncBuf1 = NULL, *syncBuf2 = NULL;
	static bool sendSendSyncPreamb = true;

	static LONG TXCnt = 0;


#ifdef DEBUG_LOSSES
	static complex16 incArr[2000];
	static int incAddInd = 0;
#endif


#ifndef DEBUG_TXRX	
	// Init sync buffer
	if (syncBuf1 == NULL)
	{
		syncBuf1 = (complex16*)inmem_malloc(ctx->TXBufferSize * sizeof(complex16));
		syncBuf2 = (complex16*)inmem_malloc(ctx->TXBufferSize * sizeof(complex16));
		if (syncBuf1 == NULL || syncBuf2 == NULL)
		{
			printf("Cannot malloc syncBufs!\n");
			exit(1);
		}
		for (int i = 0; i < ctx->TXBufferSize; i++)
		{
			syncBuf1[i].re = i;
			syncBuf1[i].im = i;
			syncBuf2[i].re = 0;
			syncBuf2[i].im = 0;
		}
	}
#endif

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

#ifdef DEBUG_LOSSES
		// Create test sequence
		for (int i = 0; i < 2000; i++)
		{
			incArr[i].re = (i % 1000);
			incArr[i].im = (i % 1000);
		}
#endif

	}
	tx_init_done = true;
	while (!rx_init_done);


#ifdef DEBUG_LOSSES
	// Send test sequence instead of the real one
	ptr = incArr + incAddInd;
	incAddInd = (incAddInd + size) % 1000;
#endif

#ifndef DEBUG_TXRX	
	// 2s delay before syncing
	const int syncPreambLen = ((2*30720000) / (int) ctx->TXBufferSize);

	// Send special sequence
	// Sequence starts with bunch of 0s to wait until the firmware's queues stabilize
	// and then sends a ramp that is detected by the RX. Data transmission continues 
	// immediately after the ramp so after it we are in sync with RX.
	if (sendSendSyncPreamb)
	{
		nextPrepareBuf = (ctx->prepareBuf + 1) % no_tx_bufs;

		for (int syncBufCnt = 0; syncBufCnt <= syncPreambLen; syncBufCnt++)
		{
			complex16 *currentBuf = (complex16*)ctx->TXBuffers[ctx->prepareBuf];

			if (syncBufCnt == syncPreambLen)
			{
				memcpy((void *)currentBuf, (void *)syncBuf1, ctx->TXBufferSize * sizeof(complex16));
			}
			else
			{
				memcpy((void *)currentBuf, (void *)syncBuf2, ctx->TXBufferSize * sizeof(complex16));
			}

			// Spin wait until there is a space in the buffer queue
			while (nextPrepareBuf == ctx->transferBuf)
			{
				ctx->prepareBlocked++;
			}

			// Full buffer ready to be sent
			// We don't really send here. 
			// We just advance the pointer and release the record
			// to be transferred and sent by other threads
			ctx->prepareBuf = nextPrepareBuf;
			nextPrepareBuf = (ctx->prepareBuf + 1) % no_tx_bufs;
			indexSrc = 0;
		}
		sendSendSyncPreamb = false;
	}


  #ifndef DEBUG_LOSSES
	// Set the bit on LSB RXTX Sync channel
	// For speed we set the bit only once every RXTX_SYNC_PERIOD (10ms - 1 frame)
	// and we don't reset the bit otherwise. We count on this bit being random so
	// we'll detect out of sync in on average 20ms
	if (TXCnt == 0)
	{
		ptr[0].re |= 1;
		ptr[0].im |= 1;
	}
	else if (TXCnt + size > RXTX_SYNC_PERIOD)
	{
		ptr[RXTX_SYNC_PERIOD - TXCnt - 1].re |= 1;
		ptr[RXTX_SYNC_PERIOD - TXCnt - 1].im |= 1;
	}
	TXCnt = (TXCnt + size) % RXTX_SYNC_PERIOD;
  #endif
#endif




	nextPrepareBuf = (ctx->prepareBuf + 1) % no_tx_bufs;

	while (remainCnt > 0)
	{
		ULONG inc = min(ctx->TXBufferSize - indexSrc, remainCnt);
		complex16 *currentBuf = (complex16*)ctx->TXBuffers[ctx->prepareBuf];
		memcpy((void *)(currentBuf + indexSrc), (void *)(ptr + indexPtr), inc * sizeof(complex16));
		indexPtr += inc;
		indexSrc += inc;
		remainCnt -= inc;

		if (indexSrc >= ctx->TXBufferSize)
		{
			bool block = false;
			// Spin wait until there is a space in the buffer queue
			while (nextPrepareBuf == ctx->transferBuf)
			{
				block = true;
			}
			if (block) ctx->prepareBlocked++;

			// Full buffer ready to be sent
			// We don't really send here. 
			// We just advance the pointer and release the record
			// to be transferred and sent by other threads
			ctx->prepareBuf = nextPrepareBuf;
			nextPrepareBuf = (ctx->prepareBuf + 1) % no_tx_bufs;
			indexSrc = 0;
		}
	}
}