Transceiver52M: Setup dual sample rate transceiver

This patch applies oversampling, when selected with 4 sps,
to the downlink only, while running the receiver with
minimal sampling at 1 sps. These split sample rates allow
us to run a highly accurate downlink signal with minimal
distortion, while keeping receive path channel filtering
on the FPGA.

Without this patch, we oversample the receive path and
require a steep receive filter to get similar adjacent
channel suppression as the FPGA halfband / CIC filter
combination, which comes with a high computational cost.

Signed-off-by: Thomas Tsou <tom@tsou.cc>

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@6747 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
Thomas Tsou 2013-10-17 06:19:05 +00:00
parent 8652b22386
commit 22bc28edc4
10 changed files with 229 additions and 162 deletions

View file

@ -53,7 +53,8 @@ Transceiver::Transceiver(int wBasePort,
RadioInterface *wRadioInterface)
:mDataSocket(wBasePort+2,TRXAddress,wBasePort+102),
mControlSocket(wBasePort+1,TRXAddress,wBasePort+101),
mClockSocket(wBasePort,TRXAddress,wBasePort+100)
mClockSocket(wBasePort,TRXAddress,wBasePort+100),
mSPSTx(wSPS), mSPSRx(1)
{
GSM::Time startTime(random() % gHyperframe,0);
@ -62,7 +63,6 @@ Transceiver::Transceiver(int wBasePort,
mControlServiceLoopThread = new Thread(32768); ///< thread to process control messages from GSM core
mTransmitPriorityQueueServiceLoopThread = new Thread(32768);///< thread to process transmit bursts from GSM core
mSPS = wSPS;
mRadioInterface = wRadioInterface;
mTransmitLatency = wTransmitLatency;
mTransmitDeadlineClock = startTime;
@ -92,7 +92,7 @@ Transceiver::~Transceiver()
bool Transceiver::init()
{
if (!sigProcLibSetup(mSPS)) {
if (!sigProcLibSetup(mSPSTx)) {
LOG(ALERT) << "Failed to initialize signal processing library";
return false;
}
@ -101,7 +101,7 @@ bool Transceiver::init()
for (int i = 0; i < 8; i++) {
signalVector* modBurst = modulateBurst(gDummyBurst,
8 + (i % 4 == 0),
mSPS);
mSPSTx);
if (!modBurst) {
sigProcLibDestroy();
LOG(ALERT) << "Failed to initialize filler table";
@ -133,7 +133,7 @@ radioVector *Transceiver::fixRadioVector(BitVector &burst,
// modulate and stick into queue
signalVector* modBurst = modulateBurst(burst,
8 + (wTime.TN() % 4 == 0),
mSPS);
mSPSTx);
scaleVector(*modBurst,txFullScale * pow(10,-RSSI/10));
radioVector *newVec = new radioVector(*modBurst,wTime);
@ -146,7 +146,7 @@ radioVector *Transceiver::fixRadioVector(BitVector &burst,
#ifdef TRANSMIT_LOGGING
void Transceiver::unModulateVector(signalVector wVector)
{
SoftVector *burst = demodulateBurst(wVector, mSPS, 1.0, 0.0);
SoftVector *burst = demodulateBurst(wVector, mSPSTx, 1.0, 0.0);
LOG(DEBUG) << "LOGGED BURST: " << *burst;
/*
@ -352,7 +352,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
float TOA = 0.0;
float avgPwr = 0.0;
#ifdef ENERGY_DETECT
if (!energyDetect(*vectorBurst, 20 * mSPS, mEnergyThreshold, &avgPwr)) {
if (!energyDetect(*vectorBurst, 20 * mSPSRx, mEnergyThreshold, &avgPwr)) {
LOG(DEBUG) << "Estimated Energy: " << sqrt(avgPwr) << ", at time " << rxBurst->getTime();
double framesElapsed = rxBurst->getTime()-prevFalseDetectionTime;
if (framesElapsed > 50) { // if we haven't had any false detections for a while, lower threshold
@ -388,7 +388,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
success = analyzeTrafficBurst(*vectorBurst,
mTSC,
5.0,
mSPS,
mSPSRx,
&amplitude,
&TOA,
mMaxExpectedDelay,
@ -421,11 +421,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
}
else {
// RACH burst
success = detectRACHBurst(*vectorBurst,
6.0,
mSPS,
&amplitude,
&TOA);
success = detectRACHBurst(*vectorBurst, 6.0, mSPSRx, &amplitude, &TOA);
if (success) {
LOG(DEBUG) << "FOUND RACH!!!!!! " << amplitude << " " << TOA;
mEnergyThreshold -= (1.0F/10.0F);
@ -444,22 +440,19 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime,
SoftVector *burst = NULL;
if ((rxBurst) && (success)) {
if ((corrType==RACH) || (!needDFE)) {
burst = demodulateBurst(*vectorBurst,
mSPS,
amplitude,TOA);
}
else { // TSC
burst = demodulateBurst(*vectorBurst, mSPSRx, amplitude, TOA);
} else {
scaleVector(*vectorBurst,complex(1.0,0.0)/amplitude);
burst = equalizeBurst(*vectorBurst,
TOA-chanRespOffset[timeslot],
mSPS,
mSPSRx,
*DFEForward[timeslot],
*DFEFeedback[timeslot]);
}
wTime = rxBurst->getTime();
RSSI = (int) floor(20.0*log10(rxFullScale/amplitude.abs()));
LOG(DEBUG) << "RSSI: " << RSSI;
timingOffset = (int) round(TOA * 256.0 / mSPS);
timingOffset = (int) round(TOA * 256.0 / mSPSRx);
}
//if (burst) LOG(DEBUG) << "burst: " << *burst << '\n';
@ -618,7 +611,7 @@ void Transceiver::driveControl()
sprintf(response,"RSP SETTSC 1 %d",TSC);
else {
mTSC = TSC;
generateMidamble(mSPS, TSC);
generateMidamble(mSPSRx, TSC);
sprintf(response,"RSP SETTSC 0 %d", TSC);
}
}