diff options
Diffstat (limited to 'Transceiver52M/DriveLoop.cpp')
-rw-r--r-- | Transceiver52M/DriveLoop.cpp | 264 |
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; +} |