mirror of
				https://github.com/RangeNetworks/openbts.git
				synced 2025-11-03 21:33:15 +00:00 
			
		
		
		
	Adding in the missing Transceiver52M directory
git-svn-id: http://wush.net/svn/range/software/public/openbts/trunk@2307 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
		
							
								
								
									
										315
									
								
								Transceiver52M/radioInterface.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								Transceiver52M/radioInterface.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,315 @@
 | 
			
		||||
/*
 | 
			
		||||
* Copyright 2008, 2009 Free Software Foundation, Inc.
 | 
			
		||||
*
 | 
			
		||||
* This software is distributed under the terms of the GNU Affero Public License.
 | 
			
		||||
* See the COPYING file in the main directory for details.
 | 
			
		||||
*
 | 
			
		||||
* This use of this software may be subject to additional restrictions.
 | 
			
		||||
* See the LEGAL file in the main directory for details.
 | 
			
		||||
 | 
			
		||||
	This program is free software: you can redistribute it and/or modify
 | 
			
		||||
	it under the terms of the GNU Affero General Public License as published by
 | 
			
		||||
	the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
	(at your option) any later version.
 | 
			
		||||
 | 
			
		||||
	This program is distributed in the hope that it will be useful,
 | 
			
		||||
	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
	GNU Affero General Public License for more details.
 | 
			
		||||
 | 
			
		||||
	You should have received a copy of the GNU Affero General Public License
 | 
			
		||||
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
//#define NDEBUG
 | 
			
		||||
#include "radioInterface.h"
 | 
			
		||||
#include <Logger.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
GSM::Time VectorQueue::nextTime() const
 | 
			
		||||
{
 | 
			
		||||
  GSM::Time retVal;
 | 
			
		||||
  ScopedLock lock(mLock);
 | 
			
		||||
  while (mQ.size()==0) mWriteSignal.wait(mLock);
 | 
			
		||||
  return mQ.top()->time();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
radioVector* VectorQueue::getStaleBurst(const GSM::Time& targTime)
 | 
			
		||||
{
 | 
			
		||||
  ScopedLock lock(mLock);
 | 
			
		||||
  if ((mQ.size()==0)) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  if (mQ.top()->time() < targTime) {
 | 
			
		||||
    radioVector* retVal = mQ.top();
 | 
			
		||||
    mQ.pop();
 | 
			
		||||
    return retVal;
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
radioVector* VectorQueue::getCurrentBurst(const GSM::Time& targTime)
 | 
			
		||||
{
 | 
			
		||||
  ScopedLock lock(mLock);
 | 
			
		||||
  if ((mQ.size()==0)) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
  if (mQ.top()->time() == targTime) {
 | 
			
		||||
    radioVector* retVal = mQ.top();
 | 
			
		||||
    mQ.pop();
 | 
			
		||||
    return retVal;
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RadioInterface::RadioInterface(RadioDevice *wRadio,
 | 
			
		||||
                               int wReceiveOffset,
 | 
			
		||||
			       int wRadioOversampling,
 | 
			
		||||
			       int wTransceiverOversampling,
 | 
			
		||||
			       GSM::Time wStartTime)
 | 
			
		||||
 | 
			
		||||
{
 | 
			
		||||
  underrun = false;
 | 
			
		||||
 
 | 
			
		||||
  sendCursor = 0; 
 | 
			
		||||
  rcvCursor = 0;
 | 
			
		||||
  mOn = false;
 | 
			
		||||
  
 | 
			
		||||
  mRadio = wRadio;
 | 
			
		||||
  receiveOffset = wReceiveOffset;
 | 
			
		||||
  samplesPerSymbol = wRadioOversampling;
 | 
			
		||||
  mClock.set(wStartTime);
 | 
			
		||||
  powerScaling = 1.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RadioInterface::~RadioInterface(void) {
 | 
			
		||||
  if (rcvBuffer!=NULL) delete rcvBuffer;
 | 
			
		||||
  //mReceiveFIFO.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double RadioInterface::fullScaleInputValue(void) {
 | 
			
		||||
  return mRadio->fullScaleInputValue();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
double RadioInterface::fullScaleOutputValue(void) {
 | 
			
		||||
  return mRadio->fullScaleOutputValue();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void RadioInterface::setPowerAttenuation(double dBAtten)
 | 
			
		||||
{
 | 
			
		||||
  float HWdBAtten = mRadio->setTxGain(-dBAtten);
 | 
			
		||||
  dBAtten -= (-HWdBAtten);
 | 
			
		||||
  float linearAtten = powf(10.0F,0.1F*dBAtten);
 | 
			
		||||
  if (linearAtten < 1.0)
 | 
			
		||||
    powerScaling = 1.0;
 | 
			
		||||
  else
 | 
			
		||||
    powerScaling = 1.0/sqrt(linearAtten);
 | 
			
		||||
  LOG(INFO) << "setting HW gain to " << HWdBAtten << " and power scaling to " << powerScaling;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
short *RadioInterface::radioifyVector(signalVector &wVector, short *retVector, double scale, bool zeroOut) 
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  signalVector::iterator itr = wVector.begin();
 | 
			
		||||
  short *shortItr = retVector;
 | 
			
		||||
  if (zeroOut) {
 | 
			
		||||
    while (itr < wVector.end()) {
 | 
			
		||||
      *shortItr++ = 0;
 | 
			
		||||
      *shortItr++ = 0;
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if (scale != 1.0) { 
 | 
			
		||||
    while (itr < wVector.end()) {
 | 
			
		||||
      *shortItr++ = (short) (itr->real()*scale);
 | 
			
		||||
      *shortItr++ = (short) (itr->imag()*scale);
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else {
 | 
			
		||||
    while (itr < wVector.end()) {
 | 
			
		||||
      *shortItr++ = (short) (itr->real());
 | 
			
		||||
      *shortItr++ = (short) (itr->imag());
 | 
			
		||||
      itr++;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return retVector;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RadioInterface::unRadioifyVector(short *shortVector, signalVector& newVector)
 | 
			
		||||
{
 | 
			
		||||
  
 | 
			
		||||
  signalVector::iterator itr = newVector.begin();
 | 
			
		||||
  short *shortItr = shortVector;
 | 
			
		||||
  while (itr < newVector.end()) {
 | 
			
		||||
    *itr++ = Complex<float>(*shortItr,*(shortItr+1));
 | 
			
		||||
    //LOG(DEBUG) << (*(itr-1));
 | 
			
		||||
    shortItr += 2;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool started = false;
 | 
			
		||||
 | 
			
		||||
void RadioInterface::pushBuffer(void) {
 | 
			
		||||
 | 
			
		||||
  if (sendCursor < 2*INCHUNK*samplesPerSymbol) return;
 | 
			
		||||
 | 
			
		||||
  // send resampleVector
 | 
			
		||||
  int samplesWritten = mRadio->writeSamples(sendBuffer,
 | 
			
		||||
					  INCHUNK*samplesPerSymbol,
 | 
			
		||||
					  &underrun,
 | 
			
		||||
					  writeTimestamp); 
 | 
			
		||||
  //LOG(DEBUG) << "writeTimestamp: " << writeTimestamp << ", samplesWritten: " << samplesWritten;
 | 
			
		||||
   
 | 
			
		||||
  writeTimestamp += (TIMESTAMP) samplesWritten;
 | 
			
		||||
 | 
			
		||||
  if (sendCursor > 2*samplesWritten) 
 | 
			
		||||
    memcpy(sendBuffer,sendBuffer+samplesWritten*2,sizeof(short)*2*(sendCursor-2*samplesWritten));
 | 
			
		||||
  sendCursor = sendCursor - 2*samplesWritten;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void RadioInterface::pullBuffer(void)
 | 
			
		||||
{
 | 
			
		||||
   
 | 
			
		||||
  bool localUnderrun;
 | 
			
		||||
 | 
			
		||||
   // receive receiveVector
 | 
			
		||||
  short* shortVector = rcvBuffer+rcvCursor;  
 | 
			
		||||
  //LOG(DEBUG) << "Reading USRP samples at timestamp " << readTimestamp;
 | 
			
		||||
  int samplesRead = mRadio->readSamples(shortVector,OUTCHUNK*samplesPerSymbol,&overrun,readTimestamp,&localUnderrun);
 | 
			
		||||
  underrun |= localUnderrun;
 | 
			
		||||
  readTimestamp += (TIMESTAMP) samplesRead;
 | 
			
		||||
  while (samplesRead < OUTCHUNK*samplesPerSymbol) {
 | 
			
		||||
    int oldSamplesRead = samplesRead;
 | 
			
		||||
    samplesRead += mRadio->readSamples(shortVector+2*samplesRead,
 | 
			
		||||
				     OUTCHUNK*samplesPerSymbol-samplesRead,
 | 
			
		||||
				     &overrun,
 | 
			
		||||
				     readTimestamp,
 | 
			
		||||
				     &localUnderrun);
 | 
			
		||||
    underrun |= localUnderrun;
 | 
			
		||||
    readTimestamp += (TIMESTAMP) (samplesRead - oldSamplesRead);
 | 
			
		||||
  }
 | 
			
		||||
  //LOG(DEBUG) << "samplesRead " << samplesRead;
 | 
			
		||||
 | 
			
		||||
  rcvCursor += samplesRead*2;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RadioInterface::tuneTx(double freq)
 | 
			
		||||
{
 | 
			
		||||
  return mRadio->setTxFreq(freq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool RadioInterface::tuneRx(double freq)
 | 
			
		||||
{
 | 
			
		||||
  return mRadio->setRxFreq(freq);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void RadioInterface::start()
 | 
			
		||||
{
 | 
			
		||||
  LOG(INFO) << "starting radio interface...";
 | 
			
		||||
  mAlignRadioServiceLoopThread.start((void * (*)(void*))AlignRadioServiceLoopAdapter,
 | 
			
		||||
                                     (void*)this);
 | 
			
		||||
  writeTimestamp = mRadio->initialWriteTimestamp();
 | 
			
		||||
  readTimestamp = mRadio->initialReadTimestamp();
 | 
			
		||||
  mRadio->start(); 
 | 
			
		||||
  LOG(DEBUG) << "Radio started";
 | 
			
		||||
  mRadio->updateAlignment(writeTimestamp-10000); 
 | 
			
		||||
  mRadio->updateAlignment(writeTimestamp-10000);
 | 
			
		||||
 | 
			
		||||
  sendBuffer = new short[2*2*INCHUNK*samplesPerSymbol];
 | 
			
		||||
  rcvBuffer = new short[2*2*OUTCHUNK*samplesPerSymbol];
 | 
			
		||||
 
 | 
			
		||||
  mOn = true;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *AlignRadioServiceLoopAdapter(RadioInterface *radioInterface)
 | 
			
		||||
{
 | 
			
		||||
  while (1) {
 | 
			
		||||
    radioInterface->alignRadio();
 | 
			
		||||
    pthread_testcancel();
 | 
			
		||||
  }
 | 
			
		||||
  return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RadioInterface::alignRadio() {
 | 
			
		||||
  sleep(60);
 | 
			
		||||
  mRadio->updateAlignment(writeTimestamp+ (TIMESTAMP) 10000);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RadioInterface::driveTransmitRadio(signalVector &radioBurst, bool zeroBurst) {
 | 
			
		||||
 | 
			
		||||
  if (!mOn) return;
 | 
			
		||||
 | 
			
		||||
  radioifyVector(radioBurst, sendBuffer+sendCursor, powerScaling, zeroBurst);
 | 
			
		||||
 | 
			
		||||
  sendCursor += (radioBurst.size()*2);
 | 
			
		||||
 | 
			
		||||
  pushBuffer();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RadioInterface::driveReceiveRadio() {
 | 
			
		||||
 | 
			
		||||
  if (!mOn) return;
 | 
			
		||||
 | 
			
		||||
  if (mReceiveFIFO.size() > 8) return;
 | 
			
		||||
 | 
			
		||||
  pullBuffer();
 | 
			
		||||
 | 
			
		||||
  GSM::Time rcvClock = mClock.get();
 | 
			
		||||
  rcvClock.decTN(receiveOffset);
 | 
			
		||||
  unsigned tN = rcvClock.TN();
 | 
			
		||||
  int rcvSz = rcvCursor/2;
 | 
			
		||||
  int readSz = 0;
 | 
			
		||||
  const int symbolsPerSlot = gSlotLen + 8;
 | 
			
		||||
 | 
			
		||||
  // while there's enough data in receive buffer, form received 
 | 
			
		||||
  //    GSM bursts and pass up to Transceiver
 | 
			
		||||
  // Using the 157-156-156-156 symbols per timeslot format.
 | 
			
		||||
  while (rcvSz > (symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol) {
 | 
			
		||||
    signalVector rxVector((symbolsPerSlot + (tN % 4 == 0))*samplesPerSymbol);
 | 
			
		||||
    unRadioifyVector(rcvBuffer+readSz*2,rxVector);
 | 
			
		||||
    GSM::Time tmpTime = rcvClock;
 | 
			
		||||
    if (rcvClock.FN() >= 0) {
 | 
			
		||||
      //LOG(DEBUG) << "FN: " << rcvClock.FN();
 | 
			
		||||
      radioVector *rxBurst = NULL;
 | 
			
		||||
      if (!loadTest)
 | 
			
		||||
        rxBurst = new radioVector(rxVector,tmpTime);
 | 
			
		||||
      else {
 | 
			
		||||
	if (tN % 4 == 0)
 | 
			
		||||
	  rxBurst = new radioVector(*finalVec9,tmpTime);
 | 
			
		||||
        else
 | 
			
		||||
          rxBurst = new radioVector(*finalVec,tmpTime); 
 | 
			
		||||
      }
 | 
			
		||||
      mReceiveFIFO.put(rxBurst); 
 | 
			
		||||
    }
 | 
			
		||||
    mClock.incTN(); 
 | 
			
		||||
    rcvClock.incTN();
 | 
			
		||||
    //if (mReceiveFIFO.size() >= 16) mReceiveFIFO.wait(8);
 | 
			
		||||
    //LOG(DEBUG) << "receiveFIFO: wrote radio vector at time: " << mClock.get() << ", new size: " << mReceiveFIFO.size() ;
 | 
			
		||||
    readSz += (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
 | 
			
		||||
    rcvSz -= (symbolsPerSlot+(tN % 4 == 0))*samplesPerSymbol;
 | 
			
		||||
 | 
			
		||||
    tN = rcvClock.TN();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (readSz > 0) { 
 | 
			
		||||
    memcpy(rcvBuffer,rcvBuffer+2*readSz,sizeof(short)*2*(rcvCursor-readSz));
 | 
			
		||||
    rcvCursor = rcvCursor-2*readSz;
 | 
			
		||||
  }
 | 
			
		||||
} 
 | 
			
		||||
  
 | 
			
		||||
		Reference in New Issue
	
	Block a user