📄 transmit.c
字号:
//==========================================================================================
// 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 + -