mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-11-04 06:03:17 +00:00 
			
		
		
		
	Compare commits
	
		
			6 Commits
		
	
	
		
			1.5.0
			...
			fairwaves/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2518186b45 | ||
| 
						 | 
					6512812e43 | ||
| 
						 | 
					ded68da44f | ||
| 
						 | 
					37bbfa2125 | ||
| 
						 | 
					fdbf914584 | ||
| 
						 | 
					bbef7e4d70 | 
@@ -206,7 +206,7 @@ Log::~Log()
 | 
				
			|||||||
	if (gLogToConsole||gLogToFile) {
 | 
						if (gLogToConsole||gLogToFile) {
 | 
				
			||||||
		int mlen = mStream.str().size();
 | 
							int mlen = mStream.str().size();
 | 
				
			||||||
		int neednl = (mlen==0 || mStream.str()[mlen-1] != '\n');
 | 
							int neednl = (mlen==0 || mStream.str()[mlen-1] != '\n');
 | 
				
			||||||
		gLogToLock.lock();
 | 
							ScopedLock lock(gLogToLock);
 | 
				
			||||||
		if (gLogToConsole) {
 | 
							if (gLogToConsole) {
 | 
				
			||||||
			// The COUT() macro prevents messages from stomping each other but adds uninteresting thread numbers,
 | 
								// The COUT() macro prevents messages from stomping each other but adds uninteresting thread numbers,
 | 
				
			||||||
			// so just use std::cout.
 | 
								// so just use std::cout.
 | 
				
			||||||
@@ -218,7 +218,6 @@ Log::~Log()
 | 
				
			|||||||
			if (neednl) {fputc('\n',gLogToFile);}
 | 
								if (neednl) {fputc('\n',gLogToFile);}
 | 
				
			||||||
			fflush(gLogToFile);
 | 
								fflush(gLogToFile);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		gLogToLock.unlock();
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@
 | 
				
			|||||||
*/
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <iomanip>      // std::setprecision
 | 
				
			||||||
#include "Transceiver.h"
 | 
					#include "Transceiver.h"
 | 
				
			||||||
#include <Logger.h>
 | 
					#include <Logger.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -140,13 +141,15 @@ bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Transceiver::Transceiver(int wBasePort,
 | 
					Transceiver::Transceiver(int wBasePort,
 | 
				
			||||||
			 const char *wTRXAddress,
 | 
					                         const char *wTRXAddress,
 | 
				
			||||||
			 size_t wSPS, size_t wChans,
 | 
					                         size_t wSPS, size_t wChans,
 | 
				
			||||||
			 GSM::Time wTransmitLatency,
 | 
					                         GSM::Time wTransmitLatency,
 | 
				
			||||||
			 RadioInterface *wRadioInterface)
 | 
					                         RadioInterface *wRadioInterface,
 | 
				
			||||||
 | 
					                         double wRssiOffset)
 | 
				
			||||||
  : mBasePort(wBasePort), mAddr(wTRXAddress),
 | 
					  : mBasePort(wBasePort), mAddr(wTRXAddress),
 | 
				
			||||||
    mClockSocket(wBasePort, wTRXAddress, mBasePort + 100),
 | 
					    mClockSocket(wBasePort, wTRXAddress, mBasePort + 100),
 | 
				
			||||||
    mTransmitLatency(wTransmitLatency), mRadioInterface(wRadioInterface),
 | 
					    mTransmitLatency(wTransmitLatency), mRadioInterface(wRadioInterface),
 | 
				
			||||||
 | 
					    rssiOffset(wRssiOffset),
 | 
				
			||||||
    mSPSTx(wSPS), mSPSRx(1), mChans(wChans), mOn(false),
 | 
					    mSPSTx(wSPS), mSPSRx(1), mChans(wChans), mOn(false),
 | 
				
			||||||
    mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelay(0)
 | 
					    mTxFreq(0.0), mRxFreq(0.0), mTSC(0), mMaxExpectedDelay(0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -531,9 +534,9 @@ Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime,
 | 
				
			|||||||
 * Detect RACH synchronization sequence within a burst. No equalization
 | 
					 * Detect RACH synchronization sequence within a burst. No equalization
 | 
				
			||||||
 * is used or available on the RACH channel.
 | 
					 * is used or available on the RACH channel.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool Transceiver::detectRACH(TransceiverState *state,
 | 
					int Transceiver::detectRACH(TransceiverState *state,
 | 
				
			||||||
                             signalVector &burst,
 | 
					                            signalVector &burst,
 | 
				
			||||||
                             complex &, float &toa)
 | 
					                            complex &, float &toa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  float threshold = 6.0;
 | 
					  float threshold = 6.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -545,9 +548,10 @@ bool Transceiver::detectRACH(TransceiverState *state,
 | 
				
			|||||||
 * state information and channel estimate if necessary. Equalization
 | 
					 * state information and channel estimate if necessary. Equalization
 | 
				
			||||||
 * is currently disabled.
 | 
					 * is currently disabled.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
bool Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
 | 
					int Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
 | 
				
			||||||
                            complex &, float &toa, GSM::Time &time)
 | 
					                           complex &, float &toa, GSM::Time &time)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  int success;
 | 
				
			||||||
  int tn = time.TN();
 | 
					  int tn = time.TN();
 | 
				
			||||||
  float chanOffset, threshold = 5.0;
 | 
					  float chanOffset, threshold = 5.0;
 | 
				
			||||||
  bool noise, needDFE = false, estimateChan = false;
 | 
					  bool noise, needDFE = false, estimateChan = false;
 | 
				
			||||||
@@ -565,10 +569,11 @@ bool Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Detect normal burst midambles */
 | 
					  /* Detect normal burst midambles */
 | 
				
			||||||
  if (!analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx, &,
 | 
					  success = analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx, &,
 | 
				
			||||||
                           &toa, mMaxExpectedDelay, estimateChan,
 | 
					                                &toa, mMaxExpectedDelay, estimateChan,
 | 
				
			||||||
                           &chanResp, &chanOffset)) {
 | 
					                                &chanResp, &chanOffset);
 | 
				
			||||||
    return false;
 | 
					  if (success <= 0) {
 | 
				
			||||||
 | 
					    return success;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  noise = state->mNoiseLev;
 | 
					  noise = state->mNoiseLev;
 | 
				
			||||||
@@ -588,7 +593,7 @@ bool Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
 | 
				
			|||||||
     state->chanEstimateTime[tn] = time;
 | 
					     state->chanEstimateTime[tn] = time;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return true;;
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -615,10 +620,12 @@ SoftVector *Transceiver::demodulate(TransceiverState *state,
 | 
				
			|||||||
 * Pull bursts from the FIFO and handle according to the slot
 | 
					 * Pull bursts from the FIFO and handle according to the slot
 | 
				
			||||||
 * and burst correlation type. Equalzation is currently disabled. 
 | 
					 * and burst correlation type. Equalzation is currently disabled. 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, int &RSSI,
 | 
					SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI,
 | 
				
			||||||
                                         int &timingOffset, size_t chan)
 | 
					                                         double &timingOffset, double &noise,
 | 
				
			||||||
 | 
					                                         size_t chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  bool success, equalize = false;
 | 
					  int success;
 | 
				
			||||||
 | 
					  bool equalize = false;
 | 
				
			||||||
  complex amp;
 | 
					  complex amp;
 | 
				
			||||||
  float toa, pow, max = -1.0, avg = 0.0;
 | 
					  float toa, pow, max = -1.0, avg = 0.0;
 | 
				
			||||||
  int max_i = -1;
 | 
					  int max_i = -1;
 | 
				
			||||||
@@ -669,12 +676,12 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, int &RSSI,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /* Update noise average if no bust detected or alert on error */
 | 
					  /* Update noise average if no bust detected or alert on error */
 | 
				
			||||||
  if (success <= 0) {
 | 
					  if (success <= 0) {
 | 
				
			||||||
    if (!success) {
 | 
					    if (success == SIGERR_NONE) {
 | 
				
			||||||
      state->mNoises.insert(avg);
 | 
					      state->mNoises.insert(avg);
 | 
				
			||||||
    } else if (success == -SIGERR_CLIP) {
 | 
					    } else if (success == -SIGERR_CLIP) {
 | 
				
			||||||
      LOG(ALERT) << "Clipping detected on RACH input";
 | 
					      LOG(WARNING) << "Clipping detected on received RACH or Normal Burst";
 | 
				
			||||||
    } else if (success < 0) {
 | 
					    } else {
 | 
				
			||||||
      LOG(ALERT) << "Unhandled RACH error";
 | 
					      LOG(WARNING) << "Unhandled RACH or Normal Burst detection error";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    delete radio_burst;
 | 
					    delete radio_burst;
 | 
				
			||||||
@@ -689,8 +696,9 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, int &RSSI,
 | 
				
			|||||||
    bits = demodulate(state, *burst, amp, toa, time.TN(), equalize);
 | 
					    bits = demodulate(state, *burst, amp, toa, time.TN(), equalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wTime = time;
 | 
					  wTime = time;
 | 
				
			||||||
  RSSI = (int) floor(20.0 * log10(rxFullScale / avg));
 | 
					  RSSI = 20.0 * log10(rxFullScale / avg);
 | 
				
			||||||
  timingOffset = (int) round(toa * 256.0 / mSPSRx);
 | 
					  timingOffset = toa / mSPSRx;
 | 
				
			||||||
 | 
					  noise = 20.0 * log10(rxFullScale / state->mNoiseLev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delete radio_burst;
 | 
					  delete radio_burst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -892,27 +900,33 @@ void Transceiver::driveReceiveRadio()
 | 
				
			|||||||
void Transceiver::driveReceiveFIFO(size_t chan)
 | 
					void Transceiver::driveReceiveFIFO(size_t chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  SoftVector *rxBurst = NULL;
 | 
					  SoftVector *rxBurst = NULL;
 | 
				
			||||||
  int RSSI;
 | 
					  double RSSI; // in dBFS
 | 
				
			||||||
  int TOA;  // in 1/256 of a symbol
 | 
					  double dBm;  // in dBm
 | 
				
			||||||
 | 
					  double TOA;  // in symbols
 | 
				
			||||||
 | 
					  int TOAint;  // in 1/256 symbols
 | 
				
			||||||
 | 
					  double noise; // noise level in dBFS
 | 
				
			||||||
  GSM::Time burstTime;
 | 
					  GSM::Time burstTime;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  rxBurst = pullRadioVector(burstTime, RSSI, TOA, chan);
 | 
					  rxBurst = pullRadioVector(burstTime, RSSI, TOA, noise, chan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (rxBurst) { 
 | 
					  if (rxBurst) { 
 | 
				
			||||||
 | 
					    dBm = RSSI+rssiOffset;
 | 
				
			||||||
 | 
					    TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LOG(DEBUG) << std::fixed << std::right
 | 
				
			||||||
 | 
					      << " time: "   << burstTime
 | 
				
			||||||
 | 
						  << " RSSI: "   << std::setw(5) << std::setprecision(1) << RSSI << "dBFS/" << std::setw(6) << -dBm << "dBm"
 | 
				
			||||||
 | 
						  << " noise: "  << std::setw(5) << std::setprecision(1) << noise << "dBFS/" << std::setw(6) << -(noise+rssiOffset) << "dBm"
 | 
				
			||||||
 | 
						  << " TOA: "    << std::setw(5) << std::setprecision(2) << TOA
 | 
				
			||||||
 | 
					      << " bits: "   << *rxBurst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LOG(DEBUG) << "burst parameters: "
 | 
					 | 
				
			||||||
	  << " time: " << burstTime
 | 
					 | 
				
			||||||
	  << " RSSI: " << RSSI
 | 
					 | 
				
			||||||
	  << " TOA: "  << TOA
 | 
					 | 
				
			||||||
	  << " bits: " << *rxBurst;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    char burstString[gSlotLen+10];
 | 
					    char burstString[gSlotLen+10];
 | 
				
			||||||
    burstString[0] = burstTime.TN();
 | 
					    burstString[0] = burstTime.TN();
 | 
				
			||||||
    for (int i = 0; i < 4; i++)
 | 
					    for (int i = 0; i < 4; i++)
 | 
				
			||||||
      burstString[1+i] = (burstTime.FN() >> ((3-i)*8)) & 0x0ff;
 | 
					      burstString[1+i] = (burstTime.FN() >> ((3-i)*8)) & 0x0ff;
 | 
				
			||||||
    burstString[5] = RSSI;
 | 
					    burstString[5] = (int)dBm;
 | 
				
			||||||
    burstString[6] = (TOA >> 8) & 0x0ff;
 | 
					    burstString[6] = (TOAint >> 8) & 0x0ff;
 | 
				
			||||||
    burstString[7] = TOA & 0x0ff;
 | 
					    burstString[7] = TOAint & 0x0ff;
 | 
				
			||||||
    SoftVector::iterator burstItr = rxBurst->begin();
 | 
					    SoftVector::iterator burstItr = rxBurst->begin();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (unsigned int i = 0; i < gSlotLen; i++) {
 | 
					    for (unsigned int i = 0; i < gSlotLen; i++) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -97,10 +97,11 @@ public:
 | 
				
			|||||||
      @param radioInterface associated radioInterface object
 | 
					      @param radioInterface associated radioInterface object
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
  Transceiver(int wBasePort,
 | 
					  Transceiver(int wBasePort,
 | 
				
			||||||
	      const char *TRXAddress,
 | 
					              const char *TRXAddress,
 | 
				
			||||||
	      size_t wSPS, size_t chans,
 | 
					              size_t wSPS, size_t chans,
 | 
				
			||||||
	      GSM::Time wTransmitLatency,
 | 
					              GSM::Time wTransmitLatency,
 | 
				
			||||||
	      RadioInterface *wRadioInterface);
 | 
					              RadioInterface *wRadioInterface,
 | 
				
			||||||
 | 
					              double wRssiOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Destructor */
 | 
					  /** Destructor */
 | 
				
			||||||
  ~Transceiver();
 | 
					  ~Transceiver();
 | 
				
			||||||
@@ -181,6 +182,8 @@ private:
 | 
				
			|||||||
  double txFullScale;                     ///< full scale input to radio
 | 
					  double txFullScale;                     ///< full scale input to radio
 | 
				
			||||||
  double rxFullScale;                     ///< full scale output to radio
 | 
					  double rxFullScale;                     ///< full scale output to radio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  double rssiOffset;                      ///< RSSI to dBm conversion offset
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** modulate and add a burst to the transmit queue */
 | 
					  /** modulate and add a burst to the transmit queue */
 | 
				
			||||||
  void addRadioVector(size_t chan, BitVector &bits,
 | 
					  void addRadioVector(size_t chan, BitVector &bits,
 | 
				
			||||||
                      int RSSI, GSM::Time &wTime);
 | 
					                      int RSSI, GSM::Time &wTime);
 | 
				
			||||||
@@ -192,8 +195,9 @@ private:
 | 
				
			|||||||
  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, int &RSSI,
 | 
					  SoftVector *pullRadioVector(GSM::Time &wTime, double &RSSI,
 | 
				
			||||||
                              int &timingOffset, size_t chan = 0);
 | 
					                              double &timingOffset, double &noise,
 | 
				
			||||||
 | 
					                              size_t chan = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Set modulus for specific timeslot */
 | 
					  /** Set modulus for specific timeslot */
 | 
				
			||||||
  void setModulus(size_t timeslot, size_t chan);
 | 
					  void setModulus(size_t timeslot, size_t chan);
 | 
				
			||||||
@@ -205,14 +209,14 @@ private:
 | 
				
			|||||||
  void writeClockInterface(void);
 | 
					  void writeClockInterface(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Detect RACH bursts */
 | 
					  /** Detect RACH bursts */
 | 
				
			||||||
  bool detectRACH(TransceiverState *state,
 | 
					  int detectRACH(TransceiverState *state,
 | 
				
			||||||
                  signalVector &burst,
 | 
					                 signalVector &burst,
 | 
				
			||||||
                  complex &, float &toa);
 | 
					                 complex &, float &toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Detect normal bursts */
 | 
					  /** Detect normal bursts */
 | 
				
			||||||
  bool detectTSC(TransceiverState *state,
 | 
					  int detectTSC(TransceiverState *state,
 | 
				
			||||||
                 signalVector &burst,
 | 
					                signalVector &burst,
 | 
				
			||||||
                 complex &, float &toa, GSM::Time &time);
 | 
					                complex &, float &toa, GSM::Time &time);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Demodulat burst and output soft bits */
 | 
					  /** Demodulat burst and output soft bits */
 | 
				
			||||||
  SoftVector *demodulate(TransceiverState *state,
 | 
					  SoftVector *demodulate(TransceiverState *state,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,6 +70,7 @@ struct trx_config {
 | 
				
			|||||||
	Transceiver::FillerType filler;
 | 
						Transceiver::FillerType filler;
 | 
				
			||||||
	bool diversity;
 | 
						bool diversity;
 | 
				
			||||||
	double offset;
 | 
						double offset;
 | 
				
			||||||
 | 
						double rssi_offset;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ConfigurationTable gConfig;
 | 
					ConfigurationTable gConfig;
 | 
				
			||||||
@@ -185,6 +186,7 @@ bool trx_setup_config(struct trx_config *config)
 | 
				
			|||||||
	ost << "   C0 Filler Table......... " << fillstr << std::endl;
 | 
						ost << "   C0 Filler Table......... " << fillstr << std::endl;
 | 
				
			||||||
	ost << "   Diversity............... " << divstr << std::endl;
 | 
						ost << "   Diversity............... " << divstr << std::endl;
 | 
				
			||||||
	ost << "   Tuning offset........... " << config->offset << std::endl;
 | 
						ost << "   Tuning offset........... " << config->offset << std::endl;
 | 
				
			||||||
 | 
						ost << "   RSSI to dBm offset...... " << config->rssi_offset << std::endl;
 | 
				
			||||||
	std::cout << ost << std::endl;
 | 
						std::cout << ost << std::endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
@@ -240,7 +242,7 @@ Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
 | 
				
			|||||||
	VectorFIFO *fifo;
 | 
						VectorFIFO *fifo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	trx = new Transceiver(config->port, config->addr.c_str(), config->sps,
 | 
						trx = new Transceiver(config->port, config->addr.c_str(), config->sps,
 | 
				
			||||||
			      config->chans, GSM::Time(3,0), radio);
 | 
							config->chans, GSM::Time(3,0), radio, config->rssi_offset);
 | 
				
			||||||
	if (!trx->init(config->filler, config->rtsc)) {
 | 
						if (!trx->init(config->filler, config->rtsc)) {
 | 
				
			||||||
		LOG(ALERT) << "Failed to initialize transceiver";
 | 
							LOG(ALERT) << "Failed to initialize transceiver";
 | 
				
			||||||
		delete trx;
 | 
							delete trx;
 | 
				
			||||||
@@ -292,7 +294,8 @@ static void print_help()
 | 
				
			|||||||
		"  -c    Number of ARFCN channels (default=1)\n"
 | 
							"  -c    Number of ARFCN channels (default=1)\n"
 | 
				
			||||||
		"  -f    Enable C0 filler table\n"
 | 
							"  -f    Enable C0 filler table\n"
 | 
				
			||||||
		"  -o    Set baseband frequency offset (default=auto)\n"
 | 
							"  -o    Set baseband frequency offset (default=auto)\n"
 | 
				
			||||||
		"  -r    Random burst test mode with TSC\n",
 | 
							"  -r    Random burst test mode with TSC\n"
 | 
				
			||||||
 | 
							"  -R    RSSI to dBm offset in dB (default=0)\n",
 | 
				
			||||||
		"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
 | 
							"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -308,8 +311,9 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
 | 
				
			|||||||
	config->filler = Transceiver::FILLER_ZERO;
 | 
						config->filler = Transceiver::FILLER_ZERO;
 | 
				
			||||||
	config->diversity = false;
 | 
						config->diversity = false;
 | 
				
			||||||
	config->offset = 0.0;
 | 
						config->offset = 0.0;
 | 
				
			||||||
 | 
						config->rssi_offset = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:")) != -1) {
 | 
						while ((option = getopt(argc, argv, "ha:l:i:p:c:dxfo:s:r:R:")) != -1) {
 | 
				
			||||||
		switch (option) {
 | 
							switch (option) {
 | 
				
			||||||
		case 'h':
 | 
							case 'h':
 | 
				
			||||||
			print_help();
 | 
								print_help();
 | 
				
			||||||
@@ -349,6 +353,9 @@ static void handle_options(int argc, char **argv, struct trx_config *config)
 | 
				
			|||||||
			config->rtsc = atoi(optarg);
 | 
								config->rtsc = atoi(optarg);
 | 
				
			||||||
			config->filler = Transceiver::FILLER_RAND;
 | 
								config->filler = Transceiver::FILLER_RAND;
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
 | 
							case 'R':
 | 
				
			||||||
 | 
								config->rssi_offset = atof(optarg);
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			print_help();
 | 
								print_help();
 | 
				
			||||||
			exit(0);
 | 
								exit(0);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,6 +28,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "sigProcLib.h"
 | 
					#include "sigProcLib.h"
 | 
				
			||||||
#include "GSMCommon.h"
 | 
					#include "GSMCommon.h"
 | 
				
			||||||
 | 
					#include "Logger.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
#include "convolve.h"
 | 
					#include "convolve.h"
 | 
				
			||||||
@@ -43,6 +44,9 @@ using namespace GSM;
 | 
				
			|||||||
/* Clipping detection threshold */
 | 
					/* Clipping detection threshold */
 | 
				
			||||||
#define CLIP_THRESH		30000.0f
 | 
					#define CLIP_THRESH		30000.0f
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* GSM 4 sps burst length */
 | 
				
			||||||
 | 
					#define GSM_BURST_LEN_4SPS	625
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Lookup tables for trigonometric approximation */
 | 
					/** Lookup tables for trigonometric approximation */
 | 
				
			||||||
float cosTable[TABLESIZE+1]; // add 1 element for wrap around
 | 
					float cosTable[TABLESIZE+1]; // add 1 element for wrap around
 | 
				
			||||||
float sinTable[TABLESIZE+1];
 | 
					float sinTable[TABLESIZE+1];
 | 
				
			||||||
@@ -696,27 +700,22 @@ static signalVector *rotateBurst(const BitVector &wBurst,
 | 
				
			|||||||
  return shaped;
 | 
					  return shaped;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static signalVector *modulateBurstLaurent(const BitVector &bits,
 | 
					/*
 | 
				
			||||||
					  int guard_len, int sps)
 | 
					 * Laurent decomposition based GMSK modulator - 4 SPS only
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static signalVector *modulateBurstLaurent(const BitVector &bits)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int burst_len;
 | 
					  const int burst_len = GSM_BURST_LEN_4SPS;
 | 
				
			||||||
 | 
					  const int sps = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float phase;
 | 
					  float phase;
 | 
				
			||||||
  signalVector *c0_pulse, *c1_pulse, *c0_burst;
 | 
					  signalVector *c0_pulse, *c1_pulse, *c0_burst;
 | 
				
			||||||
  signalVector *c1_burst, *c0_shaped, *c1_shaped;
 | 
					  signalVector *c1_burst, *c0_shaped, *c1_shaped;
 | 
				
			||||||
  signalVector::iterator c0_itr, c1_itr;
 | 
					  signalVector::iterator c0_itr, c1_itr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /*
 | 
					 | 
				
			||||||
   * Apply before and after bits to reduce phase error at burst edges.
 | 
					 | 
				
			||||||
   * Make sure there is enough room in the burst to accomodate all bits.
 | 
					 | 
				
			||||||
   */
 | 
					 | 
				
			||||||
  if (guard_len < 4)
 | 
					 | 
				
			||||||
    guard_len = 4;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  c0_pulse = GSMPulse->c0;
 | 
					  c0_pulse = GSMPulse->c0;
 | 
				
			||||||
  c1_pulse = GSMPulse->c1;
 | 
					  c1_pulse = GSMPulse->c1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  burst_len = sps * (bits.size() + guard_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  c0_burst = new signalVector(burst_len, c0_pulse->size());
 | 
					  c0_burst = new signalVector(burst_len, c0_pulse->size());
 | 
				
			||||||
  c0_burst->isReal(true);
 | 
					  c0_burst->isReal(true);
 | 
				
			||||||
  c0_itr = c0_burst->begin();
 | 
					  c0_itr = c0_burst->begin();
 | 
				
			||||||
@@ -825,7 +824,7 @@ signalVector *modulateBurst(const BitVector &wBurst, int guardPeriodLength,
 | 
				
			|||||||
  if (emptyPulse)
 | 
					  if (emptyPulse)
 | 
				
			||||||
    return rotateBurst(wBurst, guardPeriodLength, sps);
 | 
					    return rotateBurst(wBurst, guardPeriodLength, sps);
 | 
				
			||||||
  else if (sps == 4)
 | 
					  else if (sps == 4)
 | 
				
			||||||
    return modulateBurstLaurent(wBurst, guardPeriodLength, sps);
 | 
					    return modulateBurstLaurent(wBurst);
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    return modulateBurstBasic(wBurst, guardPeriodLength, sps);
 | 
					    return modulateBurstBasic(wBurst, guardPeriodLength, sps);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1284,12 +1283,12 @@ static float computePeakRatio(signalVector *corr,
 | 
				
			|||||||
  complex *peak;
 | 
					  complex *peak;
 | 
				
			||||||
  float rms, avg = 0.0;
 | 
					  float rms, avg = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  peak = corr->begin() + (int) rint(toa);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Check for bogus results */
 | 
					  /* Check for bogus results */
 | 
				
			||||||
  if ((toa < 0.0) || (toa > corr->size()))
 | 
					  if ((toa < 0.0) || (toa > corr->size()))
 | 
				
			||||||
    return 0.0;
 | 
					    return 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  peak = corr->begin() + (int) rint(toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (int i = 2 * sps; i <= 5 * sps; i++) {
 | 
					  for (int i = 2 * sps; i <= 5 * sps; i++) {
 | 
				
			||||||
    if (peak - i >= corr->begin()) {
 | 
					    if (peak - i >= corr->begin()) {
 | 
				
			||||||
      avg += (peak - i)->norm2();
 | 
					      avg += (peak - i)->norm2();
 | 
				
			||||||
@@ -1372,16 +1371,17 @@ static int detectBurst(signalVector &burst,
 | 
				
			|||||||
  return 1;
 | 
					  return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int detectClipping(signalVector &burst, float thresh)
 | 
					static float maxAmplitude(signalVector &burst)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	for (size_t i = 0; i < burst.size(); i++) {
 | 
					    float max = 0.0;
 | 
				
			||||||
		if (fabs(burst[i].real()) > thresh)
 | 
					    for (size_t i = 0; i < burst.size(); i++) {
 | 
				
			||||||
			return 1;
 | 
					        if (fabs(burst[i].real()) > max)
 | 
				
			||||||
		if (fabs(burst[i].imag()) > thresh)
 | 
					            max = fabs(burst[i].real());
 | 
				
			||||||
			return 1;
 | 
					        if (fabs(burst[i].imag()) > max)
 | 
				
			||||||
	}
 | 
					            max = fabs(burst[i].imag());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
					    return max;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 
 | 
					/* 
 | 
				
			||||||
@@ -1399,6 +1399,7 @@ int detectRACHBurst(signalVector &rxBurst,
 | 
				
			|||||||
		    float *toa)
 | 
							    float *toa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int rc, start, target, head, tail, len;
 | 
					  int rc, start, target, head, tail, len;
 | 
				
			||||||
 | 
					  bool clipping = false;
 | 
				
			||||||
  float _toa;
 | 
					  float _toa;
 | 
				
			||||||
  complex _amp;
 | 
					  complex _amp;
 | 
				
			||||||
  signalVector *corr;
 | 
					  signalVector *corr;
 | 
				
			||||||
@@ -1407,8 +1408,14 @@ int detectRACHBurst(signalVector &rxBurst,
 | 
				
			|||||||
  if ((sps != 1) && (sps != 4))
 | 
					  if ((sps != 1) && (sps != 4))
 | 
				
			||||||
    return -SIGERR_UNSUPPORTED;
 | 
					    return -SIGERR_UNSUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (detectClipping(rxBurst, CLIP_THRESH))
 | 
					  // Detect potential clipping
 | 
				
			||||||
    return -SIGERR_CLIP;
 | 
					  // We still may be able to demod the burst, so we'll give it a try
 | 
				
			||||||
 | 
					  // and only report clipping if we can't demod.
 | 
				
			||||||
 | 
					  float maxAmpl = maxAmplitude(rxBurst);
 | 
				
			||||||
 | 
					  if (maxAmpl > CLIP_THRESH) {
 | 
				
			||||||
 | 
					    LOG(DEBUG) << "max burst amplitude: " << maxAmpl << " is above the clipping threshold: " << CLIP_THRESH << std::endl;
 | 
				
			||||||
 | 
					    clipping = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  target = 8 + 40;
 | 
					  target = 8 + 40;
 | 
				
			||||||
  head = 4;
 | 
					  head = 4;
 | 
				
			||||||
@@ -1430,7 +1437,7 @@ int detectRACHBurst(signalVector &rxBurst,
 | 
				
			|||||||
      *amp = 0.0f;
 | 
					      *amp = 0.0f;
 | 
				
			||||||
    if (toa)
 | 
					    if (toa)
 | 
				
			||||||
      *toa = 0.0f;
 | 
					      *toa = 0.0f;
 | 
				
			||||||
    return 0;
 | 
					    return clipping?-SIGERR_CLIP:SIGERR_NONE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Subtract forward search bits from delay */
 | 
					  /* Subtract forward search bits from delay */
 | 
				
			||||||
@@ -1455,6 +1462,7 @@ int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
				
			|||||||
                        bool chan_req, signalVector **chan, float *chan_offset)
 | 
					                        bool chan_req, signalVector **chan, float *chan_offset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int rc, start, target, head, tail, len;
 | 
					  int rc, start, target, head, tail, len;
 | 
				
			||||||
 | 
					  bool clipping = false;
 | 
				
			||||||
  complex _amp;
 | 
					  complex _amp;
 | 
				
			||||||
  float _toa;
 | 
					  float _toa;
 | 
				
			||||||
  signalVector *corr;
 | 
					  signalVector *corr;
 | 
				
			||||||
@@ -1463,8 +1471,14 @@ int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
				
			|||||||
  if ((tsc < 0) || (tsc > 7) || ((sps != 1) && (sps != 4)))
 | 
					  if ((tsc < 0) || (tsc > 7) || ((sps != 1) && (sps != 4)))
 | 
				
			||||||
    return -SIGERR_UNSUPPORTED;
 | 
					    return -SIGERR_UNSUPPORTED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (detectClipping(rxBurst, CLIP_THRESH))
 | 
					  // Detect potential clipping
 | 
				
			||||||
    return -SIGERR_CLIP;
 | 
					  // We still may be able to demod the burst, so we'll give it a try
 | 
				
			||||||
 | 
					  // and only report clipping if we can't demod.
 | 
				
			||||||
 | 
					  float maxAmpl = maxAmplitude(rxBurst);
 | 
				
			||||||
 | 
					  if (maxAmpl > CLIP_THRESH) {
 | 
				
			||||||
 | 
					    LOG(DEBUG) << "max burst amplitude: " << maxAmpl << " is above the clipping threshold: " << CLIP_THRESH << std::endl;
 | 
				
			||||||
 | 
					    clipping = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  target = 3 + 58 + 16 + 5;
 | 
					  target = 3 + 58 + 16 + 5;
 | 
				
			||||||
  head = 4;
 | 
					  head = 4;
 | 
				
			||||||
@@ -1486,7 +1500,7 @@ int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
				
			|||||||
      *amp = 0.0f;
 | 
					      *amp = 0.0f;
 | 
				
			||||||
    if (toa)
 | 
					    if (toa)
 | 
				
			||||||
      *toa = 0.0f;
 | 
					      *toa = 0.0f;
 | 
				
			||||||
    return 0;
 | 
					    return clipping?-SIGERR_CLIP:SIGERR_NONE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Subtract forward search bits from delay */
 | 
					  /* Subtract forward search bits from delay */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user