aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M/DriveLoop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Transceiver52M/DriveLoop.cpp')
-rw-r--r--Transceiver52M/DriveLoop.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/Transceiver52M/DriveLoop.cpp b/Transceiver52M/DriveLoop.cpp
new file mode 100644
index 0000000..997d009
--- /dev/null
+++ b/Transceiver52M/DriveLoop.cpp
@@ -0,0 +1,264 @@
+/*
+* Copyright 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
+*
+* This software is distributed under the terms of the GNU Public License.
+* See the COPYING file in the main directory for details.
+*
+* This use of this software may be subject to additional restrictions.
+* See the LEGAL file in the main directory for details.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include "DriveLoop.h"
+#include <Logger.h>
+
+DriveLoop::DriveLoop(int wSamplesPerSymbol,
+ GSM::Time wTransmitLatency,
+ RadioInterface *wRadioInterface)
+{
+ mRadioDriveLoopThread = new Thread(32768);
+
+ mSamplesPerSymbol = wSamplesPerSymbol;
+ mRadioInterface = wRadioInterface;
+
+ GSM::Time startTime(random() % gHyperframe, 0);
+ mTransmitDeadlineClock = startTime;
+ mLatencyUpdateTime = startTime;
+ mTransmitLatency = wTransmitLatency;
+
+ mRadioInterface->getClock()->set(startTime);
+
+ // generate pulse and setup up signal processing library
+ gsmPulse = generateGSMPulse(2, mSamplesPerSymbol);
+ LOG(DEBUG) << "gsmPulse: " << *gsmPulse;
+ sigProcLibSetup(mSamplesPerSymbol);
+
+ txFullScale = mRadioInterface->fullScaleInputValue();
+
+ // 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), 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);
+ }
+ delete modBurst;
+
+ for (int n = 0; n < CHAN_M; n++) {
+ fillerModulus[n][i] = 26;
+ mChanType[n][i] = NONE;
+ }
+ }
+
+ mOn = false;
+}
+
+DriveLoop::~DriveLoop()
+{
+ delete gsmPulse;
+ sigProcLibDestroy();
+}
+
+void DriveLoop::start()
+{
+ mOn = true;
+ mRadioDriveLoopThread->start((void * (*)(void*))RadioDriveLoopAdapter, (void*) this);
+}
+
+void DriveLoop::pushRadioVector(GSM::Time &nowTime)
+{
+ int i;
+ radioVector *staleBurst;
+ radioVector *next;
+
+ for (i = 0; i < CHAN_M; 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;
+ }
+
+ int TN = nowTime.TN();
+ int modFN = nowTime.FN() % fillerModulus[i][nowTime.TN()];
+
+ mTxBursts[i] = fillerTable[i][modFN][TN];
+ mIsFiller[i] = true;
+ mIsZero[i] = (mChanType[i][TN] == NONE);
+
+ // 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));
+ mTxBursts[i] = next;
+ mIsFiller[i] = false;
+ }
+ }
+
+ mRadioInterface->driveTransmitRadio(mTxBursts, mIsZero);
+
+ for (i = 0; i < CHAN_M; i++) {
+ if (!mIsFiller[i])
+ delete mTxBursts[i];
+ }
+}
+
+void DriveLoop::setModulus(int channel, int timeslot)
+{
+ switch (mChanType[channel][timeslot]) {
+ case NONE:
+ case I:
+ case II:
+ case III:
+ case FILL:
+ fillerModulus[channel][timeslot] = 26;
+ break;
+ case IV:
+ case VI:
+ case V:
+ fillerModulus[channel][timeslot] = 51;
+ break;
+ //case V:
+ case VII:
+ fillerModulus[channel][timeslot] = 102;
+ break;
+ default:
+ break;
+ }
+}
+
+DriveLoop::CorrType DriveLoop::expectedCorrType(int channel, GSM::Time currTime)
+{
+ unsigned burstTN = currTime.TN();
+ unsigned burstFN = currTime.FN();
+
+ switch (mChanType[channel][burstTN]) {
+ case NONE:
+ return OFF;
+ break;
+ case FILL:
+ return IDLE;
+ break;
+ case I:
+ return TSC;
+ /*if (burstFN % 26 == 25)
+ return IDLE;
+ else
+ return TSC;*/
+ break;
+ case II:
+ if (burstFN % 2 == 1)
+ return IDLE;
+ else
+ return TSC;
+ break;
+ case III:
+ return TSC;
+ break;
+ case IV:
+ case VI:
+ return RACH;
+ break;
+ case V: {
+ int mod51 = burstFN % 51;
+ if ((mod51 <= 36) && (mod51 >= 14))
+ return RACH;
+ else if ((mod51 == 4) || (mod51 == 5))
+ return RACH;
+ else if ((mod51 == 45) || (mod51 == 46))
+ return RACH;
+ else
+ return TSC;
+ break;
+ }
+ case VII:
+ if ((burstFN % 51 <= 14) && (burstFN % 51 >= 12))
+ return IDLE;
+ else
+ return TSC;
+ break;
+ case LOOPBACK:
+ if ((burstFN % 51 <= 50) && (burstFN % 51 >=48))
+ return IDLE;
+ else
+ return TSC;
+ break;
+ default:
+ return OFF;
+ break;
+ }
+}
+
+void DriveLoop::reset()
+{
+}
+
+void DriveLoop::driveReceiveFIFO()
+{
+ SoftVector *rxBurst = NULL;
+ int RSSI;
+ int TOA; // in 1/256 of a symbol
+ GSM::Time burstTime;
+
+ mRadioInterface->driveReceiveRadio();
+}
+
+/*
+ * Features a carefully controlled latency mechanism, to
+ * assure that transmit packets arrive at the radio/USRP
+ * before they need to be transmitted.
+ *
+ * Deadline clock indicates the burst that needs to be
+ * pushed into the FIFO right NOW. If transmit queue does
+ * not have a burst, stick in filler data.
+ */
+void DriveLoop::driveTransmitFIFO()
+{
+ int i;
+
+ if (!mOn)
+ return;
+
+ RadioClock *radioClock = (mRadioInterface->getClock());
+ while (radioClock->get() + mTransmitLatency > mTransmitDeadlineClock) {
+ pushRadioVector(mTransmitDeadlineClock);
+ mTransmitDeadlineClock.incTN();
+ }
+
+ // FIXME -- This should not be a hard spin.
+ // But any delay here causes us to throw omni_thread_fatal.
+ //else radioClock->wait();
+}
+
+void *RadioDriveLoopAdapter(DriveLoop *transceiver)
+{
+ transceiver->setPriority();
+
+ while (1) {
+ transceiver->driveReceiveFIFO();
+ transceiver->driveTransmitFIFO();
+ pthread_testcancel();
+ }
+ return NULL;
+}