Adding MultiARFCN support to RAD1 radio.

git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@3689 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
Kurtis Heimerl
2012-05-31 00:05:17 +00:00
parent 13ece1dbae
commit fa00372820
8 changed files with 978 additions and 500 deletions

View File

@@ -124,21 +124,21 @@ private:
static const unsigned BSC = 3; // bits 21,20 Div by 8 to be safe
static const unsigned TEST = 0; // bit 19
static const unsigned LDP = 1; // bit 18
static const unsigned ABP = 0; // bit 17,16 3ns
static const unsigned ABP = 2; // bit 17,16 6ns, 0 = 3ns
// N-Register Common Values
static const unsigned N_RSV = 0; // bit 7
// Control Register Common Values
static const unsigned PD = 0; // bits 21,20 Normal operation
static const unsigned PL = 2; // bits 13,12 7.5mA, -6dbm
static const unsigned PL = 1; // bits 13,12 7.5mA, -6dbm
static const unsigned MTLD = 1; // bit 11 enabled
static const unsigned CPG = 0; // bit 10 CP setting 1
static const unsigned CP3S = 0; // bit 9 Normal
static const unsigned PDP = 1; // bit 8 Positive
static const unsigned MUXOUT = 1;// bits 7:5 Digital Lock Detect
static const unsigned CR = 0; // bit 4 Normal
static const unsigned PC = 2; // bits 3,2 Core power 15mA
static const unsigned PC = 0; // bits 3,2 Core power 15mA
// ATR register value
//static const int FR_ATR_MASK_0 = 20;

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,25 @@
/** Define this to be the slot number to be logged. */
//#define TRANSMIT_LOGGING 1
#define MAXARFCN 5
/** Codes for burst types of received bursts*/
typedef enum {
OFF, ///< timeslot is off
TSC, ///< timeslot should contain a normal burst
RACH, ///< timeslot should contain an access burst
IDLE ///< timeslot is an idle (or dummy) burst
} CorrType;
class Demodulator;
class Transceiver;
typedef struct ThreadStruct {
Transceiver *trx;
unsigned ARFCN;
} ThreadStruct;
/** The Transceiver class, responsible for physical layer of basestation */
class Transceiver {
@@ -48,33 +67,33 @@ private:
GSM::Time mTransmitLatency; ///< latency between basestation clock and transmit deadline clock
GSM::Time mLatencyUpdateTime; ///< last time latency was updated
UDPSocket mDataSocket; ///< socket for writing to/reading from GSM core
UDPSocket mControlSocket; ///< socket for writing/reading control commands from GSM core
UDPSocket *mDataSocket[MAXARFCN]; ///< socket for writing to/reading from GSM core
UDPSocket *mControlSocket[MAXARFCN]; ///< socket for writing/reading control commands from GSM core
UDPSocket mClockSocket; ///< socket for writing clock updates to GSM core
VectorQueue mTransmitPriorityQueue; ///< priority queue of transmit bursts received from GSM core
VectorFIFO* mTransmitFIFO; ///< radioInterface FIFO of transmit bursts
VectorFIFO* mReceiveFIFO; ///< radioInterface FIFO of receive bursts
VectorFIFO* mDemodFIFO[MAXARFCN];
Thread *mFIFOServiceLoopThread; ///< thread to push/pull bursts into transmit/receive FIFO
Thread *mControlServiceLoopThread; ///< thread to process control messages from GSM core
Thread *mTransmitPriorityQueueServiceLoopThread;///< thread to process transmit bursts from GSM core
Thread *mRFIFOServiceLoopThread;
Thread *mDemodServiceLoopThread[MAXARFCN]; ///< threads for demodulating individual ARFCNs
Thread *mControlServiceLoopThread[MAXARFCN]; ///< thread to process control messages from GSM core
Thread *mTransmitPriorityQueueServiceLoopThread[MAXARFCN];///< thread to process transmit bursts from GSM core
GSM::Time mTransmitDeadlineClock; ///< deadline for pushing bursts into transmit FIFO
GSM::Time mLastClockUpdateTime; ///< last time clock update was sent up to core
GSM::Time mStartTime;
RadioInterface *mRadioInterface; ///< associated radioInterface object
double txFullScale; ///< full scale input to radio
double rxFullScale; ///< full scale output to radio
double rxFullScale;
/** Codes for burst types of received bursts*/
typedef enum {
OFF, ///< timeslot is off
TSC, ///< timeslot should contain a normal burst
RACH, ///< timeslot should contain an access burst
IDLE ///< timeslot is an idle (or dummy) burst
} CorrType;
Mutex mControlLock;
Mutex mTransmitPriorityQueueLock;
bool mLoadTest;
/** Codes for channel combinations */
typedef enum {
@@ -99,22 +118,18 @@ private:
/** modulate and add a burst to the transmit queue */
void addRadioVector(BitVector &burst,
int RSSI,
GSM::Time &wTime);
GSM::Time &wTime,
int ARFCN);
/** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
void pushRadioVector(GSM::Time &nowTime);
/** Pull and demodulate a burst from the receive FIFO */
SoftVector *pullRadioVector(GSM::Time &wTime,
int &RSSI,
int &timingOffset);
void pullRadioVector(void);
/** Set modulus for specific timeslot */
void setModulus(int timeslot);
/** return the expected burst type for the specified timestamp */
CorrType expectedCorrType(GSM::Time currTime);
/** send messages over the clock socket */
void writeClockInterface(void);
@@ -123,24 +138,27 @@ private:
int mSamplesPerSymbol; ///< number of samples per GSM symbol
bool mOn; ///< flag to indicate that transceiver is powered on
ChannelCombination mChanType[8]; ///< channel types for all timeslots
ChannelCombination mChanType[MAXARFCN][8]; ///< channel types for all timeslots
double mTxFreq; ///< the transmit frequency
double mRxFreq; ///< the receive frequency
int mPower; ///< the transmit power in dB
unsigned mTSC; ///< the midamble sequence code
double mEnergyThreshold; ///< threshold to determine if received data is potentially a GSM burst
GSM::Time prevFalseDetectionTime; ///< last timestamp of a false energy detection
int fillerModulus[8]; ///< modulus values of all timeslots, in frames
signalVector *fillerTable[102][8]; ///< table of modulated filler waveforms for all timeslots
unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols
GSM::Time channelEstimateTime[8]; ///< last timestamp of each timeslot's channel estimate
signalVector *channelResponse[8]; ///< most recent channel estimate of all timeslots
float SNRestimate[8]; ///< most recent SNR estimate of all timeslots
signalVector *DFEForward[8]; ///< most recent DFE feedforward filter of all timeslots
signalVector *DFEFeedback[8]; ///< most recent DFE feedback filter of all timeslots
float chanRespOffset[8]; ///< most recent timing offset, e.g. TOA, of all timeslots
complex chanRespAmplitude[8]; ///< most recent channel amplitude of all timeslots
unsigned int mNumARFCNs;
bool mMultipleARFCN;
unsigned char mOversamplingRate;
double mFreqOffset;
signalVector *frequencyShifter[MAXARFCN];
signalVector *decimationFilter;
signalVector *interpolationFilter;
Demodulator *mDemodulators[MAXARFCN];
public:
@@ -155,7 +173,10 @@ public:
const char *TRXAddress,
int wSamplesPerSymbol,
GSM::Time wTransmitLatency,
RadioInterface *wRadioInterface);
RadioInterface *wRadioInterface,
unsigned int wNumARFCNs,
unsigned int wOversamplingRate,
bool wLoadTest);
/** Destructor */
~Transceiver();
@@ -163,12 +184,30 @@ public:
/** start the Transceiver */
void start();
bool multiARFCN() {return mMultipleARFCN;}
/** return the expected burst type for the specified timestamp */
CorrType expectedCorrType(GSM::Time currTime, int ARFCN);
/** attach the radioInterface receive FIFO */
void receiveFIFO(VectorFIFO *wFIFO) { mReceiveFIFO = wFIFO;}
/** attach the radioInterface transmit FIFO */
void transmitFIFO(VectorFIFO *wFIFO) { mTransmitFIFO = wFIFO;}
VectorFIFO *demodFIFO(unsigned ARFCN) { return mDemodFIFO[ARFCN]; }
RadioInterface *radioInterface(void) { return mRadioInterface; }
unsigned samplesPerSymbol(void) { return mSamplesPerSymbol; }
UDPSocket *dataSocket(int ARFCN) { return mDataSocket[ARFCN]; }
signalVector *GSMPulse(void) { return gsmPulse; }
unsigned maxDelay(void) { return mMaxExpectedDelay; }
unsigned getTSC(void) { return mTSC; }
protected:
@@ -179,19 +218,21 @@ protected:
void driveTransmitFIFO();
/** drive handling of control messages from GSM core */
void driveControl();
void driveControl(unsigned ARFCN);
/**
drive modulation and sorting of GSM bursts from GSM core
@return true if a burst was transferred successfully
*/
bool driveTransmitPriorityQueue();
bool driveTransmitPriorityQueue(unsigned ARFCN);
friend void *FIFOServiceLoopAdapter(Transceiver *);
friend void *ControlServiceLoopAdapter(Transceiver *);
friend void *RFIFOServiceLoopAdapter(Transceiver *);
friend void *ControlServiceLoopAdapter(ThreadStruct *);
friend void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *);
friend void *TransmitPriorityQueueServiceLoopAdapter(ThreadStruct *);
void reset();
};
@@ -199,9 +240,61 @@ protected:
/** FIFO thread loop */
void *FIFOServiceLoopAdapter(Transceiver *);
void *RFIFOServiceLoopAdapter(Transceiver *);
/** control message handler thread loop */
void *ControlServiceLoopAdapter(Transceiver *);
void *ControlServiceLoopAdapter(ThreadStruct *);
/** transmit queueing thread loop */
void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *);
void *TransmitPriorityQueueServiceLoopAdapter(ThreadStruct *);
class Demodulator {
private:
int mARFCN;
Transceiver *mTRX;
RadioInterface *mRadioInterface;
VectorFIFO *mDemodFIFO;
double mEnergyThreshold; ///< threshold to determine if received data is potentially a GSM burst
GSM::Time prevFalseDetectionTime; ///< last timestamp of a false energy detection
GSM::Time channelEstimateTime[8]; ///< last timestamp of each timeslot's channel estimate
signalVector *channelResponse[8]; ///< most recent channel estimate of all timeslots
float SNRestimate[8]; ///< most recent SNR estimate of all timeslots
signalVector *DFEForward[8]; ///< most recent DFE feedforward filter of all timeslots
signalVector *DFEFeedback[8]; ///< most recent DFE feedback filter of all timeslots
float chanRespOffset[8]; ///< most recent timing offset, e.g. TOA, of all timeslots
complex chanRespAmplitude[8]; ///< most recent channel amplitude of all timeslots
signalVector *gsmPulse;
unsigned mTSC;
unsigned mSamplesPerSymbol;
UDPSocket *mTRXDataSocket;
unsigned mMaxExpectedDelay;
double rxFullScale; ///< full scale output to radio
SoftVector* demodRadioVector(radioVector *rxBurst,
GSM::Time &wTime,
int &RSSI,
int &timingOffset);
public:
Demodulator(int wARFCN,
Transceiver *wTRX,
GSM::Time wStartTime);
double getEnergyThreshold() {return mEnergyThreshold;}
//protected:
void driveDemod(bool wSingleARFCN = true);
protected:
friend void *DemodServiceLoopAdapter(Demodulator *);
};
void *DemodServiceLoopAdapter(Demodulator *);

View File

@@ -71,6 +71,8 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
int wReceiveOffset,
int wRadioOversampling,
int wTransceiverOversampling,
bool wLoadTest,
unsigned int wNumARFCNs,
GSM::Time wStartTime)
{
@@ -85,6 +87,9 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
samplesPerSymbol = wRadioOversampling;
mClock.set(wStartTime);
powerScaling = 1.0;
mNumARFCNs = wNumARFCNs;
loadTest = wLoadTest;
}
RadioInterface::~RadioInterface(void) {
@@ -236,6 +241,34 @@ void RadioInterface::start()
mOn = true;
if (loadTest) {
int mOversamplingRate = samplesPerSymbol;
int numARFCN = mNumARFCNs;
signalVector *gsmPulse = generateGSMPulse(2,1);
BitVector normalBurstSeg = "0000101010100111110010101010010110101110011000111001101010000";
BitVector normalBurst(BitVector(normalBurstSeg,gTrainingSequence[2]),normalBurstSeg);
signalVector *modBurst = modulateBurst(normalBurst,*gsmPulse,8,1);
signalVector *modBurst9 = modulateBurst(normalBurst,*gsmPulse,9,1);
signalVector *interpolationFilter = createLPF(0.6/mOversamplingRate,6*mOversamplingRate,1);
scaleVector(*modBurst,mRadio->fullScaleInputValue());
scaleVector(*modBurst9,mRadio->fullScaleInputValue());
double beaconFreq = -1.0*(numARFCN-1)*200e3;
finalVec = new signalVector(156*mOversamplingRate);
finalVec9 = new signalVector(157*mOversamplingRate);
for (int j = 0; j < numARFCN; j++) {
signalVector *frequencyShifter = new signalVector(157*mOversamplingRate);
frequencyShifter->fill(1.0);
frequencyShift(frequencyShifter,frequencyShifter,2.0*M_PI*(beaconFreq+j*400e3)/(1625.0e3/6.0*mOversamplingRate));
signalVector *interpVec = polyphaseResampleVector(*modBurst,mOversamplingRate,1,interpolationFilter);
multVector(*interpVec,*frequencyShifter);
addVector(*finalVec,*interpVec);
interpVec = polyphaseResampleVector(*modBurst9,mOversamplingRate,1,interpolationFilter);
multVector(*interpVec,*frequencyShifter);
addVector(*finalVec9,*interpVec);
}
}
}
void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
@@ -287,14 +320,15 @@ void RadioInterface::driveReceiveRadio() {
GSM::Time tmpTime = rcvClock;
if (rcvClock.FN() >= 0) {
//LOG(DEBUG) << "FN: " << rcvClock.FN();
int dummyARFCN = 0;
radioVector *rxBurst = NULL;
if (!loadTest)
rxBurst = new radioVector(rxVector,tmpTime);
rxBurst = new radioVector(rxVector,tmpTime,dummyARFCN);
else {
if (tN % 4 == 0)
rxBurst = new radioVector(*finalVec9,tmpTime);
rxBurst = new radioVector(*finalVec9,tmpTime,dummyARFCN);
else
rxBurst = new radioVector(*finalVec,tmpTime);
rxBurst = new radioVector(*finalVec,tmpTime,dummyARFCN);
}
mReceiveFIFO.put(rxBurst);
}

View File

@@ -40,16 +40,22 @@ class radioVector : public signalVector {
private:
GSM::Time mTime; ///< the burst's GSM timestamp
int mARFCN;
public:
/** constructor */
radioVector(const signalVector& wVector,
GSM::Time& wTime): signalVector(wVector),mTime(wTime) {};
GSM::Time& wTime,
int& wARFCN): signalVector(wVector),mTime(wTime),mARFCN(wARFCN){};
/** timestamp read and write operators */
GSM::Time time() const { return mTime;}
void time(const GSM::Time& wTime) { mTime = wTime;}
/** ARFCN read and write operators */
int ARFCN() const { return mARFCN;}
void ARFCN(const int& wARFCN) { mARFCN = wARFCN;}
/** comparison operator, used for sorting */
bool operator>(const radioVector& other) const {return mTime > other.mTime;}
@@ -111,12 +117,12 @@ private:
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();;}
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();}
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; }
@@ -188,6 +194,8 @@ public:
int receiveOffset = 3,
int wRadioOversampling = SAMPSPERSYM,
int wTransceiverOversampling = SAMPSPERSYM,
bool wLoadTest = false,
unsigned int wNumARFCNS = 1,
GSM::Time wStartTime = GSM::Time(0));
/** destructor */

View File

@@ -74,7 +74,7 @@ int usbMsg (struct libusb_device_handle *udh,
if (ret < 0) {
// we get EPIPE if the firmware stalls the endpoint.
if (ret != LIBUSB_ERROR_PIPE) {
LOG(ALERT) << "libusb_control_transfer failed: " << _get_usb_error_str(ret);
LOG(ERR) << "libusb_control_transfer failed: " << _get_usb_error_str(ret);
}
}

View File

@@ -66,16 +66,79 @@ int main(int argc, char *argv[])
// Configure logger.
gLogInit("transceiver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
int numARFCN=1;
if (argc>1) numARFCN = atoi(argv[1]);
#ifdef SINGLEARFCN
numARFCN=1;
#endif
srandom(time(NULL));
int mOversamplingRate = 1;
switch(numARFCN) {
case 1:
mOversamplingRate = 1;
break;
case 2:
mOversamplingRate = 6;
break;
case 3:
mOversamplingRate = 8;
break;
case 4:
mOversamplingRate = 12;
break;
case 5:
mOversamplingRate = 16;
break;
default:
break;
}
//int mOversamplingRate = numARFCN/2 + numARFCN;
//mOversamplingRate = 15; //mOversamplingRate*2;
//if ((numARFCN > 1) && (mOversamplingRate % 2)) mOversamplingRate++;
RAD1Device *usrp = new RAD1Device(mOversamplingRate*1625.0e3/6.0);
//DummyLoad *usrp = new DummyLoad(mOversamplingRate*1625.0e3/6.0);
usrp->make();
RadioInterface* radio = new RadioInterface(usrp,3,SAMPSPERSYM,mOversamplingRate,false);
Transceiver *trx = new Transceiver(5700,"127.0.0.1",SAMPSPERSYM,GSM::Time(2,0),radio);
RadioInterface* radio = new RadioInterface(usrp,3,SAMPSPERSYM,mOversamplingRate,false,numARFCN);
Transceiver *trx = new Transceiver(5700,"127.0.0.1",SAMPSPERSYM,GSM::Time(2,0),radio,
numARFCN,mOversamplingRate,false);
trx->receiveFIFO(radio->receiveFIFO());
/*
signalVector *gsmPulse = generateGSMPulse(2,1);
BitVector normalBurstSeg = "0000101010100111110010101010010110101110011000111001101010000";
BitVector normalBurst(BitVector(normalBurstSeg,gTrainingSequence[0]),normalBurstSeg);
signalVector *modBurst = modulateBurst(normalBurst,*gsmPulse,8,1);
signalVector *modBurst9 = modulateBurst(normalBurst,*gsmPulse,9,1);
signalVector *interpolationFilter = createLPF(0.6/mOversamplingRate,6*mOversamplingRate,1);
signalVector totalBurst1(*modBurst,*modBurst9);
signalVector totalBurst2(*modBurst,*modBurst);
signalVector totalBurst(totalBurst1,totalBurst2);
scaleVector(totalBurst,usrp->fullScaleInputValue());
double beaconFreq = -1.0*(numARFCN-1)*200e3;
signalVector finalVec(625*mOversamplingRate);
for (int j = 0; j < numARFCN; j++) {
signalVector *frequencyShifter = new signalVector(625*mOversamplingRate);
frequencyShifter->fill(1.0);
frequencyShift(frequencyShifter,frequencyShifter,2.0*M_PI*(beaconFreq+j*400e3)/(1625.0e3/6.0*mOversamplingRate));
signalVector *interpVec = polyphaseResampleVector(totalBurst,mOversamplingRate,1,interpolationFilter);
multVector(*interpVec,*frequencyShifter);
addVector(finalVec,*interpVec);
}
signalVector::iterator itr = finalVec.begin();
short finalVecShort[2*finalVec.size()];
short *shortItr = finalVecShort;
while (itr < finalVec.end()) {
*shortItr++ = (short) (itr->real());
*shortItr++ = (short) (itr->imag());
itr++;
}
usrp->loadBurst(finalVecShort,finalVec.size());
*/
trx->start();
//int i = 0;
while(!gbShutdown) { sleep(1); } //i++; if (i==60) exit(1);}

View File

@@ -599,6 +599,7 @@ signalVector *modulateBurst(const BitVector &wBurst,
modBurst.isRealOnly(true);
//memset(staticBurst,0,sizeof(complex)*burstSize);
modBurst.fill(0.0);
//modBurst.fill(1.0);
signalVector::iterator modBurstItr = modBurst.begin();
#if 0