diff options
author | Thomas Tsou <ttsou@vt.edu> | 2012-06-05 20:31:28 -0400 |
---|---|---|
committer | Alexander Chemeris <Alexander.Chemeris@gmail.com> | 2013-06-24 01:51:02 +0400 |
commit | 41c6657938e930a1c20070d5a8952e6dea12ec32 (patch) | |
tree | 37245a030b3e44e1e3d25086af9fa29b94f6054e /Transceiver52M/DriveLoop.cpp | |
parent | cd576c9636244938a42d8c69da012e45e9fdd4f5 (diff) |
multi-arfcn: refactor to match upstream GSM core
This patch aligns the multicarrier (MC) USRP code with
released GSM core changes that accommodate the MC RAD1.
Primary changes are:
1. Runtime setting of number of channelizer paths
2. Matching channelizer path to ARFCN mapping of GSM core
3. Use a single clock update socket on the drive loop
4. Match transceiver data and control socket ports
Setting of channelizer paths (or width) was previously fixed
at compile time. In either case, channelizer width is limited
by the sample rate of the device and channel spacing of the
maximally decimated filterbank. Available settings are 1, 5,
and 10 channels, which accommodate any number of ARFCN's in
between. Also add the frequency offsets to handle the effective
shift in setting RF frequency.
Previous assumption was to place C0 at the center frequency,
but RAD1 assumes C0 at the leftmost carrier, so adjust
accordingly.
The rest is general consolidation to mostly match the RAD1
interaction with GSM core. There is some loss of flexibility to
run, say, multiple independent instances of OpenBTS through a
single bank of channelized transceivers. But, the better
compatibility and reduction in code is the appropriate tradeoff.
Signed-off-by: Thomas Tsou <ttsou@vt.edu>
Diffstat (limited to 'Transceiver52M/DriveLoop.cpp')
-rw-r--r-- | Transceiver52M/DriveLoop.cpp | 56 |
1 files changed, 41 insertions, 15 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(); |