aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/DriveLoop.cpp
diff options
context:
space:
mode:
authorThomas Tsou <ttsou@vt.edu>2012-06-05 20:31:28 -0400
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2013-06-24 01:51:02 +0400
commit41c6657938e930a1c20070d5a8952e6dea12ec32 (patch)
tree37245a030b3e44e1e3d25086af9fa29b94f6054e /Transceiver52M/DriveLoop.cpp
parentcd576c9636244938a42d8c69da012e45e9fdd4f5 (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.cpp56
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();