⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transmit.c

📁 DSP 5409 plc应用程序,调试通过,是用在电力线通讯上的演示程序.
💻 C
📖 第 1 页 / 共 2 页
字号:

//==========================================================================================
// Function:		makePreamble()
//
// Description: 	Make the preamble and send it to the AFE.
//					This function transmits data in several chunks.  Each chunk consists of
//					one or more calls to these functions:
//						CalcTxStartAddr - Finds location in txBuff big enough to hold chunk
//						FillAFETxBuffI16 - Fills values into tx buffer.
//						JamDMAReloadRegs - Jams the DMA registers to point to next chunk.
//						                   Handles timing to avoid conflicts.
//
//		logical frame   |   0   |    1  |   2   |   3   |   4   |   5   |   sync    | data  |
//					| 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 | 1 | 2 |-1 |-2 |-1 |   D0  |
//		windowing    <                                                   x           x
//		xmit frame	|  1st  | loop  | loop  | loop  | loop  | loop  | last  | sync  |       | 
//
// Return:			Pointer to the next position in txSignalArray
//
// Revision History:
//==========================================================================================
TXDATA* makePreamble(TXDATA* pTxSignal, i16 *prefix )
{
	i16				frame;
	u16				n;						// loop counter
	TXDATA*			TxStart;
 	iCplx			*ifftBuf;
	i16				preSignal[FFT_LEN];		// local copy of frame waveform


	//---- put carriers in correct fft bins and call the ifft routine ----
	getPrePhases( phaseEqArray, PreambleArray );
	//diagData(phaseEqArray, CARRIER_LEN, "prePhase", diagICPLX);

	// We must shut off timer interrupts here to prevent the receive process from corrupting the FFT buffer
	INTR_DISABLE(TINT0); 	// Disable Timer0 Interrupt

	#if SAVETRACE == TRUE
		SaveTraceData(0x5000);				// Put a marker in the trace buffer
		SaveTraceData((u16)recSignal);		// at the start of a transmit opperation
		SaveTraceData((u16)pTxSignal);		// 
	#endif

	//---- put carriers in correct fft bins and call the ifft routine ----
	fillCarriers( fftArray, phaseEqArray, PRE_IFFT_SCALE );
	cifft( (DATA *)(fftArray), FFT_LEN, IFFT_SCALE );

	//AdjustTxPeaks(fftArray, 0xF, 0xF);	// Adjust gain of tx signal to maintain constant peaks.
	setTxPower(fftArray);					// 2nd & 3rd arguments are markers for trace buffer.

	// Copy preamble from FFT buffer to a local variable so that when the receive 
	// interrupt changes the FFT buffer it doesn't affect the preamble.
	ifftBuf = fftArray;
	for( n = 0; n < FFT_LEN; n++ )
	{
		#ifdef RAMP_TEST							
			preSignal[n] = (n-128)<<5;			// Make a fake preamble ramp.
		#else
			preSignal[n] = (ifftBuf++)->re;		// Make a local copy from the FFT buffer
		#endif
	}
	//diagData(preSignal, FFT_LEN, "preSignal", diagI16);

	INTR_ENABLE(TINT0); 			// Re-Enable Timer0 Interrupt

	getSyncPhases( phaseEqArray, PreambleArray );	// get ready for sync frame
	//diagData(phaseEqArray, CARRIER_LEN, "syncPhase", diagICPLX);


	//---- get the modulated time domain signal and repeat for each frame 

	//---- send the first frame which is windowed, starting with the 2nd half of the waveform ----------
	for( n = 0; n < WINDOW_LEN ; n++ )
	{
		prefix[n]  = ( (i32)(preSignal[FFT_LEN/2 + n]) * FrameWindow[n] ) >> WINDOW_SCALE;
	}
	TxStart   = CalcTxStartAddr (pTxSignal, FFT_LEN);				// Find a free space in Tx buffer
	pTxSignal = FillAFETxBuffI16 (TxStart,   prefix, WINDOW_LEN);	// windowed part of 2nd half of waveform
	pTxSignal = FillAFETxBuffI16 (pTxSignal, preSignal+FFT_LEN/2+WINDOW_LEN, FFT_LEN/2-WINDOW_LEN); // rest of 2nd half
	pTxSignal = FillAFETxBuffI16 (pTxSignal, preSignal, 				     FFT_LEN/2); // 1st half of waveform
	JamDMAReloadRegs(TxStart, FFT_LEN);		// Load the AFE registers to start the transmit

	//---- send middle frames with normal phase, starting in the second half of the waveform ---------
	for( frame = 1; frame < NUM_PRE_FRAMES-2; frame++ )  
	{
		TxStart   = CalcTxStartAddr(pTxSignal, FFT_LEN);	// Find a free space in Tx buffer
		pTxSignal = FillAFETxBuffI16 (TxStart,   preSignal+FFT_LEN/2, FFT_LEN/2);	// 2nd half of waveform
		pTxSignal = FillAFETxBuffI16 (pTxSignal, preSignal,           FFT_LEN/2);	// 1st half of waveform
		JamDMAReloadRegs(TxStart, FFT_LEN);		// Load the AFE registers to start the transmit
	}
	
	//---- send the last half preamble frame ----------------------------------------------
	TxStart   = CalcTxStartAddr(pTxSignal, FFT_LEN);	// Find a free space in Tx buffer
	pTxSignal = FillAFETxBuffI16 (TxStart,   preSignal+FFT_LEN/2, FFT_LEN/2); // rest of 2nd half

	// //---- Ramp down the positive preamble and ramp up the negative.
	// //     Formula looks different from windowing done elsewhere because we are combining
	// //	   the ramp-down of a signal with a ramp-up of a negative version of same signal.
	// for( n = 0; n < WINDOW_LEN ; n++ )
	// {									  
	// 	prefix[n] = (256-FrameWindow[n]) - FrameWindow[n];	// prefix = (windowDn - windowUp) * preSignal
	// 	prefix[n]  = ( (i32)(preSignal[n]) * prefix[n] ) >> WINDOW_SCALE;
	// }
	// pTxSignal = FillAFETxBuffI16 (pTxSignal, prefix, WINDOW_LEN);	// windowed part of sync field

	//---- calc prefix for transition between preamble and sync frame ------------
	for( n = 0; n < WINDOW_LEN ; n++ )
	{									  
		prefix[n]  = ( (i32)(preSignal[n]) * (256-FrameWindow[n]) ) >> WINDOW_SCALE;	// Window down
	}

	//---- Now calc sync frame waveform----------------------------------------
	INTR_DISABLE(TINT0); 	// Disable Timer0 Interrupt
	
	fillCarriers( fftArray, phaseEqArray, PRE_IFFT_SCALE );
	cifft( (DATA *)(fftArray), FFT_LEN, IFFT_SCALE );

	//AdjustTxPeaks(fftArray, 0xF, 0xF);	// Adjust gain of tx signal to maintain constant peaks.
	setTxPower(fftArray);		

	ifftBuf = fftArray;
	for( n = 0; n < FFT_LEN; n++ )
	{
		#ifdef RAMP_TEST							
			preSignal[n] = -preSignal[n];		// reviewse test ramp
		#else
			preSignal[n] = (ifftBuf++)->re;		// Make a local copy from the FFT buffer
		#endif
	}
	//diagData(preSignal, FFT_LEN, "syncSignal", diagI16);
	
	INTR_ENABLE(TINT0); 			// Re-Enable Timer0 Interrupt

	//---- calc prefix for transition between preamble and sync frame ------------
	for( n = 0; n < WINDOW_LEN ; n++ )
	{									  
		prefix[n]  += ( (i32)(preSignal[n]) * FrameWindow[n] ) >> WINDOW_SCALE;	// Window up
	}

	pTxSignal = FillAFETxBuffI16 (pTxSignal, prefix, WINDOW_LEN);	// windowed part of sync field
	pTxSignal = FillAFETxBuffI16 (pTxSignal, preSignal+WINDOW_LEN, FFT_LEN/2-WINDOW_LEN); // rest of 1st half of sync
	JamDMAReloadRegs(TxStart, FFT_LEN);		// Load the AFE registers to start the transmit

	//---- Calculate the "postfix" to blend with the first data frame ----------------------
	//     The "prefix" calculated here will become "postfix" used in the first frame of data.
	for( n = 0; n < WINDOW_LEN ; n++ )
	{
		prefix[n]  = ( (i32)(preSignal[FFT_LEN/2 + n]) * (256-FrameWindow[n]) ) >> WINDOW_SCALE;	// Window down
	}

	//---- Finally, send a full frame with sync phase ----------------------------------
	TxStart = CalcTxStartAddr(pTxSignal, FFT_LEN);	// Find a free space in Tx buffer
	pTxSignal = FillAFETxBuffI16 (TxStart,   preSignal+FFT_LEN/2, FFT_LEN/2);	// 2nd half of inverted waveform
	pTxSignal = FillAFETxBuffI16 (pTxSignal, preSignal,           FFT_LEN/2);	// 1st half of inverted waveform
	JamDMAReloadRegs(TxStart, FFT_LEN);		// Load the AFE registers to start the transmit

	return pTxSignal;		// return pointer at current location
}


//==========================================================================================
// Function:		makeDataFrames()
//
// Description: 	Make the data frames and send them to the AFE.
//					Uses global buffer FFTArray, symbolArray and phaseEqArray.
//					Here phaseEqArray is used to hold the phase.
//
// 					windowing= (repeat of 1st part of previous frame) * (falling window function)
//			  				  + (1st part of cyclic prefix) * (rising window function)	
//
//					This function transmits data in several chunks.  Each chunk consists of
//					one or more calls to these functions:
//						CalcTxStartAddr - Finds location in txBuff big enough to hold chunk
//						FillAFETxBuffI16 - Fills values into tx buffer.
//						JamDMAReloadRegs - Jams the DMA registers to point to next chunk.
//						                   Handles timing to avoid conflicts.
//
// Return:			Pointer to the next position in txSignalArray
//
// Revision History:
//==========================================================================================
TXDATA* makeDataFrames(TXDATA* pTxSignal, i16 *postfix, u16 *pUserData )
{
	iCplx			*symbols;
	iCplx			*phase;
	TXDATA*			TxStart;

	u16				n, frame, block;
	i16				prevCarrier1;			// phase of previous 1st carrier
	i16				cumPhase;	  			// cumulative phase

	iCplx			*ifftBuf;				// working pointers for raised cos
	i16				prefix[CYCLIC_PREFIX_LEN];


	#if DEBUGIT == DEBUG_DISTANCE2
		diagArray = mxCreateDoubleMatrix(1, NUM_SYMBOLS*DATA_FRAMES_PER_BLOCK, mxREAL);
		mxSetName(diagArray, "txPhaseSyms");
		diag.r = mxGetPr(diagArray);
	#endif

	//---- work on the user data -----------------------
	appendParityCheckBytes(pUserData, (NUM_USER_BYTES>>1));
	//diagData(pUserData, DATA_BUFFER_LEN, "txData", diagU16);

	scramble(pUserData, DATA_BUFFER_LEN);// scramble the whole thing

	viterbiZero(pUserData);				// force end of buffer to zero
	//diagData(pUserData, DATA_BUFFER_LEN, "txScramble", diagU16);

	//---- encode and modulate the data ----------------
	viterbiEncodeInit(pUserData);
	prevCarrier1 = 0;

	#if SAVETRACE == TRUE
		SaveTraceData(0x5001);				// Put a marker in the trace buffer
		SaveTraceData((u16)recSignal);		// at the start of a data portion of 
		SaveTraceData((u16)pTxSignal);		// a transmit opperation
	#endif

	for( block = 0;  block < NUM_DATA_BLOCKS; block++ )
	{
		viterbiEncodeFrame(symbolArray);		// get data from user data buffer and put encoded 
		//if( block == 0 )				 		// result in real part of symbol buffer
		//	diagData(symbolArray, CARRIER_LEN, "txSymbols", diagICPLX);

		//---- build the data frames -----------------------
		for( frame = 0; frame < DATA_FRAMES_PER_BLOCK; frame++ )  
		{	
			symbols = symbolArray + (frame*SYMBOL_OFFSET);
			if( symbols >= (symbolArray + CARRIER_LEN) )
					symbols = symbols - CARRIER_LEN;
			phase = phaseEqArray;

			//---- assign phase based on 2-bit encoded data --------------------
			cumPhase  = prevCarrier1 + symbols->re;		// calc cumulative phase
			cumPhase &= 0x03;							// truncate to two bits
			prevCarrier1 = cumPhase;					// save this phase for the next frame	

			for(n = 0; n<CARRIER_LEN; n++ )				// start loop at 2nd carrier
			{
				#if DEBUGIT == DEBUG_DISTANCE2
					*diag.r++ = (double)(symbols->re);
				#endif

				phase->re = complexMap[cumPhase].re;	// map to complex quantity
				phase->im = complexMap[cumPhase].im;		
				phase++;
				
				symbols++;
				if( symbols >= (symbolArray + CARRIER_LEN) )
					symbols = symbolArray;

				cumPhase += symbols->re;				// calc cumulative phase
				cumPhase &= 0x03;						// truncate to two bits
			}	// end carrier loop		


			//---- put carriers in correct fft bins and call the ifft routine ----
			// We must shut off timer interrupts here to prevent the receive process from corrupting the FFT buffer
			INTR_DISABLE(TINT0); 	// Disable Timer0 Interrupt
 			fillCarriers( fftArray, phaseEqArray, DATA_IFFT_SCALE );
			cifft( (DATA *)(fftArray), FFT_LEN, IFFT_SCALE );

			//AdjustTxPeaks(fftArray, block, frame);	// Adjust the gain of the transmitted signal to maintain constant peaks.
			setTxPower(fftArray);		

			#ifdef RAMP_TEST
			{
				i16			sample;
				iCplx		*ifftBuf;

				ifftBuf = fftArray;
				for(sample = 0; sample < (FFT_LEN); sample++ )
				{
					(ifftBuf++)->re = ((sample-128)<<4)+(frame<<9)-(block<<10);
				}
			}
			#endif						

			//---- do windowing on the signal ----------------------------------------------
			ifftBuf = fftArray + (FFT_LEN - CYCLIC_PREFIX_LEN);	// Calc windowed part of prefix
			for( n = 0; n < WINDOW_LEN ; n++ )
			{
				prefix[n] = ( (i32)((ifftBuf++)->re) * FrameWindow[n] ) >> WINDOW_SCALE;
				prefix[n] += postfix[n];
			}
			for( n = WINDOW_LEN; n < CYCLIC_PREFIX_LEN ; n++ )	// Copy remaining part of prefix
			{
				prefix[n] = (ifftBuf++)->re;
			}
			ifftBuf = fftArray;									// Get overlap for next frame
			for( n = 0; n < WINDOW_LEN ; n++ )
			{
				postfix[n] = ( (i32)((ifftBuf++)->re) * (256-FrameWindow[n]) ) >> WINDOW_SCALE;
			}

			//---- construct the cyclic prefix from the last chunk of the data frame-----
			TxStart = CalcTxStartAddr(pTxSignal, FFT_LEN + CYCLIC_PREFIX_LEN);	// Find a free space in Tx buffer
			pTxSignal = FillAFETxBuffI16 (TxStart, prefix, CYCLIC_PREFIX_LEN);

			//---- construct the data frame ---------------
			pTxSignal = FillAFETxBuffCplx (pTxSignal, fftArray, FFT_LEN );

			JamDMAReloadRegs(TxStart, FFT_LEN + CYCLIC_PREFIX_LEN);
			INTR_ENABLE(TINT0); 			// Re-Enable Timer0 Interrupt	//???

		}	// end frame loop
	}	// end block loop

	prevSnrSample = ReadRxDMAPointer() - recSignalArray;	// Let SNR calc re-start here					

	//---- append postfix to end of packet ---------------
	TxStart = CalcTxStartAddr(pTxSignal, WINDOW_LEN);	// Find a free space in Tx buffer
	pTxSignal = FillAFETxBuffI16 (TxStart, postfix, WINDOW_LEN);
	JamDMAReloadRegs(TxStart, WINDOW_LEN);

	//--- Set the DMA to switch back to idle pattern when the last block finishes -------
	JamDMAReloadRegs((TXDATA*)IdleBuffArray, IDLE_BUFFER_LEN);
	

	#if DEBUGIT == DEBUG_DISTANCE2
		mexPutArray(diagArray, "caller");
	#endif
	
	#if SAVETRACE == TRUE
		SaveTraceData(0x5002);				// Put a marker in the trace buffer
		SaveTraceData((u16)recSignal);		// at the end of a transmit opperation
		SaveTraceData((u16)pTxSignal);		// 
	#endif

	return pTxSignal;
}


//==========================================================================================
// Function:		getPrePhases()
//
// Description: 	Calculate symbols to fill carriers for preamble part of packet.
//					Non-differential phase is passed in *preamble.
// Return:			Double-summed phase is returned in *phase.
//
// Revision History:
//==========================================================================================
void getPrePhases( iCplx *phase, const i16 *preamble )
{
	i16			n;
	i16			cPhase  = 0;
	i16			ccPhase = 0;

	for( n = 0; n < CARRIER_LEN;  n++ )
	{
	    cPhase  += *preamble++;		// 1st cumulative sum
	    ccPhase += cPhase;			// 2nd cum sum
	    ccPhase &= 3;				// mod 4

		phase->re = complexMap[ccPhase].re;	// map to complex quantity
		phase->im = complexMap[ccPhase].im;		
		phase++;
	}
	
	return;
}


//==========================================================================================
// Function:		getSyncPhases()
//
// Description: 	Calculate symbols to fill carriers for sync frame part of packet.
//					Non-differential phase is passed in *preamble.
// Return:			Double-summed phase is returned in *phase.
//
// Revision History:
//==========================================================================================
void getSyncPhases( iCplx *phase, const i16 *preamble )
{
	i16			n;
	i16			sync;
	i16			cPhase  = 0;
	i16			ccPhase = 0;

	static const i16	syncTable[] = {2, 3, 0, 1};

	for( n = 0; n < CARRIER_LEN;  n++ )
	{
		sync = syncTable[*preamble++];
	    cPhase  += sync;			// 1st cumulative sum
	    ccPhase += cPhase;			// 2nd cum sum
	    ccPhase &= 3;				// mod 4

		phase->re = complexMap[ccPhase].re;	// map to complex quantity
		phase->im = complexMap[ccPhase].im;		
		phase++;
	}
	
	return;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -