mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-trx.git
				synced 2025-11-04 06:03:17 +00:00 
			
		
		
		
	transceiver: Remove remainings of the equalizer, restructure driveReceiveFIFO() for better modularity.
Equalizer has never worked properly and was always disabled. Now is a good time to remove it completely to make the code cleaner.
This commit is contained in:
		@@ -50,9 +50,6 @@ TransceiverState::TransceiverState()
 | 
				
			|||||||
  for (int i = 0; i < 8; i++) {
 | 
					  for (int i = 0; i < 8; i++) {
 | 
				
			||||||
    chanType[i] = Transceiver::NONE;
 | 
					    chanType[i] = Transceiver::NONE;
 | 
				
			||||||
    fillerModulus[i] = 26;
 | 
					    fillerModulus[i] = 26;
 | 
				
			||||||
    chanResponse[i] = NULL;
 | 
					 | 
				
			||||||
    DFEForward[i] = NULL;
 | 
					 | 
				
			||||||
    DFEFeedback[i] = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (int n = 0; n < 102; n++)
 | 
					    for (int n = 0; n < 102; n++)
 | 
				
			||||||
      fillerTable[n][i] = NULL;
 | 
					      fillerTable[n][i] = NULL;
 | 
				
			||||||
@@ -62,10 +59,6 @@ TransceiverState::TransceiverState()
 | 
				
			|||||||
TransceiverState::~TransceiverState()
 | 
					TransceiverState::~TransceiverState()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  for (int i = 0; i < 8; i++) {
 | 
					  for (int i = 0; i < 8; i++) {
 | 
				
			||||||
    delete chanResponse[i];
 | 
					 | 
				
			||||||
    delete DFEForward[i];
 | 
					 | 
				
			||||||
    delete DFEFeedback[i];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (int n = 0; n < 102; n++)
 | 
					    for (int n = 0; n < 102; n++)
 | 
				
			||||||
      delete fillerTable[n][i];
 | 
					      delete fillerTable[n][i];
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -141,6 +134,12 @@ bool TransceiverState::init(int filler, size_t sps, float scale, size_t rtsc)
 | 
				
			|||||||
  return false;
 | 
					  return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Transceiver::reset()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  for (size_t i = 0; i < mTxPriorityQueues.size(); i++)
 | 
				
			||||||
 | 
					    mTxPriorityQueues[i].clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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,
 | 
				
			||||||
@@ -556,11 +555,9 @@ Transceiver::CorrType Transceiver::expectedCorrType(GSM::Time currTime,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* 
 | 
					/* 
 | 
				
			||||||
 * Detect RACH synchronization sequence within a burst. No equalization
 | 
					 * Detect RACH synchronization sequence within a burst.
 | 
				
			||||||
 * is used or available on the RACH channel.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int Transceiver::detectRACH(TransceiverState *state,
 | 
					int Transceiver::detectRACH(signalVector &burst,
 | 
				
			||||||
                            signalVector &burst,
 | 
					 | 
				
			||||||
                            complex &, float &toa)
 | 
					                            complex &, float &toa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  float threshold = 6.0;
 | 
					  float threshold = 6.0;
 | 
				
			||||||
@@ -569,76 +566,16 @@ int Transceiver::detectRACH(TransceiverState *state,
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Detect normal burst training sequence midamble. Update equalization
 | 
					 * Detect normal burst training sequence midamble.
 | 
				
			||||||
 * state information and channel estimate if necessary. Equalization
 | 
					 | 
				
			||||||
 * is currently disabled.
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int Transceiver::detectTSC(TransceiverState *state, signalVector &burst,
 | 
					int Transceiver::detectTSC(signalVector &burst,
 | 
				
			||||||
                           complex &, float &toa, GSM::Time &time)
 | 
					                           complex &, float &toa)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int success;
 | 
					  float threshold = 5.0;
 | 
				
			||||||
  int tn = time.TN();
 | 
					 | 
				
			||||||
  float chanOffset, threshold = 5.0;
 | 
					 | 
				
			||||||
  bool needDFE = false, estimateChan = false;
 | 
					 | 
				
			||||||
  double elapsed = time - state->chanEstimateTime[tn];
 | 
					 | 
				
			||||||
  signalVector *chanResp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Check equalization update state */
 | 
					 | 
				
			||||||
  if (needDFE && ((elapsed > 50) || (!state->chanResponse[tn]))) {
 | 
					 | 
				
			||||||
    delete state->DFEForward[tn];
 | 
					 | 
				
			||||||
    delete state->DFEFeedback[tn];
 | 
					 | 
				
			||||||
    state->DFEForward[tn] = NULL;
 | 
					 | 
				
			||||||
    state->DFEFeedback[tn] = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    estimateChan = true;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Detect normal burst midambles */
 | 
					  /* Detect normal burst midambles */
 | 
				
			||||||
  success = analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx, amp,
 | 
					  return analyzeTrafficBurst(burst, mTSC, threshold, mSPSRx, amp,
 | 
				
			||||||
                                toa, mMaxExpectedDelay, estimateChan,
 | 
					                             toa, mMaxExpectedDelay);
 | 
				
			||||||
                                &chanResp, &chanOffset);
 | 
					 | 
				
			||||||
  if (success <= 0) {
 | 
					 | 
				
			||||||
    return success;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Set equalizer if unabled */
 | 
					 | 
				
			||||||
  if (needDFE && estimateChan) {
 | 
					 | 
				
			||||||
     float noise = state->mNoiseLev;
 | 
					 | 
				
			||||||
     state->SNRestimate[tn] = amp.norm2() / (noise * noise + 1.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     state->chanResponse[tn] = chanResp;
 | 
					 | 
				
			||||||
     state->chanRespOffset[tn] = chanOffset;
 | 
					 | 
				
			||||||
     state->chanRespAmplitude[tn] = amp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     scaleVector(*chanResp, complex(1.0, 0.0) / amp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     designDFE(*chanResp, state->SNRestimate[tn],
 | 
					 | 
				
			||||||
               7, &state->DFEForward[tn], &state->DFEFeedback[tn]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
     state->chanEstimateTime[tn] = time;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Demodulate GMSK burst using equalization if requested. Otherwise
 | 
					 | 
				
			||||||
 * demodulate by direct rotation and soft slicing.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
SoftVector *Transceiver::demodulate(TransceiverState *state,
 | 
					 | 
				
			||||||
                                    signalVector &burst, complex amp,
 | 
					 | 
				
			||||||
                                    float toa, size_t tn, bool equalize)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  if (equalize) {
 | 
					 | 
				
			||||||
    scaleVector(burst, complex(1.0, 0.0) / amp);
 | 
					 | 
				
			||||||
    return equalizeBurst(burst,
 | 
					 | 
				
			||||||
                         toa - state->chanRespOffset[tn],
 | 
					 | 
				
			||||||
                         mSPSRx,
 | 
					 | 
				
			||||||
                         *state->DFEForward[tn],
 | 
					 | 
				
			||||||
                         *state->DFEFeedback[tn]);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return demodulateBurst(burst, mSPSRx, amp, toa);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void writeToFile(radioVector *radio_burst, size_t chan)
 | 
					void writeToFile(radioVector *radio_burst, size_t chan)
 | 
				
			||||||
@@ -655,42 +592,47 @@ void writeToFile(radioVector *radio_burst, size_t chan)
 | 
				
			|||||||
 * 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, double &RSSI, bool &isRssiValid,
 | 
					SoftVector *Transceiver::demodSignalVector(signalVector *burst,
 | 
				
			||||||
                                         double &timingOffset, double &noise,
 | 
					                                           CorrType type,
 | 
				
			||||||
                                         size_t chan)
 | 
					                                           double &timingOffset)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int success;
 | 
					  int success;
 | 
				
			||||||
  bool equalize = false;
 | 
					 | 
				
			||||||
  complex amp;
 | 
					  complex amp;
 | 
				
			||||||
  float toa, pow, max = -1.0, avg = 0.0;
 | 
					  float toa;
 | 
				
			||||||
  int max_i = -1;
 | 
					 | 
				
			||||||
  signalVector *burst;
 | 
					 | 
				
			||||||
  SoftVector *bits = NULL;
 | 
					  SoftVector *bits = NULL;
 | 
				
			||||||
  TransceiverState *state = &mStates[chan];
 | 
					 | 
				
			||||||
  isRssiValid = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Blocking FIFO read */
 | 
					  /* Detect normal or RACH bursts */
 | 
				
			||||||
  radioVector *radio_burst = mReceiveFIFO[chan]->read();
 | 
					  if (type == TSC)
 | 
				
			||||||
  if (!radio_burst)
 | 
					    success = detectTSC(*burst, amp, toa);
 | 
				
			||||||
    return NULL;
 | 
					  else
 | 
				
			||||||
 | 
					    success = detectRACH(*burst, amp, toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Set time and determine correlation type */
 | 
					  /* Alert an error and exit */
 | 
				
			||||||
  GSM::Time time = radio_burst->getTime();
 | 
					  if (success <= 0) {
 | 
				
			||||||
  CorrType type = expectedCorrType(time, chan);
 | 
					    if (success == -SIGERR_CLIP) {
 | 
				
			||||||
 | 
					      LOG(WARNING) << "Clipping detected on received RACH or Normal Burst";
 | 
				
			||||||
 | 
					    } else if (success != SIGERR_NONE) {
 | 
				
			||||||
 | 
					      LOG(WARNING) << "Unhandled RACH or Normal Burst detection error";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Debug: dump bursts to disk */
 | 
					 | 
				
			||||||
  /* bits 0-7  - chan 0 timeslots
 | 
					 | 
				
			||||||
   * bits 8-15 - chan 1 timeslots */
 | 
					 | 
				
			||||||
  if (mWriteBurstToDiskMask & ((1<<time.TN()) << (8*chan)))
 | 
					 | 
				
			||||||
    writeToFile(radio_burst, chan);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* No processing if the timeslot is off.
 | 
					 | 
				
			||||||
   * Not even power level or noise calculation. */
 | 
					 | 
				
			||||||
  if (type == OFF) {
 | 
					 | 
				
			||||||
    delete radio_burst;
 | 
					 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  timingOffset = toa / mSPSRx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bits = demodulateBurst(*burst, mSPSRx, amp, toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return bits;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					signalVector *Transceiver::chooseDiversityPath(radioVector *radio_burst, double &avg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  signalVector *burst;
 | 
				
			||||||
 | 
					  int max_i = -1;
 | 
				
			||||||
 | 
					  float pow, max = -1.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  avg = 0.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Select the diversity channel with highest energy */
 | 
					  /* Select the diversity channel with highest energy */
 | 
				
			||||||
  for (size_t i = 0; i < radio_burst->chans(); i++) {
 | 
					  for (size_t i = 0; i < radio_burst->chans(); i++) {
 | 
				
			||||||
    energyDetect(*radio_burst->getVector(i), 20 * mSPSRx, 0.0, &pow);
 | 
					    energyDetect(*radio_burst->getVector(i), 20 * mSPSRx, 0.0, &pow);
 | 
				
			||||||
@@ -703,7 +645,6 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (max_i < 0) {
 | 
					  if (max_i < 0) {
 | 
				
			||||||
    LOG(ALERT) << "Received empty burst";
 | 
					    LOG(ALERT) << "Received empty burst";
 | 
				
			||||||
    delete radio_burst;
 | 
					 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -711,62 +652,16 @@ SoftVector *Transceiver::pullRadioVector(GSM::Time &wTime, double &RSSI, bool &i
 | 
				
			|||||||
  burst = radio_burst->getVector(max_i);
 | 
					  burst = radio_burst->getVector(max_i);
 | 
				
			||||||
  avg = sqrt(avg / radio_burst->chans());
 | 
					  avg = sqrt(avg / radio_burst->chans());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wTime = time;
 | 
					  return burst;
 | 
				
			||||||
  RSSI = 20.0 * log10(rxFullScale / avg);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* RSSI estimation are valid */
 | 
					 | 
				
			||||||
  isRssiValid = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (type == IDLE) {
 | 
					 | 
				
			||||||
    /* Update noise levels */
 | 
					 | 
				
			||||||
    state->mNoises.insert(avg);
 | 
					 | 
				
			||||||
    state->mNoiseLev = state->mNoises.avg();
 | 
					 | 
				
			||||||
    noise = 20.0 * log10(rxFullScale / state->mNoiseLev);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    delete radio_burst;
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    /* Do not update noise levels */
 | 
					 | 
				
			||||||
    noise = 20.0 * log10(rxFullScale / state->mNoiseLev);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Detect normal or RACH bursts */
 | 
					 | 
				
			||||||
  if (type == TSC)
 | 
					 | 
				
			||||||
    success = detectTSC(state, *burst, amp, toa, time);
 | 
					 | 
				
			||||||
  else
 | 
					 | 
				
			||||||
    success = detectRACH(state, *burst, amp, toa);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Alert an error and exit */
 | 
					 | 
				
			||||||
  if (success <= 0) {
 | 
					 | 
				
			||||||
    if (success == -SIGERR_CLIP) {
 | 
					 | 
				
			||||||
      LOG(WARNING) << "Clipping detected on received RACH or Normal Burst";
 | 
					 | 
				
			||||||
    } else if (success != SIGERR_NONE) {
 | 
					 | 
				
			||||||
      LOG(WARNING) << "Unhandled RACH or Normal Burst detection error";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    delete radio_burst;
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  timingOffset = toa / mSPSRx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Demodulate and set output info */
 | 
					 | 
				
			||||||
  if (equalize && (type != TSC))
 | 
					 | 
				
			||||||
    equalize = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  bits = demodulate(state, *burst, amp, toa, time.TN(), equalize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete radio_burst;
 | 
					 | 
				
			||||||
  return bits;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Transceiver::reset()
 | 
					void TransceiverState::updateNoiseEstimates(double avg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  for (size_t i = 0; i < mTxPriorityQueues.size(); i++)
 | 
					  /* Update noise levels */
 | 
				
			||||||
    mTxPriorityQueues[i].clear();
 | 
					  mNoises.insert(avg);
 | 
				
			||||||
 | 
					  mNoiseLev = mNoises.avg();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  
 | 
					 | 
				
			||||||
void Transceiver::driveControl(size_t chan)
 | 
					void Transceiver::driveControl(size_t chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int MAX_PACKET_LENGTH = 100;
 | 
					  int MAX_PACKET_LENGTH = 100;
 | 
				
			||||||
@@ -841,9 +736,8 @@ void Transceiver::driveControl(size_t chan)
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  else if (strcmp(command,"NOISELEV")==0) {
 | 
					  else if (strcmp(command,"NOISELEV")==0) {
 | 
				
			||||||
    if (mOn) {
 | 
					    if (mOn) {
 | 
				
			||||||
      float lev = mStates[chan].mNoiseLev;
 | 
					 | 
				
			||||||
      sprintf(response,"RSP NOISELEV 0 %d",
 | 
					      sprintf(response,"RSP NOISELEV 0 %d",
 | 
				
			||||||
              (int) round(20.0 * log10(rxFullScale / lev)));
 | 
					              (int) round(dB2(rxFullScale / mStates[chan].mNoiseLev)));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      sprintf(response,"RSP NOISELEV 1  0");
 | 
					      sprintf(response,"RSP NOISELEV 1  0");
 | 
				
			||||||
@@ -980,20 +874,61 @@ void Transceiver::driveReceiveRadio()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Transceiver::driveReceiveFIFO(size_t chan)
 | 
					void Transceiver::driveReceiveFIFO(size_t chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  radioVector *radio_burst = NULL;
 | 
				
			||||||
 | 
					  signalVector *burst = NULL;
 | 
				
			||||||
  SoftVector *rxBurst = NULL;
 | 
					  SoftVector *rxBurst = NULL;
 | 
				
			||||||
 | 
					  double burst_power; // sqr(amp)
 | 
				
			||||||
  double RSSI; // in dBFS
 | 
					  double RSSI; // in dBFS
 | 
				
			||||||
  double dBm;  // in dBm
 | 
					  double dBm;  // in dBm
 | 
				
			||||||
  double TOA;  // in symbols
 | 
					  double TOA;  // in symbols
 | 
				
			||||||
  int TOAint;  // in 1/256 symbols
 | 
					 | 
				
			||||||
  double noise; // noise level in dBFS
 | 
					  double noise; // noise level in dBFS
 | 
				
			||||||
  GSM::Time burstTime;
 | 
					  GSM::Time burstTime;
 | 
				
			||||||
  bool isRssiValid; // are RSSI, noise and burstTime valid
 | 
					  CorrType burstType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  rxBurst = pullRadioVector(burstTime, RSSI, isRssiValid, TOA, noise, chan);
 | 
					  /* Blocking FIFO read */
 | 
				
			||||||
 | 
					  radio_burst = mReceiveFIFO[chan]->read();
 | 
				
			||||||
 | 
					  if (!radio_burst)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (rxBurst) { 
 | 
					  /* Set time and determine correlation type */
 | 
				
			||||||
 | 
					  burstTime = radio_burst->getTime();
 | 
				
			||||||
 | 
					  burstType = expectedCorrType(burstTime, chan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Debug: dump bursts to disk */
 | 
				
			||||||
 | 
					  /* bits 0-7  - chan 0 timeslots
 | 
				
			||||||
 | 
					   * bits 8-15 - chan 1 timeslots */
 | 
				
			||||||
 | 
					  if (mWriteBurstToDiskMask & ((1<<burstTime.TN()) << (8*chan)))
 | 
				
			||||||
 | 
					    writeToFile(radio_burst, chan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* No processing if the timeslot is off. */
 | 
				
			||||||
 | 
					  if (burstType == OFF) {
 | 
				
			||||||
 | 
					    delete radio_burst;
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Choose a diversity channel to use */
 | 
				
			||||||
 | 
					  burst = chooseDiversityPath(radio_burst, burst_power);
 | 
				
			||||||
 | 
					  delete radio_burst;
 | 
				
			||||||
 | 
					  if (!burst) {
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* We use idle timeslots to calculate noise levels for informational purposes.
 | 
				
			||||||
 | 
					   * Otherwise we ignore them. */
 | 
				
			||||||
 | 
					  if (burstType == IDLE) {
 | 
				
			||||||
 | 
					    mStates[chan].updateNoiseEstimates(burst_power);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Update/calculate burst info */
 | 
				
			||||||
 | 
					  noise = dB2(rxFullScale / mStates[chan].mNoiseLev);
 | 
				
			||||||
 | 
					  RSSI  = dB2(rxFullScale / burst_power);
 | 
				
			||||||
  dBm   = RSSI+rssiOffset;
 | 
					  dBm   = RSSI+rssiOffset;
 | 
				
			||||||
    TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
 | 
					
 | 
				
			||||||
 | 
					  /* Pre-process and demodulate radio vector */
 | 
				
			||||||
 | 
					  rxBurst = demodSignalVector(burst, burstType, TOA);
 | 
				
			||||||
 | 
					  if (!rxBurst)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LOG(DEBUG) << std::fixed << std::right
 | 
					  LOG(DEBUG) << std::fixed << std::right
 | 
				
			||||||
    << " time: "   << burstTime
 | 
					    << " time: "   << burstTime
 | 
				
			||||||
@@ -1003,6 +938,18 @@ void Transceiver::driveReceiveFIFO(size_t chan)
 | 
				
			|||||||
    << " bits: "   << *rxBurst;
 | 
					    << " bits: "   << *rxBurst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  char burstString[gSlotLen+10];
 | 
					  char burstString[gSlotLen+10];
 | 
				
			||||||
 | 
					  formatDemodPacket(burstTime, dBm, TOA, rxBurst, burstString);
 | 
				
			||||||
 | 
					  delete rxBurst;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mDataSockets[chan]->write(burstString,gSlotLen+10);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Transceiver::formatDemodPacket(GSM::Time burstTime, double dBm, double TOA,
 | 
				
			||||||
 | 
					                                    SoftVector *rxBurst, char *burstString)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  int TOAint;  // in 1/256 symbols
 | 
				
			||||||
 | 
					  TOAint = (int) (TOA * 256.0 + 0.5); // round to closest integer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  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;
 | 
				
			||||||
@@ -1015,10 +962,6 @@ void Transceiver::driveReceiveFIFO(size_t chan)
 | 
				
			|||||||
    burstString[8+i] =(char) round((*burstItr++)*255.0);
 | 
					    burstString[8+i] =(char) round((*burstItr++)*255.0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  burstString[gSlotLen+9] = '\0';
 | 
					  burstString[gSlotLen+9] = '\0';
 | 
				
			||||||
    delete rxBurst;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    mDataSockets[chan]->write(burstString,gSlotLen+10);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Transceiver::driveTxFIFO()
 | 
					void Transceiver::driveTxFIFO()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,29 +55,15 @@ struct TransceiverState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  /* Initialize a multiframe slot in the filler table */
 | 
					  /* Initialize a multiframe slot in the filler table */
 | 
				
			||||||
  bool init(int filler, size_t sps, float scale, size_t rtsc);
 | 
					  bool init(int filler, size_t sps, float scale, size_t rtsc);
 | 
				
			||||||
 | 
					  void updateNoiseEstimates(double avg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int chanType[8];
 | 
					  int chanType[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Last timestamp of each timeslot's channel estimate */
 | 
					 | 
				
			||||||
  GSM::Time chanEstimateTime[8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* The filler table */
 | 
					  /* The filler table */
 | 
				
			||||||
  signalVector *fillerTable[102][8];
 | 
					  signalVector *fillerTable[102][8];
 | 
				
			||||||
  int fillerModulus[8];
 | 
					  int fillerModulus[8];
 | 
				
			||||||
  bool mRetrans;
 | 
					  bool mRetrans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Most recent channel estimate of all timeslots */
 | 
					 | 
				
			||||||
  signalVector *chanResponse[8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Most recent DFE feedback filter of all timeslots */
 | 
					 | 
				
			||||||
  signalVector *DFEForward[8];
 | 
					 | 
				
			||||||
  signalVector *DFEFeedback[8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Most recent SNR, timing, and channel amplitude estimates */
 | 
					 | 
				
			||||||
  float SNRestimate[8];
 | 
					 | 
				
			||||||
  float chanRespOffset[8];
 | 
					 | 
				
			||||||
  complex chanRespAmplitude[8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /* Received noise energy levels */
 | 
					  /* Received noise energy levels */
 | 
				
			||||||
  float mNoiseLev;
 | 
					  float mNoiseLev;
 | 
				
			||||||
  noiseVector mNoises;
 | 
					  noiseVector mNoises;
 | 
				
			||||||
@@ -195,9 +181,15 @@ 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, double &RSSI, bool &isRssiValid,
 | 
					  SoftVector *demodSignalVector(signalVector *burst,
 | 
				
			||||||
                              double &timingOffset, double &noise,
 | 
					                                CorrType type,
 | 
				
			||||||
                              size_t chan = 0);
 | 
					                                double &timingOffset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** choose the channel to use */
 | 
				
			||||||
 | 
					  signalVector *chooseDiversityPath(radioVector *radio_burst, double &avg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** update noise estimate */
 | 
				
			||||||
 | 
					  double updateNoiseEstimates(TransceiverState *state, double avg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** 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);
 | 
				
			||||||
@@ -209,19 +201,12 @@ private:
 | 
				
			|||||||
  void writeClockInterface(void);
 | 
					  void writeClockInterface(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Detect RACH bursts */
 | 
					  /** Detect RACH bursts */
 | 
				
			||||||
  int detectRACH(TransceiverState *state,
 | 
					  int detectRACH(signalVector &burst,
 | 
				
			||||||
                 signalVector &burst,
 | 
					 | 
				
			||||||
                 complex &, float &toa);
 | 
					                 complex &, float &toa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** Detect normal bursts */
 | 
					  /** Detect normal bursts */
 | 
				
			||||||
  int detectTSC(TransceiverState *state,
 | 
					  int detectTSC(signalVector &burst,
 | 
				
			||||||
                signalVector &burst,
 | 
					                complex &, float &toa);
 | 
				
			||||||
                complex &, float &toa, GSM::Time &time);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  /** Demodulat burst and output soft bits */
 | 
					 | 
				
			||||||
  SoftVector *demodulate(TransceiverState *state,
 | 
					 | 
				
			||||||
                         signalVector &burst, complex amp,
 | 
					 | 
				
			||||||
                         float toa, size_t tn, bool equalize);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int mSPSTx;                          ///< number of samples per Tx symbol
 | 
					  int mSPSTx;                          ///< number of samples per Tx symbol
 | 
				
			||||||
  int mSPSRx;                          ///< number of samples per Rx symbol
 | 
					  int mSPSRx;                          ///< number of samples per Rx symbol
 | 
				
			||||||
@@ -251,6 +236,10 @@ protected:
 | 
				
			|||||||
  /** drive demodulation of GSM bursts */
 | 
					  /** drive demodulation of GSM bursts */
 | 
				
			||||||
  void driveReceiveFIFO(size_t chan);
 | 
					  void driveReceiveFIFO(size_t chan);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** format a packet of soft-bits to be sent over the network */
 | 
				
			||||||
 | 
					  void formatDemodPacket(GSM::Time burstTime, double dBm, double TOA,
 | 
				
			||||||
 | 
					                         SoftVector *rxBurst, char *burstString);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /** drive transmission of GSM bursts */
 | 
					  /** drive transmission of GSM bursts */
 | 
				
			||||||
  void driveTxFIFO();
 | 
					  void driveTxFIFO();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -147,64 +147,8 @@ void sigProcLibDestroy()
 | 
				
			|||||||
  GSMPulse1 = NULL;
 | 
					  GSMPulse1 = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// dB relative to 1.0.
 | 
					double dB2(double x) {
 | 
				
			||||||
// if > 1.0, then return 0 dB
 | 
					  return 20.0 * log10(x);
 | 
				
			||||||
float dB(float x) {
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  float arg = 1.0F;
 | 
					 | 
				
			||||||
  float dB = 0.0F;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  if (x >= 1.0F) return 0.0F;
 | 
					 | 
				
			||||||
  if (x <= 0.0F) return -200.0F;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  float prevArg = arg;
 | 
					 | 
				
			||||||
  float prevdB = dB;
 | 
					 | 
				
			||||||
  float stepSize = 16.0F;
 | 
					 | 
				
			||||||
  float dBstepSize = 12.0F;
 | 
					 | 
				
			||||||
  while (stepSize > 1.0F) {
 | 
					 | 
				
			||||||
    do {
 | 
					 | 
				
			||||||
      prevArg = arg;
 | 
					 | 
				
			||||||
      prevdB = dB;
 | 
					 | 
				
			||||||
      arg /= stepSize;
 | 
					 | 
				
			||||||
      dB -= dBstepSize;
 | 
					 | 
				
			||||||
    } while (arg > x);
 | 
					 | 
				
			||||||
    arg = prevArg;
 | 
					 | 
				
			||||||
    dB = prevdB;
 | 
					 | 
				
			||||||
    stepSize *= 0.5F;
 | 
					 | 
				
			||||||
    dBstepSize -= 3.0F;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 return ((arg-x)*(dB-3.0F) + (x-arg*0.5F)*dB)/(arg - arg*0.5F);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// 10^(-dB/10), inverse of dB func.
 | 
					 | 
				
			||||||
float dBinv(float x) {
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  float arg = 1.0F;
 | 
					 | 
				
			||||||
  float dB = 0.0F;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  if (x >= 0.0F) return 1.0F;
 | 
					 | 
				
			||||||
  if (x <= -200.0F) return 0.0F;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  float prevArg = arg;
 | 
					 | 
				
			||||||
  float prevdB = dB;
 | 
					 | 
				
			||||||
  float stepSize = 16.0F;
 | 
					 | 
				
			||||||
  float dBstepSize = 12.0F;
 | 
					 | 
				
			||||||
  while (stepSize > 1.0F) {
 | 
					 | 
				
			||||||
    do {
 | 
					 | 
				
			||||||
      prevArg = arg;
 | 
					 | 
				
			||||||
      prevdB = dB;
 | 
					 | 
				
			||||||
      arg /= stepSize;
 | 
					 | 
				
			||||||
      dB -= dBstepSize;
 | 
					 | 
				
			||||||
    } while (dB > x);
 | 
					 | 
				
			||||||
    arg = prevArg;
 | 
					 | 
				
			||||||
    dB = prevdB;
 | 
					 | 
				
			||||||
    stepSize *= 0.5F;
 | 
					 | 
				
			||||||
    dBstepSize -= 3.0F;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return ((dB-x)*(arg*0.5F)+(x-(dB-3.0F))*(arg))/3.0F;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float vectorNorm2(const signalVector &x) 
 | 
					float vectorNorm2(const signalVector &x) 
 | 
				
			||||||
@@ -1478,8 +1422,7 @@ int detectRACHBurst(signalVector &rxBurst,
 | 
				
			|||||||
 *   tail: Search 4 symbols + maximum expected delay
 | 
					 *   tail: Search 4 symbols + maximum expected delay
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
					int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
				
			||||||
                        int sps, complex &, float &toa, unsigned max_toa,
 | 
					                        int sps, complex &, float &toa, unsigned max_toa)
 | 
				
			||||||
                        bool chan_req, signalVector **chan, float *chan_offset)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int rc, target, head, tail;
 | 
					  int rc, target, head, tail;
 | 
				
			||||||
  CorrelationSequence *sync;
 | 
					  CorrelationSequence *sync;
 | 
				
			||||||
@@ -1495,14 +1438,6 @@ int analyzeTrafficBurst(signalVector &rxBurst, unsigned tsc, float thresh,
 | 
				
			|||||||
  rc = detectGeneralBurst(rxBurst, thresh, sps, amp, toa,
 | 
					  rc = detectGeneralBurst(rxBurst, thresh, sps, amp, toa,
 | 
				
			||||||
                          target, head, tail, sync);
 | 
					                          target, head, tail, sync);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Equalization not currently supported */
 | 
					 | 
				
			||||||
  if (rc > 0 && chan_req) {
 | 
					 | 
				
			||||||
    *chan = new signalVector(6 * sps);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (chan_offset)
 | 
					 | 
				
			||||||
      *chan_offset = 0.0;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return rc;
 | 
					  return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1559,166 +1494,6 @@ SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
 | 
				
			|||||||
  return bits;
 | 
					  return bits;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Assumes symbol-spaced sampling!!!
 | 
					 | 
				
			||||||
// Based upon paper by Al-Dhahir and Cioffi
 | 
					 | 
				
			||||||
bool designDFE(signalVector &channelResponse,
 | 
					 | 
				
			||||||
	       float SNRestimate,
 | 
					 | 
				
			||||||
	       int Nf,
 | 
					 | 
				
			||||||
	       signalVector **feedForwardFilter,
 | 
					 | 
				
			||||||
	       signalVector **feedbackFilter)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  signalVector G0(Nf);
 | 
					 | 
				
			||||||
  signalVector G1(Nf);
 | 
					 | 
				
			||||||
  signalVector::iterator G0ptr = G0.begin();
 | 
					 | 
				
			||||||
  signalVector::iterator G1ptr = G1.begin();
 | 
					 | 
				
			||||||
  signalVector::iterator chanPtr = channelResponse.begin();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  int nu = channelResponse.size()-1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  *G0ptr = 1.0/sqrtf(SNRestimate);
 | 
					 | 
				
			||||||
  for(int j = 0; j <= nu; j++) {
 | 
					 | 
				
			||||||
    *G1ptr = chanPtr->conj();
 | 
					 | 
				
			||||||
    G1ptr++; chanPtr++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector *L[Nf];
 | 
					 | 
				
			||||||
  signalVector::iterator Lptr;
 | 
					 | 
				
			||||||
  float d = 1.0;
 | 
					 | 
				
			||||||
  for(int i = 0; i < Nf; i++) {
 | 
					 | 
				
			||||||
    d = G0.begin()->norm2() + G1.begin()->norm2();
 | 
					 | 
				
			||||||
    L[i] = new signalVector(Nf+nu);
 | 
					 | 
				
			||||||
    Lptr = L[i]->begin()+i;
 | 
					 | 
				
			||||||
    G0ptr = G0.begin(); G1ptr = G1.begin();
 | 
					 | 
				
			||||||
    while ((G0ptr < G0.end()) &&  (Lptr < L[i]->end())) {
 | 
					 | 
				
			||||||
      *Lptr = (*G0ptr*(G0.begin()->conj()) + *G1ptr*(G1.begin()->conj()) )/d;
 | 
					 | 
				
			||||||
      Lptr++;
 | 
					 | 
				
			||||||
      G0ptr++;
 | 
					 | 
				
			||||||
      G1ptr++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    complex k = (*G1.begin())/(*G0.begin());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (i != Nf-1) {
 | 
					 | 
				
			||||||
      signalVector G0new = G1;
 | 
					 | 
				
			||||||
      scaleVector(G0new,k.conj());
 | 
					 | 
				
			||||||
      addVector(G0new,G0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      signalVector G1new = G0;
 | 
					 | 
				
			||||||
      scaleVector(G1new,k*(-1.0));
 | 
					 | 
				
			||||||
      addVector(G1new,G1);
 | 
					 | 
				
			||||||
      delayVector(&G1new, &G1new, -1.0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      scaleVector(G0new,1.0/sqrtf(1.0+k.norm2()));
 | 
					 | 
				
			||||||
      scaleVector(G1new,1.0/sqrtf(1.0+k.norm2()));
 | 
					 | 
				
			||||||
      G0 = G0new;
 | 
					 | 
				
			||||||
      G1 = G1new;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  *feedbackFilter = new signalVector(nu);
 | 
					 | 
				
			||||||
  L[Nf-1]->segmentCopyTo(**feedbackFilter,Nf,nu);
 | 
					 | 
				
			||||||
  scaleVector(**feedbackFilter,(complex) -1.0);
 | 
					 | 
				
			||||||
  conjugateVector(**feedbackFilter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector v(Nf);
 | 
					 | 
				
			||||||
  signalVector::iterator vStart = v.begin();
 | 
					 | 
				
			||||||
  signalVector::iterator vPtr;
 | 
					 | 
				
			||||||
  *(vStart+Nf-1) = (complex) 1.0;
 | 
					 | 
				
			||||||
  for(int k = Nf-2; k >= 0; k--) {
 | 
					 | 
				
			||||||
    Lptr = L[k]->begin()+k+1;
 | 
					 | 
				
			||||||
    vPtr = vStart + k+1;
 | 
					 | 
				
			||||||
    complex v_k = 0.0;
 | 
					 | 
				
			||||||
    for (int j = k+1; j < Nf; j++) {
 | 
					 | 
				
			||||||
      v_k -= (*vPtr)*(*Lptr);
 | 
					 | 
				
			||||||
      vPtr++; Lptr++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
     *(vStart + k) = v_k;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  *feedForwardFilter = new signalVector(Nf);
 | 
					 | 
				
			||||||
  signalVector::iterator w = (*feedForwardFilter)->end();
 | 
					 | 
				
			||||||
  for (int i = 0; i < Nf; i++) {
 | 
					 | 
				
			||||||
    delete L[i];
 | 
					 | 
				
			||||||
    complex w_i = 0.0;
 | 
					 | 
				
			||||||
    int endPt = ( nu < (Nf-1-i) ) ? nu : (Nf-1-i);
 | 
					 | 
				
			||||||
    vPtr = vStart+i;
 | 
					 | 
				
			||||||
    chanPtr = channelResponse.begin();
 | 
					 | 
				
			||||||
    for (int k = 0; k < endPt+1; k++) {
 | 
					 | 
				
			||||||
      w_i += (*vPtr)*(chanPtr->conj());
 | 
					 | 
				
			||||||
      vPtr++; chanPtr++;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    *--w = w_i/d;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return true;
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Assumes symbol-rate sampling!!!!
 | 
					 | 
				
			||||||
SoftVector *equalizeBurst(signalVector &rxBurst,
 | 
					 | 
				
			||||||
		       float TOA,
 | 
					 | 
				
			||||||
		       int sps,
 | 
					 | 
				
			||||||
		       signalVector &w, // feedforward filter
 | 
					 | 
				
			||||||
		       signalVector &b) // feedback filter
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  signalVector *postForwardFull;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (!delayVector(&rxBurst, &rxBurst, -TOA))
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  postForwardFull = convolve(&rxBurst, &w, NULL,
 | 
					 | 
				
			||||||
                             CUSTOM, 0, rxBurst.size() + w.size() - 1);
 | 
					 | 
				
			||||||
  if (!postForwardFull)
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector* postForward = new signalVector(rxBurst.size());
 | 
					 | 
				
			||||||
  postForwardFull->segmentCopyTo(*postForward,w.size()-1,rxBurst.size());
 | 
					 | 
				
			||||||
  delete postForwardFull;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector::iterator dPtr = postForward->begin();
 | 
					 | 
				
			||||||
  signalVector::iterator dBackPtr;
 | 
					 | 
				
			||||||
  signalVector::iterator rotPtr = GMSKRotationN->begin();
 | 
					 | 
				
			||||||
  signalVector::iterator revRotPtr = GMSKReverseRotationN->begin();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  signalVector *DFEoutput = new signalVector(postForward->size());
 | 
					 | 
				
			||||||
  signalVector::iterator DFEItr = DFEoutput->begin();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // NOTE: can insert the midamble and/or use midamble to estimate BER
 | 
					 | 
				
			||||||
  for (; dPtr < postForward->end(); dPtr++) {
 | 
					 | 
				
			||||||
    dBackPtr = dPtr-1;
 | 
					 | 
				
			||||||
    signalVector::iterator bPtr = b.begin();
 | 
					 | 
				
			||||||
    while ( (bPtr < b.end()) && (dBackPtr >= postForward->begin()) ) {
 | 
					 | 
				
			||||||
      *dPtr = *dPtr + (*bPtr)*(*dBackPtr);
 | 
					 | 
				
			||||||
      bPtr++;
 | 
					 | 
				
			||||||
      dBackPtr--;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    *dPtr = *dPtr * (*revRotPtr);
 | 
					 | 
				
			||||||
    *DFEItr = *dPtr;
 | 
					 | 
				
			||||||
    // make decision on symbol
 | 
					 | 
				
			||||||
    *dPtr = (dPtr->real() > 0.0) ? 1.0 : -1.0;
 | 
					 | 
				
			||||||
    //*DFEItr = *dPtr;
 | 
					 | 
				
			||||||
    *dPtr = *dPtr * (*rotPtr);
 | 
					 | 
				
			||||||
    DFEItr++;
 | 
					 | 
				
			||||||
    rotPtr++;
 | 
					 | 
				
			||||||
    revRotPtr++;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  vectorSlicer(DFEoutput);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  SoftVector *burstBits = new SoftVector(postForward->size());
 | 
					 | 
				
			||||||
  SoftVector::iterator burstItr = burstBits->begin();
 | 
					 | 
				
			||||||
  DFEItr = DFEoutput->begin();
 | 
					 | 
				
			||||||
  for (; DFEItr < DFEoutput->end(); DFEItr++) 
 | 
					 | 
				
			||||||
    *burstItr++ = DFEItr->real();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete postForward;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  delete DFEoutput;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return burstBits;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool sigProcLibSetup(int sps)
 | 
					bool sigProcLibSetup(int sps)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if ((sps != 1) && (sps != 4))
 | 
					  if ((sps != 1) && (sps != 4))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,8 @@ enum signalError {
 | 
				
			|||||||
  SIGERR_INTERNAL,
 | 
					  SIGERR_INTERNAL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Convert a linear number to a dB value */
 | 
					/** Convert a power value to a dB value */
 | 
				
			||||||
float dB(float x);
 | 
					double dB2(double x);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Convert a dB value into a linear value */
 | 
					/** Convert a dB value into a linear value */
 | 
				
			||||||
float dBinv(float x);
 | 
					float dBinv(float x);
 | 
				
			||||||
@@ -204,9 +204,6 @@ int detectRACHBurst(signalVector &rxBurst,
 | 
				
			|||||||
        @param amplitude The estimated amplitude of received TSC burst.
 | 
					        @param amplitude The estimated amplitude of received TSC burst.
 | 
				
			||||||
        @param TOA The estimate time-of-arrival of received TSC burst.
 | 
					        @param TOA The estimate time-of-arrival of received TSC burst.
 | 
				
			||||||
        @param maxTOA The maximum expected time-of-arrival
 | 
					        @param maxTOA The maximum expected time-of-arrival
 | 
				
			||||||
        @param requestChannel Set to true if channel estimation is desired.
 | 
					 | 
				
			||||||
        @param channelResponse The estimated channel.
 | 
					 | 
				
			||||||
        @param channelResponseOffset The time offset b/w the first sample of the channel response and the reported TOA.
 | 
					 | 
				
			||||||
        @return positive if threshold value is reached, negative on error, zero otherwise
 | 
					        @return positive if threshold value is reached, negative on error, zero otherwise
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
int analyzeTrafficBurst(signalVector &rxBurst,
 | 
					int analyzeTrafficBurst(signalVector &rxBurst,
 | 
				
			||||||
@@ -215,10 +212,7 @@ int analyzeTrafficBurst(signalVector &rxBurst,
 | 
				
			|||||||
                        int sps,
 | 
					                        int sps,
 | 
				
			||||||
                        complex &litude,
 | 
					                        complex &litude,
 | 
				
			||||||
                        float &TOA,
 | 
					                        float &TOA,
 | 
				
			||||||
                        unsigned maxTOA,
 | 
					                        unsigned maxTOA);
 | 
				
			||||||
                        bool requestChannel = false,
 | 
					 | 
				
			||||||
                        signalVector** channelResponse = NULL,
 | 
					 | 
				
			||||||
                        float *channelResponseOffset = NULL);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
	Decimate a vector.
 | 
						Decimate a vector.
 | 
				
			||||||
@@ -240,34 +234,4 @@ signalVector *decimateVector(signalVector &wVector, size_t factor);
 | 
				
			|||||||
SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
 | 
					SoftVector *demodulateBurst(signalVector &rxBurst, int sps,
 | 
				
			||||||
                            complex channel, float TOA);
 | 
					                            complex channel, float TOA);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
	Design the necessary filters for a decision-feedback equalizer.
 | 
					 | 
				
			||||||
	@param channelResponse The multipath channel that we're mitigating.
 | 
					 | 
				
			||||||
	@param SNRestimate The signal-to-noise estimate of the channel, a linear value
 | 
					 | 
				
			||||||
	@param Nf The number of taps in the feedforward filter.
 | 
					 | 
				
			||||||
	@param feedForwardFilter The designed feed forward filter.
 | 
					 | 
				
			||||||
	@param feedbackFilter The designed feedback filter.
 | 
					 | 
				
			||||||
	@return True if DFE can be designed.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
bool designDFE(signalVector &channelResponse,
 | 
					 | 
				
			||||||
	       float SNRestimate,
 | 
					 | 
				
			||||||
	       int Nf,
 | 
					 | 
				
			||||||
	       signalVector **feedForwardFilter,
 | 
					 | 
				
			||||||
	       signalVector **feedbackFilter);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
	Equalize/demodulate a received burst via a decision-feedback equalizer.
 | 
					 | 
				
			||||||
	@param rxBurst The received burst to be demodulated.
 | 
					 | 
				
			||||||
	@param TOA The time-of-arrival of the received burst.
 | 
					 | 
				
			||||||
	@param sps The number of samples per GSM symbol.
 | 
					 | 
				
			||||||
	@param w The feed forward filter of the DFE.
 | 
					 | 
				
			||||||
	@param b The feedback filter of the DFE.
 | 
					 | 
				
			||||||
	@return The demodulated bit sequence.
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
SoftVector *equalizeBurst(signalVector &rxBurst,
 | 
					 | 
				
			||||||
		       float TOA,
 | 
					 | 
				
			||||||
		       int sps,
 | 
					 | 
				
			||||||
		       signalVector &w, 
 | 
					 | 
				
			||||||
		       signalVector &b);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif /* SIGPROCLIB_H */
 | 
					#endif /* SIGPROCLIB_H */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user