diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index b60496a9..a7c629e2 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -57,15 +57,12 @@ Transceiver::Transceiver(int wBasePort, mControlSocket(wBasePort+1,TRXAddress,wBasePort+101), mClockSocket(wBasePort,TRXAddress,wBasePort+100) { - //GSM::Time startTime(0,0); - //GSM::Time startTime(gHyperframe/2 - 4*216*60,0); GSM::Time startTime(random() % gHyperframe,0); mFIFOServiceLoopThread = new Thread(32768); ///< thread to push bursts into transmit FIFO 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; @@ -75,54 +72,65 @@ Transceiver::Transceiver(int wBasePort, mRadioInterface->getClock()->set(startTime); mMaxExpectedDelay = 0; - // generate pulse and setup up signal processing library - gsmPulse = generateGSMPulse(2, mSPS); - LOG(DEBUG) << "gsmPulse: " << *gsmPulse; - sigProcLibSetup(mSPS); - txFullScale = mRadioInterface->fullScaleInputValue(); rxFullScale = mRadioInterface->fullScaleOutputValue(); - // initialize filler tables with dummy bursts, initialize other per-timeslot variables - for (int i = 0; i < 8; i++) { - signalVector* modBurst = modulateBurst(gDummyBurst,*gsmPulse, - 8 + (i % 4 == 0), - mSPS); - scaleVector(*modBurst,txFullScale); - fillerModulus[i]=26; - for (int j = 0; j < 102; j++) { - fillerTable[j][i] = new signalVector(*modBurst); - } - delete modBurst; - mChanType[i] = NONE; - channelResponse[i] = NULL; - DFEForward[i] = NULL; - DFEFeedback[i] = NULL; - channelEstimateTime[i] = startTime; - } - mOn = false; mTxFreq = 0.0; mRxFreq = 0.0; mPower = -10; mEnergyThreshold = INIT_ENERGY_THRSHD; prevFalseDetectionTime = startTime; + } Transceiver::~Transceiver() { - delete gsmPulse; sigProcLibDestroy(); mTransmitPriorityQueue.clear(); } - + +bool Transceiver::init() +{ + if (!sigProcLibSetup(mSPS)) { + LOG(ALERT) << "Failed to initialize signal processing library"; + return false; + } + + // initialize filler tables with dummy bursts + for (int i = 0; i < 8; i++) { + signalVector* modBurst = modulateBurst(gDummyBurst, + 8 + (i % 4 == 0), + mSPS); + if (!modBurst) { + sigProcLibDestroy(); + LOG(ALERT) << "Failed to initialize filler table"; + return false; + } + + scaleVector(*modBurst,txFullScale); + fillerModulus[i]=26; + for (int j = 0; j < 102; j++) { + fillerTable[j][i] = new signalVector(*modBurst); + } + + delete modBurst; + mChanType[i] = NONE; + channelResponse[i] = NULL; + DFEForward[i] = NULL; + DFEFeedback[i] = NULL; + channelEstimateTime[i] = mTransmitDeadlineClock; + } + + return true; +} void Transceiver::addRadioVector(BitVector &burst, int RSSI, GSM::Time &wTime) { // modulate and stick into queue - signalVector* modBurst = modulateBurst(burst,*gsmPulse, + signalVector* modBurst = modulateBurst(burst, 8 + (wTime.TN() % 4 == 0), mSPS); scaleVector(*modBurst,txFullScale * pow(10,-RSSI/10)); @@ -135,10 +143,7 @@ void Transceiver::addRadioVector(BitVector &burst, #ifdef TRANSMIT_LOGGING void Transceiver::unModulateVector(signalVector wVector) { - SoftVector *burst = demodulateBurst(wVector, - *gsmPulse, - mSPS, - 1.0,0.0); + SoftVector *burst = demodulateBurst(wVector, mSPS, 1.0, 0.0); LOG(DEBUG) << "LOGGED BURST: " << *burst; /* @@ -415,7 +420,6 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, if ((rxBurst) && (success)) { if ((corrType==RACH) || (!needDFE)) { burst = demodulateBurst(*vectorBurst, - *gsmPulse, mSPS, amplitude,TOA); } @@ -497,7 +501,7 @@ void Transceiver::driveControl() // Prepare for thread start mPower = -20; mRadioInterface->start(); - generateRACHSequence(*gsmPulse, mSPS); + generateRACHSequence(mSPS); // Start radio interface threads. mFIFOServiceLoopThread->start((void * (*)(void*))FIFOServiceLoopAdapter,(void*) this); @@ -589,8 +593,8 @@ void Transceiver::driveControl() sprintf(response,"RSP SETTSC 1 %d",TSC); else { mTSC = TSC; - generateMidamble(*gsmPulse, mSPS, TSC); - sprintf(response,"RSP SETTSC 0 %d",TSC); + generateMidamble(mSPS, TSC); + sprintf(response,"RSP SETTSC 0 %d", TSC); } } else if (strcmp(command,"SETSLOT")==0) { diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index 91d92b2f..31752130 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -124,8 +124,6 @@ private: /** send messages over the clock socket */ void writeClockInterface(void); - signalVector *gsmPulse; ///< the GSM shaping pulse for modulation - int mSPS; ///< number of samples per GSM symbol bool mOn; ///< flag to indicate that transceiver is powered on @@ -168,6 +166,7 @@ public: /** start the Transceiver */ void start(); + bool init(); /** attach the radioInterface receive FIFO */ void receiveFIFO(VectorFIFO *wFIFO) { mReceiveFIFO = wFIFO;} diff --git a/Transceiver52M/sigProcLib.cpp b/Transceiver52M/sigProcLib.cpp index b7f35118..ab605cf5 100644 --- a/Transceiver52M/sigProcLib.cpp +++ b/Transceiver52M/sigProcLib.cpp @@ -58,8 +58,27 @@ typedef struct { complex gain; } CorrelationSequence; +/* + * Gaussian and empty modulation pulses + */ +struct PulseSequence { + PulseSequence() : gaussian(NULL), empty(NULL) + { + } + + ~PulseSequence() + { + delete gaussian; + delete empty; + } + + signalVector *gaussian; + signalVector *empty; +}; + CorrelationSequence *gMidambles[] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}; CorrelationSequence *gRACHSequence = NULL; +PulseSequence *GSMPulse = NULL; void sigProcLibDestroy(void) { if (GMSKRotation) { @@ -234,6 +253,7 @@ void sigProcLibSetup(int sps) { initTrigTables(); initGMSKRotationTables(sps); + generateGSMPulse(sps, 2); } void GMSKRotate(signalVector &x) { @@ -439,25 +459,36 @@ signalVector* convolve(const signalVector *a, } -signalVector* generateGSMPulse(int sps, int symbolLength) +void generateGSMPulse(int sps, int symbolLength) { + int len; + float arg, center; - int numSamples = sps * symbolLength + 1; - signalVector *x = new signalVector(numSamples); - signalVector::iterator xP = x->begin(); - int centerPoint = (numSamples-1)/2; - for (int i = 0; i < numSamples; i++) { - float arg = (float) (i - centerPoint) / (float) sps; - *xP++ = 0.96*exp(-1.1380*arg*arg-0.527*arg*arg*arg*arg); // GSM pulse approx. + delete GSMPulse; + + /* Store a single tap filter used for correlation sequence generation */ + GSMPulse = new PulseSequence(); + GSMPulse->empty = new signalVector(1); + GSMPulse->empty->isRealOnly(true); + *(GSMPulse->empty->begin()) = 1.0f; + + /* GSM pulse approximation */ + GSMPulse->gaussian = new signalVector(len); + GSMPulse->gaussian->isRealOnly(true); + signalVector::iterator xP = GSMPulse->gaussian->begin(); + + center = (float) (len - 1.0) / 2.0; + + for (int i = 0; i < len; i++) { + arg = ((float) i - center) / (float) sps; + *xP++ = 0.96 * exp(-1.1380 * arg * arg - + 0.527 * arg * arg * arg * arg); } - float avgAbsval = sqrtf(vectorNorm2(*x) / sps); - xP = x->begin(); - for (int i = 0; i < numSamples; i++) + float avgAbsval = sqrtf(vectorNorm2(*GSMPulse->gaussian)/sps); + xP = GSMPulse->gaussian->begin(); + for (int i = 0; i < len; i++) *xP++ /= avgAbsval; - x->isRealOnly(true); - x->setSymmetry(ABSSYM); - return x; } signalVector* frequencyShift(signalVector *y, @@ -564,36 +595,22 @@ bool vectorSlicer(signalVector *x) return true; } -signalVector *modulateBurst(const BitVector &wBurst, - const signalVector &gsmPulse, - int guardPeriodLength, - int sps) +signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength, + int sps, bool emptyPulse) { + int burstLen; + signalVector *pulse, modBurst; + signalVector::iterator modBurstItr; - //static complex staticBurst[157]; + if (emptyPulse) + pulse = GSMPulse->empty; + else + pulse = GSMPulse->gaussian; - int burstSize = sps * (wBurst.size() + guardPeriodLength); - //signalVector modBurst((complex *) staticBurst,0,burstSize); - signalVector modBurst(burstSize);// = new signalVector(burstSize); - modBurst.isRealOnly(true); - //memset(staticBurst,0,sizeof(complex)*burstSize); - modBurst.fill(0.0); - signalVector::iterator modBurstItr = modBurst.begin(); + burstLen = sps * (wBurst.size() + guardPeriodLength); + modBurst = signalVector(burstLen); + modBurstItr = modBurst.begin(); -#if 0 - // if wBurst is already differentially decoded - *modBurstItr = 2.0*(wBurst[0] & 0x01)-1.0; - signalVector::iterator prevVal = modBurstItr; - for (unsigned int i = 1; i < wBurst.size(); i++) { - modBurstItr += sps; - if (wBurst[i] & 0x01) - *modBurstItr = *prevVal * complex(0.0,1.0); - else - *modBurstItr = *prevVal * complex(0.0,-1.0); - prevVal = modBurstItr; - } -#else - // if wBurst are the raw bits for (unsigned int i = 0; i < wBurst.size(); i++) { *modBurstItr = 2.0*(wBurst[i] & 0x01)-1.0; modBurstItr += sps; @@ -602,16 +619,13 @@ signalVector *modulateBurst(const BitVector &wBurst, // shift up pi/2 // ignore starting phase, since spec allows for discontinuous phase GMSKRotate(modBurst); -#endif + modBurst.isRealOnly(false); // filter w/ pulse shape - signalVector *shapedBurst = convolve(&modBurst,&gsmPulse,NULL,NO_DELAY); + signalVector *shapedBurst = convolve(&modBurst, pulse, NULL, NO_DELAY); - //delete modBurst; - return shapedBurst; - } float sinc(float x) @@ -837,11 +851,8 @@ void offsetVector(signalVector &x, } } -bool generateMidamble(signalVector &gsmPulse, - int sps, - int TSC) +bool generateMidamble(int sps, int TSC) { - if ((TSC < 0) || (TSC > 7)) return false; @@ -850,18 +861,13 @@ bool generateMidamble(signalVector &gsmPulse, if (gMidambles[TSC]->sequenceReversedConjugated!=NULL) delete gMidambles[TSC]->sequenceReversedConjugated; } - signalVector emptyPulse(1); - *(emptyPulse.begin()) = 1.0; - // only use middle 16 bits of each TSC signalVector *middleMidamble = modulateBurst(gTrainingSequence[TSC].segment(5,16), - emptyPulse, 0, - sps); + sps, true); signalVector *midamble = modulateBurst(gTrainingSequence[TSC], - gsmPulse, 0, - sps); + sps, false); if (midamble == NULL) return false; if (middleMidamble == NULL) return false; @@ -895,17 +901,14 @@ bool generateMidamble(signalVector &gsmPulse, return true; } -bool generateRACHSequence(signalVector &gsmPulse, - int sps) +bool generateRACHSequence(int sps) { - if (gRACHSequence) { if (gRACHSequence->sequence!=NULL) delete gRACHSequence->sequence; if (gRACHSequence->sequenceReversedConjugated!=NULL) delete gRACHSequence->sequenceReversedConjugated; } signalVector *RACHSeq = modulateBurst(gRACHSynchSequence, - gsmPulse, 0, sps); @@ -1136,12 +1139,8 @@ signalVector *decimateVector(signalVector &wVector, } -SoftVector *demodulateBurst(signalVector &rxBurst, - const signalVector &gsmPulse, - int sps, - complex channel, - float TOA) - +SoftVector *demodulateBurst(signalVector &rxBurst, int sps, + complex channel, float TOA) { scaleVector(rxBurst,((complex) 1.0)/channel); delayVector(rxBurst,-TOA); diff --git a/Transceiver52M/sigProcLib.h b/Transceiver52M/sigProcLib.h index e91644c7..a9fabb0d 100644 --- a/Transceiver52M/sigProcLib.h +++ b/Transceiver52M/sigProcLib.h @@ -125,7 +125,7 @@ signalVector* convolve(const signalVector *a, @param symbolLength The size of the pulse. @return The GSM pulse. */ -signalVector* generateGSMPulse(int sps, int symbolLength); +void generateGSMPulse(int sps, int symbolLength); /** Frequency shift a vector. @@ -162,9 +162,8 @@ bool vectorSlicer(signalVector *x); /** GMSK modulate a GSM burst of bits */ signalVector *modulateBurst(const BitVector &wBurst, - const signalVector &gsmPulse, int guardPeriodLength, - int sps); + int sps, bool emptyPulse = false); /** Sinc function */ float sinc(float x); @@ -229,15 +228,14 @@ void offsetVector(signalVector &x, @param TSC The training sequence [0..7] @return Success. */ -bool generateMidamble(signalVector &gsmPulse, int sps, int tsc); +bool generateMidamble(int sps, int tsc); /** Generate a modulated RACH sequence, stored within the library. @param gsmPulse The GSM pulse used for modulation. @param sps The number of samples per GSM symbol. @return Success. */ -bool generateRACHSequence(signalVector &gsmPulse, - int sps); +bool generateRACHSequence(int sps); /** Energy detector, checks to see if received burst energy is above a threshold. @@ -310,11 +308,8 @@ signalVector *decimateVector(signalVector &wVector, @param TOA The time-of-arrival of the received burst. @return The demodulated bit sequence. */ -SoftVector *demodulateBurst(signalVector &rxBurst, - const signalVector &gsmPulse, - int sps, - complex channel, - float TOA); +SoftVector *demodulateBurst(signalVector &rxBurst, int sps, + complex channel, float TOA); /** Creates a simple Kaiser-windowed low-pass FIR filter.