diff options
-rw-r--r-- | Transceiver52M/DriveLoop.cpp | 56 | ||||
-rw-r--r-- | Transceiver52M/DriveLoop.h | 33 | ||||
-rw-r--r-- | Transceiver52M/Transceiver.cpp | 120 | ||||
-rw-r--r-- | Transceiver52M/Transceiver.h | 15 | ||||
-rw-r--r-- | Transceiver52M/multiTRX.cpp | 69 | ||||
-rw-r--r-- | Transceiver52M/radioInterface.cpp | 21 | ||||
-rw-r--r-- | Transceiver52M/radioInterface.h | 10 |
7 files changed, 174 insertions, 150 deletions
diff --git a/Transceiver52M/DriveLoop.cpp b/Transceiver52M/DriveLoop.cpp index c925d20..1f1ea7c 100644 --- a/Transceiver52M/DriveLoop.cpp +++ b/Transceiver52M/DriveLoop.cpp @@ -25,10 +25,13 @@ #include "DriveLoop.h" #include <Logger.h> -DriveLoop::DriveLoop(int wSamplesPerSymbol, +DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress, + int wChanM, int wC0, int wSamplesPerSymbol, GSM::Time wTransmitLatency, RadioInterface *wRadioInterface) + :mClockSocket(wBasePort, TRXAddress, wBasePort + 100), mC0(wC0) { + mChanM = wChanM; mRadioDriveLoopThread = NULL; mSamplesPerSymbol = wSamplesPerSymbol; mRadioInterface = wRadioInterface; @@ -38,6 +41,7 @@ DriveLoop::DriveLoop(int wSamplesPerSymbol, mTransmitDeadlineClock = mStartTime; mLatencyUpdateTime = mStartTime; mTransmitLatency = wTransmitLatency; + mLastClockUpdateTime = mStartTime; mRadioInterface->getClock()->set(mStartTime); @@ -48,18 +52,22 @@ DriveLoop::DriveLoop(int wSamplesPerSymbol, txFullScale = mRadioInterface->fullScaleInputValue(); - // initialize filler tables with dummy bursts, initialize other per-timeslot variables + // initialize filler tables with dummy bursts on C0, empty bursts otherwise for (int i = 0; i < 8; i++) { signalVector* modBurst = modulateBurst(gDummyBurst, *gsmPulse, 8 + (i % 4 == 0), mSamplesPerSymbol); scaleVector(*modBurst, txFullScale); for (int j = 0; j < 102; j++) { - for (int n = 0; n < CHAN_M; n++) - fillerTable[n][j][i] = new signalVector(*modBurst); + for (int n = 0; n < mChanM; n++) { + if (n == mC0) + fillerTable[n][j][i] = new signalVector(*modBurst); + else + fillerTable[n][j][i] = new signalVector(modBurst->size()); + } } delete modBurst; - for (int n = 0; n < CHAN_M; n++) { + for (int n = 0; n < mChanM; n++) { fillerModulus[n][i] = 26; mChanType[n][i] = NONE; } @@ -97,17 +105,19 @@ void DriveLoop::pushRadioVector(GSM::Time &nowTime) radioVector *staleBurst; radioVector *next; - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { // dump stale bursts, if any while (staleBurst = mTransmitPriorityQueue[i].getStaleBurst(nowTime)) { // Even if the burst is stale, put it in the fillter table. // (It might be an idle pattern.) LOG(NOTICE) << "dumping STALE burst in TRX->USRP interface"; - const GSM::Time& nextTime = staleBurst->getTime(); - int TN = nextTime.TN(); - int modFN = nextTime.FN() % fillerModulus[i][TN]; - delete fillerTable[i][modFN][TN]; - fillerTable[i][modFN][TN] = staleBurst; + if (i == mC0) { + const GSM::Time& nextTime = staleBurst->getTime(); + int TN = nextTime.TN(); + int modFN = nextTime.FN() % fillerModulus[i][TN]; + delete fillerTable[i][modFN][TN]; + fillerTable[i][modFN][TN] = staleBurst; + } } int TN = nowTime.TN(); @@ -120,16 +130,18 @@ void DriveLoop::pushRadioVector(GSM::Time &nowTime) // if queue contains data at the desired timestamp, stick it into FIFO if (next = (radioVector*) mTransmitPriorityQueue[i].getCurrentBurst(nowTime)) { LOG(DEBUG) << "transmitFIFO: wrote burst " << next << " at time: " << nowTime; - delete fillerTable[i][modFN][TN]; - fillerTable[i][modFN][TN] = new signalVector(*(next)); + if (i == mC0) { + delete fillerTable[i][modFN][TN]; + fillerTable[i][modFN][TN] = new signalVector(*(next)); + mIsFiller[i] = false; + } mTxBursts[i] = next; - mIsFiller[i] = false; } } mRadioInterface->driveTransmitRadio(mTxBursts, mIsZero); - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { if (!mIsFiller[i]) delete mTxBursts[i]; } @@ -255,6 +267,20 @@ void DriveLoop::driveTransmitFIFO() //else radioClock->wait(); } +void DriveLoop::writeClockInterface() +{ + char command[50]; + // FIXME -- This should be adaptive. + sprintf(command,"IND CLOCK %llu", + (unsigned long long) (mTransmitDeadlineClock.FN() + 2)); + + LOG(INFO) << "ClockInterface: sending " << command; + + mClockSocket.write(command,strlen(command)+1); + + mLastClockUpdateTime = mTransmitDeadlineClock; +} + void *RadioDriveLoopAdapter(DriveLoop *drive) { drive->setPriority(); diff --git a/Transceiver52M/DriveLoop.h b/Transceiver52M/DriveLoop.h index 593ef58..442d27c 100644 --- a/Transceiver52M/DriveLoop.h +++ b/Transceiver52M/DriveLoop.h @@ -50,10 +50,11 @@ private: GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock GSM::Time mLatencyUpdateTime; ///< last time latency was updated + GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core UDPSocket mClockSocket; ///< socket for writing clock updates to GSM core - VectorQueue mTransmitPriorityQueue[CHAN_M]; ///< priority queue of transmit bursts received from GSM core + VectorQueue mTransmitPriorityQueue[CHAN_MAX]; ///< priority queue of transmit bursts received from GSM core Thread *mRadioDriveLoopThread; ///< thread to push/pull bursts into transmit/receive FIFO @@ -64,6 +65,8 @@ private: double txFullScale; ///< full scale input to radio double rxFullScale; ///< full scale output to radio + /** Number of channels supported by the channelizer */ + int mChanM; /** unmodulate a modulated burst */ #ifdef TRANSMIT_LOGGING @@ -79,20 +82,20 @@ private: /** Pull and demodulate a burst from the receive FIFO */ SoftVector *pullRadioVector(GSM::Time &wTime, int &RSSI, int &timingOffset); - /** send messages over the clock socket */ - void writeClockInterface(void); - signalVector *gsmPulse; ///< the GSM shaping pulse for modulation int mSamplesPerSymbol; ///< number of samples per GSM symbol bool mOn; ///< flag to indicate that transceiver is powered on - int fillerModulus[CHAN_M][8]; ///< modulus values of all timeslots, in frames - signalVector *fillerTable[CHAN_M][102][8]; ///< table of modulated filler waveforms for all timeslots + int fillerModulus[CHAN_MAX][8]; ///< modulus values of all timeslots, in frames + signalVector *fillerTable[CHAN_MAX][102][8]; ///< table of modulated filler waveforms for all timeslots + + /** Channelizer path for primary ARFCN */ + int mC0; - signalVector *mTxBursts[CHAN_M]; - bool mIsFiller[CHAN_M]; - bool mIsZero[CHAN_M]; + signalVector *mTxBursts[CHAN_MAX]; + bool mIsFiller[CHAN_MAX]; + bool mIsZero[CHAN_MAX]; public: @@ -103,7 +106,8 @@ public: @param wTransmitLatency initial setting of transmit latency @param radioInterface associated radioInterface object */ - DriveLoop(int wSamplesPerSymbol, + DriveLoop(int wBasePort, const char *TRXAddress, + int wChanM, int wC0, int wSamplesPerSymbol, GSM::Time wTransmitLatency, RadioInterface *wRadioInterface); @@ -115,8 +119,6 @@ public: VectorQueue *priorityQueue(int m) { return &mTransmitPriorityQueue[m]; } - GSM::Time *deadlineClock() { return &mTransmitDeadlineClock; } - /** Codes for burst types of received bursts*/ typedef enum { OFF, ///< timeslot is off @@ -151,10 +153,15 @@ public: } GSM::Time getStartTime() { return mStartTime; } + GSM::Time getLastClockUpdate() { return mLastClockUpdateTime; } + GSM::Time getDeadlineClock() { return mTransmitDeadlineClock; } + + /** send messages over the clock socket */ + void writeClockInterface(void); private: - ChannelCombination mChanType[CHAN_M][8]; ///< channel types for all timeslots + ChannelCombination mChanType[CHAN_MAX][8]; ///< channel types for all timeslots protected: diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp index 81b0aad..b8d9d9d 100644 --- a/Transceiver52M/Transceiver.cpp +++ b/Transceiver52M/Transceiver.cpp @@ -53,12 +53,11 @@ Transceiver::Transceiver(int wBasePort, int wSamplesPerSymbol, RadioInterface *wRadioInterface, DriveLoop *wDriveLoop, - int wChannel) + int wChannel, bool wPrimary) :mDataSocket(wBasePort+2,TRXAddress,wBasePort+102), mControlSocket(wBasePort+1,TRXAddress,wBasePort+101), - mClockSocket(wBasePort,TRXAddress,wBasePort+100), mDriveLoop(wDriveLoop), mTransmitPriorityQueue(NULL), - mChannel(wChannel), mTSC(-1) + mChannel(wChannel), mPrimary(wPrimary), mTSC(-1) { mFIFOServiceLoopThread = NULL; mControlServiceLoopThread = NULL; @@ -66,11 +65,8 @@ Transceiver::Transceiver(int wBasePort, mSamplesPerSymbol = wSamplesPerSymbol; mRadioInterface = wRadioInterface; - mLastClockUpdateTime = mDriveLoop->getStartTime(); mMaxExpectedDelay = 0; - mTransmitDeadlineClock = wDriveLoop->deadlineClock(); - // generate pulse and setup up signal processing library gsmPulse = generateGSMPulse(2,mSamplesPerSymbol); LOG(DEBUG) << "gsmPulse: " << *gsmPulse; @@ -93,11 +89,15 @@ Transceiver::Transceiver(int wBasePort, mRunning = false; mTxFreq = 0.0; mRxFreq = 0.0; + + if (mPrimary) + mFreqOffset = mChannel * CHAN_RATE; + else + mFreqOffset = 0.0; + mPower = -10; mEnergyThreshold = INIT_ENERGY_THRSHD; prevFalseDetectionTime = mDriveLoop->getStartTime(); - - mRadioLocked = mRadioInterface->started(); } Transceiver::~Transceiver() @@ -172,6 +172,7 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, bool success = false; if (corrType == DriveLoop::TSC) { LOG(DEBUG) << "looking for TSC at time: " << rxBurst->getTime(); + signalVector *channelResp; double framesElapsed = rxBurst->getTime()-channelEstimateTime[timeslot]; bool estimateChannel = false; @@ -314,6 +315,15 @@ void Transceiver::start() mRunning = true; mControlServiceLoopThread = new Thread(32768); mControlServiceLoopThread->start((void * (*)(void*))ControlServiceLoopAdapter,(void*) this); + + if (!mPrimary) { + mOn = true; + mFIFOServiceLoopThread = new Thread(32768); + mFIFOServiceLoopThread->start((void * (*)(void*))FIFOServiceLoopAdapter,(void*) this); + + mTransmitPriorityQueueServiceLoopThread = new Thread(32768); + mTransmitPriorityQueueServiceLoopThread->start((void * (*)(void*))TransmitPriorityQueueServiceLoopAdapter,(void*) this); + } } void Transceiver::shutdown() @@ -359,7 +369,7 @@ void Transceiver::driveControl() sscanf(buffer,"%3s %s",cmdcheck,command); - writeClockInterface(); + mDriveLoop->writeClockInterface(); if (strcmp(cmdcheck,"CMD")!=0) { LOG(WARNING) << "bogus message on control interface"; @@ -377,22 +387,22 @@ void Transceiver::driveControl() sprintf(response,"RSP POWERON 1"); else { sprintf(response,"RSP POWERON 0"); - if (!mOn) { + if (mPrimary && !mOn) { // Prepare for thread start mPower = -20; - if (mRadioInterface->start()) - mDriveLoop->start(); + mRadioInterface->start(); + mDriveLoop->start(); + mDriveLoop->writeClockInterface(); generateRACHSequence(*gsmPulse,mSamplesPerSymbol); // Start radio interface threads. mOn = true; mFIFOServiceLoopThread = new Thread(32768); - mTransmitPriorityQueueServiceLoopThread = new Thread(32768); - mFIFOServiceLoopThread->start((void * (*)(void*))FIFOServiceLoopAdapter,(void*) this); + + mTransmitPriorityQueueServiceLoopThread = new Thread(32768); mTransmitPriorityQueueServiceLoopThread->start((void * (*)(void*))TransmitPriorityQueueServiceLoopAdapter,(void*) this); - writeClockInterface(); } } } @@ -409,7 +419,7 @@ void Transceiver::driveControl() sscanf(buffer,"%3s %s %d",cmdcheck,command,&newGain); newGain = mRadioInterface->setRxGain(newGain); mEnergyThreshold = INIT_ENERGY_THRSHD; - if (!mRadioLocked) + if (mPrimary) newGain = mRadioInterface->setRxGain(newGain); sprintf(response,"RSP SETRXGAIN 0 %d",newGain); } @@ -430,7 +440,7 @@ void Transceiver::driveControl() sprintf(response,"RSP SETPOWER 1 %d",dbPwr); else { mPower = dbPwr; - if (!mRadioLocked) + if (mPrimary) mRadioInterface->setPowerAttenuation(dbPwr); sprintf(response,"RSP SETPOWER 0 %d",dbPwr); } @@ -446,21 +456,14 @@ void Transceiver::driveControl() sprintf(response,"RSP ADJPOWER 0 %d",mPower); } } -#define FREQOFFSET 0//11.2e3 else if (strcmp(command,"RXTUNE")==0) { // tune receiver int freqKhz; sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz); - mRxFreq = freqKhz*1.0e3+FREQOFFSET; - mRadioLocked = mRadioInterface->started(); - - if (!mRadioLocked) { - if (!mRadioInterface->tuneRx(mRxFreq)) { - LOG(ALERT) << "RX failed to tune"; - sprintf(response,"RSP RXTUNE 1 %d",freqKhz); - } else { - sprintf(response,"RSP RXTUNE 0 %d",freqKhz); - } + mRxFreq = freqKhz * 1.0e3 + mFreqOffset; + if (mPrimary && (!mRadioInterface->tuneRx(mRxFreq))) { + LOG(ALERT) << "RX failed to tune"; + sprintf(response,"RSP RXTUNE 1 %d",freqKhz); } else { sprintf(response,"RSP RXTUNE 0 %d",freqKhz); } @@ -470,17 +473,12 @@ void Transceiver::driveControl() int freqKhz; sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz); //freqKhz = 890e3; - mTxFreq = freqKhz*1.0e3+FREQOFFSET; - mRadioLocked = mRadioInterface->started(); - if (!mRadioLocked) { - if (!mRadioInterface->tuneTx(mTxFreq)) { - LOG(ALERT) << "TX failed to tune"; - sprintf(response,"RSP TXTUNE 1 %d",freqKhz); - } else { - sprintf(response,"RSP TXTUNE 0 %d",freqKhz); - } + mTxFreq = freqKhz * 1.0e3 + mFreqOffset; + if (mPrimary && (!mRadioInterface->tuneTx(mTxFreq))) { + LOG(ALERT) << "TX failed to tune"; + sprintf(response,"RSP TXTUNE 1 %d",freqKhz); } else { - sprintf(response,"RSP TXTUNE 0 %d",freqKhz); + sprintf(response,"RSP TXTUNE 0 %d",freqKhz); } } else if (strcmp(command,"SETTSC")==0) { @@ -547,28 +545,12 @@ bool Transceiver::driveTransmitPriorityQueue() for (int i = 0; i < 4; i++) frameNum = (frameNum << 8) | (0x0ff & buffer[i+1]); - /* - if (GSM::Time(frameNum,timeSlot) > mTransmitDeadlineClock + GSM::Time(51,0)) { - // stale burst - //LOG(DEBUG) << "FAST! "<< GSM::Time(frameNum,timeSlot); - //writeClockInterface(); - }*/ - -/* - DAB -- Just let these go through the demod. - if (GSM::Time(frameNum,timeSlot) < mTransmitDeadlineClock) { - // stale burst from GSM core - LOG(NOTICE) << "STALE packet on GSM->TRX interface at time "<< GSM::Time(frameNum,timeSlot); - return false; - } -*/ - // periodically update GSM core clock - LOG(DEBUG) << "mTransmitDeadlineClock " << *mTransmitDeadlineClock - << " mLastClockUpdateTime " << mLastClockUpdateTime; - if (*mTransmitDeadlineClock > mLastClockUpdateTime + GSM::Time(216,0)) - writeClockInterface(); - + LOG(DEBUG) << "mTransmitDeadlineClock " << mDriveLoop->getDeadlineClock() + << " mLastClockUpdateTime " << mDriveLoop->getLastClockUpdate(); + if (mDriveLoop->getDeadlineClock() > mDriveLoop->getLastClockUpdate() + GSM::Time(216,0)) { + mDriveLoop->writeClockInterface(); + } LOG(DEBUG) << "rcvd. burst at: " << GSM::Time(frameNum,timeSlot); @@ -590,23 +572,6 @@ bool Transceiver::driveTransmitPriorityQueue() } -void Transceiver::writeClockInterface() -{ - char command[50]; - // FIXME -- This should be adaptive. - sprintf(command,"IND CLOCK %llu", - (unsigned long long) (mTransmitDeadlineClock->FN() + 2)); - - LOG(INFO) << "ClockInterface: sending " << command; - - mClockSocket.write(command,strlen(command)+1); - - mLastClockUpdateTime = *mTransmitDeadlineClock; -} - - - - void *FIFOServiceLoopAdapter(Transceiver *transceiver) { while (transceiver->on()) { @@ -629,13 +594,14 @@ void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *transceiver) { while (transceiver->on()) { bool stale = false; + // Flush the UDP packets until a successful transfer. while (!transceiver->driveTransmitPriorityQueue()) { stale = true; } if (stale) { // If a packet was stale, remind the GSM stack of the clock. - transceiver->writeClockInterface(); + transceiver->getDriveLoop()->writeClockInterface(); } pthread_testcancel(); } diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h index 840f87b..56acd9c 100644 --- a/Transceiver52M/Transceiver.h +++ b/Transceiver52M/Transceiver.h @@ -49,7 +49,6 @@ private: UDPSocket mDataSocket; ///< socket for writing to/reading from GSM core UDPSocket mControlSocket; ///< socket for writing/reading control commands from GSM core - UDPSocket mClockSocket; ///< socket for writing clock updates to GSM core VectorQueue *mTransmitPriorityQueue; ///< priority queue of transmit bursts received from GSM core VectorFIFO* mReceiveFIFO; ///< radioInterface FIFO of receive bursts @@ -60,9 +59,6 @@ private: int mChannel; ///< channelizer attach number between 0 and 'M-1' - GSM::Time *mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO - GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core - RadioInterface *mRadioInterface; ///< associated radioInterface object double txFullScale; ///< full scale input to radio double rxFullScale; ///< full scale output to radio @@ -96,8 +92,10 @@ private: bool mOn; ///< flag to indicate that transceiver is powered on bool mRunning; ///< flag to indicate control loop is running + bool mPrimary; ///< flag to indicate C0 channel double mTxFreq; ///< the transmit frequency double mRxFreq; ///< the receive frequency + double mFreqOffset; ///< RF frequency offset int mPower; ///< the transmit power in dB int mTSC; ///< the midamble sequence code double mEnergyThreshold; ///< threshold to determine if received data is potentially a GSM burst @@ -112,7 +110,7 @@ private: float chanRespOffset[8]; ///< most recent timing offset, e.g. TOA, of all timeslots complex chanRespAmplitude[8]; ///< most recent channel amplitude of all timeslots - bool mRadioLocked; + static int mTSC; ///< the midamble sequence code public: @@ -128,7 +126,7 @@ public: int wSamplesPerSymbol, RadioInterface *wRadioInterface, DriveLoop *wDriveLoop, - int wChannel); + int wChannel, bool wPrimary); /** Destructor */ ~Transceiver(); @@ -169,9 +167,11 @@ protected: /** return control loop operational status */ bool running() { return mRunning; } + /** return the drive loop pointer */ + DriveLoop *getDriveLoop() { return mDriveLoop; } + /** set priority on current thread */ void setPriority() { mRadioInterface->setPriority(); } - }; /** FIFO thread loop */ @@ -182,4 +182,3 @@ void *ControlServiceLoopAdapter(Transceiver *); /** transmit queueing thread loop */ void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *); - diff --git a/Transceiver52M/multiTRX.cpp b/Transceiver52M/multiTRX.cpp index 85d4046..04e2c95 100644 --- a/Transceiver52M/multiTRX.cpp +++ b/Transceiver52M/multiTRX.cpp @@ -32,6 +32,8 @@ ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db"); volatile bool gbShutdown = false; +int Transceiver::mTSC = 0; + static void sigHandler(int signum) { LOG(NOTICE) << "Received shutdown signal"; @@ -56,23 +58,23 @@ static int setupSignals() } /* - * Generate the channel-transceiver ordering. Channel 0 is always centered - * at the RF tuning frequecy. Fill remaining channels alternating left and - * right moving out from the center channel. + * Generate the channel-transceiver ordering. Attempt to match the RAD1 + * ordering where the active channels are centered in the overall device + * bandwidth. C0 is always has the lowest ARFCN with increasing subsequent + * channels. When an even number of channels is selected, the carriers will + * be offset from the RF center by -200 kHz, or half ARFCN spacing. */ -static void genChanMap(int *chans) +static void genChanMap(int numARFCN, int chanM, int *chans) { int i, n; - chans[0] = 0; + chans[0] = numARFCN / 2; - for (i = 1, n = 1; i < CHAN_M; i++) { - if (i % 2) { - chans[i] = n; - } else { - chans[i] = CHAN_M - n; - n++; - } + for (i = 1, n = 1; i < numARFCN; i++) { + if (!chans[i - 1]) + chans[i] = chanM - 1; + else + chans[i] = chans[i - 1] - 1; } } @@ -80,44 +82,66 @@ static void createTrx(Transceiver **trx, int *map, int num, RadioInterface *radio, DriveLoop *drive) { int i; + bool primary = true; for (i = 0; i < num; i++) { LOG(NOTICE) << "Creating TRX" << i << " attached on channel " << map[i]; radio->activateChan(map[i]); - trx[i] = new Transceiver(5700 + i * 1000, "127.0.0.1", - SAMPSPERSYM, radio, drive, map[i]); + trx[i] = new Transceiver(5700 + 2 * i, "127.0.0.1", + SAMPSPERSYM, radio, drive, + map[i], primary); trx[i]->start(); + primary = false; } } int main(int argc, char *argv[]) { - int i, numARFCN = 1; - int chanMap[CHAN_M]; + int i, chanM, numARFCN = 1; + int chanMap[CHAN_MAX]; RadioDevice *usrp; RadioInterface* radio; DriveLoop *drive; - Transceiver *trx[CHAN_M]; + Transceiver *trx[CHAN_MAX]; gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7); if (argc > 1) { numARFCN = atoi(argv[1]); - if (numARFCN > CHAN_M) { + if (numARFCN > (CHAN_MAX - 1)) { LOG(ALERT) << numARFCN << " channels not supported with current build"; exit(-1); } } + srandom(time(NULL)); + if (setupSignals() < 0) { LOG(ERR) << "Failed to setup signal handlers, exiting..."; exit(-1); } - srandom(time(NULL)); - genChanMap(chanMap); + /* + * Select the number of channels according to the number of ARFCNs's + * and generate ARFCN-to-channelizer path mappings. The channelizer + * aliases and extracts 'M' equally spaced channels to baseband. The + * number of ARFCN's must be less than the number of channels in the + * channelizer. + */ + switch (numARFCN) { + case 1: + chanM = 1; + break; + case 2: + case 3: + chanM = 5; + break; + default: + chanM = 10; + } + genChanMap(numARFCN, chanM, chanMap); usrp = RadioDevice::make(DEVICERATE); if (!usrp->open()) { @@ -125,8 +149,9 @@ int main(int argc, char *argv[]) return EXIT_FAILURE; } - radio = new RadioInterface(usrp, numARFCN, SAMPSPERSYM, 0, false); - drive = new DriveLoop(SAMPSPERSYM, GSM::Time(3,0), radio); + radio = new RadioInterface(usrp, chanM, 3, SAMPSPERSYM, 0, false); + drive = new DriveLoop(5700, "127.0.0.1", chanM, chanMap[0], + SAMPSPERSYM, GSM::Time(3,0), radio); /* Create, attach, and activate all transceivers */ createTrx(trx, chanMap, numARFCN, radio, drive); diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp index 98af480..b3bc07c 100644 --- a/Transceiver52M/radioInterface.cpp +++ b/Transceiver52M/radioInterface.cpp @@ -50,10 +50,11 @@ static void shortToFloat(float *out, short *in, int num) } RadioInterface::RadioInterface(RadioDevice *wRadio, + int wChanM, int wReceiveOffset, int wSPS, GSM::Time wStartTime) - : underrun(false), sendCursor(0), rcvCursor(0), mOn(false), + : mChanM(wChanM), underrun(false), sendCursor(0), rcvCursor(0), mOn(false), mRadio(wRadio), receiveOffset(wReceiveOffset), samplesPerSymbol(wSPS), powerScaling(1.0), loadTest(false) @@ -62,7 +63,7 @@ RadioInterface::RadioInterface(RadioDevice *wRadio, mClock.set(wStartTime); - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { chanActive[i] = false; } } @@ -77,7 +78,7 @@ RadioInterface::~RadioInterface(void) delete mAlignRadioServiceLoopThread; - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { if (rcvBuffer[i] != NULL) delete rcvBuffer[i]; if (sendBuffer[i] != NULL) @@ -170,9 +171,7 @@ bool RadioInterface::start() #endif writeTimestamp = mRadio->initialWriteTimestamp(); readTimestamp = mRadio->initialReadTimestamp(); - mRadio->start(); - - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { sendBuffer[i] = new float[8*2*INCHUNK]; rcvBuffer[i] = new float[8*2*OUTCHUNK]; } @@ -220,7 +219,7 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur if (!mOn) return; - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { if (chanActive[i]) { radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor, powerScaling, zeroBurst[i]); @@ -236,11 +235,11 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur pushBuffer(); } -void shiftRxBuffers(float **buf, int offset, int len, bool *active) +void shiftRxBuffers(float **buf, int offset, int len, int chanM, bool *active) { int i; - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < chanM; i++) { if (active[i]) { memmove(buf[i], buf[i] + offset, sizeof(float) * len); } @@ -252,7 +251,7 @@ void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst, { int i; - for (i = 0; i < CHAN_M; i++) { + for (i = 0; i < mChanM; i++) { if (chanActive[i]) { signalVector rxVector(samplesPerBurst); unRadioifyVector(rcvBuffer[i], idx * 2, rxVector); @@ -300,7 +299,7 @@ void RadioInterface::driveReceiveRadio() if (readSz > 0) { rcvCursor -= readSz; - shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, chanActive); + shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, mChanM, chanActive); } } diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h index bc32763..f301511 100644 --- a/Transceiver52M/radioInterface.h +++ b/Transceiver52M/radioInterface.h @@ -36,19 +36,20 @@ class RadioInterface { protected: + int mChanM; ///< channelizer width Thread *mAlignRadioServiceLoopThread; ///< thread that synchronizes transmit and receive sections - VectorFIFO mReceiveFIFO[CHAN_M]; ///< FIFO that holds receive bursts + VectorFIFO mReceiveFIFO[CHAN_MAX]; ///< FIFO that holds receive bursts RadioDevice *mRadio; ///< the USRP object - float *sendBuffer[CHAN_M]; + float *sendBuffer[CHAN_MAX]; unsigned sendCursor; - float *rcvBuffer[CHAN_M]; + float *rcvBuffer[CHAN_MAX]; unsigned rcvCursor; - bool chanActive[CHAN_M]; + bool chanActive[CHAN_MAX]; bool underrun; ///< indicates writes to USRP are too slow bool overrun; ///< indicates reads from USRP are too slow @@ -103,6 +104,7 @@ public: /** constructor */ RadioInterface(RadioDevice* wRadio = NULL, + int wChanM = 1, int receiveOffset = 3, int wSPS = SAMPSPERSYM, GSM::Time wStartTime = GSM::Time(0)); |