📄 modemtx.c
字号:
#include "modemtx.h"
#include "razedcos.h" /* table for raised cosine shaping filter */
#include "sinetab.h" /* sine look-up table */
/* definition of constelation space */
struct POINT constellation[NUM_CONSTELATION_POINTS] =
{
/* first quadrant */
{0x1000, 0x1000},
{0x3000, 0x3000},
{0x1000, 0x3000},
{0x3000, 0x1000},
/* second quadrant */
{-0x1000, 0x1000},
{-0x3000, 0x3000},
{-0x1000, 0x3000},
{-0x3000, 0x1000},
/* third quadrant */
{-0x1000, -0x1000},
{-0x3000, -0x3000},
{-0x1000, -0x3000},
{-0x3000, -0x1000},
/* fourth quadrant */
{0x1000, -0x1000},
{0x3000, -0x3000},
{0x1000, -0x3000},
{0x3000, -0x1000},
};
/* global structures */
struct MODEM_PARAMETERS g_ModemData;
struct TEST
{
long i;
long j;
} g_test;
/*******************************************************
SineLookup()
============
This function returns a sine function. It is
implemented with a 1/4 wave look up table. To
*******************************************************/
int SineLookup(int sample)
{
int sineValue;
/* Find offset into 1/4 wave table, adjusting
for quadrants 2 and 4 */
int offset = sample & (SIZE_SINE_TABLE-1);
if (sample & SIZE_SINE_TABLE)
offset = SIZE_SINE_TABLE-1-offset;
/* Read value from sine table,
adjusting the sign for quadrants 3 and 4 */
sineValue = sineTable[offset];
if (sample & (SIZE_SINE_TABLE*2))
sineValue = -sineValue;
return(sineValue);
}
/*******************************************************
CosineLookup()
==============
This function returns a cosine function. It is
implemented by calling the SineLookup() function
and adjusting the phase.
*******************************************************/
int CosineLookup(int sample)
{
return( SineLookup(sample + SIZE_SINE_TABLE) );
}
/*******************************************************
Modulation()
==============
This function the modulated result of an in-phase
and quadrature phase component, added together.
*******************************************************/
int Modulation(int Isample, int Qsample, int phase)
{
#if defined(PROD_C6X)
/* work-around C6x compiler bug when using long multiplication */
long result = (short)Isample * (short)SineLookup(phase);
result += (short)Qsample * (short)CosineLookup(phase);
#else
long result = (long)Isample * (long)SineLookup(phase);
result += (long)Qsample * (long)CosineLookup(phase);
#endif
result >>= 14;
return((int)result);
}
/*******************************************************
ShapingFilter()
===============
This function shapes either the in-phase or
quadrature phase component using a raised cosine
filter. The user must pass in a delayLine big
enough to hold the shaping filter. The output
is calculated one baud at a time, and is found at
the front of the delay line.
*******************************************************/
void ShapingFilter(int *delayLine, int amplitudeOfSymbol)
{
int i;
/* shift the delay line */
for(i = 0; i < SIZE_SHAPING_FILTER - SAMPLES_PER_BAUD; i++ )
{
delayLine[i] = delayLine[i+SAMPLES_PER_BAUD];
}
/* clear end of delay buffer before addition operation */
for( ; i < SIZE_SHAPING_FILTER; i++ )
{
delayLine[i] = 0;
}
/* add new symbol into delay line */
for( i = SIZE_SHAPING_FILTER; i--; )
{
#if defined(PROD_C6X)
delayLine[i] += (((short)raisedCosineTable[i] * (short)amplitudeOfSymbol)>>14);
#else
delayLine[i] += ((raisedCosineTable[i] * (long)amplitudeOfSymbol)>>14);
#endif
}
}
/*******************************************************
ModemTransitter()
=================
This function runs the Tx modulator to generate one
baud of output signal. This function calls the
ShapingFilter() function to generate I and Q samples,
then modulates by the carrier frequency and adds the
I and Q together.
*******************************************************/
void ModemTransmitter(int baudIndex, int *outputBuffer)
{
/* local variables */
int Iamplitude; /* Quadrature component amplitude */
// int Qamplitude; /* Quadrature component amplitude */
// int n; /* loop index for each baud */
//static struct POINT ConstellationPoint;
/*******************
1. Look up in-phase and quadrature amplitudes
********************/
Iamplitude = g_ModemData.cPoints[baudIndex].I;
// Qamplitude = g_ModemData.cPoints[baudIndex].Q;
/*******************
2. Run in-phase and quadrature components through baseband
shaping filter, with interpolation
********************/
ShapingFilter(g_ModemData.Idelay, Iamplitude);
/*RP:TEMP ShapingFilter(g_ModemData.Qdelay, Qamplitude); */
/*******************
4. Modulate the in-phase and quadrature components to
generate the output signal from the transmitter
********************/
/*RP:TEMP
for (n = 0; n < SAMPLES_PER_BAUD; n++ )
{
outputBuffer[n] = Modulation(g_ModemData.Idelay[n],
g_ModemData.Qdelay[n], g_ModemData.phase);
increment phase for next pass
g_ModemData.phase += g_ModemData.carrierFreq;
} */
}
/*******************************************************
Initialize()
============
This function initializes the global modem parameter
structure;
*******************************************************/
void Initialize(void)
{
int i;
#if defined(C54X)
asm(" RSBX OVM");
#endif
g_ModemData.carrierFreq = 15; /* increment through 125Hz sine table */
g_ModemData.phase = 0; /* initialize phase for carrier */
g_ModemData.samplesPerBaud = SAMPLES_PER_BAUD;
g_ModemData.noiseLevel = 0;
/* zero delay lines for shaping filter */
for( i = SIZE_SHAPING_FILTER; i--; )
{
g_ModemData.Idelay[i] = 0;
g_ModemData.Qdelay[i] = 0;
}
/* clear output buffer */
for( i = SAMPLES_PER_BAUD*BAUD_PER_LOOP; i--; )
{
g_ModemData.OutputBuffer[i] = 0;
}
/* clear data, constellation, and noise buffers */
for( i = BAUD_PER_LOOP; i--; )
{
g_ModemData.dataSymbols[i] = 0;
g_ModemData.cPoints[i].I = 0;
g_ModemData.cPoints[i].Q = 0;
g_ModemData.cNoise[i].I = 0;
g_ModemData.cNoise[i].Q = 0;
}
for( i = BAUD_PER_LOOP; i--; )
{
int j;
g_ModemData.SymbolClock[i*SAMPLES_PER_BAUD] = 1;
for( j = SAMPLES_PER_BAUD; --j > 0; )
{
g_ModemData.SymbolClock[i*SAMPLES_PER_BAUD+j] = -1;
}
}
}
/* read next data, convert to constellation points, and add noise */
void ReadNextData(void)
{
/* add code here to generate modem data */
ReadConstellation();
}
/* convert data to constellation points and add noise */
void ReadConstellation(void)
{
AddNoiseSignal();
}
/*******************************************************
AddNoiseSignal()
================
This function adds noise to the constellation points
for the modem transmitter;
*******************************************************/
void AddNoiseSignal(void)
{
/* Add code here to read noise signal from disk */
int i;
int noiseVolume = 10 - g_ModemData.noiseLevel;
for( i = BAUD_PER_LOOP; i--; )
{
/* convert data to constellation points */
g_ModemData.cPoints[i] = constellation[(g_ModemData.dataSymbols[i])&15];
/* Add noise to constellation points, only if level not zero */
if (g_ModemData.noiseLevel != 0)
{
if (noiseVolume < 0)
{
/* if volume is negative, shift to the left */
g_ModemData.cPoints[i].I += (g_ModemData.cNoise[i].I << (-noiseVolume));
g_ModemData.cPoints[i].Q += (g_ModemData.cNoise[i].Q << (-noiseVolume));
}
else
{
g_ModemData.cPoints[i].I += (g_ModemData.cNoise[i].I >> noiseVolume);
g_ModemData.cPoints[i].Q += (g_ModemData.cNoise[i].Q >> noiseVolume);
}
}
}
}
/*******************************************************
Main()
======
Main loop for modem transmitter example program.
*******************************************************/
void main(void)
{
int i;
g_test.i = -16;
g_test.j = 0x12345678;
g_test.j <<= 4;
g_test.i *= g_test.j;
/* Initialize modem transmitter */
Initialize();
/* testing the carrier signal generator */
for(i = 0; i < SAMPLES_PER_BAUD; i++ )
{
g_ModemData.OutputBuffer[i] = SineLookup(i*g_ModemData.carrierFreq);
}
for(i = 0; i < SAMPLES_PER_BAUD; i++ )
{
g_ModemData.OutputBuffer[i] = CosineLookup(i*g_ModemData.carrierFreq);
}
/* loop forever */
while(1)
{
/* get modem data, convert to constellation points, and add noise. */
ReadNextData();
/* run modem on new data */
for( i = 0; i < BAUD_PER_LOOP; i++ )
{
ModemTransmitter(i, &(g_ModemData.OutputBuffer[i*SAMPLES_PER_BAUD]));
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -