mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-04 05:43:14 +00:00 
			
		
		
		
	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:
		@@ -124,21 +124,21 @@ private:
 | 
				
			|||||||
  static const unsigned BSC = 3;   // bits 21,20 Div by 8 to be safe
 | 
					  static const unsigned BSC = 3;   // bits 21,20 Div by 8 to be safe
 | 
				
			||||||
  static const unsigned TEST = 0;  // bit 19
 | 
					  static const unsigned TEST = 0;  // bit 19
 | 
				
			||||||
  static const unsigned LDP = 1;   // bit 18
 | 
					  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
 | 
					  // N-Register Common Values
 | 
				
			||||||
  static const unsigned N_RSV = 0; // bit 7
 | 
					  static const unsigned N_RSV = 0; // bit 7
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Control Register Common Values
 | 
					  // Control Register Common Values
 | 
				
			||||||
  static const unsigned PD = 0;    // bits 21,20   Normal operation
 | 
					  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 MTLD = 1;  // bit 11       enabled
 | 
				
			||||||
  static const unsigned CPG = 0;   // bit 10       CP setting 1
 | 
					  static const unsigned CPG = 0;   // bit 10       CP setting 1
 | 
				
			||||||
  static const unsigned CP3S = 0;  // bit 9        Normal
 | 
					  static const unsigned CP3S = 0;  // bit 9        Normal
 | 
				
			||||||
  static const unsigned PDP = 1;   // bit 8        Positive
 | 
					  static const unsigned PDP = 1;   // bit 8        Positive
 | 
				
			||||||
  static const unsigned MUXOUT = 1;// bits 7:5     Digital Lock Detect
 | 
					  static const unsigned MUXOUT = 1;// bits 7:5     Digital Lock Detect
 | 
				
			||||||
  static const unsigned CR = 0;    // bit 4        Normal
 | 
					  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
 | 
					  // ATR register value
 | 
				
			||||||
  //static const int FR_ATR_MASK_0 = 20;
 | 
					  //static const int FR_ATR_MASK_0 = 20;
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -40,32 +40,8 @@
 | 
				
			|||||||
/** Define this to be the slot number to be logged. */
 | 
					/** Define this to be the slot number to be logged. */
 | 
				
			||||||
//#define TRANSMIT_LOGGING 1
 | 
					//#define TRANSMIT_LOGGING 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** The Transceiver class, responsible for physical layer of basestation */
 | 
					#define MAXARFCN 5
 | 
				
			||||||
class Transceiver {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 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 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  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
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  GSM::Time mTransmitDeadlineClock;       ///< deadline for pushing bursts into transmit FIFO 
 | 
					 | 
				
			||||||
  GSM::Time mLastClockUpdateTime;         ///< last time clock update was sent up to core
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  RadioInterface *mRadioInterface;	  ///< associated radioInterface object
 | 
					 | 
				
			||||||
  double txFullScale;                     ///< full scale input to radio
 | 
					 | 
				
			||||||
  double rxFullScale;                     ///< full scale output to radio
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Codes for burst types of received bursts*/
 | 
					/** Codes for burst types of received bursts*/
 | 
				
			||||||
typedef enum {
 | 
					typedef enum {
 | 
				
			||||||
@@ -75,6 +51,49 @@ private:
 | 
				
			|||||||
  IDLE	       ///< timeslot is an idle (or dummy) burst
 | 
					  IDLE	       ///< timeslot is an idle (or dummy) burst
 | 
				
			||||||
} CorrType;
 | 
					} CorrType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Demodulator;
 | 
				
			||||||
 | 
					class Transceiver;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct ThreadStruct {
 | 
				
			||||||
 | 
					   Transceiver *trx;
 | 
				
			||||||
 | 
					   unsigned ARFCN;
 | 
				
			||||||
 | 
					} ThreadStruct;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** The Transceiver class, responsible for physical layer of basestation */
 | 
				
			||||||
 | 
					class Transceiver {
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  GSM::Time mTransmitLatency;     ///< latency between basestation clock and transmit deadline clock
 | 
				
			||||||
 | 
					  GSM::Time mLatencyUpdateTime;   ///< last time latency was updated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  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 *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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Mutex mControlLock;
 | 
				
			||||||
 | 
					  Mutex mTransmitPriorityQueueLock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool mLoadTest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Codes for channel combinations */
 | 
					  /** Codes for channel combinations */
 | 
				
			||||||
  typedef enum {
 | 
					  typedef enum {
 | 
				
			||||||
@@ -99,22 +118,18 @@ private:
 | 
				
			|||||||
  /** modulate and add a burst to the transmit queue */
 | 
					  /** modulate and add a burst to the transmit queue */
 | 
				
			||||||
  void addRadioVector(BitVector &burst,
 | 
					  void addRadioVector(BitVector &burst,
 | 
				
			||||||
		      int RSSI,
 | 
							      int RSSI,
 | 
				
			||||||
		      GSM::Time &wTime);
 | 
							      GSM::Time &wTime,
 | 
				
			||||||
 | 
							      int ARFCN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
 | 
					  /** Push modulated burst into transmit FIFO corresponding to a particular timestamp */
 | 
				
			||||||
  void pushRadioVector(GSM::Time &nowTime);
 | 
					  void pushRadioVector(GSM::Time &nowTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Pull and demodulate a burst from the receive FIFO */ 
 | 
					  /** Pull and demodulate a burst from the receive FIFO */ 
 | 
				
			||||||
  SoftVector *pullRadioVector(GSM::Time &wTime,
 | 
					  void pullRadioVector(void);
 | 
				
			||||||
			   int &RSSI,
 | 
					 | 
				
			||||||
			   int &timingOffset);
 | 
					 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
  /** Set modulus for specific timeslot */
 | 
					  /** Set modulus for specific timeslot */
 | 
				
			||||||
  void setModulus(int 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 */
 | 
					  /** send messages over the clock socket */
 | 
				
			||||||
  void writeClockInterface(void);
 | 
					  void writeClockInterface(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,24 +138,27 @@ private:
 | 
				
			|||||||
  int mSamplesPerSymbol;               ///< number of samples per GSM symbol
 | 
					  int mSamplesPerSymbol;               ///< number of samples per GSM symbol
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool mOn;			       ///< flag to indicate that transceiver is powered on
 | 
					  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 mTxFreq;                      ///< the transmit frequency
 | 
				
			||||||
  double mRxFreq;                      ///< the receive frequency
 | 
					  double mRxFreq;                      ///< the receive frequency
 | 
				
			||||||
  int mPower;                          ///< the transmit power in dB
 | 
					  int mPower;                          ///< the transmit power in dB
 | 
				
			||||||
  unsigned mTSC;                       ///< the midamble sequence code
 | 
					  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
 | 
					  int fillerModulus[8];                ///< modulus values of all timeslots, in frames
 | 
				
			||||||
  signalVector *fillerTable[102][8];   ///< table of modulated filler waveforms for all timeslots
 | 
					  signalVector *fillerTable[102][8];   ///< table of modulated filler waveforms for all timeslots
 | 
				
			||||||
  unsigned mMaxExpectedDelay;            ///< maximum expected time-of-arrival offset in GSM symbols
 | 
					  unsigned mMaxExpectedDelay;            ///< maximum expected time-of-arrival offset in GSM symbols
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GSM::Time    channelEstimateTime[8]; ///< last timestamp of each timeslot's channel estimate
 | 
					  unsigned int mNumARFCNs;
 | 
				
			||||||
  signalVector *channelResponse[8];    ///< most recent channel estimate of all timeslots
 | 
					  bool mMultipleARFCN;
 | 
				
			||||||
  float        SNRestimate[8];         ///< most recent SNR estimate of all timeslots
 | 
					  unsigned char mOversamplingRate;
 | 
				
			||||||
  signalVector *DFEForward[8];         ///< most recent DFE feedforward filter of all timeslots
 | 
					  double mFreqOffset;
 | 
				
			||||||
  signalVector *DFEFeedback[8];        ///< most recent DFE feedback filter of all timeslots
 | 
					  signalVector *frequencyShifter[MAXARFCN];
 | 
				
			||||||
  float        chanRespOffset[8];      ///< most recent timing offset, e.g. TOA, of all timeslots
 | 
					  signalVector *decimationFilter;
 | 
				
			||||||
  complex      chanRespAmplitude[8];   ///< most recent channel amplitude of all timeslots
 | 
					  signalVector *interpolationFilter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Demodulator *mDemodulators[MAXARFCN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -155,7 +173,10 @@ public:
 | 
				
			|||||||
	      const char *TRXAddress,
 | 
						      const char *TRXAddress,
 | 
				
			||||||
	      int wSamplesPerSymbol,
 | 
						      int wSamplesPerSymbol,
 | 
				
			||||||
	      GSM::Time wTransmitLatency,
 | 
						      GSM::Time wTransmitLatency,
 | 
				
			||||||
	      RadioInterface *wRadioInterface);
 | 
						      RadioInterface *wRadioInterface,
 | 
				
			||||||
 | 
						      unsigned int wNumARFCNs,
 | 
				
			||||||
 | 
						      unsigned int wOversamplingRate,
 | 
				
			||||||
 | 
						      bool wLoadTest);
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
  /** Destructor */
 | 
					  /** Destructor */
 | 
				
			||||||
  ~Transceiver();
 | 
					  ~Transceiver();
 | 
				
			||||||
@@ -163,12 +184,30 @@ public:
 | 
				
			|||||||
  /** start the Transceiver */
 | 
					  /** start the Transceiver */
 | 
				
			||||||
  void start();
 | 
					  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 */
 | 
					  /** attach the radioInterface receive FIFO */
 | 
				
			||||||
  void receiveFIFO(VectorFIFO *wFIFO) { mReceiveFIFO = wFIFO;}
 | 
					  void receiveFIFO(VectorFIFO *wFIFO) { mReceiveFIFO = wFIFO;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** attach the radioInterface transmit FIFO */
 | 
					  /** attach the radioInterface transmit FIFO */
 | 
				
			||||||
  void transmitFIFO(VectorFIFO *wFIFO) { mTransmitFIFO = wFIFO;}
 | 
					  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:
 | 
					protected:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -179,19 +218,21 @@ protected:
 | 
				
			|||||||
  void driveTransmitFIFO();
 | 
					  void driveTransmitFIFO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** drive handling of control messages from GSM core */
 | 
					  /** drive handling of control messages from GSM core */
 | 
				
			||||||
  void driveControl();
 | 
					  void driveControl(unsigned ARFCN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					  /**
 | 
				
			||||||
    drive modulation and sorting of GSM bursts from GSM core
 | 
					    drive modulation and sorting of GSM bursts from GSM core
 | 
				
			||||||
    @return true if a burst was transferred successfully
 | 
					    @return true if a burst was transferred successfully
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
  bool driveTransmitPriorityQueue();
 | 
					  bool driveTransmitPriorityQueue(unsigned ARFCN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friend void *FIFOServiceLoopAdapter(Transceiver *);
 | 
					  friend void *FIFOServiceLoopAdapter(Transceiver *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  friend void *ControlServiceLoopAdapter(Transceiver *);
 | 
					  friend void *RFIFOServiceLoopAdapter(Transceiver *);
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
  friend void *TransmitPriorityQueueServiceLoopAdapter(Transceiver *);
 | 
					  friend void *ControlServiceLoopAdapter(ThreadStruct *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  friend void *TransmitPriorityQueueServiceLoopAdapter(ThreadStruct *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void reset();
 | 
					  void reset();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -199,9 +240,61 @@ protected:
 | 
				
			|||||||
/** FIFO thread loop */
 | 
					/** FIFO thread loop */
 | 
				
			||||||
void *FIFOServiceLoopAdapter(Transceiver *);
 | 
					void *FIFOServiceLoopAdapter(Transceiver *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void *RFIFOServiceLoopAdapter(Transceiver *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** control message handler thread loop */
 | 
					/** control message handler thread loop */
 | 
				
			||||||
void *ControlServiceLoopAdapter(Transceiver *);
 | 
					void *ControlServiceLoopAdapter(ThreadStruct *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** transmit queueing thread loop */
 | 
					/** 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 *);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,6 +71,8 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
 | 
				
			|||||||
                               int wReceiveOffset,
 | 
					                               int wReceiveOffset,
 | 
				
			||||||
			       int wRadioOversampling,
 | 
								       int wRadioOversampling,
 | 
				
			||||||
			       int wTransceiverOversampling,
 | 
								       int wTransceiverOversampling,
 | 
				
			||||||
 | 
								       bool wLoadTest,
 | 
				
			||||||
 | 
								       unsigned int wNumARFCNs,
 | 
				
			||||||
			       GSM::Time wStartTime)
 | 
								       GSM::Time wStartTime)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -85,6 +87,9 @@ RadioInterface::RadioInterface(RadioDevice *wRadio,
 | 
				
			|||||||
  samplesPerSymbol = wRadioOversampling;
 | 
					  samplesPerSymbol = wRadioOversampling;
 | 
				
			||||||
  mClock.set(wStartTime);
 | 
					  mClock.set(wStartTime);
 | 
				
			||||||
  powerScaling = 1.0;
 | 
					  powerScaling = 1.0;
 | 
				
			||||||
 | 
					  mNumARFCNs = wNumARFCNs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  loadTest = wLoadTest;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RadioInterface::~RadioInterface(void) {
 | 
					RadioInterface::~RadioInterface(void) {
 | 
				
			||||||
@@ -236,6 +241,34 @@ void RadioInterface::start()
 | 
				
			|||||||
 
 | 
					 
 | 
				
			||||||
  mOn = true;
 | 
					  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)
 | 
					void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
 | 
				
			||||||
@@ -287,14 +320,15 @@ void RadioInterface::driveReceiveRadio() {
 | 
				
			|||||||
    GSM::Time tmpTime = rcvClock;
 | 
					    GSM::Time tmpTime = rcvClock;
 | 
				
			||||||
    if (rcvClock.FN() >= 0) {
 | 
					    if (rcvClock.FN() >= 0) {
 | 
				
			||||||
      //LOG(DEBUG) << "FN: " << rcvClock.FN();
 | 
					      //LOG(DEBUG) << "FN: " << rcvClock.FN();
 | 
				
			||||||
 | 
					      int dummyARFCN = 0;
 | 
				
			||||||
      radioVector *rxBurst = NULL;
 | 
					      radioVector *rxBurst = NULL;
 | 
				
			||||||
      if (!loadTest)
 | 
					      if (!loadTest)
 | 
				
			||||||
        rxBurst = new radioVector(rxVector,tmpTime);
 | 
					        rxBurst = new radioVector(rxVector,tmpTime,dummyARFCN);
 | 
				
			||||||
      else {
 | 
					      else {
 | 
				
			||||||
	if (tN % 4 == 0)
 | 
						if (tN % 4 == 0)
 | 
				
			||||||
	  rxBurst = new radioVector(*finalVec9,tmpTime);
 | 
						  rxBurst = new radioVector(*finalVec9,tmpTime,dummyARFCN);
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
          rxBurst = new radioVector(*finalVec,tmpTime); 
 | 
					          rxBurst = new radioVector(*finalVec,tmpTime,dummyARFCN); 
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      mReceiveFIFO.put(rxBurst); 
 | 
					      mReceiveFIFO.put(rxBurst); 
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,16 +40,22 @@ class radioVector : public signalVector {
 | 
				
			|||||||
private:
 | 
					private:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GSM::Time mTime;   ///< the burst's GSM timestamp 
 | 
					  GSM::Time mTime;   ///< the burst's GSM timestamp 
 | 
				
			||||||
 | 
					  int mARFCN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
  /** constructor */
 | 
					  /** constructor */
 | 
				
			||||||
  radioVector(const signalVector& wVector,
 | 
					  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 */
 | 
					  /** timestamp read and write operators */
 | 
				
			||||||
  GSM::Time time() const { return mTime;}
 | 
					  GSM::Time time() const { return mTime;}
 | 
				
			||||||
  void time(const GSM::Time& wTime) { mTime = wTime;}
 | 
					  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 */
 | 
					  /** comparison operator, used for sorting */
 | 
				
			||||||
  bool operator>(const radioVector& other) const {return mTime > other.mTime;}
 | 
					  bool operator>(const radioVector& other) const {return mTime > other.mTime;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -111,12 +117,12 @@ private:
 | 
				
			|||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Set clock */
 | 
					  /** 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.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.broadcast();;}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Increment clock */
 | 
					  /** Increment clock */
 | 
				
			||||||
  //void incTN() { ScopedLock lock(mLock); mClock.incTN(); updateSignal.signal();}
 | 
					  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.broadcast();}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Get clock value */
 | 
					  /** Get clock value */
 | 
				
			||||||
  GSM::Time get() { ScopedLock lock(mLock); return mClock; }
 | 
					  GSM::Time get() { ScopedLock lock(mLock); return mClock; }
 | 
				
			||||||
@@ -188,6 +194,8 @@ public:
 | 
				
			|||||||
		 int receiveOffset = 3,
 | 
							 int receiveOffset = 3,
 | 
				
			||||||
		 int wRadioOversampling = SAMPSPERSYM,
 | 
							 int wRadioOversampling = SAMPSPERSYM,
 | 
				
			||||||
		 int wTransceiverOversampling = SAMPSPERSYM,
 | 
							 int wTransceiverOversampling = SAMPSPERSYM,
 | 
				
			||||||
 | 
							 bool wLoadTest = false,
 | 
				
			||||||
 | 
							 unsigned int wNumARFCNS = 1,
 | 
				
			||||||
		 GSM::Time wStartTime = GSM::Time(0));
 | 
							 GSM::Time wStartTime = GSM::Time(0));
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  /** destructor */
 | 
					  /** destructor */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -74,7 +74,7 @@ int usbMsg (struct libusb_device_handle *udh,
 | 
				
			|||||||
  if (ret < 0) {
 | 
					  if (ret < 0) {
 | 
				
			||||||
    // we get EPIPE if the firmware stalls the endpoint.
 | 
					    // we get EPIPE if the firmware stalls the endpoint.
 | 
				
			||||||
    if (ret != LIBUSB_ERROR_PIPE) {
 | 
					    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);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,16 +66,79 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
  // Configure logger.
 | 
					  // Configure logger.
 | 
				
			||||||
  gLogInit("transceiver",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
 | 
					  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));
 | 
					  srandom(time(NULL));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int mOversamplingRate = 1;
 | 
					  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);
 | 
					  RAD1Device *usrp = new RAD1Device(mOversamplingRate*1625.0e3/6.0);
 | 
				
			||||||
 | 
					  //DummyLoad *usrp = new DummyLoad(mOversamplingRate*1625.0e3/6.0);
 | 
				
			||||||
  usrp->make(); 
 | 
					  usrp->make(); 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  RadioInterface* radio = new RadioInterface(usrp,3,SAMPSPERSYM,mOversamplingRate,false);
 | 
					  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);
 | 
					  Transceiver *trx = new Transceiver(5700,"127.0.0.1",SAMPSPERSYM,GSM::Time(2,0),radio,
 | 
				
			||||||
 | 
									     numARFCN,mOversamplingRate,false);
 | 
				
			||||||
  trx->receiveFIFO(radio->receiveFIFO());
 | 
					  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();
 | 
					  trx->start();
 | 
				
			||||||
  //int i = 0;
 | 
					  //int i = 0;
 | 
				
			||||||
  while(!gbShutdown) { sleep(1); } //i++; if (i==60) exit(1);}
 | 
					  while(!gbShutdown) { sleep(1); } //i++; if (i==60) exit(1);}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -599,6 +599,7 @@ signalVector *modulateBurst(const BitVector &wBurst,
 | 
				
			|||||||
  modBurst.isRealOnly(true);
 | 
					  modBurst.isRealOnly(true);
 | 
				
			||||||
  //memset(staticBurst,0,sizeof(complex)*burstSize);
 | 
					  //memset(staticBurst,0,sizeof(complex)*burstSize);
 | 
				
			||||||
  modBurst.fill(0.0);
 | 
					  modBurst.fill(0.0);
 | 
				
			||||||
 | 
					  //modBurst.fill(1.0);
 | 
				
			||||||
  signalVector::iterator modBurstItr = modBurst.begin();
 | 
					  signalVector::iterator modBurstItr = modBurst.begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if 0 
 | 
					#if 0 
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user