osmo-trx/Transceiver52M/radioInterface.h

249 lines
6.8 KiB
C
Raw Normal View History

/*
* Copyright 2008 Free Software Foundation, Inc.
*
* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribuion.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
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.
*/
#include "sigProcLib.h"
#include "GSMCommon.h"
#include "LinkedLists.h"
#include "radioDevice.h"
/** samples per GSM symbol */
#define SAMPSPERSYM 1
#define INCHUNK (625)
#define OUTCHUNK (625)
/** class used to organize GSM bursts by GSM timestamps */
class radioVector : public signalVector {
private:
GSM::Time mTime; ///< the burst's GSM timestamp
public:
/** constructor */
radioVector(const signalVector& wVector,
GSM::Time& wTime): signalVector(wVector),mTime(wTime) {};
/** timestamp read and write operators */
GSM::Time time() const { return mTime;}
void time(const GSM::Time& wTime) { mTime = wTime;}
/** comparison operator, used for sorting */
bool operator>(const radioVector& other) const {return mTime > other.mTime;}
};
/** a priority queue of radioVectors, i.e. GSM bursts, sorted so that earliest element is at top */
class VectorQueue : public InterthreadPriorityQueue<radioVector> {
public:
/** the top element of the queue */
GSM::Time nextTime() const;
/**
Get stale burst, if any.
@param targTime The target time.
@return Pointer to burst older than target time, removed from queue, or NULL.
*/
radioVector* getStaleBurst(const GSM::Time& targTime);
/**
Get current burst, if any.
@param targTime The target time.
@return Pointer to burst at the target time, removed from queue, or NULL.
*/
radioVector* getCurrentBurst(const GSM::Time& targTime);
};
/** a FIFO of radioVectors */
class VectorFIFO {
private:
PointerFIFO mQ;
Mutex mLock;
public:
unsigned size() {return mQ.size();}
void put(radioVector *ptr) {ScopedLock lock(mLock); mQ.put((void*) ptr);}
radioVector *get() { ScopedLock lock(mLock); return (radioVector*) mQ.get();}
};
/** the basestation clock class */
class RadioClock {
private:
GSM::Time mClock;
Mutex mLock;
Signal updateSignal;
public:
/** Set clock */
//void set(const GSM::Time& wTime) { ScopedLock lock(mLock); mClock = wTime; updateSignal.signal();}
void set(const GSM::Time& wTime) { ScopedLock lock(mLock); mClock = wTime; updateSignal.broadcast();;}
/** Increment clock */
//void incTN() { ScopedLock lock(mLock); mClock.incTN(); updateSignal.signal();}
void incTN() { ScopedLock lock(mLock); mClock.incTN(); updateSignal.broadcast();}
/** Get clock value */
GSM::Time get() { ScopedLock lock(mLock); return mClock; }
/** Wait until clock has changed */
//void wait() {ScopedLock lock(mLock); updateSignal.wait(mLock,1);}
// FIXME -- If we take away the timeout, a lot of threads don't start. Why?
void wait() {ScopedLock lock(mLock); updateSignal.wait(mLock);}
};
/** class to interface the transceiver with the USRP */
class RadioInterface {
private:
Thread mAlignRadioServiceLoopThread; ///< thread that synchronizes transmit and receive sections
VectorFIFO mReceiveFIFO; ///< FIFO that holds receive bursts
RadioDevice *mRadio; ///< the USRP object
short *sendBuffer; //[2*2*INCHUNK];
unsigned sendCursor;
short *rcvBuffer; //[2*2*OUTCHUNK];
unsigned rcvCursor;
bool underrun; ///< indicates writes to USRP are too slow
bool overrun; ///< indicates reads from USRP are too slow
TIMESTAMP writeTimestamp; ///< sample timestamp of next packet written to USRP
TIMESTAMP readTimestamp; ///< sample timestamp of next packet read from USRP
RadioClock mClock; ///< the basestation clock!
int samplesPerSymbol; ///< samples per GSM symbol
int receiveOffset; ///< offset b/w transmit and receive GSM timestamps, in timeslots
int mRadioOversampling;
int mTransceiverOversampling;
bool mOn; ///< indicates radio is on
double powerScaling;
bool loadTest;
int mNumARFCNs;
signalVector *finalVec, *finalVec9;
/** format samples to USRP */
short *radioifyVector(signalVector &wVector,
short *shortVector,
float scale,
bool zeroOut);
/** format samples from USRP */
void unRadioifyVector(short *shortVector, signalVector &wVector);
/** push GSM bursts into the transmit buffer */
void pushBuffer(void);
/** pull GSM bursts from the receive buffer */
void pullBuffer(void);
public:
/** start the interface */
void start();
/** constructor */
RadioInterface(RadioDevice* wRadio = NULL,
int receiveOffset = 3,
int wRadioOversampling = SAMPSPERSYM,
int wTransceiverOversampling = SAMPSPERSYM,
GSM::Time wStartTime = GSM::Time(0));
/** destructor */
~RadioInterface();
void setSamplesPerSymbol(int wSamplesPerSymbol) {if (!mOn) samplesPerSymbol = wSamplesPerSymbol;}
int getSamplesPerSymbol() { return samplesPerSymbol;}
/** check for underrun, resets underrun value */
bool isUnderrun() { bool retVal = underrun; underrun = false; return retVal;}
/** attach an existing USRP to this interface */
void attach(RadioDevice *wRadio, int wRadioOversampling) {if (!mOn) {mRadio = wRadio; mRadioOversampling = SAMPSPERSYM;} }
/** return the receive FIFO */
VectorFIFO* receiveFIFO() { return &mReceiveFIFO;}
/** return the basestation clock */
RadioClock* getClock(void) { return &mClock;};
/** set receive gain */
double setRxGain(double dB) {if (mRadio) return mRadio->setRxGain(dB); else return -1;}
/** get receive gain */
double getRxGain(void) {if (mRadio) return mRadio->getRxGain(); else return -1;}
/** set transmit frequency */
bool tuneTx(double freq);
/** set receive frequency */
bool tuneRx(double freq);
/** drive transmission of GSM bursts */
void driveTransmitRadio(signalVector &radioBurst, bool zeroBurst);
/** drive reception of GSM bursts */
void driveReceiveRadio();
void setPowerAttenuation(double atten);
/** returns the full-scale transmit amplitude **/
double fullScaleInputValue();
/** returns the full-scale receive amplitude **/
double fullScaleOutputValue();
/** set thread priority on current thread */
void setPriority() { mRadio->setPriority(); }
protected:
/** drive synchronization of Tx/Rx of USRP */
void alignRadio();
/** reset the interface */
void reset();
friend void *AlignRadioServiceLoopAdapter(RadioInterface*);
};
/** synchronization thread loop */
void *AlignRadioServiceLoopAdapter(RadioInterface*);